321 #if UINT_MAX == 65535
322 typedef unsigned long int32;
332 #define ByteCopy( a, b, c ) memcpy( b, a, c )
334 # define MIN(a,b) ((a<b) ? a : b)
335 # define MAX(a,b) ((a>b) ? a : b)
339 #if defined(_MSC_VER)
341 # define snprintf _snprintf
343 #elif defined(WIN32) || defined(_WIN32)
345 # define snprintf _snprintf
351 #if defined(__GNUC__) && __GNUC__ >= 4
352 # define CPL_UNUSED __attribute((__unused__))
359 #define bBigEndian FALSE
360 #elif defined(CPL_MSB)
361 #define bBigEndian TRUE
367 #define STATIC_CAST(type,x) static_cast<type>(x)
368 #define SHPLIB_NULLPTR nullptr
370 #define STATIC_CAST(type,x) ((type)(x))
371 #define SHPLIB_NULLPTR NULL
386 for( i=0; i < length/2; i++ )
405 return malloc(nNewSize);
407 return realloc(pMem,nNewSize);
420 uchar abyHeader[100] = { 0 };
428 psSHP->
sHooks.
Error(
"SHPWriteHeader failed : SHX file is closed");
452 ByteCopy( &dValue, abyHeader+36, 8 );
456 ByteCopy( &dValue, abyHeader+44, 8 );
460 ByteCopy( &dValue, abyHeader+52, 8 );
464 ByteCopy( &dValue, abyHeader+60, 8 );
468 ByteCopy( &dValue, abyHeader+68, 8 );
472 ByteCopy( &dValue, abyHeader+76, 8 );
476 ByteCopy( &dValue, abyHeader+84, 8 );
480 ByteCopy( &dValue, abyHeader+92, 8 );
489 char szErrorMsg[200];
491 snprintf( szErrorMsg,
sizeof(szErrorMsg),
492 "Failure writing .shp header: %s", strerror(errno) );
493 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
508 char szErrorMsg[200];
510 snprintf( szErrorMsg,
sizeof(szErrorMsg),
511 "Failure writing .shx header: %s", strerror(errno) );
512 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
528 for( i = 0; i < psSHP->
nRecords; i++ )
539 char szErrorMsg[200];
541 snprintf( szErrorMsg,
sizeof(szErrorMsg),
542 "Failure writing .shx contents: %s", strerror(errno) );
543 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
561 SHPOpen(
const char * pszLayer,
const char * pszAccess )
568 return SHPOpenLL( pszLayer, pszAccess, &sHooks );
580 i > 0 && pszBasename[i] !=
'/' && pszBasename[i] !=
'\\';
583 if( pszBasename[i] ==
'.' )
608 int bLazySHXLoading =
FALSE;
609 int nLenWithoutExtension;
616 if( strcmp(pszAccess,
"rb+") == 0 || strcmp(pszAccess,
"r+b") == 0
617 || strcmp(pszAccess,
"r+") == 0 )
628 #if !defined(bBigEndian)
630 if( *((
uchar *) &i) == 1 )
649 pszFullname =
STATIC_CAST(
char *, malloc(nLenWithoutExtension + 5));
650 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
651 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
655 memcpy(pszFullname + nLenWithoutExtension,
".SHP", 5);
661 size_t nMessageLen = strlen(pszFullname)*2+256;
662 char *pszMessage =
STATIC_CAST(
char *, malloc(nMessageLen));
663 pszFullname[nLenWithoutExtension] = 0;
664 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shp or %s.SHP.",
665 pszFullname, pszFullname );
666 psHooks->
Error( pszMessage );
675 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
679 memcpy(pszFullname + nLenWithoutExtension,
".SHX", 5);
685 size_t nMessageLen = strlen(pszFullname)*2+256;
686 char *pszMessage =
STATIC_CAST(
char *, malloc(nMessageLen));
687 pszFullname[nLenWithoutExtension] = 0;
688 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shx or %s.SHX. "
689 "Set SHAPE_RESTORE_SHX config option to YES to restore or "
690 "create it.", pszFullname, pszFullname );
691 psHooks->
Error( pszMessage );
708 psSHP->
sHooks.
Error(
".shp file is unreadable, or corrupt." );
718 (pabyBuf[26]<<8)|pabyBuf[27];
730 || pabyBuf[2] != 0x27
731 || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
733 psSHP->
sHooks.
Error(
".shx file is unreadable, or corrupt." );
742 psSHP->
nRecords = pabyBuf[27]|(pabyBuf[26]<<8)|(pabyBuf[25]<<16)|
743 ((pabyBuf[24] & 0x7F)<<24);
750 char szErrorMsg[200];
752 snprintf( szErrorMsg,
sizeof(szErrorMsg),
753 "Record count in .shp header is %d, which seems\n"
754 "unreasonable. Assuming header is corrupt.",
756 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
768 if( psSHP->
nRecords >= 1024 * 1024 )
773 if( nFileSize > 100 &&
785 memcpy( &dValue, pabyBuf+36, 8 );
789 memcpy( &dValue, pabyBuf+44, 8 );
793 memcpy( &dValue, pabyBuf+52, 8 );
797 memcpy( &dValue, pabyBuf+60, 8 );
801 memcpy( &dValue, pabyBuf+68, 8 );
805 memcpy( &dValue, pabyBuf+76, 8 );
809 memcpy( &dValue, pabyBuf+84, 8 );
813 memcpy( &dValue, pabyBuf+92, 8 );
828 if( bLazySHXLoading )
837 char szErrorMsg[200];
839 snprintf( szErrorMsg,
sizeof(szErrorMsg),
840 "Not enough memory to allocate requested memory (nRecords=%d).\n"
841 "Probably broken SHP file",
843 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
849 if (pabyBuf) free( pabyBuf );
854 if( bLazySHXLoading )
865 char szErrorMsg[200];
867 snprintf( szErrorMsg,
sizeof(szErrorMsg),
868 "Failed to read all values for %d records in .shx file: %s.",
870 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
885 if (strcmp(pszAccess,
"rb") == 0)
891 for( i = 0; i < psSHP->
nRecords; i++ )
893 unsigned int nOffset, nLength;
895 memcpy( &nOffset, pabyBuf + i * 8, 4 );
898 memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
904 snprintf( str,
sizeof(str),
905 "Invalid offset for entity %d", i);
906 str[
sizeof(str)-1] =
'\0';
913 if( nLength >
STATIC_CAST(
unsigned int, INT_MAX / 2 - 4) )
916 snprintf( str,
sizeof(str),
917 "Invalid length for entity %d", i);
918 str[
sizeof(str)-1] =
'\0';
946 if ( !bRestoreSHX )
return SHPOpenLL ( pszLayer, pszAccess, psHooks );
951 return SHPOpenLL ( pszLayer, pszAccess, psHooks );
974 int nLenWithoutExtension;
975 unsigned int nSHPFilesize;
977 unsigned int nCurrentRecordOffset = 0;
978 unsigned int nCurrentSHPOffset = 100;
979 size_t nRealSHXContentSize = 100;
981 const char pszSHXAccess[] =
"w+b";
983 char abyReadedRecord[8];
984 unsigned int niRecord = 0;
985 unsigned int nRecordLength = 0;
986 unsigned int nRecordOffset = 50;
993 if( strcmp(pszAccess,
"rb+") == 0 || strcmp(pszAccess,
"r+b") == 0
994 || strcmp(pszAccess,
"r+") == 0 )
1004 #if !defined(bBigEndian)
1007 if( *((
uchar *) &i) == 1 )
1019 pszFullname =
STATIC_CAST(
char *, malloc(nLenWithoutExtension + 5));
1020 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
1021 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
1022 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
1025 memcpy(pszFullname + nLenWithoutExtension,
".SHP", 5);
1026 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
1031 size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
1032 char* pszMessage =
STATIC_CAST(
char *, malloc( nMessageLen ));
1034 pszFullname[nLenWithoutExtension] = 0;
1035 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shp or %s.SHP.",
1036 pszFullname, pszFullname );
1037 psHooks->
Error( pszMessage );
1040 free( pszFullname );
1049 psHooks->
FRead( pabyBuf, 100, 1, fpSHP );
1051 nSHPFilesize = (
STATIC_CAST(
unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
1052 (pabyBuf[26]<<8)|pabyBuf[27];
1053 if( nSHPFilesize < UINT_MAX / 2 )
1056 nSHPFilesize = (UINT_MAX / 2) * 2;
1058 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
1059 fpSHX = psHooks->
FOpen( pszFullname, pszSHXAccess );
1062 memcpy(pszFullname + nLenWithoutExtension,
".SHX", 5);
1063 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
1068 size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
1069 char* pszMessage =
STATIC_CAST(
char *, malloc( nMessageLen ));
1070 pszFullname[nLenWithoutExtension] = 0;
1071 snprintf( pszMessage, nMessageLen,
1072 "Error opening file %s.shx or %s.SHX for writing",
1073 pszFullname, pszFullname );
1074 psHooks->
Error( pszMessage );
1077 psHooks->
FClose( fpSHX );
1080 free( pszFullname );
1088 psHooks->
FSeek( fpSHP, 100, 0 );
1089 pabySHXHeader =
STATIC_CAST(
char *, malloc ( 100 ));
1090 memcpy( pabySHXHeader, pabyBuf, 100 );
1091 psHooks->
FWrite( pabySHXHeader, 100, 1, fpSHX );
1093 while( nCurrentSHPOffset < nSHPFilesize )
1095 if( psHooks->
FRead( &niRecord, 4, 1, fpSHP ) == 1 &&
1096 psHooks->
FRead( &nRecordLength, 4, 1, fpSHP ) == 1)
1099 memcpy( abyReadedRecord, &nRecordOffset, 4 );
1100 memcpy( abyReadedRecord + 4, &nRecordLength, 4 );
1102 psHooks->
FWrite( abyReadedRecord, 8, 1, fpSHX );
1106 nRecordOffset += nRecordLength + 4;
1107 nCurrentRecordOffset += 8;
1108 nCurrentSHPOffset += 8 + nRecordLength * 2;
1110 psHooks->
FSeek( fpSHP, nCurrentSHPOffset, 0 );
1111 nRealSHXContentSize += 8;
1115 psHooks->
Error(
"Error parsing .shp to restore .shx" );
1117 psHooks->
FClose( fpSHX );
1118 psHooks->
FClose( fpSHP );
1120 free( pabySHXHeader );
1121 free( pszFullname );
1127 nRealSHXContentSize /= 2;
1129 psHooks->
FSeek( fpSHX, 24, 0 );
1130 psHooks->
FWrite( &nRealSHXContentSize, 4, 1, fpSHX );
1132 psHooks->
FClose( fpSHP );
1133 psHooks->
FClose( fpSHX );
1136 free ( pszFullname );
1137 free ( pabySHXHeader );
1218 double * padfMinBound,
double * padfMaxBound )
1232 for( i = 0; i < 4; i++ )
1256 return SHPCreateLL( pszLayer, nShapeType, &sHooks );
1273 uchar abyHeader[100];
1276 int nLenWithoutExtension;
1281 #if !defined(bBigEndian)
1284 if( *((
uchar *) &i) == 1 )
1295 pszFullname =
STATIC_CAST(
char *, malloc(nLenWithoutExtension + 5));
1296 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
1297 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
1298 fpSHP = psHooks->
FOpen(pszFullname,
"wb" );
1301 char szErrorMsg[200];
1302 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1303 "Failed to create file %s: %s",
1304 pszFullname, strerror(errno) );
1305 psHooks->
Error( szErrorMsg );
1310 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
1311 fpSHX = psHooks->
FOpen(pszFullname,
"wb" );
1314 char szErrorMsg[200];
1315 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1316 "Failed to create file %s: %s",
1317 pszFullname, strerror(errno) );
1318 psHooks->
Error( szErrorMsg );
1327 memset( abyHeader, 0,
sizeof(abyHeader) );
1329 abyHeader[2] = 0x27;
1330 abyHeader[3] = 0x0a;
1345 ByteCopy( &dValue, abyHeader+36, 8 );
1346 ByteCopy( &dValue, abyHeader+44, 8 );
1347 ByteCopy( &dValue, abyHeader+52, 8 );
1348 ByteCopy( &dValue, abyHeader+60, 8 );
1353 if( psHooks->
FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
1355 char szErrorMsg[200];
1357 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1358 "Failed to write .shp header: %s", strerror(errno) );
1359 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1360 psHooks->
Error( szErrorMsg );
1372 if( psHooks->
FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
1374 char szErrorMsg[200];
1376 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1377 "Failure writing .shx header: %s", strerror(errno) );
1378 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1379 psHooks->
Error( szErrorMsg );
1387 psHooks->
FClose( fpSHP );
1388 psHooks->
FClose( fpSHX );
1390 return(
SHPOpenLL( pszLayer,
"r+b", psHooks ) );
1393 if (pszFullname) free(pszFullname);
1394 if (fpSHP) psHooks->
FClose( fpSHP );
1395 if (fpSHX) psHooks->
FClose( fpSHX );
1447 for( i = 0; i < psObject->
nVertices; i++ )
1470 const
int * panPartStart, const
int * panPartType,
1471 int nVertices, const
double *padfX, const
double *padfY,
1472 const
double * padfZ, const
double * padfM )
1476 int i, bHasM, bHasZ;
1521 calloc(
sizeof(
int), psObject->
nParts));
1523 malloc(
sizeof(
int) * psObject->
nParts));
1528 for( i = 0; i < nParts; i++ )
1548 size_t nSize =
sizeof(double) * nVertices;
1550 calloc(
sizeof(
double),nVertices));
1552 calloc(
sizeof(
double),nVertices));
1554 calloc(
sizeof(
double),nVertices));
1556 calloc(
sizeof(
double),nVertices));
1558 memcpy(psObject->
padfX, padfX, nSize);
1560 memcpy(psObject->
padfY, padfY, nSize);
1562 memcpy(psObject->
padfZ, padfZ, nSize);
1565 memcpy(psObject->
padfM, padfM, nSize);
1588 const
double * padfX, const
double * padfY,
1589 const
double * padfZ )
1607 unsigned int nRecordOffset, nRecordSize=0;
1611 int bAppendToLastRecord =
FALSE;
1612 int bAppendToFile =
FALSE;
1628 assert( nShapeId == -1
1629 || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
1631 if( nShapeId != -1 && nShapeId >= psSHP->
nRecords )
1640 unsigned int* panRecOffsetNew;
1641 unsigned int* panRecSizeNew;
1662 + psObject->
nParts * 8 + 128));
1677 int32 nPoints, nParts;
1680 nParts = psObject->
nParts;
1687 ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
1688 ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
1697 for( i = 0; i < psObject->
nParts; i++ )
1708 memcpy( pabyRec + nRecordSize, psObject->
panPartType,
1710 for( i = 0; i < psObject->
nParts; i++ )
1720 for( i = 0; i < psObject->
nVertices; i++ )
1723 ByteCopy( psObject->
padfY + i, pabyRec + nRecordSize + 8, 8 );
1726 SwapWord( 8, pabyRec + nRecordSize );
1729 SwapWord( 8, pabyRec + nRecordSize + 8 );
1731 nRecordSize += 2 * 8;
1749 for( i = 0; i < psObject->
nVertices; i++ )
1777 for( i = 0; i < psObject->
nVertices; i++ )
1800 ByteCopy( &nPoints, pabyRec + 44, 4 );
1802 for( i = 0; i < psObject->
nVertices; i++ )
1805 ByteCopy( psObject->
padfY + i, pabyRec + 48 + i*16 + 8, 8 );
1811 nRecordSize = 48 + 16 * psObject->
nVertices;
1823 for( i = 0; i < psObject->
nVertices; i++ )
1843 for( i = 0; i < psObject->
nVertices; i++ )
1909 bAppendToLastRecord =
TRUE;
1911 else if( nShapeId == -1 || psSHP->
panRecSize[nShapeId] < nRecordSize-8 )
1913 if( psSHP->
nFileSize > UINT_MAX - nRecordSize)
1916 snprintf( str,
sizeof(str),
"Failed to write shape object. "
1917 "File size cannot reach %u + %u.",
1919 str[
sizeof(str)-1] =
'\0';
1925 bAppendToFile =
TRUE;
1936 i32 = (nShapeId < 0) ? psSHP->
nRecords+1 : nShapeId+1;
1940 i32 = (nRecordSize-8)/2;
1953 char szErrorMsg[200];
1955 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1956 "Error in psSHP->sHooks.FSeek() while writing object to .shp file: %s",
1958 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1966 char szErrorMsg[200];
1968 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1969 "Error in psSHP->sHooks.FWrite() while writing object of %u bytes to .shp file: %s",
1970 nRecordSize, strerror(errno) );
1971 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1980 if( bAppendToLastRecord )
1984 else if( bAppendToFile )
1986 if( nShapeId == -1 )
2018 for( i = 0; i < psObject->
nVertices; i++ )
2024 if( psObject->
padfZ )
2029 if( psObject->
padfM )
2045 unsigned char* pRet;
2048 return calloc(1, nSize);
2054 (*pBuffer) += nSize;
2063 int nObjectBufSize )
2065 unsigned char* pBuffer;
2066 if( nObjectBufSize == 0 )
2068 nObjectBufSize = 4 *
sizeof(double);
2095 int nEntitySize, nRequiredSize;
2097 char szErrorMsg[128];
2104 if( hEntity < 0 || hEntity >= psSHP->nRecords )
2110 if( psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX !=
SHPLIB_NULLPTR )
2112 unsigned int nOffset, nLength;
2114 if( psSHP->sHooks.FSeek( psSHP->fpSHX, 100 + 8 * hEntity, 0 ) != 0 ||
2115 psSHP->sHooks.FRead( &nOffset, 1, 4, psSHP->fpSHX ) != 4 ||
2116 psSHP->sHooks.FRead( &nLength, 1, 4, psSHP->fpSHX ) != 4 )
2119 snprintf( str,
sizeof(str),
2120 "Error in fseek()/fread() reading object from .shx file at offset %d",
2122 str[
sizeof(str)-1] =
'\0';
2124 psSHP->sHooks.Error( str );
2130 if( nOffset >
STATIC_CAST(
unsigned int, INT_MAX) )
2133 snprintf( str,
sizeof(str),
2134 "Invalid offset for entity %d", hEntity);
2135 str[
sizeof(str)-1] =
'\0';
2137 psSHP->sHooks.Error( str );
2140 if( nLength >
STATIC_CAST(
unsigned int, INT_MAX / 2 - 4) )
2143 snprintf( str,
sizeof(str),
2144 "Invalid length for entity %d", hEntity);
2145 str[
sizeof(str)-1] =
'\0';
2147 psSHP->sHooks.Error( str );
2151 psSHP->panRecOffset[hEntity] = nOffset*2;
2152 psSHP->panRecSize[hEntity] = nLength*2;
2158 nEntitySize = psSHP->panRecSize[hEntity]+8;
2159 if( nEntitySize > psSHP->nBufSize )
2162 int nNewBufSize = nEntitySize;
2163 if( nNewBufSize < INT_MAX - nNewBufSize / 3 )
2164 nNewBufSize += nNewBufSize / 3;
2166 nNewBufSize = INT_MAX;
2171 if( nNewBufSize >= 10 * 1024 * 1024 )
2173 if( psSHP->nBufSize < 10 * 1024 * 1024 )
2176 psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 2 );
2177 nFileSize = psSHP->sHooks.FTell(psSHP->fpSHP);
2178 if( nFileSize >= UINT_MAX )
2179 psSHP->nFileSize = UINT_MAX;
2181 psSHP->nFileSize =
STATIC_CAST(
unsigned int, nFileSize);
2184 if( psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
2189 psSHP->panRecSize[hEntity] > psSHP->nFileSize - psSHP->panRecOffset[hEntity] )
2192 snprintf( str,
sizeof(str),
2193 "Error in fread() reading object of size %d at offset %u from .shp file",
2194 nEntitySize, psSHP->panRecOffset[hEntity] );
2195 str[
sizeof(str)-1] =
'\0';
2197 psSHP->sHooks.Error( str );
2205 snprintf( szErrorMsg,
sizeof(szErrorMsg),
2206 "Not enough memory to allocate requested memory (nNewBufSize=%d). "
2207 "Probably broken SHP file", nNewBufSize);
2208 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2209 psSHP->sHooks.Error( szErrorMsg );
2214 psSHP->pabyRec = pabyRecNew;
2215 psSHP->nBufSize = nNewBufSize;
2227 if( psSHP->sHooks.FSeek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 )
2234 snprintf( str,
sizeof(str),
2235 "Error in fseek() reading object from .shp file at offset %u",
2236 psSHP->panRecOffset[hEntity]);
2237 str[
sizeof(str)-1] =
'\0';
2239 psSHP->sHooks.Error( str );
2243 nBytesRead =
STATIC_CAST(
int, psSHP->sHooks.FRead( psSHP->pabyRec, 1, nEntitySize, psSHP->fpSHP ));
2251 if( nBytesRead >= 8 && nBytesRead == nEntitySize - 8 )
2254 int nSHPContentLength;
2255 memcpy( &nSHPContentLength, psSHP->pabyRec + 4, 4 );
2257 if( nSHPContentLength < 0 ||
2258 nSHPContentLength > INT_MAX / 2 - 4 ||
2259 2 * nSHPContentLength + 8 != nBytesRead )
2262 snprintf( str,
sizeof(str),
2263 "Sanity check failed when trying to recover from inconsistent .shx/.shp with shape %d",
2265 str[
sizeof(str)-1] =
'\0';
2267 psSHP->sHooks.Error( str );
2271 else if( nBytesRead != nEntitySize )
2278 snprintf( str,
sizeof(str),
2279 "Error in fread() reading object of size %d at offset %u from .shp file",
2280 nEntitySize, psSHP->panRecOffset[hEntity] );
2281 str[
sizeof(str)-1] =
'\0';
2283 psSHP->sHooks.Error( str );
2287 if ( 8 + 4 > nEntitySize )
2289 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2290 "Corrupted .shp file : shape %d : nEntitySize = %d",
2291 hEntity, nEntitySize);
2292 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2293 psSHP->sHooks.Error( szErrorMsg );
2296 memcpy( &nSHPType, psSHP->pabyRec + 8, 4 );
2303 if( psSHP->bFastModeReadObject )
2305 if( psSHP->psCachedObject->bFastModeReadObject )
2307 psSHP->sHooks.Error(
"Invalid read pattern in fast read mode. "
2308 "SHPDestroyObject() should be called." );
2312 psShape = psSHP->psCachedObject;
2332 int32 nPoints, nParts;
2337 if ( 40 + 8 + 4 > nEntitySize )
2339 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2340 "Corrupted .shp file : shape %d : nEntitySize = %d",
2341 hEntity, nEntitySize);
2342 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2343 psSHP->sHooks.Error( szErrorMsg );
2350 memcpy( &(psShape->
dfXMin), psSHP->pabyRec + 8 + 4, 8 );
2351 memcpy( &(psShape->
dfYMin), psSHP->pabyRec + 8 + 12, 8 );
2352 memcpy( &(psShape->
dfXMax), psSHP->pabyRec + 8 + 20, 8 );
2353 memcpy( &(psShape->
dfYMax), psSHP->pabyRec + 8 + 28, 8 );
2364 memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
2365 memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
2372 nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
2374 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2375 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u.",
2376 hEntity, nPoints, nParts);
2377 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2378 psSHP->sHooks.Error( szErrorMsg );
2386 nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
2391 nRequiredSize += 16 + 8 * nPoints;
2395 nRequiredSize += 4 * nParts;
2397 if (nRequiredSize > nEntitySize)
2399 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2400 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, nEntitySize=%d.",
2401 hEntity, nPoints, nParts, nEntitySize);
2402 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2403 psSHP->sHooks.Error( szErrorMsg );
2410 int nObjectBufSize = 4 *
sizeof(double) * nPoints + 2 *
sizeof(
int) * nParts;
2412 ppBuffer = &pBuffer;
2421 psShape->
nParts = nParts;
2432 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2433 "Not enough memory to allocate requested memory (nPoints=%u, nParts=%u) for shape %d. "
2434 "Probably broken SHP file", nPoints, nParts, hEntity );
2435 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2436 psSHP->sHooks.Error( szErrorMsg );
2447 memcpy( psShape->
panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
2458 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2459 "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
2461 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2462 psSHP->sHooks.Error( szErrorMsg );
2468 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2469 "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
2471 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2472 psSHP->sHooks.Error( szErrorMsg );
2478 nOffset = 44 + 8 + 4*nParts;
2485 memcpy( psShape->
panPartType, psSHP->pabyRec + nOffset, 4*nParts );
2491 nOffset += 4*nParts;
2499 memcpy(psShape->
padfX + i,
2500 psSHP->pabyRec + nOffset + i * 16,
2503 memcpy(psShape->
padfY + i,
2504 psSHP->pabyRec + nOffset + i * 16 + 8,
2511 nOffset += 16*nPoints;
2520 memcpy( &(psShape->
dfZMin), psSHP->pabyRec + nOffset, 8 );
2521 memcpy( &(psShape->
dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
2528 memcpy( psShape->
padfZ + i,
2529 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2533 nOffset += 16 + 8*nPoints;
2546 if( nEntitySize >=
STATIC_CAST(
int, nOffset + 16 + 8*nPoints) )
2548 memcpy( &(psShape->
dfMMin), psSHP->pabyRec + nOffset, 8 );
2549 memcpy( &(psShape->
dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
2556 memcpy( psShape->
padfM + i,
2557 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2580 if ( 44 + 4 > nEntitySize )
2582 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2583 "Corrupted .shp file : shape %d : nEntitySize = %d",
2584 hEntity, nEntitySize);
2585 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2586 psSHP->sHooks.Error( szErrorMsg );
2590 memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
2595 if ( nPoints > 50 * 1000 * 1000)
2597 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2598 "Corrupted .shp file : shape %d : nPoints = %u",
2600 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2601 psSHP->sHooks.Error( szErrorMsg );
2606 nRequiredSize = 48 + nPoints * 16;
2609 nRequiredSize += 16 + nPoints * 8;
2611 if (nRequiredSize > nEntitySize)
2613 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2614 "Corrupted .shp file : shape %d : nPoints = %u, nEntitySize = %d",
2615 hEntity, nPoints, nEntitySize);
2616 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2617 psSHP->sHooks.Error( szErrorMsg );
2624 int nObjectBufSize = 4 *
sizeof(double) * nPoints;
2626 ppBuffer = &pBuffer;
2641 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2642 "Not enough memory to allocate requested memory (nPoints=%u) for shape %d. "
2643 "Probably broken SHP file", nPoints, hEntity );
2644 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2645 psSHP->sHooks.Error( szErrorMsg );
2652 memcpy(psShape->
padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
2653 memcpy(psShape->
padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
2659 nOffset = 48 + 16*nPoints;
2664 memcpy( &(psShape->
dfXMin), psSHP->pabyRec + 8 + 4, 8 );
2665 memcpy( &(psShape->
dfYMin), psSHP->pabyRec + 8 + 12, 8 );
2666 memcpy( &(psShape->
dfXMax), psSHP->pabyRec + 8 + 20, 8 );
2667 memcpy( &(psShape->
dfYMax), psSHP->pabyRec + 8 + 28, 8 );
2679 memcpy( &(psShape->
dfZMin), psSHP->pabyRec + nOffset, 8 );
2680 memcpy( &(psShape->
dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
2687 memcpy( psShape->
padfZ + i,
2688 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2692 nOffset += 16 + 8*nPoints;
2703 if( nEntitySize >=
STATIC_CAST(
int, nOffset + 16 + 8*nPoints) )
2705 memcpy( &(psShape->
dfMMin), psSHP->pabyRec + nOffset, 8 );
2706 memcpy( &(psShape->
dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
2713 memcpy( psShape->
padfM + i,
2714 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2739 psShape->
padfZ[0] = 0.0;
2740 psShape->
padfM[0] = 0.0;
2752 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2753 "Corrupted .shp file : shape %d : nEntitySize = %d",
2754 hEntity, nEntitySize);
2755 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2756 psSHP->sHooks.Error( szErrorMsg );
2760 memcpy( psShape->
padfX, psSHP->pabyRec + 12, 8 );
2761 memcpy( psShape->
padfY, psSHP->pabyRec + 20, 8 );
2773 memcpy( psShape->
padfZ, psSHP->pabyRec + nOffset, 8 );
2786 if( nEntitySize >= nOffset + 8 )
2788 memcpy( psShape->
padfM, psSHP->pabyRec + nOffset, 8 );
2830 return "MultiPoint";
2842 return "MultiPointZ";
2854 return "MultiPointM";
2857 return "MultiPatch";
2860 return "UnknownShapeType";
2875 return "TriangleStrip";
2878 return "TriangleFan";
2893 return "UnknownPartType";
2915 free( psShape->
padfX );
2917 free( psShape->
padfY );
2919 free( psShape->
padfZ );
2921 free( psShape->
padfM );
2937 if( iPart == psObject->
nParts-1 )
2962 const int iOpRingStart = psObject->
panPartStart[iOpRing];
2963 double dfTestX = ( psObject->
padfX[iOpRingStart] +
2964 psObject->
padfX[iOpRingStart + 1] ) / 2;
2965 double dfTestY = ( psObject->
padfY[iOpRingStart] +
2966 psObject->
padfY[iOpRingStart + 1] ) / 2;
2970 for( iCheckRing = 0; iCheckRing < psObject->
nParts; iCheckRing++ )
2972 int nVertStartCheck, nVertCountCheck;
2975 if( iCheckRing == iOpRing )
2981 for( iEdge = 0; iEdge < nVertCountCheck; iEdge++ )
2985 if( iEdge < nVertCountCheck-1 )
2995 if ( ( psObject->
padfY[iEdge+nVertStartCheck] < dfTestY
2996 && dfTestY <= psObject->padfY[iNext+nVertStartCheck] )
2997 || ( psObject->
padfY[iNext+nVertStartCheck] < dfTestY
2998 && dfTestY <= psObject->padfY[iEdge+nVertStartCheck] ) )
3004 double const intersect =
3005 ( psObject->
padfX[iEdge+nVertStartCheck]
3006 + ( dfTestY - psObject->
padfY[iEdge+nVertStartCheck] )
3007 / ( psObject->
padfY[iNext+nVertStartCheck] -
3008 psObject->
padfY[iEdge+nVertStartCheck] )
3009 * ( psObject->
padfX[iNext+nVertStartCheck] -
3010 psObject->
padfX[iEdge+nVertStartCheck] ) );
3012 if (intersect < dfTestX)
3033 int iOpRing, bAltered = 0;
3049 for( iOpRing = 0; iOpRing < psObject->
nParts; iOpRing++ )
3051 int bInner, iVert, nVertCount, nVertStart;
3067 dfSum = psObject->
padfX[nVertStart] *
3068 (psObject->
padfY[nVertStart+1] -
3069 psObject->
padfY[nVertStart+nVertCount-1]);
3070 for( iVert = nVertStart + 1; iVert < nVertStart+nVertCount-1; iVert++ )
3072 dfSum += psObject->
padfX[iVert] * (psObject->
padfY[iVert+1] -
3073 psObject->
padfY[iVert-1]);
3076 dfSum += psObject->
padfX[iVert] * (psObject->
padfY[nVertStart] -
3077 psObject->
padfY[iVert-1]);
3082 if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
3087 for( i = 0; i < nVertCount/2; i++ )
3092 dfSaved = psObject->
padfX[nVertStart+i];
3093 psObject->
padfX[nVertStart+i] =
3094 psObject->
padfX[nVertStart+nVertCount-i-1];
3095 psObject->
padfX[nVertStart+nVertCount-i-1] = dfSaved;
3098 dfSaved = psObject->
padfY[nVertStart+i];
3099 psObject->
padfY[nVertStart+i] =
3100 psObject->
padfY[nVertStart+nVertCount-i-1];
3101 psObject->
padfY[nVertStart+nVertCount-i-1] = dfSaved;
3104 if( psObject->
padfZ )
3106 dfSaved = psObject->
padfZ[nVertStart+i];
3107 psObject->
padfZ[nVertStart+i] =
3108 psObject->
padfZ[nVertStart+nVertCount-i-1];
3109 psObject->
padfZ[nVertStart+nVertCount-i-1] = dfSaved;
3113 if( psObject->
padfM )
3115 dfSaved = psObject->
padfM[nVertStart+i];
3116 psObject->
padfM[nVertStart+i] =
3117 psObject->
padfM[nVertStart+nVertCount-i-1];
3118 psObject->
padfM[nVertStart+nVertCount-i-1] = dfSaved;
void SASetupDefaultHooks(SAHooks *psHooks)
#define SHP_CVSID(string)
#define DISABLE_MULTIPATCH_MEASURE
static unsigned char * SHPReallocObjectBufIfNecessary(SHPHandle psSHP, int nObjectBufSize)
SHPHandle SHPOpenLLEx(const char *pszLayer, const char *pszAccess, SAHooks *psHooks, int bRestoreSHX)
SHPObject * SHPReadObject(SHPHandle psSHP, int hEntity)
SHPObject * SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX, const double *padfY, const double *padfZ)
SHPObject * 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)
void SHPClose(SHPHandle psSHP)
SHPHandle SHPCreateLL(const char *pszLayer, int nShapeType, SAHooks *psHooks)
int SHPRestoreSHX(const char *pszLayer, const char *pszAccess, SAHooks *psHooks)
SHPHandle SHPOpenLL(const char *pszLayer, const char *pszAccess, SAHooks *psHooks)
void SHPWriteHeader(SHPHandle psSHP)
void SHPDestroyObject(SHPObject *psShape)
static void SwapWord(int length, void *wordP)
void SHPGetInfo(SHPHandle psSHP, int *pnEntities, int *pnShapeType, double *padfMinBound, double *padfMaxBound)
static int SHPGetLenWithoutExtension(const char *pszBasename)
#define STATIC_CAST(type, x)
const char * SHPPartTypeName(int nPartType)
static int SHPGetPartVertexCount(const SHPObject *psObject, int iPart)
SHPHandle SHPOpen(const char *pszLayer, const char *pszAccess)
int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject *psObject)
static void * SHPAllocBuffer(unsigned char **pBuffer, int nSize)
static void * SfRealloc(void *pMem, int nNewSize)
static void _SHPSetBounds(uchar *pabyRec, SHPObject *psShape)
void SHPSetFastModeReadObject(SHPHandle hSHP, int bFastMode)
void SHPComputeExtents(SHPObject *psObject)
static int SHPRewindIsInnerRing(const SHPObject *psObject, int iOpRing)
#define ByteCopy(a, b, c)
SHPHandle SHPCreate(const char *pszLayer, int nShapeType)
const char * SHPTypeName(int nSHPType)
int SHPRewindObject(SHPHandle hSHP, SHPObject *psObject)
void(* Error)(const char *message)
SAFile(* FOpen)(const char *filename, const char *access)
SAOffset(* FTell)(SAFile file)
int(* FFlush)(SAFile file)
SAOffset(* FWrite)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
int(* FClose)(SAFile file)
SAOffset(* FRead)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
SAOffset(* FSeek)(SAFile file, SAOffset offset, int whence)
SHPObject * psCachedObject
unsigned int * panRecSize
unsigned char * pabyObjectBuf
unsigned int * panRecOffset