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';
254 psSHP->
sHooks.
Error(
"Failure allocating panSHX" );
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 )
387 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
388 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
392 memcpy(pszFullname + nLenWithoutExtension,
".SHP", 5);
398 size_t nMessageLen = strlen(pszFullname)*2+256;
400 pszFullname[nLenWithoutExtension] = 0;
401 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shp or %s.SHP.",
402 pszFullname, pszFullname );
403 psHooks->
Error( pszMessage );
412 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
416 memcpy(pszFullname + nLenWithoutExtension,
".SHX", 5);
422 size_t nMessageLen = strlen(pszFullname)*2+256;
424 pszFullname[nLenWithoutExtension] = 0;
425 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shx or %s.SHX. "
426 "Set SHAPE_RESTORE_SHX config option to YES to restore or "
427 "create it.", pszFullname, pszFullname );
428 psHooks->
Error( pszMessage );
445 psSHP->
sHooks.
Error(
".shp file is unreadable, or corrupt." );
455 (pabyBuf[26]<<8)|pabyBuf[27];
467 || pabyBuf[2] != 0x27
468 || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
470 psSHP->
sHooks.
Error(
".shx file is unreadable, or corrupt." );
479 psSHP->
nRecords = pabyBuf[27]|(pabyBuf[26]<<8)|(pabyBuf[25]<<16)|
480 ((pabyBuf[24] & 0x7F)<<24);
487 char szErrorMsg[200];
489 snprintf( szErrorMsg,
sizeof(szErrorMsg),
490 "Record count in .shp header is %d, which seems\n"
491 "unreasonable. Assuming header is corrupt.",
493 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
505 if( psSHP->
nRecords >= 1024 * 1024 )
510 if( nFileSize > 100 &&
522 memcpy( &dValue, pabyBuf+36, 8 );
526 memcpy( &dValue, pabyBuf+44, 8 );
530 memcpy( &dValue, pabyBuf+52, 8 );
534 memcpy( &dValue, pabyBuf+60, 8 );
538 memcpy( &dValue, pabyBuf+68, 8 );
542 memcpy( &dValue, pabyBuf+76, 8 );
546 memcpy( &dValue, pabyBuf+84, 8 );
550 memcpy( &dValue, pabyBuf+92, 8 );
565 if( bLazySHXLoading )
574 char szErrorMsg[200];
576 snprintf( szErrorMsg,
sizeof(szErrorMsg),
577 "Not enough memory to allocate requested memory (nRecords=%d).\n"
578 "Probably broken SHP file",
580 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
586 if (pabyBuf)
free( pabyBuf );
591 if( bLazySHXLoading )
602 char szErrorMsg[200];
604 snprintf( szErrorMsg,
sizeof(szErrorMsg),
605 "Failed to read all values for %d records in .shx file: %s.",
607 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
622 if (strcmp(pszAccess,
"rb") == 0)
628 for( i = 0; i < psSHP->
nRecords; i++ )
630 unsigned int nOffset, nLength;
632 memcpy( &nOffset, pabyBuf + i * 8, 4 );
635 memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
641 snprintf(
str,
sizeof(
str),
642 "Invalid offset for entity %d", i);
643 str[
sizeof(
str)-1] =
'\0';
650 if( nLength >
STATIC_CAST(
unsigned int, INT_MAX / 2 - 4) )
653 snprintf(
str,
sizeof(
str),
654 "Invalid length for entity %d", i);
655 str[
sizeof(
str)-1] =
'\0';
683 if ( !bRestoreSHX )
return SHPOpenLL ( pszLayer, pszAccess, psHooks );
688 return SHPOpenLL ( pszLayer, pszAccess, psHooks );
711 int nLenWithoutExtension;
712 unsigned int nSHPFilesize;
714 unsigned int nCurrentSHPOffset = 100;
715 size_t nRealSHXContentSize = 100;
717 const char pszSHXAccess[] =
"w+b";
719 char abyReadedRecord[8];
720 unsigned int niRecord = 0;
721 unsigned int nRecordLength = 0;
722 unsigned int nRecordOffset = 50;
729 if( strcmp(pszAccess,
"rb+") == 0 || strcmp(pszAccess,
"r+b") == 0
730 || strcmp(pszAccess,
"r+") == 0 )
740 #if !defined(bBigEndian)
743 if( *((
uchar *) &i) == 1 )
758 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
759 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
760 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
763 memcpy(pszFullname + nLenWithoutExtension,
".SHP", 5);
764 fpSHP = psHooks->
FOpen(pszFullname, pszAccess );
769 size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
772 pszFullname[nLenWithoutExtension] = 0;
773 snprintf( pszMessage, nMessageLen,
"Unable to open %s.shp or %s.SHP.",
774 pszFullname, pszFullname );
775 psHooks->
Error( pszMessage );
787 if( psHooks->
FRead( pabyBuf, 100, 1, fpSHP ) != 1 )
789 psHooks->
Error(
".shp file is unreadable, or corrupt." );
798 nSHPFilesize = (
STATIC_CAST(
unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
799 (pabyBuf[26]<<8)|pabyBuf[27];
800 if( nSHPFilesize < UINT_MAX / 2 )
803 nSHPFilesize = (UINT_MAX / 2) * 2;
805 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
806 fpSHX = psHooks->
FOpen( pszFullname, pszSHXAccess );
809 size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
811 pszFullname[nLenWithoutExtension] = 0;
812 snprintf( pszMessage, nMessageLen,
813 "Error opening file %s.shx for writing", pszFullname );
814 psHooks->
Error( pszMessage );
828 psHooks->
FSeek( fpSHP, 100, 0 );
830 memcpy( pabySHXHeader, pabyBuf, 100 );
831 psHooks->
FWrite( pabySHXHeader, 100, 1, fpSHX );
834 while( nCurrentSHPOffset < nSHPFilesize )
836 if( psHooks->
FRead( &niRecord, 4, 1, fpSHP ) == 1 &&
837 psHooks->
FRead( &nRecordLength, 4, 1, fpSHP ) == 1)
840 memcpy( abyReadedRecord, &nRecordOffset, 4 );
841 memcpy( abyReadedRecord + 4, &nRecordLength, 4 );
843 psHooks->
FWrite( abyReadedRecord, 8, 1, fpSHX );
847 nRecordOffset += nRecordLength + 4;
848 nCurrentSHPOffset += 8 + nRecordLength * 2;
850 psHooks->
FSeek( fpSHP, nCurrentSHPOffset, 0 );
851 nRealSHXContentSize += 8;
855 psHooks->
Error(
"Error parsing .shp to restore .shx" );
860 free( pabySHXHeader );
867 nRealSHXContentSize /= 2;
869 psHooks->
FSeek( fpSHX, 24, 0 );
870 psHooks->
FWrite( &nRealSHXContentSize, 4, 1, fpSHX );
875 free ( pszFullname );
876 free ( pabySHXHeader );
957 double * padfMinBound,
double * padfMaxBound )
971 for( i = 0; i < 4; i++ )
995 return SHPCreateLL( pszLayer, nShapeType, &sHooks );
1012 uchar abyHeader[100];
1015 int nLenWithoutExtension;
1020 #if !defined(bBigEndian)
1023 if( *((
uchar *) &i) == 1 )
1037 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
1038 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
1039 fpSHP = psHooks->
FOpen(pszFullname,
"wb" );
1042 char szErrorMsg[200];
1043 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1044 "Failed to create file %s: %s",
1045 pszFullname, strerror(errno) );
1046 psHooks->
Error( szErrorMsg );
1051 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
1052 fpSHX = psHooks->
FOpen(pszFullname,
"wb" );
1055 char szErrorMsg[200];
1056 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1057 "Failed to create file %s: %s",
1058 pszFullname, strerror(errno) );
1059 psHooks->
Error( szErrorMsg );
1068 memset( abyHeader, 0,
sizeof(abyHeader) );
1070 abyHeader[2] = 0x27;
1071 abyHeader[3] = 0x0a;
1086 ByteCopy( &dValue, abyHeader+36, 8 );
1087 ByteCopy( &dValue, abyHeader+44, 8 );
1088 ByteCopy( &dValue, abyHeader+52, 8 );
1089 ByteCopy( &dValue, abyHeader+60, 8 );
1094 if( psHooks->
FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
1096 char szErrorMsg[200];
1098 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1099 "Failed to write .shp header: %s", strerror(errno) );
1100 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1101 psHooks->
Error( szErrorMsg );
1113 if( psHooks->
FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
1115 char szErrorMsg[200];
1117 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1118 "Failure writing .shx header: %s", strerror(errno) );
1119 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1120 psHooks->
Error( szErrorMsg );
1128 psHooks->
FClose( fpSHP );
1129 psHooks->
FClose( fpSHX );
1131 return(
SHPOpenLL( pszLayer,
"r+b", psHooks ) );
1134 if (pszFullname)
free(pszFullname);
1135 if (fpSHP) psHooks->
FClose( fpSHP );
1136 if (fpSHX) psHooks->
FClose( fpSHX );
1188 for( i = 0; i < psObject->
nVertices; i++ )
1211 const
int * panPartStart, const
int * panPartType,
1212 int nVertices, const
double *padfX, const
double *padfY,
1213 const
double * padfZ, const
double * padfM )
1217 int i, bHasM,
bHasZ;
1262 calloc(psObject->
nParts,
sizeof(
int)));
1269 for( i = 0; i < nParts; i++ )
1289 size_t nSize =
sizeof(double) *
nVertices;
1299 memcpy(psObject->
padfX, padfX, nSize);
1301 memcpy(psObject->
padfY, padfY, nSize);
1303 memcpy(psObject->
padfZ, padfZ, nSize);
1306 memcpy(psObject->
padfM, padfM, nSize);
1329 const
double * padfX, const
double * padfY,
1330 const
double * padfZ )
1349 unsigned int nRecordSize=0;
1353 int bAppendToLastRecord =
FALSE;
1354 int bAppendToFile =
FALSE;
1371 || (
nShapeId >= 0 && nShapeId < psSHP->nRecords) );
1382 unsigned int* panRecOffsetNew;
1383 unsigned int* panRecSizeNew;
1404 + psObject->
nParts * 8 + 128));
1419 int32 nPoints, nParts;
1422 nParts = psObject->
nParts;
1429 ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
1430 ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
1439 for( i = 0; i < psObject->
nParts; i++ )
1450 memcpy( pabyRec + nRecordSize, psObject->
panPartType,
1452 for( i = 0; i < psObject->
nParts; i++ )
1462 for( i = 0; i < psObject->
nVertices; i++ )
1465 ByteCopy( psObject->
padfY + i, pabyRec + nRecordSize + 8, 8 );
1468 SwapWord( 8, pabyRec + nRecordSize );
1471 SwapWord( 8, pabyRec + nRecordSize + 8 );
1473 nRecordSize += 2 * 8;
1491 for( i = 0; i < psObject->
nVertices; i++ )
1519 for( i = 0; i < psObject->
nVertices; i++ )
1542 ByteCopy( &nPoints, pabyRec + 44, 4 );
1544 for( i = 0; i < psObject->
nVertices; i++ )
1547 ByteCopy( psObject->
padfY + i, pabyRec + 48 + i*16 + 8, 8 );
1553 nRecordSize = 48 + 16 * psObject->
nVertices;
1565 for( i = 0; i < psObject->
nVertices; i++ )
1585 for( i = 0; i < psObject->
nVertices; i++ )
1651 bAppendToLastRecord =
TRUE;
1655 if( psSHP->
nFileSize > UINT_MAX - nRecordSize)
1658 snprintf(
str,
sizeof(
str),
"Failed to write shape object. "
1659 "File size cannot reach %u + %u.",
1661 str[
sizeof(
str)-1] =
'\0';
1667 bAppendToFile =
TRUE;
1682 i32 = (nRecordSize-8)/2;
1702 char szErrorMsg[200];
1704 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1705 "Error in psSHP->sHooks.FSeek() while writing object to .shp file: %s",
1707 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1716 char szErrorMsg[200];
1718 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1719 "Error in psSHP->sHooks.FWrite() while writing object of %u bytes to .shp file: %s",
1720 nRecordSize, strerror(errno) );
1721 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1730 if( bAppendToLastRecord )
1734 else if( bAppendToFile )
1768 for( i = 0; i < psObject->
nVertices; i++ )
1774 if( psObject->
padfZ )
1779 if( psObject->
padfM )
1795 unsigned char* pRet;
1798 return calloc(1, nSize);
1804 (*pBuffer) += nSize;
1813 int nObjectBufSize )
1815 unsigned char* pBuffer;
1816 if( nObjectBufSize == 0 )
1818 nObjectBufSize = 4 *
sizeof(double);
1847 char szErrorMsg[160];
1854 if( hEntity < 0 || hEntity >= psSHP->nRecords )
1860 if( psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX !=
SHPLIB_NULLPTR )
1862 unsigned int nOffset, nLength;
1864 if( psSHP->sHooks.FSeek( psSHP->fpSHX, 100 + 8 * hEntity, 0 ) != 0 ||
1865 psSHP->sHooks.FRead( &nOffset, 1, 4, psSHP->fpSHX ) != 4 ||
1866 psSHP->sHooks.FRead( &nLength, 1, 4, psSHP->fpSHX ) != 4 )
1869 snprintf(
str,
sizeof(
str),
1870 "Error in fseek()/fread() reading object from .shx file at offset %d",
1872 str[
sizeof(
str)-1] =
'\0';
1874 psSHP->sHooks.Error(
str );
1880 if( nOffset >
STATIC_CAST(
unsigned int, INT_MAX) )
1883 snprintf(
str,
sizeof(
str),
1884 "Invalid offset for entity %d", hEntity);
1885 str[
sizeof(
str)-1] =
'\0';
1887 psSHP->sHooks.Error(
str );
1890 if( nLength >
STATIC_CAST(
unsigned int, INT_MAX / 2 - 4) )
1893 snprintf(
str,
sizeof(
str),
1894 "Invalid length for entity %d", hEntity);
1895 str[
sizeof(
str)-1] =
'\0';
1897 psSHP->sHooks.Error(
str );
1901 psSHP->panRecOffset[hEntity] = nOffset*2;
1902 psSHP->panRecSize[hEntity] = nLength*2;
1913 if( nNewBufSize < INT_MAX - nNewBufSize / 3 )
1914 nNewBufSize += nNewBufSize / 3;
1916 nNewBufSize = INT_MAX;
1921 if( nNewBufSize >= 10 * 1024 * 1024 )
1923 if( psSHP->nBufSize < 10 * 1024 * 1024 )
1926 psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 2 );
1927 nFileSize = psSHP->sHooks.FTell(psSHP->fpSHP);
1928 if( nFileSize >= UINT_MAX )
1929 psSHP->nFileSize = UINT_MAX;
1931 psSHP->nFileSize =
STATIC_CAST(
unsigned int, nFileSize);
1934 if( psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
1939 psSHP->panRecSize[hEntity] > psSHP->nFileSize - psSHP->panRecOffset[hEntity] )
1942 snprintf(
str,
sizeof(
str),
1943 "Error in fread() reading object of size %d at offset %u from .shp file",
1945 str[
sizeof(
str)-1] =
'\0';
1947 psSHP->sHooks.Error(
str );
1955 snprintf( szErrorMsg,
sizeof(szErrorMsg),
1956 "Not enough memory to allocate requested memory (nNewBufSize=%d). "
1957 "Probably broken SHP file", nNewBufSize);
1958 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
1959 psSHP->sHooks.Error( szErrorMsg );
1964 psSHP->pabyRec = pabyRecNew;
1965 psSHP->nBufSize = nNewBufSize;
1977 if( psSHP->sHooks.FSeek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 )
1984 snprintf(
str,
sizeof(
str),
1985 "Error in fseek() reading object from .shp file at offset %u",
1986 psSHP->panRecOffset[hEntity]);
1987 str[
sizeof(
str)-1] =
'\0';
1989 psSHP->sHooks.Error(
str );
2004 int nSHPContentLength;
2005 memcpy( &nSHPContentLength, psSHP->pabyRec + 4, 4 );
2007 if( nSHPContentLength < 0 ||
2008 nSHPContentLength > INT_MAX / 2 - 4 ||
2012 snprintf(
str,
sizeof(
str),
2013 "Sanity check failed when trying to recover from inconsistent .shx/.shp with shape %d",
2015 str[
sizeof(
str)-1] =
'\0';
2017 psSHP->sHooks.Error(
str );
2028 snprintf(
str,
sizeof(
str),
2029 "Error in fread() reading object of size %d at offset %u from .shp file",
2031 str[
sizeof(
str)-1] =
'\0';
2033 psSHP->sHooks.Error(
str );
2039 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2040 "Corrupted .shp file : shape %d : nEntitySize = %d",
2042 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2043 psSHP->sHooks.Error( szErrorMsg );
2046 memcpy( &
nSHPType, psSHP->pabyRec + 8, 4 );
2053 if( psSHP->bFastModeReadObject )
2055 if( psSHP->psCachedObject->bFastModeReadObject )
2057 psSHP->sHooks.Error(
"Invalid read pattern in fast read mode. "
2058 "SHPDestroyObject() should be called." );
2062 psShape = psSHP->psCachedObject;
2070 psShape->bFastModeReadObject = psSHP->bFastModeReadObject;
2082 int32 nPoints, nParts;
2089 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2090 "Corrupted .shp file : shape %d : nEntitySize = %d",
2092 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2093 psSHP->sHooks.Error( szErrorMsg );
2100 memcpy( &(
psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
2101 memcpy( &(
psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
2102 memcpy( &(
psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
2103 memcpy( &(
psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
2114 memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
2115 memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
2122 nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
2124 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2125 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u.",
2126 hEntity, nPoints, nParts);
2127 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2128 psSHP->sHooks.Error( szErrorMsg );
2136 nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
2141 nRequiredSize += 16 + 8 * nPoints;
2145 nRequiredSize += 4 * nParts;
2149 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2150 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, nEntitySize=%d.",
2152 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2153 psSHP->sHooks.Error( szErrorMsg );
2158 if(
psShape->bFastModeReadObject )
2160 int nObjectBufSize = 4 *
sizeof(double) * nPoints + 2 *
sizeof(
int) * nParts;
2162 ppBuffer = &pBuffer;
2182 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2183 "Not enough memory to allocate requested memory (nPoints=%u, nParts=%u) for shape %d. "
2184 "Probably broken SHP file", nPoints, nParts, hEntity );
2185 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2186 psSHP->sHooks.Error( szErrorMsg );
2197 memcpy(
psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
2203 if (
psShape->panPartStart[i] < 0
2208 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2209 "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
2211 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2212 psSHP->sHooks.Error( szErrorMsg );
2216 if (i > 0 &&
psShape->panPartStart[i] <=
psShape->panPartStart[i-1])
2218 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2219 "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
2220 hEntity, i,
psShape->panPartStart[i], i - 1,
psShape->panPartStart[i - 1]);
2221 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2222 psSHP->sHooks.Error( szErrorMsg );
2228 nOffset = 44 + 8 + 4*nParts;
2235 memcpy(
psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
2241 nOffset += 4*nParts;
2250 psSHP->pabyRec + nOffset + i * 16,
2254 psSHP->pabyRec + nOffset + i * 16 + 8,
2261 nOffset += 16*nPoints;
2270 memcpy( &(
psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
2271 memcpy( &(
psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
2279 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2283 nOffset += 16 + 8*nPoints;
2285 else if(
psShape->bFastModeReadObject )
2298 memcpy( &(
psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
2299 memcpy( &(
psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
2307 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2312 else if(
psShape->bFastModeReadObject )
2332 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2333 "Corrupted .shp file : shape %d : nEntitySize = %d",
2335 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2336 psSHP->sHooks.Error( szErrorMsg );
2340 memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
2345 if ( nPoints > 50 * 1000 * 1000)
2347 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2348 "Corrupted .shp file : shape %d : nPoints = %u",
2350 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2351 psSHP->sHooks.Error( szErrorMsg );
2356 nRequiredSize = 48 + nPoints * 16;
2359 nRequiredSize += 16 + nPoints * 8;
2363 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2364 "Corrupted .shp file : shape %d : nPoints = %u, nEntitySize = %d",
2366 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2367 psSHP->sHooks.Error( szErrorMsg );
2372 if(
psShape->bFastModeReadObject )
2374 int nObjectBufSize = 4 *
sizeof(double) * nPoints;
2376 ppBuffer = &pBuffer;
2391 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2392 "Not enough memory to allocate requested memory (nPoints=%u) for shape %d. "
2393 "Probably broken SHP file", nPoints, hEntity );
2394 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2395 psSHP->sHooks.Error( szErrorMsg );
2402 memcpy(
psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
2403 memcpy(
psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
2409 nOffset = 48 + 16*nPoints;
2414 memcpy( &(
psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
2415 memcpy( &(
psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
2416 memcpy( &(
psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
2417 memcpy( &(
psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
2429 memcpy( &(
psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
2430 memcpy( &(
psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
2438 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2442 nOffset += 16 + 8*nPoints;
2444 else if(
psShape->bFastModeReadObject )
2455 memcpy( &(
psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
2456 memcpy( &(
psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
2464 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
2469 else if(
psShape->bFastModeReadObject )
2483 if(
psShape->bFastModeReadObject )
2502 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2503 "Corrupted .shp file : shape %d : nEntitySize = %d",
2505 szErrorMsg[
sizeof(szErrorMsg)-1] =
'\0';
2506 psSHP->sHooks.Error( szErrorMsg );
2510 memcpy(
psShape->padfX, psSHP->pabyRec + 12, 8 );
2511 memcpy(
psShape->padfY, psSHP->pabyRec + 20, 8 );
2523 memcpy(
psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
2538 memcpy(
psShape->padfM, psSHP->pabyRec + nOffset, 8 );
2580 return "MultiPoint";
2592 return "MultiPointZ";
2604 return "MultiPointM";
2607 return "MultiPatch";
2610 return "UnknownShapeType";
2625 return "TriangleStrip";
2628 return "TriangleFan";
2643 return "UnknownPartType";
2658 if(
psShape->bFastModeReadObject )
2687 if( iPart == psObject->
nParts-1 )
2700 double dfTestX,
double dfTestY )
2713 for( iCheckRing = 0; iCheckRing < psObject->
nParts; iCheckRing++ )
2715 int nVertStartCheck, nVertCountCheck;
2718 if( iCheckRing == iOpRing )
2724 for( iEdge = 0; iEdge < nVertCountCheck; iEdge++ )
2728 if( iEdge < nVertCountCheck-1 )
2738 if ( ( psObject->
padfY[iEdge+nVertStartCheck] < dfTestY
2739 && dfTestY <= psObject->padfY[iNext+nVertStartCheck] )
2740 || ( psObject->
padfY[iNext+nVertStartCheck] < dfTestY
2741 && dfTestY <= psObject->padfY[iEdge+nVertStartCheck] ) )
2747 double const intersect =
2748 ( psObject->
padfX[iEdge+nVertStartCheck]
2749 + ( dfTestY - psObject->
padfY[iEdge+nVertStartCheck] )
2750 / ( psObject->
padfY[iNext+nVertStartCheck] -
2751 psObject->
padfY[iEdge+nVertStartCheck] )
2752 * ( psObject->
padfX[iNext+nVertStartCheck] -
2753 psObject->
padfX[iEdge+nVertStartCheck] ) );
2755 if (intersect < dfTestX)
2759 else if( intersect == dfTestX )
2781 int iOpRing, bAltered = 0;
2797 for( iOpRing = 0; iOpRing < psObject->
nParts; iOpRing++ )
2803 const int nVertStart = psObject->
panPartStart[iOpRing];
2809 for( iVert = nVertStart; iVert + 1 < nVertStart + nVertCount; ++iVert )
2814 const double dfTestX = ( psObject->
padfX[iVert] +
2815 psObject->
padfX[iVert + 1] ) / 2;
2816 const double dfTestY = ( psObject->
padfY[iVert] +
2817 psObject->
padfY[iVert + 1] ) / 2;
2834 dfSum = psObject->
padfX[nVertStart] *
2835 (psObject->
padfY[nVertStart+1] -
2836 psObject->
padfY[nVertStart+nVertCount-1]);
2837 for( iVert = nVertStart + 1; iVert < nVertStart+nVertCount-1; iVert++ )
2839 dfSum += psObject->
padfX[iVert] * (psObject->
padfY[iVert+1] -
2840 psObject->
padfY[iVert-1]);
2843 dfSum += psObject->
padfX[iVert] * (psObject->
padfY[nVertStart] -
2844 psObject->
padfY[iVert-1]);
2849 if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
2854 for( i = 0; i < nVertCount/2; i++ )
2859 dfSaved = psObject->
padfX[nVertStart+i];
2860 psObject->
padfX[nVertStart+i] =
2861 psObject->
padfX[nVertStart+nVertCount-i-1];
2862 psObject->
padfX[nVertStart+nVertCount-i-1] = dfSaved;
2865 dfSaved = psObject->
padfY[nVertStart+i];
2866 psObject->
padfY[nVertStart+i] =
2867 psObject->
padfY[nVertStart+nVertCount-i-1];
2868 psObject->
padfY[nVertStart+nVertCount-i-1] = dfSaved;
2871 if( psObject->
padfZ )
2873 dfSaved = psObject->
padfZ[nVertStart+i];
2874 psObject->
padfZ[nVertStart+i] =
2875 psObject->
padfZ[nVertStart+nVertCount-i-1];
2876 psObject->
padfZ[nVertStart+nVertCount-i-1] = dfSaved;
2880 if( psObject->
padfM )
2882 dfSaved = psObject->
padfM[nVertStart+i];
2883 psObject->
padfM[nVertStart+i] =
2884 psObject->
padfM[nVertStart+nVertCount-i-1];
2885 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