268 #include <grass/shapefil.h> 285 #if UINT_MAX == 65535 286 typedef unsigned long int32;
296 #define ByteCopy( a, b, c ) memcpy( b, a, c ) 298 # define MIN(a,b) ((a<b) ? a : b) 299 # define MAX(a,b) ((a>b) ? a : b) 302 #if defined(WIN32) || defined(_WIN32) 304 # define snprintf _snprintf 309 #define bBigEndian FALSE 310 #elif defined(CPL_MSB) 311 #define bBigEndian TRUE 313 static int bBigEndian;
322 static void SwapWord(
int length,
void * wordP )
328 for( i=0; i < length/2; i++ )
330 temp = ((uchar *) wordP)[i];
331 ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1];
332 ((uchar *) wordP)[length-i-1] = temp;
343 static void * SfRealloc(
void * pMem,
int nNewSize )
347 return( (
void *)
malloc(nNewSize) );
349 return( (
void *) realloc(pMem,nNewSize) );
362 uchar abyHeader[100];
370 psSHP->
sHooks.
Error(
"SHPWriteHeader failed : SHX file is closed");
377 for( i = 0; i < 100; i++ )
385 if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
389 if( bBigEndian ) SwapWord( 4, abyHeader+28 );
393 if( bBigEndian ) SwapWord( 4, abyHeader+32 );
396 ByteCopy( &dValue, abyHeader+36, 8 );
397 if( bBigEndian ) SwapWord( 8, abyHeader+36 );
400 ByteCopy( &dValue, abyHeader+44, 8 );
401 if( bBigEndian ) SwapWord( 8, abyHeader+44 );
404 ByteCopy( &dValue, abyHeader+52, 8 );
405 if( bBigEndian ) SwapWord( 8, abyHeader+52 );
408 ByteCopy( &dValue, abyHeader+60, 8 );
409 if( bBigEndian ) SwapWord( 8, abyHeader+60 );
412 ByteCopy( &dValue, abyHeader+68, 8 );
413 if( bBigEndian ) SwapWord( 8, abyHeader+68 );
416 ByteCopy( &dValue, abyHeader+76, 8 );
417 if( bBigEndian ) SwapWord( 8, abyHeader+76 );
420 ByteCopy( &dValue, abyHeader+84, 8 );
421 if( bBigEndian ) SwapWord( 8, abyHeader+84 );
424 ByteCopy( &dValue, abyHeader+92, 8 );
425 if( bBigEndian ) SwapWord( 8, abyHeader+92 );
433 psSHP->
sHooks.
Error(
"Failure writing .shp header" );
442 if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
447 psSHP->
sHooks.
Error(
"Failure writing .shx header" );
461 for( i = 0; i < psSHP->
nRecords; i++ )
465 if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
466 if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
472 psSHP->
sHooks.
Error(
"Failure writing .shx contents" );
489 SHPOpen(
const char * pszLayer,
const char * pszAccess )
496 return SHPOpenLL( pszLayer, pszAccess, &sHooks );
510 char *pszFullname, *pszBasename;
516 int bLazySHXLoading =
FALSE;
524 if( strcmp(pszAccess,
"rb+") == 0 || strcmp(pszAccess,
"r+b") == 0
525 || strcmp(pszAccess,
"r+") == 0 )
529 bLazySHXLoading = strchr(pszAccess,
'l') !=
NULL;
536 #if !defined(bBigEndian) 538 if( *((uchar *) &i) == 1 )
556 pszBasename = (
char *)
malloc(strlen(pszLayer)+5);
557 strcpy( pszBasename, pszLayer );
558 for( i = (
int)strlen(pszBasename)-1;
559 i > 0 && pszBasename[i] !=
'.' && pszBasename[i] !=
'/' 560 && pszBasename[i] !=
'\\';
563 if( pszBasename[i] ==
'.' )
564 pszBasename[i] =
'\0';
570 nFullnameLen = strlen(pszBasename) + 5;
571 pszFullname = (
char *)
malloc(nFullnameLen);
572 snprintf( pszFullname, nFullnameLen,
"%s.shp", pszBasename ) ;
576 snprintf( pszFullname, nFullnameLen,
"%s.SHP", pszBasename );
582 size_t nMessageLen = strlen(pszBasename)*2+256;
583 char *pszMessage = (
char *)
malloc(nMessageLen);
584 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shp or %s.SHP.",
585 pszBasename, pszBasename );
586 psHooks->
Error( pszMessage );
596 snprintf( pszFullname, nFullnameLen,
"%s.shx", pszBasename );
600 snprintf( pszFullname, nFullnameLen,
"%s.SHX", pszBasename );
606 size_t nMessageLen = strlen(pszBasename)*2+256;
607 char *pszMessage = (
char *)
malloc(nMessageLen);
608 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shx or %s.SHX." 609 "Try --config SHAPE_RESTORE_SHX true to restore or create it",
610 pszBasename, pszBasename );
611 psHooks->
Error( pszMessage );
627 pabyBuf = (uchar *)
malloc(100);
630 psSHP->
nFileSize = ((
unsigned int)pabyBuf[24] * 256 * 256 * 256
631 + (
unsigned int)pabyBuf[25] * 256 * 256
632 + (
unsigned int)pabyBuf[26] * 256
633 + (
unsigned int)pabyBuf[27]);
645 || pabyBuf[2] != 0x27
646 || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
648 psSHP->
sHooks.
Error(
".shx file is unreadable, or corrupt." );
656 psSHP->
nRecords = pabyBuf[27] + pabyBuf[26] * 256
657 + pabyBuf[25] * 256 * 256 + (pabyBuf[24] & 0x7F) * 256 * 256 * 256;
666 snprintf( szError,
sizeof(szError),
667 "Record count in .shp header is %d, which seems\n" 668 "unreasonable. Assuming header is corrupt.",
681 if( psSHP->
nRecords >= 1024 * 1024 )
686 if( nFileSize > 100 &&
689 psSHP->
nRecords = (int)((nFileSize - 100) / 8);
697 if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
698 memcpy( &dValue, pabyBuf+36, 8 );
701 if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
702 memcpy( &dValue, pabyBuf+44, 8 );
705 if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
706 memcpy( &dValue, pabyBuf+52, 8 );
709 if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
710 memcpy( &dValue, pabyBuf+60, 8 );
713 if( bBigEndian ) SwapWord( 8, pabyBuf+68 );
714 memcpy( &dValue, pabyBuf+68, 8 );
717 if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
718 memcpy( &dValue, pabyBuf+76, 8 );
721 if( bBigEndian ) SwapWord( 8, pabyBuf+84 );
722 memcpy( &dValue, pabyBuf+84, 8 );
725 if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
726 memcpy( &dValue, pabyBuf+92, 8 );
741 if( bLazySHXLoading )
748 (!bLazySHXLoading && pabyBuf ==
NULL))
752 snprintf( szError,
sizeof(szError),
753 "Not enough memory to allocate requested memory (nRecords=%d).\n" 754 "Probably broken SHP file",
761 if (pabyBuf)
free( pabyBuf );
766 if( bLazySHXLoading )
778 snprintf( szError,
sizeof(szError),
779 "Failed to read all values for %d records in .shx file.",
795 if (strcmp(pszAccess,
"rb") == 0)
801 for( i = 0; i < psSHP->
nRecords; i++ )
803 unsigned int nOffset, nLength;
805 memcpy( &nOffset, pabyBuf + i * 8, 4 );
806 if( !bBigEndian ) SwapWord( 4, &nOffset );
808 memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
809 if( !bBigEndian ) SwapWord( 4, &nLength );
811 if( nOffset > (
unsigned int)INT_MAX )
814 snprintf( str,
sizeof(str),
815 "Invalid offset for entity %d", i);
822 if( nLength > (
unsigned int)(INT_MAX / 2 - 4) )
825 snprintf( str,
sizeof(str),
826 "Invalid length for entity %d", i);
854 if ( !bRestoreSHX )
return SHPOpenLL ( pszLayer, pszAccess, psHooks );
859 return SHPOpenLL ( pszLayer, pszAccess, psHooks );
877 char *pszFullname, *pszBasename;
884 unsigned int nSHPFilesize;
889 unsigned int nCurrentRecordOffset = 0;
890 unsigned int nCurrentSHPOffset = 100;
891 size_t nRealSHXContentSize = 100;
893 const char pszSHXAccess[] =
"w+b";
895 char abyReadedRecord[8];
896 unsigned int niRecord = 0;
897 unsigned int nRecordLength = 0;
898 unsigned int nRecordOffset = 50;
905 if( strcmp(pszAccess,
"rb+") == 0 || strcmp(pszAccess,
"r+b") == 0
906 || strcmp(pszAccess,
"r+") == 0 )
916 #if !defined(bBigEndian) 918 if( *((uchar *) &i) == 1 )
928 pszBasename = (
char *)
malloc(strlen(pszLayer)+5);
929 strcpy( pszBasename, pszLayer );
930 for( i = (
int)strlen(pszBasename)-1;
931 i > 0 && pszBasename[i] !=
'.' && pszBasename[i] !=
'/' 932 && pszBasename[i] !=
'\\';
935 if( pszBasename[i] ==
'.' )
936 pszBasename[i] =
'\0';
942 nFullnameLen = strlen(pszBasename) + 5;
943 pszFullname = (
char *)
malloc(nFullnameLen);
944 snprintf( pszFullname, nFullnameLen,
"%s.shp", pszBasename ) ;
945 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
948 snprintf( pszFullname, nFullnameLen,
"%s.SHP", pszBasename );
949 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
954 nMessageLen = strlen(pszBasename)*2+256;
955 pszMessage = (
char *)
malloc(nMessageLen);
956 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shp or %s.SHP.",
957 pszBasename, pszBasename );
958 psHooks->
Error( pszMessage );
970 pabyBuf = (uchar *)
malloc(100);
971 psHooks->
FRead( pabyBuf, 100, 1, fpSHP );
973 nSHPFilesize = ((
unsigned int)pabyBuf[24] * 256 * 256 * 256
974 + (
unsigned int)pabyBuf[25] * 256 * 256
975 + (
unsigned int)pabyBuf[26] * 256
976 + (
unsigned int)pabyBuf[27]);
977 if( nSHPFilesize < 0xFFFFFFFFU / 2 )
980 nSHPFilesize = 0xFFFFFFFEU;
982 snprintf( pszFullname, nFullnameLen,
"%s.shx", pszBasename );
983 fpSHX = psHooks->
FOpen( pszFullname, pszSHXAccess );
987 nMessageLen = strlen( pszBasename ) * 2 + 256;
988 pszMessage = (
char *)
malloc( nMessageLen );
989 snprintf( pszMessage, nMessageLen,
"Error opening file %s.shx for writing",
991 psHooks->
Error( pszMessage );
1006 psHooks->
FSeek( fpSHP, 100, 0 );
1007 pabySHXHeader = (
char *)
malloc ( 100 );
1008 memcpy( pabySHXHeader, pabyBuf, 100 );
1009 psHooks->
FWrite( pabySHXHeader, 100, 1, fpSHX );
1011 while( nCurrentSHPOffset < nSHPFilesize )
1013 if( psHooks->
FRead( &niRecord, 4, 1, fpSHP ) == 1 &&
1014 psHooks->
FRead( &nRecordLength, 4, 1, fpSHP ) == 1)
1016 if( !bBigEndian ) SwapWord( 4, &nRecordOffset );
1017 memcpy( abyReadedRecord, &nRecordOffset, 4 );
1018 memcpy( abyReadedRecord + 4, &nRecordLength, 4 );
1020 psHooks->
FWrite( abyReadedRecord, 8, 1, fpSHX );
1022 if ( !bBigEndian ) SwapWord( 4, &nRecordOffset );
1023 if ( !bBigEndian ) SwapWord( 4, &nRecordLength );
1024 nRecordOffset += nRecordLength + 4;
1025 nCurrentRecordOffset += 8;
1026 nCurrentSHPOffset += 8 + nRecordLength * 2;
1028 psHooks->
FSeek( fpSHP, nCurrentSHPOffset, 0 );
1029 nRealSHXContentSize += 8;
1033 nMessageLen = strlen( pszBasename ) * 2 + 256;
1034 pszMessage = (
char *)
malloc( nMessageLen );
1035 snprintf( pszMessage, nMessageLen,
"Error parsing .shp to restore .shx" );
1036 psHooks->
Error( pszMessage );
1039 psHooks->
FClose( fpSHX );
1040 psHooks->
FClose( fpSHP );
1042 free( pabySHXHeader );
1043 free( pszBasename );
1044 free( pszFullname );
1050 nRealSHXContentSize /= 2;
1051 if( !bBigEndian ) SwapWord( 4, &nRealSHXContentSize );
1052 psHooks->
FSeek( fpSHX, 24, 0 );
1053 psHooks->
FWrite( &nRealSHXContentSize, 4, 1, fpSHX );
1055 psHooks->
FClose( fpSHP );
1056 psHooks->
FClose( fpSHX );
1059 free ( pszFullname );
1060 free ( pszBasename );
1061 free ( pabySHXHeader );
1142 double * padfMinBound,
double * padfMaxBound )
1150 if( pnEntities !=
NULL )
1153 if( pnShapeType !=
NULL )
1156 for( i = 0; i < 4; i++ )
1158 if( padfMinBound !=
NULL )
1160 if( padfMaxBound !=
NULL )
1180 return SHPCreateLL( pszLayer, nShapeType, &sHooks );
1194 char *pszBasename =
NULL, *pszFullname =
NULL;
1197 uchar abyHeader[100];
1200 size_t nFullnameLen;
1205 #if !defined(bBigEndian) 1207 if( *((uchar *) &i) == 1 )
1217 pszBasename = (
char *)
malloc(strlen(pszLayer)+5);
1218 strcpy( pszBasename, pszLayer );
1219 for( i = (
int)strlen(pszBasename)-1;
1220 i > 0 && pszBasename[i] !=
'.' && pszBasename[i] !=
'/' 1221 && pszBasename[i] !=
'\\';
1224 if( pszBasename[i] ==
'.' )
1225 pszBasename[i] =
'\0';
1230 nFullnameLen = strlen(pszBasename) + 5;
1231 pszFullname = (
char *)
malloc(nFullnameLen);
1232 snprintf( pszFullname, nFullnameLen,
"%s.shp", pszBasename );
1233 fpSHP = psHooks->
FOpen(pszFullname,
"wb" );
1236 psHooks->
Error(
"Failed to create file .shp file." );
1240 snprintf( pszFullname, nFullnameLen,
"%s.shx", pszBasename );
1241 fpSHX = psHooks->
FOpen(pszFullname,
"wb" );
1244 psHooks->
Error(
"Failed to create file .shx file." );
1248 free( pszFullname ); pszFullname =
NULL;
1249 free( pszBasename ); pszBasename =
NULL;
1254 for( i = 0; i < 100; i++ )
1257 abyHeader[2] = 0x27;
1258 abyHeader[3] = 0x0a;
1262 if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
1266 if( bBigEndian ) SwapWord( 4, abyHeader+28 );
1270 if( bBigEndian ) SwapWord( 4, abyHeader+32 );
1273 ByteCopy( &dValue, abyHeader+36, 8 );
1274 ByteCopy( &dValue, abyHeader+44, 8 );
1275 ByteCopy( &dValue, abyHeader+52, 8 );
1276 ByteCopy( &dValue, abyHeader+60, 8 );
1281 if( psHooks->
FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
1283 psHooks->
Error(
"Failed to write .shp header." );
1292 if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
1294 if( psHooks->
FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
1296 psHooks->
Error(
"Failed to write .shx header." );
1303 psHooks->
FClose( fpSHP );
1304 psHooks->
FClose( fpSHX );
1306 return(
SHPOpenLL( pszLayer,
"r+b", psHooks ) );
1309 if (pszFullname)
free(pszFullname);
1310 if (pszBasename)
free(pszBasename);
1311 if (fpSHP) psHooks->
FClose( fpSHP );
1312 if (fpSHX) psHooks->
FClose( fpSHX );
1333 SwapWord( 8, pabyRec + 0 );
1334 SwapWord( 8, pabyRec + 8 );
1335 SwapWord( 8, pabyRec + 16 );
1336 SwapWord( 8, pabyRec + 24 );
1364 for( i = 0; i < psObject->
nVertices; i++ )
1387 const int * panPartStart,
const int * panPartType,
1388 int nVertices,
const double *padfX,
const double *padfY,
1389 const double * padfZ,
const double * padfM )
1393 int i, bHasM,
bHasZ;
1438 calloc(
sizeof(
int), psObject->
nParts);
1445 for( i = 0; i < nParts; i++ )
1447 if( panPartStart !=
NULL )
1450 if( panPartType !=
NULL )
1473 psObject->
padfX[i] = padfX[i];
1475 psObject->
padfY[i] = padfY[i];
1476 if( padfZ !=
NULL && bHasZ )
1477 psObject->
padfZ[i] = padfZ[i];
1478 if( padfM !=
NULL && bHasM )
1479 psObject->
padfM[i] = padfM[i];
1481 if( padfM !=
NULL && bHasM )
1503 const
double * padfX, const
double * padfY,
1504 const
double * padfZ )
1508 nVertices, padfX, padfY, padfZ,
NULL ) );
1522 unsigned int nRecordOffset, nRecordSize=0;
1526 int bExtendFile =
FALSE;
1543 || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
1545 if( nShapeId != -1 && nShapeId >= psSHP->
nRecords )
1554 unsigned int* panRecOffsetNew;
1555 unsigned int* panRecSizeNew;
1557 panRecOffsetNew = (
unsigned int *)
1558 SfRealloc(psSHP->
panRecOffset,
sizeof(
unsigned int) * nNewMaxRecords );
1559 if( panRecOffsetNew ==
NULL )
1563 panRecSizeNew = (
unsigned int *)
1564 SfRealloc(psSHP->
panRecSize,
sizeof(
unsigned int) * nNewMaxRecords );
1565 if( panRecSizeNew ==
NULL )
1576 + psObject->
nParts * 8 + 128);
1577 if( pabyRec ==
NULL )
1591 int32 nPoints, nParts;
1594 nParts = psObject->
nParts;
1596 _SHPSetBounds( pabyRec + 12, psObject );
1598 if( bBigEndian ) SwapWord( 4, &nPoints );
1599 if( bBigEndian ) SwapWord( 4, &nParts );
1601 ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
1602 ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
1611 for( i = 0; i < psObject->
nParts; i++ )
1613 if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
1622 memcpy( pabyRec + nRecordSize, psObject->
panPartType,
1624 for( i = 0; i < psObject->
nParts; i++ )
1626 if( bBigEndian ) SwapWord( 4, pabyRec + nRecordSize );
1634 for( i = 0; i < psObject->
nVertices; i++ )
1637 ByteCopy( psObject->
padfY + i, pabyRec + nRecordSize + 8, 8 );
1640 SwapWord( 8, pabyRec + nRecordSize );
1643 SwapWord( 8, pabyRec + nRecordSize + 8 );
1645 nRecordSize += 2 * 8;
1656 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1660 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1663 for( i = 0; i < psObject->
nVertices; i++ )
1666 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1684 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1688 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1691 for( i = 0; i < psObject->
nVertices; i++ )
1694 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1711 _SHPSetBounds( pabyRec + 12, psObject );
1713 if( bBigEndian ) SwapWord( 4, &nPoints );
1714 ByteCopy( &nPoints, pabyRec + 44, 4 );
1716 for( i = 0; i < psObject->
nVertices; i++ )
1719 ByteCopy( psObject->
padfY + i, pabyRec + 48 + i*16 + 8, 8 );
1721 if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
1722 if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
1725 nRecordSize = 48 + 16 * psObject->
nVertices;
1730 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1734 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1737 for( i = 0; i < psObject->
nVertices; i++ )
1740 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1750 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1754 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1757 for( i = 0; i < psObject->
nVertices; i++ )
1760 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1776 if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
1777 if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
1784 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1793 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1817 if( nShapeId == -1 || psSHP->
panRecSize[nShapeId] < nRecordSize-8 )
1819 unsigned int nExpectedSize = psSHP->
nFileSize + nRecordSize;
1820 if( nExpectedSize < psSHP->nFileSize )
1823 snprintf( str,
sizeof(str),
"Failed to write shape object. " 1824 "File size cannot reach %u + %u.",
1842 i32 = (nShapeId < 0) ? psSHP->
nRecords+1 : nShapeId+1;
1843 if( !bBigEndian ) SwapWord( 4, &i32 );
1846 i32 = (nRecordSize-8)/2;
1847 if( !bBigEndian ) SwapWord( 4, &i32 );
1851 if( bBigEndian ) SwapWord( 4, &i32 );
1859 psSHP->
sHooks.
Error(
"Error in psSHP->sHooks.FSeek() while writing object to .shp file." );
1865 psSHP->
sHooks.
Error(
"Error in psSHP->sHooks.Fwrite() while writing object to .shp file." );
1874 if( nShapeId == -1 )
1906 for( i = 0; i < psObject->
nVertices; i++ )
1912 if( psObject->
padfZ )
1917 if( psObject->
padfM )
1931 static void* SHPAllocBuffer(
unsigned char** pBuffer,
int nSize)
1933 unsigned char* pRet;
1935 if( pBuffer ==
NULL )
1936 return calloc(1, nSize);
1942 (*pBuffer) += nSize;
1950 static unsigned char* SHPReallocObjectBufIfNecessary (
SHPHandle psSHP,
1951 int nObjectBufSize )
1953 unsigned char* pBuffer;
1954 if( nObjectBufSize == 0 )
1956 nObjectBufSize = 4 *
sizeof(double);
1960 pBuffer = (
unsigned char*) realloc( psSHP->
pabyObjectBuf, nObjectBufSize );
1961 if( pBuffer !=
NULL )
1985 char szErrorMsg[128];
1992 if( hEntity < 0 || hEntity >= psSHP->
nRecords )
2000 unsigned int nOffset, nLength;
2007 snprintf( str,
sizeof(str),
2008 "Error in fseek()/fread() reading object from .shx file at offset %d",
2014 if( !bBigEndian ) SwapWord( 4, &nOffset );
2015 if( !bBigEndian ) SwapWord( 4, &nLength );
2017 if( nOffset > (
unsigned int)INT_MAX )
2020 snprintf( str,
sizeof(str),
2021 "Invalid offset for entity %d", hEntity);
2026 if( nLength > (
unsigned int)(INT_MAX / 2 - 4) )
2029 snprintf( str,
sizeof(str),
2030 "Invalid length for entity %d", hEntity);
2048 if( nNewBufSize < INT_MAX - nNewBufSize / 3 )
2049 nNewBufSize += nNewBufSize / 3;
2051 nNewBufSize = INT_MAX;
2054 if( nEntitySize >= 10 * 1024 * 1024 &&
2062 if( nFileSize >= 0xFFFFFFFFU )
2065 psSHP->
nFileSize = (
unsigned int)nFileSize;
2071 snprintf( str,
sizeof(str),
2072 "Error in fread() reading object of size %u at offset %u from .shp file",
2080 pabyRecNew = (uchar *) SfRealloc(psSHP->
pabyRec,nNewBufSize);
2081 if (pabyRecNew ==
NULL)
2085 snprintf( szError,
sizeof(szError),
2086 "Not enough memory to allocate requested memory (nNewBufSize=%d). " 2087 "Probably broken SHP file", nNewBufSize);
2113 snprintf( str,
sizeof(str),
2114 "Error in fseek() reading object from .shp file at offset %u",
2129 if( nBytesRead >= 8 && nBytesRead == nEntitySize - 8 )
2132 int nSHPContentLength;
2133 memcpy( &nSHPContentLength, psSHP->
pabyRec + 4, 4 );
2134 if( !bBigEndian ) SwapWord( 4, &(nSHPContentLength) );
2135 if( nSHPContentLength < 0 ||
2136 nSHPContentLength > INT_MAX / 2 - 4 ||
2137 2 * nSHPContentLength + 8 != nBytesRead )
2140 snprintf( str,
sizeof(str),
2141 "Sanity check failed when trying to recover from inconsistent .shx/.shp with shape %d",
2148 else if( nBytesRead != nEntitySize )
2155 snprintf( str,
sizeof(str),
2156 "Error in fread() reading object of size %u at offset %u from .shp file",
2163 if ( 8 + 4 > nEntitySize )
2165 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2166 "Corrupted .shp file : shape %d : nEntitySize = %d",
2167 hEntity, nEntitySize);
2171 memcpy( &nSHPType, psSHP->
pabyRec + 8, 4 );
2173 if( bBigEndian ) SwapWord( 4, &(nSHPType) );
2182 psSHP->
sHooks.
Error(
"Invalid read pattern in fast read mode. " 2183 "SHPDestroyObject() should be called." );
2207 int32 nPoints, nParts;
2209 unsigned char* pBuffer =
NULL;
2210 unsigned char** ppBuffer =
NULL;
2212 if ( 40 + 8 + 4 > nEntitySize )
2214 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2215 "Corrupted .shp file : shape %d : nEntitySize = %d",
2216 hEntity, nEntitySize);
2229 if( bBigEndian ) SwapWord( 8, &(psShape->
dfXMin) );
2230 if( bBigEndian ) SwapWord( 8, &(psShape->
dfYMin) );
2231 if( bBigEndian ) SwapWord( 8, &(psShape->
dfXMax) );
2232 if( bBigEndian ) SwapWord( 8, &(psShape->
dfYMax) );
2238 memcpy( &nPoints, psSHP->
pabyRec + 40 + 8, 4 );
2239 memcpy( &nParts, psSHP->
pabyRec + 36 + 8, 4 );
2241 if( bBigEndian ) SwapWord( 4, &nPoints );
2242 if( bBigEndian ) SwapWord( 4, &nParts );
2246 nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
2248 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2249 "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d.",
2250 hEntity, nPoints, nParts);
2259 nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
2264 nRequiredSize += 16 + 8 * nPoints;
2268 nRequiredSize += 4 * nParts;
2270 if (nRequiredSize > nEntitySize)
2272 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2273 "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d, nEntitySize=%d.",
2274 hEntity, nPoints, nParts, nEntitySize);
2282 int nObjectBufSize = 4 *
sizeof(double) * nPoints + 2 *
sizeof(
int) * nParts;
2283 pBuffer = SHPReallocObjectBufIfNecessary(psSHP, nObjectBufSize);
2284 ppBuffer = &pBuffer;
2288 psShape->
padfX = (
double *) SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints);
2289 psShape->
padfY = (
double *) SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints);
2290 psShape->
padfZ = (
double *) SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints);
2291 psShape->
padfM = (
double *) SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints);
2293 psShape->
nParts = nParts;
2294 psShape->
panPartStart = (
int *) SHPAllocBuffer(ppBuffer, nParts *
sizeof(
int));
2295 psShape->
panPartType = (
int *) SHPAllocBuffer(ppBuffer, nParts *
sizeof(
int));
2304 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2305 "Not enough memory to allocate requested memory (nPoints=%d, nParts=%d) for shape %d. " 2306 "Probably broken SHP file", hEntity, nPoints, nParts );
2312 for( i = 0; (
int32)i < nParts; i++ )
2319 for( i = 0; (
int32)i < nParts; i++ )
2321 if( bBigEndian ) SwapWord( 4, psShape->
panPartStart+i );
2329 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2330 "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
2338 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2339 "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
2347 nOffset = 44 + 8 + 4*nParts;
2355 for( i = 0; (
int32)i < nParts; i++ )
2357 if( bBigEndian ) SwapWord( 4, psShape->
panPartType+i );
2360 nOffset += 4*nParts;
2366 for( i = 0; (
int32)i < nPoints; i++ )
2368 memcpy(psShape->
padfX + i,
2369 psSHP->
pabyRec + nOffset + i * 16,
2372 memcpy(psShape->
padfY + i,
2373 psSHP->
pabyRec + nOffset + i * 16 + 8,
2376 if( bBigEndian ) SwapWord( 8, psShape->
padfX + i );
2377 if( bBigEndian ) SwapWord( 8, psShape->
padfY + i );
2380 nOffset += 16*nPoints;
2390 memcpy( &(psShape->
dfZMax), psSHP->
pabyRec + nOffset + 8, 8 );
2392 if( bBigEndian ) SwapWord( 8, &(psShape->
dfZMin) );
2393 if( bBigEndian ) SwapWord( 8, &(psShape->
dfZMax) );
2395 for( i = 0; (
int32)i < nPoints; i++ )
2397 memcpy( psShape->
padfZ + i,
2398 psSHP->
pabyRec + nOffset + 16 + i*8, 8 );
2399 if( bBigEndian ) SwapWord( 8, psShape->
padfZ + i );
2402 nOffset += 16 + 8*nPoints;
2415 if( nEntitySize >= (
int)(nOffset + 16 + 8*nPoints) )
2418 memcpy( &(psShape->
dfMMax), psSHP->
pabyRec + nOffset + 8, 8 );
2420 if( bBigEndian ) SwapWord( 8, &(psShape->
dfMMin) );
2421 if( bBigEndian ) SwapWord( 8, &(psShape->
dfMMax) );
2423 for( i = 0; (
int32)i < nPoints; i++ )
2425 memcpy( psShape->
padfM + i,
2426 psSHP->
pabyRec + nOffset + 16 + i*8, 8 );
2427 if( bBigEndian ) SwapWord( 8, psShape->
padfM + i );
2446 unsigned char* pBuffer =
NULL;
2447 unsigned char** ppBuffer =
NULL;
2449 if ( 44 + 4 > nEntitySize )
2451 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2452 "Corrupted .shp file : shape %d : nEntitySize = %d",
2453 hEntity, nEntitySize);
2458 memcpy( &nPoints, psSHP->
pabyRec + 44, 4 );
2460 if( bBigEndian ) SwapWord( 4, &nPoints );
2463 if ( nPoints > 50 * 1000 * 1000)
2465 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2466 "Corrupted .shp file : shape %d : nPoints = %d",
2473 nRequiredSize = 48 + nPoints * 16;
2476 nRequiredSize += 16 + nPoints * 8;
2478 if (nRequiredSize > nEntitySize)
2480 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2481 "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d",
2482 hEntity, nPoints, nEntitySize);
2490 int nObjectBufSize = 4 *
sizeof(double) * nPoints;
2491 pBuffer = SHPReallocObjectBufIfNecessary(psSHP, nObjectBufSize);
2492 ppBuffer = &pBuffer;
2497 psShape->
padfX = (
double *) SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints);
2498 psShape->
padfY = (
double *) SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints);
2499 psShape->
padfZ = (
double *) SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints);
2500 psShape->
padfM = (
double *) SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints);
2507 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2508 "Not enough memory to allocate requested memory (nPoints=%d) for shape %d. " 2509 "Probably broken SHP file", hEntity, nPoints );
2515 for( i = 0; (
int32)i < nPoints; i++ )
2517 memcpy(psShape->
padfX+i, psSHP->
pabyRec + 48 + 16 * i, 8 );
2518 memcpy(psShape->
padfY+i, psSHP->
pabyRec + 48 + 16 * i + 8, 8 );
2520 if( bBigEndian ) SwapWord( 8, psShape->
padfX + i );
2521 if( bBigEndian ) SwapWord( 8, psShape->
padfY + i );
2524 nOffset = 48 + 16*nPoints;
2534 if( bBigEndian ) SwapWord( 8, &(psShape->
dfXMin) );
2535 if( bBigEndian ) SwapWord( 8, &(psShape->
dfYMin) );
2536 if( bBigEndian ) SwapWord( 8, &(psShape->
dfXMax) );
2537 if( bBigEndian ) SwapWord( 8, &(psShape->
dfYMax) );
2545 memcpy( &(psShape->
dfZMax), psSHP->
pabyRec + nOffset + 8, 8 );
2547 if( bBigEndian ) SwapWord( 8, &(psShape->
dfZMin) );
2548 if( bBigEndian ) SwapWord( 8, &(psShape->
dfZMax) );
2550 for( i = 0; (
int32)i < nPoints; i++ )
2552 memcpy( psShape->
padfZ + i,
2553 psSHP->
pabyRec + nOffset + 16 + i*8, 8 );
2554 if( bBigEndian ) SwapWord( 8, psShape->
padfZ + i );
2557 nOffset += 16 + 8*nPoints;
2568 if( nEntitySize >= (
int)(nOffset + 16 + 8*nPoints) )
2571 memcpy( &(psShape->
dfMMax), psSHP->
pabyRec + nOffset + 8, 8 );
2573 if( bBigEndian ) SwapWord( 8, &(psShape->
dfMMin) );
2574 if( bBigEndian ) SwapWord( 8, &(psShape->
dfMMax) );
2576 for( i = 0; (
int32)i < nPoints; i++ )
2578 memcpy( psShape->
padfM + i,
2579 psSHP->
pabyRec + nOffset + 16 + i*8, 8 );
2580 if( bBigEndian ) SwapWord( 8, psShape->
padfM + i );
2604 psShape->
padfZ[0] = 0.0;
2605 psShape->
padfM[0] = 0.0;
2609 psShape->
padfX = (
double *) calloc(1,
sizeof(
double));
2610 psShape->
padfY = (
double *) calloc(1,
sizeof(
double));
2611 psShape->
padfZ = (
double *) calloc(1,
sizeof(
double));
2612 psShape->
padfM = (
double *) calloc(1,
sizeof(
double));
2617 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2618 "Corrupted .shp file : shape %d : nEntitySize = %d",
2619 hEntity, nEntitySize);
2627 if( bBigEndian ) SwapWord( 8, psShape->
padfX );
2628 if( bBigEndian ) SwapWord( 8, psShape->
padfY );
2639 if( bBigEndian ) SwapWord( 8, psShape->
padfZ );
2650 if( nEntitySize >= nOffset + 8 )
2654 if( bBigEndian ) SwapWord( 8, psShape->
padfM );
2694 return "MultiPoint";
2706 return "MultiPointZ";
2718 return "MultiPointM";
2721 return "MultiPatch";
2724 return "UnknownShapeType";
2739 return "TriangleStrip";
2742 return "TriangleFan";
2757 return "UnknownPartType";
2769 if( psShape ==
NULL )
2806 int iOpRing, bAltered = 0;
2822 for( iOpRing = 0; iOpRing < psObject->
nParts; iOpRing++ )
2824 int bInner, iVert, nVertCount, nVertStart, iCheckRing;
2825 double dfSum, dfTestX, dfTestY;
2845 for( iCheckRing = 0; iCheckRing < psObject->
nParts; iCheckRing++ )
2849 if( iCheckRing == iOpRing )
2854 if( iCheckRing == psObject->
nParts-1 )
2861 for( iEdge = 0; iEdge < nVertCount; iEdge++ )
2865 if( iEdge < nVertCount-1 )
2874 if ( ( psObject->
padfY[iEdge+nVertStart] < dfTestY
2875 && dfTestY <= psObject->padfY[iNext+nVertStart] )
2876 || ( psObject->
padfY[iNext+nVertStart] < dfTestY
2877 && dfTestY <= psObject->
padfY[iEdge+nVertStart] ) )
2882 double const intersect =
2883 ( psObject->
padfX[iEdge+nVertStart]
2884 + ( dfTestY - psObject->
padfY[iEdge+nVertStart] )
2885 / ( psObject->
padfY[iNext+nVertStart] - psObject->
padfY[iEdge+nVertStart] )
2886 * ( psObject->
padfX[iNext+nVertStart] - psObject->
padfX[iEdge+nVertStart] ) );
2888 if (intersect < dfTestX)
2902 if( iOpRing == psObject->
nParts-1 )
2911 dfSum = psObject->
padfX[nVertStart] * (psObject->
padfY[nVertStart+1] - psObject->
padfY[nVertStart+nVertCount-1]);
2912 for( iVert = nVertStart + 1; iVert < nVertStart+nVertCount-1; iVert++ )
2914 dfSum += psObject->
padfX[iVert] * (psObject->
padfY[iVert+1] - psObject->
padfY[iVert-1]);
2917 dfSum += psObject->
padfX[iVert] * (psObject->
padfY[nVertStart] - psObject->
padfY[iVert-1]);
2922 if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
2927 for( i = 0; i < nVertCount/2; i++ )
2932 dfSaved = psObject->
padfX[nVertStart+i];
2933 psObject->
padfX[nVertStart+i] =
2934 psObject->
padfX[nVertStart+nVertCount-i-1];
2935 psObject->
padfX[nVertStart+nVertCount-i-1] = dfSaved;
2938 dfSaved = psObject->
padfY[nVertStart+i];
2939 psObject->
padfY[nVertStart+i] =
2940 psObject->
padfY[nVertStart+nVertCount-i-1];
2941 psObject->
padfY[nVertStart+nVertCount-i-1] = dfSaved;
2944 if( psObject->
padfZ )
2946 dfSaved = psObject->
padfZ[nVertStart+i];
2947 psObject->
padfZ[nVertStart+i] =
2948 psObject->
padfZ[nVertStart+nVertCount-i-1];
2949 psObject->
padfZ[nVertStart+nVertCount-i-1] = dfSaved;
2953 if( psObject->
padfM )
2955 dfSaved = psObject->
padfM[nVertStart+i];
2956 psObject->
padfM[nVertStart+i] =
2957 psObject->
padfM[nVertStart+nVertCount-i-1];
2958 psObject->
padfM[nVertStart+nVertCount-i-1] = dfSaved;
SAOffset(* FTell)(SAFile file)
SHPObject SHPAPI_CALL1 * SHPCreateObject(int nSHPType, int nShapeId, int nParts, const int *panPartStart, const int *panPartType, int nVertices, const double *padfX, const double *padfY, const double *padfZ, const double *padfM){ SHPObject *psObject;int i, bHasM, bHasZ;psObject=(SHPObject *) calloc(1, sizeof(SHPObject)
void SHPAPI_CALL SHPSetFastModeReadObject(SHPHandle hSHP, int bFastMode)
SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, SAHooks *psHooks)
int(* FFlush)(SAFile file)
SHPHandle SHPAPI_CALL SHPOpen(const char *pszLayer, const char *pszAccess)
void SHPAPI_CALL SHPGetInfo(SHPHandle psSHP, int *pnEntities, int *pnShapeType, double *padfMinBound, double *padfMaxBound)
void SHPAPI_CALL SHPDestroyObject(SHPObject *psShape)
SHPHandle SHPAPI_CALL SHPOpenLLEx(const char *pszLayer, const char *pszAccess, SAHooks *psHooks, int bRestoreSHX)
SAOffset(* FSeek)(SAFile file, SAOffset offset, int whence)
void SHPAPI_CALL SHPComputeExtents(SHPObject *psObject)
unsigned int * panRecOffset
int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject *psObject)
void SASetupDefaultHooks(SAHooks *psHooks)
#define assert(condition)
SAOffset(* FWrite)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
const char SHPAPI_CALL1 * SHPTypeName(int nSHPType){ switch(nSHPType
SHPObject SHPAPI_CALL1 * SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX, const double *padfY, const double *padfZ){ return(SHPCreateObject(nSHPType, -1, 0, NULL, NULL, nVertices, padfX, padfY, padfZ, NULL)
SAFile(* FOpen)(const char *filename, const char *access)
SHPObject * psCachedObject
SHPHandle SHPAPI_CALL SHPCreate(const char *pszLayer, int nShapeType)
void(* Error)(const char *message)
int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess, SAHooks *psHooks)
#define SHP_CVSID(string)
SHPObject SHPAPI_CALL1 * SHPReadObject(SHPHandle psSHP, int hEntity){ int nEntitySize, nRequiredSize;SHPObject *psShape;char szErrorMsg[128];int nSHPType;int nBytesRead;if(hEntity< 0||hEntity >=psSHP->nRecords) return(NULL
#define ByteCopy(a, b, c)
int SHPAPI_CALL SHPRewindObject(CPL_UNUSED SHPHandle hSHP, SHPObject *psObject)
#define DISABLE_MULTIPATCH_MEASURE
void SHPAPI_CALL SHPClose(SHPHandle psSHP)
void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP)
unsigned int * panRecSize
unsigned char * pabyObjectBuf
const char SHPAPI_CALL1 * SHPPartTypeName(int nPartType){ switch(nPartType
SAOffset(* FRead)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
int(* FClose)(SAFile file)
SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, SAHooks *psHooks)