65 psSHP->
sHooks.
Error(
"SHPWriteHeader failed : SHX file is closed");
73 unsigned char abyHeader[100] = {0};
79#if !defined(SHP_BIG_ENDIAN)
85#if defined(SHP_BIG_ENDIAN)
91#if defined(SHP_BIG_ENDIAN)
96 ByteCopy(&dValue, abyHeader + 36, 8);
97#if defined(SHP_BIG_ENDIAN)
101 ByteCopy(&dValue, abyHeader + 44, 8);
102#if defined(SHP_BIG_ENDIAN)
106 ByteCopy(&dValue, abyHeader + 52, 8);
107#if defined(SHP_BIG_ENDIAN)
112 ByteCopy(&dValue, abyHeader + 60, 8);
113#if defined(SHP_BIG_ENDIAN)
118 ByteCopy(&dValue, abyHeader + 68, 8);
119#if defined(SHP_BIG_ENDIAN)
124 ByteCopy(&dValue, abyHeader + 76, 8);
125#if defined(SHP_BIG_ENDIAN)
130 ByteCopy(&dValue, abyHeader + 84, 8);
131#if defined(SHP_BIG_ENDIAN)
136 ByteCopy(&dValue, abyHeader + 92, 8);
137#if defined(SHP_BIG_ENDIAN)
146 char szErrorMsg[200];
148 snprintf(szErrorMsg,
sizeof(szErrorMsg),
149 "Failure writing .shp header: %s", strerror(errno));
150 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
158 i32 = (psSHP->
nRecords * 2 *
sizeof(uint32_t) + 100) / 2;
160#if !defined(SHP_BIG_ENDIAN)
166 char szErrorMsg[200];
168 snprintf(szErrorMsg,
sizeof(szErrorMsg),
169 "Failure writing .shx header: %s", strerror(errno));
170 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
186 for (
int i = 0; i < psSHP->
nRecords; i++) {
189#if !defined(SHP_BIG_ENDIAN)
198 char szErrorMsg[200];
200 snprintf(szErrorMsg,
sizeof(szErrorMsg),
201 "Failure writing .shx contents: %s", strerror(errno));
202 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
259 bool bLazySHXLoading =
false;
260 if (strcmp(pszAccess,
"rb+") == 0 || strcmp(pszAccess,
"r+b") == 0 ||
261 strcmp(pszAccess,
"r+") == 0) {
283 const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
284 char *pszFullname =
STATIC_CAST(
char *, malloc(nLenWithoutExtension + 5));
289 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
290 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
294 memcpy(pszFullname + nLenWithoutExtension,
".SHP", 5);
300 const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
301 char *pszMessage =
STATIC_CAST(
char *, malloc(nMessageLen));
303 pszFullname[nLenWithoutExtension] = 0;
304 snprintf(pszMessage, nMessageLen,
305 "Unable to open %s.shp or %s.SHP in %s mode.", pszFullname,
306 pszFullname, pszAccess);
307 psHooks->
Error(pszMessage);
317 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
321 memcpy(pszFullname + nLenWithoutExtension,
".SHX", 5);
327 const size_t nMessageLen =
329 char *pszMessage =
STATIC_CAST(
char *, malloc(nMessageLen));
331 pszFullname[nLenWithoutExtension] = 0;
333 pszMessage, nMessageLen,
335 pszFullname, pszFullname);
336 psHooks->
Error(pszMessage);
351 unsigned char *pabyBuf =
STATIC_CAST(
unsigned char *, malloc(100));
353 psSHP->
sHooks.
Error(
".shp file is unreadable, or corrupt.");
363 (pabyBuf[25] << 16) | (pabyBuf[26] << 8) | pabyBuf[27];
373 pabyBuf[0] != 0 || pabyBuf[1] != 0 || pabyBuf[2] != 0x27 ||
374 (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d)) {
375 psSHP->
sHooks.
Error(
".shx file is unreadable, or corrupt.");
384 psSHP->
nRecords = pabyBuf[27] | (pabyBuf[26] << 8) | (pabyBuf[25] << 16) |
385 ((pabyBuf[24] & 0x7F) << 24);
391 char szErrorMsg[200];
393 snprintf(szErrorMsg,
sizeof(szErrorMsg),
394 "Record count in .shx header is %d, which seems\n"
395 "unreasonable. Assuming header is corrupt.",
397 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
409 if (psSHP->
nRecords >= 1024 * 1024) {
412 if (nFileSize > 100 &&
424#if defined(SHP_BIG_ENDIAN)
427 memcpy(&dValue, pabyBuf + 36, 8);
430#if defined(SHP_BIG_ENDIAN)
433 memcpy(&dValue, pabyBuf + 44, 8);
436#if defined(SHP_BIG_ENDIAN)
439 memcpy(&dValue, pabyBuf + 52, 8);
442#if defined(SHP_BIG_ENDIAN)
445 memcpy(&dValue, pabyBuf + 60, 8);
448#if defined(SHP_BIG_ENDIAN)
451 memcpy(&dValue, pabyBuf + 68, 8);
454#if defined(SHP_BIG_ENDIAN)
457 memcpy(&dValue, pabyBuf + 76, 8);
460#if defined(SHP_BIG_ENDIAN)
463 memcpy(&dValue, pabyBuf + 84, 8);
466#if defined(SHP_BIG_ENDIAN)
469 memcpy(&dValue, pabyBuf + 92, 8);
495 char szErrorMsg[200];
498 szErrorMsg,
sizeof(szErrorMsg),
499 "Not enough memory to allocate requested memory (nRecords=%d).\n"
500 "Probably broken SHP file",
502 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
516 if (bLazySHXLoading) {
528 char szErrorMsg[200];
530 snprintf(szErrorMsg,
sizeof(szErrorMsg),
531 "Failed to read all values for %d records in .shx file: %s.",
533 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
548 if (strcmp(pszAccess,
"rb") == 0) {
553 for (
int i = 0; i < psSHP->
nRecords; i++) {
554 unsigned int nOffset;
555 memcpy(&nOffset, pabyBuf + i * 8, 4);
556#if !defined(SHP_BIG_ENDIAN)
560 unsigned int nLength;
561 memcpy(&nLength, pabyBuf + i * 8 + 4, 4);
562#if !defined(SHP_BIG_ENDIAN)
566 if (nOffset >
STATIC_CAST(
unsigned int, INT_MAX)) {
568 snprintf(str,
sizeof(str),
"Invalid offset for entity %d", i);
569 str[
sizeof(str) - 1] =
'\0';
576 if (nLength >
STATIC_CAST(
unsigned int, INT_MAX / 2 - 4)) {
578 snprintf(str,
sizeof(str),
"Invalid length for entity %d", i);
579 str[
sizeof(str) - 1] =
'\0';
631 if (strcmp(pszAccess,
"rb+") == 0 || strcmp(pszAccess,
"r+b") == 0 ||
632 strcmp(pszAccess,
"r+") == 0) {
643 const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
644 char *pszFullname =
STATIC_CAST(
char *, malloc(nLenWithoutExtension + 5));
647 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
648 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
651 memcpy(pszFullname + nLenWithoutExtension,
".SHP", 5);
656 const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
657 char *pszMessage =
STATIC_CAST(
char *, malloc(nMessageLen));
659 pszFullname[nLenWithoutExtension] = 0;
660 snprintf(pszMessage, nMessageLen,
661 "Unable to open %s.shp or %s.SHP.", pszFullname,
663 psHooks->
Error(pszMessage);
675 unsigned char *pabyBuf =
STATIC_CAST(
unsigned char *, malloc(100));
676 if (psHooks->
FRead(pabyBuf, 100, 1, fpSHP) != 1) {
677 psHooks->
Error(
".shp file is unreadable, or corrupt.");
686 unsigned int nSHPFilesize = (
STATIC_CAST(
unsigned int, pabyBuf[24]) << 24) |
687 (pabyBuf[25] << 16) | (pabyBuf[26] << 8) |
689 if (nSHPFilesize < UINT_MAX / 2)
692 nSHPFilesize = (UINT_MAX / 2) * 2;
694 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
695 const char pszSHXAccess[] =
"w+b";
699 size_t nMessageLen = strlen(pszFullname) * 2 + 256;
700 char *pszMessage =
STATIC_CAST(
char *, malloc(nMessageLen));
702 pszFullname[nLenWithoutExtension] = 0;
703 snprintf(pszMessage, nMessageLen,
704 "Error opening file %s.shx for writing", pszFullname);
705 psHooks->
Error(pszMessage);
720 psHooks->
FSeek(fpSHP, 100, 0);
721 char *pabySHXHeader =
STATIC_CAST(
char *, malloc(100));
722 if (!pabySHXHeader) {
730 memcpy(pabySHXHeader, pabyBuf, 100);
731 psHooks->
FWrite(pabySHXHeader, 100, 1, fpSHX);
735 unsigned int nCurrentSHPOffset = 100;
736 unsigned int nRealSHXContentSize = 100;
738 unsigned int nRecordOffset = 50;
740 while (nCurrentSHPOffset < nSHPFilesize) {
741 unsigned int niRecord = 0;
742 unsigned int nRecordLength = 0;
745 if (psHooks->
FRead(&niRecord, 4, 1, fpSHP) == 1 &&
746 psHooks->
FRead(&nRecordLength, 4, 1, fpSHP) == 1 &&
747 psHooks->
FRead(&nSHPType, 4, 1, fpSHP) == 1) {
748 char abyReadRecord[8];
749 unsigned int nRecordOffsetBE = nRecordOffset;
751#if !defined(SHP_BIG_ENDIAN)
754 memcpy(abyReadRecord, &nRecordOffsetBE, 4);
755 memcpy(abyReadRecord + 4, &nRecordLength, 4);
757#if !defined(SHP_BIG_ENDIAN)
760#if defined(SHP_BIG_ENDIAN)
765 if (nRecordLength < 1 ||
766 nRecordLength > (nSHPFilesize - (nCurrentSHPOffset + 8)) / 2) {
767 char szErrorMsg[200];
768 snprintf(szErrorMsg,
sizeof(szErrorMsg),
769 "Error parsing .shp to restore .shx. "
770 "Invalid record length = %u at record starting at "
772 nRecordLength, nCurrentSHPOffset);
773 psHooks->
Error(szErrorMsg);
787 char szErrorMsg[200];
788 snprintf(szErrorMsg,
sizeof(szErrorMsg),
789 "Error parsing .shp to restore .shx. "
790 "Invalid shape type = %d at record starting at "
792 nSHPType, nCurrentSHPOffset);
793 psHooks->
Error(szErrorMsg);
799 psHooks->
FWrite(abyReadRecord, 8, 1, fpSHX);
801 nRecordOffset += nRecordLength + 4;
803 nCurrentSHPOffset += 8 + nRecordLength * 2;
805 psHooks->
FSeek(fpSHP, nCurrentSHPOffset, 0);
806 nRealSHXContentSize += 8;
809 char szErrorMsg[200];
810 snprintf(szErrorMsg,
sizeof(szErrorMsg),
811 "Error parsing .shp to restore .shx. "
812 "Cannot read first bytes of record starting at "
815 psHooks->
Error(szErrorMsg);
821 if (nRetCode && nCurrentSHPOffset != nSHPFilesize) {
822 psHooks->
Error(
"Error parsing .shp to restore .shx. "
823 "Not expected number of bytes");
828 nRealSHXContentSize /= 2;
829#if !defined(SHP_BIG_ENDIAN)
833 psHooks->
FSeek(fpSHX, 24, 0);
834 psHooks->
FWrite(&nRealSHXContentSize, 4, 1, fpSHX);
971 const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
972 char *pszFullname =
STATIC_CAST(
char *, malloc(nLenWithoutExtension + 5));
977 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
978 memcpy(pszFullname + nLenWithoutExtension,
".shp", 5);
981 const size_t nMessageLen = strlen(pszFullname) + 256;
982 char *pszMessage =
STATIC_CAST(
char *, malloc(nMessageLen));
984 snprintf(pszMessage, nMessageLen,
"Failed to create file %s: %s",
985 pszFullname, strerror(errno));
986 psHooks->
Error(pszMessage);
994 memcpy(pszFullname + nLenWithoutExtension,
".shx", 5);
997 const size_t nMessageLen = strlen(pszFullname) + 256;
998 char *pszMessage =
STATIC_CAST(
char *, malloc(nMessageLen));
1000 snprintf(pszMessage, nMessageLen,
"Failed to create file %s: %s",
1001 pszFullname, strerror(errno));
1002 psHooks->
Error(pszMessage);
1018 unsigned char abyHeader[100];
1019 memset(abyHeader, 0,
sizeof(abyHeader));
1021 abyHeader[2] = 0x27;
1022 abyHeader[3] = 0x0a;
1026#if !defined(SHP_BIG_ENDIAN)
1032#if defined(SHP_BIG_ENDIAN)
1038#if defined(SHP_BIG_ENDIAN)
1042 double dValue = 0.0;
1043 ByteCopy(&dValue, abyHeader + 36, 8);
1044 ByteCopy(&dValue, abyHeader + 44, 8);
1045 ByteCopy(&dValue, abyHeader + 52, 8);
1046 ByteCopy(&dValue, abyHeader + 60, 8);
1051 if (psHooks->
FWrite(abyHeader, 100, 1, fpSHP) != 1) {
1052 char szErrorMsg[200];
1054 snprintf(szErrorMsg,
sizeof(szErrorMsg),
1055 "Failed to write .shp header: %s", strerror(errno));
1056 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
1057 psHooks->
Error(szErrorMsg);
1071#if !defined(SHP_BIG_ENDIAN)
1075 if (psHooks->
FWrite(abyHeader, 100, 1, fpSHX) != 1) {
1076 char szErrorMsg[200];
1078 snprintf(szErrorMsg,
sizeof(szErrorMsg),
1079 "Failure writing .shx header: %s", strerror(errno));
1080 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
1081 psHooks->
Error(szErrorMsg);
1093 psSHP->
fpSHP = fpSHP;
1094 psSHP->
fpSHX = fpSHX;
1098 STATIC_CAST(
unsigned int *, malloc(
sizeof(
unsigned int)));
1100 STATIC_CAST(
unsigned int *, malloc(
sizeof(
unsigned int)));
1104 psSHP->
sHooks.
Error(
"Not enough memory to allocate requested memory");
1340 assert(nShapeId == -1 || (nShapeId >= 0 && nShapeId < psSHP->nRecords));
1342 if (nShapeId != -1 && nShapeId >= psSHP->
nRecords)
1354 unsigned int *panRecOffsetNew;
1355 unsigned int *panRecSizeNew;
1359 sizeof(
unsigned int) * nNewMaxRecords));
1361 psSHP->
sHooks.
Error(
"Failed to write shape object. "
1362 "Memory allocation error.");
1369 realloc(psSHP->
panRecSize,
sizeof(
unsigned int) * nNewMaxRecords));
1371 psSHP->
sHooks.
Error(
"Failed to write shape object. "
1372 "Memory allocation error.");
1386 size_t nRecMaxSize =
1390 const unsigned nExtraSpaceForGeomHeader = 128;
1391 if (nRecMaxSize > UINT_MAX - nExtraSpaceForGeomHeader) {
1392 psSHP->
sHooks.
Error(
"Failed to write shape object. Too big geometry.");
1395 nRecMaxSize += nExtraSpaceForGeomHeader;
1396 unsigned char *pabyRec =
STATIC_CAST(
unsigned char *, malloc(nRecMaxSize));
1398 psSHP->
sHooks.
Error(
"Failed to write shape object. "
1399 "Memory allocation error.");
1406 unsigned int nRecordSize = 0;
1407 const bool bFirstFeature = psSHP->
nRecords == 0;
1415 uint32_t nParts = psObject->
nParts;
1417 _SHPSetBounds(pabyRec + 12, psObject);
1419#if defined(SHP_BIG_ENDIAN)
1424 ByteCopy(&nPoints, pabyRec + 40 + 8, 4);
1425 ByteCopy(&nParts, pabyRec + 36 + 8, 4);
1434 for (
int i = 0; i < psObject->
nParts; i++) {
1435#if defined(SHP_BIG_ENDIAN)
1445 memcpy(pabyRec + nRecordSize, psObject->
panPartType,
1447 for (
int i = 0; i < psObject->
nParts; i++) {
1448#if defined(SHP_BIG_ENDIAN)
1458 for (
int i = 0; i < psObject->
nVertices; i++) {
1460 ByteCopy(psObject->
padfY + i, pabyRec + nRecordSize + 8, 8);
1462#if defined(SHP_BIG_ENDIAN)
1467 nRecordSize += 2 * 8;
1477#if defined(SHP_BIG_ENDIAN)
1483#if defined(SHP_BIG_ENDIAN)
1488 for (
int i = 0; i < psObject->
nVertices; i++) {
1490#if defined(SHP_BIG_ENDIAN)
1509#if defined(SHP_BIG_ENDIAN)
1515#if defined(SHP_BIG_ENDIAN)
1520 for (
int i = 0; i < psObject->
nVertices; i++) {
1522#if defined(SHP_BIG_ENDIAN)
1538 _SHPSetBounds(pabyRec + 12, psObject);
1540#if defined(SHP_BIG_ENDIAN)
1543 ByteCopy(&nPoints, pabyRec + 44, 4);
1545 for (
int i = 0; i < psObject->
nVertices; i++) {
1547 ByteCopy(psObject->
padfY + i, pabyRec + 48 + i * 16 + 8, 8);
1549#if defined(SHP_BIG_ENDIAN)
1555 nRecordSize = 48 + 16 * psObject->
nVertices;
1559#if defined(SHP_BIG_ENDIAN)
1565#if defined(SHP_BIG_ENDIAN)
1570 for (
int i = 0; i < psObject->
nVertices; i++) {
1572#if defined(SHP_BIG_ENDIAN)
1583#if defined(SHP_BIG_ENDIAN)
1589#if defined(SHP_BIG_ENDIAN)
1594 for (
int i = 0; i < psObject->
nVertices; i++) {
1596#if defined(SHP_BIG_ENDIAN)
1613#if defined(SHP_BIG_ENDIAN)
1622#if defined(SHP_BIG_ENDIAN)
1631#if defined(SHP_BIG_ENDIAN)
1657 bool bAppendToLastRecord =
false;
1658 bool bAppendToFile =
false;
1659 if (nShapeId != -1 &&
1663 bAppendToLastRecord =
true;
1665 else if (nShapeId == -1 || psSHP->
panRecSize[nShapeId] < nRecordSize - 8) {
1666 if (psSHP->
nFileSize > UINT_MAX - nRecordSize) {
1668 snprintf(str,
sizeof(str),
1669 "Failed to write shape object. "
1670 "The maximum file size of %u has been reached. "
1671 "The current record of size %u cannot be added.",
1673 str[
sizeof(str) - 1] =
'\0';
1679 bAppendToFile =
true;
1690 (nShapeId < 0) ? psSHP->
nRecords + 1 : nShapeId + 1;
1691#if !defined(SHP_BIG_ENDIAN)
1696 i32 = (nRecordSize - 8) / 2;
1697#if !defined(SHP_BIG_ENDIAN)
1703#if defined(SHP_BIG_ENDIAN)
1718 char szErrorMsg[200];
1720 snprintf(szErrorMsg,
sizeof(szErrorMsg),
1721 "Error in psSHP->sHooks.FSeek() while writing object to "
1724 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
1732 char szErrorMsg[200];
1734 snprintf(szErrorMsg,
sizeof(szErrorMsg),
1735 "Error in psSHP->sHooks.FWrite() while writing object of %u "
1736 "bytes to .shp file: %s",
1737 nRecordSize, strerror(errno));
1738 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
1747 if (bAppendToLastRecord) {
1750 else if (bAppendToFile) {
1757 psSHP->
panRecSize[nShapeId] = nRecordSize - 8;
1762 if (bFirstFeature) {
1779 for (
int i = 0; i < psObject->
nVertices; i++) {
1784 if (psObject->
padfZ) {
1790 if (psObject->
padfM) {
1857 if (hEntity < 0 || hEntity >= psSHP->nRecords)
1863 if (psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX !=
SHPLIB_NULLPTR) {
1864 unsigned int nOffset;
1865 unsigned int nLength;
1867 if (psSHP->sHooks.FSeek(psSHP->fpSHX, 100 + 8 * hEntity, 0) != 0 ||
1868 psSHP->sHooks.FRead(&nOffset, 1, 4, psSHP->fpSHX) != 4 ||
1869 psSHP->sHooks.FRead(&nLength, 1, 4, psSHP->fpSHX) != 4) {
1871 snprintf(str, sizeof(str),
1872 "Error in fseek()/fread() reading object from .shx file "
1875 str[sizeof(str) - 1] =
'\0';
1877 psSHP->sHooks.Error(str);
1878 return SHPLIB_NULLPTR;
1880#
if !defined(SHP_BIG_ENDIAN)
1885 if (nOffset >
STATIC_CAST(
unsigned int, INT_MAX)) {
1887 snprintf(str,
sizeof(str),
"Invalid offset for entity %d", hEntity);
1888 str[
sizeof(str) - 1] =
'\0';
1890 psSHP->sHooks.Error(str);
1893 if (nLength >
STATIC_CAST(
unsigned int, INT_MAX / 2 - 4)) {
1895 snprintf(str,
sizeof(str),
"Invalid length for entity %d", hEntity);
1896 str[
sizeof(str) - 1] =
'\0';
1898 psSHP->sHooks.Error(str);
1902 psSHP->panRecOffset[hEntity] = nOffset * 2;
1903 psSHP->panRecSize[hEntity] = nLength * 2;
1909 const int nEntitySize = psSHP->
panRecSize[hEntity] + 8;
1910 if (nEntitySize > psSHP->
nBufSize) {
1911 int nNewBufSize = nEntitySize;
1912 if (nNewBufSize < INT_MAX - nNewBufSize / 3)
1913 nNewBufSize += nNewBufSize / 3;
1915 nNewBufSize = INT_MAX;
1921 if (nNewBufSize >= 10 * 1024 * 1024) {
1922 if (psSHP->
nBufSize < 10 * 1024 * 1024) {
1926 if (nFileSize >= UINT_MAX)
1942 snprintf(str,
sizeof(str),
1943 "Error in fread() reading object of size %d at offset "
1944 "%u from .shp file",
1946 str[
sizeof(str) - 1] =
'\0';
1953 unsigned char *pabyRecNew =
1956 char szErrorMsg[160];
1957 snprintf(szErrorMsg,
sizeof(szErrorMsg),
1958 "Not enough memory to allocate requested memory "
1959 "(nNewBufSize=%d). "
1960 "Probably broken SHP file",
1962 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
1987 snprintf(str,
sizeof(str),
1988 "Error in fseek() reading object from .shp file at offset %u",
1990 str[
sizeof(str) - 1] =
'\0';
2009 if (nBytesRead >= 8 && nBytesRead == nEntitySize - 8) {
2011 int nSHPContentLength;
2012 memcpy(&nSHPContentLength, psSHP->
pabyRec + 4, 4);
2013#if !defined(SHP_BIG_ENDIAN)
2016 if (nSHPContentLength < 0 || nSHPContentLength > INT_MAX / 2 - 4 ||
2017 2 * nSHPContentLength + 8 != nBytesRead) {
2019 snprintf(str,
sizeof(str),
2020 "Sanity check failed when trying to recover from "
2021 "inconsistent .shx/.shp with shape %d",
2023 str[
sizeof(str) - 1] =
'\0';
2029 else if (nBytesRead != nEntitySize) {
2035 snprintf(str,
sizeof(str),
2036 "Error in fread() reading object of size %d at offset %u from "
2039 str[
sizeof(str) - 1] =
'\0';
2045 if (8 + 4 > nEntitySize) {
2046 char szErrorMsg[160];
2047 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2048 "Corrupted .shp file : shape %d : nEntitySize = %d", hEntity,
2050 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2055 memcpy(&nSHPType, psSHP->
pabyRec + 8, 4);
2057#if defined(SHP_BIG_ENDIAN)
2067 psSHP->
sHooks.
Error(
"Invalid read pattern in fast read mode. "
2068 "SHPDestroyObject() should be called.");
2095 if (40 + 8 + 4 > nEntitySize) {
2096 char szErrorMsg[160];
2097 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2098 "Corrupted .shp file : shape %d : nEntitySize = %d",
2099 hEntity, nEntitySize);
2100 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2110#if defined(SHP_BIG_ENDIAN)
2129 memcpy(&nPoints, psSHP->
pabyRec + 40 + 8, 4);
2131 memcpy(&nParts, psSHP->
pabyRec + 36 + 8, 4);
2133#if defined(SHP_BIG_ENDIAN)
2140 nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000) {
2141 char szErrorMsg[160];
2142 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2143 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u.",
2144 hEntity, nPoints, nParts);
2145 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2154 int nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
2158 nRequiredSize += 16 + 8 * nPoints;
2161 nRequiredSize += 4 * nParts;
2163 if (nRequiredSize > nEntitySize) {
2164 char szErrorMsg[160];
2165 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2166 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, "
2168 hEntity, nPoints, nParts, nEntitySize);
2169 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2179 const int nObjectBufSize =
2180 4 *
sizeof(double) * nPoints + 2 *
sizeof(
int) * nParts;
2181 pBuffer = SHPReallocObjectBufIfNecessary(psSHP, nObjectBufSize);
2182 ppBuffer = &pBuffer;
2187 double *, SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints));
2189 double *, SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints));
2191 double *, SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints));
2193 double *, SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints));
2195 psShape->
nParts = nParts;
2197 STATIC_CAST(
int *, SHPAllocBuffer(ppBuffer, nParts *
sizeof(
int)));
2199 STATIC_CAST(
int *, SHPAllocBuffer(ppBuffer, nParts *
sizeof(
int)));
2207 char szErrorMsg[160];
2208 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2209 "Not enough memory to allocate requested memory "
2210 "(nPoints=%u, nParts=%u) for shape %d. "
2211 "Probably broken SHP file",
2212 nPoints, nParts, hEntity);
2213 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2219 for (
int i = 0;
STATIC_CAST(uint32_t, i) < nParts; i++)
2228 for (
int i = 0;
STATIC_CAST(uint32_t, i) < nParts; i++) {
2229#if defined(SHP_BIG_ENDIAN)
2238 char szErrorMsg[160];
2239 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2240 "Corrupted .shp file : shape %d : panPartStart[%d] = "
2241 "%d, nVertices = %d",
2244 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2251 char szErrorMsg[160];
2252 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2253 "Corrupted .shp file : shape %d : panPartStart[%d] = "
2254 "%d, panPartStart[%d] = %d",
2257 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2264 int nOffset = 44 + 8 + 4 * nParts;
2273 for (
int i = 0;
STATIC_CAST(uint32_t, i) < nParts; i++) {
2274#if defined(SHP_BIG_ENDIAN)
2279 nOffset += 4 * nParts;
2287 for (
int i = 0;
STATIC_CAST(uint32_t, i) < nPoints; i++) {
2288#if defined(SHP_BIG_ENDIAN)
2290 psSHP->
pabyRec + nOffset + i * 16);
2292 psSHP->
pabyRec + nOffset + i * 16 + 8);
2294 memcpy(psShape->
padfX + i, psSHP->
pabyRec + nOffset + i * 16, 8);
2295 memcpy(psShape->
padfY + i, psSHP->
pabyRec + nOffset + i * 16 + 8,
2300 nOffset += 16 * nPoints;
2310#if defined(SHP_BIG_ENDIAN)
2319 for (
int i = 0;
STATIC_CAST(uint32_t, i) < nPoints; i++) {
2320#if defined(SHP_BIG_ENDIAN)
2322 psSHP->
pabyRec + nOffset + 16 + i * 8);
2324 memcpy(psShape->
padfZ + i,
2325 psSHP->
pabyRec + nOffset + 16 + i * 8, 8);
2329 nOffset += 16 + 8 * nPoints;
2343 if (nEntitySize >=
STATIC_CAST(
int, nOffset + 16 + 8 * nPoints)) {
2344#if defined(SHP_BIG_ENDIAN)
2352 for (
int i = 0;
STATIC_CAST(uint32_t, i) < nPoints; i++) {
2353#if defined(SHP_BIG_ENDIAN)
2355 psSHP->
pabyRec + nOffset + 16 + i * 8);
2357 memcpy(psShape->
padfM + i,
2358 psSHP->
pabyRec + nOffset + 16 + i * 8, 8);
2374 if (44 + 4 > nEntitySize) {
2375 char szErrorMsg[160];
2376 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2377 "Corrupted .shp file : shape %d : nEntitySize = %d",
2378 hEntity, nEntitySize);
2379 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2385 memcpy(&nPoints, psSHP->
pabyRec + 44, 4);
2387#if defined(SHP_BIG_ENDIAN)
2392 if ( nPoints > 50 * 1000 * 1000) {
2393 char szErrorMsg[160];
2394 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2395 "Corrupted .shp file : shape %d : nPoints = %u", hEntity,
2397 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2403 int nRequiredSize = 48 + nPoints * 16;
2405 nRequiredSize += 16 + nPoints * 8;
2407 if (nRequiredSize > nEntitySize) {
2408 char szErrorMsg[160];
2409 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2410 "Corrupted .shp file : shape %d : nPoints = %u, "
2412 hEntity, nPoints, nEntitySize);
2413 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2423 const int nObjectBufSize = 4 *
sizeof(double) * nPoints;
2424 pBuffer = SHPReallocObjectBufIfNecessary(psSHP, nObjectBufSize);
2425 ppBuffer = &pBuffer;
2431 double *, SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints));
2433 double *, SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints));
2435 double *, SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints));
2437 double *, SHPAllocBuffer(ppBuffer,
sizeof(
double) * nPoints));
2443 char szErrorMsg[160];
2444 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2445 "Not enough memory to allocate requested memory "
2446 "(nPoints=%u) for shape %d. "
2447 "Probably broken SHP file",
2449 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2455 for (
int i = 0;
STATIC_CAST(uint32_t, i) < nPoints; i++) {
2456#if defined(SHP_BIG_ENDIAN)
2458 psSHP->
pabyRec + 48 + 16 * i);
2460 psSHP->
pabyRec + 48 + 16 * i + 8);
2462 memcpy(psShape->
padfX + i, psSHP->
pabyRec + 48 + 16 * i, 8);
2463 memcpy(psShape->
padfY + i, psSHP->
pabyRec + 48 + 16 * i + 8, 8);
2467 int nOffset = 48 + 16 * nPoints;
2474#if defined(SHP_BIG_ENDIAN)
2492#if defined(SHP_BIG_ENDIAN)
2500 for (
int i = 0;
STATIC_CAST(uint32_t, i) < nPoints; i++) {
2501#if defined(SHP_BIG_ENDIAN)
2503 psSHP->
pabyRec + nOffset + 16 + i * 8);
2505 memcpy(psShape->
padfZ + i,
2506 psSHP->
pabyRec + nOffset + 16 + i * 8, 8);
2510 nOffset += 16 + 8 * nPoints;
2523 if (nEntitySize >=
STATIC_CAST(
int, nOffset + 16 + 8 * nPoints)) {
2524#if defined(SHP_BIG_ENDIAN)
2532 for (
int i = 0;
STATIC_CAST(uint32_t, i) < nPoints; i++) {
2533#if defined(SHP_BIG_ENDIAN)
2535 psSHP->
pabyRec + nOffset + 16 + i * 8);
2537 memcpy(psShape->
padfM + i,
2538 psSHP->
pabyRec + nOffset + 16 + i * 8, 8);
2559 psShape->
padfZ[0] = 0.0;
2560 psShape->
padfM[0] = 0.0;
2571 char szErrorMsg[160];
2572 snprintf(szErrorMsg,
sizeof(szErrorMsg),
2573 "Corrupted .shp file : shape %d : nEntitySize = %d",
2574 hEntity, nEntitySize);
2575 szErrorMsg[
sizeof(szErrorMsg) - 1] =
'\0';
2580#if defined(SHP_BIG_ENDIAN)
2588 int nOffset = 20 + 8;
2596#if defined(SHP_BIG_ENDIAN)
2613 if (nEntitySize >= nOffset + 8) {
2614#if defined(SHP_BIG_ENDIAN)
2876 for (
int iVert = 1; iVert < psObject->
nVertices; ++iVert) {
2877 if (psObject->
padfZ[iVert] != psObject->
padfZ[0]) {
2888 for (
int iOpRing = 0; iOpRing < psObject->
nParts; iOpRing++) {
2889 const int nVertStart = psObject->
panPartStart[iOpRing];
2890 const int nVertCount = SHPGetPartVertexCount(psObject, iOpRing);
2901 int bDoIsInnerRingTest =
TRUE;
2903 int bPartSameZ =
TRUE;
2904 for (
int iVert = nVertStart + 1; iVert < nVertStart + nVertCount;
2906 if (psObject->
padfZ[iVert] != psObject->
padfZ[nVertStart]) {
2912 bDoIsInnerRingTest =
FALSE;
2916 if (bDoIsInnerRingTest) {
2917 for (
int iTolerance = 0; iTolerance < 2; iTolerance++) {
2925 const double dfRelativeTolerance = (iTolerance == 0) ? 1e-9 : 0;
2926 for (
int iVert = nVertStart;
2927 iVert + 1 < nVertStart + nVertCount; ++iVert) {
2931 const double dfTestX =
2932 (psObject->
padfX[iVert] + psObject->
padfX[iVert + 1]) /
2934 const double dfTestY =
2935 (psObject->
padfY[iVert] + psObject->
padfY[iVert + 1]) /
2937 const double dfTestZ =
2938 !bSameZ ? psObject->
padfZ[nVertStart] : 0;
2940 bInner = SHPRewindIsInnerRing(psObject, iOpRing, dfTestX,
2941 dfTestY, dfRelativeTolerance,
2962 double dfSum = psObject->
padfX[nVertStart] *
2963 (psObject->
padfY[nVertStart + 1] -
2964 psObject->
padfY[nVertStart + nVertCount - 1]);
2965 int iVert = nVertStart + 1;
2966 for (; iVert < nVertStart + nVertCount - 1; iVert++) {
2967 dfSum += psObject->
padfX[iVert] *
2968 (psObject->
padfY[iVert + 1] - psObject->
padfY[iVert - 1]);
2971 dfSum += psObject->
padfX[iVert] *
2972 (psObject->
padfY[nVertStart] - psObject->
padfY[iVert - 1]);
2979 if ((dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner)) {
2981 for (
int i = 0; i < nVertCount / 2; i++) {
2983 double dfSaved = psObject->
padfX[nVertStart + i];
2984 psObject->
padfX[nVertStart + i] =
2985 psObject->
padfX[nVertStart + nVertCount - i - 1];
2986 psObject->
padfX[nVertStart + nVertCount - i - 1] = dfSaved;
2989 dfSaved = psObject->
padfY[nVertStart + i];
2990 psObject->
padfY[nVertStart + i] =
2991 psObject->
padfY[nVertStart + nVertCount - i - 1];
2992 psObject->
padfY[nVertStart + nVertCount - i - 1] = dfSaved;
2995 if (psObject->
padfZ) {
2996 dfSaved = psObject->
padfZ[nVertStart + i];
2997 psObject->
padfZ[nVertStart + i] =
2998 psObject->
padfZ[nVertStart + nVertCount - i - 1];
2999 psObject->
padfZ[nVertStart + nVertCount - i - 1] = dfSaved;
3003 if (psObject->
padfM) {
3004 dfSaved = psObject->
padfM[nVertStart + i];
3005 psObject->
padfM[nVertStart + i] =
3006 psObject->
padfM[nVertStart + nVertCount - i - 1];
3007 psObject->
padfM[nVertStart + nVertCount - i - 1] = dfSaved;