52 typedef unsigned long int32;
62 #define ByteCopy( a, b, c ) memcpy( b, a, c )
64 # define MIN(a,b) ((a<b) ? a : b)
65 # define MAX(a,b) ((a>b) ? a : b)
71 # define snprintf _snprintf
73 #elif defined(WIN32) || defined(_WIN32)
75 # define snprintf _snprintf
81 #if defined(__GNUC__) && __GNUC__ >= 4
82 # define CPL_UNUSED __attribute((__unused__))
89 #define bBigEndian FALSE
90 #elif defined(CPL_MSB)
91 #define bBigEndian TRUE
97 #define STATIC_CAST(type,x) static_cast<type>(x)
98 #define SHPLIB_NULLPTR nullptr
100 #define STATIC_CAST(type,x) ((type)(x))
101 #define SHPLIB_NULLPTR NULL
116 for( i=0; i < length/2; i++ )
137 return realloc(pMem,nNewSize);
150 uchar abyHeader[100] = { 0 };
158 psSHP->
sHooks.
Error(
"SHPWriteHeader failed : SHX file is closed");
182 ByteCopy( &dValue, abyHeader+36, 8 );
186 ByteCopy( &dValue, abyHeader+44, 8 );
190 ByteCopy( &dValue, abyHeader+52, 8 );
194 ByteCopy( &dValue, abyHeader+60, 8 );
198 ByteCopy( &dValue, abyHeader+68, 8 );
202 ByteCopy( &dValue, abyHeader+76, 8 );
206 ByteCopy( &dValue, abyHeader+84, 8 );
210 ByteCopy( &dValue, abyHeader+92, 8 );
219 char szErrorMsg[200];
221 snprintf( szErrorMsg,
sizeof(szErrorMsg),
222 "Failure writing .shp header: %s", strerror(errno) );
223 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
238 char szErrorMsg[200];
240 snprintf( szErrorMsg,
sizeof(szErrorMsg),
241 "Failure writing .shx header: %s", strerror(errno) );
242 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
258 for( i = 0; i < psSHP->
nRecords; i++ )
269 char szErrorMsg[200];
271 snprintf( szErrorMsg,
sizeof(szErrorMsg),
272 "Failure writing .shx contents: %s", strerror(errno) );
273 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
291 SHPOpen(
const char * pszLayer,
const char * pszAccess )
298 return SHPOpenLL( pszLayer, pszAccess, &sHooks );
310 i > 0 && pszBasename[i] !=
'/' && pszBasename[i] !=
'\\';
313 if( pszBasename[i] ==
'.' )
338 int bLazySHXLoading =
FALSE;
339 int nLenWithoutExtension;
346 if( strcmp(pszAccess,
"rb+") == 0 || strcmp(pszAccess,
"r+b") == 0
347 || strcmp(pszAccess,
"r+") == 0 )
358 #if !defined(bBigEndian)
360 if( *((
uchar *) &i) == 1 )
380 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
381 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
385 memcpy(pszFullname + nLenWithoutExtension,
".SHP", 5);
391 size_t nMessageLen = strlen(pszFullname)*2+256;
393 pszFullname[nLenWithoutExtension] = 0;
394 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shp or %s.SHP.",
395 pszFullname, pszFullname );
396 psHooks->
Error( pszMessage );
405 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
409 memcpy(pszFullname + nLenWithoutExtension,
".SHX", 5);
415 size_t nMessageLen = strlen(pszFullname)*2+256;
417 pszFullname[nLenWithoutExtension] = 0;
418 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shx or %s.SHX. "
419 "Set SHAPE_RESTORE_SHX config option to YES to restore or "
420 "create it.", pszFullname, pszFullname );
421 psHooks->
Error( pszMessage );
438 psSHP->
sHooks.
Error(
".shp file is unreadable, or corrupt." );
448 (pabyBuf[26]<<8)|pabyBuf[27];
460 || pabyBuf[2] != 0x27
461 || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
463 psSHP->
sHooks.
Error(
".shx file is unreadable, or corrupt." );
472 psSHP->
nRecords = pabyBuf[27]|(pabyBuf[26]<<8)|(pabyBuf[25]<<16)|
473 ((pabyBuf[24] & 0x7F)<<24);
480 char szErrorMsg[200];
482 snprintf( szErrorMsg,
sizeof(szErrorMsg),
483 "Record count in .shp header is %d, which seems\n"
484 "unreasonable. Assuming header is corrupt.",
486 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
498 if( psSHP->
nRecords >= 1024 * 1024 )
503 if( nFileSize > 100 &&
515 memcpy( &dValue, pabyBuf+36, 8 );
519 memcpy( &dValue, pabyBuf+44, 8 );
523 memcpy( &dValue, pabyBuf+52, 8 );
527 memcpy( &dValue, pabyBuf+60, 8 );
531 memcpy( &dValue, pabyBuf+68, 8 );
535 memcpy( &dValue, pabyBuf+76, 8 );
539 memcpy( &dValue, pabyBuf+84, 8 );
543 memcpy( &dValue, pabyBuf+92, 8 );
558 if( bLazySHXLoading )
567 char szErrorMsg[200];
569 snprintf( szErrorMsg,
sizeof(szErrorMsg),
570 "Not enough memory to allocate requested memory (nRecords=%d).\n"
571 "Probably broken SHP file",
573 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
579 if (pabyBuf)
free( pabyBuf );
584 if( bLazySHXLoading )
595 char szErrorMsg[200];
597 snprintf( szErrorMsg,
sizeof(szErrorMsg),
598 "Failed to read all values for %d records in .shx file: %s.",
600 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
615 if (strcmp(pszAccess,
"rb") == 0)
621 for( i = 0; i < psSHP->
nRecords; i++ )
623 unsigned int nOffset, nLength;
625 memcpy( &nOffset, pabyBuf + i * 8, 4 );
628 memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
634 snprintf(
str,
sizeof(
str),
635 "Invalid offset for entity %d", i);
636 str[
sizeof(
str)-1] =
'\0';
643 if( nLength >
STATIC_CAST(
unsigned int, INT_MAX / 2 - 4) )
646 snprintf(
str,
sizeof(
str),
647 "Invalid length for entity %d", i);
648 str[
sizeof(
str)-1] =
'\0';
676 if ( !bRestoreSHX )
return SHPOpenLL ( pszLayer, pszAccess, psHooks );
681 return SHPOpenLL ( pszLayer, pszAccess, psHooks );
704 int nLenWithoutExtension;
705 unsigned int nSHPFilesize;
707 unsigned int nCurrentSHPOffset = 100;
708 size_t nRealSHXContentSize = 100;
710 const char pszSHXAccess[] =
"w+b";
712 char abyReadedRecord[8];
713 unsigned int niRecord = 0;
714 unsigned int nRecordLength = 0;
715 unsigned int nRecordOffset = 50;
722 if( strcmp(pszAccess,
"rb+") == 0 || strcmp(pszAccess,
"r+b") == 0
723 || strcmp(pszAccess,
"r+") == 0 )
733 #if !defined(bBigEndian)
736 if( *((
uchar *) &i) == 1 )
749 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
750 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
751 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
754 memcpy(pszFullname + nLenWithoutExtension,
".SHP", 5);
755 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
760 size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
763 pszFullname[nLenWithoutExtension] = 0;
764 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shp or %s.SHP.",
765 pszFullname, pszFullname );
766 psHooks->
Error( pszMessage );
778 if( psHooks->
FRead( pabyBuf, 100, 1, fpSHP ) != 1 )
780 psHooks->
Error(
".shp file is unreadable, or corrupt." );
789 nSHPFilesize = (
STATIC_CAST(
unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
790 (pabyBuf[26]<<8)|pabyBuf[27];
791 if( nSHPFilesize < UINT_MAX / 2 )
794 nSHPFilesize = (UINT_MAX / 2) * 2;
796 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
797 fpSHX = psHooks->
FOpen( pszFullname, pszSHXAccess );
800 size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
802 pszFullname[nLenWithoutExtension] = 0;
803 snprintf( pszMessage, nMessageLen,
804 "Error opening file %s.shx for writing", pszFullname );
805 psHooks->
Error( pszMessage );
819 psHooks->
FSeek( fpSHP, 100, 0 );
821 memcpy( pabySHXHeader, pabyBuf, 100 );
822 psHooks->
FWrite( pabySHXHeader, 100, 1, fpSHX );
825 while( nCurrentSHPOffset < nSHPFilesize )
827 if( psHooks->
FRead( &niRecord, 4, 1, fpSHP ) == 1 &&
828 psHooks->
FRead( &nRecordLength, 4, 1, fpSHP ) == 1)
831 memcpy( abyReadedRecord, &nRecordOffset, 4 );
832 memcpy( abyReadedRecord + 4, &nRecordLength, 4 );
834 psHooks->
FWrite( abyReadedRecord, 8, 1, fpSHX );
838 nRecordOffset += nRecordLength + 4;
839 nCurrentSHPOffset += 8 + nRecordLength * 2;
841 psHooks->
FSeek( fpSHP, nCurrentSHPOffset, 0 );
842 nRealSHXContentSize += 8;
846 psHooks->
Error(
"Error parsing .shp to restore .shx" );
851 free( pabySHXHeader );
858 nRealSHXContentSize /= 2;
860 psHooks->
FSeek( fpSHX, 24, 0 );
861 psHooks->
FWrite( &nRealSHXContentSize, 4, 1, fpSHX );
866 free ( pszFullname );
867 free ( pabySHXHeader );
948 double * padfMinBound,
double * padfMaxBound )
962 for( i = 0; i < 4; i++ )
986 return SHPCreateLL( pszLayer, nShapeType, &sHooks );
1003 uchar abyHeader[100];
1006 int nLenWithoutExtension;
1011 #if !defined(bBigEndian)
1014 if( *((
uchar *) &i) == 1 )
1026 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
1027 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
1028 fpSHP = psHooks->
FOpen(pszFullname,
"wb" );
1031 char szErrorMsg[200];
1032 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1033 "Failed to create file %s: %s",
1034 pszFullname, strerror(errno) );
1035 psHooks->
Error( szErrorMsg );
1040 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
1041 fpSHX = psHooks->
FOpen(pszFullname,
"wb" );
1044 char szErrorMsg[200];
1045 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1046 "Failed to create file %s: %s",
1047 pszFullname, strerror(errno) );
1048 psHooks->
Error( szErrorMsg );
1057 memset( abyHeader, 0,
sizeof(abyHeader) );
1059 abyHeader[2] = 0x27;
1060 abyHeader[3] = 0x0a;
1075 ByteCopy( &dValue, abyHeader+36, 8 );
1076 ByteCopy( &dValue, abyHeader+44, 8 );
1077 ByteCopy( &dValue, abyHeader+52, 8 );
1078 ByteCopy( &dValue, abyHeader+60, 8 );
1083 if( psHooks->
FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
1085 char szErrorMsg[200];
1087 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1088 "Failed to write .shp header: %s", strerror(errno) );
1089 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1090 psHooks->
Error( szErrorMsg );
1102 if( psHooks->
FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
1104 char szErrorMsg[200];
1106 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1107 "Failure writing .shx header: %s", strerror(errno) );
1108 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1109 psHooks->
Error( szErrorMsg );
1117 psHooks->
FClose( fpSHP );
1118 psHooks->
FClose( fpSHX );
1120 return(
SHPOpenLL( pszLayer,
"r+b", psHooks ) );
1123 if (pszFullname)
free(pszFullname);
1124 if (fpSHP) psHooks->
FClose( fpSHP );
1125 if (fpSHX) psHooks->
FClose( fpSHX );
1177 for( i = 0; i < psObject->
nVertices; i++ )
1200 const
int * panPartStart, const
int * panPartType,
1201 int nVertices, const
double *padfX, const
double *padfY,
1202 const
double * padfZ, const
double * padfM )
1206 int i, bHasM,
bHasZ;
1251 calloc(
sizeof(
int), psObject->
nParts));
1258 for( i = 0; i < nParts; i++ )
1278 size_t nSize =
sizeof(double) *
nVertices;
1288 memcpy(psObject->
padfX, padfX, nSize);
1290 memcpy(psObject->
padfY, padfY, nSize);
1292 memcpy(psObject->
padfZ, padfZ, nSize);
1295 memcpy(psObject->
padfM, padfM, nSize);
1318 const
double * padfX, const
double * padfY,
1319 const
double * padfZ )
1338 unsigned int nRecordSize=0;
1342 int bAppendToLastRecord =
FALSE;
1343 int bAppendToFile =
FALSE;
1360 || (
nShapeId >= 0 && nShapeId < psSHP->nRecords) );
1371 unsigned int* panRecOffsetNew;
1372 unsigned int* panRecSizeNew;
1393 + psObject->
nParts * 8 + 128));
1408 int32 nPoints, nParts;
1411 nParts = psObject->
nParts;
1418 ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
1419 ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
1428 for( i = 0; i < psObject->
nParts; i++ )
1439 memcpy( pabyRec + nRecordSize, psObject->
panPartType,
1441 for( i = 0; i < psObject->
nParts; i++ )
1451 for( i = 0; i < psObject->
nVertices; i++ )
1454 ByteCopy( psObject->
padfY + i, pabyRec + nRecordSize + 8, 8 );
1457 SwapWord( 8, pabyRec + nRecordSize );
1460 SwapWord( 8, pabyRec + nRecordSize + 8 );
1462 nRecordSize += 2 * 8;
1480 for( i = 0; i < psObject->
nVertices; i++ )
1508 for( i = 0; i < psObject->
nVertices; i++ )
1531 ByteCopy( &nPoints, pabyRec + 44, 4 );
1533 for( i = 0; i < psObject->
nVertices; i++ )
1536 ByteCopy( psObject->
padfY + i, pabyRec + 48 + i*16 + 8, 8 );
1542 nRecordSize = 48 + 16 * psObject->
nVertices;
1554 for( i = 0; i < psObject->
nVertices; i++ )
1574 for( i = 0; i < psObject->
nVertices; i++ )
1640 bAppendToLastRecord =
TRUE;
1644 if( psSHP->
nFileSize > UINT_MAX - nRecordSize)
1647 snprintf(
str,
sizeof(
str),
"Failed to write shape object. "
1648 "File size cannot reach %u + %u.",
1650 str[
sizeof(
str)-1] =
'\0';
1656 bAppendToFile =
TRUE;
1671 i32 = (nRecordSize-8)/2;
1691 char szErrorMsg[200];
1693 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1694 "Error in psSHP->sHooks.FSeek() while writing object to .shp file: %s",
1696 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1705 char szErrorMsg[200];
1707 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1708 "Error in psSHP->sHooks.FWrite() while writing object of %u bytes to .shp file: %s",
1709 nRecordSize, strerror(errno) );
1710 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1719 if( bAppendToLastRecord )
1723 else if( bAppendToFile )
1757 for( i = 0; i < psObject->
nVertices; i++ )
1763 if( psObject->
padfZ )
1768 if( psObject->
padfM )
1784 unsigned char* pRet;
1787 return calloc(1, nSize);
1793 (*pBuffer) += nSize;
1802 int nObjectBufSize )
1804 unsigned char* pBuffer;
1805 if( nObjectBufSize == 0 )
1807 nObjectBufSize = 4 *
sizeof(double);
1836 char szErrorMsg[160];
1843 if( hEntity < 0 || hEntity >= psSHP->nRecords )
1849 if( psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX !=
SHPLIB_NULLPTR )
1851 unsigned int nOffset, nLength;
1853 if( psSHP->sHooks.FSeek( psSHP->fpSHX, 100 + 8 * hEntity, 0 ) != 0 ||
1854 psSHP->sHooks.FRead( &nOffset, 1, 4, psSHP->fpSHX ) != 4 ||
1855 psSHP->sHooks.FRead( &nLength, 1, 4, psSHP->fpSHX ) != 4 )
1858 snprintf(
str,
sizeof(
str),
1859 "Error in fseek()/fread() reading object from .shx file at offset %d",
1861 str[
sizeof(
str)-1] =
'\0';
1863 psSHP->sHooks.Error(
str );
1869 if( nOffset >
STATIC_CAST(
unsigned int, INT_MAX) )
1872 snprintf(
str,
sizeof(
str),
1873 "Invalid offset for entity %d", hEntity);
1874 str[
sizeof(
str)-1] =
'\0';
1876 psSHP->sHooks.Error(
str );
1879 if( nLength >
STATIC_CAST(
unsigned int, INT_MAX / 2 - 4) )
1882 snprintf(
str,
sizeof(
str),
1883 "Invalid length for entity %d", hEntity);
1884 str[
sizeof(
str)-1] =
'\0';
1886 psSHP->sHooks.Error(
str );
1890 psSHP->panRecOffset[hEntity] = nOffset*2;
1891 psSHP->panRecSize[hEntity] = nLength*2;
1902 if( nNewBufSize < INT_MAX - nNewBufSize / 3 )
1903 nNewBufSize += nNewBufSize / 3;
1905 nNewBufSize = INT_MAX;
1910 if( nNewBufSize >= 10 * 1024 * 1024 )
1912 if( psSHP->nBufSize < 10 * 1024 * 1024 )
1915 psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 2 );
1916 nFileSize = psSHP->sHooks.FTell(psSHP->fpSHP);
1917 if( nFileSize >= UINT_MAX )
1918 psSHP->nFileSize = UINT_MAX;
1920 psSHP->nFileSize =
STATIC_CAST(
unsigned int, nFileSize);
1923 if( psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
1928 psSHP->panRecSize[hEntity] > psSHP->nFileSize - psSHP->panRecOffset[hEntity] )
1931 snprintf(
str,
sizeof(
str),
1932 "Error in fread() reading object of size %d at offset %u from .shp file",
1934 str[
sizeof(
str)-1] =
'\0';
1936 psSHP->sHooks.Error(
str );
1944 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1945 "Not enough memory to allocate requested memory (nNewBufSize=%d). "
1946 "Probably broken SHP file", nNewBufSize);
1947 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1948 psSHP->sHooks.Error( szErrorMsg );
1953 psSHP->pabyRec = pabyRecNew;
1954 psSHP->nBufSize = nNewBufSize;
1966 if( psSHP->sHooks.FSeek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 )
1973 snprintf(
str,
sizeof(
str),
1974 "Error in fseek() reading object from .shp file at offset %u",
1975 psSHP->panRecOffset[hEntity]);
1976 str[
sizeof(
str)-1] =
'\0';
1978 psSHP->sHooks.Error(
str );
1993 int nSHPContentLength;
1994 memcpy( &nSHPContentLength, psSHP->pabyRec + 4, 4 );
1996 if( nSHPContentLength < 0 ||
1997 nSHPContentLength > INT_MAX / 2 - 4 ||
2001 snprintf(
str,
sizeof(
str),
2002 "Sanity check failed when trying to recover from inconsistent .shx/.shp with shape %d",
2004 str[
sizeof(
str)-1] =
'\0';
2006 psSHP->sHooks.Error(
str );
2017 snprintf(
str,
sizeof(
str),
2018 "Error in fread() reading object of size %d at offset %u from .shp file",
2020 str[
sizeof(
str)-1] =
'\0';
2022 psSHP->sHooks.Error(
str );
2028 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2029 "Corrupted .shp file : shape %d : nEntitySize = %d",
2031 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2032 psSHP->sHooks.Error( szErrorMsg );
2035 memcpy( &
nSHPType, psSHP->pabyRec + 8, 4 );
2042 if( psSHP->bFastModeReadObject )
2044 if( psSHP->psCachedObject->bFastModeReadObject )
2046 psSHP->sHooks.Error(
"Invalid read pattern in fast read mode. "
2047 "SHPDestroyObject() should be called." );
2051 psShape = psSHP->psCachedObject;
2059 psShape->bFastModeReadObject = psSHP->bFastModeReadObject;
2071 int32 nPoints, nParts;
2078 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2079 "Corrupted .shp file : shape %d : nEntitySize = %d",
2081 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2082 psSHP->sHooks.Error( szErrorMsg );
2089 memcpy( &(
psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
2090 memcpy( &(
psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
2091 memcpy( &(
psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
2092 memcpy( &(
psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
2103 memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
2104 memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
2111 nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
2113 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2114 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u.",
2115 hEntity, nPoints, nParts);
2116 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2117 psSHP->sHooks.Error( szErrorMsg );
2125 nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
2130 nRequiredSize += 16 + 8 * nPoints;
2134 nRequiredSize += 4 * nParts;
2138 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2139 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, nEntitySize=%d.",
2141 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2142 psSHP->sHooks.Error( szErrorMsg );
2147 if(
psShape->bFastModeReadObject )
2149 int nObjectBufSize = 4 *
sizeof(double) * nPoints + 2 *
sizeof(
int) * nParts;
2151 ppBuffer = &pBuffer;
2171 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2172 "Not enough memory to allocate requested memory (nPoints=%u, nParts=%u) for shape %d. "
2173 "Probably broken SHP file", nPoints, nParts, hEntity );
2174 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2175 psSHP->sHooks.Error( szErrorMsg );
2186 memcpy(
psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
2192 if (
psShape->panPartStart[i] < 0
2197 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2198 "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
2200 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2201 psSHP->sHooks.Error( szErrorMsg );
2205 if (i > 0 &&
psShape->panPartStart[i] <=
psShape->panPartStart[i-1])
2207 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2208 "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
2209 hEntity, i,
psShape->panPartStart[i], i - 1,
psShape->panPartStart[i - 1]);
2210 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2211 psSHP->sHooks.Error( szErrorMsg );
2217 nOffset = 44 + 8 + 4*nParts;
2224 memcpy(
psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
2230 nOffset += 4*nParts;
2239 psSHP->pabyRec + nOffset + i * 16,
2243 psSHP->pabyRec + nOffset + i * 16 + 8,
2250 nOffset += 16*nPoints;
2259 memcpy( &(
psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
2260 memcpy( &(
psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
2268 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2272 nOffset += 16 + 8*nPoints;
2274 else if(
psShape->bFastModeReadObject )
2287 memcpy( &(
psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
2288 memcpy( &(
psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
2296 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2301 else if(
psShape->bFastModeReadObject )
2321 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2322 "Corrupted .shp file : shape %d : nEntitySize = %d",
2324 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2325 psSHP->sHooks.Error( szErrorMsg );
2329 memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
2334 if ( nPoints > 50 * 1000 * 1000)
2336 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2337 "Corrupted .shp file : shape %d : nPoints = %u",
2339 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2340 psSHP->sHooks.Error( szErrorMsg );
2345 nRequiredSize = 48 + nPoints * 16;
2348 nRequiredSize += 16 + nPoints * 8;
2352 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2353 "Corrupted .shp file : shape %d : nPoints = %u, nEntitySize = %d",
2355 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2356 psSHP->sHooks.Error( szErrorMsg );
2361 if(
psShape->bFastModeReadObject )
2363 int nObjectBufSize = 4 *
sizeof(double) * nPoints;
2365 ppBuffer = &pBuffer;
2380 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2381 "Not enough memory to allocate requested memory (nPoints=%u) for shape %d. "
2382 "Probably broken SHP file", nPoints, hEntity );
2383 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2384 psSHP->sHooks.Error( szErrorMsg );
2391 memcpy(
psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
2392 memcpy(
psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
2398 nOffset = 48 + 16*nPoints;
2403 memcpy( &(
psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
2404 memcpy( &(
psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
2405 memcpy( &(
psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
2406 memcpy( &(
psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
2418 memcpy( &(
psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
2419 memcpy( &(
psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
2427 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2431 nOffset += 16 + 8*nPoints;
2433 else if(
psShape->bFastModeReadObject )
2444 memcpy( &(
psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
2445 memcpy( &(
psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
2453 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2458 else if(
psShape->bFastModeReadObject )
2472 if(
psShape->bFastModeReadObject )
2491 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2492 "Corrupted .shp file : shape %d : nEntitySize = %d",
2494 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2495 psSHP->sHooks.Error( szErrorMsg );
2499 memcpy(
psShape->padfX, psSHP->pabyRec + 12, 8 );
2500 memcpy(
psShape->padfY, psSHP->pabyRec + 20, 8 );
2512 memcpy(
psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
2527 memcpy(
psShape->padfM, psSHP->pabyRec + nOffset, 8 );
2569 return "MultiPoint";
2581 return "MultiPointZ";
2593 return "MultiPointM";
2596 return "MultiPatch";
2599 return "UnknownShapeType";
2614 return "TriangleStrip";
2617 return "TriangleFan";
2632 return "UnknownPartType";
2647 if(
psShape->bFastModeReadObject )
2676 if( iPart == psObject->
nParts-1 )
2689 double dfTestX,
double dfTestY )
2702 for( iCheckRing = 0; iCheckRing < psObject->
nParts; iCheckRing++ )
2704 int nVertStartCheck, nVertCountCheck;
2707 if( iCheckRing == iOpRing )
2713 for( iEdge = 0; iEdge < nVertCountCheck; iEdge++ )
2717 if( iEdge < nVertCountCheck-1 )
2727 if ( ( psObject->
padfY[iEdge+nVertStartCheck] < dfTestY
2728 && dfTestY <= psObject->padfY[iNext+nVertStartCheck] )
2729 || ( psObject->
padfY[iNext+nVertStartCheck] < dfTestY
2730 && dfTestY <= psObject->padfY[iEdge+nVertStartCheck] ) )
2736 double const intersect =
2737 ( psObject->
padfX[iEdge+nVertStartCheck]
2738 + ( dfTestY - psObject->
padfY[iEdge+nVertStartCheck] )
2739 / ( psObject->
padfY[iNext+nVertStartCheck] -
2740 psObject->
padfY[iEdge+nVertStartCheck] )
2741 * ( psObject->
padfX[iNext+nVertStartCheck] -
2742 psObject->
padfX[iEdge+nVertStartCheck] ) );
2744 if (intersect < dfTestX)
2748 else if( intersect == dfTestX )
2770 int iOpRing, bAltered = 0;
2786 for( iOpRing = 0; iOpRing < psObject->
nParts; iOpRing++ )
2792 const int nVertStart = psObject->
panPartStart[iOpRing];
2798 for( iVert = nVertStart; iVert + 1 < nVertStart + nVertCount; ++iVert )
2803 const double dfTestX = ( psObject->
padfX[iVert] +
2804 psObject->
padfX[iVert + 1] ) / 2;
2805 const double dfTestY = ( psObject->
padfY[iVert] +
2806 psObject->
padfY[iVert + 1] ) / 2;
2823 dfSum = psObject->
padfX[nVertStart] *
2824 (psObject->
padfY[nVertStart+1] -
2825 psObject->
padfY[nVertStart+nVertCount-1]);
2826 for( iVert = nVertStart + 1; iVert < nVertStart+nVertCount-1; iVert++ )
2828 dfSum += psObject->
padfX[iVert] * (psObject->
padfY[iVert+1] -
2829 psObject->
padfY[iVert-1]);
2832 dfSum += psObject->
padfX[iVert] * (psObject->
padfY[nVertStart] -
2833 psObject->
padfY[iVert-1]);
2838 if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
2843 for( i = 0; i < nVertCount/2; i++ )
2848 dfSaved = psObject->
padfX[nVertStart+i];
2849 psObject->
padfX[nVertStart+i] =
2850 psObject->
padfX[nVertStart+nVertCount-i-1];
2851 psObject->
padfX[nVertStart+nVertCount-i-1] = dfSaved;
2854 dfSaved = psObject->
padfY[nVertStart+i];
2855 psObject->
padfY[nVertStart+i] =
2856 psObject->
padfY[nVertStart+nVertCount-i-1];
2857 psObject->
padfY[nVertStart+nVertCount-i-1] = dfSaved;
2860 if( psObject->
padfZ )
2862 dfSaved = psObject->
padfZ[nVertStart+i];
2863 psObject->
padfZ[nVertStart+i] =
2864 psObject->
padfZ[nVertStart+nVertCount-i-1];
2865 psObject->
padfZ[nVertStart+nVertCount-i-1] = dfSaved;
2869 if( psObject->
padfM )
2871 dfSaved = psObject->
padfM[nVertStart+i];
2872 psObject->
padfM[nVertStart+i] =
2873 psObject->
padfM[nVertStart+nVertCount-i-1];
2874 psObject->
padfM[nVertStart+nVertCount-i-1] = dfSaved;
void SASetupDefaultHooks(SAHooks *psHooks)
#define DISABLE_MULTIPATCH_MEASURE
static unsigned char * SHPReallocObjectBufIfNecessary(SHPHandle psSHP, int nObjectBufSize)
SHPHandle SHPAPI_CALL SHPOpen(const char *pszLayer, const char *pszAccess)
SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, SAHooks *psHooks)
SHPHandle SHPAPI_CALL SHPCreate(const char *pszLayer, int nShapeType)
void SHPAPI_CALL SHPSetFastModeReadObject(SHPHandle hSHP, int bFastMode)
SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, SAHooks *psHooks)
void SHPAPI_CALL SHPComputeExtents(SHPObject *psObject)
SHPObject SHPAPI_CALL1 * SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX, const double *padfY, const double *padfZ){ return(SHPCreateObject(nSHPType, -1, 0, SHPLIB_NULLPTR, SHPLIB_NULLPTR, nVertices, padfX, padfY, padfZ, SHPLIB_NULLPTR)
static void SwapWord(int length, void *wordP)
void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP)
static int SHPGetLenWithoutExtension(const char *pszBasename)
void SHPAPI_CALL SHPClose(SHPHandle psSHP)
void SHPAPI_CALL SHPGetInfo(SHPHandle psSHP, int *pnEntities, int *pnShapeType, double *padfMinBound, double *padfMaxBound)
#define STATIC_CAST(type, x)
int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess, SAHooks *psHooks)
static int SHPGetPartVertexCount(const SHPObject *psObject, int iPart)
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=STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject))
SHPObject SHPAPI_CALL1 * SHPReadObject(SHPHandle psSHP, int hEntity){ int nEntitySize, nRequiredSize;SHPObject *psShape;char szErrorMsg[160];int nSHPType;int nBytesRead;if(hEntity< 0||hEntity >=psSHP->nRecords) return SHPLIB_NULLPTR;if(psSHP->panRecOffset[hEntity]==0 &&psSHP->fpSHX !=SHPLIB_NULLPTR
int SHPAPI_CALL SHPRewindObject(CPL_UNUSED SHPHandle hSHP, SHPObject *psObject)
void SHPAPI_CALL SHPDestroyObject(SHPObject *psShape)
static void * SHPAllocBuffer(unsigned char **pBuffer, int nSize)
static void * SfRealloc(void *pMem, int nNewSize)
static void _SHPSetBounds(uchar *pabyRec, SHPObject *psShape)
int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject *psObject)
#define ByteCopy(a, b, c)
SHPHandle SHPAPI_CALL SHPOpenLLEx(const char *pszLayer, const char *pszAccess, SAHooks *psHooks, int bRestoreSHX)
const char SHPAPI_CALL1 * SHPPartTypeName(int nPartType){ switch(nPartType
static int SHPRewindIsInnerRing(const SHPObject *psObject, int iOpRing, double dfTestX, double dfTestY)
const char SHPAPI_CALL1 * SHPTypeName(int nSHPType){ switch(nSHPType
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