LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/kml - kml.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 311 252 81.0 %
Date: 2010-01-09 Functions: 33 23 69.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: kml.cpp 17946 2009-11-01 18:31:43Z 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              61 : KML::KML()
      40                 : {
      41              61 :   nDepth_ = 0;
      42              61 :   validity = KML_VALIDITY_UNKNOWN;
      43              61 :   pKMLFile_ = NULL;
      44              61 :   sError_ = "";
      45              61 :   poTrunk_ = NULL;
      46              61 :   poCurrent_ = NULL;
      47              61 :   nNumLayers_ = -1;
      48              61 :         papoLayers_ = NULL;
      49              61 : }
      50                 : 
      51              61 : KML::~KML()
      52                 : {
      53              61 :     if( NULL != pKMLFile_ )
      54              56 :         VSIFCloseL(pKMLFile_);
      55              61 :     CPLFree(papoLayers_);
      56                 : 
      57              61 :     delete poTrunk_;
      58              61 : }
      59                 : 
      60              61 : bool KML::open(const char * pszFilename)
      61                 : {
      62              61 :     if( NULL != pKMLFile_ )
      63               0 :         VSIFCloseL( pKMLFile_ );
      64                 : 
      65              61 :     pKMLFile_ = VSIFOpenL( pszFilename, "r" );
      66              61 :     if( NULL == pKMLFile_ )
      67                 :     {
      68               5 :         return FALSE;
      69                 :     }
      70                 : 
      71              56 :     return TRUE;
      72                 : }
      73                 : 
      74               3 : void KML::parse()
      75                 : {
      76               3 :     std::size_t nDone = 0;
      77               3 :     std::size_t nLen = 0;
      78               3 :     char aBuf[BUFSIZ] = { 0 };
      79                 : 
      80               3 :     if( NULL == pKMLFile_ )
      81                 :     {
      82               0 :         sError_ = "No file given";
      83               0 :         return;
      84                 :     }
      85                 : 
      86               3 :     if(poTrunk_ != NULL) {
      87               0 :         delete poTrunk_;
      88               0 :         poTrunk_ = NULL;
      89                 :     }
      90                 : 
      91               3 :     if(poCurrent_ != NULL)
      92                 :     {
      93               0 :         delete poCurrent_;
      94               0 :         poCurrent_ = NULL;
      95                 :     }
      96                 : 
      97               3 :     XML_Parser oParser = OGRCreateExpatXMLParser();
      98               3 :     XML_SetUserData(oParser, this);
      99               3 :     XML_SetElementHandler(oParser, startElement, endElement);
     100               3 :     XML_SetCharacterDataHandler(oParser, dataHandler);
     101               3 :     oCurrentParser = oParser;
     102               3 :     nWithoutEventCounter = 0;
     103                 : 
     104               7 :     do
     105                 :     {
     106               7 :         nDataHandlerCounter = 0;
     107               7 :         nLen = (int)VSIFReadL( aBuf, 1, sizeof(aBuf), pKMLFile_ );
     108               7 :         nDone = VSIFEofL(pKMLFile_);
     109               7 :         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               7 :         nWithoutEventCounter ++;
     121                 :     } while (!nDone && nLen > 0 && nWithoutEventCounter < 10);
     122                 : 
     123               3 :     XML_ParserFree(oParser);
     124               3 :     VSIRewindL(pKMLFile_);
     125               3 :     poCurrent_ = NULL;
     126                 : 
     127               3 :     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              56 : void KML::checkValidity()
     135                 : {
     136              56 :     std::size_t nDone = 0;
     137              56 :     std::size_t nLen = 0;
     138              56 :     char aBuf[BUFSIZ] = { 0 };
     139                 : 
     140              56 :     if(poTrunk_ != NULL)
     141                 :     {
     142               0 :         delete poTrunk_;
     143               0 :         poTrunk_ = NULL;
     144                 :     }
     145                 : 
     146              56 :     if(poCurrent_ != NULL)
     147                 :     {
     148               0 :         delete poCurrent_;
     149               0 :         poCurrent_ = NULL;
     150                 :     }
     151                 : 
     152              56 :     if(pKMLFile_ == NULL)
     153                 :     {
     154               0 :         this->sError_ = "No file given";
     155               0 :         return;
     156                 :     }
     157                 : 
     158              56 :     XML_Parser oParser = OGRCreateExpatXMLParser();
     159              56 :     XML_SetUserData(oParser, this);
     160              56 :     XML_SetElementHandler(oParser, startElementValidate, NULL);
     161              56 :     XML_SetCharacterDataHandler(oParser, dataHandlerValidate);
     162              56 :     int nCount = 0;
     163                 : 
     164              56 :     oCurrentParser = oParser;
     165                 : 
     166                 :     /* Parses the file until we find the first element */
     167              17 :     do
     168                 :     {
     169              56 :         nDataHandlerCounter = 0;
     170              56 :         nLen = (int)VSIFReadL( aBuf, 1, sizeof(aBuf), pKMLFile_ );
     171              56 :         nDone = VSIFEofL(pKMLFile_);
     172              56 :         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
     173                 :         {
     174              39 :             if (nLen <= BUFSIZ-1)
     175              29 :                 aBuf[nLen] = 0;
     176                 :             else
     177              10 :                 aBuf[BUFSIZ-1] = 0;
     178              39 :             if (strstr(aBuf, "<?xml") && strstr(aBuf, "<kml"))
     179                 :             {
     180                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     181                 :                         "XML parsing of KML file failed : %s at line %d, column %d",
     182                 :                         XML_ErrorString(XML_GetErrorCode(oParser)),
     183                 :                         (int)XML_GetCurrentLineNumber(oParser),
     184               0 :                         (int)XML_GetCurrentColumnNumber(oParser));
     185                 :             }
     186                 : 
     187              39 :             validity = KML_VALIDITY_INVALID;
     188              39 :             XML_ParserFree(oParser);
     189              39 :             VSIRewindL(pKMLFile_);
     190              39 :             return;
     191                 :         }
     192                 : 
     193              17 :         nCount ++;
     194                 :         /* After reading 50 * BUFSIZE bytes, and not finding whether the file */
     195                 :         /* is KML or not, we give up and fail silently */
     196                 :     } while (!nDone && nLen > 0 && validity == KML_VALIDITY_UNKNOWN && nCount < 50);
     197                 : 
     198              17 :     XML_ParserFree(oParser);
     199              17 :     VSIRewindL(pKMLFile_);
     200              17 :     poCurrent_ = NULL;
     201                 : }
     202                 : 
     203             570 : void XMLCALL KML::startElement(void* pUserData, const char* pszName, const char** ppszAttr)
     204                 : {
     205             570 :     int i = 0;
     206             570 :     KMLNode* poMynew = NULL;
     207             570 :     Attribute* poAtt = NULL;
     208                 : 
     209             570 :     KML* poKML = (KML*) pUserData;
     210                 : 
     211             570 :     poKML->nWithoutEventCounter = 0;
     212                 : 
     213             570 :     if(poKML->poTrunk_ == NULL 
     214                 :     || (poKML->poCurrent_->getName()).compare("description") != 0)
     215                 :     {
     216             567 :         poMynew = new KMLNode();
     217            1134 :             poMynew->setName(pszName);
     218             567 :         poMynew->setLevel(poKML->nDepth_);
     219                 : 
     220            1424 :         for (i = 0; ppszAttr[i]; i += 2)
     221                 :         {
     222             145 :             poAtt = new Attribute();
     223             145 :             poAtt->sName = ppszAttr[i];
     224             145 :             poAtt->sValue = ppszAttr[i + 1];
     225             145 :             poMynew->addAttribute(poAtt);
     226                 :         }
     227                 : 
     228             567 :         if(poKML->poTrunk_ == NULL)
     229               3 :             poKML->poTrunk_ = poMynew;
     230             567 :         if(poKML->poCurrent_ != NULL)
     231             564 :             poMynew->setParent(poKML->poCurrent_);
     232             567 :         poKML->poCurrent_ = poMynew;
     233                 : 
     234             567 :         poKML->nDepth_++;
     235                 :     }
     236                 :     else
     237                 :     {
     238               3 :         std::string sNewContent = "<";
     239               3 :         sNewContent += pszName;
     240               4 :         for (i = 0; ppszAttr[i]; i += 2)
     241                 :         {
     242               1 :             sNewContent += " ";
     243               1 :             sNewContent += ppszAttr[i];
     244               1 :             sNewContent += "=\"";
     245               1 :             sNewContent += ppszAttr[i + 1];
     246               1 :             sNewContent += "\"";
     247                 :         }
     248               3 :         sNewContent += ">";
     249               3 :         if(poKML->poCurrent_->numContent() == 0)
     250               0 :             poKML->poCurrent_->addContent(sNewContent);
     251                 :         else
     252               3 :             poKML->poCurrent_->appendContent(sNewContent);
     253                 :     }
     254             570 : }
     255                 : 
     256             546 : void XMLCALL KML::startElementValidate(void* pUserData, const char* pszName, const char** ppszAttr)
     257                 : {
     258             546 :     int i = 0;
     259                 : 
     260             546 :     KML* poKML = (KML*) pUserData;
     261                 : 
     262             546 :     if (poKML->validity != KML_VALIDITY_UNKNOWN)
     263             529 :         return;
     264                 : 
     265              17 :     poKML->validity = KML_VALIDITY_INVALID;
     266                 : 
     267              17 :     if(strcmp(pszName, "kml") == 0)
     268                 :     {
     269                 :         // Check all Attributes
     270               6 :         for (i = 0; ppszAttr[i]; i += 2)
     271                 :         {
     272                 :             // Find the namespace and determine the KML version
     273               3 :             if(strcmp(ppszAttr[i], "xmlns") == 0)
     274                 :             {
     275                 :                 // Is it KML 2.2?
     276               4 :                 if((strcmp(ppszAttr[i + 1], "http://earth.google.com/kml/2.2") == 0) || 
     277                 :                    (strcmp(ppszAttr[i + 1], "http://www.opengis.net/kml/2.2") == 0))
     278                 :                 {
     279               1 :                     poKML->validity = KML_VALIDITY_VALID;
     280               1 :                     poKML->sVersion_ = "2.2";
     281                 :                 }
     282               2 :                 else if(strcmp(ppszAttr[i + 1], "http://earth.google.com/kml/2.1") == 0)
     283                 :                 {
     284               2 :                     poKML->validity = KML_VALIDITY_VALID;
     285               2 :                     poKML->sVersion_ = "2.1";
     286                 :                 }
     287               0 :                 else if(strcmp(ppszAttr[i + 1], "http://earth.google.com/kml/2.0") == 0)
     288                 :                 {
     289               0 :                     poKML->validity = KML_VALIDITY_VALID;
     290               0 :                     poKML->sVersion_ = "2.0";
     291                 :                 }
     292                 :                 else
     293                 :                 {
     294               0 :                     CPLDebug("KML", "Unhandled xmlns value : %s. Going on though...", ppszAttr[i]);
     295               0 :                     poKML->validity = KML_VALIDITY_VALID;
     296               0 :                     poKML->sVersion_ = "?";
     297                 :                 }
     298                 :             }
     299                 :         }
     300                 : 
     301               3 :         if (poKML->validity == KML_VALIDITY_INVALID)
     302                 :         {
     303               0 :             CPLDebug("KML", "Did not find xmlns attribute in <kml> element. Going on though...");
     304               0 :             poKML->validity = KML_VALIDITY_VALID;
     305               0 :             poKML->sVersion_ = "?";
     306                 :         }
     307                 :     }
     308                 : }
     309                 : 
     310            1643 : void XMLCALL KML::dataHandlerValidate(void * pUserData, const char * pszData, int nLen)
     311                 : {
     312            1643 :     KML* poKML = (KML*) pUserData;
     313                 : 
     314            1643 :     poKML->nDataHandlerCounter ++;
     315            1643 :     if (poKML->nDataHandlerCounter >= BUFSIZ)
     316                 :     {
     317               0 :         CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
     318               0 :         XML_StopParser(poKML->oCurrentParser, XML_FALSE);
     319                 :     }
     320            1643 : }
     321                 : 
     322             570 : void XMLCALL KML::endElement(void* pUserData, const char* pszName)
     323                 : {
     324             570 :     KMLNode* poTmp = NULL;
     325                 : 
     326             570 :     KML* poKML = (KML*) pUserData;
     327                 : 
     328             570 :     poKML->nWithoutEventCounter = 0;
     329                 : 
     330             570 :     if(poKML->poCurrent_ != NULL &&
     331                 :        poKML->poCurrent_->getName().compare(pszName) == 0)
     332                 :     {
     333             567 :         poKML->nDepth_--;
     334             567 :         poTmp = poKML->poCurrent_;
     335                 :         // Split the coordinates
     336             567 :         if(poKML->poCurrent_->getName().compare("coordinates") == 0 &&
     337                 :            poKML->poCurrent_->numContent() == 1)
     338                 :         {
     339              37 :             std::string sData = poKML->poCurrent_->getContent(0);
     340              37 :             std::size_t nPos = 0;
     341              37 :             std::size_t nLength = sData.length();
     342              37 :             const char* pszData = sData.c_str();
     343             221 :             while(TRUE)
     344                 :             {
     345                 :                 // Cut off whitespaces
     346            7322 :                 while(nPos < nLength &&
     347            3484 :                       (pszData[nPos] == ' ' || pszData[nPos] == '\n'
     348             442 :                        || pszData[nPos] == '\r' || pszData[nPos] == '\t' ))
     349            2880 :                     nPos ++;
     350                 : 
     351             258 :                 if (nPos == nLength)
     352                 :                     break;
     353                 : 
     354             221 :                 std::size_t nPosBegin = nPos;
     355                 : 
     356                 :                 // Get content
     357           37394 :                 while(nPos < nLength &&
     358           22316 :                       pszData[nPos] != ' ' && pszData[nPos] != '\n' && pszData[nPos] != '\r' && 
     359            7318 :                       pszData[nPos] != '\t')
     360            7318 :                     nPos++;
     361                 : 
     362             221 :                 if(nPos - nPosBegin > 0)
     363                 :                 {
     364             221 :                     std::string sTmp(pszData + nPosBegin, nPos - nPosBegin);
     365             442 :                     poKML->poCurrent_->addContent(sTmp);
     366                 :                 }
     367                 :             }
     368              74 :             if(poKML->poCurrent_->numContent() > 1)
     369              37 :                 poKML->poCurrent_->deleteContent(0);
     370                 :         }
     371             530 :         else if (poKML->poCurrent_->numContent() == 1)
     372                 :         {
     373             468 :             std::string sData = poKML->poCurrent_->getContent(0);
     374             468 :             std::string sDataWithoutNL;
     375             468 :             std::size_t nPos = 0;
     376             468 :             std::size_t nLength = sData.length();
     377             468 :             const char* pszData = sData.c_str();
     378             468 :             std::size_t nLineStartPos = 0;
     379             468 :             int bLineStart = TRUE;
     380                 : 
     381                 :             /* Re-assemble multi-line content by removing leading spaces for each line */
     382                 :             /* I'm not sure why we do that. Shouldn't we preserve content as such ? */
     383           15575 :             while(nPos < nLength)
     384                 :             {
     385           14639 :                 char ch = pszData[nPos];
     386           21137 :                 if (bLineStart && (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'))
     387            6498 :                     nLineStartPos ++;
     388            8255 :                 else if (ch == '\n' || ch == '\r')
     389                 :                 {
     390             114 :                     if (!bLineStart)
     391                 :                     {
     392             114 :                         std::string sTmp(pszData + nLineStartPos, nPos - nLineStartPos);
     393             228 :                         if (sDataWithoutNL.size() > 0)
     394             101 :                             sDataWithoutNL += " ";
     395             114 :                         sDataWithoutNL += sTmp;
     396             114 :                         bLineStart = TRUE;
     397                 :                     }
     398             114 :                     nLineStartPos = nPos + 1;
     399                 :                 }
     400                 :                 else
     401                 :                 {
     402            8027 :                     bLineStart = FALSE;
     403                 :                 }
     404           14639 :                 nPos ++;
     405                 :             }
     406                 : 
     407             468 :             if (nLineStartPos > 0)
     408                 :             {
     409             181 :                 if (nLineStartPos < nPos)
     410                 :                 {
     411              11 :                     std::string sTmp(pszData + nLineStartPos, nPos - nLineStartPos);
     412              22 :                     if (sDataWithoutNL.size() > 0)
     413              11 :                         sDataWithoutNL += " ";
     414              11 :                     sDataWithoutNL += sTmp;
     415                 :                 }
     416                 : 
     417             181 :                 poKML->poCurrent_->deleteContent(0);
     418             181 :                 poKML->poCurrent_->addContent(sDataWithoutNL);
     419             468 :             }
     420                 :         }
     421                 : 
     422             567 :         if(poKML->poCurrent_->getParent() != NULL)
     423             564 :             poKML->poCurrent_ = poKML->poCurrent_->getParent();
     424                 :         else
     425               3 :             poKML->poCurrent_ = NULL;
     426                 : 
     427             567 :         if(!poKML->isHandled(pszName))
     428                 :         {
     429             331 :             CPLDebug("KML", "Not handled: %s", pszName);
     430             331 :             delete poTmp;
     431                 :         }
     432                 :         else
     433                 :         {
     434             236 :             if(poKML->poCurrent_ != NULL)
     435             233 :                 poKML->poCurrent_->addChildren(poTmp);
     436                 :         }
     437                 :     }
     438               3 :     else if(poKML->poCurrent_ != NULL)
     439                 :     {
     440               3 :         std::string sNewContent = "</";
     441               3 :         sNewContent += pszName;
     442               3 :         sNewContent += ">";
     443               3 :         if(poKML->poCurrent_->numContent() == 0)
     444               0 :             poKML->poCurrent_->addContent(sNewContent);
     445                 :         else
     446               3 :             poKML->poCurrent_->appendContent(sNewContent);
     447                 :     }
     448             570 : }
     449                 : 
     450            2270 : void XMLCALL KML::dataHandler(void* pUserData, const char* pszData, int nLen)
     451                 : {
     452            2270 :     KML* poKML = (KML*) pUserData;
     453                 : 
     454            2270 :     poKML->nWithoutEventCounter = 0;
     455                 : 
     456            2270 :     if(nLen < 1 || poKML->poCurrent_ == NULL)
     457               0 :         return;
     458                 : 
     459            2270 :     poKML->nDataHandlerCounter ++;
     460            2270 :     if (poKML->nDataHandlerCounter >= BUFSIZ)
     461                 :     {
     462               0 :         CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
     463               0 :         XML_StopParser(poKML->oCurrentParser, XML_FALSE);
     464                 :     }
     465                 : 
     466            2270 :     std::string sData(pszData, nLen);
     467                 : 
     468            4540 :     if(poKML->poCurrent_->numContent() == 0)
     469             505 :         poKML->poCurrent_->addContent(sData);
     470                 :     else
     471            1765 :         poKML->poCurrent_->appendContent(sData);
     472                 : }
     473                 : 
     474              56 : bool KML::isValid()
     475                 : {
     476              56 :     checkValidity();
     477                 : 
     478              56 :     if( validity == KML_VALIDITY_VALID )
     479                 :         CPLDebug("KML", "Valid: %d Version: %s", 
     480               3 :                  validity == KML_VALIDITY_VALID, sVersion_.c_str());
     481                 : 
     482              56 :     return validity == KML_VALIDITY_VALID;
     483                 : }
     484                 : 
     485               0 : std::string KML::getError() const
     486                 : {
     487               0 :   return sError_;
     488                 : }
     489                 : 
     490               3 : void KML::classifyNodes()
     491                 : {
     492               3 :     poTrunk_->classify(this);
     493               3 : }
     494                 : 
     495               3 : void KML::eliminateEmpty()
     496                 : {
     497               3 :     poTrunk_->eliminateEmpty(this);
     498               3 : }
     499                 : 
     500               0 : void KML::print(unsigned short nNum)
     501                 : {
     502               0 :     if( poTrunk_ != NULL )
     503               0 :         poTrunk_->print(nNum);
     504               0 : }
     505                 : 
     506             567 : bool KML::isHandled(std::string const& elem) const
     507                 : {
     508            1310 :     if( isLeaf(elem) || isFeature(elem) || isFeatureContainer(elem)
     509             743 :         || isContainer(elem) || isRest(elem) )
     510                 :     {
     511             236 :         return true;
     512                 :     }
     513             331 :     return false;
     514                 : }
     515                 : 
     516               0 : bool KML::isLeaf(std::string const& elem) const
     517                 : {
     518               0 :     return false;
     519                 : };
     520                 : 
     521               0 : bool KML::isFeature(std::string const& elem) const
     522                 : {
     523               0 :     return false;
     524                 : };
     525                 : 
     526               0 : bool KML::isFeatureContainer(std::string const& elem) const
     527                 : {
     528               0 :     return false;
     529                 : };
     530                 : 
     531               0 : bool KML::isContainer(std::string const& elem) const
     532                 : {
     533               0 :     return false;
     534                 : };
     535                 : 
     536               0 : bool KML::isRest(std::string const& elem) const
     537                 : {
     538               0 :     return false;
     539                 : };
     540                 : 
     541               0 : void KML::findLayers(KMLNode* poNode)
     542                 : {
     543                 :     // idle
     544               0 : };
     545                 : 
     546               3 : int KML::getNumLayers() const
     547                 : {
     548               3 :     return nNumLayers_;
     549                 : }
     550                 : 
     551              42 : bool KML::selectLayer(int nNum) {
     552              42 :     if(this->nNumLayers_ < 1 || nNum >= this->nNumLayers_)
     553               0 :         return FALSE;
     554              42 :     poCurrent_ = papoLayers_[nNum];
     555              42 :     return TRUE;
     556                 : }
     557                 : 
     558               9 : std::string KML::getCurrentName() const
     559                 : {
     560               9 :     std::string tmp;
     561               9 :     if( poCurrent_ != NULL )
     562                 :     {
     563               9 :         tmp = poCurrent_->getNameElement();
     564                 :     }
     565               0 :     return tmp;
     566                 : }
     567                 : 
     568              22 : Nodetype KML::getCurrentType() const
     569                 : {
     570              22 :     if(poCurrent_ != NULL)
     571              22 :         return poCurrent_->getType();
     572                 :     else
     573               0 :         return Unknown;
     574                 : }
     575                 : 
     576               8 : int KML::is25D() const
     577                 : {
     578               8 :     if(poCurrent_ != NULL)
     579               8 :         return poCurrent_->is25D();
     580                 :     else
     581               0 :         return Unknown;
     582                 : }
     583                 : 
     584               1 : int KML::getNumFeatures()
     585                 : {
     586               1 :     if(poCurrent_ != NULL)
     587               1 :         return static_cast<int>(poCurrent_->getNumFeatures());
     588                 :     else
     589               0 :         return -1;
     590                 : }
     591                 : 
     592              32 : Feature* KML::getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount)
     593                 : {
     594              32 :     if(poCurrent_ != NULL)
     595              32 :         return poCurrent_->getFeature(nNum, nLastAsked, nLastCount);
     596                 :     else
     597               0 :         return NULL;
     598            1140 : }

Generated by: LCOV version 1.7