31#define ByteCopy(a, b, c) memcpy(b, a, c)
33#define MIN(a, b) ((a < b) ? a : b)
34#define MAX(a, b) ((a > b) ? a : b)
40#define snprintf _snprintf
44#define snprintf _snprintf
59 psSHP->sHooks.Error(
"SHPWriteHeader failed : SHX file is closed");
73#if !defined(SHP_BIG_ENDIAN)
79#if defined(SHP_BIG_ENDIAN)
85#if defined(SHP_BIG_ENDIAN)
91#if defined(SHP_BIG_ENDIAN)
96#if defined(SHP_BIG_ENDIAN)
101#if defined(SHP_BIG_ENDIAN)
107#if defined(SHP_BIG_ENDIAN)
113#if defined(SHP_BIG_ENDIAN)
119#if defined(SHP_BIG_ENDIAN)
125#if defined(SHP_BIG_ENDIAN)
131#if defined(SHP_BIG_ENDIAN)
138 if (
psSHP->sHooks.FSeek(
psSHP->fpSHP, 0, 0) != 0 ||
154#if !defined(SHP_BIG_ENDIAN)
158 if (
psSHP->sHooks.FSeek(
psSHP->fpSHX, 0, 0) != 0 ||
176 psSHP->sHooks.Error(
"Failure allocatin panSHX");
180 for (
int i = 0; i <
psSHP->nRecords; i++) {
183#if !defined(SHP_BIG_ENDIAN)
226static int SHPGetLenWithoutExtension(
const char *
pszBasename)
229 for (
int i =
nLen - 1;
284 psSHP->sHooks.pvUserData);
292 "Unable to open %s.shp or %s.SHP in %s mode.",
pszFullname,
309 psSHP->sHooks.pvUserData);
317 "Unable to open %s.shx or %s.SHX. "
318 "Set SHAPE_RESTORE_SHX config option to YES to restore or "
337 psSHP->sHooks.Error(
".shp file is unreadable, or corrupt.");
349 psSHP->nFileSize *= 2;
359 psSHP->sHooks.Error(
".shx file is unreadable, or corrupt.");
374 if (
psSHP->nRecords < 0 ||
psSHP->nRecords > 256000000) {
378 "Record count in .shx header is %d, which seems\n"
379 "unreasonable. Assuming header is corrupt.",
393 if (
psSHP->nRecords >= 1024 * 1024) {
396 if (nFileSize > 100 &&
408#if defined(SHP_BIG_ENDIAN)
414#if defined(SHP_BIG_ENDIAN)
420#if defined(SHP_BIG_ENDIAN)
426#if defined(SHP_BIG_ENDIAN)
432#if defined(SHP_BIG_ENDIAN)
438#if defined(SHP_BIG_ENDIAN)
444#if defined(SHP_BIG_ENDIAN)
450#if defined(SHP_BIG_ENDIAN)
464 psSHP->panRecOffset =
483 "Not enough memory to allocate requested memory (nRecords=%d).\n"
484 "Probably broken SHP file",
490 if (
psSHP->panRecOffset)
492 if (
psSHP->panRecSize)
502 sizeof(
unsigned int) *
MAX(1,
psSHP->nMaxRecords));
504 sizeof(
unsigned int) *
MAX(1,
psSHP->nMaxRecords));
515 "Failed to read all values for %d records in .shx file: %s.",
537 for (
int i = 0; i <
psSHP->nRecords; i++) {
540#if !defined(SHP_BIG_ENDIAN)
546#if !defined(SHP_BIG_ENDIAN)
552 snprintf(str,
sizeof(str),
"Invalid offset for entity %d", i);
553 str[
sizeof(str) - 1] =
'\0';
555 psSHP->sHooks.Error(str);
562 snprintf(str,
sizeof(str),
"Invalid length for entity %d", i);
563 str[
sizeof(str) - 1] =
'\0';
565 psSHP->sHooks.Error(str);
657 psHooks->Error(
".shp file is unreadable, or corrupt.");
683 "Error opening file %s.shx for writing",
pszFullname);
712 unsigned int nRecordLength = 0;
716 psHooks->FRead(&nRecordLength, 4, 1, fpSHP) == 1 &&
717 psHooks->FRead(&nSHPType, 4, 1, fpSHP) == 1) {
721#if !defined(SHP_BIG_ENDIAN)
727#if !defined(SHP_BIG_ENDIAN)
730#if defined(SHP_BIG_ENDIAN)
735 if (nRecordLength < 1 ||
739 "Error parsing .shp to restore .shx. "
740 "Invalid record length = %u at record starting at "
759 "Error parsing .shp to restore .shx. "
760 "Invalid shape type = %d at record starting at "
781 "Error parsing .shp to restore .shx. "
782 "Cannot read first bytes of record starting at "
792 psHooks->Error(
"Error parsing .shp to restore .shx. "
793 "Not expected number of bytes");
799#if !defined(SHP_BIG_ENDIAN)
899 for (
int i = 0; i < 4; i++) {
978#if !defined(SHP_BIG_ENDIAN)
984#if defined(SHP_BIG_ENDIAN)
990#if defined(SHP_BIG_ENDIAN)
1022#if !defined(SHP_BIG_ENDIAN)
1045 psSHP->fpSHP = fpSHP;
1046 psSHP->fpSHX = fpSHX;
1047 psSHP->nShapeType = nShapeType;
1048 psSHP->nFileSize = 100;
1049 psSHP->panRecOffset =
1056 psSHP->sHooks.Error(
"Not enough memory to allocate requested memory");
1059 if (
psSHP->panRecOffset)
1061 if (
psSHP->panRecSize)
1084#if defined(SHP_BIG_ENDIAN)
1111 for (
int i = 0; i <
psObject->nVertices; i++) {
1133 const int *panPartStart,
const int *panPartType,
1134 int nVertices,
const double *padfX,
const double *padfY,
1183 for (
int i = 0; i < nParts; i++) {
1185 psObject->panPartStart[i] = panPartStart[i];
1188 psObject->panPartType[i] = panPartType[i];
1199 if (nVertices > 0) {
1203 :
calloc(nVertices,
sizeof(
double)));
1206 :
calloc(nVertices,
sizeof(
double)));
1275 if (nShapeId != -1 && nShapeId >=
psSHP->nRecords)
1281 if (nShapeId == -1 &&
psSHP->nRecords + 1 >
psSHP->nMaxRecords) {
1294 psSHP->sHooks.Error(
"Failed to write shape object. "
1295 "Memory allocation error.");
1304 psSHP->sHooks.Error(
"Failed to write shape object. "
1305 "Memory allocation error.");
1325 psSHP->sHooks.Error(
"Failed to write shape object. Too big geometry.");
1331 psSHP->sHooks.Error(
"Failed to write shape object. "
1332 "Memory allocation error.");
1350 _SHPSetBounds(pabyRec + 12,
psObject);
1352#if defined(SHP_BIG_ENDIAN)
1358 ByteCopy(&nParts, pabyRec + 36 + 8, 4);
1367 for (
int i = 0; i <
psObject->nParts; i++) {
1368#if defined(SHP_BIG_ENDIAN)
1380 for (
int i = 0; i <
psObject->nParts; i++) {
1381#if defined(SHP_BIG_ENDIAN)
1391 for (
int i = 0; i <
psObject->nVertices; i++) {
1395#if defined(SHP_BIG_ENDIAN)
1410#if defined(SHP_BIG_ENDIAN)
1416#if defined(SHP_BIG_ENDIAN)
1421 for (
int i = 0; i <
psObject->nVertices; i++) {
1423#if defined(SHP_BIG_ENDIAN)
1442#if defined(SHP_BIG_ENDIAN)
1448#if defined(SHP_BIG_ENDIAN)
1453 for (
int i = 0; i <
psObject->nVertices; i++) {
1455#if defined(SHP_BIG_ENDIAN)
1471 _SHPSetBounds(pabyRec + 12,
psObject);
1473#if defined(SHP_BIG_ENDIAN)
1478 for (
int i = 0; i <
psObject->nVertices; i++) {
1482#if defined(SHP_BIG_ENDIAN)
1492#if defined(SHP_BIG_ENDIAN)
1498#if defined(SHP_BIG_ENDIAN)
1503 for (
int i = 0; i <
psObject->nVertices; i++) {
1505#if defined(SHP_BIG_ENDIAN)
1516#if defined(SHP_BIG_ENDIAN)
1522#if defined(SHP_BIG_ENDIAN)
1527 for (
int i = 0; i <
psObject->nVertices; i++) {
1529#if defined(SHP_BIG_ENDIAN)
1546#if defined(SHP_BIG_ENDIAN)
1555#if defined(SHP_BIG_ENDIAN)
1564#if defined(SHP_BIG_ENDIAN)
1592 if (nShapeId != -1 &&
1593 psSHP->panRecOffset[nShapeId] +
psSHP->panRecSize[nShapeId] + 8 ==
1598 else if (nShapeId == -1 ||
psSHP->panRecSize[nShapeId] <
nRecordSize - 8) {
1602 "Failed to write shape object. "
1603 "The maximum file size of %u has been reached. "
1604 "The current record of size %u cannot be added.",
1606 str[
sizeof(str) - 1] =
'\0';
1607 psSHP->sHooks.Error(str);
1623 (nShapeId < 0) ?
psSHP->nRecords + 1 : nShapeId + 1;
1624#if !defined(SHP_BIG_ENDIAN)
1630#if !defined(SHP_BIG_ENDIAN)
1636#if defined(SHP_BIG_ENDIAN)
1654 "Error in psSHP->sHooks.FSeek() while writing object to "
1668 "Error in psSHP->sHooks.FWrite() while writing object of %u "
1669 "bytes to .shp file: %s",
1685 nShapeId =
psSHP->nRecords++;
1687 psSHP->panRecOffset[nShapeId] =
psSHP->nFileSize;
1697 psSHP->adBoundsMin[0] =
psSHP->adBoundsMax[0] = 0.0;
1698 psSHP->adBoundsMin[1] =
psSHP->adBoundsMax[1] = 0.0;
1699 psSHP->adBoundsMin[2] =
psSHP->adBoundsMax[2] = 0.0;
1700 psSHP->adBoundsMin[3] =
psSHP->adBoundsMax[3] = 0.0;
1705 psSHP->adBoundsMin[2] =
psSHP->adBoundsMax[2] =
1707 psSHP->adBoundsMin[3] =
psSHP->adBoundsMax[3] =
1712 for (
int i = 0; i <
psObject->nVertices; i++) {
1718 psSHP->adBoundsMin[2] =
1720 psSHP->adBoundsMax[2] =
1724 psSHP->adBoundsMin[3] =
1726 psSHP->adBoundsMax[3] =
1738static void *SHPAllocBuffer(
unsigned char **
pBuffer,
int nSize)
1747 (*pBuffer) +=
nSize;
1755static unsigned char *SHPReallocObjectBufIfNecessary(
SHPHandle psSHP,
1758 if (nObjectBufSize == 0) {
1759 nObjectBufSize = 4 *
sizeof(
double);
1763 if (nObjectBufSize >
psSHP->nObjectBufSize) {
1768 psSHP->nObjectBufSize = nObjectBufSize;
1805 "Error in fseek()/fread() reading object from .shx file "
1808 str[
sizeof(str) - 1] =
'\0';
1810 psSHP->sHooks.Error(str);
1813#if !defined(SHP_BIG_ENDIAN)
1821 str[
sizeof(str) - 1] =
'\0';
1823 psSHP->sHooks.Error(str);
1829 str[
sizeof(str) - 1] =
'\0';
1831 psSHP->sHooks.Error(str);
1855 if (
psSHP->nBufSize < 10 * 1024 * 1024) {
1858 nFileSize =
psSHP->sHooks.FTell(
psSHP->fpSHP);
1876 "Error in fread() reading object of size %d at offset "
1877 "%u from .shp file",
1879 str[
sizeof(str) - 1] =
'\0';
1881 psSHP->sHooks.Error(str);
1891 "Not enough memory to allocate requested memory "
1892 "(nNewBufSize=%d). "
1893 "Probably broken SHP file",
1921 "Error in fseek() reading object from .shp file at offset %u",
1923 str[
sizeof(str) - 1] =
'\0';
1925 psSHP->sHooks.Error(str);
1946#if !defined(SHP_BIG_ENDIAN)
1953 "Sanity check failed when trying to recover from "
1954 "inconsistent .shx/.shp with shape %d",
1956 str[
sizeof(str) - 1] =
'\0';
1958 psSHP->sHooks.Error(str);
1969 "Error in fread() reading object of size %d at offset %u from "
1972 str[
sizeof(str) - 1] =
'\0';
1974 psSHP->sHooks.Error(str);
1981 "Corrupted .shp file : shape %d : nEntitySize = %d",
hEntity,
1990#if defined(SHP_BIG_ENDIAN)
1998 if (
psSHP->bFastModeReadObject) {
1999 if (
psSHP->psCachedObject->bFastModeReadObject) {
2000 psSHP->sHooks.Error(
"Invalid read pattern in fast read mode. "
2001 "SHPDestroyObject() should be called.");
2014 psShape->bFastModeReadObject =
psSHP->bFastModeReadObject;
2027 "Corrupted .shp file : shape %d : nEntitySize = %d",
2039#if defined(SHP_BIG_ENDIAN)
2062#if defined(SHP_BIG_ENDIAN)
2069 nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000) {
2072 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u.",
2095 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, "
2107 if (
psShape->bFastModeReadObject) {
2108 const int nObjectBufSize =
2110 pBuffer = SHPReallocObjectBufIfNecessary(
psSHP, nObjectBufSize);
2138 "Not enough memory to allocate requested memory "
2139 "(nPoints=%u, nParts=%u) for shape %d. "
2140 "Probably broken SHP file",
2158#if defined(SHP_BIG_ENDIAN)
2163 if (
psShape->panPartStart[i] < 0 ||
2169 "Corrupted .shp file : shape %d : panPartStart[%d] = "
2170 "%d, nVertices = %d",
2182 "Corrupted .shp file : shape %d : panPartStart[%d] = "
2183 "%d, panPartStart[%d] = %d",
2185 psShape->panPartStart[i - 1]);
2193 int nOffset = 44 + 8 + 4 * nParts;
2203#if defined(SHP_BIG_ENDIAN)
2217#if defined(SHP_BIG_ENDIAN)
2239#if defined(SHP_BIG_ENDIAN)
2249#if defined(SHP_BIG_ENDIAN)
2260 else if (
psShape->bFastModeReadObject) {
2273#if defined(SHP_BIG_ENDIAN)
2282#if defined(SHP_BIG_ENDIAN)
2292 else if (
psShape->bFastModeReadObject) {
2306 "Corrupted .shp file : shape %d : nEntitySize = %d",
2316#if defined(SHP_BIG_ENDIAN)
2321 if (
nPoints > 50 * 1000 * 1000) {
2324 "Corrupted .shp file : shape %d : nPoints = %u",
hEntity,
2339 "Corrupted .shp file : shape %d : nPoints = %u, "
2351 if (
psShape->bFastModeReadObject) {
2353 pBuffer = SHPReallocObjectBufIfNecessary(
psSHP, nObjectBufSize);
2374 "Not enough memory to allocate requested memory "
2375 "(nPoints=%u) for shape %d. "
2376 "Probably broken SHP file",
2385#if defined(SHP_BIG_ENDIAN)
2387 psSHP->pabyRec + 48 + 16 * i);
2389 psSHP->pabyRec + 48 + 16 * i + 8);
2403#if defined(SHP_BIG_ENDIAN)
2421#if defined(SHP_BIG_ENDIAN)
2430#if defined(SHP_BIG_ENDIAN)
2441 else if (
psShape->bFastModeReadObject)
2453#if defined(SHP_BIG_ENDIAN)
2462#if defined(SHP_BIG_ENDIAN)
2472 else if (
psShape->bFastModeReadObject)
2483 if (
psShape->bFastModeReadObject) {
2502 "Corrupted .shp file : shape %d : nEntitySize = %d",
2509#if defined(SHP_BIG_ENDIAN)
2525#if defined(SHP_BIG_ENDIAN)
2543#if defined(SHP_BIG_ENDIAN)
2586 return "MultiPoint";
2598 return "MultiPointZ";
2610 return "MultiPointM";
2613 return "MultiPatch";
2616 return "UnknownShapeType";
2628 return "TriangleStrip";
2631 return "TriangleFan";
2646 return "UnknownPartType";
2659 if (
psShape->bFastModeReadObject) {
#define assert(condition)
void SASetupDefaultHooks(SAHooks *psHooks)
#define DISABLE_MULTIPATCH_MEASURE
#define SHP_SWAPDOUBLE_CPY(dst, src)
#define STATIC_CAST(type, x)
SHPObject * SHPCreateObject(int nSHPType, int nShapeId, int nParts, const int *panPartStart, const int *panPartType, int nVertices, const double *padfX, const double *padfY, const double *padfZ, const double *padfM)
SHPObject * SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX, const double *padfY, const double *padfZ)
void SHPClose(SHPHandle psSHP)
SHPHandle SHPOpenLLEx(const char *pszLayer, const char *pszAccess, const SAHooks *psHooks, int bRestoreSHX)
SHPHandle SHPCreateLL(const char *pszLayer, int nShapeType, const SAHooks *psHooks)
void SHPWriteHeader(SHPHandle psSHP)
void SHPDestroyObject(SHPObject *psShape)
const char * SHPTypeName(int nSHPType)
SHPHandle SHPOpenLL(const char *pszLayer, const char *pszAccess, const SAHooks *psHooks)
int SHPRewindObject(const SHPHandle hSHP, SHPObject *psObject)
SHPHandle SHPOpen(const char *pszLayer, const char *pszAccess)
const char * SHPPartTypeName(int nPartType)
void SHPSetFastModeReadObject(SHPHandle hSHP, int bFastMode)
void SHPComputeExtents(SHPObject *psObject)
#define ByteCopy(a, b, c)
int SHPRestoreSHX(const char *pszLayer, const char *pszAccess, const SAHooks *psHooks)
void SHPGetInfo(const SHPHandle psSHP, int *pnEntities, int *pnShapeType, double *padfMinBound, double *padfMaxBound)
SHPHandle SHPCreate(const char *pszLayer, int nShapeType)
int SHPWriteObject(SHPHandle psSHP, int nShapeId, const SHPObject *psObject)
SHPObject * SHPReadObject(const SHPHandle psSHP, int hEntity)
SHPObject * psCachedObject