LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/bna - ogrbnadatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 148 111 75.0 %
Date: 2010-01-09 Functions: 8 7 87.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrbnadatasource.cpp
       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             174 : OGRBNADataSource::OGRBNADataSource()
      41                 : 
      42                 : {
      43             174 :     papoLayers = NULL;
      44             174 :     nLayers = 0;
      45                 :     
      46             174 :     fpOutput = NULL;
      47                 : 
      48             174 :     pszName = NULL;
      49                 :     
      50             174 :     pszCoordinateSeparator = NULL;
      51                 : 
      52             174 :     bUpdate = FALSE;
      53             174 : }
      54                 : 
      55                 : /************************************************************************/
      56                 : /*                         ~OGRBNADataSource()                          */
      57                 : /************************************************************************/
      58                 : 
      59             348 : OGRBNADataSource::~OGRBNADataSource()
      60                 : 
      61                 : {
      62             174 :     if ( fpOutput != NULL )
      63                 :     {
      64               3 :         VSIFClose( fpOutput);
      65                 :     }
      66                 : 
      67             215 :     for( int i = 0; i < nLayers; i++ )
      68              41 :         delete papoLayers[i];
      69             174 :     CPLFree( papoLayers );
      70                 :     
      71             174 :     CPLFree( pszCoordinateSeparator );
      72                 : 
      73             174 :     CPLFree( pszName );
      74             348 : }
      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             171 : int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
     154                 : 
     155                 : {
     156             171 :     int ok = FALSE;
     157                 : 
     158             171 :     pszName = CPLStrdup( pszFilename );
     159             171 :     bUpdate = bUpdateIn;
     160                 : 
     161                 : /* -------------------------------------------------------------------- */
     162                 : /*      Determine what sort of object this is.                          */
     163                 : /* -------------------------------------------------------------------- */
     164                 :     VSIStatBufL sStatBuf;
     165                 : 
     166             171 :     if( VSIStatL( pszFilename, &sStatBuf ) != 0 )
     167              60 :         return FALSE;
     168                 :     
     169                 : // -------------------------------------------------------------------- 
     170                 : //      Does this appear to be an .bna file?
     171                 : // --------------------------------------------------------------------
     172             111 :     if( !EQUAL( CPLGetExtension(pszFilename), "bna" ) )
     173             103 :         return FALSE;
     174                 :     
     175               8 :     FILE* fp = VSIFOpen(pszFilename, "rb");
     176               8 :     if (fp)
     177                 :     {
     178                 :         BNARecord* record;
     179               8 :         int curLine = 0;
     180               8 :         const char* layerRadixName[] = { "points", "polygons", "lines", "ellipses"};
     181               8 :         OGRwkbGeometryType wkbGeomTypes[] = { wkbPoint, wkbMultiPolygon, wkbLineString, wkbPolygon };
     182                 :         int i;
     183                 : #if defined(BNA_FAST_DS_OPEN)
     184                 :         record = BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
     185                 :         BNA_FreeRecord(record);
     186                 : 
     187                 :         if (ok)
     188                 :         {
     189                 :             nLayers = 4;
     190                 : 
     191                 :             papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*));
     192                 :             for(i=0;i<4;i++)
     193                 :                 papoLayers[i] = new OGRBNALayer( pszFilename,
     194                 :                                                  layerRadixName[i],
     195                 :                                                  (BNAFeatureType)i, wkbGeomTypes[i], FALSE, this );
     196                 :         }
     197                 : #else
     198               8 :         int nFeatures[4] = { 0, 0, 0, 0 };
     199               8 :         OffsetAndLine* offsetAndLineFeaturesTable[4] = { NULL, NULL, NULL, NULL };
     200               8 :         int nIDs[4] = {0, 0, 0, 0};
     201               8 :         int partialIndexTable = TRUE;
     202                 : 
     203              58 :         while(1)
     204                 :         {
     205              66 :             int offset = VSIFTell(fp);
     206              66 :             int line = curLine;
     207              66 :             record =  BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
     208              66 :             if (ok == FALSE)
     209                 :             {
     210               0 :                 BNA_FreeRecord(record);
     211               0 :                 if (line != 0)
     212               0 :                     ok = TRUE;
     213               0 :                 break;
     214                 :             }
     215              66 :             if (record == NULL)
     216                 :             {
     217                 :                 /* end of file */
     218               8 :                 ok = TRUE;
     219                 : 
     220                 :                 /* and we have finally build the whole index table */
     221               8 :                 partialIndexTable = FALSE;
     222               8 :                 break;
     223                 :             }
     224                 : 
     225              58 :             if (record->nIDs > nIDs[record->featureType])
     226              29 :                 nIDs[record->featureType] = record->nIDs;
     227                 : 
     228              58 :             nFeatures[record->featureType]++;
     229              58 :             offsetAndLineFeaturesTable[record->featureType] =
     230              58 :                 (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable[record->featureType],
     231             116 :                                            nFeatures[record->featureType] * sizeof(OffsetAndLine));
     232              58 :             offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].offset = offset;
     233              58 :             offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].line = line;
     234                 : 
     235              58 :             BNA_FreeRecord(record);
     236                 :         }
     237                 : 
     238               8 :         nLayers = (nFeatures[0] != 0) + (nFeatures[1] != 0) + (nFeatures[2] != 0) + (nFeatures[3] != 0);
     239               8 :         papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*));
     240               8 :         int iLayer = 0;
     241              40 :         for(i=0;i<4;i++)
     242                 :         {
     243              32 :             if (nFeatures[i])
     244                 :             {
     245              29 :                 papoLayers[iLayer] = new OGRBNALayer( pszFilename,
     246                 :                                                       layerRadixName[i],
     247                 :                                                       (BNAFeatureType)i,
     248                 :                                                       wkbGeomTypes[i],
     249                 :                                                       FALSE,
     250                 :                                                       this,
     251              58 :                                                       nIDs[i]);
     252              29 :                 papoLayers[iLayer]->SetFeatureIndexTable(nFeatures[i],
     253                 :                                                         offsetAndLineFeaturesTable[i],
     254              58 :                                                         partialIndexTable);
     255              29 :                 iLayer++;
     256                 :             }
     257                 :         }
     258                 : #endif
     259               8 :         VSIFClose(fp);
     260                 :     }
     261                 : 
     262               8 :     return ok;
     263                 : }
     264                 : 
     265                 : 
     266                 : /************************************************************************/
     267                 : /*                               Create()                               */
     268                 : /************************************************************************/
     269                 : 
     270               3 : int OGRBNADataSource::Create( const char *pszFilename, 
     271                 :                               char **papszOptions )
     272                 : {
     273               3 :     if( fpOutput != NULL)
     274                 :     {
     275                 :         CPLAssert( FALSE );
     276               0 :         return FALSE;
     277                 :     }
     278                 : 
     279                 : /* -------------------------------------------------------------------- */
     280                 : /*     Do not override exiting file.                                    */
     281                 : /* -------------------------------------------------------------------- */
     282                 :     VSIStatBufL sStatBuf;
     283                 : 
     284               3 :     if( VSIStatL( pszFilename, &sStatBuf ) == 0 )
     285               0 :         return FALSE;
     286                 :     
     287                 : /* -------------------------------------------------------------------- */
     288                 : /*      Create the output file.                                         */
     289                 : /* -------------------------------------------------------------------- */
     290               3 :     pszName = CPLStrdup( pszFilename );
     291                 : 
     292               3 :     if( EQUAL(pszFilename,"stdout") )
     293               0 :         fpOutput = stdout;
     294                 :     else
     295               3 :         fpOutput = VSIFOpen( pszFilename, "wb" );
     296               3 :     if( fpOutput == NULL )
     297                 :     {
     298                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     299                 :                   "Failed to create BNA file %s.", 
     300               0 :                   pszFilename );
     301               0 :         return FALSE;
     302                 :     }
     303                 :     
     304                 :     /* EOL token */
     305               3 :     const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
     306                 : 
     307               3 :     if( pszCRLFFormat == NULL )
     308                 :     {
     309                 : #ifdef WIN32
     310                 :         bUseCRLF = TRUE;
     311                 : #else
     312               1 :         bUseCRLF = FALSE;
     313                 : #endif
     314                 :     }
     315               2 :     else if( EQUAL(pszCRLFFormat,"CRLF") )
     316               1 :         bUseCRLF = TRUE;
     317               1 :     else if( EQUAL(pszCRLFFormat,"LF") )
     318               1 :         bUseCRLF = FALSE;
     319                 :     else
     320                 :     {
     321                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     322                 :                   "LINEFORMAT=%s not understood, use one of CRLF or LF.",
     323               0 :                   pszCRLFFormat );
     324                 : #ifdef WIN32
     325                 :         bUseCRLF = TRUE;
     326                 : #else
     327               0 :         bUseCRLF = FALSE;
     328                 : #endif
     329                 :     }
     330                 : 
     331                 :     /* Multi line or single line format ? */
     332               3 :     bMultiLine = CSLFetchBoolean( papszOptions, "MULTILINE", TRUE);
     333                 :     
     334                 :     /* Number of identifiers per record */
     335               3 :     const char* pszNbOutID = CSLFetchNameValue ( papszOptions, "NB_IDS");
     336               3 :     if (pszNbOutID == NULL)
     337                 :     {
     338               3 :         nbOutID = NB_MIN_BNA_IDS;
     339                 :     }
     340               0 :     else if (EQUAL(pszNbOutID, "NB_SOURCE_FIELDS"))
     341                 :     {
     342               0 :         nbOutID = -1;
     343                 :     }
     344                 :     else
     345                 :     {
     346               0 :         nbOutID = atoi(pszNbOutID);
     347               0 :         if (nbOutID <= 0)
     348                 :         {
     349                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     350                 :                   "NB_ID=%s not understood. Must be >=%d and <=%d or equal to NB_SOURCE_FIELDS",
     351               0 :                   pszNbOutID, NB_MIN_BNA_IDS, NB_MAX_BNA_IDS );
     352               0 :             nbOutID = NB_MIN_BNA_IDS;
     353                 :         }
     354               0 :         if (nbOutID > NB_MAX_BNA_IDS)
     355                 :         {
     356                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     357                 :                   "NB_ID=%s not understood. Must be >=%d and <=%d or equal to NB_SOURCE_FIELDS",
     358               0 :                   pszNbOutID, NB_MIN_BNA_IDS, NB_MAX_BNA_IDS );
     359               0 :             nbOutID = NB_MAX_BNA_IDS;
     360                 :         }
     361                 :     }
     362                 :     
     363                 :     /* Ellipses export as ellipses or polygons ? */
     364               3 :     bEllipsesAsEllipses = CSLFetchBoolean( papszOptions, "ELLIPSES_AS_ELLIPSES", TRUE);
     365                 :     
     366                 :     /* Number of coordinate pairs per line */
     367               3 :     const char* pszNbPairPerLine = CSLFetchNameValue( papszOptions, "NB_PAIRS_PER_LINE");
     368               3 :     if (pszNbPairPerLine)
     369                 :     {
     370               0 :         nbPairPerLine = atoi(pszNbPairPerLine);
     371               0 :         if (nbPairPerLine <= 0)
     372               0 :             nbPairPerLine = (bMultiLine == FALSE) ? 1000000000 : 1;
     373               0 :         if (bMultiLine == FALSE)
     374                 :         {
     375               0 :             CPLError( CE_Warning, CPLE_AppDefined, "NB_PAIR_PER_LINE option is ignored when MULTILINE=NO");
     376                 :         }
     377                 :     }
     378                 :     else
     379                 :     {
     380               3 :         nbPairPerLine = (bMultiLine == FALSE) ? 1000000000 : 1;
     381                 :     }
     382                 :     
     383                 :     /* Coordinate precision */
     384               3 :     const char* pszCoordinatePrecision = CSLFetchNameValue( papszOptions, "COORDINATE_PRECISION");
     385               3 :     if (pszCoordinatePrecision)
     386                 :     {
     387               2 :         coordinatePrecision = atoi(pszCoordinatePrecision);
     388               2 :         if (coordinatePrecision <= 0)
     389               0 :             coordinatePrecision = 0;
     390               2 :         else if (coordinatePrecision >= 20)
     391               0 :             coordinatePrecision = 20;
     392                 :     }
     393                 :     else
     394                 :     {
     395               1 :         coordinatePrecision = 10;
     396                 :     }
     397                 :     
     398               3 :     pszCoordinateSeparator = (char*)CSLFetchNameValue( papszOptions, "COORDINATE_SEPARATOR");
     399               3 :     if (pszCoordinateSeparator == NULL)
     400               3 :         pszCoordinateSeparator = CPLStrdup(",");
     401                 :     else
     402               0 :         pszCoordinateSeparator = CPLStrdup(pszCoordinateSeparator);
     403                 : 
     404               3 :     return TRUE;
     405                 : }

Generated by: LCOV version 1.7