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
50#ifndef SHP_RESTORE_SHX_HINT_MESSAGE
51#define SHP_RESTORE_SHX_HINT_MESSAGE \
52 " Use SHPRestoreSHX() to restore or create it."
65 psSHP->sHooks.Error(
"SHPWriteHeader failed : SHX file is closed");
79#if !defined(SHP_BIG_ENDIAN)
85#if defined(SHP_BIG_ENDIAN)
91#if defined(SHP_BIG_ENDIAN)
97#if defined(SHP_BIG_ENDIAN)
102#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)
137#if defined(SHP_BIG_ENDIAN)
144 if (
psSHP->sHooks.FSeek(
psSHP->fpSHP, 0, 0) != 0 ||
160#if !defined(SHP_BIG_ENDIAN)
164 if (
psSHP->sHooks.FSeek(
psSHP->fpSHX, 0, 0) != 0 ||
182 psSHP->sHooks.Error(
"Failure allocating panSHX");
186 for (
int i = 0; i <
psSHP->nRecords; i++) {
189#if !defined(SHP_BIG_ENDIAN)
232static int SHPGetLenWithoutExtension(
const char *
pszBasename)
235 for (
int i =
nLen - 1;
296 psSHP->sHooks.pvUserData);
305 "Unable to open %s.shp or %s.SHP in %s mode.",
pszFullname,
323 psSHP->sHooks.pvUserData);
353 psSHP->sHooks.Error(
".shp file is unreadable, or corrupt.");
365 psSHP->nFileSize *= 2;
375 psSHP->sHooks.Error(
".shx file is unreadable, or corrupt.");
390 if (
psSHP->nRecords < 0 ||
psSHP->nRecords > 256000000) {
394 "Record count in .shx header is %d, which seems\n"
395 "unreasonable. Assuming header is corrupt.",
409 if (
psSHP->nRecords >= 1024 * 1024) {
412 if (nFileSize > 100 &&
424#if defined(SHP_BIG_ENDIAN)
430#if defined(SHP_BIG_ENDIAN)
436#if defined(SHP_BIG_ENDIAN)
442#if defined(SHP_BIG_ENDIAN)
448#if defined(SHP_BIG_ENDIAN)
454#if defined(SHP_BIG_ENDIAN)
460#if defined(SHP_BIG_ENDIAN)
466#if defined(SHP_BIG_ENDIAN)
480 psSHP->panRecOffset =
499 "Not enough memory to allocate requested memory (nRecords=%d).\n"
500 "Probably broken SHP file",
506 if (
psSHP->panRecOffset)
508 if (
psSHP->panRecSize)
518 sizeof(
unsigned int) *
MAX(1,
psSHP->nMaxRecords));
520 sizeof(
unsigned int) *
MAX(1,
psSHP->nMaxRecords));
531 "Failed to read all values for %d records in .shx file: %s.",
553 for (
int i = 0; i <
psSHP->nRecords; i++) {
556#if !defined(SHP_BIG_ENDIAN)
562#if !defined(SHP_BIG_ENDIAN)
568 snprintf(str,
sizeof(str),
"Invalid offset for entity %d", i);
569 str[
sizeof(str) - 1] =
'\0';
571 psSHP->sHooks.Error(str);
578 snprintf(str,
sizeof(str),
"Invalid length for entity %d", i);
579 str[
sizeof(str) - 1] =
'\0';
581 psSHP->sHooks.Error(str);
677 psHooks->Error(
".shp file is unreadable, or corrupt.");
704 "Error opening file %s.shx for writing",
pszFullname);
742 unsigned int nRecordLength = 0;
746 psHooks->FRead(&nRecordLength, 4, 1, fpSHP) == 1 &&
747 psHooks->FRead(&nSHPType, 4, 1, fpSHP) == 1) {
751#if !defined(SHP_BIG_ENDIAN)
757#if !defined(SHP_BIG_ENDIAN)
760#if defined(SHP_BIG_ENDIAN)
765 if (nRecordLength < 1 ||
769 "Error parsing .shp to restore .shx. "
770 "Invalid record length = %u at record starting at "
789 "Error parsing .shp to restore .shx. "
790 "Invalid shape type = %d at record starting at "
811 "Error parsing .shp to restore .shx. "
812 "Cannot read first bytes of record starting at "
822 psHooks->Error(
"Error parsing .shp to restore .shx. "
823 "Not expected number of bytes");
829#if !defined(SHP_BIG_ENDIAN)
929 for (
int i = 0; i < 4; i++) {
1026#if !defined(SHP_BIG_ENDIAN)
1032#if defined(SHP_BIG_ENDIAN)
1038#if defined(SHP_BIG_ENDIAN)
1071#if !defined(SHP_BIG_ENDIAN)
1093 psSHP->fpSHP = fpSHP;
1094 psSHP->fpSHX = fpSHX;
1095 psSHP->nShapeType = nShapeType;
1096 psSHP->nFileSize = 100;
1097 psSHP->panRecOffset =
1104 psSHP->sHooks.Error(
"Not enough memory to allocate requested memory");
1107 if (
psSHP->panRecOffset)
1109 if (
psSHP->panRecSize)
1132#if defined(SHP_BIG_ENDIAN)
1159 for (
int i = 0; i <
psObject->nVertices; i++) {
1181 const int *panPartStart,
const int *panPartType,
1182 int nVertices,
const double *padfX,
const double *padfY,
1239 for (
int i = 0; i < nParts; i++) {
1241 psObject->panPartStart[i] = panPartStart[i];
1244 psObject->panPartType[i] = panPartType[i];
1255 if (nVertices > 0) {
1259 :
calloc(nVertices,
sizeof(
double)));
1262 :
calloc(nVertices,
sizeof(
double)));
1342 if (nShapeId != -1 && nShapeId >=
psSHP->nRecords)
1348 if (nShapeId == -1 &&
psSHP->nRecords + 1 >
psSHP->nMaxRecords) {
1361 psSHP->sHooks.Error(
"Failed to write shape object. "
1362 "Memory allocation error.");
1371 psSHP->sHooks.Error(
"Failed to write shape object. "
1372 "Memory allocation error.");
1392 psSHP->sHooks.Error(
"Failed to write shape object. Too big geometry.");
1398 psSHP->sHooks.Error(
"Failed to write shape object. "
1399 "Memory allocation error.");
1417 _SHPSetBounds(pabyRec + 12,
psObject);
1419#if defined(SHP_BIG_ENDIAN)
1425 ByteCopy(&nParts, pabyRec + 36 + 8, 4);
1434 for (
int i = 0; i <
psObject->nParts; i++) {
1435#if defined(SHP_BIG_ENDIAN)
1447 for (
int i = 0; i <
psObject->nParts; i++) {
1448#if defined(SHP_BIG_ENDIAN)
1458 for (
int i = 0; i <
psObject->nVertices; i++) {
1462#if defined(SHP_BIG_ENDIAN)
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)
1545 for (
int i = 0; i <
psObject->nVertices; i++) {
1549#if defined(SHP_BIG_ENDIAN)
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)
1659 if (nShapeId != -1 &&
1660 psSHP->panRecOffset[nShapeId] +
psSHP->panRecSize[nShapeId] + 8 ==
1665 else if (nShapeId == -1 ||
psSHP->panRecSize[nShapeId] <
nRecordSize - 8) {
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';
1674 psSHP->sHooks.Error(str);
1690 (nShapeId < 0) ?
psSHP->nRecords + 1 : nShapeId + 1;
1691#if !defined(SHP_BIG_ENDIAN)
1697#if !defined(SHP_BIG_ENDIAN)
1703#if defined(SHP_BIG_ENDIAN)
1721 "Error in psSHP->sHooks.FSeek() while writing object to "
1735 "Error in psSHP->sHooks.FWrite() while writing object of %u "
1736 "bytes to .shp file: %s",
1752 nShapeId =
psSHP->nRecords++;
1754 psSHP->panRecOffset[nShapeId] =
psSHP->nFileSize;
1764 psSHP->adBoundsMin[0] =
psSHP->adBoundsMax[0] = 0.0;
1765 psSHP->adBoundsMin[1] =
psSHP->adBoundsMax[1] = 0.0;
1766 psSHP->adBoundsMin[2] =
psSHP->adBoundsMax[2] = 0.0;
1767 psSHP->adBoundsMin[3] =
psSHP->adBoundsMax[3] = 0.0;
1772 psSHP->adBoundsMin[2] =
psSHP->adBoundsMax[2] =
1774 psSHP->adBoundsMin[3] =
psSHP->adBoundsMax[3] =
1779 for (
int i = 0; i <
psObject->nVertices; i++) {
1785 psSHP->adBoundsMin[2] =
1787 psSHP->adBoundsMax[2] =
1791 psSHP->adBoundsMin[3] =
1793 psSHP->adBoundsMax[3] =
1805static void *SHPAllocBuffer(
unsigned char **
pBuffer,
int nSize)
1814 (*pBuffer) +=
nSize;
1822static unsigned char *SHPReallocObjectBufIfNecessary(
SHPHandle psSHP,
1825 if (nObjectBufSize == 0) {
1826 nObjectBufSize = 4 *
sizeof(
double);
1830 if (nObjectBufSize >
psSHP->nObjectBufSize) {
1835 psSHP->nObjectBufSize = nObjectBufSize;
1872 "Error in fseek()/fread() reading object from .shx file "
1875 str[
sizeof(str) - 1] =
'\0';
1877 psSHP->sHooks.Error(str);
1880#if !defined(SHP_BIG_ENDIAN)
1888 str[
sizeof(str) - 1] =
'\0';
1890 psSHP->sHooks.Error(str);
1896 str[
sizeof(str) - 1] =
'\0';
1898 psSHP->sHooks.Error(str);
1922 if (
psSHP->nBufSize < 10 * 1024 * 1024) {
1925 nFileSize =
psSHP->sHooks.FTell(
psSHP->fpSHP);
1943 "Error in fread() reading object of size %d at offset "
1944 "%u from .shp file",
1946 str[
sizeof(str) - 1] =
'\0';
1948 psSHP->sHooks.Error(str);
1958 "Not enough memory to allocate requested memory "
1959 "(nNewBufSize=%d). "
1960 "Probably broken SHP file",
1988 "Error in fseek() reading object from .shp file at offset %u",
1990 str[
sizeof(str) - 1] =
'\0';
1992 psSHP->sHooks.Error(str);
2013#if !defined(SHP_BIG_ENDIAN)
2020 "Sanity check failed when trying to recover from "
2021 "inconsistent .shx/.shp with shape %d",
2023 str[
sizeof(str) - 1] =
'\0';
2025 psSHP->sHooks.Error(str);
2036 "Error in fread() reading object of size %d at offset %u from "
2039 str[
sizeof(str) - 1] =
'\0';
2041 psSHP->sHooks.Error(str);
2048 "Corrupted .shp file : shape %d : nEntitySize = %d",
hEntity,
2057#if defined(SHP_BIG_ENDIAN)
2065 if (
psSHP->bFastModeReadObject) {
2066 if (
psSHP->psCachedObject->bFastModeReadObject) {
2067 psSHP->sHooks.Error(
"Invalid read pattern in fast read mode. "
2068 "SHPDestroyObject() should be called.");
2078 psSHP->sHooks.Error(
"Out of memory.");
2085 psShape->bFastModeReadObject =
psSHP->bFastModeReadObject;
2098 "Corrupted .shp file : shape %d : nEntitySize = %d",
2110#if defined(SHP_BIG_ENDIAN)
2133#if defined(SHP_BIG_ENDIAN)
2140 nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000) {
2143 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u.",
2166 "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, "
2178 if (
psShape->bFastModeReadObject) {
2179 const int nObjectBufSize =
2181 pBuffer = SHPReallocObjectBufIfNecessary(
psSHP, nObjectBufSize);
2209 "Not enough memory to allocate requested memory "
2210 "(nPoints=%u, nParts=%u) for shape %d. "
2211 "Probably broken SHP file",
2229#if defined(SHP_BIG_ENDIAN)
2234 if (
psShape->panPartStart[i] < 0 ||
2240 "Corrupted .shp file : shape %d : panPartStart[%d] = "
2241 "%d, nVertices = %d",
2253 "Corrupted .shp file : shape %d : panPartStart[%d] = "
2254 "%d, panPartStart[%d] = %d",
2256 psShape->panPartStart[i - 1]);
2264 int nOffset = 44 + 8 + 4 * nParts;
2274#if defined(SHP_BIG_ENDIAN)
2288#if defined(SHP_BIG_ENDIAN)
2310#if defined(SHP_BIG_ENDIAN)
2320#if defined(SHP_BIG_ENDIAN)
2331 else if (
psShape->bFastModeReadObject) {
2344#if defined(SHP_BIG_ENDIAN)
2353#if defined(SHP_BIG_ENDIAN)
2363 else if (
psShape->bFastModeReadObject) {
2377 "Corrupted .shp file : shape %d : nEntitySize = %d",
2387#if defined(SHP_BIG_ENDIAN)
2392 if (
nPoints > 50 * 1000 * 1000) {
2395 "Corrupted .shp file : shape %d : nPoints = %u",
hEntity,
2410 "Corrupted .shp file : shape %d : nPoints = %u, "
2422 if (
psShape->bFastModeReadObject) {
2424 pBuffer = SHPReallocObjectBufIfNecessary(
psSHP, nObjectBufSize);
2445 "Not enough memory to allocate requested memory "
2446 "(nPoints=%u) for shape %d. "
2447 "Probably broken SHP file",
2456#if defined(SHP_BIG_ENDIAN)
2458 psSHP->pabyRec + 48 + 16 * i);
2460 psSHP->pabyRec + 48 + 16 * i + 8);
2474#if defined(SHP_BIG_ENDIAN)
2492#if defined(SHP_BIG_ENDIAN)
2501#if defined(SHP_BIG_ENDIAN)
2512 else if (
psShape->bFastModeReadObject)
2524#if defined(SHP_BIG_ENDIAN)
2533#if defined(SHP_BIG_ENDIAN)
2543 else if (
psShape->bFastModeReadObject)
2554 if (
psShape->bFastModeReadObject) {
2573 "Corrupted .shp file : shape %d : nEntitySize = %d",
2580#if defined(SHP_BIG_ENDIAN)
2596#if defined(SHP_BIG_ENDIAN)
2614#if defined(SHP_BIG_ENDIAN)
2657 return "MultiPoint";
2669 return "MultiPointZ";
2681 return "MultiPointM";
2684 return "MultiPatch";
2687 return "UnknownShapeType";
2699 return "TriangleStrip";
2702 return "TriangleFan";
2717 return "UnknownPartType";
2730 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)
#define SHP_RESTORE_SHX_HINT_MESSAGE
SHPObject * SHPReadObject(const SHPHandle psSHP, int hEntity)
SHPObject * psCachedObject