int* SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, double *padfBoundsMax, int *pnShapeCount ) { int i, bNeedSwap, nBufferMax = 0; unsigned char abyBuf[16]; int *panResultBuffer = NULL; *pnShapeCount = 0; /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine. */ /* -------------------------------------------------------------------- */ i = 1; if( *((unsigned char *) &i) == 1 ) bBigEndian = FALSE; else bBigEndian = TRUE; /* -------------------------------------------------------------------- */ /* Read the header. */ /* -------------------------------------------------------------------- */ hDiskTree->sHooks.FSeek( hDiskTree->fpQIX, 0, SEEK_SET ); hDiskTree->sHooks.FRead( abyBuf, 16, 1, hDiskTree->fpQIX ); if( memcmp( abyBuf, "SQT", 3 ) != 0 ) return NULL; if( (abyBuf[3] == 2 && bBigEndian) || (abyBuf[3] == 1 && !bBigEndian) ) bNeedSwap = FALSE; else bNeedSwap = TRUE; /* -------------------------------------------------------------------- */ /* Search through root node and it's descendants. */ /* -------------------------------------------------------------------- */ if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax, &panResultBuffer, &nBufferMax, pnShapeCount, bNeedSwap, 0 ) ) { if( panResultBuffer != NULL ) free( panResultBuffer ); *pnShapeCount = 0; return NULL; } /* -------------------------------------------------------------------- */ /* Sort the id array */ /* -------------------------------------------------------------------- */ /* To distinguish between empty intersection from error case */ if( panResultBuffer == NULL ) panResultBuffer = (int*) calloc(1, sizeof(int)); else qsort(panResultBuffer, *pnShapeCount, sizeof(int), compare_ints); return panResultBuffer; }
SHPSearchDiskTree( FILE *fp, double *padfBoundsMin, double *padfBoundsMax, int *pnShapeCount ) { int i, bNeedSwap, nBufferMax = 0; unsigned char abyBuf[16]; int *panResultBuffer = NULL; *pnShapeCount = 0; /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine. */ /* -------------------------------------------------------------------- */ i = 1; if( *((unsigned char *) &i) == 1 ) bBigEndian = FALSE; else bBigEndian = TRUE; /* -------------------------------------------------------------------- */ /* Read the header. */ /* -------------------------------------------------------------------- */ fseek( fp, 0, SEEK_SET ); fread( abyBuf, 16, 1, fp ); if( memcmp( abyBuf, "SQT", 3 ) != 0 ) return NULL; if( (abyBuf[3] == 2 && bBigEndian) || (abyBuf[3] == 1 && !bBigEndian) ) bNeedSwap = FALSE; else bNeedSwap = TRUE; /* -------------------------------------------------------------------- */ /* Search through root node and it's decendents. */ /* -------------------------------------------------------------------- */ if( !SHPSearchDiskTreeNode( fp, padfBoundsMin, padfBoundsMax, &panResultBuffer, &nBufferMax, pnShapeCount, bNeedSwap ) ) { if( panResultBuffer != NULL ) free( panResultBuffer ); *pnShapeCount = 0; return NULL; } /* -------------------------------------------------------------------- */ /* Sort the id array */ /* -------------------------------------------------------------------- */ qsort(panResultBuffer, *pnShapeCount, sizeof(int), compare_ints); return panResultBuffer; }
static int SHPSearchDiskTreeNode( FILE *fp, double *padfBoundsMin, double *padfBoundsMax, int **ppanResultBuffer, int *pnBufferMax, int *pnResultCount, int bNeedSwap ) { int i; int offset; int numshapes, numsubnodes; double adfNodeBoundsMin[2], adfNodeBoundsMax[2]; /* -------------------------------------------------------------------- */ /* Read and unswap first part of node info. */ /* -------------------------------------------------------------------- */ fread( &offset, 4, 1, fp ); if ( bNeedSwap ) SwapWord ( 4, &offset ); fread( adfNodeBoundsMin, sizeof(double), 2, fp ); fread( adfNodeBoundsMax, sizeof(double), 2, fp ); if ( bNeedSwap ) { SwapWord( 8, adfNodeBoundsMin + 0 ); SwapWord( 8, adfNodeBoundsMin + 1 ); SwapWord( 8, adfNodeBoundsMax + 0 ); SwapWord( 8, adfNodeBoundsMax + 1 ); } fread( &numshapes, 4, 1, fp ); if ( bNeedSwap ) SwapWord ( 4, &numshapes ); /* -------------------------------------------------------------------- */ /* If we don't overlap this node at all, we can just fseek() */ /* pass this node info and all subnodes. */ /* -------------------------------------------------------------------- */ if( !SHPCheckBoundsOverlap( adfNodeBoundsMin, adfNodeBoundsMax, padfBoundsMin, padfBoundsMax, 2 ) ) { offset += numshapes*sizeof(int) + sizeof(int); fseek(fp, offset, SEEK_CUR); return TRUE; } /* -------------------------------------------------------------------- */ /* Add all the shapeids at this node to our list. */ /* -------------------------------------------------------------------- */ if(numshapes > 0) { if( *pnResultCount + numshapes > *pnBufferMax ) { *pnBufferMax = (int) ((*pnResultCount + numshapes + 100) * 1.25); *ppanResultBuffer = (int *) SfRealloc( *ppanResultBuffer, *pnBufferMax * sizeof(int) ); } fread( *ppanResultBuffer + *pnResultCount, sizeof(int), numshapes, fp ); if (bNeedSwap ) { for( i=0; i<numshapes; i++ ) SwapWord( 4, *ppanResultBuffer + *pnResultCount + i ); } *pnResultCount += numshapes; } /* -------------------------------------------------------------------- */ /* Process the subnodes. */ /* -------------------------------------------------------------------- */ fread( &numsubnodes, 4, 1, fp ); if ( bNeedSwap ) SwapWord ( 4, &numsubnodes ); for(i=0; i<numsubnodes; i++) { if( !SHPSearchDiskTreeNode( fp, padfBoundsMin, padfBoundsMax, ppanResultBuffer, pnBufferMax, pnResultCount, bNeedSwap ) ) return FALSE; } return TRUE; }
static int SHPSearchDiskTreeNode( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, double *padfBoundsMax, int **ppanResultBuffer, int *pnBufferMax, int *pnResultCount, int bNeedSwap, int nRecLevel ) { unsigned int i; unsigned int offset; unsigned int numshapes, numsubnodes; double adfNodeBoundsMin[2], adfNodeBoundsMax[2]; int nFReadAcc; /* -------------------------------------------------------------------- */ /* Read and unswap first part of node info. */ /* -------------------------------------------------------------------- */ nFReadAcc = (int)hDiskTree->sHooks.FRead( &offset, 4, 1, hDiskTree->fpQIX ); if ( bNeedSwap ) SwapWord ( 4, &offset ); nFReadAcc += (int)hDiskTree->sHooks.FRead( adfNodeBoundsMin, sizeof(double), 2, hDiskTree->fpQIX ); nFReadAcc += (int)hDiskTree->sHooks.FRead( adfNodeBoundsMax, sizeof(double), 2, hDiskTree->fpQIX ); if ( bNeedSwap ) { SwapWord( 8, adfNodeBoundsMin + 0 ); SwapWord( 8, adfNodeBoundsMin + 1 ); SwapWord( 8, adfNodeBoundsMax + 0 ); SwapWord( 8, adfNodeBoundsMax + 1 ); } nFReadAcc += (int)hDiskTree->sHooks.FRead( &numshapes, 4, 1, hDiskTree->fpQIX ); if ( bNeedSwap ) SwapWord ( 4, &numshapes ); /* Check that we could read all previous values */ if( nFReadAcc != 1 + 2 + 2 + 1 ) { hDiskTree->sHooks.Error("I/O error"); return FALSE; } /* Sanity checks to avoid int overflows in later computation */ if( offset > INT_MAX - sizeof(int) ) { hDiskTree->sHooks.Error("Invalid value for offset"); return FALSE; } if( numshapes > (INT_MAX - offset - sizeof(int)) / sizeof(int) || numshapes > INT_MAX / sizeof(int) - *pnResultCount ) { hDiskTree->sHooks.Error("Invalid value for numshapes"); return FALSE; } /* -------------------------------------------------------------------- */ /* If we don't overlap this node at all, we can just fseek() */ /* pass this node info and all subnodes. */ /* -------------------------------------------------------------------- */ if( !SHPCheckBoundsOverlap( adfNodeBoundsMin, adfNodeBoundsMax, padfBoundsMin, padfBoundsMax, 2 ) ) { offset += numshapes*sizeof(int) + sizeof(int); hDiskTree->sHooks.FSeek(hDiskTree->fpQIX, offset, SEEK_CUR); return TRUE; } /* -------------------------------------------------------------------- */ /* Add all the shapeids at this node to our list. */ /* -------------------------------------------------------------------- */ if(numshapes > 0) { if( *pnResultCount + numshapes > *pnBufferMax ) { int* pNewBuffer; *pnBufferMax = (*pnResultCount + numshapes + 100) * 5 / 4; if( *pnBufferMax > INT_MAX / sizeof(int) ) *pnBufferMax = *pnResultCount + numshapes; pNewBuffer = (int *) SfRealloc( *ppanResultBuffer, *pnBufferMax * sizeof(int) ); if( pNewBuffer == NULL ) { hDiskTree->sHooks.Error("Out of memory error"); return FALSE; } *ppanResultBuffer = pNewBuffer; } if( hDiskTree->sHooks.FRead( *ppanResultBuffer + *pnResultCount, sizeof(int), numshapes, hDiskTree->fpQIX ) != numshapes ) { hDiskTree->sHooks.Error("I/O error"); return FALSE; } if (bNeedSwap ) { for( i=0; i<numshapes; i++ ) SwapWord( 4, *ppanResultBuffer + *pnResultCount + i ); } *pnResultCount += numshapes; } /* -------------------------------------------------------------------- */ /* Process the subnodes. */ /* -------------------------------------------------------------------- */ if( hDiskTree->sHooks.FRead( &numsubnodes, 4, 1, hDiskTree->fpQIX ) != 1 ) { hDiskTree->sHooks.Error("I/O error"); return FALSE; } if ( bNeedSwap ) SwapWord ( 4, &numsubnodes ); if( numsubnodes > 0 && nRecLevel == 32 ) { hDiskTree->sHooks.Error("Shape tree is too deep"); return FALSE; } for(i=0; i<numsubnodes; i++) { if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax, ppanResultBuffer, pnBufferMax, pnResultCount, bNeedSwap, nRecLevel + 1 ) ) return FALSE; } return TRUE; }