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 nCurrentRecordOffset = 0;
708 unsigned int nCurrentSHPOffset = 100;
709 size_t nRealSHXContentSize = 100;
711 const char pszSHXAccess[] =
"w+b";
713 char abyReadedRecord[8];
714 unsigned int niRecord = 0;
715 unsigned int nRecordLength = 0;
716 unsigned int nRecordOffset = 50;
723 if( strcmp(pszAccess,
"rb+") == 0 || strcmp(pszAccess,
"r+b") == 0
724 || strcmp(pszAccess,
"r+") == 0 )
734 #if !defined(bBigEndian)
737 if( *((
uchar *) &i) == 1 )
750 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
751 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
752 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
755 memcpy(pszFullname + nLenWithoutExtension,
".SHP", 5);
756 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
761 size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
764 pszFullname[nLenWithoutExtension] = 0;
765 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shp or %s.SHP.",
766 pszFullname, pszFullname );
767 psHooks->
Error( pszMessage );
779 if( psHooks->
FRead( pabyBuf, 100, 1, fpSHP ) != 1 )
781 psHooks->
Error(
".shp file is unreadable, or corrupt." );
790 nSHPFilesize = (
STATIC_CAST(
unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
791 (pabyBuf[26]<<8)|pabyBuf[27];
792 if( nSHPFilesize < UINT_MAX / 2 )
795 nSHPFilesize = (UINT_MAX / 2) * 2;
797 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
798 fpSHX = psHooks->
FOpen( pszFullname, pszSHXAccess );
801 size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
803 pszFullname[nLenWithoutExtension] = 0;
804 snprintf( pszMessage, nMessageLen,
805 "Error opening file %s.shx for writing", pszFullname );
806 psHooks->
Error( pszMessage );
820 psHooks->
FSeek( fpSHP, 100, 0 );
822 memcpy( pabySHXHeader, pabyBuf, 100 );
823 psHooks->
FWrite( pabySHXHeader, 100, 1, fpSHX );
826 while( nCurrentSHPOffset < nSHPFilesize )
828 if( psHooks->
FRead( &niRecord, 4, 1, fpSHP ) == 1 &&
829 psHooks->
FRead( &nRecordLength, 4, 1, fpSHP ) == 1)
832 memcpy( abyReadedRecord, &nRecordOffset, 4 );
833 memcpy( abyReadedRecord + 4, &nRecordLength, 4 );
835 psHooks->
FWrite( abyReadedRecord, 8, 1, fpSHX );
839 nRecordOffset += nRecordLength + 4;
840 nCurrentRecordOffset += 8;
841 nCurrentSHPOffset += 8 + nRecordLength * 2;
843 psHooks->
FSeek( fpSHP, nCurrentSHPOffset, 0 );
844 nRealSHXContentSize += 8;
848 psHooks->
Error(
"Error parsing .shp to restore .shx" );
853 free( pabySHXHeader );
860 nRealSHXContentSize /= 2;
862 psHooks->
FSeek( fpSHX, 24, 0 );
863 psHooks->
FWrite( &nRealSHXContentSize, 4, 1, fpSHX );
868 free ( pszFullname );
869 free ( pabySHXHeader );
950 double * padfMinBound,
double * padfMaxBound )
964 for( i = 0; i < 4; i++ )
988 return SHPCreateLL( pszLayer, nShapeType, &sHooks );
1005 uchar abyHeader[100];
1008 int nLenWithoutExtension;
1013 #if !defined(bBigEndian)
1016 if( *((
uchar *) &i) == 1 )
1028 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
1029 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
1030 fpSHP = psHooks->
FOpen(pszFullname,
"wb" );
1033 char szErrorMsg[200];
1034 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1035 "Failed to create file %s: %s",
1036 pszFullname, strerror(errno) );
1037 psHooks->
Error( szErrorMsg );
1042 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
1043 fpSHX = psHooks->
FOpen(pszFullname,
"wb" );
1046 char szErrorMsg[200];
1047 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1048 "Failed to create file %s: %s",
1049 pszFullname, strerror(errno) );
1050 psHooks->
Error( szErrorMsg );
1059 memset( abyHeader, 0,
sizeof(abyHeader) );
1061 abyHeader[2] = 0x27;
1062 abyHeader[3] = 0x0a;
1077 ByteCopy( &dValue, abyHeader+36, 8 );
1078 ByteCopy( &dValue, abyHeader+44, 8 );
1079 ByteCopy( &dValue, abyHeader+52, 8 );
1080 ByteCopy( &dValue, abyHeader+60, 8 );
1085 if( psHooks->
FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
1087 char szErrorMsg[200];
1089 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1090 "Failed to write .shp header: %s", strerror(errno) );
1091 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1092 psHooks->
Error( szErrorMsg );
1104 if( psHooks->
FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
1106 char szErrorMsg[200];
1108 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1109 "Failure writing .shx header: %s", strerror(errno) );
1110 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1111 psHooks->
Error( szErrorMsg );
1119 psHooks->
FClose( fpSHP );
1120 psHooks->
FClose( fpSHX );
1122 return(
SHPOpenLL( pszLayer,
"r+b", psHooks ) );
1125 if (pszFullname)
free(pszFullname);
1126 if (fpSHP) psHooks->
FClose( fpSHP );
1127 if (fpSHX) psHooks->
FClose( fpSHX );
1179 for( i = 0; i < psObject->
nVertices; i++ )
1202 const
int * panPartStart, const
int * panPartType,
1203 int nVertices, const
double *padfX, const
double *padfY,
1204 const
double * padfZ, const
double * padfM )
1208 int i, bHasM,
bHasZ;
1253 calloc(
sizeof(
int), psObject->
nParts));
1260 for( i = 0; i < nParts; i++ )
1280 size_t nSize =
sizeof(double) *
nVertices;
1290 memcpy(psObject->
padfX, padfX, nSize);
1292 memcpy(psObject->
padfY, padfY, nSize);
1294 memcpy(psObject->
padfZ, padfZ, nSize);
1297 memcpy(psObject->
padfM, padfM, nSize);
1320 const
double * padfX, const
double * padfY,
1321 const
double * padfZ )
1340 unsigned int nRecordSize=0;
1344 int bAppendToLastRecord =
FALSE;
1345 int bAppendToFile =
FALSE;
1362 || (
nShapeId >= 0 && nShapeId < psSHP->nRecords) );
1373 unsigned int* panRecOffsetNew;
1374 unsigned int* panRecSizeNew;
1395 + psObject->
nParts * 8 + 128));
1410 int32 nPoints, nParts;
1413 nParts = psObject->
nParts;
1420 ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
1421 ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
1430 for( i = 0; i < psObject->
nParts; i++ )
1441 memcpy( pabyRec + nRecordSize, psObject->
panPartType,
1443 for( i = 0; i < psObject->
nParts; i++ )
1453 for( i = 0; i < psObject->
nVertices; i++ )
1456 ByteCopy( psObject->
padfY + i, pabyRec + nRecordSize + 8, 8 );
1459 SwapWord( 8, pabyRec + nRecordSize );
1462 SwapWord( 8, pabyRec + nRecordSize + 8 );
1464 nRecordSize += 2 * 8;
1482 for( i = 0; i < psObject->
nVertices; i++ )
1510 for( i = 0; i < psObject->
nVertices; i++ )
1533 ByteCopy( &nPoints, pabyRec + 44, 4 );
1535 for( i = 0; i < psObject->
nVertices; i++ )
1538 ByteCopy( psObject->
padfY + i, pabyRec + 48 + i*16 + 8, 8 );
1544 nRecordSize = 48 + 16 * psObject->
nVertices;
1556 for( i = 0; i < psObject->
nVertices; i++ )
1576 for( i = 0; i < psObject->
nVertices; i++ )
1642 bAppendToLastRecord =
TRUE;
1646 if( psSHP->
nFileSize > UINT_MAX - nRecordSize)
1649 snprintf(
str,
sizeof(
str),
"Failed to write shape object. "
1650 "File size cannot reach %u + %u.",
1652 str[
sizeof(
str)-1] =
'\0';
1658 bAppendToFile =
TRUE;
1673 i32 = (nRecordSize-8)/2;
1693 char szErrorMsg[200];
1695 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1696 "Error in psSHP->sHooks.FSeek() while writing object to .shp file: %s",
1698 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1707 char szErrorMsg[200];
1709 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1710 "Error in psSHP->sHooks.FWrite() while writing object of %u bytes to .shp file: %s",
1711 nRecordSize, strerror(errno) );
1712 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1721 if( bAppendToLastRecord )
1725 else if( bAppendToFile )
1759 for( i = 0; i < psObject->
nVertices; i++ )
1765 if( psObject->
padfZ )
1770 if( psObject->
padfM )
1786 unsigned char* pRet;
1789 return calloc(1, nSize);
1795 (*pBuffer) += nSize;
1804 int nObjectBufSize )
1806 unsigned char* pBuffer;
1807 if( nObjectBufSize == 0 )
1809 nObjectBufSize = 4 *
sizeof(double);
1838 char szErrorMsg[160];
1845 if( hEntity < 0 || hEntity >= psSHP->nRecords )
1851 if( psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX !=
SHPLIB_NULLPTR )
1853 unsigned int nOffset, nLength;
1855 if( psSHP->sHooks.FSeek( psSHP->fpSHX, 100 + 8 * hEntity, 0 ) != 0 ||
1856 psSHP->sHooks.FRead( &nOffset, 1, 4, psSHP->fpSHX ) != 4 ||
1857 psSHP->sHooks.FRead( &nLength, 1, 4, psSHP->fpSHX ) != 4 )
1860 snprintf(
str,
sizeof(
str),
1861 "Error in fseek()/fread() reading object from .shx file at offset %d",
1863 str[
sizeof(
str)-1] =
'\0';
1865 psSHP->sHooks.Error(
str );
1871 if( nOffset >
STATIC_CAST(
unsigned int, INT_MAX) )
1874 snprintf(
str,
sizeof(
str),
1875 "Invalid offset for entity %d", hEntity);
1876 str[
sizeof(
str)-1] =
'\0';
1878 psSHP->sHooks.Error(
str );
1881 if( nLength >
STATIC_CAST(
unsigned int, INT_MAX / 2 - 4) )
1884 snprintf(
str,
sizeof(
str),
1885 "Invalid length for entity %d", hEntity);
1886 str[
sizeof(
str)-1] =
'\0';
1888 psSHP->sHooks.Error(
str );
1892 psSHP->panRecOffset[hEntity] = nOffset*2;
1893 psSHP->panRecSize[hEntity] = nLength*2;
1904 if( nNewBufSize < INT_MAX - nNewBufSize / 3 )
1905 nNewBufSize += nNewBufSize / 3;
1907 nNewBufSize = INT_MAX;
1912 if( nNewBufSize >= 10 * 1024 * 1024 )
1914 if( psSHP->nBufSize < 10 * 1024 * 1024 )
1917 psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 2 );
1918 nFileSize = psSHP->sHooks.FTell(psSHP->fpSHP);
1919 if( nFileSize >= UINT_MAX )
1920 psSHP->nFileSize = UINT_MAX;
1922 psSHP->nFileSize =
STATIC_CAST(
unsigned int, nFileSize);
1925 if( psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
1930 psSHP->panRecSize[hEntity] > psSHP->nFileSize - psSHP->panRecOffset[hEntity] )
1933 snprintf(
str,
sizeof(
str),
1934 "Error in fread() reading object of size %d at offset %u from .shp file",
1936 str[
sizeof(
str)-1] =
'\0';
1938 psSHP->sHooks.Error(
str );
1946 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1947 "Not enough memory to allocate requested memory (nNewBufSize=%d). "
1948 "Probably broken SHP file", nNewBufSize);
1949 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1950 psSHP->sHooks.Error( szErrorMsg );
1955 psSHP->pabyRec = pabyRecNew;
1956 psSHP->nBufSize = nNewBufSize;
1968 if( psSHP->sHooks.FSeek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 )
1975 snprintf(
str,
sizeof(
str),
1976 "Error in fseek() reading object from .shp file at offset %u",
1977 psSHP->panRecOffset[hEntity]);
1978 str[
sizeof(
str)-1] =
'\0';
1980 psSHP->sHooks.Error(
str );
1995 int nSHPContentLength;
1996 memcpy( &nSHPContentLength, psSHP->pabyRec + 4, 4 );
1998 if( nSHPContentLength < 0 ||
1999 nSHPContentLength > INT_MAX / 2 - 4 ||
2003 snprintf(
str,
sizeof(
str),
2004 "Sanity check failed when trying to recover from inconsistent .shx/.shp with shape %d",
2006 str[
sizeof(
str)-1] =
'\0';
2008 psSHP->sHooks.Error(
str );
2019 snprintf(
str,
sizeof(
str),
2020 "Error in fread() reading object of size %d at offset %u from .shp file",
2022 str[
sizeof(
str)-1] =
'\0';
2024 psSHP->sHooks.Error(
str );
2030 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2031 "Corrupted .shp file : shape %d : nEntitySize = %d",
2033 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2034 psSHP->sHooks.Error( szErrorMsg );
2037 memcpy( &
nSHPType, psSHP->pabyRec + 8, 4 );
2044 if( psSHP->bFastModeReadObject )
2046 if( psSHP->psCachedObject->bFastModeReadObject )
2048 psSHP->sHooks.Error(
"Invalid read pattern in fast read mode. "
2049 "SHPDestroyObject() should be called." );
2053 psShape = psSHP->psCachedObject;
2061 psShape->bFastModeReadObject = psSHP->bFastModeReadObject;
2073 int32 nPoints, nParts;
2080 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2081 "Corrupted .shp file : shape %d : nEntitySize = %d",
2083 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2084 psSHP->sHooks.Error( szErrorMsg );
2091 memcpy( &(
psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
2092 memcpy( &(
psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
2093 memcpy( &(
psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
2094 memcpy( &(
psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
2105 memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
2106 memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
2113 nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
2115 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2116 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u.",
2117 hEntity, nPoints, nParts);
2118 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2119 psSHP->sHooks.Error( szErrorMsg );
2127 nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
2132 nRequiredSize += 16 + 8 * nPoints;
2136 nRequiredSize += 4 * nParts;
2140 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2141 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, nEntitySize=%d.",
2143 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2144 psSHP->sHooks.Error( szErrorMsg );
2149 if(
psShape->bFastModeReadObject )
2151 int nObjectBufSize = 4 *
sizeof(double) * nPoints + 2 *
sizeof(
int) * nParts;
2153 ppBuffer = &pBuffer;
2173 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2174 "Not enough memory to allocate requested memory (nPoints=%u, nParts=%u) for shape %d. "
2175 "Probably broken SHP file", nPoints, nParts, hEntity );
2176 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2177 psSHP->sHooks.Error( szErrorMsg );
2188 memcpy(
psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
2194 if (
psShape->panPartStart[i] < 0
2199 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2200 "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
2202 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2203 psSHP->sHooks.Error( szErrorMsg );
2207 if (i > 0 &&
psShape->panPartStart[i] <=
psShape->panPartStart[i-1])
2209 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2210 "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
2211 hEntity, i,
psShape->panPartStart[i], i - 1,
psShape->panPartStart[i - 1]);
2212 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2213 psSHP->sHooks.Error( szErrorMsg );
2219 nOffset = 44 + 8 + 4*nParts;
2226 memcpy(
psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
2232 nOffset += 4*nParts;
2241 psSHP->pabyRec + nOffset + i * 16,
2245 psSHP->pabyRec + nOffset + i * 16 + 8,
2252 nOffset += 16*nPoints;
2261 memcpy( &(
psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
2262 memcpy( &(
psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
2270 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2274 nOffset += 16 + 8*nPoints;
2276 else if(
psShape->bFastModeReadObject )
2289 memcpy( &(
psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
2290 memcpy( &(
psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
2298 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2303 else if(
psShape->bFastModeReadObject )
2323 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2324 "Corrupted .shp file : shape %d : nEntitySize = %d",
2326 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2327 psSHP->sHooks.Error( szErrorMsg );
2331 memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
2336 if ( nPoints > 50 * 1000 * 1000)
2338 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2339 "Corrupted .shp file : shape %d : nPoints = %u",
2341 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2342 psSHP->sHooks.Error( szErrorMsg );
2347 nRequiredSize = 48 + nPoints * 16;
2350 nRequiredSize += 16 + nPoints * 8;
2354 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2355 "Corrupted .shp file : shape %d : nPoints = %u, nEntitySize = %d",
2357 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2358 psSHP->sHooks.Error( szErrorMsg );
2363 if(
psShape->bFastModeReadObject )
2365 int nObjectBufSize = 4 *
sizeof(double) * nPoints;
2367 ppBuffer = &pBuffer;
2382 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2383 "Not enough memory to allocate requested memory (nPoints=%u) for shape %d. "
2384 "Probably broken SHP file", nPoints, hEntity );
2385 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2386 psSHP->sHooks.Error( szErrorMsg );
2393 memcpy(
psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
2394 memcpy(
psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
2400 nOffset = 48 + 16*nPoints;
2405 memcpy( &(
psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
2406 memcpy( &(
psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
2407 memcpy( &(
psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
2408 memcpy( &(
psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
2420 memcpy( &(
psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
2421 memcpy( &(
psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
2429 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2433 nOffset += 16 + 8*nPoints;
2435 else if(
psShape->bFastModeReadObject )
2446 memcpy( &(
psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
2447 memcpy( &(
psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
2455 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2460 else if(
psShape->bFastModeReadObject )
2474 if(
psShape->bFastModeReadObject )
2493 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2494 "Corrupted .shp file : shape %d : nEntitySize = %d",
2496 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2497 psSHP->sHooks.Error( szErrorMsg );
2501 memcpy(
psShape->padfX, psSHP->pabyRec + 12, 8 );
2502 memcpy(
psShape->padfY, psSHP->pabyRec + 20, 8 );
2514 memcpy(
psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
2529 memcpy(
psShape->padfM, psSHP->pabyRec + nOffset, 8 );
2571 return "MultiPoint";
2583 return "MultiPointZ";
2595 return "MultiPointM";
2598 return "MultiPatch";
2601 return "UnknownShapeType";
2616 return "TriangleStrip";
2619 return "TriangleFan";
2634 return "UnknownPartType";
2649 if(
psShape->bFastModeReadObject )
2678 if( iPart == psObject->
nParts-1 )
2691 double dfTestX,
double dfTestY )
2704 for( iCheckRing = 0; iCheckRing < psObject->
nParts; iCheckRing++ )
2706 int nVertStartCheck, nVertCountCheck;
2709 if( iCheckRing == iOpRing )
2715 for( iEdge = 0; iEdge < nVertCountCheck; iEdge++ )
2719 if( iEdge < nVertCountCheck-1 )
2729 if ( ( psObject->
padfY[iEdge+nVertStartCheck] < dfTestY
2730 && dfTestY <= psObject->padfY[iNext+nVertStartCheck] )
2731 || ( psObject->
padfY[iNext+nVertStartCheck] < dfTestY
2732 && dfTestY <= psObject->padfY[iEdge+nVertStartCheck] ) )
2738 double const intersect =
2739 ( psObject->
padfX[iEdge+nVertStartCheck]
2740 + ( dfTestY - psObject->
padfY[iEdge+nVertStartCheck] )
2741 / ( psObject->
padfY[iNext+nVertStartCheck] -
2742 psObject->
padfY[iEdge+nVertStartCheck] )
2743 * ( psObject->
padfX[iNext+nVertStartCheck] -
2744 psObject->
padfX[iEdge+nVertStartCheck] ) );
2746 if (intersect < dfTestX)
2750 else if( intersect == dfTestX )
2772 int iOpRing, bAltered = 0;
2788 for( iOpRing = 0; iOpRing < psObject->
nParts; iOpRing++ )
2794 const int nVertStart = psObject->
panPartStart[iOpRing];
2800 for( iVert = nVertStart; iVert + 1 < nVertStart + nVertCount; ++iVert )
2805 const double dfTestX = ( psObject->
padfX[iVert] +
2806 psObject->
padfX[iVert + 1] ) / 2;
2807 const double dfTestY = ( psObject->
padfY[iVert] +
2808 psObject->
padfY[iVert + 1] ) / 2;
2825 dfSum = psObject->
padfX[nVertStart] *
2826 (psObject->
padfY[nVertStart+1] -
2827 psObject->
padfY[nVertStart+nVertCount-1]);
2828 for( iVert = nVertStart + 1; iVert < nVertStart+nVertCount-1; iVert++ )
2830 dfSum += psObject->
padfX[iVert] * (psObject->
padfY[iVert+1] -
2831 psObject->
padfY[iVert-1]);
2834 dfSum += psObject->
padfX[iVert] * (psObject->
padfY[nVertStart] -
2835 psObject->
padfY[iVert-1]);
2840 if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
2845 for( i = 0; i < nVertCount/2; i++ )
2850 dfSaved = psObject->
padfX[nVertStart+i];
2851 psObject->
padfX[nVertStart+i] =
2852 psObject->
padfX[nVertStart+nVertCount-i-1];
2853 psObject->
padfX[nVertStart+nVertCount-i-1] = dfSaved;
2856 dfSaved = psObject->
padfY[nVertStart+i];
2857 psObject->
padfY[nVertStart+i] =
2858 psObject->
padfY[nVertStart+nVertCount-i-1];
2859 psObject->
padfY[nVertStart+nVertCount-i-1] = dfSaved;
2862 if( psObject->
padfZ )
2864 dfSaved = psObject->
padfZ[nVertStart+i];
2865 psObject->
padfZ[nVertStart+i] =
2866 psObject->
padfZ[nVertStart+nVertCount-i-1];
2867 psObject->
padfZ[nVertStart+nVertCount-i-1] = dfSaved;
2871 if( psObject->
padfM )
2873 dfSaved = psObject->
padfM[nVertStart+i];
2874 psObject->
padfM[nVertStart+i] =
2875 psObject->
padfM[nVertStart+nVertCount-i-1];
2876 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