LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vfk - vfkreader.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 153 111 72.5 %
Date: 2012-04-28 Functions: 21 12 57.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: vfkreader.cpp 24217 2012-04-11 14:25:09Z martinl $
       3                 :  *
       4                 :  * Project:  VFK Reader
       5                 :  * Purpose:  Implements VFKReader class.
       6                 :  * Author:   Martin Landa, landa.martin gmail.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2009-2010, 2012, Martin Landa <landa.martin gmail.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person
      12                 :  * obtaining a copy of this software and associated documentation
      13                 :  * files (the "Software"), to deal in the Software without
      14                 :  * restriction, including without limitation the rights to use, copy,
      15                 :  * modify, merge, publish, distribute, sublicense, and/or sell copies
      16                 :  * of the Software, and to permit persons to whom the Software is
      17                 :  * furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be
      20                 :  * included in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      23                 :  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      24                 :  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      25                 :  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
      26                 :  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
      27                 :  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
      28                 :  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      29                 :  * SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "vfkreader.h"
      33                 : #include "vfkreaderp.h"
      34                 : 
      35                 : #include "cpl_conv.h"
      36                 : #include "cpl_error.h"
      37                 : #include "cpl_string.h"
      38                 : 
      39                 : #define SUPPORT_GEOMETRY
      40                 : 
      41                 : #ifdef SUPPORT_GEOMETRY
      42                 : #  include "ogr_geometry.h"
      43                 : #endif
      44                 : 
      45                 : static char *GetDataBlockName(const char *);
      46                 : 
      47                 : /*!
      48                 :   \brief IVFKReader desctructor
      49                 : */
      50               2 : IVFKReader::~IVFKReader()
      51                 : {
      52               2 : }
      53                 : 
      54                 : /*!
      55                 :   \brief Create new instance of VFKReader
      56                 : 
      57                 :   \return pointer to VFKReader instance
      58                 : */
      59               2 : IVFKReader *CreateVFKReader(const char *pszFilename)
      60                 : {
      61                 : #ifdef HAVE_SQLITE
      62               2 :     return new VFKReaderSQLite(pszFilename);
      63                 : #else
      64                 :     return new VFKReader(pszFilename);
      65                 : #endif
      66                 : }
      67                 : 
      68                 : /*!
      69                 :   \brief VFKReader constructor
      70                 : */
      71               2 : VFKReader::VFKReader(const char *pszFilename)
      72                 : {
      73               2 :     m_nDataBlockCount = 0;
      74               2 :     m_papoDataBlock   = NULL;
      75               2 :     m_bLatin2         = TRUE; /* encoding ISO-8859-2 or WINDOWS-1250 */
      76                 : 
      77                 :     /* open VFK file for reading */
      78               2 :     CPLAssert(NULL != pszFilename);
      79               2 :     m_pszFilename = CPLStrdup(pszFilename);
      80               2 :     m_poFD = VSIFOpen(m_pszFilename, "rb");
      81               2 :     if (m_poFD == NULL) {
      82                 :         CPLError(CE_Failure, CPLE_OpenFailed, 
      83               0 :                  "Failed to open file %s.", m_pszFilename);
      84                 :     }
      85               2 : }
      86                 : 
      87                 : /*!
      88                 :   \brief VFKReader destructor
      89                 : */
      90               2 : VFKReader::~VFKReader()
      91                 : {
      92               2 :     CPLFree(m_pszFilename);
      93                 : 
      94               2 :     if (m_poFD)
      95               2 :         VSIFClose(m_poFD);
      96                 :     
      97                 :     /* clear data blocks */
      98             124 :     for (int i = 0; i < m_nDataBlockCount; i++)
      99             122 :         delete m_papoDataBlock[i];
     100               2 :     CPLFree(m_papoDataBlock);
     101               2 : }
     102                 : 
     103             273 : char *GetDataBlockName(const char *pszLine)
     104                 : {
     105                 :     int         n;
     106                 :     const char *pszLineChar;
     107                 :     char       *pszBlockName;
     108                 : 
     109             273 :     for (pszLineChar = pszLine + 2, n = 0; *pszLineChar != '\0' && *pszLineChar != ';'; pszLineChar++, n++)
     110                 :         ;
     111                 : 
     112             273 :     if (*pszLineChar == '\0')
     113               0 :         return NULL;
     114                 : 
     115             273 :     pszBlockName = (char *) CPLMalloc(n + 1);
     116             273 :     strncpy(pszBlockName, pszLine + 2, n);
     117             273 :     pszBlockName[n] = '\0';
     118                 : 
     119             273 :     return pszBlockName;
     120                 : }
     121                 : 
     122                 : /*!
     123                 :   \brief Read a line from file
     124                 : 
     125                 :   \return a NULL terminated string which should be freed with CPLFree().
     126                 : */
     127             640 : char *VFKReader::ReadLine()
     128                 : {
     129                 :     const char *pszRawLine;
     130                 :     char *pszLine;
     131                 :     
     132             640 :     pszRawLine = CPLReadLine(m_poFD);
     133             640 :     if (pszRawLine == NULL)
     134               0 :         return NULL;
     135                 :     
     136                 :     pszLine = CPLRecode(pszRawLine,
     137                 :                         m_bLatin2 ? "ISO-8859-2" : "WINDOWS-1250",
     138             640 :                         CPL_ENC_UTF8);
     139                 :     
     140             640 :     return pszLine;
     141                 : }
     142                 : 
     143                 : /*!
     144                 :   \brief Load data block definitions (&B)
     145                 : 
     146                 :   Call VFKReader::OpenFile() before this function.
     147                 : 
     148                 :   \return number of data blocks
     149                 :   \return -1 on error
     150                 : */
     151               1 : int VFKReader::ReadDataBlocks()
     152                 : {
     153                 :     char       *pszLine, *pszBlockName;
     154                 : 
     155                 :     IVFKDataBlock *poNewDataBlock;
     156                 :     
     157               1 :     CPLAssert(NULL != m_pszFilename);
     158                 : 
     159               1 :     VSIFSeek(m_poFD, 0, SEEK_SET);
     160             129 :     while ((pszLine = ReadLine()) != NULL) {
     161             128 :         if (strlen(pszLine) < 2 || pszLine[0] != '&')
     162               0 :             continue;
     163             128 :         if (pszLine[1] == 'B') {
     164              61 :             pszBlockName = GetDataBlockName(pszLine);
     165              61 :             if (pszBlockName == NULL) { 
     166                 :                 CPLError(CE_Failure, CPLE_NotSupported, 
     167               0 :                          "Corrupted data - line\n%s\n", pszLine);
     168               0 :                 return -1;
     169                 :             }
     170              61 :             poNewDataBlock = (IVFKDataBlock *) CreateDataBlock(pszBlockName);
     171              61 :             CPLFree(pszBlockName);
     172              61 :             poNewDataBlock->SetGeometryType();
     173              61 :             poNewDataBlock->SetProperties(pszLine);
     174              61 :             AddDataBlock(poNewDataBlock, pszLine);
     175                 :         }
     176              67 :         else if (pszLine[1] == 'H') {
     177                 :             /* header - metadata */
     178              13 :             AddInfo(pszLine);
     179                 :         }
     180              54 :         else if (pszLine[1] == 'K' && strlen(pszLine) == 2) {
     181                 :             /* end of file */
     182               1 :             CPLFree(pszLine);
     183               1 :             break;
     184                 :         }
     185             127 :         CPLFree(pszLine);
     186                 :     }
     187                 :     
     188               1 :     return m_nDataBlockCount;
     189                 : }
     190                 : 
     191                 : 
     192                 : /*!
     193                 :   \brief Load data records (&D)
     194                 : 
     195                 :   Call VFKReader::OpenFile() before this function.
     196                 :   
     197                 :   \return number of data records
     198                 :   \return -1 on error
     199                 : */
     200               4 : int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
     201                 : {
     202                 :     const char *pszName;
     203                 :     char       *pszBlockName, *pszLine;
     204                 :     int         nLength;
     205                 :     
     206                 :     VFKFeature *poNewFeature;
     207                 :     
     208               4 :     if (poDataBlock->GetFeatureCount() >= 0)
     209               0 :         return -1;
     210                 : 
     211               4 :     poDataBlock->SetFeatureCount(0);
     212               4 :     poDataBlock->SetMaxFID(0);
     213               4 :     pszName = poDataBlock->GetName();
     214                 : 
     215               4 :     VSIFSeek(m_poFD, 0, SEEK_SET);
     216             516 :     while ((pszLine = ReadLine()) != NULL) {
     217             512 :         nLength = strlen(pszLine);
     218             512 :         if (nLength < 2)
     219               0 :             continue;
     220                 :         
     221             512 :         if (pszLine[1] == 'D') {
     222             212 :             pszBlockName = GetDataBlockName(pszLine);
     223             212 :             if (pszBlockName && EQUAL(pszBlockName, pszName)) {
     224                 :                 /* merge lines if needed */
     225              53 :                 if (pszLine[nLength - 2] == '\302' &&
     226               0 :                     pszLine[nLength - 1] == '\244') {
     227                 :                     
     228                 :                     /* remove 0302 0244 (currency sign) from string */
     229               0 :                     pszLine[nLength - 2] = '\0';
     230                 :                     
     231               0 :                     CPLString pszMultiLine(pszLine);
     232               0 :                     CPLFree(pszLine);
     233                 :                     
     234               0 :                     while ((pszLine = ReadLine()) != NULL &&
     235               0 :                            pszLine[strlen(pszLine) - 2] == '\302' &&
     236               0 :                            pszLine[strlen(pszLine) - 1] == '\244') {
     237                 :                         /* remove 0302 0244 (currency sign) from string */
     238               0 :                         pszLine[strlen(pszLine) - 2] = '\0';
     239                 :                         
     240                 :                         /* append line */
     241               0 :                         pszMultiLine += pszLine;
     242               0 :                         CPLFree(pszLine);
     243                 :                     } 
     244               0 :                     pszMultiLine += pszLine;
     245               0 :                     CPLFree(pszLine);
     246                 :                     
     247               0 :                     nLength = pszMultiLine.size();
     248               0 :                     pszLine = (char *) CPLMalloc(nLength + 1);
     249               0 :                     strncpy(pszLine, pszMultiLine.c_str(), nLength);
     250               0 :                     pszLine[nLength] = '\0';
     251                 :                 }
     252                 :                 
     253              53 :                 poNewFeature = new VFKFeature(poDataBlock);
     254              53 :                 poNewFeature->SetProperties(pszLine);
     255              53 :                 AddFeature(poDataBlock, poNewFeature);
     256                 :             }
     257             212 :             CPLFree(pszBlockName);
     258                 :         }
     259             300 :         else if (pszLine[1] == 'K' && strlen(pszLine) == 2) {
     260                 :             /* end of file */
     261               4 :             CPLFree(pszLine);
     262               4 :             break;
     263                 :         }
     264             508 :         CPLFree(pszLine);
     265                 :     }
     266                 :     
     267               4 :     return poDataBlock->GetFeatureCount();
     268                 : }
     269                 : 
     270               0 : IVFKDataBlock *VFKReader::CreateDataBlock(const char *pszBlockName)
     271                 : {
     272               0 :   return (IVFKDataBlock *) new VFKDataBlock(pszBlockName, (IVFKReader *) this);
     273                 : }
     274                 : 
     275                 : /*!
     276                 :   \brief Add new data block
     277                 : 
     278                 :   \param poNewDataBlock pointer to VFKDataBlock instance
     279                 : 
     280                 :   \return number of registred data blocks
     281                 : */
     282             122 : void VFKReader::AddDataBlock(IVFKDataBlock *poNewDataBlock, const char *pszDefn)
     283                 : {
     284             122 :     m_nDataBlockCount++;
     285                 :     
     286                 :     m_papoDataBlock = (IVFKDataBlock **)
     287             122 :         CPLRealloc(m_papoDataBlock, sizeof (IVFKDataBlock *) * m_nDataBlockCount);
     288             122 :     m_papoDataBlock[m_nDataBlockCount-1] = poNewDataBlock;
     289             122 : }
     290                 : 
     291                 : /*!
     292                 :   \brief Add feature
     293                 : 
     294                 :   \param poNewDataBlock pointer to VFKDataBlock instance
     295                 :   \param poNewFeature pointer to VFKFeature instance
     296                 : */
     297               0 : void VFKReader::AddFeature(IVFKDataBlock *poDataBlock, VFKFeature *poFeature)
     298                 : {
     299               0 :     poDataBlock->AddFeature(poFeature);
     300               0 : }
     301                 : 
     302                 : /*!
     303                 :   \brief Get data block
     304                 : 
     305                 :   \param i index (starting with 0)
     306                 : 
     307                 :   \return pointer to VFKDataBlock instance
     308                 :   \return NULL on failure
     309                 : */
     310            4308 : IVFKDataBlock *VFKReader::GetDataBlock(int i) const
     311                 : {
     312            4308 :     if (i < 0 || i >= m_nDataBlockCount)
     313               0 :         return NULL;
     314                 :     
     315            4308 :     return m_papoDataBlock[i];
     316                 : }
     317                 : 
     318                 : /*!
     319                 :   \brief Get data block
     320                 : 
     321                 :   \param pszName data block name
     322                 : 
     323                 :   \return pointer to VFKDataBlock instance
     324                 :   \return NULL on failure
     325                 : */
     326             128 : IVFKDataBlock *VFKReader::GetDataBlock(const char *pszName) const
     327                 : {
     328            4058 :     for (int i = 0; i < m_nDataBlockCount; i++) {
     329            4058 :         if (EQUAL(GetDataBlock(i)->GetName(), pszName))
     330             128 :             return GetDataBlock(i);
     331                 :     }
     332                 : 
     333               0 :     return NULL;
     334                 : }
     335                 : 
     336                 : /*!
     337                 :   \brief Load geometry (loop datablocks)
     338                 : 
     339                 :   \return number of invalid features
     340                 : */
     341               0 : int VFKReader::LoadGeometry()
     342                 : {
     343                 :     long int nfeatures;
     344                 : 
     345               0 :     nfeatures = 0;
     346               0 :     for (int i = 0; i < m_nDataBlockCount; i++) {
     347               0 :         nfeatures += m_papoDataBlock[i]->LoadGeometry();
     348                 :     }
     349                 :     
     350               0 :     CPLDebug("OGR_VFK", "VFKReader::LoadGeometry(): invalid=%ld", nfeatures);
     351                 :     
     352               0 :     return nfeatures;
     353                 : }
     354                 : 
     355                 : /*!
     356                 :   \brief Add info
     357                 : 
     358                 :   \param pszLine pointer to line
     359                 : */
     360              13 : void VFKReader::AddInfo(const char *pszLine)
     361                 : {
     362                 :     int         iKeyLength, iValueLength;
     363                 :     char       *pszKey, *pszValue;
     364                 :     const char *poChar, *poKey, *poValue;
     365              13 :     CPLString   key, value;
     366                 :     
     367              13 :     poChar = poKey = pszLine + 2; /* &H */
     368              13 :     iKeyLength = 0;
     369             103 :     while (*poChar != '\0' && *poChar != ';') {
     370              77 :         iKeyLength++;
     371              77 :         poChar ++;
     372                 :     }
     373              13 :     if (*poChar == '\0')
     374                 :         return;
     375                 : 
     376              13 :     pszKey = (char *) CPLMalloc(iKeyLength + 1);
     377              13 :     strncpy(pszKey, poKey, iKeyLength);
     378              13 :     pszKey[iKeyLength] = '\0';
     379                 : 
     380              13 :     poValue = ++poChar; /* skip ';' */
     381              13 :     iValueLength = 0;
     382            1178 :     while (*poChar != '\0') {
     383            1152 :         iValueLength++;
     384            1152 :         poChar++;
     385                 :     }
     386                 : 
     387              13 :     pszValue = (char *) CPLMalloc(iValueLength + 1);
     388              13 :     strncpy(pszValue, poValue, iValueLength);
     389              13 :     pszValue[iValueLength] = '\0';
     390                 : 
     391              13 :     poInfo[pszKey] = pszValue;
     392                 : 
     393              13 :     if (EQUAL(pszKey, "CODEPAGE")) {
     394               1 :         if (!EQUAL(pszValue, "\"WE8ISO8859P2\""))
     395               0 :             m_bLatin2 = FALSE;
     396                 :     }
     397                 : 
     398              13 :     CPLFree(pszKey);
     399              13 :     CPLFree(pszValue);
     400                 : }
     401                 : 
     402                 : /*!
     403                 :   \brief Get info
     404                 : 
     405                 :   \param key key string
     406                 : 
     407                 :   \return pointer to value string
     408                 :   \return NULL if key not found
     409                 : */
     410               0 : const char *VFKReader::GetInfo(const char *key)
     411                 : {
     412               0 :     if (poInfo.find(key) == poInfo.end())
     413               0 :         return NULL;
     414                 : 
     415               0 :     return poInfo[key].c_str();
     416                 : }

Generated by: LCOV version 1.7