Exemple #1
0
void OGRBNALayer::FastParseUntil ( int interestFID)
{
    if (partialIndexTable)
    {
        ResetReading();

        BNARecord* record;

        if (nFeatures > 0)
        {
            VSIFSeekL( fpBNA, offsetAndLineFeaturesTable[nFeatures-1].offset, SEEK_SET );
            curLine = offsetAndLineFeaturesTable[nFeatures-1].line;

            /* Just skip the last read one */
            int ok = FALSE;
            record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, BNA_READ_NONE);
            BNA_FreeRecord(record);
        }

        while(1)
        {
            int ok = FALSE;
            int offset = (int) VSIFTellL(fpBNA);
            int line = curLine;
            record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, BNA_READ_NONE);
            if (ok == FALSE)
            {
                failed = TRUE;
                return;
            }
            if (record == NULL)
            {
                /* end of file */
                eof = TRUE;

                /* and we have finally build the whole index table */
                partialIndexTable = FALSE;
                return;
            }

            if (record->featureType == bnaFeatureType)
            {
                nFeatures++;
                offsetAndLineFeaturesTable =
                    (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable, nFeatures * sizeof(OffsetAndLine));
                offsetAndLineFeaturesTable[nFeatures-1].offset = offset;
                offsetAndLineFeaturesTable[nFeatures-1].line = line;

                BNA_FreeRecord(record);

                if (nFeatures - 1 == interestFID)
                  return;
            }
            else
            {
                BNA_FreeRecord(record);
            }
        }
    }
}
Exemple #2
0
OGRFeature *  OGRBNALayer::GetFeature( long nFID )
{
    OGRFeature  *poFeature;
    BNARecord* record;
    int ok;
    
    if (nFID < 0)
        return NULL;

    FastParseUntil(nFID);

    if (nFID >= nFeatures)
        return NULL;

    VSIFSeekL( fpBNA, offsetAndLineFeaturesTable[nFID].offset, SEEK_SET );
    curLine = offsetAndLineFeaturesTable[nFID].line;
    record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType);

    poFeature = BuildFeatureFromBNARecord(record, nFID);

    BNA_FreeRecord(record);

    return poFeature;
}
Exemple #3
0
OGRFeature *  OGRBNALayer::GetFeature( GIntBig nFID )
{
    if (nFID < 0 || !CPL_INT64_FITS_ON_INT32(nFID))
        return NULL;

    FastParseUntil( static_cast<int>( nFID ) );

    if (nFID >= nFeatures)
        return NULL;

    int ok;
    if( VSIFSeekL( fpBNA, offsetAndLineFeaturesTable[nFID].offset, SEEK_SET ) < 0 )
        return NULL;

    curLine = offsetAndLineFeaturesTable[nFID].line;
    BNARecord* record
        = BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType);

    OGRFeature *poFeature = BuildFeatureFromBNARecord(record, (int)nFID);

    BNA_FreeRecord(record);

    return poFeature;
}
Exemple #4
0
OGRFeature *OGRBNALayer::GetNextFeature()
{
    OGRFeature  *poFeature;
    BNARecord* record;
    int offset, line;

    if (failed || eof) return NULL;

    while(1)
    {
        int ok = FALSE;
        offset = (int) VSIFTellL(fpBNA);
        line = curLine;
        if (nNextFID < nFeatures)
        {
            VSIFSeekL( fpBNA, offsetAndLineFeaturesTable[nNextFID].offset, SEEK_SET );
            curLine = offsetAndLineFeaturesTable[nNextFID].line;
        }
        record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType);
        if (ok == FALSE)
        {
            BNA_FreeRecord(record);
            failed = TRUE;
            return NULL;
        }
        if (record == NULL)
        {
            /* end of file */
            eof = TRUE;

            /* and we have finally build the whole index table */
            partialIndexTable = FALSE;
            return NULL;
        }

        if (record->featureType == bnaFeatureType)
        {
            if (nNextFID >= nFeatures)
            {
                nFeatures++;
                offsetAndLineFeaturesTable =
                    (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable, nFeatures * sizeof(OffsetAndLine));
                offsetAndLineFeaturesTable[nFeatures-1].offset = offset;
                offsetAndLineFeaturesTable[nFeatures-1].line = line;
            }

            poFeature = BuildFeatureFromBNARecord(record, nNextFID++);

            BNA_FreeRecord(record);

            if(   (m_poFilterGeom == NULL
                || FilterGeometry( poFeature->GetGeometryRef() ) )
            && (m_poAttrQuery == NULL
                || m_poAttrQuery->Evaluate( poFeature )) )
            {
                 return poFeature;
            }

            delete poFeature;
        }
        else
        {
            BNA_FreeRecord(record);
        }
    }
}
int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)

{
    int ok = FALSE;

    pszName = CPLStrdup( pszFilename );
    bUpdate = bUpdateIn;

/* -------------------------------------------------------------------- */
/*      Determine what sort of object this is.                          */
/* -------------------------------------------------------------------- */
    VSIStatBufL sStatBuf;

    if( VSIStatL( pszFilename, &sStatBuf ) != 0 )
        return FALSE;
    
// -------------------------------------------------------------------- 
//      Does this appear to be a .bna file?
// --------------------------------------------------------------------
    if( !(EQUAL( CPLGetExtension(pszFilename), "bna" )
           || ((EQUALN( pszFilename, "/vsigzip/", 9) || EQUALN( pszFilename, "/vsizip/", 8)) &&
               (strstr( pszFilename, ".bna") || strstr( pszFilename, ".BNA")))) )
        return FALSE;
    
    VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
    if (fp)
    {
        BNARecord* record;
        int curLine = 0;
        const char* layerRadixName[] = { "points", "polygons", "lines", "ellipses"};
        OGRwkbGeometryType wkbGeomTypes[] = { wkbPoint, wkbMultiPolygon, wkbLineString, wkbPolygon };
        int i;
#if defined(BNA_FAST_DS_OPEN)
        record = BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
        BNA_FreeRecord(record);

        if (ok)
        {
            nLayers = 4;

            papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*));
            for(i=0;i<4;i++)
                papoLayers[i] = new OGRBNALayer( pszFilename,
                                                 layerRadixName[i],
                                                 (BNAFeatureType)i, wkbGeomTypes[i], FALSE, this );
        }
#else
        int nFeatures[4] = { 0, 0, 0, 0 };
        OffsetAndLine* offsetAndLineFeaturesTable[4] = { NULL, NULL, NULL, NULL };
        int nIDs[4] = {0, 0, 0, 0};
        int partialIndexTable = TRUE;

        while(1)
        {
            int offset = VSIFTellL(fp);
            int line = curLine;
            record =  BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
            if (ok == FALSE)
            {
                BNA_FreeRecord(record);
                if (line != 0)
                    ok = TRUE;
                break;
            }
            if (record == NULL)
            {
                /* end of file */
                ok = TRUE;

                /* and we have finally build the whole index table */
                partialIndexTable = FALSE;
                break;
            }

            if (record->nIDs > nIDs[record->featureType])
                nIDs[record->featureType] = record->nIDs;

            nFeatures[record->featureType]++;
            offsetAndLineFeaturesTable[record->featureType] =
                (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable[record->featureType],
                                           nFeatures[record->featureType] * sizeof(OffsetAndLine));
            offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].offset = offset;
            offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].line = line;

            BNA_FreeRecord(record);
        }

        nLayers = (nFeatures[0] != 0) + (nFeatures[1] != 0) + (nFeatures[2] != 0) + (nFeatures[3] != 0);
        papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*));
        int iLayer = 0;
        for(i=0;i<4;i++)
        {
            if (nFeatures[i])
            {
                papoLayers[iLayer] = new OGRBNALayer( pszFilename,
                                                      layerRadixName[i],
                                                      (BNAFeatureType)i,
                                                      wkbGeomTypes[i],
                                                      FALSE,
                                                      this,
                                                      nIDs[i]);
                papoLayers[iLayer]->SetFeatureIndexTable(nFeatures[i],
                                                        offsetAndLineFeaturesTable[i],
                                                        partialIndexTable);
                iLayer++;
            }
        }
#endif
        VSIFCloseL(fp);
    }

    return ok;
}
Exemple #6
0
BNARecord* BNA_GetNextRecord(VSILFILE* f,
                             int* ok,
                             int* curLine,
                             int verbose,
                             BNAFeatureType interestFeatureType)
{
    BNARecord* record;
    char c;
    int inQuotes = FALSE;
    int numField = 0;
    char* ptrBeginningOfNumber = NULL;
    int exponentFound = 0;
    int exponentSignFound = 0;
    int dotFound = 0;
    int numChar = 0;
    const char* detailedErrorMsg = NULL;
    BNAFeatureType currentFeatureType = BNA_UNKNOWN;
    int nbExtraId = 0;
    char tmpBuffer[NB_MAX_BNA_IDS][TMP_BUFFER_SIZE+1];
    int  tmpBufferLength[NB_MAX_BNA_IDS] = {0, 0, 0};
    char szLineBuffer[LINE_BUFFER_SIZE + 1];

    record = (BNARecord*)CPLMalloc(sizeof(BNARecord));
    memset(record, 0, sizeof(BNARecord));

    while (TRUE)
    {
      numChar = 0;
      (*curLine)++;

      int retGetLine = BNA_GetLine(szLineBuffer, f);
      if (retGetLine == BNA_LINE_TOO_LONG)
      {
          detailedErrorMsg = LINE_TOO_LONG;
          goto error;
      }
      else if (retGetLine == BNA_LINE_EOF)
      {
          break;
      }

      char* ptrCurLine = szLineBuffer;
      const char* ptrBeginLine = szLineBuffer;

      if (*ptrCurLine == 0)
        continue;

      while(1)
      {
        numChar = ptrCurLine - ptrBeginLine;
        c = *ptrCurLine;
        if (c == 0) c = 10;
        if (inQuotes)
        {
          if (c == 10)
          {
            detailedErrorMsg = STRING_NOT_TERMINATED;
            goto error;
          }
          else if (c == '"' && ptrCurLine[1] == '"')
          {
            if (tmpBufferLength[numField] == TMP_BUFFER_SIZE)
            {
              detailedErrorMsg = TOO_LONG_ID; 
              goto error;
            }
            tmpBuffer[numField][tmpBufferLength[numField]++] = c;

            ptrCurLine++;
          }
          else if (c == '"')
          {
            inQuotes = FALSE;
          }
          else
          {
            if (tmpBufferLength[numField] == TMP_BUFFER_SIZE)
            {
              detailedErrorMsg = TOO_LONG_ID; 
              goto error;
            }
            tmpBuffer[numField][tmpBufferLength[numField]++] = c;
          }
        }
        else if (c == ' ' || c == '\t')
        {
          if (numField > NB_MIN_BNA_IDS + nbExtraId && ptrBeginningOfNumber != NULL)
          {
            do
            {
              ptrCurLine++;
              numChar = ptrCurLine - ptrBeginLine;
              c = *ptrCurLine;
              if (!(c == ' ' || c == '\t'))
                break;
            } while(c);
            if (c == 0) c = 10;

            if (interestFeatureType == BNA_READ_ALL ||
                interestFeatureType == currentFeatureType)
            {
              char* pszComma = strchr(ptrBeginningOfNumber, ',');
              if (pszComma)
                  *pszComma = '\0';
              record->tabCoords[(numField - nbExtraId - NB_MIN_BNA_IDS - 1) / 2]
                               [1 - ((numField - nbExtraId) % 2)] =
                  CPLAtof(ptrBeginningOfNumber);
              if (pszComma)
                  *pszComma = ',';
            }
            if (numField == NB_MIN_BNA_IDS + 1 + nbExtraId + 2 * record->nCoords - 1)
            {
              if (c != 10)
              {
                if (verbose)
                {
                  CPLError(CE_Warning, CPLE_AppDefined, 
                           "At line %d, at char %d, extra data will be ignored!\n",
                           *curLine, numChar+1);
                }
              }
              *ok = 1;
              return record;
            }

            ptrBeginningOfNumber = NULL;
            exponentFound = 0;
            exponentSignFound = 0;
            dotFound = 0;
            numField++;

            if (c == 10)
              break;

            if (c != ',')
            {
              /* don't increment ptrCurLine */
              continue;
            }
          }
          else
          {
            /* ignore */
          }
        }
        else if (c == 10 || c == ',')
        {
          /* Eat a comma placed at end of line */
          if (c == ',')
          {
              const char* ptr = ptrCurLine+1;
              while(*ptr)
              {
                  if (*ptr != ' ' && *ptr != '\t')
                      break;
                  ptr++;
              }
              if (*ptr == 0)
              {
                  c = 10;
              }
          }

          if (numField == 0)
          {
            /* Maybe not so mandatory.. Atlas MapMaker(TM) exports BNA files with empty primaryID */
            /*
            if (record->primaryID == NULL || *(record->primaryID) == 0)
            {
              detailedErrorMsg = PRIMARY_ID_MANDATORY;
              goto error;
            }
            */
          }
          else if (numField == NB_MIN_BNA_IDS + nbExtraId)
          {
            int nCoords;
            if (ptrBeginningOfNumber == NULL)
            {
              detailedErrorMsg = INTEGER_NUMBER_EXPECTED;
              goto error;
            }
            nCoords = atoi(ptrBeginningOfNumber);
            if (nCoords == 0 || nCoords == -1)
            {
              detailedErrorMsg = INVALID_GEOMETRY_TYPE;
              goto error;
            }
            else if (nCoords == 1)
            {
              currentFeatureType = record->featureType = BNA_POINT;
              record->nCoords = 1;
            }
            else if (nCoords == 2)
            {
              currentFeatureType = record->featureType = BNA_ELLIPSE;
              record->nCoords = 2;
            }
            else if (nCoords > 0)
            {
              currentFeatureType = record->featureType = BNA_POLYGON;
              record->nCoords = nCoords;
            }
            else
            {
              currentFeatureType = record->featureType = BNA_POLYLINE;
              record->nCoords = -nCoords;
            }

            record->nIDs = NB_MIN_BNA_IDS + nbExtraId;

            if (interestFeatureType == BNA_READ_ALL ||
                interestFeatureType == currentFeatureType)
            {
              int i;
              for(i=0;i<NB_MAX_BNA_IDS;i++)
              {
                if (tmpBufferLength[i] && tmpBuffer[i][0])
                {
                  record->ids[i] = (char*)CPLMalloc(tmpBufferLength[i] + 1);
                  tmpBuffer[i][tmpBufferLength[i]] = 0;
                  memcpy(record->ids[i], tmpBuffer[i], tmpBufferLength[i] + 1);
                }
              }

              record->tabCoords =
                  (double(*)[2])VSIMalloc(record->nCoords * 2 * sizeof(double));
              if (record->tabCoords == NULL)
              {
                  detailedErrorMsg = NOT_ENOUGH_MEMORY;
                  goto error;
              }
            }
          }
          else if (numField > NB_MIN_BNA_IDS + nbExtraId)
          {
            if (ptrBeginningOfNumber == NULL)
            {
              detailedErrorMsg = FLOAT_NUMBER_EXPECTED;
              goto error;
            }
            if (interestFeatureType == BNA_READ_ALL ||
                interestFeatureType == currentFeatureType)
            {
              char* pszComma = strchr(ptrBeginningOfNumber, ',');
              if (pszComma)
                  *pszComma = '\0';
              record->tabCoords[(numField - nbExtraId - NB_MIN_BNA_IDS - 1) / 2]
                               [1 - ((numField - nbExtraId) % 2)] =
                  CPLAtof(ptrBeginningOfNumber);
              if (pszComma)
                  *pszComma = ',';
            }
            if (numField == NB_MIN_BNA_IDS + 1 + nbExtraId + 2 * record->nCoords - 1)
            {
              if (c != 10)
              {
                if (verbose)
                {
                  CPLError(CE_Warning, CPLE_AppDefined, 
                           "At line %d, at char %d, extra data will be ignored!\n",
                           *curLine, numChar+1);
                }
              }
              *ok = 1;
              return record;
            }
          }

          ptrBeginningOfNumber = NULL;
          exponentFound = 0;
          exponentSignFound = 0;
          dotFound = 0;
          numField++;

          if (c == 10)
            break;
        }
        else if (c == '"')
        {
          if (numField < NB_MIN_BNA_IDS)
          {
            inQuotes = TRUE;
          }
          else if (numField >= NB_MIN_BNA_IDS && currentFeatureType == BNA_UNKNOWN)
          {
            if (ptrBeginningOfNumber == NULL)
            {
              if (nbExtraId == NB_MAX_BNA_IDS - NB_MIN_BNA_IDS)
              {
                detailedErrorMsg = MAX_BNA_IDS_REACHED;
                goto error;
              }
              nbExtraId ++;
              inQuotes = TRUE;
            }
            else
            {
              detailedErrorMsg = BAD_INTEGER_NUMBER_FORMAT;
              goto error;
            }
          }
          else
          {
            detailedErrorMsg = NUMBER_EXPECTED;
            goto error;
          }
        }
        else
        {
          if (numField < NB_MIN_BNA_IDS || (numField == NB_MIN_BNA_IDS + nbExtraId - 1))
          {
            detailedErrorMsg = STRING_EXPECTED;
            goto error;
          }
          else if (numField == NB_MIN_BNA_IDS + nbExtraId)
          {
            if (c >= '0' && c <= '9')
            {
            }
            else if (c == '+' || c == '-')
            {
              if (ptrBeginningOfNumber != NULL)
              {
                detailedErrorMsg = BAD_INTEGER_NUMBER_FORMAT;
                goto error;
              }
            }
            else
            {
              detailedErrorMsg = BAD_INTEGER_NUMBER_FORMAT;
              goto error;
            }
            if (ptrBeginningOfNumber == NULL)
              ptrBeginningOfNumber = ptrCurLine;
          }
          else
          {
            if (c >= '0' && c <= '9')
            {
            }
            else if (c == '.')
            {
              if (dotFound || exponentFound)
              {
                detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
                goto error;
              }
              dotFound = 1;
            }
            else if (c == '+' || c == '-')
            {
              if (ptrBeginningOfNumber == NULL)
              {
              }
              else if (exponentFound)
              {
                if (exponentSignFound == 0 && ptrCurLine > ptrBeginLine &&
                    (ptrCurLine[-1] == 'e' || ptrCurLine[-1] == 'E' ||
                     ptrCurLine[-1] == 'd' || ptrCurLine[-1] == 'D'))
                {
                  exponentSignFound = 1;
                }
                else
                {
                  detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
                  goto error;
                }
              }
              else
              {
                detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
                goto error;
              }
            }
            else if (c == 'e' || c == 'E' || c == 'd' || c == 'D')
            {
              if (ptrBeginningOfNumber == NULL ||
                  !(ptrCurLine[-1] >= '0' && ptrCurLine[-1] <= '9') ||
                  exponentFound == 1)
              {
                detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
                goto error;
              }
              exponentFound = 1;
            }
            else
            {
              detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
              goto error;
            }
            if (ptrBeginningOfNumber == NULL)
              ptrBeginningOfNumber = ptrCurLine;
          }
        }
        ptrCurLine++;
      }
    }

    if (numField == 0)
    {
        /* End of file */
        *ok = 1;
        BNA_FreeRecord(record);
        return NULL;
    }
    else
    {
        detailedErrorMsg = MISSING_FIELDS;
        goto error;
    }
error:
    if (verbose)
    {
      if (detailedErrorMsg)
      {
        CPLError(CE_Failure, CPLE_AppDefined, 
                "Parsing failed at line %d, at char %d : %s!\n",
                 *curLine, numChar+1, detailedErrorMsg);
      }
      else
      {
        CPLError(CE_Failure, CPLE_AppDefined, 
                "Parsing failed at line %d, at char %d!\n",
                 *curLine, numChar+1);
      }
    }
    BNA_FreeRecord(record);
    return NULL;
}
Exemple #7
0
int OGRBNADataSource::Open( const char * pszFilename )

{
    int ok = FALSE;

    pszName = CPLStrdup( pszFilename );

    VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
    if (fp)
    {
        int curLine = 0;
        static const char* const layerRadixName[]
            = { "points", "polygons", "lines", "ellipses"};
        static const OGRwkbGeometryType wkbGeomTypes[]
            = { wkbPoint, wkbMultiPolygon, wkbLineString, wkbPolygon };

#if defined(BNA_FAST_DS_OPEN)
        BNARecord* record = BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
        BNA_FreeRecord(record);

        if (ok)
        {
            nLayers = 4;

            papoLayers = static_cast<OGRBNALayer **>(
                CPLMalloc(nLayers * sizeof(OGRBNALayer*)));
            for( i = 0; i < 4; i++ )
                papoLayers[i] = new OGRBNALayer(
                    pszFilename,
                    layerRadixName[i],
                    static_cast<BNAFeatureType>( i ),
                    wkbGeomTypes[i], FALSE, this );
        }
#else
        int nFeatures[4] = { 0, 0, 0, 0 };
        OffsetAndLine* offsetAndLineFeaturesTable[4] = { nullptr, nullptr, nullptr, nullptr };
        int nIDs[4] = {0, 0, 0, 0};
        bool partialIndexTable = true;

        BNARecord* record = nullptr;
        while(1)
        {
            int offset = static_cast<int>( VSIFTellL(fp) );
            int line = curLine;
            record =  BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
            if (ok == FALSE)
            {
                BNA_FreeRecord(record);
                if (line != 0)
                    ok = TRUE;
                break;
            }
            if (record == nullptr)
            {
                /* end of file */
                ok = TRUE;

                /* and we have finally build the whole index table */
                partialIndexTable = false;
                break;
            }

            if (record->nIDs > nIDs[record->featureType])
                nIDs[record->featureType] = record->nIDs;

            nFeatures[record->featureType]++;
            offsetAndLineFeaturesTable[record->featureType] =
              static_cast<OffsetAndLine *>( CPLRealloc(
                  offsetAndLineFeaturesTable[record->featureType],
                  nFeatures[record->featureType] * sizeof(OffsetAndLine) ) );
            offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].offset = offset;
            offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].line = line;

            BNA_FreeRecord(record);
        }

        nLayers = (nFeatures[0] != 0) + (nFeatures[1] != 0) + (nFeatures[2] != 0) + (nFeatures[3] != 0);
        papoLayers = static_cast<OGRBNALayer **>(
            CPLMalloc(nLayers * sizeof(OGRBNALayer*)) );
        int iLayer = 0;
        for( int i = 0; i < 4; i++ )
        {
            if (nFeatures[i])
            {
                papoLayers[iLayer] = new OGRBNALayer( pszFilename,
                                                      layerRadixName[i],
                                                      (BNAFeatureType)i,
                                                      wkbGeomTypes[i],
                                                      FALSE,
                                                      this,
                                                      nIDs[i]);
                papoLayers[iLayer]->SetFeatureIndexTable(nFeatures[i],
                                                        offsetAndLineFeaturesTable[i],
                                                        partialIndexTable);
                iLayer++;
            }
        }
#endif
        VSIFCloseL(fp);
    }

    return ok;
}