86 changes: 23 additions & 63 deletions gdal/ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,8 @@
* - Read-only
* - Base tables can only be of type TABFile
* - Feature Ids are build using the id of the base table in the main
* index table and the actual feature id of each object inside the base
* tables. Since we are limited to 32 bits for feature ids, this implies
* a limit on the (number of base tables) * (features/table)
* The current implementation can support up to 2047 (0x7ff) base tables
* and a max of 1048575 (0xfffff) features per base table.
* index table (upper 32 bits) and the actual feature id of each object
* inside the base tables (lower 32 bits).
* - Only relative paths are supported for base tables names.
*
*====================================================================*/
Expand All @@ -108,8 +105,6 @@ TABSeamless::TABSeamless()
m_nCurFeatureId = -1;

m_poIndexTable = NULL;
m_nIndexTableFIDBits = 0;
m_nIndexTableFIDMask = 0;
m_nTableNameField = -1;
m_nCurBaseTableId = -1;
m_poCurBaseTable = NULL;
Expand Down Expand Up @@ -307,13 +302,6 @@ int TABSeamless::OpenForRead(const char *pszFname,
return -1;
}

/* Set the number of bits required to encode features for this index
* table. (Based of the number of features)
*/
int s=0, numFeatures = m_poIndexTable->GetFeatureCount64(FALSE);
do s++, numFeatures>>=1; while(numFeatures);
m_nIndexTableFIDBits= s+1;

/*-----------------------------------------------------------------
* We need to open the first table to get its FeatureDefn
*----------------------------------------------------------------*/
Expand Down Expand Up @@ -347,8 +335,8 @@ int TABSeamless::Close()
delete m_poIndexTable; // Automatically closes.
m_poIndexTable = NULL;

if (m_poFeatureDefnRef && m_poFeatureDefnRef->Dereference() == 0)
delete m_poFeatureDefnRef;
if (m_poFeatureDefnRef )
m_poFeatureDefnRef->Release();
m_poFeatureDefnRef = NULL;

if (m_poCurFeature)
Expand Down Expand Up @@ -388,7 +376,9 @@ int TABSeamless::OpenBaseTable(TABFeature *poIndexFeature,
* Fetch table id. We actually use the index feature's ids as the
* base table ids.
*----------------------------------------------------------------*/
int nTableId = poIndexFeature->GetFID64();
GIntBig nTableId64 = poIndexFeature->GetFID64();
int nTableId = (int)nTableId64;
CPLAssert((GIntBig)nTableId == nTableId64);

if (m_nCurBaseTableId == nTableId && m_poCurBaseTable != NULL)
{
Expand Down Expand Up @@ -433,32 +423,6 @@ int TABSeamless::OpenBaseTable(TABFeature *poIndexFeature,
CPLFree(pszFname);
return -1;
}

/* Set the number of bits required to encode feature id for this base
* table. (Based of the number of features) This will be used for
* encode and extract feature ID.
*/
int s=0, nCurBaseTableFIDBits = 0,
numFeatures = m_poCurBaseTable->GetFeatureCount64(FALSE);
do s++, numFeatures>>=1; while(numFeatures);
nCurBaseTableFIDBits = s;

/* Check if we can encode feature IDs in 32 bits to avoid overflow */
if (nCurBaseTableFIDBits + m_nIndexTableFIDBits > 32)
{
CPLError(CE_Failure, CPLE_NotSupported,
"Open() failed: feature ids cannot be encoded in 32 bits "
"for the index table (%s) and the base table (%s).",
m_pszFname, pszName);
if (bTestOpenNoError)
CPLErrorReset();
delete m_poCurBaseTable;
m_poCurBaseTable = NULL;
CPLFree(pszFname);
return -1;
}

m_nIndexTableFIDMask = (32-m_nIndexTableFIDBits);

// Set the spatial filter to the new table
if( m_poFilterGeom != NULL && m_poCurBaseTable )
Expand Down Expand Up @@ -563,43 +527,32 @@ int TABSeamless::OpenNextBaseTable(GBool bTestOpenNoError /*=FALSE*/)
*
* Combine the table id + feature id into a single feature id that should
* be unique amongst all base tables in this seamless dataset.
*
* We reserve some bits in the feature id for the table id based on the
* number of features in the index table. This reduces the available range
* of feature ids for each base table... for instance, if the index contains
* 65000 entries, then each base table will be limited to 65535 features.
*
* If the number of features in a base table exceeds the number of bits
* available (e.g. 65535 inthe above example) then the feature ids will
* wrap for this table and thus it will be impossible to access some of
* the features unless the caller uses only calls to GetNextFeature() and
* avoids calls to GetFeatureRef().
**********************************************************************/
int TABSeamless::EncodeFeatureId(int nTableId, int nBaseFeatureId)
GIntBig TABSeamless::EncodeFeatureId(int nTableId, int nBaseFeatureId)
{
if (nTableId == -1 || nBaseFeatureId == -1)
return -1;

/* Feature encoding is now based on the numbers of bits on the number
of features in the index table. */

return ((nTableId<<m_nIndexTableFIDMask) + nBaseFeatureId);
return (((GIntBig)nTableId<<32) + nBaseFeatureId);
}

int TABSeamless::ExtractBaseTableId(int nEncodedFeatureId)
int TABSeamless::ExtractBaseTableId(GIntBig nEncodedFeatureId)
{
if (nEncodedFeatureId == -1)
return -1;

return ((nEncodedFeatureId>>m_nIndexTableFIDMask));
return ((int)(nEncodedFeatureId>>32));
}

int TABSeamless::ExtractBaseFeatureId(int nEncodedFeatureId)
int TABSeamless::ExtractBaseFeatureId(GIntBig nEncodedFeatureId)
{
if (nEncodedFeatureId == -1)
return -1;

return (nEncodedFeatureId & ((1<<m_nIndexTableFIDMask)-1));
return ((int)(nEncodedFeatureId & 0xffffffff));
}

/**********************************************************************
Expand All @@ -608,7 +561,7 @@ int TABSeamless::ExtractBaseFeatureId(int nEncodedFeatureId)
* Returns feature id that follows nPrevId, or -1 if it is the
* last feature id. Pass nPrevId=-1 to fetch the first valid feature id.
**********************************************************************/
int TABSeamless::GetNextFeatureId(int nPrevId)
GIntBig TABSeamless::GetNextFeatureId(GIntBig nPrevId)
{
if (m_poIndexTable == NULL)
return -1; // File is not opened yet
Expand Down Expand Up @@ -647,7 +600,7 @@ int TABSeamless::GetNextFeatureId(int nPrevId)
* error happened. In any case, CPLError() will have been called to
* report the reason of the failure.
**********************************************************************/
TABFeature *TABSeamless::GetFeatureRef(int nFeatureId)
TABFeature *TABSeamless::GetFeatureRef(GIntBig nFeatureId)
{
if (m_poIndexTable == NULL)
return NULL; // File is not opened yet
Expand All @@ -665,8 +618,15 @@ TABFeature *TABSeamless::GetFeatureRef(int nFeatureId)
{
if (m_poCurFeature)
delete m_poCurFeature;
m_poCurFeature = NULL;

TABFeature* poCurFeature = (TABFeature*)m_poCurBaseTable->GetFeature(ExtractBaseFeatureId(nFeatureId));
if( poCurFeature == NULL )
return NULL;
m_poCurFeature = new TABFeature(m_poFeatureDefnRef);
m_poCurFeature->SetFrom(poCurFeature);
delete poCurFeature;

m_poCurFeature = (TABFeature*)m_poCurBaseTable->GetFeature(ExtractBaseFeatureId(nFeatureId));
m_nCurFeatureId = nFeatureId;

m_poCurFeature->SetFID(nFeatureId);
Expand Down
4 changes: 2 additions & 2 deletions gdal/ogr/ogrsf_frmts/mitab/mitab_tabview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ int TABView::SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode/*=TRUE*/)
* Returns feature id that follows nPrevId, or -1 if it is the
* last feature id. Pass nPrevId=-1 to fetch the first valid feature id.
**********************************************************************/
int TABView::GetNextFeatureId(int nPrevId)
GIntBig TABView::GetNextFeatureId(GIntBig nPrevId)
{
if (m_nMainTableIndex != -1)
return m_papoTABFiles[m_nMainTableIndex]->GetNextFeatureId(nPrevId);
Expand All @@ -866,7 +866,7 @@ int TABView::GetNextFeatureId(int nPrevId)
* error happened. In any case, CPLError() will have been called to
* report the reason of the failure.
**********************************************************************/
TABFeature *TABView::GetFeatureRef(int nFeatureId)
TABFeature *TABView::GetFeatureRef(GIntBig nFeatureId)
{

/*-----------------------------------------------------------------
Expand Down