LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/bna - ogrbnadatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 149 111 74.5 %
Date: 2012-12-26 Functions: 10 6 60.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrbnadatasource.cpp 23244 2011-10-16 21:52:16Z rouault $
       3                 :  *
       4                 :  * Project:  BNA Translator
       5                 :  * Purpose:  Implements OGRBNADataSource class
       6                 :  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2007, Even Rouault
      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                 : 
      30                 : #include "ogr_bna.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include "cpl_csv.h"
      34                 : #include "ogrbnaparser.h"
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                          OGRBNADataSource()                          */
      38                 : /************************************************************************/
      39                 : 
      40             730 : OGRBNADataSource::OGRBNADataSource()
      41                 : 
      42                 : {
      43             730 :     papoLayers = NULL;
      44             730 :     nLayers = 0;
      45                 :     
      46             730 :     fpOutput = NULL;
      47                 : 
      48             730 :     pszName = NULL;
      49                 :     
      50             730 :     pszCoordinateSeparator = NULL;
      51                 : 
      52             730 :     bUpdate = FALSE;
      53             730 : }
      54                 : 
      55                 : /************************************************************************/
      56                 : /*                         ~OGRBNADataSource()                          */
      57                 : /************************************************************************/
      58                 : 
      59             730 : OGRBNADataSource::~OGRBNADataSource()
      60                 : 
      61                 : {
      62             730 :     if ( fpOutput != NULL )
      63                 :     {
      64               3 :         VSIFCloseL( fpOutput);
      65                 :     }
      66                 : 
      67             771 :     for( int i = 0; i < nLayers; i++ )
      68              41 :         delete papoLayers[i];
      69             730 :     CPLFree( papoLayers );
      70                 :     
      71             730 :     CPLFree( pszCoordinateSeparator );
      72                 : 
      73             730 :     CPLFree( pszName );
      74             730 : }
      75                 : 
      76                 : /************************************************************************/
      77                 : /*                           TestCapability()                           */
      78                 : /************************************************************************/
      79                 : 
      80               0 : int OGRBNADataSource::TestCapability( const char * pszCap )
      81                 : 
      82                 : {
      83               0 :     if( EQUAL(pszCap,ODsCCreateLayer) )
      84               0 :         return TRUE;
      85               0 :     else if( EQUAL(pszCap,ODsCDeleteLayer) )
      86               0 :         return FALSE;
      87                 :     else
      88               0 :         return FALSE;
      89                 : }
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                              GetLayer()                              */
      93                 : /************************************************************************/
      94                 : 
      95             101 : OGRLayer *OGRBNADataSource::GetLayer( int iLayer )
      96                 : 
      97                 : {
      98             101 :     if( iLayer < 0 || iLayer >= nLayers )
      99               0 :         return NULL;
     100                 :     else
     101             101 :         return papoLayers[iLayer];
     102                 : }
     103                 : 
     104                 : /************************************************************************/
     105                 : /*                            CreateLayer()                             */
     106                 : /************************************************************************/
     107                 : 
     108              12 : OGRLayer * OGRBNADataSource::CreateLayer( const char * pszLayerName,
     109                 :                                           OGRSpatialReference *poSRS,
     110                 :                                           OGRwkbGeometryType eType,
     111                 :                                           char ** papszOptions )
     112                 : 
     113                 : {
     114                 :     BNAFeatureType bnaFeatureType;
     115                 :     
     116              12 :     switch(eType)
     117                 :     {
     118                 :         case wkbPolygon:
     119                 :         case wkbPolygon25D:
     120                 :         case wkbMultiPolygon:
     121                 :         case wkbMultiPolygon25D:
     122               6 :             bnaFeatureType = BNA_POLYGON;
     123               6 :             break;
     124                 :         
     125                 :         case wkbPoint:
     126                 :         case wkbPoint25D:
     127               3 :             bnaFeatureType = BNA_POINT;
     128               3 :             break;
     129                 :             
     130                 :         case wkbLineString:
     131                 :         case wkbLineString25D:
     132               3 :             bnaFeatureType = BNA_POLYLINE;
     133               3 :             break;
     134                 :             
     135                 :         default:
     136                 :             CPLError( CE_Failure, CPLE_NotSupported,
     137                 :                     "Geometry type of `%s' not supported in BNAs.\n",
     138               0 :                     OGRGeometryTypeToName(eType) );
     139               0 :             return NULL;
     140                 :     }
     141                 :     
     142              12 :     nLayers++;
     143              12 :     papoLayers = (OGRBNALayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRBNALayer*));
     144              12 :     papoLayers[nLayers-1] = new OGRBNALayer( pszName, pszLayerName, bnaFeatureType, eType, TRUE, this );
     145                 :     
     146              12 :     return papoLayers[nLayers-1];
     147                 : }
     148                 : 
     149                 : /************************************************************************/
     150                 : /*                                Open()                                */
     151                 : /************************************************************************/
     152                 : 
     153             727 : int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
     154                 : 
     155                 : {
     156             727 :     int ok = FALSE;
     157                 : 
     158             727 :     pszName = CPLStrdup( pszFilename );
     159             727 :     bUpdate = bUpdateIn;
     160                 : 
     161                 : /* -------------------------------------------------------------------- */
     162                 : /*      Determine what sort of object this is.                          */
     163                 : /* -------------------------------------------------------------------- */
     164                 :     VSIStatBufL sStatBuf;
     165                 : 
     166             727 :     if( VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) != 0 )
     167             189 :         return FALSE;
     168                 :     
     169                 : // -------------------------------------------------------------------- 
     170                 : //      Does this appear to be a .bna file?
     171                 : // --------------------------------------------------------------------
     172             538 :     if( !(EQUAL( CPLGetExtension(pszFilename), "bna" )
     173                 :            || ((EQUALN( pszFilename, "/vsigzip/", 9) || EQUALN( pszFilename, "/vsizip/", 8)) &&
     174                 :                (strstr( pszFilename, ".bna") || strstr( pszFilename, ".BNA")))) )
     175             530 :         return FALSE;
     176                 :     
     177               8 :     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
     178               8 :     if (fp)
     179                 :     {
     180                 :         BNARecord* record;
     181               8 :         int curLine = 0;
     182               8 :         const char* layerRadixName[] = { "points", "polygons", "lines", "ellipses"};
     183               8 :         OGRwkbGeometryType wkbGeomTypes[] = { wkbPoint, wkbMultiPolygon, wkbLineString, wkbPolygon };
     184                 :         int i;
     185                 : #if defined(BNA_FAST_DS_OPEN)
     186                 :         record = BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
     187                 :         BNA_FreeRecord(record);
     188                 : 
     189                 :         if (ok)
     190                 :         {
     191                 :             nLayers = 4;
     192                 : 
     193                 :             papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*));
     194                 :             for(i=0;i<4;i++)
     195                 :                 papoLayers[i] = new OGRBNALayer( pszFilename,
     196                 :                                                  layerRadixName[i],
     197                 :                                                  (BNAFeatureType)i, wkbGeomTypes[i], FALSE, this );
     198                 :         }
     199                 : #else
     200               8 :         int nFeatures[4] = { 0, 0, 0, 0 };
     201               8 :         OffsetAndLine* offsetAndLineFeaturesTable[4] = { NULL, NULL, NULL, NULL };
     202               8 :         int nIDs[4] = {0, 0, 0, 0};
     203               8 :         int partialIndexTable = TRUE;
     204                 : 
     205              58 :         while(1)
     206                 :         {
     207              66 :             int offset = (int) VSIFTellL(fp);
     208              66 :             int line = curLine;
     209              66 :             record =  BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
     210              66 :             if (ok == FALSE)
     211                 :             {
     212               0 :                 BNA_FreeRecord(record);
     213               0 :                 if (line != 0)
     214               0 :                     ok = TRUE;
     215               0 :                 break;
     216                 :             }
     217              66 :             if (record == NULL)
     218                 :             {
     219                 :                 /* end of file */
     220               8 :                 ok = TRUE;
     221                 : 
     222                 :                 /* and we have finally build the whole index table */
     223               8 :                 partialIndexTable = FALSE;
     224               8 :                 break;
     225                 :             }
     226                 : 
     227              58 :             if (record->nIDs > nIDs[record->featureType])
     228              29 :                 nIDs[record->featureType] = record->nIDs;
     229                 : 
     230              58 :             nFeatures[record->featureType]++;
     231              58 :             offsetAndLineFeaturesTable[record->featureType] =
     232              58 :                 (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable[record->featureType],
     233             116 :                                            nFeatures[record->featureType] * sizeof(OffsetAndLine));
     234              58 :             offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].offset = offset;
     235              58 :             offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].line = line;
     236                 : 
     237              58 :             BNA_FreeRecord(record);
     238                 :         }
     239                 : 
     240               8 :         nLayers = (nFeatures[0] != 0) + (nFeatures[1] != 0) + (nFeatures[2] != 0) + (nFeatures[3] != 0);
     241               8 :         papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*));
     242               8 :         int iLayer = 0;
     243              40 :         for(i=0;i<4;i++)
     244                 :         {
     245              32 :             if (nFeatures[i])
     246                 :             {
     247              29 :                 papoLayers[iLayer] = new OGRBNALayer( pszFilename,
     248                 :                                                       layerRadixName[i],
     249                 :                                                       (BNAFeatureType)i,
     250                 :                                                       wkbGeomTypes[i],
     251                 :                                                       FALSE,
     252                 :                                                       this,
     253              58 :                                                       nIDs[i]);
     254              29 :                 papoLayers[iLayer]->SetFeatureIndexTable(nFeatures[i],
     255                 :                                                         offsetAndLineFeaturesTable[i],
     256              58 :                                                         partialIndexTable);
     257              29 :                 iLayer++;
     258                 :             }
     259                 :         }
     260                 : #endif
     261               8 :         VSIFCloseL(fp);
     262                 :     }
     263                 : 
     264               8 :     return ok;
     265                 : }
     266                 : 
     267                 : 
     268                 : /************************************************************************/
     269                 : /*                               Create()                               */
     270                 : /************************************************************************/
     271                 : 
     272               3 : int OGRBNADataSource::Create( const char *pszFilename, 
     273                 :                               char **papszOptions )
     274                 : {
     275               3 :     if( fpOutput != NULL)
     276                 :     {
     277               0 :         CPLAssert( FALSE );
     278               0 :         return FALSE;
     279                 :     }
     280                 : 
     281               3 :     if( strcmp(pszFilename,"/dev/stdout") == 0 )
     282               0 :         pszFilename = "/vsistdout/";
     283                 : 
     284                 : /* -------------------------------------------------------------------- */
     285                 : /*     Do not override exiting file.                                    */
     286                 : /* -------------------------------------------------------------------- */
     287                 :     VSIStatBufL sStatBuf;
     288                 : 
     289               3 :     if( VSIStatL( pszFilename, &sStatBuf ) == 0 )
     290               0 :         return FALSE;
     291                 :     
     292                 : /* -------------------------------------------------------------------- */
     293                 : /*      Create the output file.                                         */
     294                 : /* -------------------------------------------------------------------- */
     295               3 :     pszName = CPLStrdup( pszFilename );
     296                 : 
     297               3 :     fpOutput = VSIFOpenL( pszFilename, "wb" );
     298               3 :     if( fpOutput == NULL )
     299                 :     {
     300                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     301                 :                   "Failed to create BNA file %s.", 
     302               0 :                   pszFilename );
     303               0 :         return FALSE;
     304                 :     }
     305                 :     
     306                 :     /* EOL token */
     307               3 :     const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
     308                 : 
     309               3 :     if( pszCRLFFormat == NULL )
     310                 :     {
     311                 : #ifdef WIN32
     312                 :         bUseCRLF = TRUE;
     313                 : #else
     314               1 :         bUseCRLF = FALSE;
     315                 : #endif
     316                 :     }
     317               2 :     else if( EQUAL(pszCRLFFormat,"CRLF") )
     318               1 :         bUseCRLF = TRUE;
     319               1 :     else if( EQUAL(pszCRLFFormat,"LF") )
     320               1 :         bUseCRLF = FALSE;
     321                 :     else
     322                 :     {
     323                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     324                 :                   "LINEFORMAT=%s not understood, use one of CRLF or LF.",
     325               0 :                   pszCRLFFormat );
     326                 : #ifdef WIN32
     327                 :         bUseCRLF = TRUE;
     328                 : #else
     329               0 :         bUseCRLF = FALSE;
     330                 : #endif
     331                 :     }
     332                 : 
     333                 :     /* Multi line or single line format ? */
     334               3 :     bMultiLine = CSLFetchBoolean( papszOptions, "MULTILINE", TRUE);
     335                 :     
     336                 :     /* Number of identifiers per record */
     337               3 :     const char* pszNbOutID = CSLFetchNameValue ( papszOptions, "NB_IDS");
     338               3 :     if (pszNbOutID == NULL)
     339                 :     {
     340               3 :         nbOutID = NB_MIN_BNA_IDS;
     341                 :     }
     342               0 :     else if (EQUAL(pszNbOutID, "NB_SOURCE_FIELDS"))
     343                 :     {
     344               0 :         nbOutID = -1;
     345                 :     }
     346                 :     else
     347                 :     {
     348               0 :         nbOutID = atoi(pszNbOutID);
     349               0 :         if (nbOutID <= 0)
     350                 :         {
     351                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     352                 :                   "NB_ID=%s not understood. Must be >=%d and <=%d or equal to NB_SOURCE_FIELDS",
     353               0 :                   pszNbOutID, NB_MIN_BNA_IDS, NB_MAX_BNA_IDS );
     354               0 :             nbOutID = NB_MIN_BNA_IDS;
     355                 :         }
     356               0 :         if (nbOutID > NB_MAX_BNA_IDS)
     357                 :         {
     358                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     359                 :                   "NB_ID=%s not understood. Must be >=%d and <=%d or equal to NB_SOURCE_FIELDS",
     360               0 :                   pszNbOutID, NB_MIN_BNA_IDS, NB_MAX_BNA_IDS );
     361               0 :             nbOutID = NB_MAX_BNA_IDS;
     362                 :         }
     363                 :     }
     364                 :     
     365                 :     /* Ellipses export as ellipses or polygons ? */
     366               3 :     bEllipsesAsEllipses = CSLFetchBoolean( papszOptions, "ELLIPSES_AS_ELLIPSES", TRUE);
     367                 :     
     368                 :     /* Number of coordinate pairs per line */
     369               3 :     const char* pszNbPairPerLine = CSLFetchNameValue( papszOptions, "NB_PAIRS_PER_LINE");
     370               3 :     if (pszNbPairPerLine)
     371                 :     {
     372               0 :         nbPairPerLine = atoi(pszNbPairPerLine);
     373               0 :         if (nbPairPerLine <= 0)
     374               0 :             nbPairPerLine = (bMultiLine == FALSE) ? 1000000000 : 1;
     375               0 :         if (bMultiLine == FALSE)
     376                 :         {
     377               0 :             CPLError( CE_Warning, CPLE_AppDefined, "NB_PAIR_PER_LINE option is ignored when MULTILINE=NO");
     378                 :         }
     379                 :     }
     380                 :     else
     381                 :     {
     382               3 :         nbPairPerLine = (bMultiLine == FALSE) ? 1000000000 : 1;
     383                 :     }
     384                 :     
     385                 :     /* Coordinate precision */
     386               3 :     const char* pszCoordinatePrecision = CSLFetchNameValue( papszOptions, "COORDINATE_PRECISION");
     387               3 :     if (pszCoordinatePrecision)
     388                 :     {
     389               2 :         coordinatePrecision = atoi(pszCoordinatePrecision);
     390               2 :         if (coordinatePrecision <= 0)
     391               0 :             coordinatePrecision = 0;
     392               2 :         else if (coordinatePrecision >= 20)
     393               0 :             coordinatePrecision = 20;
     394                 :     }
     395                 :     else
     396                 :     {
     397               1 :         coordinatePrecision = 10;
     398                 :     }
     399                 :     
     400               3 :     pszCoordinateSeparator = (char*)CSLFetchNameValue( papszOptions, "COORDINATE_SEPARATOR");
     401               3 :     if (pszCoordinateSeparator == NULL)
     402               3 :         pszCoordinateSeparator = CPLStrdup(",");
     403                 :     else
     404               0 :         pszCoordinateSeparator = CPLStrdup(pszCoordinateSeparator);
     405                 : 
     406               3 :     return TRUE;
     407                 : }

Generated by: LCOV version 1.7