LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/kml - kml.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 318 253 79.6 %
Date: 2013-03-30 Functions: 36 24 66.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: kml.cpp 25440 2013-01-03 20:20:32Z rouault $
       3                 :  *
       4                 :  * Project:  KML Driver
       5                 :  * Purpose:  Class for reading, parsing and handling a kmlfile.
       6                 :  * Author:   Jens Oberender, j.obi@troja.net
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2007, Jens Oberender
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : #include "kmlnode.h"
      30                 : #include "kml.h"
      31                 : #include "cpl_error.h"
      32                 : #include "cpl_conv.h"
      33                 : // std
      34                 : #include <cstdio>
      35                 : #include <cerrno>
      36                 : #include <string>
      37                 : #include <iostream>
      38                 : 
      39              98 : KML::KML()
      40                 : {
      41              98 :   nDepth_ = 0;
      42              98 :   validity = KML_VALIDITY_UNKNOWN;
      43              98 :   pKMLFile_ = NULL;
      44              98 :   sError_ = "";
      45              98 :   poTrunk_ = NULL;
      46              98 :   poCurrent_ = NULL;
      47              98 :   nNumLayers_ = -1;
      48              98 :         papoLayers_ = NULL;
      49              98 : }
      50                 : 
      51              98 : KML::~KML()
      52                 : {
      53              98 :     if( NULL != pKMLFile_ )
      54              66 :         VSIFCloseL(pKMLFile_);
      55              98 :     CPLFree(papoLayers_);
      56                 : 
      57              98 :     delete poTrunk_;
      58              98 : }
      59                 : 
      60              98 : bool KML::open(const char * pszFilename)
      61                 : {
      62              98 :     if( NULL != pKMLFile_ )
      63               0 :         VSIFCloseL( pKMLFile_ );
      64                 : 
      65              98 :     pKMLFile_ = VSIFOpenL( pszFilename, "r" );
      66              98 :     if( NULL == pKMLFile_ )
      67                 :     {
      68              32 :         return FALSE;
      69                 :     }
      70                 : 
      71              66 :     return TRUE;
      72                 : }
      73                 : 
      74               9 : void KML::parse()
      75                 : {
      76               9 :     std::size_t nDone = 0;
      77               9 :     std::size_t nLen = 0;
      78               9 :     char aBuf[BUFSIZ] = { 0 };
      79                 : 
      80               9 :     if( NULL == pKMLFile_ )
      81                 :     {
      82               0 :         sError_ = "No file given";
      83               0 :         return;
      84                 :     }
      85                 : 
      86               9 :     if(poTrunk_ != NULL) {
      87               0 :         delete poTrunk_;
      88               0 :         poTrunk_ = NULL;
      89                 :     }
      90                 : 
      91               9 :     if(poCurrent_ != NULL)
      92                 :     {
      93               0 :         delete poCurrent_;
      94               0 :         poCurrent_ = NULL;
      95                 :     }
      96                 : 
      97               9 :     XML_Parser oParser = OGRCreateExpatXMLParser();
      98               9 :     XML_SetUserData(oParser, this);
      99               9 :     XML_SetElementHandler(oParser, startElement, endElement);
     100               9 :     XML_SetCharacterDataHandler(oParser, dataHandler);
     101               9 :     oCurrentParser = oParser;
     102               9 :     nWithoutEventCounter = 0;
     103                 : 
     104              21 :     do
     105                 :     {
     106              21 :         nDataHandlerCounter = 0;
     107              21 :         nLen = (int)VSIFReadL( aBuf, 1, sizeof(aBuf), pKMLFile_ );
     108              21 :         nDone = VSIFEofL(pKMLFile_);
     109              21 :         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
     110                 :         {
     111                 :             CPLError(CE_Failure, CPLE_AppDefined,
     112                 :                         "XML parsing of KML file failed : %s at line %d, column %d",
     113                 :                         XML_ErrorString(XML_GetErrorCode(oParser)),
     114                 :                         (int)XML_GetCurrentLineNumber(oParser),
     115               0 :                         (int)XML_GetCurrentColumnNumber(oParser));
     116               0 :             XML_ParserFree(oParser);
     117               0 :             VSIRewindL(pKMLFile_);
     118               0 :             return;
     119                 :         }
     120              21 :         nWithoutEventCounter ++;
     121                 :     } while (!nDone && nLen > 0 && nWithoutEventCounter < 10);
     122                 : 
     123               9 :     XML_ParserFree(oParser);
     124               9 :     VSIRewindL(pKMLFile_);
     125               9 :     poCurrent_ = NULL;
     126                 : 
     127               9 :     if (nWithoutEventCounter == 10)
     128                 :     {
     129                 :         CPLError(CE_Failure, CPLE_AppDefined,
     130               0 :                  "Too much data inside one element. File probably corrupted");
     131                 :     }
     132                 : }
     133                 : 
     134              66 : void KML::checkValidity()
     135                 : {
     136              66 :     std::size_t nDone = 0;
     137              66 :     std::size_t nLen = 0;
     138              66 :     char aBuf[BUFSIZ] = { 0 };
     139                 : 
     140              66 :     if(poTrunk_ != NULL)
     141                 :     {
     142               0 :         delete poTrunk_;
     143               0 :         poTrunk_ = NULL;
     144                 :     }
     145                 : 
     146              66 :     if(poCurrent_ != NULL)
     147                 :     {
     148               0 :         delete poCurrent_;
     149               0 :         poCurrent_ = NULL;
     150                 :     }
     151                 : 
     152              66 :     if(pKMLFile_ == NULL)
     153                 :     {
     154               0 :         this->sError_ = "No file given";
     155               0 :         return;
     156                 :     }
     157                 : 
     158              66 :     XML_Parser oParser = OGRCreateExpatXMLParser();
     159              66 :     XML_SetUserData(oParser, this);
     160              66 :     XML_SetElementHandler(oParser, startElementValidate, NULL);
     161              66 :     XML_SetCharacterDataHandler(oParser, dataHandlerValidate);
     162              66 :     int nCount = 0;
     163                 : 
     164              66 :     oCurrentParser = oParser;
     165                 : 
     166                 :     /* Parses the file until we find the first element */
     167              14 :     do
     168                 :     {
     169              66 :         nDataHandlerCounter = 0;
     170              66 :         nLen = (int)VSIFReadL( aBuf, 1, sizeof(aBuf), pKMLFile_ );
     171              66 :         nDone = VSIFEofL(pKMLFile_);
     172              66 :         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
     173                 :         {
     174              52 :             if (nLen <= BUFSIZ-1)
     175              24 :                 aBuf[nLen] = 0;
     176                 :             else
     177              28 :                 aBuf[BUFSIZ-1] = 0;
     178              52 :             if( strstr(aBuf, "<?xml") && (
     179                 :                     strstr(aBuf, "<kml") ||
     180                 :                     (strstr(aBuf, "<Document") && strstr(aBuf, "/kml/2.")) ) )
     181                 :             {
     182                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     183                 :                         "XML parsing of KML file failed : %s at line %d, column %d",
     184                 :                         XML_ErrorString(XML_GetErrorCode(oParser)),
     185                 :                         (int)XML_GetCurrentLineNumber(oParser),
     186               0 :                         (int)XML_GetCurrentColumnNumber(oParser));
     187                 :             }
     188                 : 
     189              52 :             validity = KML_VALIDITY_INVALID;
     190              52 :             XML_ParserFree(oParser);
     191              52 :             VSIRewindL(pKMLFile_);
     192              52 :             return;
     193                 :         }
     194                 : 
     195              14 :         nCount ++;
     196                 :         /* After reading 50 * BUFSIZE bytes, and not finding whether the file */
     197                 :         /* is KML or not, we give up and fail silently */
     198                 :     } while (!nDone && nLen > 0 && validity == KML_VALIDITY_UNKNOWN && nCount < 50);
     199                 : 
     200              14 :     XML_ParserFree(oParser);
     201              14 :     VSIRewindL(pKMLFile_);
     202              14 :     poCurrent_ = NULL;
     203                 : }
     204                 : 
     205            1695 : void XMLCALL KML::startElement(void* pUserData, const char* pszName, const char** ppszAttr)
     206                 : {
     207            1695 :     int i = 0;
     208            1695 :     KMLNode* poMynew = NULL;
     209            1695 :     Attribute* poAtt = NULL;
     210                 : 
     211            1695 :     KML* poKML = (KML*) pUserData;
     212                 : 
     213            1695 :     poKML->nWithoutEventCounter = 0;
     214                 : 
     215            1695 :     if(poKML->poTrunk_ == NULL 
     216                 :     || (poKML->poCurrent_->getName()).compare("description") != 0)
     217                 :     {
     218            1690 :         if (poKML->nDepth_ == 1024)
     219                 :         {
     220                 :             CPLError( CE_Failure, CPLE_AppDefined,
     221                 :                       "Too big depth level (%d) while parsing KML.",
     222               0 :                       poKML->nDepth_ );
     223               0 :             XML_StopParser(poKML->oCurrentParser, XML_FALSE);
     224               0 :             return;
     225                 :         }
     226                 : 
     227            1690 :         poMynew = new KMLNode();
     228            3380 :             poMynew->setName(pszName);
     229            1690 :         poMynew->setLevel(poKML->nDepth_);
     230                 : 
     231            4198 :         for (i = 0; ppszAttr[i]; i += 2)
     232                 :         {
     233             409 :             poAtt = new Attribute();
     234             409 :             poAtt->sName = ppszAttr[i];
     235             409 :             poAtt->sValue = ppszAttr[i + 1];
     236             409 :             poMynew->addAttribute(poAtt);
     237                 :         }
     238                 : 
     239            1690 :         if(poKML->poTrunk_ == NULL)
     240               9 :             poKML->poTrunk_ = poMynew;
     241            1690 :         if(poKML->poCurrent_ != NULL)
     242            1681 :             poMynew->setParent(poKML->poCurrent_);
     243            1690 :         poKML->poCurrent_ = poMynew;
     244                 : 
     245            1690 :         poKML->nDepth_++;
     246                 :     }
     247                 :     else
     248                 :     {
     249               5 :         std::string sNewContent = "<";
     250               5 :         sNewContent += pszName;
     251               6 :         for (i = 0; ppszAttr[i]; i += 2)
     252                 :         {
     253               1 :             sNewContent += " ";
     254               1 :             sNewContent += ppszAttr[i];
     255               1 :             sNewContent += "=\"";
     256               1 :             sNewContent += ppszAttr[i + 1];
     257               1 :             sNewContent += "\"";
     258                 :         }
     259               5 :         sNewContent += ">";
     260               5 :         if(poKML->poCurrent_->numContent() == 0)
     261               0 :             poKML->poCurrent_->addContent(sNewContent);
     262                 :         else
     263               5 :             poKML->poCurrent_->appendContent(sNewContent);
     264                 :     }
     265                 : }
     266                 : 
     267             706 : void XMLCALL KML::startElementValidate(void* pUserData, const char* pszName, const char** ppszAttr)
     268                 : {
     269             706 :     int i = 0;
     270                 : 
     271             706 :     KML* poKML = (KML*) pUserData;
     272                 : 
     273             706 :     if (poKML->validity != KML_VALIDITY_UNKNOWN)
     274             696 :         return;
     275                 : 
     276              10 :     poKML->validity = KML_VALIDITY_INVALID;
     277                 : 
     278              10 :     if(strcmp(pszName, "kml") == 0 || strcmp(pszName, "Document") == 0)
     279                 :     {
     280                 :         // Check all Attributes
     281              20 :         for (i = 0; ppszAttr[i]; i += 2)
     282                 :         {
     283                 :             // Find the namespace and determine the KML version
     284              11 :             if(strcmp(ppszAttr[i], "xmlns") == 0)
     285                 :             {
     286                 :                 // Is it KML 2.2?
     287              13 :                 if((strcmp(ppszAttr[i + 1], "http://earth.google.com/kml/2.2") == 0) || 
     288                 :                    (strcmp(ppszAttr[i + 1], "http://www.opengis.net/kml/2.2") == 0))
     289                 :                 {
     290               4 :                     poKML->validity = KML_VALIDITY_VALID;
     291               4 :                     poKML->sVersion_ = "2.2";
     292                 :                 }
     293               5 :                 else if(strcmp(ppszAttr[i + 1], "http://earth.google.com/kml/2.1") == 0)
     294                 :                 {
     295               5 :                     poKML->validity = KML_VALIDITY_VALID;
     296               5 :                     poKML->sVersion_ = "2.1";
     297                 :                 }
     298               0 :                 else if(strcmp(ppszAttr[i + 1], "http://earth.google.com/kml/2.0") == 0)
     299                 :                 {
     300               0 :                     poKML->validity = KML_VALIDITY_VALID;
     301               0 :                     poKML->sVersion_ = "2.0";
     302                 :                 }
     303                 :                 else
     304                 :                 {
     305               0 :                     CPLDebug("KML", "Unhandled xmlns value : %s. Going on though...", ppszAttr[i]);
     306               0 :                     poKML->validity = KML_VALIDITY_VALID;
     307               0 :                     poKML->sVersion_ = "?";
     308                 :                 }
     309                 :             }
     310                 :         }
     311                 : 
     312               9 :         if (poKML->validity == KML_VALIDITY_INVALID)
     313                 :         {
     314               0 :             CPLDebug("KML", "Did not find xmlns attribute in <kml> element. Going on though...");
     315               0 :             poKML->validity = KML_VALIDITY_VALID;
     316               0 :             poKML->sVersion_ = "?";
     317                 :         }
     318                 :     }
     319                 : }
     320                 : 
     321            2264 : void XMLCALL KML::dataHandlerValidate(void * pUserData, const char * pszData, int nLen)
     322                 : {
     323            2264 :     KML* poKML = (KML*) pUserData;
     324                 : 
     325            2264 :     poKML->nDataHandlerCounter ++;
     326            2264 :     if (poKML->nDataHandlerCounter >= BUFSIZ)
     327                 :     {
     328               0 :         CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
     329               0 :         XML_StopParser(poKML->oCurrentParser, XML_FALSE);
     330                 :     }
     331            2264 : }
     332                 : 
     333            1695 : void XMLCALL KML::endElement(void* pUserData, const char* pszName)
     334                 : {
     335            1695 :     KMLNode* poTmp = NULL;
     336                 : 
     337            1695 :     KML* poKML = (KML*) pUserData;
     338                 : 
     339            1695 :     poKML->nWithoutEventCounter = 0;
     340                 : 
     341            1695 :     if(poKML->poCurrent_ != NULL &&
     342                 :        poKML->poCurrent_->getName().compare(pszName) == 0)
     343                 :     {
     344            1690 :         poKML->nDepth_--;
     345            1690 :         poTmp = poKML->poCurrent_;
     346                 :         // Split the coordinates
     347            1690 :         if(poKML->poCurrent_->getName().compare("coordinates") == 0 &&
     348                 :            poKML->poCurrent_->numContent() == 1)
     349                 :         {
     350              94 :             std::string sData = poKML->poCurrent_->getContent(0);
     351              94 :             std::size_t nPos = 0;
     352              94 :             std::size_t nLength = sData.length();
     353              94 :             const char* pszData = sData.c_str();
     354             634 :             while(TRUE)
     355                 :             {
     356                 :                 // Cut off whitespaces
     357           21734 :                 while(nPos < nLength &&
     358           10382 :                       (pszData[nPos] == ' ' || pszData[nPos] == '\n'
     359            1268 :                        || pszData[nPos] == '\r' || pszData[nPos] == '\t' ))
     360            8628 :                     nPos ++;
     361                 : 
     362             728 :                 if (nPos == nLength)
     363                 :                     break;
     364                 : 
     365             634 :                 std::size_t nPosBegin = nPos;
     366                 : 
     367                 :                 // Get content
     368          111242 :                 while(nPos < nLength &&
     369           66414 :                       pszData[nPos] != ' ' && pszData[nPos] != '\n' && pszData[nPos] != '\r' && 
     370           21780 :                       pszData[nPos] != '\t')
     371           21780 :                     nPos++;
     372                 : 
     373             634 :                 if(nPos - nPosBegin > 0)
     374                 :                 {
     375             634 :                     std::string sTmp(pszData + nPosBegin, nPos - nPosBegin);
     376            1268 :                     poKML->poCurrent_->addContent(sTmp);
     377                 :                 }
     378                 :             }
     379             188 :             if(poKML->poCurrent_->numContent() > 1)
     380              94 :                 poKML->poCurrent_->deleteContent(0);
     381                 :         }
     382            1596 :         else if (poKML->poCurrent_->numContent() == 1)
     383                 :         {
     384            1403 :             std::string sData = poKML->poCurrent_->getContent(0);
     385            1403 :             std::string sDataWithoutNL;
     386            1403 :             std::size_t nPos = 0;
     387            1403 :             std::size_t nLength = sData.length();
     388            1403 :             const char* pszData = sData.c_str();
     389            1403 :             std::size_t nLineStartPos = 0;
     390            1403 :             int bLineStart = TRUE;
     391                 : 
     392                 :             /* Re-assemble multi-line content by removing leading spaces for each line */
     393                 :             /* I'm not sure why we do that. Shouldn't we preserve content as such ? */
     394           46721 :             while(nPos < nLength)
     395                 :             {
     396           43915 :                 char ch = pszData[nPos];
     397           63555 :                 if (bLineStart && (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'))
     398           19640 :                     nLineStartPos ++;
     399           24615 :                 else if (ch == '\n' || ch == '\r')
     400                 :                 {
     401             340 :                     if (!bLineStart)
     402                 :                     {
     403             340 :                         std::string sTmp(pszData + nLineStartPos, nPos - nLineStartPos);
     404             680 :                         if (sDataWithoutNL.size() > 0)
     405             303 :                             sDataWithoutNL += " ";
     406             340 :                         sDataWithoutNL += sTmp;
     407             340 :                         bLineStart = TRUE;
     408                 :                     }
     409             340 :                     nLineStartPos = nPos + 1;
     410                 :                 }
     411                 :                 else
     412                 :                 {
     413           23935 :                     bLineStart = FALSE;
     414                 :                 }
     415           43915 :                 nPos ++;
     416                 :             }
     417                 : 
     418            1403 :             if (nLineStartPos > 0)
     419                 :             {
     420             540 :                 if (nLineStartPos < nPos)
     421                 :                 {
     422              33 :                     std::string sTmp(pszData + nLineStartPos, nPos - nLineStartPos);
     423              66 :                     if (sDataWithoutNL.size() > 0)
     424              33 :                         sDataWithoutNL += " ";
     425              33 :                     sDataWithoutNL += sTmp;
     426                 :                 }
     427                 : 
     428             540 :                 poKML->poCurrent_->deleteContent(0);
     429             540 :                 poKML->poCurrent_->addContent(sDataWithoutNL);
     430            1403 :             }
     431                 :         }
     432                 : 
     433            1690 :         if(poKML->poCurrent_->getParent() != NULL)
     434            1681 :             poKML->poCurrent_ = poKML->poCurrent_->getParent();
     435                 :         else
     436               9 :             poKML->poCurrent_ = NULL;
     437                 : 
     438            1690 :         if(!poKML->isHandled(pszName))
     439                 :         {
     440             993 :             CPLDebug("KML", "Not handled: %s", pszName);
     441             993 :             delete poTmp;
     442                 :         }
     443                 :         else
     444                 :         {
     445             697 :             if(poKML->poCurrent_ != NULL)
     446             688 :                 poKML->poCurrent_->addChildren(poTmp);
     447                 :         }
     448                 :     }
     449               5 :     else if(poKML->poCurrent_ != NULL)
     450                 :     {
     451               5 :         std::string sNewContent = "</";
     452               5 :         sNewContent += pszName;
     453               5 :         sNewContent += ">";
     454               5 :         if(poKML->poCurrent_->numContent() == 0)
     455               0 :             poKML->poCurrent_->addContent(sNewContent);
     456                 :         else
     457               5 :             poKML->poCurrent_->appendContent(sNewContent);
     458                 :     }
     459            1695 : }
     460                 : 
     461            6804 : void XMLCALL KML::dataHandler(void* pUserData, const char* pszData, int nLen)
     462                 : {
     463            6804 :     KML* poKML = (KML*) pUserData;
     464                 : 
     465            6804 :     poKML->nWithoutEventCounter = 0;
     466                 : 
     467            6804 :     if(nLen < 1 || poKML->poCurrent_ == NULL)
     468               0 :         return;
     469                 : 
     470            6804 :     poKML->nDataHandlerCounter ++;
     471            6804 :     if (poKML->nDataHandlerCounter >= BUFSIZ)
     472                 :     {
     473               0 :         CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
     474               0 :         XML_StopParser(poKML->oCurrentParser, XML_FALSE);
     475                 :     }
     476                 : 
     477                 :     try
     478                 :     {
     479            6804 :         std::string sData(pszData, nLen);
     480                 : 
     481           13608 :         if(poKML->poCurrent_->numContent() == 0)
     482            1497 :             poKML->poCurrent_->addContent(sData);
     483                 :         else
     484            5307 :             poKML->poCurrent_->appendContent(sData);
     485                 :     }
     486               0 :     catch(const std::exception& ex)
     487                 :     {
     488               0 :         CPLError(CE_Failure, CPLE_AppDefined, "libstdc++ exception : %s", ex.what());
     489               0 :         XML_StopParser(poKML->oCurrentParser, XML_FALSE);
     490                 :     }
     491                 : }
     492                 : 
     493              66 : bool KML::isValid()
     494                 : {
     495              66 :     checkValidity();
     496                 : 
     497              66 :     if( validity == KML_VALIDITY_VALID )
     498                 :         CPLDebug("KML", "Valid: %d Version: %s", 
     499               9 :                  validity == KML_VALIDITY_VALID, sVersion_.c_str());
     500                 : 
     501              66 :     return validity == KML_VALIDITY_VALID;
     502                 : }
     503                 : 
     504               0 : std::string KML::getError() const
     505                 : {
     506               0 :   return sError_;
     507                 : }
     508                 : 
     509               9 : int KML::classifyNodes()
     510                 : {
     511               9 :     return poTrunk_->classify(this);
     512                 : }
     513                 : 
     514               7 : void KML::eliminateEmpty()
     515                 : {
     516               7 :     poTrunk_->eliminateEmpty(this);
     517               7 : }
     518                 : 
     519               0 : void KML::print(unsigned short nNum)
     520                 : {
     521               0 :     if( poTrunk_ != NULL )
     522               0 :         poTrunk_->print(nNum);
     523               0 : }
     524                 : 
     525            1690 : bool KML::isHandled(std::string const& elem) const
     526                 : {
     527            3925 :     if( isLeaf(elem) || isFeature(elem) || isFeatureContainer(elem)
     528            2235 :         || isContainer(elem) || isRest(elem) )
     529                 :     {
     530             697 :         return true;
     531                 :     }
     532             993 :     return false;
     533                 : }
     534                 : 
     535               0 : bool KML::isLeaf(std::string const& elem) const
     536                 : {
     537               0 :     return false;
     538                 : };
     539                 : 
     540               0 : bool KML::isFeature(std::string const& elem) const
     541                 : {
     542               0 :     return false;
     543                 : };
     544                 : 
     545               0 : bool KML::isFeatureContainer(std::string const& elem) const
     546                 : {
     547               0 :     return false;
     548                 : };
     549                 : 
     550               0 : bool KML::isContainer(std::string const& elem) const
     551                 : {
     552               0 :     return false;
     553                 : };
     554                 : 
     555               0 : bool KML::isRest(std::string const& elem) const
     556                 : {
     557               0 :     return false;
     558                 : };
     559                 : 
     560               0 : void KML::findLayers(KMLNode* poNode, int bKeepEmptyContainers)
     561                 : {
     562                 :     // idle
     563               0 : };
     564                 : 
     565               9 : bool KML::hasOnlyEmpty() const
     566                 : {
     567               9 :     return poTrunk_->hasOnlyEmpty();
     568                 : }
     569                 : 
     570               9 : int KML::getNumLayers() const
     571                 : {
     572               9 :     return nNumLayers_;
     573                 : }
     574                 : 
     575             414 : bool KML::selectLayer(int nNum) {
     576             414 :     if(this->nNumLayers_ < 1 || nNum >= this->nNumLayers_)
     577               0 :         return FALSE;
     578             414 :     poCurrent_ = papoLayers_[nNum];
     579             414 :     return TRUE;
     580                 : }
     581                 : 
     582              25 : std::string KML::getCurrentName() const
     583                 : {
     584              25 :     std::string tmp;
     585              25 :     if( poCurrent_ != NULL )
     586                 :     {
     587              25 :         tmp = poCurrent_->getNameElement();
     588                 :     }
     589               0 :     return tmp;
     590                 : }
     591                 : 
     592              70 : Nodetype KML::getCurrentType() const
     593                 : {
     594              70 :     if(poCurrent_ != NULL)
     595              70 :         return poCurrent_->getType();
     596                 :     else
     597               0 :         return Unknown;
     598                 : }
     599                 : 
     600              21 : int KML::is25D() const
     601                 : {
     602              21 :     if(poCurrent_ != NULL)
     603              21 :         return poCurrent_->is25D();
     604                 :     else
     605               0 :         return Unknown;
     606                 : }
     607                 : 
     608              29 : int KML::getNumFeatures()
     609                 : {
     610              29 :     if(poCurrent_ != NULL)
     611              29 :         return static_cast<int>(poCurrent_->getNumFeatures());
     612                 :     else
     613               0 :         return -1;
     614                 : }
     615                 : 
     616             442 : Feature* KML::getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount)
     617                 : {
     618             442 :     if(poCurrent_ != NULL)
     619             442 :         return poCurrent_->getFeature(nNum, nLastAsked, nLastCount);
     620                 :     else
     621               0 :         return NULL;
     622            2274 : }

Generated by: LCOV version 1.7