[Git][debian-gis-team/shapelib][upstream] New upstream version 1.6.2
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Wed Sep 24 00:12:37 BST 2025
Bas Couwenberg pushed to branch upstream at Debian GIS Project / shapelib
Commits:
789bb79c by Bas Couwenberg at 2025-09-23T15:49:56-07:00
New upstream version 1.6.2
- - - - -
20 changed files:
- CMakeLists.txt
- Makefile.am
- Makefile.in
- configure
- configure.ac
- dbfadd.c
- dbfcreate.c
- dbfdump.c
- dbfopen.c
- safileio.c
- sbnsearch.c
- shapefil.h
- shpopen.c
- shptree.c
- tests/CMakeLists.txt
- tests/dbf_test.cc
- tests/expect3.out
- + tests/shp_bench.cc
- tests/test3.sh
- web/release.html
Changes:
=====================================
CMakeLists.txt
=====================================
@@ -7,6 +7,11 @@
#
# See README.CMake
+set(PACKAGE shp)
+if (TARGET ${PACKAGE})
+ return ()
+endif ()
+
# Version 3.11 or above of cmake is currently required for all platforms.
cmake_minimum_required(VERSION 3.11)
project(shapelib C CXX)
@@ -16,8 +21,8 @@ message(STATUS "CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 6)
-set(PROJECT_VERSION_PATCH 1)
-set(shp_LIB_VERSIONINFO "5:0:1")
+set(PROJECT_VERSION_PATCH 2)
+set(shp_LIB_VERSIONINFO "6:0:2")
set(PROJECT_VERSION
"${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
@@ -49,7 +54,6 @@ if(BUILD_SHARED_LIBS AND (WIN32 OR CYGWIN))
set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dll)
endif()
-set(PACKAGE shp)
# Set up install locations.
set(
@@ -202,8 +206,9 @@ endif()
find_program(BASH_EXECUTABLE bash)
if(BASH_EXECUTABLE)
- set(BUILD_TESTING ON CACHE BOOL "")
+ option(BUILD_TESTING "Build tests" ON)
else()
+ set(BUILD_TESTING OFF CACHE BOOL "Disable tests")
message(STATUS "WARNING: bash not available so disabling testing")
endif()
@@ -292,8 +297,6 @@ if(BUILD_TESTING)
)
declare_test_executable(test3 "dbfadd;dbfcreate;dbfdump;shpadd;shpcreate;shpdump")
- include(CTest)
-
add_subdirectory(tests)
endif()
=====================================
Makefile.am
=====================================
@@ -21,6 +21,7 @@ EXTRA_DIST = makefile.vc CMakeLists.txt autogen.sh \
tests/CMakeLists.txt \
tests/dbf_test.cc \
tests/sbn_test.cc \
+ tests/shp_bench.cc \
tests/shp_test.cc \
tests/test1.sh tests/test2.sh tests/test3.sh \
tests/expect1.out tests/expect2.out tests/expect3.out \
=====================================
Makefile.in
=====================================
@@ -640,6 +640,7 @@ EXTRA_DIST = makefile.vc CMakeLists.txt autogen.sh \
tests/CMakeLists.txt \
tests/dbf_test.cc \
tests/sbn_test.cc \
+ tests/shp_bench.cc \
tests/shp_test.cc \
tests/test1.sh tests/test2.sh tests/test3.sh \
tests/expect1.out tests/expect2.out tests/expect3.out \
=====================================
configure
=====================================
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for shapelib 1.6.1.
+# Generated by GNU Autoconf 2.69 for shapelib 1.6.2.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='shapelib'
PACKAGE_TARNAME='shapelib'
-PACKAGE_VERSION='1.6.1'
-PACKAGE_STRING='shapelib 1.6.1'
+PACKAGE_VERSION='1.6.2'
+PACKAGE_STRING='shapelib 1.6.2'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1336,7 +1336,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures shapelib 1.6.1 to adapt to many kinds of systems.
+\`configure' configures shapelib 1.6.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1407,7 +1407,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of shapelib 1.6.1:";;
+ short | recursive ) echo "Configuration of shapelib 1.6.2:";;
esac
cat <<\_ACEOF
@@ -1520,7 +1520,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-shapelib configure 1.6.1
+shapelib configure 1.6.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1919,7 +1919,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by shapelib $as_me 1.6.1, which was
+It was created by shapelib $as_me 1.6.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -4328,7 +4328,7 @@ fi
# Define the identity of the package.
PACKAGE='shapelib'
- VERSION='1.6.1'
+ VERSION='1.6.2'
cat >>confdefs.h <<_ACEOF
@@ -4762,7 +4762,7 @@ unknown)
esac
-SHAPELIB_SO_VERSION=5:0:1
+SHAPELIB_SO_VERSION=6:0:2
ac_ext=c
@@ -17429,7 +17429,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by shapelib $as_me 1.6.1, which was
+This file was extended by shapelib $as_me 1.6.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -17486,7 +17486,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-shapelib config.status 1.6.1
+shapelib config.status 1.6.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
=====================================
configure.ac
=====================================
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
m4_define(shapelib_version_major, 1)
m4_define(shapelib_version_minor, 6)
-m4_define(shapelib_version_micro, 1)
+m4_define(shapelib_version_micro, 2)
AC_PREREQ(2.62)
AC_INIT(shapelib, shapelib_version_major.shapelib_version_minor.shapelib_version_micro)
@@ -28,7 +28,7 @@ AM_SILENT_RULES([yes])
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
dnl See http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
-AC_SUBST([SHAPELIB_SO_VERSION], [5:0:1])
+AC_SUBST([SHAPELIB_SO_VERSION], [6:0:2])
AC_PROG_CC
AC_PROG_CXX
=====================================
dbfadd.c
=====================================
@@ -44,6 +44,9 @@ int main(int argc, char **argv)
const int iRecord = DBFGetRecordCount(hDBF);
+ SHPDate date;
+ char bool;
+
// Loop assigning the new field values.
for (int i = 0; i < DBFGetFieldCount(hDBF); i++)
{
@@ -51,7 +54,23 @@ int main(int argc, char **argv)
DBFWriteNULLAttribute(hDBF, iRecord, i);
else if (DBFGetFieldInfo(hDBF, i, NULL, NULL, NULL) == FTString)
DBFWriteStringAttribute(hDBF, iRecord, i, argv[i + 2]);
+ else if (DBFGetFieldInfo(hDBF, i, NULL, NULL, NULL) == FTDate)
+ {
+ if (3 == sscanf(argv[i + 2], "%4d%2d%2d", &date.year, &date.month,
+ &date.day))
+ {
+ DBFWriteDateAttribute(hDBF, iRecord, i, &date);
+ }
+ }
+ else if (DBFGetFieldInfo(hDBF, i, NULL, NULL, NULL) == FTLogical)
+ {
+ if (1 == sscanf(argv[i + 2], "%c", &bool))
+ {
+ DBFWriteLogicalAttribute(hDBF, iRecord, i, bool);
+ }
+ }
else
+
DBFWriteDoubleAttribute(hDBF, iRecord, i, atof(argv[i + 2]));
}
=====================================
dbfcreate.c
=====================================
@@ -23,7 +23,9 @@ int main(int argc, char **argv)
if (argc < 2)
{
printf("dbfcreate xbase_file [[-s field_name width], "
- "[-n field_name width decimals]]...\n");
+ "[-n field_name width decimals], "
+ "[-d field_name], "
+ "[-l field_name]]...\n");
return 1;
}
@@ -65,6 +67,33 @@ int main(int argc, char **argv)
}
i += 3;
}
+ else if (i < argc - 1 && strcmp(argv[i], "-d") == 0)
+ {
+ const char *field = argv[i + 1];
+ const int width = 8;
+ const int decimals = 0;
+ if (DBFAddField(hDBF, field, FTDate, width, decimals) == -1)
+ {
+ printf("DBFAddField(%s,FTDate,%d,0) failed.\n", field, width);
+ DBFClose(hDBF);
+ return 4;
+ }
+ i += 1;
+ }
+ else if (i < argc - 1 && strcmp(argv[i], "-l") == 0)
+ {
+ const char *field = argv[i + 1];
+ const int width = 1;
+ const int decimals = 0;
+ if (DBFAddField(hDBF, field, FTLogical, width, decimals) == -1)
+ {
+ printf("DBFAddField(%s,FTLogical,%d,0) failed.\n", field,
+ width);
+ DBFClose(hDBF);
+ return 4;
+ }
+ i += 1;
+ }
else
{
printf("Argument incomplete, or unrecognised: %s\n", argv[i]);
=====================================
dbfdump.c
=====================================
@@ -59,7 +59,7 @@ int main(int argc, char **argv)
DBFHandle hDBF = DBFOpen(pszFilename, "rb");
if (hDBF == NULL)
{
- printf("DBFOpen(%s,\"r\") failed.\n", argv[1]);
+ printf("DBFOpen(%s,\"r\") failed.\n", pszFilename);
exit(2);
}
=====================================
dbfopen.c
=====================================
@@ -13,6 +13,8 @@
#include "shapefil_private.h"
+#include <assert.h>
+#include <errno.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
@@ -24,6 +26,7 @@
#include "cpl_string.h"
#else
+#ifndef STRCASECMP
#if defined(_MSC_VER)
#define STRCASECMP(a, b) (_stricmp(a, b))
#elif defined(_WIN32)
@@ -32,6 +35,7 @@
#include <strings.h>
#define STRCASECMP(a, b) (strcasecmp(a, b))
#endif
+#endif
#if defined(_MSC_VER)
#if _MSC_VER < 1900
@@ -353,10 +357,19 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
/* -------------------------------------------------------------------- */
const int nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+ if (!pszFullname)
+ {
+ return SHPLIB_NULLPTR;
+ }
memcpy(pszFullname, pszFilename, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5);
DBFHandle psDBF = STATIC_CAST(DBFHandle, calloc(1, sizeof(DBFInfo)));
+ if (!psDBF)
+ {
+ free(pszFullname);
+ return SHPLIB_NULLPTR;
+ }
psDBF->fp = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData);
memcpy(&(psDBF->sHooks), psHooks, sizeof(SAHooks));
@@ -394,6 +407,14 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
/* -------------------------------------------------------------------- */
const int nBufSize = 500;
unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(nBufSize));
+ if (!pabyBuf)
+ {
+ psDBF->sHooks.FClose(psDBF->fp);
+ if (pfCPG)
+ psHooks->FClose(pfCPG);
+ free(psDBF);
+ return SHPLIB_NULLPTR;
+ }
if (psDBF->sHooks.FRead(pabyBuf, XBASE_FILEHDR_SZ, 1, psDBF->fp) != 1)
{
psDBF->sHooks.FClose(psDBF->fp);
@@ -427,8 +448,17 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
const int nFields = (nHeadLen - XBASE_FILEHDR_SZ) / XBASE_FLDHDR_SZ;
psDBF->nFields = nFields;
- /* coverity[tainted_data] */
+ assert(psDBF->nRecordLength < 65536);
psDBF->pszCurrentRecord = STATIC_CAST(char *, malloc(psDBF->nRecordLength));
+ if (!psDBF->pszCurrentRecord)
+ {
+ psDBF->sHooks.FClose(psDBF->fp);
+ if (pfCPG)
+ psDBF->sHooks.FClose(pfCPG);
+ free(pabyBuf);
+ free(psDBF);
+ return SHPLIB_NULLPTR;
+ }
/* -------------------------------------------------------------------- */
/* Figure out the code page from the LDID and CPG */
@@ -443,7 +473,8 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
{
pabyBuf[n] = '\0';
psDBF->pszCodePage = STATIC_CAST(char *, malloc(n + 1));
- memcpy(psDBF->pszCodePage, pabyBuf, n + 1);
+ if (psDBF->pszCodePage)
+ memcpy(psDBF->pszCodePage, pabyBuf, n + 1);
}
psDBF->sHooks.FClose(pfCPG);
}
@@ -453,13 +484,28 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
psDBF->iLanguageDriver);
psDBF->pszCodePage = STATIC_CAST(
char *, malloc(strlen(REINTERPRET_CAST(char *, pabyBuf)) + 1));
- strcpy(psDBF->pszCodePage, REINTERPRET_CAST(char *, pabyBuf));
+ if (psDBF->pszCodePage)
+ strcpy(psDBF->pszCodePage, REINTERPRET_CAST(char *, pabyBuf));
}
/* -------------------------------------------------------------------- */
/* Read in Field Definitions */
/* -------------------------------------------------------------------- */
- pabyBuf = STATIC_CAST(unsigned char *, realloc(pabyBuf, nHeadLen));
+
+ // To please Coverity Scan
+ assert(nHeadLen < 65536);
+ unsigned char *pabyBufNew =
+ STATIC_CAST(unsigned char *, realloc(pabyBuf, nHeadLen));
+ if (!pabyBufNew)
+ {
+ psDBF->sHooks.FClose(psDBF->fp);
+ free(pabyBuf);
+ free(psDBF->pszCurrentRecord);
+ free(psDBF->pszCodePage);
+ free(psDBF);
+ return SHPLIB_NULLPTR;
+ }
+ pabyBuf = pabyBufNew;
psDBF->pszHeader = REINTERPRET_CAST(char *, pabyBuf);
psDBF->sHooks.FSeek(psDBF->fp, XBASE_FILEHDR_SZ, 0);
@@ -478,6 +524,12 @@ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
psDBF->panFieldSize = STATIC_CAST(int *, malloc(sizeof(int) * nFields));
psDBF->panFieldDecimals = STATIC_CAST(int *, malloc(sizeof(int) * nFields));
psDBF->pachFieldType = STATIC_CAST(char *, malloc(sizeof(char) * nFields));
+ if (!psDBF->panFieldOffset || !psDBF->panFieldSize ||
+ !psDBF->panFieldDecimals || !psDBF->pachFieldType)
+ {
+ DBFClose(psDBF);
+ return SHPLIB_NULLPTR;
+ }
for (int iField = 0; iField < nFields; iField++)
{
@@ -625,6 +677,8 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
/* -------------------------------------------------------------------- */
const int nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+ if (!pszFullname)
+ return SHPLIB_NULLPTR;
memcpy(pszFullname, pszFilename, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5);
@@ -634,6 +688,16 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
SAFile fp = psHooks->FOpen(pszFullname, "wb+", psHooks->pvUserData);
if (fp == SHPLIB_NULLPTR)
{
+ const size_t nMessageLen = strlen(pszFullname) + 256;
+ char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
+ if (pszMessage)
+ {
+ snprintf(pszMessage, nMessageLen, "Failed to create file %s: %s",
+ pszFullname, strerror(errno));
+ psHooks->Error(pszMessage);
+ free(pszMessage);
+ }
+
free(pszFullname);
return SHPLIB_NULLPTR;
}
@@ -670,6 +734,10 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
/* Create the info structure. */
/* -------------------------------------------------------------------- */
DBFHandle psDBF = STATIC_CAST(DBFHandle, calloc(1, sizeof(DBFInfo)));
+ if (!psDBF)
+ {
+ return SHPLIB_NULLPTR;
+ }
memcpy(&(psDBF->sHooks), psHooks, sizeof(SAHooks));
psDBF->fp = fp;
@@ -697,7 +765,8 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
{
psDBF->pszCodePage =
STATIC_CAST(char *, malloc(strlen(pszCodePage) + 1));
- strcpy(psDBF->pszCodePage, pszCodePage);
+ if (psDBF->pszCodePage)
+ strcpy(psDBF->pszCodePage, pszCodePage);
}
DBFSetLastModifiedDate(psDBF, 95, 7, 26); /* dummy date */
@@ -804,19 +873,67 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
/* realloc all the arrays larger to hold the additional field */
/* information. */
/* -------------------------------------------------------------------- */
- psDBF->nFields++;
- psDBF->panFieldOffset = STATIC_CAST(
- int *, realloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields));
+ int *panFieldOffsetNew =
+ STATIC_CAST(int *, realloc(psDBF->panFieldOffset,
+ sizeof(int) * (psDBF->nFields + 1)));
- psDBF->panFieldSize = STATIC_CAST(
- int *, realloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields));
+ int *panFieldSizeNew =
+ STATIC_CAST(int *, realloc(psDBF->panFieldSize,
+ sizeof(int) * (psDBF->nFields + 1)));
- psDBF->panFieldDecimals = STATIC_CAST(
- int *, realloc(psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields));
+ int *panFieldDecimalsNew =
+ STATIC_CAST(int *, realloc(psDBF->panFieldDecimals,
+ sizeof(int) * (psDBF->nFields + 1)));
- psDBF->pachFieldType = STATIC_CAST(
- char *, realloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields));
+ char *pachFieldTypeNew =
+ STATIC_CAST(char *, realloc(psDBF->pachFieldType,
+ sizeof(char) * (psDBF->nFields + 1)));
+
+ char *pszHeaderNew =
+ STATIC_CAST(char *, realloc(psDBF->pszHeader,
+ (psDBF->nFields + 1) * XBASE_FLDHDR_SZ));
+
+ /* -------------------------------------------------------------------- */
+ /* Make the current record buffer appropriately larger. */
+ /* -------------------------------------------------------------------- */
+ char *pszCurrentRecordNew =
+ STATIC_CAST(char *, realloc(psDBF->pszCurrentRecord,
+ psDBF->nRecordLength + nWidth));
+
+ if (panFieldOffsetNew)
+ psDBF->panFieldOffset = panFieldOffsetNew;
+ if (panFieldSizeNew)
+ psDBF->panFieldSize = panFieldSizeNew;
+ if (panFieldDecimalsNew)
+ psDBF->panFieldDecimals = panFieldDecimalsNew;
+ if (pachFieldTypeNew)
+ psDBF->pachFieldType = pachFieldTypeNew;
+ if (pszHeaderNew)
+ psDBF->pszHeader = pszHeaderNew;
+ if (pszCurrentRecordNew)
+ psDBF->pszCurrentRecord = pszCurrentRecordNew;
+
+ if (!panFieldOffsetNew || !panFieldSizeNew || !panFieldDecimalsNew ||
+ !pachFieldTypeNew || !pszHeaderNew || !pszCurrentRecordNew)
+ {
+ psDBF->sHooks.Error("Out of memory");
+ return -1;
+ }
+
+ /* alloc record */
+ char *pszRecord = SHPLIB_NULLPTR;
+ if (!psDBF->bNoHeader)
+ {
+ pszRecord = STATIC_CAST(char *, malloc(psDBF->nRecordLength + nWidth));
+ if (!pszRecord)
+ {
+ psDBF->sHooks.Error("Out of memory");
+ return -1;
+ }
+ }
+
+ psDBF->nFields++;
/* -------------------------------------------------------------------- */
/* Assign the new field information fields. */
@@ -833,9 +950,6 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
psDBF->nHeaderLength += XBASE_FLDHDR_SZ;
psDBF->bUpdated = FALSE;
- psDBF->pszHeader = STATIC_CAST(
- char *, realloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ));
-
char *pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields - 1);
for (int i = 0; i < XBASE_FLDHDR_SZ; i++)
@@ -856,12 +970,6 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
}
- /* -------------------------------------------------------------------- */
- /* Make the current record buffer appropriately larger. */
- /* -------------------------------------------------------------------- */
- psDBF->pszCurrentRecord = STATIC_CAST(
- char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));
-
/* we're done if dealing with new .dbf */
if (psDBF->bNoHeader)
return (psDBF->nFields - 1);
@@ -870,10 +978,6 @@ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
/* For existing .dbf file, shift records */
/* -------------------------------------------------------------------- */
- /* alloc record */
- char *pszRecord =
- STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
-
const char chFieldFill = DBFGetNullCharacter(chType);
SAOffset nRecordOffset;
@@ -1346,14 +1450,14 @@ static bool DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
char szFormat[20];
snprintf(szFormat, sizeof(szFormat), "%%%d.%df", nWidth,
psDBF->panFieldDecimals[iField]);
- CPLsnprintf(szSField, sizeof(szSField), szFormat,
- *STATIC_CAST(double *, pValue));
+ const double value = *STATIC_CAST(double *, pValue);
+ CPLsnprintf(szSField, sizeof(szSField), szFormat, value);
szSField[sizeof(szSField) - 1] = '\0';
if (STATIC_CAST(int, strlen(szSField)) >
psDBF->panFieldSize[iField])
{
szSField[psDBF->panFieldSize[iField]] = '\0';
- nRetResult = false;
+ nRetResult = psDBF->sHooks.Atof(szSField) == value;
}
memcpy(REINTERPRET_CAST(char *,
pabyRec + psDBF->panFieldOffset[iField]),
@@ -1781,11 +1885,7 @@ int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape,
/* -------------------------------------------------------------------- */
/* Assign value, marking record as dirty if it changes. */
/* -------------------------------------------------------------------- */
- char chNewFlag;
- if (bIsDeleted)
- chNewFlag = '*';
- else
- chNewFlag = ' ';
+ const char chNewFlag = bIsDeleted ? '*' : ' ';
if (psDBF->pszCurrentRecord[0] != chNewFlag)
{
@@ -1963,6 +2063,31 @@ int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap)
STATIC_CAST(char *, calloc(psDBF->nFields, sizeof(char)));
char *pszHeaderNew = STATIC_CAST(
char *, malloc(sizeof(char) * XBASE_FLDHDR_SZ * psDBF->nFields));
+ char *pszRecord = SHPLIB_NULLPTR;
+ char *pszRecordNew = SHPLIB_NULLPTR;
+ if (!(psDBF->bNoHeader && psDBF->nRecords == 0))
+ {
+ /* alloc record */
+ pszRecord =
+ STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+ pszRecordNew =
+ STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+ }
+ if (!panFieldOffsetNew || !panFieldSizeNew || !panFieldDecimalsNew ||
+ !pachFieldTypeNew || !pszHeaderNew ||
+ (!(psDBF->bNoHeader && psDBF->nRecords == 0) &&
+ (!pszRecord || !pszRecordNew)))
+ {
+ free(panFieldOffsetNew);
+ free(panFieldSizeNew);
+ free(panFieldDecimalsNew);
+ free(pachFieldTypeNew);
+ free(pszHeaderNew);
+ free(pszRecord);
+ free(pszRecordNew);
+ psDBF->sHooks.Error("Out of memory");
+ return FALSE;
+ }
/* shuffle fields definitions */
for (int i = 0; i < psDBF->nFields; i++)
@@ -1992,12 +2117,6 @@ int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap)
psDBF->bNoHeader = TRUE;
DBFUpdateHeader(psDBF);
- /* alloc record */
- char *pszRecord =
- STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
- char *pszRecordNew =
- STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
-
/* shuffle fields in records */
for (int iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
{
@@ -2028,12 +2147,12 @@ int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap)
psDBF->sHooks.FWrite(pszRecordNew, psDBF->nRecordLength, 1,
psDBF->fp);
}
-
- /* free record */
- free(pszRecord);
- free(pszRecordNew);
}
+ /* free record */
+ free(pszRecord);
+ free(pszRecordNew);
+
if (errorAbort)
{
free(panFieldOffsetNew);
@@ -2096,6 +2215,31 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
if (nWidth > XBASE_FLD_MAX_WIDTH)
nWidth = XBASE_FLD_MAX_WIDTH;
+ char *pszRecord = STATIC_CAST(
+ char *, malloc(nOldRecordLength +
+ ((nWidth > nOldWidth) ? nWidth - nOldWidth : 0)));
+ char *pszOldField = STATIC_CAST(char *, malloc(nOldWidth + 1));
+ if (!pszRecord || !pszOldField)
+ {
+ free(pszRecord);
+ free(pszOldField);
+ return FALSE;
+ }
+
+ if (nWidth != nOldWidth)
+ {
+ char *pszCurrentRecordNew = STATIC_CAST(
+ char *, realloc(psDBF->pszCurrentRecord,
+ psDBF->nRecordLength + nWidth - nOldWidth));
+ if (!pszCurrentRecordNew)
+ {
+ free(pszRecord);
+ free(pszOldField);
+ return FALSE;
+ }
+ psDBF->pszCurrentRecord = pszCurrentRecordNew;
+ }
+
/* -------------------------------------------------------------------- */
/* Assign the new field information fields. */
/* -------------------------------------------------------------------- */
@@ -2134,14 +2278,15 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
for (int i = iField + 1; i < psDBF->nFields; i++)
psDBF->panFieldOffset[i] += nWidth - nOldWidth;
psDBF->nRecordLength += nWidth - nOldWidth;
-
- psDBF->pszCurrentRecord = STATIC_CAST(
- char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));
}
/* we're done if we're dealing with not yet created .dbf */
if (psDBF->bNoHeader && psDBF->nRecords == 0)
+ {
+ free(pszRecord);
+ free(pszOldField);
return TRUE;
+ }
/* force update of header with new header and record length */
psDBF->bNoHeader = TRUE;
@@ -2151,11 +2296,6 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
{
- char *pszRecord =
- STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
- char *pszOldField =
- STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
-
pszOldField[nOldWidth] = 0;
/* move records to their new positions */
@@ -2223,17 +2363,9 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
}
/* TODO: truncate file */
-
- free(pszRecord);
- free(pszOldField);
}
else if (nWidth > nOldWidth)
{
- char *pszRecord =
- STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
- char *pszOldField =
- STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
-
pszOldField[nOldWidth] = 0;
/* move records to their new positions */
@@ -2296,7 +2428,7 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
if (!errorAbort && psDBF->bWriteEndOfFileChar)
{
- char ch = END_OF_FILE_CHARACTER;
+ const char ch = END_OF_FILE_CHARACTER;
SAOffset nRecordOffset =
psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nRecords) +
@@ -2305,11 +2437,11 @@ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
}
-
- free(pszRecord);
- free(pszOldField);
}
+ free(pszRecord);
+ free(pszOldField);
+
if (errorAbort)
{
psDBF->nCurrentRecord = -1;
=====================================
safileio.c
=====================================
@@ -13,7 +13,7 @@
*
*/
-#include "shapefil.h"
+#include "shapefil_private.h"
#include <assert.h>
#include <math.h>
@@ -101,7 +101,7 @@ void SASetupDefaultHooks(SAHooks *psHooks)
psHooks->Error = SADError;
psHooks->Atof = atof;
- psHooks->pvUserData = NULL;
+ psHooks->pvUserData = SHPLIB_NULLPTR;
}
#ifdef SHPAPI_WINDOWS
@@ -182,5 +182,6 @@ void SASetupUtf8Hooks(SAHooks *psHooks)
psHooks->Error = SADError;
psHooks->Atof = atof;
+ psHooks->pvUserData = SHPLIB_NULLPTR;
}
#endif
=====================================
sbnsearch.c
=====================================
@@ -38,6 +38,7 @@
((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3]))
typedef int coord;
+
/*typedef unsigned char coord;*/
typedef struct
@@ -127,6 +128,8 @@ SBNSearchHandle SBNOpenDiskTree(const char *pszSBNFilename,
/* -------------------------------------------------------------------- */
SBNSearchHandle hSBN =
STATIC_CAST(SBNSearchHandle, calloc(1, sizeof(struct SBNSearchInfo)));
+ if (!hSBN)
+ return SHPLIB_NULLPTR;
if (psHooks == SHPLIB_NULLPTR)
SASetupDefaultHooks(&(hSBN->sHooks));
=====================================
shapefil.h
=====================================
@@ -33,7 +33,7 @@ extern "C"
#define SHAPELIB_VERSION_MAJOR 1
#define SHAPELIB_VERSION_MINOR 6
-#define SHAPELIB_VERSION_MICRO 1
+#define SHAPELIB_VERSION_MICRO 2
#define SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro) \
((major) * 10000 + (minor) * 100 + (micro))
@@ -419,7 +419,7 @@ extern "C"
/************************************************************************/
/* DBF Support. */
/************************************************************************/
- typedef struct
+ typedef struct DBFInfo
{
SAHooks sHooks;
@@ -467,7 +467,7 @@ extern "C"
int bRequireNextWriteSeek;
} DBFInfo;
- typedef DBFInfo *DBFHandle;
+ typedef struct DBFInfo *DBFHandle;
typedef enum
{
=====================================
shpopen.c
=====================================
@@ -183,7 +183,7 @@ void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP)
STATIC_CAST(uint32_t *, malloc(sizeof(uint32_t) * 2 * psSHP->nRecords));
if (panSHX == SHPLIB_NULLPTR)
{
- psSHP->sHooks.Error("Failure allocatin panSHX");
+ psSHP->sHooks.Error("Failure allocating panSHX");
return;
}
@@ -280,6 +280,8 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
/* Initialize the info structure. */
/* -------------------------------------------------------------------- */
SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1, sizeof(SHPInfo)));
+ if (!psSHP)
+ return SHPLIB_NULLPTR;
psSHP->bUpdated = FALSE;
memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));
@@ -290,6 +292,11 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
/* -------------------------------------------------------------------- */
const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+ if (!pszFullname)
+ {
+ free(psSHP);
+ return SHPLIB_NULLPTR;
+ }
memcpy(pszFullname, pszLayer, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
psSHP->fpSHP =
@@ -305,12 +312,15 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
{
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 in %s mode.", pszFullname,
- pszFullname, pszAccess);
- psHooks->Error(pszMessage);
- free(pszMessage);
+ if (pszMessage)
+ {
+ pszFullname[nLenWithoutExtension] = 0;
+ snprintf(pszMessage, nMessageLen,
+ "Unable to open %s.shp or %s.SHP in %s mode.", pszFullname,
+ pszFullname, pszAccess);
+ psHooks->Error(pszMessage);
+ free(pszMessage);
+ }
free(psSHP);
free(pszFullname);
@@ -333,13 +343,16 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
const size_t nMessageLen =
64 + strlen(pszFullname) * 2 + strlen(SHP_RESTORE_SHX_HINT_MESSAGE);
char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
- pszFullname[nLenWithoutExtension] = 0;
- snprintf(
- pszMessage, nMessageLen,
- "Unable to open %s.shx or %s.SHX." SHP_RESTORE_SHX_HINT_MESSAGE,
- pszFullname, pszFullname);
- psHooks->Error(pszMessage);
- free(pszMessage);
+ if (pszMessage)
+ {
+ pszFullname[nLenWithoutExtension] = 0;
+ snprintf(
+ pszMessage, nMessageLen,
+ "Unable to open %s.shx or %s.SHX." SHP_RESTORE_SHX_HINT_MESSAGE,
+ pszFullname, pszFullname);
+ psHooks->Error(pszMessage);
+ free(pszMessage);
+ }
psSHP->sHooks.FClose(psSHP->fpSHP);
free(psSHP);
@@ -353,7 +366,7 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
/* Read the file size from the SHP file. */
/* -------------------------------------------------------------------- */
unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(100));
- if (psSHP->sHooks.FRead(pabyBuf, 100, 1, psSHP->fpSHP) != 1)
+ if (!pabyBuf || psSHP->sHooks.FRead(pabyBuf, 100, 1, psSHP->fpSHP) != 1)
{
psSHP->sHooks.Error(".shp file is unreadable, or corrupt.");
psSHP->sHooks.FClose(psSHP->fpSHP);
@@ -661,6 +674,8 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess,
/* -------------------------------------------------------------------- */
const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+ if (!pszFullname)
+ return 0;
memcpy(pszFullname, pszLayer, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
SAFile fpSHP = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData);
@@ -674,12 +689,15 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess,
{
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);
- psHooks->Error(pszMessage);
- free(pszMessage);
+ if (pszMessage)
+ {
+ pszFullname[nLenWithoutExtension] = 0;
+ snprintf(pszMessage, nMessageLen,
+ "Unable to open %s.shp or %s.SHP.", pszFullname,
+ pszFullname);
+ psHooks->Error(pszMessage);
+ free(pszMessage);
+ }
free(pszFullname);
@@ -717,11 +735,14 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess,
{
size_t nMessageLen = strlen(pszFullname) * 2 + 256;
char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
- pszFullname[nLenWithoutExtension] = 0;
- snprintf(pszMessage, nMessageLen,
- "Error opening file %s.shx for writing", pszFullname);
- psHooks->Error(pszMessage);
- free(pszMessage);
+ if (pszMessage)
+ {
+ pszFullname[nLenWithoutExtension] = 0;
+ snprintf(pszMessage, nMessageLen,
+ "Error opening file %s.shx for writing", pszFullname);
+ psHooks->Error(pszMessage);
+ free(pszMessage);
+ }
psHooks->FClose(fpSHP);
@@ -736,6 +757,15 @@ int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess,
/* -------------------------------------------------------------------- */
psHooks->FSeek(fpSHP, 100, 0);
char *pabySHXHeader = STATIC_CAST(char *, malloc(100));
+ if (!pabySHXHeader)
+ {
+ psHooks->FClose(fpSHP);
+
+ free(pabyBuf);
+ free(pszFullname);
+
+ return (0);
+ }
memcpy(pabySHXHeader, pabyBuf, 100);
psHooks->FWrite(pabySHXHeader, 100, 1, fpSHX);
free(pabyBuf);
@@ -978,22 +1008,37 @@ SHPHandle SHPAPI_CALL SHPCreate(const char *pszLayer, int nShapeType)
SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
const SAHooks *psHooks)
{
+
+ SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1, sizeof(SHPInfo)));
+ if (!psSHP)
+ return SHPLIB_NULLPTR;
+
/* -------------------------------------------------------------------- */
/* Open the two files so we can write their headers. */
/* -------------------------------------------------------------------- */
const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+ if (!pszFullname)
+ {
+ free(psSHP);
+ return SHPLIB_NULLPTR;
+ }
memcpy(pszFullname, pszLayer, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
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",
- pszFullname, strerror(errno));
- psHooks->Error(szErrorMsg);
-
+ const size_t nMessageLen = strlen(pszFullname) + 256;
+ char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
+ if (pszMessage)
+ {
+ snprintf(pszMessage, nMessageLen, "Failed to create file %s: %s",
+ pszFullname, strerror(errno));
+ psHooks->Error(pszMessage);
+ free(pszMessage);
+ }
free(pszFullname);
+ free(psSHP);
return SHPLIB_NULLPTR;
}
@@ -1001,13 +1046,19 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
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",
- pszFullname, strerror(errno));
- psHooks->Error(szErrorMsg);
+ const size_t nMessageLen = strlen(pszFullname) + 256;
+ char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
+ if (pszMessage)
+ {
+ snprintf(pszMessage, nMessageLen, "Failed to create file %s: %s",
+ pszFullname, strerror(errno));
+ psHooks->Error(pszMessage);
+ free(pszMessage);
+ }
free(pszFullname);
psHooks->FClose(fpSHP);
+ free(psSHP);
return SHPLIB_NULLPTR;
}
@@ -1062,6 +1113,7 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
free(pszFullname);
psHooks->FClose(fpSHP);
psHooks->FClose(fpSHX);
+ free(psSHP);
return SHPLIB_NULLPTR;
}
@@ -1086,11 +1138,10 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
free(pszFullname);
psHooks->FClose(fpSHP);
psHooks->FClose(fpSHX);
+ free(psSHP);
return SHPLIB_NULLPTR;
}
- SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1, sizeof(SHPInfo)));
-
psSHP->bUpdated = FALSE;
memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));
@@ -1191,6 +1242,8 @@ SHPObject SHPAPI_CALL1(*)
{
SHPObject *psObject =
STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject)));
+ if (!psObject)
+ return SHPLIB_NULLPTR;
psObject->nSHPType = nSHPType;
psObject->nShapeId = nShapeId;
psObject->bMeasureIsUsed = FALSE;
@@ -1235,6 +1288,13 @@ SHPObject SHPAPI_CALL1(*)
STATIC_CAST(int *, calloc(psObject->nParts, sizeof(int)));
psObject->panPartType =
STATIC_CAST(int *, malloc(sizeof(int) * psObject->nParts));
+ if (!psObject->panPartStart || !psObject->panPartType)
+ {
+ free(psObject->panPartStart);
+ free(psObject->panPartType);
+ free(psObject);
+ return SHPLIB_NULLPTR;
+ }
psObject->panPartStart[0] = 0;
psObject->panPartType[0] = SHPP_RING;
@@ -1271,6 +1331,18 @@ SHPObject SHPAPI_CALL1(*)
psObject->padfM = STATIC_CAST(
double *,
padfM &&bHasM ? malloc(nSize) : calloc(nVertices, sizeof(double)));
+ if (!psObject->padfX || !psObject->padfY || !psObject->padfZ ||
+ !psObject->padfM)
+ {
+ free(psObject->panPartStart);
+ free(psObject->panPartType);
+ free(psObject->padfX);
+ free(psObject->padfY);
+ free(psObject->padfZ);
+ free(psObject->padfM);
+ free(psObject);
+ return SHPLIB_NULLPTR;
+ }
if (padfX != SHPLIB_NULLPTR)
memcpy(psObject->padfX, padfX, nSize);
if (padfY != SHPLIB_NULLPTR)
@@ -2123,6 +2195,11 @@ SHPObject SHPAPI_CALL1(*) SHPReadObject(const SHPHandle psSHP, int hEntity)
else
{
psShape = STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject)));
+ if (!psShape)
+ {
+ psSHP->sHooks.Error("Out of memory.");
+ return SHPLIB_NULLPTR;
+ }
}
psShape->nShapeId = hEntity;
psShape->nSHPType = nSHPType;
=====================================
shptree.c
=====================================
@@ -678,6 +678,8 @@ SHPTreeDiskHandle SHPOpenDiskTree(const char *pszQIXFilename,
hDiskTree = STATIC_CAST(SHPTreeDiskHandle,
calloc(1, sizeof(struct SHPDiskTreeInfo)));
+ if (!hDiskTree)
+ return SHPLIB_NULLPTR;
if (psHooks == SHPLIB_NULLPTR)
SASetupDefaultHooks(&(hDiskTree->sHooks));
=====================================
tests/CMakeLists.txt
=====================================
@@ -1,16 +1,31 @@
-# CMake configuration for SHP C++ unit tests
+# CMake configuration for C++ unit tests
project(${CMAKE_PROJECT_NAME}Tests CXX)
-# Set up GoogleTest
+# Set up GoogleTest and Benchmark
include(FetchContent)
+FetchContent_Declare(
+ benchmark
+ GIT_REPOSITORY https://github.com/google/benchmark.git
+ GIT_TAG v1.9.4
+ GIT_SHALLOW TRUE
+)
+
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
- GIT_TAG v1.15.2
+ GIT_TAG v1.17.0
+ GIT_SHALLOW TRUE
)
+set(BENCHMARK_DOWNLOAD_DEPENDENCIES OFF CACHE BOOL "" FORCE)
+set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
+set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
+set(BENCHMARK_INSTALL_DOCS OFF CACHE BOOL "" FORCE)
+
+FetchContent_MakeAvailable(benchmark)
+
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
@@ -22,16 +37,23 @@ set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
-foreach(executable dbf_test sbn_test shp_test)
+set_target_properties(gtest gtest_main benchmark benchmark_main PROPERTIES FOLDER "tests/third-party")
+
+foreach(executable dbf_test sbn_test shp_test shp_bench)
add_executable(${executable} ${PROJECT_SOURCE_DIR}/${executable}.cc)
- target_link_libraries(${executable} PRIVATE ${PACKAGE} gtest)
+ target_link_libraries(${executable} PRIVATE ${PACKAGE} gtest benchmark)
add_test(
NAME ${executable}
COMMAND ${executable}
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
)
target_compile_features(${executable} PUBLIC cxx_std_17)
- set_target_properties(${executable} PROPERTIES FOLDER "tests" CXX_EXTENSIONS OFF)
+ if("${executable}" MATCHES ".*_bench$")
+ set(exec_folder "tests/bench")
+ else()
+ set(exec_folder "tests")
+ endif()
+ set_target_properties(${executable} PROPERTIES FOLDER ${exec_folder} CXX_EXTENSIONS OFF)
if (BUILD_SHARED_LIBS AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.21" AND (WIN32 OR CYGWIN))
add_custom_command(
TARGET ${executable} POST_BUILD
=====================================
tests/dbf_test.cc
=====================================
@@ -309,7 +309,7 @@ TEST(DBFFieldTest, SetAndGetLogicalFalse)
fs::remove(filename);
}
-TEST(DBFFieldTest, SetAndGetLogicalInvalid)
+TEST(DBFFieldTest, SetLogicalInvalid)
{
const auto filename =
fs::temp_directory_path() / GenerateUniqueFilename(".dbf");
@@ -318,6 +318,80 @@ TEST(DBFFieldTest, SetAndGetLogicalInvalid)
fs::remove(filename);
}
+TEST(DBFFieldTest, SetAndGetDouble)
+{
+ const auto filename =
+ fs::temp_directory_path() / GenerateUniqueFilename(".dbf");
+ constexpr const double value = 1623819823.809;
+ {
+ const auto handle = DBFCreate(filename.string().c_str());
+ EXPECT_NE(nullptr, handle);
+ const auto fid = DBFAddField(handle, "double", FTDouble, 14, 4);
+ EXPECT_GE(fid, 0);
+ const auto success = DBFWriteDoubleAttribute(handle, 0, 0, value);
+ EXPECT_TRUE(success);
+ DBFClose(handle);
+ }
+ {
+ const auto handle = DBFOpen(filename.string().c_str(), "r");
+ EXPECT_NE(nullptr, handle);
+ EXPECT_EQ(value, DBFReadDoubleAttribute(handle, 0, 0));
+ DBFClose(handle);
+ }
+ fs::remove(filename);
+}
+
+static auto WriteDuplicateFields(const fs::path &filename) -> auto
+{
+ const auto handle = DBFCreate(filename.string().c_str());
+ EXPECT_NE(nullptr, handle);
+ const auto fid1 = DBFAddField(handle, "field", FTDate, 8, 0);
+ EXPECT_GE(fid1, 0);
+ const auto fid2 = DBFAddField(handle, "field", FTDate, 8, 0);
+ EXPECT_GE(fid2, 0);
+ const auto fid3 = DBFAddField(handle, "field", FTDouble, 8, 5);
+ EXPECT_GE(fid3, 0);
+ const auto fid4 = DBFAddField(handle, "field", FTDouble, 8, 10);
+ EXPECT_GE(fid4, 0);
+ const auto fid5 = DBFAddField(handle, "field", FTInteger, 8, 0);
+ EXPECT_GE(fid5, 0);
+ const auto fid6 = DBFAddField(handle, "field", FTInteger, 8, 0);
+ EXPECT_GE(fid6, 0);
+ const auto fid7 = DBFAddField(handle, "field", FTLogical, 1, 0);
+ EXPECT_GE(fid7, 0);
+ const auto fid8 = DBFAddField(handle, "field", FTLogical, 1, 0);
+ EXPECT_GE(fid8, 0);
+ const auto fid9 = DBFAddField(handle, "field", FTString, 5, 0);
+ EXPECT_GE(fid9, 0);
+ const auto fid0 = DBFAddField(handle, "field", FTString, 10, 0);
+ EXPECT_GE(fid0, 0);
+ const auto nFields = DBFGetFieldCount(handle);
+ EXPECT_EQ(nFields, 10);
+ DBFClose(handle);
+}
+
+static auto ReadDuplicateFields(const fs::path &filename) -> auto
+{
+ const auto handle = DBFOpen(filename.string().c_str(), "r");
+ EXPECT_NE(nullptr, handle);
+ const auto nFields = DBFGetFieldCount(handle);
+ EXPECT_EQ(nFields, 10);
+ const auto fid = DBFGetFieldIndex(handle, "field");
+ EXPECT_EQ(fid, 0);
+ DBFClose(handle);
+}
+
+TEST(DBFFieldTest, AddDuplicateField)
+{
+ const auto filename =
+ fs::temp_directory_path() / GenerateUniqueFilename(".dbf");
+ WriteDuplicateFields(filename);
+ const auto size = fs::file_size(filename);
+ EXPECT_EQ(354, size);
+ ReadDuplicateFields(filename);
+ fs::remove(filename);
+}
+
} // namespace
int main(int argc, char **argv)
=====================================
tests/expect3.out
=====================================
@@ -31,7 +31,7 @@ Shape:2 (Polygon) nVertices=4, nParts=1
(160,150, 0)
(180,170, 0)
(150,150, 0)
-Descriptio TestInt TestDouble
-Square with triangle missing 1 2.50000
-Smaller triangle 100 1000.25000
-(NULL) (NULL) (NULL)
+Descriptio TestInt TestDouble TestDate TestBool
+Square with triangle missing 1 2.50000 20241102 T
+Smaller triangle 100 1000.25000 20241102 F
+(NULL) (NULL) (NULL) (NULL) (NULL)
=====================================
tests/shp_bench.cc
=====================================
@@ -0,0 +1,46 @@
+#include <array>
+#include <filesystem>
+
+#include <benchmark/benchmark.h>
+#include "shapefil.h"
+
+namespace fs = std::filesystem;
+namespace bm = benchmark;
+
+namespace
+{
+
+static const auto kTestData = fs::path{"shape_eg_data"};
+
+constexpr static auto filenames = std::array<const char *, 11>{
+ "3dpoints.shp", "anno.shp", "brklinz.shp", "CoHI_GCS12.shp",
+ "csah.shp", "masspntz.shp", "mpatch3.shp", "multipatch.shp",
+ "multipnt.shp", "pline.shp", "polygon.shp"};
+
+static void Benchmark_ReadAll(bm::State &state)
+{
+ const auto filename = kTestData / filenames[state.range(1)];
+ const auto handle = SHPOpen(filename.string().c_str(), "rb");
+ SHPSetFastModeReadObject(handle, static_cast<int>(state.range(0)));
+ int nEntities;
+ SHPGetInfo(handle, &nEntities, nullptr, nullptr, nullptr);
+ for (auto _ : state)
+ {
+ for (int i = 0; i < nEntities; ++i)
+ {
+ auto obj = SHPReadObject(handle, i);
+ SHPDestroyObject(obj);
+ }
+ }
+ state.SetItemsProcessed(state.iterations() * nEntities);
+ SHPClose(handle);
+}
+
+BENCHMARK(Benchmark_ReadAll)
+ ->ArgsProduct({{0, 1}, bm::CreateDenseRange(0, filenames.size() - 1, 1)})
+ ->ArgNames({"fastMode", "fileId"})
+ ->Unit(bm::kMicrosecond);
+
+} // namespace
+
+BENCHMARK_MAIN();
=====================================
tests/test3.sh
=====================================
@@ -12,16 +12,16 @@ readonly EXPECT="${1:-$SCRIPTDIR/expect3.out}"
{
"${SHPCREATE:-./shpcreate}" test polygon
-"${DBFCREATE:-./dbfcreate}" test.dbf -s Description 30 -n TestInt 6 0 -n TestDouble 16 5
+"${DBFCREATE:-./dbfcreate}" test.dbf -s Description 30 -n TestInt 6 0 -n TestDouble 16 5 -d TestDate -l TestBool
"${SHPADD:-./shpadd}" test 0 0 100 0 100 100 0 100 0 0 + 20 20 20 30 30 30 20 20
-"${DBFADD:-./dbfadd}" test.dbf "Square with triangle missing" 1.4 2.5
+"${DBFADD:-./dbfadd}" test.dbf "Square with triangle missing" 1.4 2.5 20241102 T
"${SHPADD:-./shpadd}" test 150 150 160 150 180 170 150 150
-"${DBFADD:-./dbfadd}" test.dbf "Smaller triangle" 100 1000.25
+"${DBFADD:-./dbfadd}" test.dbf "Smaller triangle" 100 1000.25 20241102 F
"${SHPADD:-./shpadd}" test 150 150 160 150 180 170 150 150
-"${DBFADD:-./dbfadd}" test.dbf "" "" ""
+"${DBFADD:-./dbfadd}" test.dbf "" "" "" "" ""
"${SHPDUMP:-./shpdump}" test.shp
"${DBFDUMP:-./dbfdump}" test.dbf
=====================================
web/release.html
=====================================
@@ -10,6 +10,19 @@
To get notification of new releases of Shapelib <i>subscribe</i> to
the project mailing list at https://lists.osgeo.org/pipermail/shapelib/.<p>
+<b>Release 1.6.2</b>:
+<ul>
+<li>Nullify userdata also in SASetupUtf8Hooks</li>
+<li>Test suite enhancements</li>
+<li>CMake: no longer use CTest and add manual BUILD_TESTING option instead (default to OFF)</li>
+<li>Prefer tagged version of Google Benchmark</li>
+<li>dbfcreate: allow creation of Date and Logical fields #167 (#168)</li>
+<li>Fix cppcheck nullPointerOutOfMemory warnings</li>
+<li>DBFWriteAttribute(): return true when no precision loss occured when writing a double</li>
+<li>SHPCreateLL()/DBFCreate(): make error message contains full filename (in case it is very long)</li>
+</ul>
+
+
<b>Release 1.6.1</b>:
<ul>
<li>DBFIsValueNULL(): accept empty string as NULL Date (https://github.com/OSGeo/gdal/issues/10405)</li>
View it on GitLab: https://salsa.debian.org/debian-gis-team/shapelib/-/commit/789bb79c5a275653c5b516f82c97b8ea718a4c09
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/shapelib/-/commit/789bb79c5a275653c5b516f82c97b8ea718a4c09
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20250923/b72d3bfd/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list