LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vfk - vfkreader.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 162 117 72.2 %
Date: 2012-12-26 Functions: 21 12 57.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: vfkreader.cpp 25340 2012-12-21 20:30:21Z rouault $
       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                 :   \param bRecode do recoding
     126                 : 
     127                 :   \return a NULL terminated string which should be freed with CPLFree().
     128                 : */
     129             640 : char *VFKReader::ReadLine(bool bRecode)
     130                 : {
     131                 :     const char *pszRawLine;
     132                 :     char *pszLine;
     133                 :     
     134             640 :     pszRawLine = CPLReadLine(m_poFD);
     135             640 :     if (pszRawLine == NULL)
     136               0 :         return NULL;
     137                 :     
     138             640 :     if (bRecode)
     139                 :         pszLine = CPLRecode(pszRawLine,
     140                 :                             m_bLatin2 ? "ISO-8859-2" : "WINDOWS-1250",
     141               0 :                             CPL_ENC_UTF8);
     142                 :     else {
     143             640 :         pszLine = (char *) CPLMalloc(strlen(pszRawLine) + 1);
     144             640 :         strcpy(pszLine, pszRawLine);
     145                 :     }
     146                 :     
     147             640 :     return pszLine;
     148                 : }
     149                 : 
     150                 : /*!
     151                 :   \brief Load data block definitions (&B)
     152                 : 
     153                 :   Call VFKReader::OpenFile() before this function.
     154                 : 
     155                 :   \return number of data blocks or -1 on error
     156                 : */
     157               1 : int VFKReader::ReadDataBlocks()
     158                 : {
     159                 :     char       *pszLine, *pszBlockName;
     160                 : 
     161                 :     IVFKDataBlock *poNewDataBlock;
     162                 :     
     163               1 :     CPLAssert(NULL != m_pszFilename);
     164                 : 
     165               1 :     VSIFSeek(m_poFD, 0, SEEK_SET);
     166             129 :     while ((pszLine = ReadLine()) != NULL) {
     167             128 :         if (strlen(pszLine) < 2 || pszLine[0] != '&')
     168               0 :             continue;
     169             128 :         if (pszLine[1] == 'B') {
     170              61 :             pszBlockName = GetDataBlockName(pszLine);
     171              61 :             if (pszBlockName == NULL) { 
     172                 :                 CPLError(CE_Failure, CPLE_NotSupported, 
     173               0 :                          "Corrupted data - line\n%s\n", pszLine);
     174               0 :                 return -1;
     175                 :             }
     176              61 :             poNewDataBlock = (IVFKDataBlock *) CreateDataBlock(pszBlockName);
     177              61 :             CPLFree(pszBlockName);
     178              61 :             poNewDataBlock->SetGeometryType();
     179              61 :             poNewDataBlock->SetProperties(pszLine);
     180              61 :             AddDataBlock(poNewDataBlock, pszLine);
     181                 :         }
     182              67 :         else if (pszLine[1] == 'H') {
     183                 :             /* header - metadata */
     184              13 :             AddInfo(pszLine);
     185                 :         }
     186              54 :         else if (pszLine[1] == 'K' && strlen(pszLine) == 2) {
     187                 :             /* end of file */
     188               1 :             CPLFree(pszLine);
     189               1 :             break;
     190                 :         }
     191             127 :         CPLFree(pszLine);
     192                 :     }
     193                 :     
     194               1 :     return m_nDataBlockCount;
     195                 : }
     196                 : 
     197                 : 
     198                 : /*!
     199                 :   \brief Load data records (&D)
     200                 : 
     201                 :   Call VFKReader::OpenFile() before this function.
     202                 :   
     203                 :   \return number of data records or -1 on error
     204                 : */
     205               4 : int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
     206                 : {
     207                 :     const char *pszName;
     208                 :     char       *pszBlockName, *pszLine;
     209                 :     int         nLength, iLine;
     210                 :     
     211               4 :     CPLString pszMultiLine;
     212                 : 
     213                 :     VFKFeature *poNewFeature;
     214                 :     
     215               4 :     if (poDataBlock->GetFeatureCount() >= 0)
     216               0 :         return -1;
     217                 : 
     218               4 :     poDataBlock->SetFeatureCount(0);
     219               4 :     poDataBlock->SetMaxFID(0);
     220               4 :     pszName = poDataBlock->GetName();
     221                 : 
     222               4 :     VSIFSeek(m_poFD, 0, SEEK_SET);
     223               4 :     iLine = 0;
     224             516 :     while ((pszLine = ReadLine()) != NULL) {
     225             512 :         iLine++;
     226             512 :         nLength = strlen(pszLine);
     227             512 :         if (nLength < 2)
     228               0 :             continue;
     229                 :         
     230             512 :         if (pszLine[1] == 'D') {
     231             212 :             pszBlockName = GetDataBlockName(pszLine);
     232             212 :             if (pszBlockName && EQUAL(pszBlockName, pszName)) {
     233                 :                 /* merge lines if needed */
     234              53 :                 if (pszLine[nLength - 2] == '\302' &&
     235               0 :                     pszLine[nLength - 1] == '\244') {
     236                 :                     
     237                 :                     /* remove 0302 0244 (currency sign) from string */
     238               0 :                     pszLine[nLength - 2] = '\0';
     239                 :                     
     240               0 :                     pszMultiLine.clear();
     241               0 :                     pszMultiLine = pszLine;
     242               0 :                     CPLFree(pszLine);
     243                 :                     
     244               0 :                     while ((pszLine = ReadLine()) != NULL &&
     245               0 :                            pszLine[strlen(pszLine) - 2] == '\302' &&
     246               0 :                            pszLine[strlen(pszLine) - 1] == '\244') {
     247                 :                         /* append line */
     248               0 :                         pszMultiLine += pszLine;
     249                 :                         /* remove 0302 0244 (currency sign) from string */
     250               0 :                         pszMultiLine[strlen(pszLine) - 2] = '\0';
     251                 : 
     252               0 :                         CPLFree(pszLine);
     253                 :                     } 
     254               0 :                     pszMultiLine += pszLine;
     255               0 :                     CPLFree(pszLine);
     256                 :                     
     257               0 :                     nLength = pszMultiLine.size();
     258               0 :                     pszLine = (char *) CPLMalloc(nLength + 1);
     259               0 :                     strncpy(pszLine, pszMultiLine.c_str(), nLength);
     260               0 :                     pszLine[nLength] = '\0';
     261                 :                 }
     262                 :                 
     263              53 :                 poNewFeature = new VFKFeature(poDataBlock);
     264             106 :                 if (poNewFeature->SetProperties(pszLine))
     265              53 :                     AddFeature(poDataBlock, poNewFeature);
     266                 :                 else
     267                 :                     CPLError(CE_Warning, CPLE_AppDefined, 
     268               0 :                              "Invalid VFK data record skipped (line %d).\n%s\n", iLine, pszLine);
     269                 :             }
     270             212 :             CPLFree(pszBlockName);
     271                 :         }
     272             300 :         else if (pszLine[1] == 'K' && strlen(pszLine) == 2) {
     273                 :             /* end of file */
     274               4 :             CPLFree(pszLine);
     275               4 :             break;
     276                 :         }
     277             508 :         CPLFree(pszLine);
     278                 :     }
     279                 :     
     280                 :     CPLDebug("OGR_VFK", "VFKReader::ReadDataRecords(): name=%s n=%d",
     281               4 :              poDataBlock->GetName(), poDataBlock->GetFeatureCount());
     282                 : 
     283               4 :     return poDataBlock->GetFeatureCount();
     284                 : }
     285                 : 
     286               0 : IVFKDataBlock *VFKReader::CreateDataBlock(const char *pszBlockName)
     287                 : {
     288               0 :   return (IVFKDataBlock *) new VFKDataBlock(pszBlockName, (IVFKReader *) this);
     289                 : }
     290                 : 
     291                 : /*!
     292                 :   \brief Add new data block
     293                 : 
     294                 :   \param poNewDataBlock pointer to VFKDataBlock instance
     295                 :   \param pszDefn unused (FIXME ?)
     296                 : */
     297             122 : void VFKReader::AddDataBlock(IVFKDataBlock *poNewDataBlock, const char *pszDefn)
     298                 : {
     299             122 :     m_nDataBlockCount++;
     300                 :     
     301                 :     m_papoDataBlock = (IVFKDataBlock **)
     302             122 :         CPLRealloc(m_papoDataBlock, sizeof (IVFKDataBlock *) * m_nDataBlockCount);
     303             122 :     m_papoDataBlock[m_nDataBlockCount-1] = poNewDataBlock;
     304             122 : }
     305                 : 
     306                 : /*!
     307                 :   \brief Add feature
     308                 : 
     309                 :   \param poDataBlock pointer to VFKDataBlock instance
     310                 :   \param poFeature pointer to VFKFeature instance
     311                 : */
     312               0 : void VFKReader::AddFeature(IVFKDataBlock *poDataBlock, VFKFeature *poFeature)
     313                 : {
     314               0 :     poDataBlock->AddFeature(poFeature);
     315               0 : }
     316                 : 
     317                 : /*!
     318                 :   \brief Get data block
     319                 : 
     320                 :   \param i index (starting with 0)
     321                 : 
     322                 :   \return pointer to VFKDataBlock instance or NULL on failure
     323                 : */
     324            4167 : IVFKDataBlock *VFKReader::GetDataBlock(int i) const
     325                 : {
     326            4167 :     if (i < 0 || i >= m_nDataBlockCount)
     327               0 :         return NULL;
     328                 :     
     329            4167 :     return m_papoDataBlock[i];
     330                 : }
     331                 : 
     332                 : /*!
     333                 :   \brief Get data block
     334                 : 
     335                 :   \param pszName data block name
     336                 : 
     337                 :   \return pointer to VFKDataBlock instance or NULL on failure
     338                 : */
     339             125 : IVFKDataBlock *VFKReader::GetDataBlock(const char *pszName) const
     340                 : {
     341            3920 :     for (int i = 0; i < m_nDataBlockCount; i++) {
     342            3920 :         if (EQUAL(GetDataBlock(i)->GetName(), pszName))
     343             125 :             return GetDataBlock(i);
     344                 :     }
     345                 : 
     346               0 :     return NULL;
     347                 : }
     348                 : 
     349                 : /*!
     350                 :   \brief Load geometry (loop datablocks)
     351                 : 
     352                 :   \return number of invalid features
     353                 : */
     354               0 : int VFKReader::LoadGeometry()
     355                 : {
     356                 :     long int nfeatures;
     357                 : 
     358               0 :     nfeatures = 0;
     359               0 :     for (int i = 0; i < m_nDataBlockCount; i++) {
     360               0 :         nfeatures += m_papoDataBlock[i]->LoadGeometry();
     361                 :     }
     362                 :     
     363               0 :     CPLDebug("OGR_VFK", "VFKReader::LoadGeometry(): invalid=%ld", nfeatures);
     364                 :     
     365               0 :     return nfeatures;
     366                 : }
     367                 : 
     368                 : /*!
     369                 :   \brief Add info
     370                 : 
     371                 :   \param pszLine pointer to line
     372                 : */
     373              13 : void VFKReader::AddInfo(const char *pszLine)
     374                 : {
     375                 :     int         iKeyLength, iValueLength;
     376                 :     char       *pszKey, *pszValue;
     377                 :     const char *poChar, *poKey, *poValue;
     378              13 :     CPLString   key, value;
     379                 :     
     380              13 :     poChar = poKey = pszLine + 2; /* &H */
     381              13 :     iKeyLength = 0;
     382             103 :     while (*poChar != '\0' && *poChar != ';') {
     383              77 :         iKeyLength++;
     384              77 :         poChar ++;
     385                 :     }
     386              13 :     if (*poChar == '\0')
     387                 :         return;
     388                 : 
     389              13 :     pszKey = (char *) CPLMalloc(iKeyLength + 1);
     390              13 :     strncpy(pszKey, poKey, iKeyLength);
     391              13 :     pszKey[iKeyLength] = '\0';
     392                 : 
     393              13 :     poValue = ++poChar; /* skip ';' */
     394              13 :     iValueLength = 0;
     395            1177 :     while (*poChar != '\0') {
     396            1151 :         iValueLength++;
     397            1151 :         poChar++;
     398                 :     }
     399                 : 
     400              13 :     pszValue = (char *) CPLMalloc(iValueLength + 1);
     401              13 :     strncpy(pszValue, poValue, iValueLength);
     402              13 :     pszValue[iValueLength] = '\0';
     403                 : 
     404              13 :     poInfo[pszKey] = pszValue;
     405                 : 
     406              13 :     if (EQUAL(pszKey, "CODEPAGE")) {
     407               1 :         if (!EQUAL(pszValue, "\"WE8ISO8859P2\""))
     408               0 :             m_bLatin2 = FALSE;
     409                 :     }
     410                 : 
     411              13 :     CPLFree(pszKey);
     412              13 :     CPLFree(pszValue);
     413                 : }
     414                 : 
     415                 : /*!
     416                 :   \brief Get info
     417                 : 
     418                 :   \param key key string
     419                 : 
     420                 :   \return pointer to value string or NULL if key not found
     421                 : */
     422               0 : const char *VFKReader::GetInfo(const char *key)
     423                 : {
     424               0 :     if (poInfo.find(key) == poInfo.end())
     425               0 :         return NULL;
     426                 : 
     427               0 :     return poInfo[key].c_str();
     428                 : }

Generated by: LCOV version 1.7