diff --git a/lib/external/shapelib/README.md b/lib/external/shapelib/README.md index e004d2d0419..d446eccd014 100644 --- a/lib/external/shapelib/README.md +++ b/lib/external/shapelib/README.md @@ -1,12 +1,13 @@ # Update history of SHAPELIB copy -* files `shpopen.c`, `shapefil.h`, `dbfopen.c` +* files `shpopen.c`, `shapefil.h`, `dbfopen.c`, `shapefil_private.h` from GDAL [ogr/ogrsf_frmts/shape/](https://github.com/OSGeo/gdal/tree/master/ogr/ogrsf_frmts/shape) * file `safileio.c` from [SHAPELIB](http://download.osgeo.org/shapelib/) ## Last update +* taken from GDAL 3.9.2 and SHAPELIB 1.6.0 (Sep 2024) * taken from GDAL 3.5.3 and SHAPELIB 1.5.0 (Dec 2022) * taken from GDAL 2.1.2 and SHAPELIB 1.3.0 (Thu Nov 24 10:45:41 CET 2016) * taken from GDAL 1.5.1-SVN (Sun Mar 30 11:20:43 CEST 2008) @@ -15,44 +16,5 @@ ## Summary of fixes -* dbfopen.c - around line 1229: GDAL bug [ticket-#809](http://trac.osgeo.org/gdal/ticket/809) - * safileio.c - SHP_CVSID: ISO C does not allow extra ‘;’ outside of a function - -## Full fix - -```diff -diff --git a/lib/external/shapelib/dbfopen.c b/lib/external/shapelib/dbfopen.c -index 5380e3e20b..5151148d33 100644 ---- a/lib/external/shapelib/dbfopen.c -+++ b/lib/external/shapelib/dbfopen.c -@@ -1226,9 +1226,10 @@ DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName, - else if( psDBF->pachFieldType[iField] == 'N' - || psDBF->pachFieldType[iField] == 'F' ) - { -- if( psDBF->panFieldDecimals[iField] > 0 -- || psDBF->panFieldSize[iField] >= 10 ) -+ if( psDBF->panFieldDecimals[iField] > 0 ) { -+ /* || psDBF->panFieldSize[iField] >= 10 ) */ /* GDAL bug #809 */ - return( FTDouble ); -+ } - else - return( FTInteger ); - } -diff --git a/lib/external/shapelib/safileio.c b/lib/external/shapelib/safileio.c -index 289d347eaf..7a614a5806 100644 ---- a/lib/external/shapelib/safileio.c -+++ b/lib/external/shapelib/safileio.c -@@ -74,7 +74,7 @@ - #include - #include - --SHP_CVSID("$Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $"); -+SHP_CVSID("$Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $") - - #ifdef SHPAPI_UTF8_HOOKS - # ifdef SHPAPI_WINDOWS - -``` + [shapelib commit 316ff87](https://github.com/OSGeo/shapelib/commit/316ff872566ea0d91d6b62fe01bfe39931db39aa#diff-f068bc465ca1a32e1b9c214d4eb9504ef9e0f3c4cabc1aa4bab8aa41e2248cc6R153) diff --git a/lib/external/shapelib/dbfopen.c b/lib/external/shapelib/dbfopen.c index 2bbba339e21..9078a29ba95 100644 --- a/lib/external/shapelib/dbfopen.c +++ b/lib/external/shapelib/dbfopen.c @@ -1,5 +1,4 @@ /****************************************************************************** - * $Id$ * * Project: Shapelib * Purpose: Implementation of .dbf access API documented in dbf_api.html. @@ -9,32 +8,10 @@ * Copyright (c) 1999, Frank Warmerdam * Copyright (c) 2012-2019, Even Rouault * - * This software is available under the following "MIT Style" license, - * or at the option of the licensee under the LGPL (see COPYING). This - * option is discussed in more detail in shapelib.html. - * - * -- - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later ******************************************************************************/ -#include "shapefil.h" +#include "shapefil_private.h" #include #include @@ -47,7 +24,9 @@ #include "cpl_string.h" #else -#if defined(WIN32) || defined(_WIN32) +#if defined(_MSC_VER) +#define STRCASECMP(a, b) (_stricmp(a, b)) +#elif defined(_WIN32) #define STRCASECMP(a, b) (stricmp(a, b)) #else #include @@ -58,7 +37,7 @@ #if _MSC_VER < 1900 #define snprintf _snprintf #endif -#elif defined(WIN32) || defined(_WIN32) +#elif defined(_WIN32) #ifndef snprintf #define snprintf _snprintf #endif @@ -68,8 +47,6 @@ #define CPLsnprintf snprintf #endif -SHP_CVSID("$Id$") - #ifndef FALSE #define FALSE 0 #define TRUE 1 @@ -91,33 +68,6 @@ CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) #define CPL_IGNORE_RET_VAL_INT(x) x #endif -#ifdef __cplusplus -#define STATIC_CAST(type, x) static_cast(x) -#define REINTERPRET_CAST(type, x) reinterpret_cast(x) -#define CONST_CAST(type, x) const_cast(x) -#define SHPLIB_NULLPTR nullptr -#else -#define STATIC_CAST(type, x) ((type)(x)) -#define REINTERPRET_CAST(type, x) ((type)(x)) -#define CONST_CAST(type, x) ((type)(x)) -#define SHPLIB_NULLPTR NULL -#endif - -/************************************************************************/ -/* SfRealloc() */ -/* */ -/* A realloc cover function that will access a NULL pointer as */ -/* a valid input. */ -/************************************************************************/ - -static void *SfRealloc(void *pMem, int nNewSize) -{ - if (pMem == SHPLIB_NULLPTR) - return malloc(nNewSize); - else - return realloc(pMem, nNewSize); -} - /************************************************************************/ /* DBFWriteHeader() */ /* */ @@ -137,9 +87,9 @@ static void DBFWriteHeader(DBFHandle psDBF) psDBF->bNoHeader = FALSE; /* -------------------------------------------------------------------- */ - /* Initialize the file header information. */ + /* Initialize the file header information. */ /* -------------------------------------------------------------------- */ - abyHeader[0] = 0x03; /* memo field? - just copying */ + abyHeader[0] = 0x03; /* memo field? - just copying */ /* write out update date */ abyHeader[1] = STATIC_CAST(unsigned char, psDBF->nUpdateYearSince1900); @@ -158,7 +108,7 @@ static void DBFWriteHeader(DBFHandle psDBF) /* -------------------------------------------------------------------- */ /* Write the initial 32 byte file header, and all the field */ - /* descriptions. */ + /* descriptions. */ /* -------------------------------------------------------------------- */ psDBF->sHooks.FSeek(psDBF->fp, 0, 0); psDBF->sHooks.FWrite(abyHeader, XBASE_FILEHDR_SZ, 1, psDBF->fp); @@ -344,7 +294,6 @@ void SHPAPI_CALL DBFSetLastModifiedDate(DBFHandle psDBF, int nYYSince1900, /************************************************************************/ DBFHandle SHPAPI_CALL DBFOpen(const char *pszFilename, const char *pszAccess) - { SAHooks sHooks; @@ -376,7 +325,7 @@ static int DBFGetLenWithoutExtension(const char *pszBasename) /************************************************************************/ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess, - SAHooks *psHooks) + const SAHooks *psHooks) { /* -------------------------------------------------------------------- */ /* We only allow the access strings "rb" and "r+". */ @@ -393,8 +342,8 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess, pszAccess = "rb+"; /* -------------------------------------------------------------------- */ - /* Compute the base (layer) name. If there is any extension */ - /* on the passed in filename we will strip it off. */ + /* Compute the base (layer) name. If there is any extension */ + /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ const int nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename); char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5)); @@ -402,19 +351,20 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess, memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5); DBFHandle psDBF = STATIC_CAST(DBFHandle, calloc(1, sizeof(DBFInfo))); - psDBF->fp = psHooks->FOpen(pszFullname, pszAccess); + psDBF->fp = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData); memcpy(&(psDBF->sHooks), psHooks, sizeof(SAHooks)); if (psDBF->fp == SHPLIB_NULLPTR) { memcpy(pszFullname + nLenWithoutExtension, ".DBF", 5); - psDBF->fp = psDBF->sHooks.FOpen(pszFullname, pszAccess); + psDBF->fp = + psDBF->sHooks.FOpen(pszFullname, pszAccess, psHooks->pvUserData); } memcpy(pszFullname + nLenWithoutExtension, ".cpg", 5); - SAFile pfCPG = psHooks->FOpen(pszFullname, "r"); + SAFile pfCPG = psHooks->FOpen(pszFullname, "r", psHooks->pvUserData); if (pfCPG == SHPLIB_NULLPTR) { memcpy(pszFullname + nLenWithoutExtension, ".CPG", 5); - pfCPG = psHooks->FOpen(pszFullname, "r"); + pfCPG = psHooks->FOpen(pszFullname, "r", psHooks->pvUserData); } free(pszFullname); @@ -495,7 +445,7 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess, /* -------------------------------------------------------------------- */ /* Read in Field Definitions */ /* -------------------------------------------------------------------- */ - pabyBuf = STATIC_CAST(unsigned char *, SfRealloc(pabyBuf, nHeadLen)); + pabyBuf = STATIC_CAST(unsigned char *, realloc(pabyBuf, nHeadLen)); psDBF->pszHeader = REINTERPRET_CAST(char *, pabyBuf); psDBF->sHooks.FSeek(psDBF->fp, XBASE_FILEHDR_SZ, 0); @@ -583,8 +533,8 @@ void SHPAPI_CALL DBFClose(DBFHandle psDBF) CPL_IGNORE_RET_VAL_INT(DBFFlushRecord(psDBF)); /* -------------------------------------------------------------------- */ - /* Update last access date, and number of records if we have */ - /* write access. */ + /* Update last access date, and number of records if we have */ + /* write access. */ /* -------------------------------------------------------------------- */ if (psDBF->bUpdated) DBFUpdateHeader(psDBF); @@ -645,11 +595,12 @@ DBFHandle SHPAPI_CALL DBFCreateEx(const char *pszFilename, /************************************************************************/ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename, - const char *pszCodePage, SAHooks *psHooks) + const char *pszCodePage, + const SAHooks *psHooks) { /* -------------------------------------------------------------------- */ - /* Compute the base (layer) name. If there is any extension */ - /* on the passed in filename we will strip it off. */ + /* Compute the base (layer) name. If there is any extension */ + /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ const int nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename); char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5)); @@ -659,17 +610,7 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename, /* -------------------------------------------------------------------- */ /* Create the file. */ /* -------------------------------------------------------------------- */ - SAFile fp = psHooks->FOpen(pszFullname, "wb"); - if (fp == SHPLIB_NULLPTR) { - free(pszFullname); - return SHPLIB_NULLPTR; - } - - char chZero = '\0'; - psHooks->FWrite(&chZero, 1, 1, fp); - psHooks->FClose(fp); - - fp = psHooks->FOpen(pszFullname, "rb+"); + SAFile fp = psHooks->FOpen(pszFullname, "wb+", psHooks->pvUserData); if (fp == SHPLIB_NULLPTR) { free(pszFullname); return SHPLIB_NULLPTR; @@ -685,7 +626,8 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename, // a valid one } if (ldid < 0) { - SAFile fpCPG = psHooks->FOpen(pszFullname, "w"); + SAFile fpCPG = + psHooks->FOpen(pszFullname, "w", psHooks->pvUserData); psHooks->FWrite( CONST_CAST(void *, STATIC_CAST(const void *, pszCodePage)), strlen(pszCodePage), 1, fpCPG); @@ -693,13 +635,13 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename, } } if (pszCodePage == SHPLIB_NULLPTR || ldid >= 0) { - psHooks->Remove(pszFullname); + psHooks->Remove(pszFullname, psHooks->pvUserData); } free(pszFullname); /* -------------------------------------------------------------------- */ - /* Create the info structure. */ + /* Create the info structure. */ /* -------------------------------------------------------------------- */ DBFHandle psDBF = STATIC_CAST(DBFHandle, calloc(1, sizeof(DBFInfo))); @@ -829,23 +771,22 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName, const int nOldHeaderLength = psDBF->nHeaderLength; /* -------------------------------------------------------------------- */ - /* SfRealloc all the arrays larger to hold the additional field */ + /* realloc all the arrays larger to hold the additional field */ /* information. */ /* -------------------------------------------------------------------- */ psDBF->nFields++; psDBF->panFieldOffset = STATIC_CAST( - int *, SfRealloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields)); + int *, realloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields)); psDBF->panFieldSize = STATIC_CAST( - int *, SfRealloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields)); + int *, realloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields)); - psDBF->panFieldDecimals = - STATIC_CAST(int *, SfRealloc(psDBF->panFieldDecimals, - sizeof(int) * psDBF->nFields)); + psDBF->panFieldDecimals = STATIC_CAST( + int *, realloc(psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields)); psDBF->pachFieldType = STATIC_CAST( - char *, SfRealloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields)); + char *, realloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields)); /* -------------------------------------------------------------------- */ /* Assign the new field information fields. */ @@ -863,7 +804,7 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName, psDBF->bUpdated = FALSE; psDBF->pszHeader = STATIC_CAST( - char *, SfRealloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ)); + char *, realloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ)); char *pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields - 1); @@ -887,7 +828,7 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName, /* Make the current record buffer appropriately larger. */ /* -------------------------------------------------------------------- */ psDBF->pszCurrentRecord = STATIC_CAST( - char *, SfRealloc(psDBF->pszCurrentRecord, psDBF->nRecordLength)); + char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength)); /* we're done if dealing with new .dbf */ if (psDBF->bNoHeader) @@ -971,13 +912,13 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField, return SHPLIB_NULLPTR; /* -------------------------------------------------------------------- */ - /* Have we read the record? */ + /* Have we read the record? */ /* -------------------------------------------------------------------- */ if (!DBFLoadRecord(psDBF, hEntity)) return SHPLIB_NULLPTR; - unsigned char *pabyRec = - REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord); + const unsigned char *pabyRec = + REINTERPRET_CAST(const unsigned char *, psDBF->pszCurrentRecord); /* -------------------------------------------------------------------- */ /* Ensure we have room to extract the target field. */ @@ -993,7 +934,7 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField, } /* -------------------------------------------------------------------- */ - /* Extract the requested field. */ + /* Extract the requested field. */ /* -------------------------------------------------------------------- */ memcpy(psDBF->pszWorkField, REINTERPRET_CAST(const char *, pabyRec) + @@ -1085,7 +1026,6 @@ double SHPAPI_CALL DBFReadDoubleAttribute(DBFHandle psDBF, int iRecord, const char SHPAPI_CALL1(*) DBFReadStringAttribute(DBFHandle psDBF, int iRecord, int iField) - { return STATIC_CAST(const char *, DBFReadAttribute(psDBF, iRecord, iField, 'C')); @@ -1099,12 +1039,40 @@ const char SHPAPI_CALL1(*) const char SHPAPI_CALL1(*) DBFReadLogicalAttribute(DBFHandle psDBF, int iRecord, int iField) - { return STATIC_CAST(const char *, DBFReadAttribute(psDBF, iRecord, iField, 'L')); } +/************************************************************************/ +/* DBFReadDateAttribute() */ +/* */ +/* Read a date attribute. */ +/************************************************************************/ + +SHPDate SHPAPI_CALL DBFReadDateAttribute(DBFHandle psDBF, int iRecord, + int iField) +{ + const char *pdateValue = STATIC_CAST( + const char *, DBFReadAttribute(psDBF, iRecord, iField, 'D')); + + SHPDate date; + + if (pdateValue == SHPLIB_NULLPTR) { + date.year = 0; + date.month = 0; + date.day = 0; + } + else if (3 != sscanf(pdateValue, "%4d%2d%2d", &date.year, &date.month, + &date.day)) { + date.year = 0; + date.month = 0; + date.day = 0; + } + + return date; +} + /************************************************************************/ /* DBFIsValueNULL() */ /* */ @@ -1135,7 +1103,16 @@ static bool DBFIsValueNULL(char chType, const char *pszValue) case 'D': /* NULL date fields have value "00000000" */ - return strncmp(pszValue, "00000000", 8) == 0; + /* Some DBF files have fields filled with spaces */ + /* (trimmed by DBFReadStringAttribute) to indicate null */ + /* values for dates (#4265). */ + /* And others have ' 0': + * https://lists.osgeo.org/pipermail/gdal-dev/2023-November/058010.html + */ + /* And others just empty string: + * https://github.com/OSGeo/gdal/issues/10405 */ + return pszValue[0] == 0 || strncmp(pszValue, "00000000", 8) == 0 || + strcmp(pszValue, " ") == 0 || strcmp(pszValue, "0") == 0; case 'L': /* NULL boolean fields have value "?" */ @@ -1155,7 +1132,8 @@ static bool DBFIsValueNULL(char chType, const char *pszValue) /* Contributed by Jim Matthews. */ /************************************************************************/ -int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle psDBF, int iRecord, int iField) +int SHPAPI_CALL DBFIsAttributeNULL(const DBFHandle psDBF, int iRecord, + int iField) { const char *pszValue = DBFReadStringAttribute(psDBF, iRecord, iField); @@ -1171,8 +1149,7 @@ int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle psDBF, int iRecord, int iField) /* Return the number of fields in this table. */ /************************************************************************/ -int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF) - +int SHPAPI_CALL DBFGetFieldCount(const DBFHandle psDBF) { return (psDBF->nFields); } @@ -1183,8 +1160,7 @@ int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF) /* Return the number of records in this table. */ /************************************************************************/ -int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF) - +int SHPAPI_CALL DBFGetRecordCount(const DBFHandle psDBF) { return (psDBF->nRecords); } @@ -1197,10 +1173,9 @@ int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF) /* bytes long. */ /************************************************************************/ -DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField, +DBFFieldType SHPAPI_CALL DBFGetFieldInfo(const DBFHandle psDBF, int iField, char *pszFieldName, int *pnWidth, int *pnDecimals) - { if (iField < 0 || iField >= psDBF->nFields) return (FTInvalid); @@ -1230,10 +1205,9 @@ DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField, else if (psDBF->pachFieldType[iField] == 'N' || psDBF->pachFieldType[iField] == 'F') { - if (psDBF->panFieldDecimals[iField] > 0) { - /* || psDBF->panFieldSize[iField] >= 10 ) */ /* GDAL bug #809 */ + if (psDBF->panFieldDecimals[iField] > 0 || + psDBF->panFieldSize[iField] >= 10) return (FTDouble); - } else return (FTInteger); } @@ -1244,15 +1218,15 @@ DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField, /************************************************************************/ /* DBFWriteAttribute() */ -/* */ -/* Write an attribute record to the file. */ +/* */ +/* Write an attribute record to the file. */ /************************************************************************/ static bool DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField, void *pValue) { /* -------------------------------------------------------------------- */ - /* Is this a valid record? */ + /* Is this a valid record? */ /* -------------------------------------------------------------------- */ if (hEntity < 0 || hEntity > psDBF->nRecords) return false; @@ -1333,9 +1307,13 @@ static bool DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField, case 'L': if (psDBF->panFieldSize[iField] >= 1 && (*STATIC_CAST(char *, pValue) == 'F' || - *STATIC_CAST(char *, pValue) == 'T')) + *STATIC_CAST(char *, pValue) == 'T')) { *(pabyRec + psDBF->panFieldOffset[iField]) = *STATIC_CAST(char *, pValue); + } + else { + nRetResult = false; + } break; default: { @@ -1370,10 +1348,10 @@ static bool DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField, /************************************************************************/ int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, - int iField, void *pValue) + int iField, const void *pValue) { /* -------------------------------------------------------------------- */ - /* Is this a valid record? */ + /* Is this a valid record? */ /* -------------------------------------------------------------------- */ if (hEntity < 0 || hEntity > psDBF->nRecords) return (FALSE); @@ -1402,24 +1380,29 @@ int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, if (!DBFLoadRecord(psDBF, hEntity)) return FALSE; - unsigned char *pabyRec = - REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord); + if (iField >= 0) { + unsigned char *pabyRec = + REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord); - /* -------------------------------------------------------------------- */ - /* Assign all the record fields. */ - /* -------------------------------------------------------------------- */ - int j; - if (STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue))) > - psDBF->panFieldSize[iField]) - j = psDBF->panFieldSize[iField]; - else { - memset(pabyRec + psDBF->panFieldOffset[iField], ' ', - psDBF->panFieldSize[iField]); - j = STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue))); - } + /* -------------------------------------------------------------------- + */ + /* Assign all the record fields. */ + /* -------------------------------------------------------------------- + */ + int j; + if (STATIC_CAST(int, strlen(STATIC_CAST(const char *, pValue))) > + psDBF->panFieldSize[iField]) + j = psDBF->panFieldSize[iField]; + else { + memset(pabyRec + psDBF->panFieldOffset[iField], ' ', + psDBF->panFieldSize[iField]); + j = STATIC_CAST(int, strlen(STATIC_CAST(const char *, pValue))); + } - strncpy(REINTERPRET_CAST(char *, pabyRec + psDBF->panFieldOffset[iField]), + memcpy( + REINTERPRET_CAST(char *, pabyRec + psDBF->panFieldOffset[iField]), STATIC_CAST(const char *, pValue), j); + } psDBF->bCurrentRecordModified = TRUE; psDBF->bUpdated = TRUE; @@ -1443,7 +1426,7 @@ int SHPAPI_CALL DBFWriteDoubleAttribute(DBFHandle psDBF, int iRecord, /************************************************************************/ /* DBFWriteIntegerAttribute() */ /* */ -/* Write a integer attribute. */ +/* Write an integer attribute. */ /************************************************************************/ int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle psDBF, int iRecord, @@ -1463,7 +1446,6 @@ int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle psDBF, int iRecord, int SHPAPI_CALL DBFWriteStringAttribute(DBFHandle psDBF, int iRecord, int iField, const char *pszValue) - { return ( DBFWriteAttribute(psDBF, iRecord, iField, @@ -1473,11 +1455,10 @@ int SHPAPI_CALL DBFWriteStringAttribute(DBFHandle psDBF, int iRecord, /************************************************************************/ /* DBFWriteNULLAttribute() */ /* */ -/* Write a string attribute. */ +/* Write a NULL attribute. */ /************************************************************************/ int SHPAPI_CALL DBFWriteNULLAttribute(DBFHandle psDBF, int iRecord, int iField) - { return (DBFWriteAttribute(psDBF, iRecord, iField, SHPLIB_NULLPTR)); } @@ -1490,23 +1471,47 @@ int SHPAPI_CALL DBFWriteNULLAttribute(DBFHandle psDBF, int iRecord, int iField) int SHPAPI_CALL DBFWriteLogicalAttribute(DBFHandle psDBF, int iRecord, int iField, const char lValue) - { return ( DBFWriteAttribute(psDBF, iRecord, iField, STATIC_CAST(void *, CONST_CAST(char *, &lValue)))); } +/************************************************************************/ +/* DBFWriteDateAttribute() */ +/* */ +/* Write a date attribute. */ +/************************************************************************/ + +int SHPAPI_CALL DBFWriteDateAttribute(DBFHandle psDBF, int iRecord, int iField, + const SHPDate *lValue) +{ + if (SHPLIB_NULLPTR == lValue) + return false; + /* check for supported digit range, but do not check for valid date */ + if (lValue->year < 0 || lValue->year > 9999) + return false; + if (lValue->month < 0 || lValue->month > 99) + return false; + if (lValue->day < 0 || lValue->day > 99) + return false; + char dateValue[9]; /* "yyyyMMdd\0" */ + snprintf(dateValue, sizeof(dateValue), "%04d%02d%02d", lValue->year, + lValue->month, lValue->day); + return (DBFWriteAttributeDirectly(psDBF, iRecord, iField, dateValue)); +} + /************************************************************************/ /* DBFWriteTuple() */ -/* */ -/* Write an attribute record to the file. */ +/* */ +/* Write an attribute record to the file. */ /************************************************************************/ -int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity, void *pRawTuple) +int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity, + const void *pRawTuple) { /* -------------------------------------------------------------------- */ - /* Is this a valid record? */ + /* Is this a valid record? */ /* -------------------------------------------------------------------- */ if (hEntity < 0 || hEntity > psDBF->nRecords) return (FALSE); @@ -1554,7 +1559,6 @@ int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity, void *pRawTuple) /************************************************************************/ const char SHPAPI_CALL1(*) DBFReadTuple(DBFHandle psDBF, int hEntity) - { if (hEntity < 0 || hEntity >= psDBF->nRecords) return SHPLIB_NULLPTR; @@ -1566,14 +1570,17 @@ const char SHPAPI_CALL1(*) DBFReadTuple(DBFHandle psDBF, int hEntity) } /************************************************************************/ -/* DBFCloneEmpty() */ +/* DBFCloneEmpty() */ /* */ -/* Read one of the attribute fields of a record. */ +/* Create a new .dbf file with same code page and field */ +/* definitions as the given handle. */ /************************************************************************/ -DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF, const char *pszFilename) +DBFHandle SHPAPI_CALL DBFCloneEmpty(const DBFHandle psDBF, + const char *pszFilename) { - DBFHandle newDBF = DBFCreateEx(pszFilename, psDBF->pszCodePage); + DBFHandle newDBF = + DBFCreateLL(pszFilename, psDBF->pszCodePage, &psDBF->sHooks); if (newDBF == SHPLIB_NULLPTR) return SHPLIB_NULLPTR; @@ -1629,8 +1636,7 @@ DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF, const char *pszFilename) /* 'M' (Memo: 10 digits .DBT block ptr) */ /************************************************************************/ -char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle psDBF, int iField) - +char SHPAPI_CALL DBFGetNativeFieldType(const DBFHandle psDBF, int iField) { if (iField >= 0 && iField < psDBF->nFields) return psDBF->pachFieldType[iField]; @@ -1646,7 +1652,8 @@ char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle psDBF, int iField) /* Contributed by Jim Matthews. */ /************************************************************************/ -int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName) +int SHPAPI_CALL DBFGetFieldIndex(const DBFHandle psDBF, + const char *pszFieldName) { char name[XBASE_FLDNAME_LEN_READ + 1]; @@ -1665,7 +1672,7 @@ int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName) /* it returns FALSE. */ /************************************************************************/ -int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape) +int SHPAPI_CALL DBFIsRecordDeleted(const DBFHandle psDBF, int iShape) { /* -------------------------------------------------------------------- */ /* Verify selection. */ @@ -1674,7 +1681,7 @@ int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape) return TRUE; /* -------------------------------------------------------------------- */ - /* Have we read the record? */ + /* Have we read the record? */ /* -------------------------------------------------------------------- */ if (!DBFLoadRecord(psDBF, iShape)) return FALSE; @@ -1727,7 +1734,7 @@ int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape, /* DBFGetCodePage */ /************************************************************************/ -const char SHPAPI_CALL1(*) DBFGetCodePage(DBFHandle psDBF) +const char SHPAPI_CALL1(*) DBFGetCodePage(const DBFHandle psDBF) { if (psDBF == SHPLIB_NULLPTR) return SHPLIB_NULLPTR; @@ -1768,17 +1775,16 @@ int SHPAPI_CALL DBFDeleteField(DBFHandle psDBF, int iField) psDBF->nFields--; psDBF->panFieldOffset = STATIC_CAST( - int *, SfRealloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields)); + int *, realloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields)); psDBF->panFieldSize = STATIC_CAST( - int *, SfRealloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields)); + int *, realloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields)); - psDBF->panFieldDecimals = - STATIC_CAST(int *, SfRealloc(psDBF->panFieldDecimals, - sizeof(int) * psDBF->nFields)); + psDBF->panFieldDecimals = STATIC_CAST( + int *, realloc(psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields)); psDBF->pachFieldType = STATIC_CAST( - char *, SfRealloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields)); + char *, realloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields)); /* update header information */ psDBF->nHeaderLength -= XBASE_FLDHDR_SZ; @@ -1790,11 +1796,11 @@ int SHPAPI_CALL DBFDeleteField(DBFHandle psDBF, int iField) sizeof(char) * (psDBF->nFields - iField) * XBASE_FLDHDR_SZ); psDBF->pszHeader = STATIC_CAST( - char *, SfRealloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ)); + char *, realloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ)); /* update size of current record appropriately */ psDBF->pszCurrentRecord = STATIC_CAST( - char *, SfRealloc(psDBF->pszCurrentRecord, psDBF->nRecordLength)); + char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength)); /* we're done if we're dealing with not yet created .dbf */ if (psDBF->bNoHeader && psDBF->nRecords == 0) @@ -1866,7 +1872,7 @@ int SHPAPI_CALL DBFDeleteField(DBFHandle psDBF, int iField) /* code of DBFReorderFields. */ /************************************************************************/ -int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, int *panMap) +int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap) { if (psDBF->nFields == 0) return TRUE; @@ -1878,13 +1884,13 @@ int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, int *panMap) /* a simple malloc() would be enough, but calloc() helps clang static * analyzer */ int *panFieldOffsetNew = - STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields)); + STATIC_CAST(int *, calloc(psDBF->nFields, sizeof(int))); int *panFieldSizeNew = - STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields)); + STATIC_CAST(int *, calloc(psDBF->nFields, sizeof(int))); int *panFieldDecimalsNew = - STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields)); + STATIC_CAST(int *, calloc(psDBF->nFields, sizeof(int))); char *pachFieldTypeNew = - STATIC_CAST(char *, calloc(sizeof(char), psDBF->nFields)); + STATIC_CAST(char *, calloc(psDBF->nFields, sizeof(char))); char *pszHeaderNew = STATIC_CAST( char *, malloc(sizeof(char) * XBASE_FLDHDR_SZ * psDBF->nFields)); @@ -2050,7 +2056,7 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField, psDBF->nRecordLength += nWidth - nOldWidth; psDBF->pszCurrentRecord = STATIC_CAST( - char *, SfRealloc(psDBF->pszCurrentRecord, psDBF->nRecordLength)); + char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength)); } /* we're done if we're dealing with not yet created .dbf */ @@ -2069,7 +2075,6 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField, char *pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1))); - /* cppcheck-suppress uninitdata */ pszOldField[nOldWidth] = 0; /* move records to their new positions */ @@ -2139,7 +2144,6 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField, char *pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1))); - /* cppcheck-suppress uninitdata */ pszOldField[nOldWidth] = 0; /* move records to their new positions */ diff --git a/lib/external/shapelib/safileio.c b/lib/external/shapelib/safileio.c index 3377642e4d4..e13f1f29acf 100644 --- a/lib/external/shapelib/safileio.c +++ b/lib/external/shapelib/safileio.c @@ -1,5 +1,4 @@ /****************************************************************************** - * $Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $ * * Project: Shapelib * Purpose: Default implementation of file io based on stdio. @@ -8,74 +7,19 @@ ****************************************************************************** * Copyright (c) 2007, Frank Warmerdam * - * This software is available under the following "MIT Style" license, - * or at the option of the licensee under the LGPL (see COPYING). This - * option is discussed in more detail in shapelib.html. - * - * -- - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later ****************************************************************************** * - * $Log: safileio.c,v $ - * Revision 1.6 2018-06-15 19:56:32 erouault - * * safileio.c: remove duplicate test. Patch by Jaroslav Fojtik. - * Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2744 - * - * Revision 1.5 2016-12-05 12:44:05 erouault - * * Major overhaul of Makefile build system to use autoconf/automake. - * - * * Warning fixes in contrib/ - * - * Revision 1.4 2008-01-16 20:05:14 bram - * Add file hooks that accept UTF-8 encoded filenames on some platforms. Use - *SASetupUtf8Hooks tosetup the hooks and check SHPAPI_UTF8_HOOKS for its - *availability. Currently, this is only available on the Windows platform that - *decodes the UTF-8 filenames to wide character strings and feeds them to - *_wfopen and _wremove. - * - * Revision 1.3 2007/12/18 18:28:11 bram - * - create hook for client specific atof (bugzilla ticket 1615) - * - check for NULL handle before closing cpCPG file, and close after reading. - * - * Revision 1.2 2007/12/15 20:25:30 bram - * dbfopen.c now reads the Code Page information from the DBF file, and exports - * this information as a string through the DBFGetCodePage function. This is - * either the number from the LDID header field ("LDID/") or as the - * content of an accompanying .CPG file. When creating a DBF file, the code can - * be set using DBFCreateEx. - * - * Revision 1.1 2007/12/06 06:56:41 fwarmerdam - * new - * */ #include "shapefil.h" +#include #include #include -#include +#include #include #include -#include - -SHP_CVSID("$Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $") #ifdef SHPAPI_UTF8_HOOKS #ifdef SHPAPI_WINDOWS @@ -86,102 +30,64 @@ SHP_CVSID("$Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $") #endif #endif -/************************************************************************/ -/* SADFOpen() */ -/************************************************************************/ - -SAFile SADFOpen(const char *pszFilename, const char *pszAccess) - +static SAFile SADFOpen(const char *pszFilename, const char *pszAccess, + void *pvUserData) { + (void)pvUserData; return (SAFile)fopen(pszFilename, pszAccess); } -/************************************************************************/ -/* SADFRead() */ -/************************************************************************/ - -SAOffset SADFRead(void *p, SAOffset size, SAOffset nmemb, SAFile file) - +static SAOffset SADFRead(void *p, SAOffset size, SAOffset nmemb, SAFile file) { return (SAOffset)fread(p, (size_t)size, (size_t)nmemb, (FILE *)file); } -/************************************************************************/ -/* SADFWrite() */ -/************************************************************************/ - -SAOffset SADFWrite(void *p, SAOffset size, SAOffset nmemb, SAFile file) - +static SAOffset SADFWrite(const void *p, SAOffset size, SAOffset nmemb, + SAFile file) { return (SAOffset)fwrite(p, (size_t)size, (size_t)nmemb, (FILE *)file); } -/************************************************************************/ -/* SADFSeek() */ -/************************************************************************/ - -SAOffset SADFSeek(SAFile file, SAOffset offset, int whence) - +static SAOffset SADFSeek(SAFile file, SAOffset offset, int whence) { +#if defined(_MSC_VER) && _MSC_VER >= 1400 + return (SAOffset)_fseeki64((FILE *)file, (__int64)offset, whence); +#else return (SAOffset)fseek((FILE *)file, (long)offset, whence); +#endif } -/************************************************************************/ -/* SADFTell() */ -/************************************************************************/ - -SAOffset SADFTell(SAFile file) - +static SAOffset SADFTell(SAFile file) { +#if defined(_MSC_VER) && _MSC_VER >= 1400 + return (SAOffset)_ftelli64((FILE *)file); +#else return (SAOffset)ftell((FILE *)file); +#endif } -/************************************************************************/ -/* SADFFlush() */ -/************************************************************************/ - -int SADFFlush(SAFile file) - +static int SADFFlush(SAFile file) { return fflush((FILE *)file); } -/************************************************************************/ -/* SADFClose() */ -/************************************************************************/ - -int SADFClose(SAFile file) - +static int SADFClose(SAFile file) { return fclose((FILE *)file); } -/************************************************************************/ -/* SADFClose() */ -/************************************************************************/ - -int SADRemove(const char *filename) - +static int SADRemove(const char *filename, void *pvUserData) { + (void)pvUserData; return remove(filename); } -/************************************************************************/ -/* SADError() */ -/************************************************************************/ - -void SADError(const char *message) - +static void SADError(const char *message) { fprintf(stderr, "%s\n", message); } -/************************************************************************/ -/* SASetupDefaultHooks() */ -/************************************************************************/ - void SASetupDefaultHooks(SAHooks *psHooks) - { psHooks->FOpen = SADFOpen; psHooks->FRead = SADFRead; @@ -194,25 +100,20 @@ void SASetupDefaultHooks(SAHooks *psHooks) psHooks->Error = SADError; psHooks->Atof = atof; + psHooks->pvUserData = NULL; } #ifdef SHPAPI_WINDOWS -/************************************************************************/ -/* Utf8ToWideChar */ -/************************************************************************/ - -const wchar_t *Utf8ToWideChar(const char *pszFilename) +static wchar_t *Utf8ToWideChar(const char *pszFilename) { - int nMulti, nWide; - wchar_t *pwszFileName; - - nMulti = strlen(pszFilename) + 1; - nWide = MultiByteToWideChar(CP_UTF8, 0, pszFilename, nMulti, 0, 0); + const int nMulti = (int)strlen(pszFilename) + 1; + const int nWide = + MultiByteToWideChar(CP_UTF8, 0, pszFilename, nMulti, 0, 0); if (nWide == 0) { return NULL; } - pwszFileName = (wchar_t *)malloc(nWide * sizeof(wchar_t)); + wchar_t *pwszFileName = (wchar_t *)malloc(nWide * sizeof(wchar_t)); if (pwszFileName == NULL) { return NULL; } @@ -228,51 +129,44 @@ const wchar_t *Utf8ToWideChar(const char *pszFilename) /* SAUtf8WFOpen */ /************************************************************************/ -SAFile SAUtf8WFOpen(const char *pszFilename, const char *pszAccess) +static SAFile SAUtf8WFOpen(const char *pszFilename, const char *pszAccess, + void *pvUserData) { + (void)pvUserData; SAFile file = NULL; - const wchar_t *pwszFileName, *pwszAccess; - pwszFileName = Utf8ToWideChar(pszFilename); - pwszAccess = Utf8ToWideChar(pszAccess); + wchar_t *pwszFileName = Utf8ToWideChar(pszFilename); + wchar_t *pwszAccess = Utf8ToWideChar(pszAccess); if (pwszFileName != NULL && pwszAccess != NULL) { file = (SAFile)_wfopen(pwszFileName, pwszAccess); } - free((wchar_t *)pwszFileName); - free((wchar_t *)pwszAccess); + free(pwszFileName); + free(pwszAccess); return file; } -/************************************************************************/ -/* SAUtf8WRemove() */ -/************************************************************************/ - -int SAUtf8WRemove(const char *pszFilename) +static int SAUtf8WRemove(const char *pszFilename, void *pvUserData) { - const wchar_t *pwszFileName = Utf8ToWideChar(pszFilename); + (void)pvUserData; + wchar_t *pwszFileName = Utf8ToWideChar(pszFilename); int rc = -1; if (pwszFileName != NULL) { rc = _wremove(pwszFileName); } - free((wchar_t *)pwszFileName); + free(pwszFileName); return rc; } #endif #ifdef SHPAPI_UTF8_HOOKS - -/************************************************************************/ -/* SASetupUtf8Hooks() */ -/************************************************************************/ +#ifndef SHPAPI_WINDOWS +#error "no implementations of UTF-8 hooks available for this platform" +#endif void SASetupUtf8Hooks(SAHooks *psHooks) { -#ifdef SHPAPI_WINDOWS psHooks->FOpen = SAUtf8WFOpen; psHooks->Remove = SAUtf8WRemove; -#else -#error "no implementations of UTF-8 hooks available for this platform" -#endif psHooks->FRead = SADFRead; psHooks->FWrite = SADFWrite; psHooks->FSeek = SADFSeek; @@ -283,5 +177,4 @@ void SASetupUtf8Hooks(SAHooks *psHooks) psHooks->Error = SADError; psHooks->Atof = atof; } - #endif diff --git a/lib/external/shapelib/shapefil.h b/lib/external/shapelib/shapefil.h index cd4ef54aa56..c11632fa6ba 100644 --- a/lib/external/shapelib/shapefil.h +++ b/lib/external/shapelib/shapefil.h @@ -2,7 +2,6 @@ #define SHAPEFILE_H_INCLUDED /****************************************************************************** - * $Id$ * * Project: Shapelib * Purpose: Primary include file for Shapelib. @@ -12,29 +11,7 @@ * Copyright (c) 1999, Frank Warmerdam * Copyright (c) 2012-2016, Even Rouault * - * This software is available under the following "MIT Style" license, - * or at the option of the licensee under the LGPL (see COPYING). This - * option is discussed in more detail in shapelib.html. - * - * -- - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later ****************************************************************************** * */ @@ -49,6 +26,26 @@ extern "C" { #endif +/************************************************************************/ +/* Version related macros (added in 1.6.0) */ +/************************************************************************/ + +#define SHAPELIB_VERSION_MAJOR 1 +#define SHAPELIB_VERSION_MINOR 6 +#define SHAPELIB_VERSION_MICRO 0 + +#define SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro) \ + ((major) * 10000 + (minor) * 100 + (micro)) + +#define SHAPELIB_VERSION_NUMBER \ + SHAPELIB_MAKE_VERSION_NUMBER(SHAPELIB_VERSION_MAJOR, \ + SHAPELIB_VERSION_MINOR, \ + SHAPELIB_VERSION_MICRO) + +#define SHAPELIB_AT_LEAST(major, minor, micro) \ + (SHAPELIB_VERSION_NUMBER >= \ + SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro)) + /************************************************************************/ /* Configuration options. */ /************************************************************************/ @@ -73,7 +70,7 @@ extern "C" { /* various calling conventions on the Shapelib API. */ /* */ /* To force __stdcall conventions (needed to call Shapelib */ -/* from Visual Basic and/or Dephi I believe) the makefile could */ +/* from Visual Basic and/or Delphi I believe) the makefile could */ /* be modified to define: */ /* */ /* /DSHPAPI_CALL=__stdcall */ @@ -113,31 +110,11 @@ extern "C" { #define SHPAPI_CALL1(x) x SHPAPI_CALL #endif -/* -------------------------------------------------------------------- */ -/* Macros for controlling CVSID and ensuring they don't appear */ -/* as unreferenced variables resulting in lots of warnings. */ -/* -------------------------------------------------------------------- */ -#ifndef DISABLE_CVSID -#if defined(__GNUC__) && __GNUC__ >= 4 -#define SHP_CVSID(string) \ - static const char cpl_cvsid[] __attribute__((used)) = string; -#else -#define SHP_CVSID(string) \ - static const char cpl_cvsid[] = string; \ - static const char *cvsid_aw() \ - { \ - return (cvsid_aw() ? NULL : cpl_cvsid); \ - } -#endif -#else -#define SHP_CVSID(string) -#endif - /* -------------------------------------------------------------------- */ /* On some platforms, additional file IO hooks are defined that */ /* UTF-8 encoded filenames Unicode filenames */ /* -------------------------------------------------------------------- */ -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +#if defined(_WIN32) #define SHPAPI_WINDOWS #define SHPAPI_UTF8_HOOKS #endif @@ -148,21 +125,27 @@ extern "C" { typedef int *SAFile; #ifndef SAOffset +#if defined(_MSC_VER) && _MSC_VER >= 1400 +typedef unsigned __int64 SAOffset; +#else typedef unsigned long SAOffset; #endif +#endif typedef struct { - SAFile (*FOpen)(const char *filename, const char *access); + SAFile (*FOpen)(const char *filename, const char *access, void *pvUserData); SAOffset (*FRead)(void *p, SAOffset size, SAOffset nmemb, SAFile file); - SAOffset (*FWrite)(void *p, SAOffset size, SAOffset nmemb, SAFile file); + SAOffset (*FWrite)(const void *p, SAOffset size, SAOffset nmemb, + SAFile file); SAOffset (*FSeek)(SAFile file, SAOffset offset, int whence); SAOffset (*FTell)(SAFile file); int (*FFlush)(SAFile file); int (*FClose)(SAFile file); - int (*Remove)(const char *filename); + int (*Remove)(const char *filename, void *pvUserData); void (*Error)(const char *message); double (*Atof)(const char *str); + void *pvUserData; } SAHooks; void SHPAPI_CALL SASetupDefaultHooks(SAHooks *psHooks); @@ -206,6 +189,12 @@ typedef struct { typedef SHPInfo *SHPHandle; +typedef struct { + int year; + int month; + int day; +} SHPDate; + /* -------------------------------------------------------------------- */ /* Shape types (nSHPType) */ /* -------------------------------------------------------------------- */ @@ -277,13 +266,13 @@ struct tagSHPObject { /* will be NULL as it is not necessary to keep the SHX file open */ SHPHandle SHPAPI_CALL SHPOpen(const char *pszShapeFile, const char *pszAccess); SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszShapeFile, const char *pszAccess, - SAHooks *psHooks); + const SAHooks *psHooks); SHPHandle SHPAPI_CALL SHPOpenLLEx(const char *pszShapeFile, - const char *pszAccess, SAHooks *psHooks, + const char *pszAccess, const SAHooks *psHooks, int bRestoreSHX); int SHPAPI_CALL SHPRestoreSHX(const char *pszShapeFile, const char *pszAccess, - SAHooks *psHooks); + const SAHooks *psHooks); /* If setting bFastMode = TRUE, the content of SHPReadObject() is owned by the * SHPHandle. */ @@ -296,12 +285,14 @@ void SHPAPI_CALL SHPSetFastModeReadObject(SHPHandle hSHP, int bFastMode); SHPHandle SHPAPI_CALL SHPCreate(const char *pszShapeFile, int nShapeType); SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszShapeFile, int nShapeType, - SAHooks *psHooks); -void SHPAPI_CALL SHPGetInfo(SHPHandle hSHP, int *pnEntities, int *pnShapeType, - double *padfMinBound, double *padfMaxBound); + const SAHooks *psHooks); +void SHPAPI_CALL SHPGetInfo(const SHPHandle hSHP, int *pnEntities, + int *pnShapeType, double *padfMinBound, + double *padfMaxBound); -SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle hSHP, int iShape); -int SHPAPI_CALL SHPWriteObject(SHPHandle hSHP, int iShape, SHPObject *psObject); +SHPObject SHPAPI_CALL1(*) SHPReadObject(const SHPHandle hSHP, int iShape); +int SHPAPI_CALL SHPWriteObject(SHPHandle hSHP, int iShape, + const SHPObject *psObject); void SHPAPI_CALL SHPDestroyObject(SHPObject *psObject); void SHPAPI_CALL SHPComputeExtents(SHPObject *psObject); @@ -314,7 +305,7 @@ SHPObject SHPAPI_CALL1(*) SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX, const double *padfY, const double *padfZ); -int SHPAPI_CALL SHPRewindObject(SHPHandle hSHP, SHPObject *psObject); +int SHPAPI_CALL SHPRewindObject(const SHPHandle hSHP, SHPObject *psObject); void SHPAPI_CALL SHPClose(SHPHandle hSHP); void SHPAPI_CALL SHPWriteHeader(SHPHandle hSHP); @@ -360,21 +351,20 @@ typedef struct { SHPTree SHPAPI_CALL1(*) SHPCreateTree(SHPHandle hSHP, int nDimension, int nMaxDepth, - double *padfBoundsMin, double *padfBoundsMax); + const double *padfBoundsMin, const double *padfBoundsMax); void SHPAPI_CALL SHPDestroyTree(SHPTree *hTree); int SHPAPI_CALL SHPWriteTree(SHPTree *hTree, const char *pszFilename); int SHPAPI_CALL SHPTreeAddShapeId(SHPTree *hTree, SHPObject *psObject); -int SHPAPI_CALL SHPTreeRemoveShapeId(SHPTree *hTree, int nShapeId); void SHPAPI_CALL SHPTreeTrimExtraNodes(SHPTree *hTree); int SHPAPI_CALL1(*) - SHPTreeFindLikelyShapes(SHPTree *hTree, double *padfBoundsMin, + SHPTreeFindLikelyShapes(const SHPTree *hTree, double *padfBoundsMin, double *padfBoundsMax, int *); -int SHPAPI_CALL SHPCheckBoundsOverlap(double *, double *, double *, double *, - int); +int SHPAPI_CALL SHPCheckBoundsOverlap(const double *, const double *, + const double *, const double *, int); int SHPAPI_CALL1(*) SHPSearchDiskTree(FILE *fp, double *padfBoundsMin, double *padfBoundsMax, int *pnShapeCount); @@ -382,16 +372,17 @@ int SHPAPI_CALL1(*) SHPSearchDiskTree(FILE *fp, double *padfBoundsMin, typedef struct SHPDiskTreeInfo *SHPTreeDiskHandle; SHPTreeDiskHandle SHPAPI_CALL SHPOpenDiskTree(const char *pszQIXFilename, - SAHooks *psHooks); + const SAHooks *psHooks); void SHPAPI_CALL SHPCloseDiskTree(SHPTreeDiskHandle hDiskTree); int SHPAPI_CALL1(*) - SHPSearchDiskTreeEx(SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, - double *padfBoundsMax, int *pnShapeCount); + SHPSearchDiskTreeEx(const SHPTreeDiskHandle hDiskTree, + double *padfBoundsMin, double *padfBoundsMax, + int *pnShapeCount); int SHPAPI_CALL SHPWriteTreeLL(SHPTree *hTree, const char *pszFilename, - SAHooks *psHooks); + const SAHooks *psHooks); /* -------------------------------------------------------------------- */ /* SBN Search API */ @@ -400,16 +391,16 @@ int SHPAPI_CALL SHPWriteTreeLL(SHPTree *hTree, const char *pszFilename, typedef struct SBNSearchInfo *SBNSearchHandle; SBNSearchHandle SHPAPI_CALL SBNOpenDiskTree(const char *pszSBNFilename, - SAHooks *psHooks); + const SAHooks *psHooks); void SHPAPI_CALL SBNCloseDiskTree(SBNSearchHandle hSBN); int SHPAPI_CALL1(*) - SBNSearchDiskTree(SBNSearchHandle hSBN, double *padfBoundsMin, - double *padfBoundsMax, int *pnShapeCount); + SBNSearchDiskTree(const SBNSearchHandle hSBN, const double *padfBoundsMin, + const double *padfBoundsMax, int *pnShapeCount); int SHPAPI_CALL1(*) - SBNSearchDiskTreeInteger(SBNSearchHandle hSBN, int bMinX, int bMinY, + SBNSearchDiskTreeInteger(const SBNSearchHandle hSBN, int bMinX, int bMinY, int bMaxX, int bMaxY, int *pnShapeCount); void SHPAPI_CALL SBNSearchFreeIds(int *panShapeId); @@ -485,15 +476,16 @@ typedef enum { DBFHandle SHPAPI_CALL DBFOpen(const char *pszDBFFile, const char *pszAccess); DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszDBFFile, const char *pszAccess, - SAHooks *psHooks); + const SAHooks *psHooks); DBFHandle SHPAPI_CALL DBFCreate(const char *pszDBFFile); DBFHandle SHPAPI_CALL DBFCreateEx(const char *pszDBFFile, const char *pszCodePage); DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszDBFFile, - const char *pszCodePage, SAHooks *psHooks); + const char *pszCodePage, + const SAHooks *psHooks); -int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF); -int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF); +int SHPAPI_CALL DBFGetFieldCount(const DBFHandle psDBF); +int SHPAPI_CALL DBFGetRecordCount(const DBFHandle psDBF); int SHPAPI_CALL DBFAddField(DBFHandle hDBF, const char *pszFieldName, DBFFieldType eType, int nWidth, int nDecimals); @@ -502,17 +494,18 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle hDBF, const char *pszFieldName, int SHPAPI_CALL DBFDeleteField(DBFHandle hDBF, int iField); -int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, int *panMap); +int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap); int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField, const char *pszFieldName, char chType, int nWidth, int nDecimals); -DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField, +DBFFieldType SHPAPI_CALL DBFGetFieldInfo(const DBFHandle psDBF, int iField, char *pszFieldName, int *pnWidth, int *pnDecimals); -int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName); +int SHPAPI_CALL DBFGetFieldIndex(const DBFHandle psDBF, + const char *pszFieldName); int SHPAPI_CALL DBFReadIntegerAttribute(DBFHandle hDBF, int iShape, int iField); double SHPAPI_CALL DBFReadDoubleAttribute(DBFHandle hDBF, int iShape, @@ -521,7 +514,10 @@ const char SHPAPI_CALL1(*) DBFReadStringAttribute(DBFHandle hDBF, int iShape, int iField); const char SHPAPI_CALL1(*) DBFReadLogicalAttribute(DBFHandle hDBF, int iShape, int iField); -int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle hDBF, int iShape, int iField); +SHPDate SHPAPI_CALL DBFReadDateAttribute(DBFHandle hDBF, int iShape, + int iField); +int SHPAPI_CALL DBFIsAttributeNULL(const DBFHandle hDBF, int iShape, + int iField); int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle hDBF, int iShape, int iField, int nFieldValue); @@ -533,22 +529,26 @@ int SHPAPI_CALL DBFWriteNULLAttribute(DBFHandle hDBF, int iShape, int iField); int SHPAPI_CALL DBFWriteLogicalAttribute(DBFHandle hDBF, int iShape, int iField, const char lFieldValue); +int SHPAPI_CALL DBFWriteDateAttribute(DBFHandle hDBF, int iShape, int iField, + const SHPDate *dateFieldValue); int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, - int iField, void *pValue); + int iField, const void *pValue); const char SHPAPI_CALL1(*) DBFReadTuple(DBFHandle psDBF, int hEntity); -int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity, void *pRawTuple); +int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity, + const void *pRawTuple); -int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape); +int SHPAPI_CALL DBFIsRecordDeleted(const DBFHandle psDBF, int iShape); int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape, int bIsDeleted); -DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF, const char *pszFilename); +DBFHandle SHPAPI_CALL DBFCloneEmpty(const DBFHandle psDBF, + const char *pszFilename); void SHPAPI_CALL DBFClose(DBFHandle hDBF); void SHPAPI_CALL DBFUpdateHeader(DBFHandle hDBF); -char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle hDBF, int iField); +char SHPAPI_CALL DBFGetNativeFieldType(const DBFHandle hDBF, int iField); -const char SHPAPI_CALL1(*) DBFGetCodePage(DBFHandle psDBF); +const char SHPAPI_CALL1(*) DBFGetCodePage(const DBFHandle psDBF); void SHPAPI_CALL DBFSetLastModifiedDate(DBFHandle psDBF, int nYYSince1900, int nMM, int nDD); diff --git a/lib/external/shapelib/shapefil_private.h b/lib/external/shapelib/shapefil_private.h new file mode 100644 index 00000000000..1bed49e7cce --- /dev/null +++ b/lib/external/shapelib/shapefil_private.h @@ -0,0 +1,115 @@ +#ifndef SHAPEFILE_PRIVATE_H_INCLUDED +#define SHAPEFILE_PRIVATE_H_INCLUDED + +/****************************************************************************** + * + * Project: Shapelib + * Purpose: Private include file for Shapelib. + * Author: Frank Warmerdam, warmerdam@pobox.com + * + ****************************************************************************** + * Copyright (c) 1999, Frank Warmerdam + * Copyright (c) 2012-2016, Even Rouault + * + * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later + ****************************************************************************** + * + */ + +#ifdef __cplusplus +#define STATIC_CAST(type, x) static_cast(x) +#define REINTERPRET_CAST(type, x) reinterpret_cast(x) +#define CONST_CAST(type, x) const_cast(x) +#define SHPLIB_NULLPTR nullptr +#else +#define STATIC_CAST(type, x) ((type)(x)) +#define REINTERPRET_CAST(type, x) ((type)(x)) +#define CONST_CAST(type, x) ((type)(x)) +#define SHPLIB_NULLPTR NULL +#endif + +#if !defined(SHP_BIG_ENDIAN) +#if defined(CPL_MSB) +#define SHP_BIG_ENDIAN 1 +#elif (defined(__GNUC__) && __GNUC__ >= 5) || \ + (defined(__GNUC__) && defined(__GNUC_MINOR__) && __GNUC__ == 4 && \ + __GNUC_MINOR__ >= 6) +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define SHP_BIG_ENDIAN 1 +#endif +#elif defined(__GLIBC__) +#if __BYTE_ORDER == __BIG_ENDIAN +#define SHP_BIG_ENDIAN 1 +#endif +#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +#define SHP_BIG_ENDIAN 1 +#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +#elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || \ + defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || \ + defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +#define SHP_BIG_ENDIAN 1 +#endif +#endif + +#include "shapefil.h" +#include +#include + +/************************************************************************/ +/* Little endian <==> big endian byte swap macros. */ +/************************************************************************/ + +#if (defined(__GNUC__) && __GNUC__ >= 5) || \ + (defined(__GNUC__) && defined(__GNUC_MINOR__) && __GNUC__ == 4 && \ + __GNUC_MINOR__ >= 8) +#define _SHP_SWAP32(x) \ + STATIC_CAST(uint32_t, __builtin_bswap32(STATIC_CAST(uint32_t, x))) +#define _SHP_SWAP64(x) \ + STATIC_CAST(uint64_t, __builtin_bswap64(STATIC_CAST(uint64_t, x))) +#elif defined(_MSC_VER) +#define _SHP_SWAP32(x) \ + STATIC_CAST(uint32_t, _byteswap_ulong(STATIC_CAST(uint32_t, x))) +#define _SHP_SWAP64(x) \ + STATIC_CAST(uint64_t, _byteswap_uint64(STATIC_CAST(uint64_t, x))) +#else +#define _SHP_SWAP32(x) \ + STATIC_CAST(uint32_t, \ + ((STATIC_CAST(uint32_t, x) & 0x000000ffU) << 24) | \ + ((STATIC_CAST(uint32_t, x) & 0x0000ff00U) << 8) | \ + ((STATIC_CAST(uint32_t, x) & 0x00ff0000U) >> 8) | \ + ((STATIC_CAST(uint32_t, x) & 0xff000000U) >> 24)) +#define _SHP_SWAP64(x) \ + ((STATIC_CAST(uint64_t, _SHP_SWAP32(STATIC_CAST(uint32_t, x))) << 32) | \ + (STATIC_CAST(uint64_t, _SHP_SWAP32(STATIC_CAST( \ + uint32_t, STATIC_CAST(uint64_t, x) >> 32))))) + +#endif + +/* in-place uint32_t* swap */ +#define SHP_SWAP32(p) \ + *REINTERPRET_CAST(uint32_t *, p) = \ + _SHP_SWAP32(*REINTERPRET_CAST(uint32_t *, p)) +/* in-place uint64_t* swap */ +#define SHP_SWAP64(p) \ + *REINTERPRET_CAST(uint64_t *, p) = \ + _SHP_SWAP64(*REINTERPRET_CAST(uint64_t *, p)) +/* in-place double* swap */ +#define SHP_SWAPDOUBLE(x) \ + do { \ + uint64_t _n64; \ + void *_lx = x; \ + memcpy(&_n64, _lx, 8); \ + _n64 = _SHP_SWAP64(_n64); \ + memcpy(_lx, &_n64, 8); \ + } while (0) +/* copy double* swap*/ +#define SHP_SWAPDOUBLE_CPY(dst, src) \ + do { \ + uint64_t _n64; \ + const void *_ls = src; \ + void *_ld = dst; \ + memcpy(&_n64, _ls, 8); \ + _n64 = _SHP_SWAP64(_n64); \ + memcpy(_ld, &_n64, 8); \ + } while (0) +#endif /* ndef SHAPEFILE_PRIVATE_H_INCLUDED */ diff --git a/lib/external/shapelib/shpopen.c b/lib/external/shapelib/shpopen.c index e63cf768d25..b2eeb3614fb 100644 --- a/lib/external/shapelib/shpopen.c +++ b/lib/external/shapelib/shpopen.c @@ -8,52 +8,21 @@ * Copyright (c) 1999, 2001, Frank Warmerdam * Copyright (c) 2011-2019, Even Rouault * - * This software is available under the following "MIT Style" license, - * or at the option of the licensee under the LGPL (see COPYING). This - * option is discussed in more detail in shapelib.html. - * - * -- - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later ******************************************************************************/ -#include "shapefil.h" +#include "shapefil_private.h" #include #include #include #include #include +#include #include #include #include -SHP_CVSID("$Id$") - -typedef unsigned char uchar; - -#if UINT_MAX == 65535 -typedef unsigned long int32; -#else -typedef unsigned int int32; -#endif - #ifndef FALSE #define FALSE 0 #define TRUE 1 @@ -70,73 +39,18 @@ typedef unsigned int int32; #if _MSC_VER < 1900 #define snprintf _snprintf #endif -#elif defined(WIN32) || defined(_WIN32) +#elif defined(_WIN32) #ifndef snprintf #define snprintf _snprintf #endif #endif #endif -#ifndef CPL_UNUSED -#if defined(__GNUC__) && __GNUC__ >= 4 -#define CPL_UNUSED __attribute((__unused__)) -#else -#define CPL_UNUSED -#endif -#endif - -#if defined(CPL_LSB) -#define bBigEndian false -#elif defined(CPL_MSB) -#define bBigEndian true -#else -static bool bBigEndian; -#endif - -#ifdef __cplusplus -#define STATIC_CAST(type, x) static_cast(x) -#define SHPLIB_NULLPTR nullptr -#else -#define STATIC_CAST(type, x) ((type)(x)) -#define SHPLIB_NULLPTR NULL -#endif - -/************************************************************************/ -/* SwapWord() */ -/* */ -/* Swap a 2, 4 or 8 byte word. */ -/************************************************************************/ - -static void SwapWord(int length, void *wordP) -{ - for (int i = 0; i < length / 2; i++) { - const uchar temp = STATIC_CAST(uchar *, wordP)[i]; - STATIC_CAST(uchar *, wordP) - [i] = STATIC_CAST(uchar *, wordP)[length - i - 1]; - STATIC_CAST(uchar *, wordP)[length - i - 1] = temp; - } -} - -/************************************************************************/ -/* SfRealloc() */ -/* */ -/* A realloc cover function that will access a NULL pointer as */ -/* a valid input. */ -/************************************************************************/ - -static void *SfRealloc(void *pMem, int nNewSize) -{ - if (pMem == SHPLIB_NULLPTR) - return malloc(nNewSize); - else - return realloc(pMem, nNewSize); -} - /************************************************************************/ /* SHPWriteHeader() */ /* */ -/* Write out a header for the .shp and .shx files as well as the */ -/* contents of the index (.shx) file. */ +/* Write out a header for the .shp and .shx files as well as the */ +/* contents of the index (.shx) file. */ /************************************************************************/ void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP) @@ -150,64 +64,73 @@ void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP) /* Prepare header block for .shp file. */ /* -------------------------------------------------------------------- */ - uchar abyHeader[100] = {0}; + unsigned char abyHeader[100] = {0}; abyHeader[2] = 0x27; /* magic cookie */ abyHeader[3] = 0x0a; - int32 i32 = psSHP->nFileSize / 2; /* file size */ + uint32_t i32 = psSHP->nFileSize / 2; /* file size */ ByteCopy(&i32, abyHeader + 24, 4); - if (!bBigEndian) - SwapWord(4, abyHeader + 24); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(abyHeader + 24); +#endif i32 = 1000; /* version */ ByteCopy(&i32, abyHeader + 28, 4); - if (bBigEndian) - SwapWord(4, abyHeader + 28); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(abyHeader + 28); +#endif i32 = psSHP->nShapeType; /* shape type */ ByteCopy(&i32, abyHeader + 32, 4); - if (bBigEndian) - SwapWord(4, abyHeader + 32); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(abyHeader + 32); +#endif double dValue = psSHP->adBoundsMin[0]; /* set bounds */ ByteCopy(&dValue, abyHeader + 36, 8); - if (bBigEndian) - SwapWord(8, abyHeader + 36); - +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(abyHeader + 36); +#endif dValue = psSHP->adBoundsMin[1]; ByteCopy(&dValue, abyHeader + 44, 8); - if (bBigEndian) - SwapWord(8, abyHeader + 44); - +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(abyHeader + 44); +#endif dValue = psSHP->adBoundsMax[0]; ByteCopy(&dValue, abyHeader + 52, 8); - if (bBigEndian) - SwapWord(8, abyHeader + 52); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(abyHeader + 52); +#endif dValue = psSHP->adBoundsMax[1]; ByteCopy(&dValue, abyHeader + 60, 8); - if (bBigEndian) - SwapWord(8, abyHeader + 60); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(abyHeader + 60); +#endif dValue = psSHP->adBoundsMin[2]; /* z */ ByteCopy(&dValue, abyHeader + 68, 8); - if (bBigEndian) - SwapWord(8, abyHeader + 68); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(abyHeader + 68); +#endif dValue = psSHP->adBoundsMax[2]; ByteCopy(&dValue, abyHeader + 76, 8); - if (bBigEndian) - SwapWord(8, abyHeader + 76); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(abyHeader + 76); +#endif dValue = psSHP->adBoundsMin[3]; /* m */ ByteCopy(&dValue, abyHeader + 84, 8); - if (bBigEndian) - SwapWord(8, abyHeader + 84); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(abyHeader + 84); +#endif dValue = psSHP->adBoundsMax[3]; ByteCopy(&dValue, abyHeader + 92, 8); - if (bBigEndian) - SwapWord(8, abyHeader + 92); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(abyHeader + 92); +#endif /* -------------------------------------------------------------------- */ /* Write .shp file header. */ @@ -226,10 +149,11 @@ void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP) /* -------------------------------------------------------------------- */ /* Prepare, and write .shx file header. */ /* -------------------------------------------------------------------- */ - i32 = (psSHP->nRecords * 2 * sizeof(int32) + 100) / 2; /* file size */ + i32 = (psSHP->nRecords * 2 * sizeof(uint32_t) + 100) / 2; /* file size */ ByteCopy(&i32, abyHeader + 24, 4); - if (!bBigEndian) - SwapWord(4, abyHeader + 24); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(abyHeader + 24); +#endif if (psSHP->sHooks.FSeek(psSHP->fpSHX, 0, 0) != 0 || psSHP->sHooks.FWrite(abyHeader, 100, 1, psSHP->fpSHX) != 1) { @@ -246,8 +170,8 @@ void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP) /* -------------------------------------------------------------------- */ /* Write out the .shx contents. */ /* -------------------------------------------------------------------- */ - int32 *panSHX = - STATIC_CAST(int32 *, malloc(sizeof(int32) * 2 * psSHP->nRecords)); + uint32_t *panSHX = + STATIC_CAST(uint32_t *, malloc(sizeof(uint32_t) * 2 * psSHP->nRecords)); if (panSHX == SHPLIB_NULLPTR) { psSHP->sHooks.Error("Failure allocatin panSHX"); return; @@ -256,13 +180,13 @@ void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP) for (int i = 0; i < psSHP->nRecords; i++) { panSHX[i * 2] = psSHP->panRecOffset[i] / 2; panSHX[i * 2 + 1] = psSHP->panRecSize[i] / 2; - if (!bBigEndian) - SwapWord(4, panSHX + i * 2); - if (!bBigEndian) - SwapWord(4, panSHX + i * 2 + 1); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(panSHX + i * 2); + SHP_SWAP32(panSHX + i * 2 + 1); +#endif } - if (STATIC_CAST(int, psSHP->sHooks.FWrite(panSHX, sizeof(int32) * 2, + if (STATIC_CAST(int, psSHP->sHooks.FWrite(panSHX, sizeof(uint32_t) * 2, psSHP->nRecords, psSHP->fpSHX)) != psSHP->nRecords) { char szErrorMsg[200]; @@ -319,7 +243,7 @@ static int SHPGetLenWithoutExtension(const char *pszBasename) /************************************************************************/ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, - SAHooks *psHooks) + const SAHooks *psHooks) { /* -------------------------------------------------------------------- */ /* Ensure the access string is one of the legal ones. We */ @@ -336,23 +260,10 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, pszAccess = "rb"; } -/* -------------------------------------------------------------------- */ -/* Establish the byte order on this machine. */ -/* -------------------------------------------------------------------- */ -#if !defined(bBigEndian) - { - int i = 1; - if (*((uchar *)&i) == 1) - bBigEndian = false; - else - bBigEndian = true; - } -#endif - /* -------------------------------------------------------------------- */ /* Initialize the info structure. */ /* -------------------------------------------------------------------- */ - SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo), 1)); + SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1, sizeof(SHPInfo))); psSHP->bUpdated = FALSE; memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks)); @@ -365,18 +276,21 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5)); memcpy(pszFullname, pszLayer, nLenWithoutExtension); memcpy(pszFullname + nLenWithoutExtension, ".shp", 5); - psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess); + psSHP->fpSHP = + psSHP->sHooks.FOpen(pszFullname, pszAccess, psSHP->sHooks.pvUserData); if (psSHP->fpSHP == SHPLIB_NULLPTR) { memcpy(pszFullname + nLenWithoutExtension, ".SHP", 5); - psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess); + psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess, + psSHP->sHooks.pvUserData); } if (psSHP->fpSHP == SHPLIB_NULLPTR) { const size_t nMessageLen = strlen(pszFullname) * 2 + 256; char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen)); pszFullname[nLenWithoutExtension] = 0; - snprintf(pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.", - pszFullname, pszFullname); + snprintf(pszMessage, nMessageLen, + "Unable to open %s.shp or %s.SHP in %s mode.", pszFullname, + pszFullname, pszAccess); psHooks->Error(pszMessage); free(pszMessage); @@ -387,10 +301,12 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, } memcpy(pszFullname + nLenWithoutExtension, ".shx", 5); - psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess); + psSHP->fpSHX = + psSHP->sHooks.FOpen(pszFullname, pszAccess, psSHP->sHooks.pvUserData); if (psSHP->fpSHX == SHPLIB_NULLPTR) { memcpy(pszFullname + nLenWithoutExtension, ".SHX", 5); - psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess); + psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess, + psSHP->sHooks.pvUserData); } if (psSHP->fpSHX == SHPLIB_NULLPTR) { @@ -416,7 +332,7 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, /* -------------------------------------------------------------------- */ /* Read the file size from the SHP file. */ /* -------------------------------------------------------------------- */ - uchar *pabyBuf = STATIC_CAST(uchar *, malloc(100)); + unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(100)); if (psSHP->sHooks.FRead(pabyBuf, 100, 1, psSHP->fpSHP) != 1) { psSHP->sHooks.Error(".shp file is unreadable, or corrupt."); psSHP->sHooks.FClose(psSHP->fpSHP); @@ -489,43 +405,51 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, /* -------------------------------------------------------------------- */ double dValue; - if (bBigEndian) - SwapWord(8, pabyBuf + 36); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyBuf + 36); +#endif memcpy(&dValue, pabyBuf + 36, 8); psSHP->adBoundsMin[0] = dValue; - if (bBigEndian) - SwapWord(8, pabyBuf + 44); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyBuf + 44); +#endif memcpy(&dValue, pabyBuf + 44, 8); psSHP->adBoundsMin[1] = dValue; - if (bBigEndian) - SwapWord(8, pabyBuf + 52); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyBuf + 52); +#endif memcpy(&dValue, pabyBuf + 52, 8); psSHP->adBoundsMax[0] = dValue; - if (bBigEndian) - SwapWord(8, pabyBuf + 60); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyBuf + 60); +#endif memcpy(&dValue, pabyBuf + 60, 8); psSHP->adBoundsMax[1] = dValue; - if (bBigEndian) - SwapWord(8, pabyBuf + 68); /* z */ +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyBuf + 68); /* z */ +#endif memcpy(&dValue, pabyBuf + 68, 8); psSHP->adBoundsMin[2] = dValue; - if (bBigEndian) - SwapWord(8, pabyBuf + 76); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyBuf + 76); +#endif memcpy(&dValue, pabyBuf + 76, 8); psSHP->adBoundsMax[2] = dValue; - if (bBigEndian) - SwapWord(8, pabyBuf + 84); /* z */ +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyBuf + 84); /* z */ +#endif memcpy(&dValue, pabyBuf + 84, 8); psSHP->adBoundsMin[3] = dValue; - if (bBigEndian) - SwapWord(8, pabyBuf + 92); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyBuf + 92); +#endif memcpy(&dValue, pabyBuf + 92, 8); psSHP->adBoundsMax[3] = dValue; @@ -546,7 +470,8 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, if (bLazySHXLoading) pabyBuf = SHPLIB_NULLPTR; else - pabyBuf = STATIC_CAST(uchar *, malloc(8 * MAX(1, psSHP->nRecords))); + pabyBuf = + STATIC_CAST(unsigned char *, malloc(8 * MAX(1, psSHP->nRecords))); if (psSHP->panRecOffset == SHPLIB_NULLPTR || psSHP->panRecSize == SHPLIB_NULLPTR || @@ -612,13 +537,15 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, for (int i = 0; i < psSHP->nRecords; i++) { unsigned int nOffset; memcpy(&nOffset, pabyBuf + i * 8, 4); - if (!bBigEndian) - SwapWord(4, &nOffset); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nOffset); +#endif unsigned int nLength; memcpy(&nLength, pabyBuf + i * 8 + 4, 4); - if (!bBigEndian) - SwapWord(4, &nLength); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nLength); +#endif if (nOffset > STATIC_CAST(unsigned int, INT_MAX)) { char str[128]; @@ -657,7 +584,7 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess, /************************************************************************/ SHPHandle SHPAPI_CALL SHPOpenLLEx(const char *pszLayer, const char *pszAccess, - SAHooks *psHooks, int bRestoreSHX) + const SAHooks *psHooks, int bRestoreSHX) { if (!bRestoreSHX) return SHPOpenLL(pszLayer, pszAccess, psHooks); @@ -678,7 +605,7 @@ SHPHandle SHPAPI_CALL SHPOpenLLEx(const char *pszLayer, const char *pszAccess, /************************************************************************/ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess, - SAHooks *psHooks) + const SAHooks *psHooks) { /* -------------------------------------------------------------------- */ /* Ensure the access string is one of the legal ones. We */ @@ -693,19 +620,6 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess, pszAccess = "rb"; } -/* -------------------------------------------------------------------- */ -/* Establish the byte order on this machine. */ -/* -------------------------------------------------------------------- */ -#if !defined(bBigEndian) - { - int i = 1; - if (*((uchar *)&i) == 1) - bBigEndian = false; - else - bBigEndian = true; - } -#endif - /* -------------------------------------------------------------------- */ /* Open the .shp file. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ @@ -714,10 +628,10 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess, char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5)); memcpy(pszFullname, pszLayer, nLenWithoutExtension); memcpy(pszFullname + nLenWithoutExtension, ".shp", 5); - SAFile fpSHP = psHooks->FOpen(pszFullname, pszAccess); + SAFile fpSHP = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData); if (fpSHP == SHPLIB_NULLPTR) { memcpy(pszFullname + nLenWithoutExtension, ".SHP", 5); - fpSHP = psHooks->FOpen(pszFullname, pszAccess); + fpSHP = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData); } if (fpSHP == SHPLIB_NULLPTR) { @@ -738,7 +652,7 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess, /* -------------------------------------------------------------------- */ /* Read the file size from the SHP file. */ /* -------------------------------------------------------------------- */ - uchar *pabyBuf = STATIC_CAST(uchar *, malloc(100)); + unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(100)); if (psHooks->FRead(pabyBuf, 100, 1, fpSHP) != 1) { psHooks->Error(".shp file is unreadable, or corrupt."); psHooks->FClose(fpSHP); @@ -759,7 +673,8 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess, memcpy(pszFullname + nLenWithoutExtension, ".shx", 5); const char pszSHXAccess[] = "w+b"; - SAFile fpSHX = psHooks->FOpen(pszFullname, pszSHXAccess); + SAFile fpSHX = + psHooks->FOpen(pszFullname, pszSHXAccess, psHooks->pvUserData); if (fpSHX == SHPLIB_NULLPTR) { size_t nMessageLen = strlen(pszFullname) * 2 + 256; char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen)); @@ -789,25 +704,70 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess, // unsigned int nCurrentRecordOffset = 0; unsigned int nCurrentSHPOffset = 100; unsigned int nRealSHXContentSize = 100; - unsigned int niRecord = 0; - unsigned int nRecordLength = 0; + int nRetCode = TRUE; unsigned int nRecordOffset = 50; - char abyReadRecord[8]; while (nCurrentSHPOffset < nSHPFilesize) { + unsigned int niRecord = 0; + unsigned int nRecordLength = 0; + int nSHPType; + if (psHooks->FRead(&niRecord, 4, 1, fpSHP) == 1 && - psHooks->FRead(&nRecordLength, 4, 1, fpSHP) == 1) { - if (!bBigEndian) - SwapWord(4, &nRecordOffset); - memcpy(abyReadRecord, &nRecordOffset, 4); + psHooks->FRead(&nRecordLength, 4, 1, fpSHP) == 1 && + psHooks->FRead(&nSHPType, 4, 1, fpSHP) == 1) { + char abyReadRecord[8]; + unsigned int nRecordOffsetBE = nRecordOffset; + +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nRecordOffsetBE); +#endif + memcpy(abyReadRecord, &nRecordOffsetBE, 4); memcpy(abyReadRecord + 4, &nRecordLength, 4); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nRecordLength); +#endif +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nSHPType); +#endif + + // Sanity check on record length + if (nRecordLength < 1 || + nRecordLength > (nSHPFilesize - (nCurrentSHPOffset + 8)) / 2) { + char szErrorMsg[200]; + snprintf(szErrorMsg, sizeof(szErrorMsg), + "Error parsing .shp to restore .shx. " + "Invalid record length = %u at record starting at " + "offset %u", + nRecordLength, nCurrentSHPOffset); + psHooks->Error(szErrorMsg); + + nRetCode = FALSE; + break; + } + + // Sanity check on record type + if (nSHPType != SHPT_NULL && nSHPType != SHPT_POINT && + nSHPType != SHPT_ARC && nSHPType != SHPT_POLYGON && + nSHPType != SHPT_MULTIPOINT && nSHPType != SHPT_POINTZ && + nSHPType != SHPT_ARCZ && nSHPType != SHPT_POLYGONZ && + nSHPType != SHPT_MULTIPOINTZ && nSHPType != SHPT_POINTM && + nSHPType != SHPT_ARCM && nSHPType != SHPT_POLYGONM && + nSHPType != SHPT_MULTIPOINTM && nSHPType != SHPT_MULTIPATCH) { + char szErrorMsg[200]; + snprintf(szErrorMsg, sizeof(szErrorMsg), + "Error parsing .shp to restore .shx. " + "Invalid shape type = %d at record starting at " + "offset %u", + nSHPType, nCurrentSHPOffset); + psHooks->Error(szErrorMsg); + + nRetCode = FALSE; + break; + } + psHooks->FWrite(abyReadRecord, 8, 1, fpSHX); - if (!bBigEndian) - SwapWord(4, &nRecordOffset); - if (!bBigEndian) - SwapWord(4, &nRecordLength); nRecordOffset += nRecordLength + 4; // nCurrentRecordOffset += 8; nCurrentSHPOffset += 8 + nRecordLength * 2; @@ -816,21 +776,30 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess, nRealSHXContentSize += 8; } else { - psHooks->Error("Error parsing .shp to restore .shx"); - - psHooks->FClose(fpSHX); - psHooks->FClose(fpSHP); - - free(pabySHXHeader); - free(pszFullname); + char szErrorMsg[200]; + snprintf(szErrorMsg, sizeof(szErrorMsg), + "Error parsing .shp to restore .shx. " + "Cannot read first bytes of record starting at " + "offset %u", + nCurrentSHPOffset); + psHooks->Error(szErrorMsg); - return (0); + nRetCode = FALSE; + break; } } + if (nRetCode && nCurrentSHPOffset != nSHPFilesize) { + psHooks->Error("Error parsing .shp to restore .shx. " + "Not expected number of bytes"); + + nRetCode = FALSE; + } nRealSHXContentSize /= 2; // Bytes counted -> WORDs - if (!bBigEndian) - SwapWord(4, &nRealSHXContentSize); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nRealSHXContentSize); +#endif + psHooks->FSeek(fpSHX, 24, 0); psHooks->FWrite(&nRealSHXContentSize, 4, 1, fpSHX); @@ -840,13 +809,13 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess, free(pszFullname); free(pabySHXHeader); - return (1); + return nRetCode; } /************************************************************************/ /* SHPClose() */ -/* */ -/* Close the .shp and .shx files. */ +/* */ +/* Close the .shp and .shx files. */ /************************************************************************/ void SHPAPI_CALL SHPClose(SHPHandle psSHP) @@ -855,7 +824,7 @@ void SHPAPI_CALL SHPClose(SHPHandle psSHP) return; /* -------------------------------------------------------------------- */ - /* Update the header if we have modified anything. */ + /* Update the header if we have modified anything. */ /* -------------------------------------------------------------------- */ if (psSHP->bUpdated) SHPWriteHeader(psSHP); @@ -914,8 +883,9 @@ void SHPAPI_CALL SHPSetFastModeReadObject(SHPHandle hSHP, int bFastMode) /* Fetch general information about the shape file. */ /************************************************************************/ -void SHPAPI_CALL SHPGetInfo(SHPHandle psSHP, int *pnEntities, int *pnShapeType, - double *padfMinBound, double *padfMaxBound) +void SHPAPI_CALL SHPGetInfo(const SHPHandle psSHP, int *pnEntities, + int *pnShapeType, double *padfMinBound, + double *padfMaxBound) { if (psSHP == SHPLIB_NULLPTR) return; @@ -958,21 +928,8 @@ SHPHandle SHPAPI_CALL SHPCreate(const char *pszLayer, int nShapeType) /************************************************************************/ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, - SAHooks *psHooks) + const SAHooks *psHooks) { -/* -------------------------------------------------------------------- */ -/* Establish the byte order on this system. */ -/* -------------------------------------------------------------------- */ -#if !defined(bBigEndian) - { - int i = 1; - if (*((uchar *)&i) == 1) - bBigEndian = false; - else - bBigEndian = true; - } -#endif - /* -------------------------------------------------------------------- */ /* Open the two files so we can write their headers. */ /* -------------------------------------------------------------------- */ @@ -980,7 +937,7 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5)); memcpy(pszFullname, pszLayer, nLenWithoutExtension); memcpy(pszFullname + nLenWithoutExtension, ".shp", 5); - SAFile fpSHP = psHooks->FOpen(pszFullname, "wb"); + SAFile fpSHP = psHooks->FOpen(pszFullname, "w+b", psHooks->pvUserData); if (fpSHP == SHPLIB_NULLPTR) { char szErrorMsg[200]; snprintf(szErrorMsg, sizeof(szErrorMsg), "Failed to create file %s: %s", @@ -988,11 +945,11 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, psHooks->Error(szErrorMsg); free(pszFullname); - return NULL; + return SHPLIB_NULLPTR; } memcpy(pszFullname + nLenWithoutExtension, ".shx", 5); - SAFile fpSHX = psHooks->FOpen(pszFullname, "wb"); + SAFile fpSHX = psHooks->FOpen(pszFullname, "w+b", psHooks->pvUserData); if (fpSHX == SHPLIB_NULLPTR) { char szErrorMsg[200]; snprintf(szErrorMsg, sizeof(szErrorMsg), "Failed to create file %s: %s", @@ -1001,7 +958,7 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, free(pszFullname); psHooks->FClose(fpSHP); - return NULL; + return SHPLIB_NULLPTR; } free(pszFullname); @@ -1010,26 +967,29 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, /* -------------------------------------------------------------------- */ /* Prepare header block for .shp file. */ /* -------------------------------------------------------------------- */ - uchar abyHeader[100]; + unsigned char abyHeader[100]; memset(abyHeader, 0, sizeof(abyHeader)); abyHeader[2] = 0x27; /* magic cookie */ abyHeader[3] = 0x0a; - int32 i32 = 50; /* file size */ + uint32_t i32 = 50; /* file size */ ByteCopy(&i32, abyHeader + 24, 4); - if (!bBigEndian) - SwapWord(4, abyHeader + 24); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(abyHeader + 24); +#endif i32 = 1000; /* version */ ByteCopy(&i32, abyHeader + 28, 4); - if (bBigEndian) - SwapWord(4, abyHeader + 28); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(abyHeader + 28); +#endif i32 = nShapeType; /* shape type */ ByteCopy(&i32, abyHeader + 32, 4); - if (bBigEndian) - SwapWord(4, abyHeader + 32); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(abyHeader + 32); +#endif double dValue = 0.0; /* set bounds */ ByteCopy(&dValue, abyHeader + 36, 8); @@ -1051,7 +1011,7 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, free(pszFullname); psHooks->FClose(fpSHP); psHooks->FClose(fpSHX); - return NULL; + return SHPLIB_NULLPTR; } /* -------------------------------------------------------------------- */ @@ -1059,8 +1019,9 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, /* -------------------------------------------------------------------- */ i32 = 50; /* file size */ ByteCopy(&i32, abyHeader + 24, 4); - if (!bBigEndian) - SwapWord(4, abyHeader + 24); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(abyHeader + 24); +#endif if (psHooks->FWrite(abyHeader, 100, 1, fpSHX) != 1) { char szErrorMsg[200]; @@ -1073,16 +1034,37 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, free(pszFullname); psHooks->FClose(fpSHP); psHooks->FClose(fpSHX); - return NULL; + return SHPLIB_NULLPTR; } - /* -------------------------------------------------------------------- */ - /* Close the files, and then open them as regular existing files. */ - /* -------------------------------------------------------------------- */ - psHooks->FClose(fpSHP); - psHooks->FClose(fpSHX); + SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1, sizeof(SHPInfo))); - return (SHPOpenLL(pszLayer, "r+b", psHooks)); + psSHP->bUpdated = FALSE; + memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks)); + + psSHP->fpSHP = fpSHP; + psSHP->fpSHX = fpSHX; + psSHP->nShapeType = nShapeType; + psSHP->nFileSize = 100; + psSHP->panRecOffset = + STATIC_CAST(unsigned int *, malloc(sizeof(unsigned int))); + psSHP->panRecSize = + STATIC_CAST(unsigned int *, malloc(sizeof(unsigned int))); + + if (psSHP->panRecOffset == SHPLIB_NULLPTR || + psSHP->panRecSize == SHPLIB_NULLPTR) { + psSHP->sHooks.Error("Not enough memory to allocate requested memory"); + psSHP->sHooks.FClose(psSHP->fpSHP); + psSHP->sHooks.FClose(psSHP->fpSHX); + if (psSHP->panRecOffset) + free(psSHP->panRecOffset); + if (psSHP->panRecSize) + free(psSHP->panRecSize); + free(psSHP); + return SHPLIB_NULLPTR; + } + + return psSHP; } /************************************************************************/ @@ -1092,19 +1074,19 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType, /* indicated location in the record. */ /************************************************************************/ -static void _SHPSetBounds(uchar *pabyRec, SHPObject *psShape) +static void _SHPSetBounds(unsigned char *pabyRec, const SHPObject *psShape) { ByteCopy(&(psShape->dfXMin), pabyRec + 0, 8); ByteCopy(&(psShape->dfYMin), pabyRec + 8, 8); ByteCopy(&(psShape->dfXMax), pabyRec + 16, 8); ByteCopy(&(psShape->dfYMax), pabyRec + 24, 8); - if (bBigEndian) { - SwapWord(8, pabyRec + 0); - SwapWord(8, pabyRec + 8); - SwapWord(8, pabyRec + 16); - SwapWord(8, pabyRec + 24); - } +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + 0); + SHP_SWAP64(pabyRec + 8); + SHP_SWAP64(pabyRec + 16); + SHP_SWAP64(pabyRec + 24); +#endif } /************************************************************************/ @@ -1159,7 +1141,7 @@ SHPObject SHPAPI_CALL1(*) psObject->bMeasureIsUsed = FALSE; /* -------------------------------------------------------------------- */ - /* Establish whether this shape type has M, and Z values. */ + /* Establish whether this shape type has M, and Z values. */ /* -------------------------------------------------------------------- */ bool bHasM; bool bHasZ; @@ -1191,7 +1173,7 @@ SHPObject SHPAPI_CALL1(*) psObject->nParts = MAX(1, nParts); psObject->panPartStart = - STATIC_CAST(int *, calloc(sizeof(int), psObject->nParts)); + STATIC_CAST(int *, calloc(psObject->nParts, sizeof(int))); psObject->panPartType = STATIC_CAST(int *, malloc(sizeof(int) * psObject->nParts)); @@ -1208,8 +1190,7 @@ SHPObject SHPAPI_CALL1(*) psObject->panPartType[i] = SHPP_RING; } - if (psObject->panPartStart[0] != 0) - psObject->panPartStart[0] = 0; + psObject->panPartStart[0] = 0; } /* -------------------------------------------------------------------- */ @@ -1219,16 +1200,16 @@ SHPObject SHPAPI_CALL1(*) const size_t nSize = sizeof(double) * nVertices; psObject->padfX = STATIC_CAST(double *, padfX ? malloc(nSize) - : calloc(sizeof(double), nVertices)); + : calloc(nVertices, sizeof(double))); psObject->padfY = STATIC_CAST(double *, padfY ? malloc(nSize) - : calloc(sizeof(double), nVertices)); + : calloc(nVertices, sizeof(double))); psObject->padfZ = STATIC_CAST( double *, - padfZ &&bHasZ ? malloc(nSize) : calloc(sizeof(double), nVertices)); + padfZ &&bHasZ ? malloc(nSize) : calloc(nVertices, sizeof(double))); psObject->padfM = STATIC_CAST( double *, - padfM &&bHasM ? malloc(nSize) : calloc(sizeof(double), nVertices)); + padfM &&bHasM ? malloc(nSize) : calloc(nVertices, sizeof(double))); if (padfX != SHPLIB_NULLPTR) memcpy(psObject->padfX, padfX, nSize); if (padfY != SHPLIB_NULLPTR) @@ -1273,7 +1254,7 @@ SHPObject SHPAPI_CALL1(*) /************************************************************************/ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, - SHPObject *psObject) + const SHPObject *psObject) { psSHP->bUpdated = TRUE; @@ -1298,22 +1279,32 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, /* Add the new entity to the in memory index. */ /* -------------------------------------------------------------------- */ if (nShapeId == -1 && psSHP->nRecords + 1 > psSHP->nMaxRecords) { + /* This cannot overflow given that we check that the file size does + * not grow over 4 GB, and the minimum size of a record is 12 bytes, + * hence the maximm value for nMaxRecords is 357,913,941 + */ int nNewMaxRecords = psSHP->nMaxRecords + psSHP->nMaxRecords / 3 + 100; unsigned int *panRecOffsetNew; unsigned int *panRecSizeNew; panRecOffsetNew = STATIC_CAST( - unsigned int *, SfRealloc(psSHP->panRecOffset, - sizeof(unsigned int) * nNewMaxRecords)); - if (panRecOffsetNew == SHPLIB_NULLPTR) + unsigned int *, realloc(psSHP->panRecOffset, + sizeof(unsigned int) * nNewMaxRecords)); + if (panRecOffsetNew == SHPLIB_NULLPTR) { + psSHP->sHooks.Error("Failed to write shape object. " + "Memory allocation error."); return -1; + } psSHP->panRecOffset = panRecOffsetNew; panRecSizeNew = STATIC_CAST( - unsigned int *, SfRealloc(psSHP->panRecSize, - sizeof(unsigned int) * nNewMaxRecords)); - if (panRecSizeNew == SHPLIB_NULLPTR) + unsigned int *, + realloc(psSHP->panRecSize, sizeof(unsigned int) * nNewMaxRecords)); + if (panRecSizeNew == SHPLIB_NULLPTR) { + psSHP->sHooks.Error("Failed to write shape object. " + "Memory allocation error."); return -1; + } psSHP->panRecSize = panRecSizeNew; psSHP->nMaxRecords = nNewMaxRecords; @@ -1322,14 +1313,28 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, /* -------------------------------------------------------------------- */ /* Initialize record. */ /* -------------------------------------------------------------------- */ - uchar *pabyRec = - STATIC_CAST(uchar *, malloc(psObject->nVertices * 4 * sizeof(double) + - psObject->nParts * 8 + 128)); - if (pabyRec == SHPLIB_NULLPTR) + + /* The following computation cannot overflow on 32-bit platforms given that + * the user had to allocate arrays of at least that size. */ + size_t nRecMaxSize = + psObject->nVertices * 4 * sizeof(double) + psObject->nParts * 8; + /* But the following test could trigger on 64-bit platforms on huge + * geometries. */ + const unsigned nExtraSpaceForGeomHeader = 128; + if (nRecMaxSize > UINT_MAX - nExtraSpaceForGeomHeader) { + psSHP->sHooks.Error("Failed to write shape object. Too big geometry."); return -1; + } + nRecMaxSize += nExtraSpaceForGeomHeader; + unsigned char *pabyRec = STATIC_CAST(unsigned char *, malloc(nRecMaxSize)); + if (pabyRec == SHPLIB_NULLPTR) { + psSHP->sHooks.Error("Failed to write shape object. " + "Memory allocation error."); + return -1; + } /* -------------------------------------------------------------------- */ - /* Extract vertices for a Polygon or Arc. */ + /* Extract vertices for a Polygon or Arc. */ /* -------------------------------------------------------------------- */ unsigned int nRecordSize = 0; const bool bFirstFeature = psSHP->nRecords == 0; @@ -1339,15 +1344,15 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, psObject->nSHPType == SHPT_POLYGONM || psObject->nSHPType == SHPT_ARC || psObject->nSHPType == SHPT_ARCZ || psObject->nSHPType == SHPT_ARCM || psObject->nSHPType == SHPT_MULTIPATCH) { - int32 nPoints = psObject->nVertices; - int32 nParts = psObject->nParts; + uint32_t nPoints = psObject->nVertices; + uint32_t nParts = psObject->nParts; _SHPSetBounds(pabyRec + 12, psObject); - if (bBigEndian) - SwapWord(4, &nPoints); - if (bBigEndian) - SwapWord(4, &nParts); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nPoints); + SHP_SWAP32(&nParts); +#endif ByteCopy(&nPoints, pabyRec + 40 + 8, 4); ByteCopy(&nParts, pabyRec + 36 + 8, 4); @@ -1360,8 +1365,9 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, ByteCopy(psObject->panPartStart, pabyRec + 44 + 8, 4 * psObject->nParts); for (int i = 0; i < psObject->nParts; i++) { - if (bBigEndian) - SwapWord(4, pabyRec + 44 + 8 + 4 * i); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(pabyRec + 44 + 8 + 4 * i); +#endif nRecordSize += 4; } @@ -1372,8 +1378,9 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, memcpy(pabyRec + nRecordSize, psObject->panPartType, 4 * psObject->nParts); for (int i = 0; i < psObject->nParts; i++) { - if (bBigEndian) - SwapWord(4, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(pabyRec + nRecordSize); +#endif nRecordSize += 4; } } @@ -1385,11 +1392,10 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, ByteCopy(psObject->padfX + i, pabyRec + nRecordSize, 8); ByteCopy(psObject->padfY + i, pabyRec + nRecordSize + 8, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); - - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize + 8); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); + SHP_SWAP64(pabyRec + nRecordSize + 8); +#endif nRecordSize += 2 * 8; } @@ -1401,19 +1407,22 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, psObject->nSHPType == SHPT_ARCZ || psObject->nSHPType == SHPT_MULTIPATCH) { ByteCopy(&(psObject->dfZMin), pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; ByteCopy(&(psObject->dfZMax), pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; for (int i = 0; i < psObject->nVertices; i++) { ByteCopy(psObject->padfZ + i, pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; } } @@ -1430,65 +1439,72 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, || psObject->nSHPType == SHPT_POLYGONZ || psObject->nSHPType == SHPT_ARCZ)) { ByteCopy(&(psObject->dfMMin), pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; ByteCopy(&(psObject->dfMMax), pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; for (int i = 0; i < psObject->nVertices; i++) { ByteCopy(psObject->padfM + i, pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; } } } /* -------------------------------------------------------------------- */ - /* Extract vertices for a MultiPoint. */ + /* Extract vertices for a MultiPoint. */ /* -------------------------------------------------------------------- */ else if (psObject->nSHPType == SHPT_MULTIPOINT || psObject->nSHPType == SHPT_MULTIPOINTZ || psObject->nSHPType == SHPT_MULTIPOINTM) { - int32 nPoints = psObject->nVertices; + uint32_t nPoints = psObject->nVertices; _SHPSetBounds(pabyRec + 12, psObject); - if (bBigEndian) - SwapWord(4, &nPoints); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nPoints); +#endif ByteCopy(&nPoints, pabyRec + 44, 4); for (int i = 0; i < psObject->nVertices; i++) { ByteCopy(psObject->padfX + i, pabyRec + 48 + i * 16, 8); ByteCopy(psObject->padfY + i, pabyRec + 48 + i * 16 + 8, 8); - if (bBigEndian) - SwapWord(8, pabyRec + 48 + i * 16); - if (bBigEndian) - SwapWord(8, pabyRec + 48 + i * 16 + 8); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + 48 + i * 16); + SHP_SWAP64(pabyRec + 48 + i * 16 + 8); +#endif } nRecordSize = 48 + 16 * psObject->nVertices; if (psObject->nSHPType == SHPT_MULTIPOINTZ) { ByteCopy(&(psObject->dfZMin), pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; ByteCopy(&(psObject->dfZMax), pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; for (int i = 0; i < psObject->nVertices; i++) { ByteCopy(psObject->padfZ + i, pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; } } @@ -1497,26 +1513,29 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, (psObject->nSHPType == SHPT_MULTIPOINTZ || psObject->nSHPType == SHPT_MULTIPOINTM)) { ByteCopy(&(psObject->dfMMin), pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; ByteCopy(&(psObject->dfMMax), pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; for (int i = 0; i < psObject->nVertices; i++) { ByteCopy(psObject->padfM + i, pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; } } } /* -------------------------------------------------------------------- */ - /* Write point. */ + /* Write point. */ /* -------------------------------------------------------------------- */ else if (psObject->nSHPType == SHPT_POINT || psObject->nSHPType == SHPT_POINTZ || @@ -1524,25 +1543,27 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, ByteCopy(psObject->padfX, pabyRec + 12, 8); ByteCopy(psObject->padfY, pabyRec + 20, 8); - if (bBigEndian) - SwapWord(8, pabyRec + 12); - if (bBigEndian) - SwapWord(8, pabyRec + 20); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + 12); + SHP_SWAP64(pabyRec + 20); +#endif nRecordSize = 28; if (psObject->nSHPType == SHPT_POINTZ) { ByteCopy(psObject->padfZ, pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; } if (psObject->bMeasureIsUsed && (psObject->nSHPType == SHPT_POINTZ || psObject->nSHPType == SHPT_POINTM)) { ByteCopy(psObject->padfM, pabyRec + nRecordSize, 8); - if (bBigEndian) - SwapWord(8, pabyRec + nRecordSize); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP64(pabyRec + nRecordSize); +#endif nRecordSize += 8; } } @@ -1598,20 +1619,23 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, /* -------------------------------------------------------------------- */ /* Set the shape type, record number, and record size. */ /* -------------------------------------------------------------------- */ - int32 i32 = + uint32_t i32 = (nShapeId < 0) ? psSHP->nRecords + 1 : nShapeId + 1; /* record # */ - if (!bBigEndian) - SwapWord(4, &i32); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&i32); +#endif ByteCopy(&i32, pabyRec, 4); i32 = (nRecordSize - 8) / 2; /* record size */ - if (!bBigEndian) - SwapWord(4, &i32); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&i32); +#endif ByteCopy(&i32, pabyRec + 4, 4); i32 = psObject->nSHPType; /* shape type */ - if (bBigEndian) - SwapWord(4, &i32); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&i32); +#endif ByteCopy(&i32, pabyRec + 8, 4); /* -------------------------------------------------------------------- */ @@ -1666,7 +1690,7 @@ int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, psSHP->panRecSize[nShapeId] = nRecordSize - 8; /* -------------------------------------------------------------------- */ - /* Expand file wide bounds based on this shape. */ + /* Expand file wide bounds based on this shape. */ /* -------------------------------------------------------------------- */ if (bFirstFeature) { if (psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0) { @@ -1754,11 +1778,11 @@ static unsigned char *SHPReallocObjectBufIfNecessary(SHPHandle psSHP, /************************************************************************/ /* SHPReadObject() */ /* */ -/* Read the vertices, parts, and other non-attribute information */ -/* for one shape. */ +/* Read the vertices, parts, and other non-attribute information */ +/* for one shape. */ /************************************************************************/ -SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) +SHPObject SHPAPI_CALL1(*) SHPReadObject(const SHPHandle psSHP, int hEntity) { /* -------------------------------------------------------------------- */ /* Validate the record/entity number. */ @@ -1786,10 +1810,10 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) psSHP->sHooks.Error(str); return SHPLIB_NULLPTR; } - if (!bBigEndian) - SwapWord(4, &nOffset); - if (!bBigEndian) - SwapWord(4, &nLength); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nOffset); + SHP_SWAP32(&nLength); +#endif if (nOffset > STATIC_CAST(unsigned int, INT_MAX)) { char str[128]; @@ -1859,8 +1883,8 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) } } - uchar *pabyRecNew = - STATIC_CAST(uchar *, SfRealloc(psSHP->pabyRec, nNewBufSize)); + unsigned char *pabyRecNew = + STATIC_CAST(unsigned char *, realloc(psSHP->pabyRec, nNewBufSize)); if (pabyRecNew == SHPLIB_NULLPTR) { char szErrorMsg[160]; snprintf(szErrorMsg, sizeof(szErrorMsg), @@ -1919,8 +1943,9 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) /* Do a sanity check */ int nSHPContentLength; memcpy(&nSHPContentLength, psSHP->pabyRec + 4, 4); - if (!bBigEndian) - SwapWord(4, &(nSHPContentLength)); +#if !defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&(nSHPContentLength)); +#endif if (nSHPContentLength < 0 || nSHPContentLength > INT_MAX / 2 - 4 || 2 * nSHPContentLength + 8 != nBytesRead) { char str[128]; @@ -1962,11 +1987,12 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) int nSHPType; memcpy(&nSHPType, psSHP->pabyRec + 8, 4); - if (bBigEndian) - SwapWord(4, &(nSHPType)); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&(nSHPType)); +#endif /* -------------------------------------------------------------------- */ - /* Allocate and minimally initialize the object. */ + /* Allocate and minimally initialize the object. */ /* -------------------------------------------------------------------- */ SHPObject *psShape; if (psSHP->bFastModeReadObject) { @@ -1988,7 +2014,7 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) psShape->bFastModeReadObject = psSHP->bFastModeReadObject; /* ==================================================================== */ - /* Extract vertices for a Polygon or Arc. */ + /* Extract vertices for a Polygon or Arc. */ /* ==================================================================== */ if (psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC || psShape->nSHPType == SHPT_POLYGONZ || @@ -2007,22 +2033,20 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) } /* -------------------------------------------------------------------- */ - /* Get the X/Y bounds. */ + /* Get the X/Y bounds. */ /* -------------------------------------------------------------------- */ - memcpy(&(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8); - memcpy(&(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8); - memcpy(&(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8); - memcpy(&(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8); - - if (bBigEndian) - SwapWord(8, &(psShape->dfXMin)); - if (bBigEndian) - SwapWord(8, &(psShape->dfYMin)); - if (bBigEndian) - SwapWord(8, &(psShape->dfXMax)); - if (bBigEndian) - SwapWord(8, &(psShape->dfYMax)); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(&psShape->dfXMin, psSHP->pabyRec + 8 + 4); + SHP_SWAPDOUBLE_CPY(&psShape->dfYMin, psSHP->pabyRec + 8 + 12); + SHP_SWAPDOUBLE_CPY(&psShape->dfXMax, psSHP->pabyRec + 8 + 20); + SHP_SWAPDOUBLE_CPY(&psShape->dfYMax, psSHP->pabyRec + 8 + 28); +#else + memcpy(&psShape->dfXMin, psSHP->pabyRec + 8 + 4, 8); + memcpy(&psShape->dfYMin, psSHP->pabyRec + 8 + 12, 8); + memcpy(&psShape->dfXMax, psSHP->pabyRec + 8 + 20, 8); + memcpy(&psShape->dfYMax, psSHP->pabyRec + 8 + 28, 8); +#endif /* -------------------------------------------------------------------- */ @@ -2030,15 +2054,15 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) /* to proper size. */ /* -------------------------------------------------------------------- */ - int32 nPoints; + uint32_t nPoints; memcpy(&nPoints, psSHP->pabyRec + 40 + 8, 4); - int32 nParts; + uint32_t nParts; memcpy(&nParts, psSHP->pabyRec + 36 + 8, 4); - if (bBigEndian) - SwapWord(4, &nPoints); - if (bBigEndian) - SwapWord(4, &nParts); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nPoints); + SHP_SWAP32(&nParts); +#endif /* nPoints and nParts are unsigned */ if (/* nPoints < 0 || nParts < 0 || */ @@ -2121,7 +2145,7 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) return SHPLIB_NULLPTR; } - for (int i = 0; STATIC_CAST(int32, i) < nParts; i++) + for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++) psShape->panPartType[i] = SHPP_RING; /* -------------------------------------------------------------------- @@ -2130,9 +2154,10 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) /* -------------------------------------------------------------------- */ memcpy(psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts); - for (int i = 0; STATIC_CAST(int32, i) < nParts; i++) { - if (bBigEndian) - SwapWord(4, psShape->panPartStart + i); + for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++) { +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(psShape->panPartStart + i); +#endif /* We check that the offset is inside the vertex array */ if (psShape->panPartStart[i] < 0 || @@ -2174,9 +2199,10 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) */ if (psShape->nSHPType == SHPT_MULTIPATCH) { memcpy(psShape->panPartType, psSHP->pabyRec + nOffset, 4 * nParts); - for (int i = 0; STATIC_CAST(int32, i) < nParts; i++) { - if (bBigEndian) - SwapWord(4, psShape->panPartType + i); + for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++) { +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(psShape->panPartType + i); +#endif } nOffset += 4 * nParts; @@ -2187,16 +2213,17 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) /* Copy out the vertices from the record. */ /* -------------------------------------------------------------------- */ - for (int i = 0; STATIC_CAST(int32, i) < nPoints; i++) { + for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++) { +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(psShape->padfX + i, + psSHP->pabyRec + nOffset + i * 16); + SHP_SWAPDOUBLE_CPY(psShape->padfY + i, + psSHP->pabyRec + nOffset + i * 16 + 8); +#else memcpy(psShape->padfX + i, psSHP->pabyRec + nOffset + i * 16, 8); - memcpy(psShape->padfY + i, psSHP->pabyRec + nOffset + i * 16 + 8, 8); - - if (bBigEndian) - SwapWord(8, psShape->padfX + i); - if (bBigEndian) - SwapWord(8, psShape->padfY + i); +#endif } nOffset += 16 * nPoints; @@ -2209,19 +2236,23 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) if (psShape->nSHPType == SHPT_POLYGONZ || psShape->nSHPType == SHPT_ARCZ || psShape->nSHPType == SHPT_MULTIPATCH) { - memcpy(&(psShape->dfZMin), psSHP->pabyRec + nOffset, 8); - memcpy(&(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(&psShape->dfZMin, psSHP->pabyRec + nOffset); + SHP_SWAPDOUBLE_CPY(&psShape->dfZMax, psSHP->pabyRec + nOffset + 8); +#else + memcpy(&psShape->dfZMin, psSHP->pabyRec + nOffset, 8); + memcpy(&psShape->dfZMax, psSHP->pabyRec + nOffset + 8, 8); - if (bBigEndian) - SwapWord(8, &(psShape->dfZMin)); - if (bBigEndian) - SwapWord(8, &(psShape->dfZMax)); +#endif - for (int i = 0; STATIC_CAST(int32, i) < nPoints; i++) { + for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++) { +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(psShape->padfZ + i, + psSHP->pabyRec + nOffset + 16 + i * 8); +#else memcpy(psShape->padfZ + i, psSHP->pabyRec + nOffset + 16 + i * 8, 8); - if (bBigEndian) - SwapWord(8, psShape->padfZ + i); +#endif } nOffset += 16 + 8 * nPoints; @@ -2239,19 +2270,22 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) /* -------------------------------------------------------------------- */ if (nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8 * nPoints)) { - memcpy(&(psShape->dfMMin), psSHP->pabyRec + nOffset, 8); - memcpy(&(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8); - - if (bBigEndian) - SwapWord(8, &(psShape->dfMMin)); - if (bBigEndian) - SwapWord(8, &(psShape->dfMMax)); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(&psShape->dfMMin, psSHP->pabyRec + nOffset); + SHP_SWAPDOUBLE_CPY(&psShape->dfMMax, psSHP->pabyRec + nOffset + 8); +#else + memcpy(&psShape->dfMMin, psSHP->pabyRec + nOffset, 8); + memcpy(&psShape->dfMMax, psSHP->pabyRec + nOffset + 8, 8); +#endif - for (int i = 0; STATIC_CAST(int32, i) < nPoints; i++) { + for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++) { +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(psShape->padfM + i, + psSHP->pabyRec + nOffset + 16 + i * 8); +#else memcpy(psShape->padfM + i, psSHP->pabyRec + nOffset + 16 + i * 8, 8); - if (bBigEndian) - SwapWord(8, psShape->padfM + i); +#endif } psShape->bMeasureIsUsed = TRUE; } @@ -2261,7 +2295,7 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) } /* ==================================================================== */ - /* Extract vertices for a MultiPoint. */ + /* Extract vertices for a MultiPoint. */ /* ==================================================================== */ else if (psShape->nSHPType == SHPT_MULTIPOINT || psShape->nSHPType == SHPT_MULTIPOINTM || @@ -2276,11 +2310,12 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) SHPDestroyObject(psShape); return SHPLIB_NULLPTR; } - int32 nPoints; + uint32_t nPoints; memcpy(&nPoints, psSHP->pabyRec + 44, 4); - if (bBigEndian) - SwapWord(4, &nPoints); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAP32(&nPoints); +#endif /* nPoints is unsigned */ if (/* nPoints < 0 || */ nPoints > 50 * 1000 * 1000) { @@ -2346,36 +2381,36 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) return SHPLIB_NULLPTR; } - for (int i = 0; STATIC_CAST(int32, i) < nPoints; i++) { + for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++) { +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(psShape->padfX + i, + psSHP->pabyRec + 48 + 16 * i); + SHP_SWAPDOUBLE_CPY(psShape->padfY + i, + psSHP->pabyRec + 48 + 16 * i + 8); +#else memcpy(psShape->padfX + i, psSHP->pabyRec + 48 + 16 * i, 8); memcpy(psShape->padfY + i, psSHP->pabyRec + 48 + 16 * i + 8, 8); - - if (bBigEndian) - SwapWord(8, psShape->padfX + i); - if (bBigEndian) - SwapWord(8, psShape->padfY + i); +#endif } int nOffset = 48 + 16 * nPoints; /* -------------------------------------------------------------------- */ - /* Get the X/Y bounds. */ + /* Get the X/Y bounds. */ /* -------------------------------------------------------------------- */ - memcpy(&(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8); - memcpy(&(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8); - memcpy(&(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8); - memcpy(&(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8); - - if (bBigEndian) - SwapWord(8, &(psShape->dfXMin)); - if (bBigEndian) - SwapWord(8, &(psShape->dfYMin)); - if (bBigEndian) - SwapWord(8, &(psShape->dfXMax)); - if (bBigEndian) - SwapWord(8, &(psShape->dfYMax)); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(&psShape->dfXMin, psSHP->pabyRec + 8 + 4); + SHP_SWAPDOUBLE_CPY(&psShape->dfYMin, psSHP->pabyRec + 8 + 12); + SHP_SWAPDOUBLE_CPY(&psShape->dfXMax, psSHP->pabyRec + 8 + 20); + SHP_SWAPDOUBLE_CPY(&psShape->dfYMax, psSHP->pabyRec + 8 + 28); +#else + memcpy(&psShape->dfXMin, psSHP->pabyRec + 8 + 4, 8); + memcpy(&psShape->dfYMin, psSHP->pabyRec + 8 + 12, 8); + memcpy(&psShape->dfXMax, psSHP->pabyRec + 8 + 20, 8); + memcpy(&psShape->dfYMax, psSHP->pabyRec + 8 + 28, 8); +#endif /* -------------------------------------------------------------------- */ @@ -2383,19 +2418,22 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) /* -------------------------------------------------------------------- */ if (psShape->nSHPType == SHPT_MULTIPOINTZ) { - memcpy(&(psShape->dfZMin), psSHP->pabyRec + nOffset, 8); - memcpy(&(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8); - - if (bBigEndian) - SwapWord(8, &(psShape->dfZMin)); - if (bBigEndian) - SwapWord(8, &(psShape->dfZMax)); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(&psShape->dfZMin, psSHP->pabyRec + nOffset); + SHP_SWAPDOUBLE_CPY(&psShape->dfZMax, psSHP->pabyRec + nOffset + 8); +#else + memcpy(&psShape->dfZMin, psSHP->pabyRec + nOffset, 8); + memcpy(&psShape->dfZMax, psSHP->pabyRec + nOffset + 8, 8); +#endif - for (int i = 0; STATIC_CAST(int32, i) < nPoints; i++) { + for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++) { +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(psShape->padfZ + i, + psSHP->pabyRec + nOffset + 16 + i * 8); +#else memcpy(psShape->padfZ + i, psSHP->pabyRec + nOffset + 16 + i * 8, 8); - if (bBigEndian) - SwapWord(8, psShape->padfZ + i); +#endif } nOffset += 16 + 8 * nPoints; @@ -2412,19 +2450,22 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) /* -------------------------------------------------------------------- */ if (nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8 * nPoints)) { - memcpy(&(psShape->dfMMin), psSHP->pabyRec + nOffset, 8); - memcpy(&(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8); - - if (bBigEndian) - SwapWord(8, &(psShape->dfMMin)); - if (bBigEndian) - SwapWord(8, &(psShape->dfMMax)); +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(&psShape->dfMMin, psSHP->pabyRec + nOffset); + SHP_SWAPDOUBLE_CPY(&psShape->dfMMax, psSHP->pabyRec + nOffset + 8); +#else + memcpy(&psShape->dfMMin, psSHP->pabyRec + nOffset, 8); + memcpy(&psShape->dfMMax, psSHP->pabyRec + nOffset + 8, 8); +#endif - for (int i = 0; STATIC_CAST(int32, i) < nPoints; i++) { + for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++) { +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(psShape->padfM + i, + psSHP->pabyRec + nOffset + 16 + i * 8); +#else memcpy(psShape->padfM + i, psSHP->pabyRec + nOffset + 16 + i * 8, 8); - if (bBigEndian) - SwapWord(8, psShape->padfM + i); +#endif } psShape->bMeasureIsUsed = TRUE; } @@ -2465,13 +2506,13 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) SHPDestroyObject(psShape); return SHPLIB_NULLPTR; } +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(psShape->padfX, psSHP->pabyRec + 12); + SHP_SWAPDOUBLE_CPY(psShape->padfY, psSHP->pabyRec + 20); +#else memcpy(psShape->padfX, psSHP->pabyRec + 12, 8); memcpy(psShape->padfY, psSHP->pabyRec + 20, 8); - - if (bBigEndian) - SwapWord(8, psShape->padfX); - if (bBigEndian) - SwapWord(8, psShape->padfY); +#endif int nOffset = 20 + 8; @@ -2481,10 +2522,11 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) /* -------------------------------------------------------------------- */ if (psShape->nSHPType == SHPT_POINTZ) { +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(psShape->padfZ, psSHP->pabyRec + nOffset); +#else memcpy(psShape->padfZ, psSHP->pabyRec + nOffset, 8); - - if (bBigEndian) - SwapWord(8, psShape->padfZ); +#endif nOffset += 8; } @@ -2498,10 +2540,11 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity) /* -------------------------------------------------------------------- */ if (nEntitySize >= nOffset + 8) { +#if defined(SHP_BIG_ENDIAN) + SHP_SWAPDOUBLE_CPY(psShape->padfM, psSHP->pabyRec + nOffset); +#else memcpy(psShape->padfM, psSHP->pabyRec + nOffset, 8); - - if (bBigEndian) - SwapWord(8, psShape->padfM); +#endif psShape->bMeasureIsUsed = TRUE; } @@ -2739,8 +2782,9 @@ static int SHPRewindIsInnerRing(const SHPObject *psObject, int iOpRing, /* specification. */ /************************************************************************/ -int SHPAPI_CALL SHPRewindObject(CPL_UNUSED SHPHandle hSHP, SHPObject *psObject) +int SHPAPI_CALL SHPRewindObject(const SHPHandle hSHP, SHPObject *psObject) { + (void)hSHP; /* -------------------------------------------------------------------- */ /* Do nothing if this is not a polygon object. */ /* -------------------------------------------------------------------- */