LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/bna - ogrbnaparser.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 253 159 62.8 %
Date: 2010-01-09 Functions: 5 3 60.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrbnadataparser.c
       3                 :  *
       4                 :  * Project:  BNA Parser
       5                 :  * Purpose:  Parse a BNA record
       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 "ogrbnaparser.h"
      31                 : 
      32                 : #include "cpl_conv.h"
      33                 : #include "cpl_string.h"
      34                 : 
      35             442 : void BNA_FreeRecord(BNARecord* record)
      36                 : {
      37             442 :   if (record)
      38                 :   {
      39                 :     int i;
      40            2210 :     for(i=0;i<NB_MAX_BNA_IDS;i++)
      41                 :     {
      42            1768 :         if (record->ids[i]) VSIFree(record->ids[i]);
      43            1768 :         record->ids[i] = NULL;
      44                 :     }
      45             442 :     CPLFree(record->tabCoords);
      46             442 :     record->tabCoords = NULL;
      47             442 :     CPLFree(record);
      48                 :   }
      49             442 : }
      50                 : 
      51               0 : const char* BNA_FeatureTypeToStr(BNAFeatureType featureType)
      52                 : {
      53               0 :   switch (featureType)
      54                 :   {
      55                 :     case BNA_POINT:
      56               0 :       return "point";
      57                 :     case BNA_POLYGON:
      58               0 :       return "polygon";
      59                 :     case BNA_POLYLINE:
      60               0 :       return "polyline";
      61                 :     case BNA_ELLIPSE:
      62               0 :       return "ellipse";
      63                 :     default:
      64               0 :       return "unknown";
      65                 :   }
      66                 : }
      67                 : 
      68               0 : void BNA_Display(BNARecord* record)
      69                 : {
      70                 :   int i;
      71                 :   fprintf(stderr, "\"%s\", \"%s\", \"%s\", %s\n",
      72               0 :           record->ids[0] ? record->ids[0] : "",
      73               0 :           record->ids[1] ? record->ids[1] : "",
      74               0 :           record->ids[2] ? record->ids[2] : "",
      75               0 :           BNA_FeatureTypeToStr(record->featureType));
      76               0 :   for(i=0;i<record->nCoords;i++)
      77               0 :     fprintf(stderr, "%f, %f\n", record->tabCoords[i][0], record->tabCoords[i][1]);
      78               0 : }
      79                 : 
      80                 : /*
      81                 : For a description of the format, see http://www.softwright.com/faq/support/boundary_file_bna_format.html
      82                 : and http://64.145.236.125/forum/topic.asp?topic_id=1930&forum_id=1&Topic_Title=how+to+edit+*.bna+files%3F&forum_title=Surfer+Support&M=False
      83                 : */
      84                 : 
      85                 : /* The following lines are a valid BNA file (for this parser) :
      86                 : "PID1","SID1",1
      87                 : -0,0
      88                 : "PID2","SID2",-2,   -1e-5,-1e2   ,-2,-2
      89                 : "PID3""a","SID3",4
      90                 : 5,5
      91                 : 6,5
      92                 : 6,6
      93                 : 5,5
      94                 : "PID4","SID4",2
      95                 : 10,10
      96                 : 5,4
      97                 : 
      98                 : "PID4","SID4",2
      99                 : 
     100                 : 10,10
     101                 : 5,4
     102                 : */
     103                 : 
     104                 : /* The following lines are a valid BNA file (for this parser) :
     105                 :   (small extract from ftp://ftp.ciesin.org/pub/census/usa/tiger/ct/bnablk/b09001.zip)
     106                 : "090010000.00099A","099A","090010000.00099A","blk",21
     107                 : -73.049337, 41.125000 -73.093761, 41.157780 -73.107900, 41.168300
     108                 : -73.106878, 41.166459 -73.095800, 41.146500 -73.114553, 41.146331
     109                 : -73.138922, 41.147993 -73.166200, 41.154200 -73.198497, 41.085988
     110                 : -73.232241, 41.029986 -73.229548, 41.030507 -73.183922, 41.041955
     111                 : -73.178678, 41.043239 -73.177951, 41.043417 -73.147888, 41.050781
     112                 : -73.118658, 41.057942 -73.052399, 41.074174 -73.024976, 41.080892
     113                 : -73.000000, 41.087010 -73.035597, 41.114420 -73.049337, 41.125000
     114                 : */
     115                 : 
     116                 : /* We are (and must be) a bit tolerant : BNA files format has several variations */
     117                 : /* and most don't follow strictly the 'specification' */
     118                 : /* Extra spaces, tabulations or line feed are accepted and ignored */
     119                 : /* We allow one line format and several line format in the same file */
     120                 : /* We allow from NB_MIN_BNA_IDS to NB_MAX_BNA_IDS ids */
     121                 : /* We allow that couples of coordinates on the same line may be separated only by spaces */
     122                 : /* (instead of being separated by a comma) */
     123                 : 
     124                 : #define STRING_NOT_TERMINATED      "string not terminated when end of line occured"
     125                 : #define MISSING_FIELDS             "missing fields"
     126                 : #define BAD_INTEGER_NUMBER_FORMAT  "bad integer number format"
     127                 : #define BAD_FLOAT_NUMBER_FORMAT    "bad float number format"
     128                 : #define PRIMARY_ID_MANDATORY       "primary ID can't be empty or missing"
     129                 : #define STRING_EXPECTED            "string expected"
     130                 : #define NUMBER_EXPECTED            "number expected"
     131                 : #define INTEGER_NUMBER_EXPECTED    "integer number expected"
     132                 : #define FLOAT_NUMBER_EXPECTED      "float number expected"
     133                 : #define INVALID_GEOMETRY_TYPE      "invalid geometry type"
     134                 : #define TOO_LONG_ID                "too long id (> 256 characters)"
     135                 : #define MAX_BNA_IDS_REACHED        "maximum number of IDs reached"
     136                 : #define NOT_ENOUGH_MEMORY          "not enough memory for request number of coordinates"
     137                 : #define LINE_TOO_LONG              "line too long"
     138                 : 
     139                 : #define TMP_BUFFER_SIZE             256
     140                 : #define LINE_BUFFER_SIZE            1024
     141                 : 
     142                 : enum
     143                 : {
     144                 :     BNA_LINE_OK,
     145                 :     BNA_LINE_EOF,
     146                 :     BNA_LINE_TOO_LONG
     147                 : };
     148                 : 
     149            3049 : static int BNA_GetLine(char szLineBuffer[LINE_BUFFER_SIZE+1], FILE* f)
     150                 : {
     151            3049 :     char* ptrCurLine = szLineBuffer;
     152            3049 :     int nRead = VSIFRead(szLineBuffer, 1, LINE_BUFFER_SIZE, f);
     153            3049 :     szLineBuffer[nRead] = 0;
     154            3049 :     if (nRead == 0)
     155                 :     {
     156                 :         /* EOF */
     157              73 :         return BNA_LINE_EOF;
     158                 :     }
     159                 : 
     160            2976 :     int bFoundEOL = FALSE;
     161           80639 :     while (*ptrCurLine)
     162                 :     {
     163           77663 :         if (*ptrCurLine == 0x0d || *ptrCurLine == 0x0a)
     164                 :         {
     165            2976 :             bFoundEOL = TRUE;
     166            2976 :             break;
     167                 :         }
     168           74687 :         ptrCurLine ++;
     169                 :     }
     170            2976 :     if (!bFoundEOL)
     171                 :     {
     172               0 :         if (nRead < LINE_BUFFER_SIZE)
     173               0 :             return BNA_LINE_OK;
     174                 :         else
     175               0 :             return BNA_LINE_TOO_LONG;
     176                 :     }
     177                 : 
     178            2976 :     if (*ptrCurLine == 0x0d)
     179                 :     {
     180            2224 :         if (ptrCurLine == szLineBuffer + LINE_BUFFER_SIZE - 1)
     181                 :         {
     182                 :             char c;
     183               0 :             nRead = VSIFRead(&c, 1, 1, f);
     184               0 :             if (nRead == 1)
     185                 :             {
     186               0 :                 if (c == 0x0a)
     187                 :                 {
     188                 :                     /* Do nothing */
     189                 :                 }
     190                 :                 else
     191                 :                 {
     192               0 :                     VSIFSeek(f, -1, SEEK_CUR);
     193                 :                 }
     194                 :             }
     195                 :         }
     196            2224 :         else if (ptrCurLine[1] == 0x0a)
     197                 :         {
     198            2224 :             VSIFSeek(f, ptrCurLine + 2 - (szLineBuffer + nRead), SEEK_CUR);
     199                 :         }
     200                 :         else
     201                 :         {
     202               0 :             VSIFSeek(f, ptrCurLine + 1 - (szLineBuffer + nRead), SEEK_CUR);
     203                 :         }
     204                 :     }
     205                 :     else /* *ptrCurLine == 0x0a */
     206                 :     {
     207             752 :         VSIFSeek(f, ptrCurLine + 1 - (szLineBuffer + nRead), SEEK_CUR);
     208                 :     }
     209            2976 :     *ptrCurLine = 0;
     210                 : 
     211            2976 :     return BNA_LINE_OK;
     212                 : }
     213                 : 
     214                 : 
     215             442 : BNARecord* BNA_GetNextRecord(FILE* f,
     216                 :                              int* ok,
     217                 :                              int* curLine,
     218                 :                              int verbose,
     219                 :                              BNAFeatureType interestFeatureType)
     220                 : {
     221                 :     BNARecord* record;
     222                 :     char c;
     223             442 :     int inQuotes = FALSE;
     224             442 :     int numField = 0;
     225             442 :     const char* ptrBeginningOfNumber = NULL;
     226             442 :     int exponentFound = 0;
     227             442 :     int exponentSignFound = 0;
     228             442 :     int dotFound = 0;
     229             442 :     int numChar = 0;
     230             442 :     const char* detailedErrorMsg = NULL;
     231             442 :     BNAFeatureType currentFeatureType = (BNAFeatureType) -1;
     232             442 :     int nbExtraId = 0;
     233                 :     char tmpBuffer[NB_MAX_BNA_IDS][TMP_BUFFER_SIZE+1];
     234             442 :     int  tmpBufferLength[NB_MAX_BNA_IDS] = {0, 0, 0};
     235                 :     char szLineBuffer[LINE_BUFFER_SIZE + 1];
     236                 : 
     237             442 :     record = (BNARecord*)CPLMalloc(sizeof(BNARecord));
     238             442 :     memset(record, 0, sizeof(BNARecord));
     239                 : 
     240            2607 :     while (TRUE)
     241                 :     {
     242            3049 :       numChar = 0;
     243            3049 :       (*curLine)++;
     244                 : 
     245            3049 :       int retGetLine = BNA_GetLine(szLineBuffer, f);
     246            3049 :       if (retGetLine == BNA_LINE_TOO_LONG)
     247                 :       {
     248               0 :           detailedErrorMsg = LINE_TOO_LONG;
     249               0 :           goto error;
     250                 :       }
     251            3049 :       else if (retGetLine == BNA_LINE_EOF)
     252                 :       {
     253                 :           break;
     254                 :       }
     255                 : 
     256            2976 :       const char* ptrCurLine = szLineBuffer;
     257            2976 :       const char* ptrBeginLine = szLineBuffer;
     258                 : 
     259            2976 :       if (*ptrCurLine == 0)
     260               0 :         continue;
     261                 : 
     262           74687 :       while(1)
     263                 :       {
     264           77663 :         numChar = ptrCurLine - ptrBeginLine;
     265           77663 :         c = *ptrCurLine;
     266           77663 :         if (c == 0) c = 10;
     267           77663 :         if (inQuotes)
     268                 :         {
     269            3700 :           if (c == 10)
     270                 :           {
     271               0 :             detailedErrorMsg = STRING_NOT_TERMINATED;
     272               0 :             goto error;
     273                 :           }
     274            3700 :           else if (c == '"' && ptrCurLine[1] == '"')
     275                 :           {
     276               0 :             if (tmpBufferLength[numField] == TMP_BUFFER_SIZE)
     277                 :             {
     278               0 :               detailedErrorMsg = TOO_LONG_ID; 
     279               0 :               goto error;
     280                 :             }
     281               0 :             tmpBuffer[numField][tmpBufferLength[numField]++] = c;
     282                 : 
     283               0 :             ptrCurLine++;
     284                 :           }
     285            3700 :           else if (c == '"')
     286                 :           {
     287             740 :             inQuotes = FALSE;
     288                 :           }
     289                 :           else
     290                 :           {
     291            2960 :             if (tmpBufferLength[numField] == TMP_BUFFER_SIZE)
     292                 :             {
     293               0 :               detailedErrorMsg = TOO_LONG_ID; 
     294               0 :               goto error;
     295                 :             }
     296            2960 :             tmpBuffer[numField][tmpBufferLength[numField]++] = c;
     297                 :           }
     298                 :         }
     299           73963 :         else if (c == ' ' || c == '\t')
     300                 :         {
     301            1182 :           if (numField > NB_MIN_BNA_IDS + nbExtraId && ptrBeginningOfNumber != NULL)
     302                 :           {
     303               0 :             do
     304                 :             {
     305            1182 :               ptrCurLine++;
     306            1182 :               numChar = ptrCurLine - ptrBeginLine;
     307            1182 :               c = *ptrCurLine;
     308            1182 :               if (!(c == ' ' || c == '\t'))
     309            1182 :                 break;
     310                 :             } while(c);
     311            1182 :             if (c == 0) c = 10;
     312                 : 
     313            1182 :             if (interestFeatureType == BNA_READ_ALL ||
     314                 :                 interestFeatureType == currentFeatureType)
     315                 :             {
     316             340 :               record->tabCoords[(numField - nbExtraId - NB_MIN_BNA_IDS - 1) / 2]
     317             340 :                                [1 - ((numField - nbExtraId) % 2)] =
     318             340 :                   CPLAtof(ptrBeginningOfNumber);
     319                 :             }
     320            1182 :             if (numField == NB_MIN_BNA_IDS + 1 + nbExtraId + 2 * record->nCoords - 1)
     321                 :             {
     322               0 :               if (c != 10)
     323                 :               {
     324               0 :                 if (verbose)
     325                 :                 {
     326                 :                   CPLError(CE_Warning, CPLE_AppDefined, 
     327                 :                            "At line %d, at char %d, extra data will be ignored!\n",
     328               0 :                            *curLine, numChar+1);
     329                 :                 }
     330                 :               }
     331               0 :               *ok = 1;
     332               0 :               return record;
     333                 :             }
     334                 : 
     335            1182 :             ptrBeginningOfNumber = NULL;
     336            1182 :             exponentFound = 0;
     337            1182 :             exponentSignFound = 0;
     338            1182 :             dotFound = 0;
     339            1182 :             numField++;
     340                 : 
     341            1182 :             if (c == 10)
     342               0 :               break;
     343                 : 
     344            1182 :             if (c != ',')
     345                 :             {
     346                 :               /* don't increment ptrCurLine */
     347            1182 :               continue;
     348                 :             }
     349                 :           }
     350                 :           else
     351                 :           {
     352                 :             /* ignore */
     353                 :           }
     354                 :         }
     355           77538 :         else if (c == 10 || c == ',')
     356                 :         {
     357                 :           /* Eat a comma placed at end of line */
     358            7733 :           if (c == ',')
     359                 :           {
     360            4757 :               const char* ptr = ptrCurLine+1;
     361            9514 :               while(*ptr)
     362                 :               {
     363            4757 :                   if (*ptr != ' ' && *ptr != '\t')
     364            4757 :                       break;
     365               0 :                   ptr++;
     366                 :               }
     367            4757 :               if (*ptr == 0)
     368                 :               {
     369               0 :                   c = 10;
     370                 :               }
     371                 :           }
     372                 : 
     373            7733 :           if (numField == 0)
     374                 :           {
     375                 :             /* Maybe not so mandatory.. Atlas MapMaker(TM) exports BNA files with empty primaryID */
     376                 :             /*
     377                 :             if (record->primaryID == NULL || *(record->primaryID) == 0)
     378                 :             {
     379                 :               detailedErrorMsg = PRIMARY_ID_MANDATORY;
     380                 :               goto error;
     381                 :             }
     382                 :             */
     383                 :           }
     384            7364 :           else if (numField == NB_MIN_BNA_IDS + nbExtraId)
     385                 :           {
     386                 :             int nCoords;
     387             369 :             if (ptrBeginningOfNumber == NULL)
     388                 :             {
     389               0 :               detailedErrorMsg = INTEGER_NUMBER_EXPECTED;
     390               0 :               goto error;
     391                 :             }
     392             369 :             nCoords = atoi(ptrBeginningOfNumber);
     393             369 :             if (nCoords == 0 || nCoords == -1)
     394                 :             {
     395               0 :               detailedErrorMsg = INVALID_GEOMETRY_TYPE;
     396               0 :               goto error;
     397                 :             }
     398             369 :             else if (nCoords == 1)
     399                 :             {
     400              72 :               currentFeatureType = record->featureType = BNA_POINT;
     401              72 :               record->nCoords = 1;
     402                 :             }
     403             297 :             else if (nCoords == 2)
     404                 :             {
     405              62 :               currentFeatureType = record->featureType = BNA_ELLIPSE;
     406              62 :               record->nCoords = 2;
     407                 :             }
     408             235 :             else if (nCoords > 0)
     409                 :             {
     410             205 :               currentFeatureType = record->featureType = BNA_POLYGON;
     411             205 :               record->nCoords = nCoords;
     412                 :             }
     413                 :             else
     414                 :             {
     415              30 :               currentFeatureType = record->featureType = BNA_POLYLINE;
     416              30 :               record->nCoords = -nCoords;
     417                 :             }
     418                 : 
     419             369 :             record->nIDs = NB_MIN_BNA_IDS + nbExtraId;
     420                 : 
     421             369 :             if (interestFeatureType == BNA_READ_ALL ||
     422                 :                 interestFeatureType == currentFeatureType)
     423                 :             {
     424                 :               int i;
     425             695 :               for(i=0;i<NB_MAX_BNA_IDS;i++)
     426                 :               {
     427             556 :                 if (tmpBufferLength[i] && tmpBuffer[i][0])
     428                 :                 {
     429             279 :                   record->ids[i] = (char*)CPLMalloc(tmpBufferLength[i] + 1);
     430             279 :                   tmpBuffer[i][tmpBufferLength[i]] = 0;
     431             279 :                   memcpy(record->ids[i], tmpBuffer[i], tmpBufferLength[i] + 1);
     432                 :                 }
     433                 :               }
     434                 : 
     435                 :               record->tabCoords =
     436             139 :                   (double(*)[2])VSIMalloc(record->nCoords * 2 * sizeof(double));
     437             139 :               if (record->tabCoords == NULL)
     438                 :               {
     439               0 :                   detailedErrorMsg = NOT_ENOUGH_MEMORY;
     440               0 :                   goto error;
     441                 :               }
     442                 :             }
     443                 :           }
     444            6995 :           else if (numField > NB_MIN_BNA_IDS + nbExtraId)
     445                 :           {
     446            6624 :             if (ptrBeginningOfNumber == NULL)
     447                 :             {
     448               0 :               detailedErrorMsg = FLOAT_NUMBER_EXPECTED;
     449               0 :               goto error;
     450                 :             }
     451            6624 :             if (interestFeatureType == BNA_READ_ALL ||
     452                 :                 interestFeatureType == currentFeatureType)
     453                 :             {
     454            2870 :               record->tabCoords[(numField - nbExtraId - NB_MIN_BNA_IDS - 1) / 2]
     455            2870 :                                [1 - ((numField - nbExtraId) % 2)] =
     456            2870 :                   CPLAtof(ptrBeginningOfNumber);
     457                 :             }
     458            6624 :             if (numField == NB_MIN_BNA_IDS + 1 + nbExtraId + 2 * record->nCoords - 1)
     459                 :             {
     460             369 :               if (c != 10)
     461                 :               {
     462               0 :                 if (verbose)
     463                 :                 {
     464                 :                   CPLError(CE_Warning, CPLE_AppDefined, 
     465                 :                            "At line %d, at char %d, extra data will be ignored!\n",
     466               0 :                            *curLine, numChar+1);
     467                 :                 }
     468                 :               }
     469             369 :               *ok = 1;
     470             369 :               return record;
     471                 :             }
     472                 :           }
     473                 : 
     474            7364 :           ptrBeginningOfNumber = NULL;
     475            7364 :           exponentFound = 0;
     476            7364 :           exponentSignFound = 0;
     477            7364 :           dotFound = 0;
     478            7364 :           numField++;
     479                 : 
     480            7364 :           if (c == 10)
     481            2607 :             break;
     482                 :         }
     483           65048 :         else if (c == '"')
     484                 :         {
     485             740 :           if (numField < NB_MIN_BNA_IDS)
     486                 :           {
     487             738 :             inQuotes = TRUE;
     488                 :           }
     489               4 :           else if (numField >= NB_MIN_BNA_IDS && currentFeatureType == -1)
     490                 :           {
     491               2 :             if (ptrBeginningOfNumber == NULL)
     492                 :             {
     493               2 :               if (nbExtraId == NB_MAX_BNA_IDS - NB_MIN_BNA_IDS)
     494                 :               {
     495               0 :                 detailedErrorMsg = MAX_BNA_IDS_REACHED;
     496               0 :                 goto error;
     497                 :               }
     498               2 :               nbExtraId ++;
     499               2 :               inQuotes = TRUE;
     500                 :             }
     501                 :             else
     502                 :             {
     503               0 :               detailedErrorMsg = BAD_INTEGER_NUMBER_FORMAT;
     504               0 :               goto error;
     505                 :             }
     506                 :           }
     507                 :           else
     508                 :           {
     509               0 :             detailedErrorMsg = NUMBER_EXPECTED;
     510               0 :             goto error;
     511                 :           }
     512                 :         }
     513                 :         else
     514                 :         {
     515           64308 :           if (numField < NB_MIN_BNA_IDS || (numField == NB_MIN_BNA_IDS + nbExtraId - 1))
     516                 :           {
     517               0 :             detailedErrorMsg = STRING_EXPECTED;
     518               0 :             goto error;
     519                 :           }
     520           64308 :           else if (numField == NB_MIN_BNA_IDS + nbExtraId)
     521                 :           {
     522             537 :             if (c >= '0' && c <= '9')
     523                 :             {
     524                 :             }
     525              60 :             else if (c == '+' || c == '-')
     526                 :             {
     527              30 :               if (ptrBeginningOfNumber != NULL)
     528                 :               {
     529               0 :                 detailedErrorMsg = BAD_INTEGER_NUMBER_FORMAT;
     530               0 :                 goto error;
     531                 :               }
     532                 :             }
     533                 :             else
     534                 :             {
     535               0 :               detailedErrorMsg = BAD_INTEGER_NUMBER_FORMAT;
     536               0 :               goto error;
     537                 :             }
     538             537 :             if (ptrBeginningOfNumber == NULL)
     539             369 :               ptrBeginningOfNumber = ptrCurLine;
     540                 :           }
     541                 :           else
     542                 :           {
     543           63771 :             if (c >= '0' && c <= '9')
     544                 :             {
     545                 :             }
     546            7198 :             else if (c == '.')
     547                 :             {
     548            7198 :               if (dotFound || exponentFound)
     549                 :               {
     550               0 :                 detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
     551               0 :                 goto error;
     552                 :               }
     553            7198 :               dotFound = 1;
     554                 :             }
     555               0 :             else if (c == '+' || c == '-')
     556                 :             {
     557               0 :               if (ptrBeginningOfNumber == NULL)
     558                 :               {
     559                 :               }
     560               0 :               else if (exponentFound)
     561                 :               {
     562               0 :                 if (exponentSignFound == 0 && ptrCurLine > ptrBeginLine &&
     563               0 :                     (ptrCurLine[-1] == 'e' || ptrCurLine[-1] == 'E' ||
     564               0 :                      ptrCurLine[-1] == 'd' || ptrCurLine[-1] == 'D'))
     565                 :                 {
     566               0 :                   exponentSignFound = 1;
     567                 :                 }
     568                 :                 else
     569                 :                 {
     570               0 :                   detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
     571               0 :                   goto error;
     572                 :                 }
     573                 :               }
     574                 :               else
     575                 :               {
     576               0 :                 detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
     577               0 :                 goto error;
     578                 :               }
     579                 :             }
     580               0 :             else if (c == 'e' || c == 'E' || c == 'd' || c == 'D')
     581                 :             {
     582               0 :               if (ptrBeginningOfNumber == NULL ||
     583               0 :                   !(ptrCurLine[-1] >= '0' && ptrCurLine[-1] <= '9') ||
     584                 :                   exponentFound == 1)
     585                 :               {
     586               0 :                 detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
     587               0 :                 goto error;
     588                 :               }
     589               0 :               exponentFound = 1;
     590                 :             }
     591                 :             else
     592                 :             {
     593               0 :               detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
     594               0 :               goto error;
     595                 :             }
     596           63771 :             if (ptrBeginningOfNumber == NULL)
     597            7806 :               ptrBeginningOfNumber = ptrCurLine;
     598                 :           }
     599                 :         }
     600           73505 :         ptrCurLine++;
     601                 :       }
     602                 :     }
     603                 : 
     604              73 :     if (numField == 0)
     605                 :     {
     606                 :         /* End of file */
     607              73 :         *ok = 1;
     608              73 :         BNA_FreeRecord(record);
     609              73 :         return NULL;
     610                 :     }
     611                 :     else
     612                 :     {
     613               0 :         detailedErrorMsg = MISSING_FIELDS;
     614                 :         goto error;
     615                 :     }
     616                 : error:
     617               0 :     if (verbose)
     618                 :     {
     619               0 :       if (detailedErrorMsg)
     620                 :       {
     621                 :         CPLError(CE_Failure, CPLE_AppDefined, 
     622                 :                 "Parsing failed at line %d, at char %d : %s!\n",
     623               0 :                  *curLine, numChar+1, detailedErrorMsg);
     624                 :       }
     625                 :       else
     626                 :       {
     627                 :         CPLError(CE_Failure, CPLE_AppDefined, 
     628                 :                 "Parsing failed at line %d, at char %d!\n",
     629               0 :                  *curLine, numChar+1);
     630                 :       }
     631                 :     }
     632               0 :     BNA_FreeRecord(record);
     633               0 :     return NULL;
     634                 : }

Generated by: LCOV version 1.7