summaryrefslogtreecommitdiff
path: root/navit/map
diff options
context:
space:
mode:
authorwoglinde <woglinde@ffa7fe5e-494d-0410-b361-a75ebd5db220>2011-07-05 20:06:29 +0000
committerwoglinde <woglinde@ffa7fe5e-494d-0410-b361-a75ebd5db220>2011-07-05 20:06:29 +0000
commit0121e6fecb7dd3d2257ded6f990089e93ba1dd3e (patch)
tree52316b5b7e1c531007ce2fda0bb1c6a225f66795 /navit/map
parent1ad9ff01b942c15ea1575dd9e059c3d58681643e (diff)
downloadnavit-0121e6fecb7dd3d2257ded6f990089e93ba1dd3e.tar.gz
Fix:map_shapefile:Split out shapelib, make prober library check, cp15 said to take care about cmake disable it for now
git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit@4586 ffa7fe5e-494d-0410-b361-a75ebd5db220
Diffstat (limited to 'navit/map')
-rw-r--r--navit/map/shapefile/Makefile.am9
-rw-r--r--navit/map/shapefile/dbfopen.c1869
-rw-r--r--navit/map/shapefile/shapefil.h609
-rw-r--r--navit/map/shapefile/shpopen.c2283
-rw-r--r--navit/map/shapefile/shptree.c1050
5 files changed, 5 insertions, 5815 deletions
diff --git a/navit/map/shapefile/Makefile.am b/navit/map/shapefile/Makefile.am
index 35e420e84..ba6e22886 100644
--- a/navit/map/shapefile/Makefile.am
+++ b/navit/map/shapefile/Makefile.am
@@ -5,10 +5,11 @@ if PLUGINS
else
noinst_LTLIBRARIES = libmap_shapefile.la
endif
-if HAVE_SYSTEM_SHAPEFILELIB
libmap_shapefile_la_SOURCES = shapefile.c
-libmap_shapefile_la_LDFLAGS = -module -avoid-version @NAVIT_MODULE_LDFLAGS@ @SHAPEFILE_LIBS@
-else
-libmap_shapefile_la_SOURCES = shapefile.c dbfopen.c shpopen.c shptree.c shapefil.h
libmap_shapefile_la_LDFLAGS = -module -avoid-version @NAVIT_MODULE_LDFLAGS@
+if HAVE_SYSTEM_SHAPEFILELIB
+libmap_shapefile_la_LDFLAGS += @SHAPEFILE_LIBS@
+else
+AM_CPPFLAGS += -I$(top_srcdir)/navit/support/shapefile
+libmap_shapefile_la_LDFLAGS += $(top_srcdir)/navit/support/shapefile/libsupport_shapefile.la
endif
diff --git a/navit/map/shapefile/dbfopen.c b/navit/map/shapefile/dbfopen.c
deleted file mode 100644
index 51944fc53..000000000
--- a/navit/map/shapefile/dbfopen.c
+++ /dev/null
@@ -1,1869 +0,0 @@
-/******************************************************************************
- * $Id: dbfopen.c,v 1.83 2008/11/12 14:28:15 fwarmerdam Exp $
- *
- * Project: Shapelib
- * Purpose: Implementation of .dbf access API documented in dbf_api.html.
- * Author: Frank Warmerdam, warmerdam@pobox.com
- *
- ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
- *
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL). 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.
- ******************************************************************************
- *
- * $Log: dbfopen.c,v $
- * Revision 1.83 2008/11/12 14:28:15 fwarmerdam
- * DBFCreateField() now works on files with records
- *
- * Revision 1.82 2008/11/11 17:47:09 fwarmerdam
- * added DBFDeleteField() function
- *
- * Revision 1.81 2008/01/03 17:48:13 bram
- * in DBFCreate, use default code page LDID/87 (= 0x57, ANSI)
- * instead of LDID/3. This seems to be the same as what ESRI
- * would be doing by default.
- *
- * Revision 1.80 2007/12/30 14:36:39 fwarmerdam
- * avoid syntax issue with last comment.
- *
- * Revision 1.79 2007/12/30 14:35:48 fwarmerdam
- * Avoid char* / unsigned char* warnings.
- *
- * Revision 1.78 2007/12/18 18:28:07 bram
- * - create hook for client specific atof (bugzilla ticket 1615)
- * - check for NULL handle before closing cpCPG file, and close after reading.
- *
- * Revision 1.77 2007/12/15 20:25:21 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/<number>") or as the
- * content of an accompanying .CPG file. When creating a DBF file, the code can
- * be set using DBFCreateEx.
- *
- * Revision 1.76 2007/12/12 22:21:32 bram
- * DBFClose: check for NULL psDBF handle before trying to close it.
- *
- * Revision 1.75 2007/12/06 13:58:19 fwarmerdam
- * make sure file offset calculations are done in as SAOffset
- *
- * Revision 1.74 2007/12/06 07:00:25 fwarmerdam
- * dbfopen now using SAHooks for fileio
- *
- * Revision 1.73 2007/09/03 19:48:11 fwarmerdam
- * move DBFReadAttribute() static dDoubleField into dbfinfo
- *
- * Revision 1.72 2007/09/03 19:34:06 fwarmerdam
- * Avoid use of static tuple buffer in DBFReadTuple()
- *
- * Revision 1.71 2006/06/22 14:37:18 fwarmerdam
- * avoid memory leak if dbfopen fread fails
- *
- * Revision 1.70 2006/06/17 17:47:05 fwarmerdam
- * use calloc() for dbfinfo in DBFCreate
- *
- * Revision 1.69 2006/06/17 15:34:32 fwarmerdam
- * disallow creating fields wider than 255
- *
- * Revision 1.68 2006/06/17 15:12:40 fwarmerdam
- * Fixed C++ style comments.
- *
- * Revision 1.67 2006/06/17 00:24:53 fwarmerdam
- * Don't treat non-zero decimals values as high order byte for length
- * for strings. It causes serious corruption for some files.
- * http://bugzilla.remotesensing.org/show_bug.cgi?id=1202
- *
- * Revision 1.66 2006/03/29 18:26:20 fwarmerdam
- * fixed bug with size of pachfieldtype in dbfcloneempty
- *
- * Revision 1.65 2006/02/15 01:14:30 fwarmerdam
- * added DBFAddNativeFieldType
- *
- * Revision 1.64 2006/02/09 00:29:04 fwarmerdam
- * Changed to put spaces into string fields that are NULL as
- * per http://bugzilla.maptools.org/show_bug.cgi?id=316.
- *
- * Revision 1.63 2006/01/25 15:35:43 fwarmerdam
- * check success on DBFFlushRecord
- *
- * Revision 1.62 2006/01/10 16:28:03 fwarmerdam
- * Fixed typo in CPLError.
- *
- * Revision 1.61 2006/01/10 16:26:29 fwarmerdam
- * Push loading record buffer into DBFLoadRecord.
- * Implement CPL error reporting if USE_CPL defined.
- *
- * Revision 1.60 2006/01/05 01:27:27 fwarmerdam
- * added dbf deletion mark/fetch
- *
- * Revision 1.59 2005/03/14 15:20:28 fwarmerdam
- * Fixed last change.
- *
- * Revision 1.58 2005/03/14 15:18:54 fwarmerdam
- * Treat very wide fields with no decimals as double. This is
- * more than 32bit integer fields.
- *
- * Revision 1.57 2005/02/10 20:16:54 fwarmerdam
- * Make the pszStringField buffer for DBFReadAttribute() static char [256]
- * as per bug 306.
- *
- * Revision 1.56 2005/02/10 20:07:56 fwarmerdam
- * Fixed bug 305 in DBFCloneEmpty() - header length problem.
- *
- * Revision 1.55 2004/09/26 20:23:46 fwarmerdam
- * avoid warnings with rcsid and signed/unsigned stuff
- *
- * Revision 1.54 2004/09/15 16:26:10 fwarmerdam
- * Treat all blank numeric fields as null too.
- */
-
-#include "shapefil.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-
-#ifndef FALSE
-# define FALSE 0
-# define TRUE 1
-#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 == NULL )
- return( (void *) malloc(nNewSize) );
- else
- return( (void *) realloc(pMem,nNewSize) );
-}
-
-/************************************************************************/
-/* DBFWriteHeader() */
-/* */
-/* This is called to write out the file header, and field */
-/* descriptions before writing any actual data records. This */
-/* also computes all the DBFDataSet field offset/size/decimals */
-/* and so forth values. */
-/************************************************************************/
-
-static void DBFWriteHeader(DBFHandle psDBF)
-
-{
- unsigned char abyHeader[XBASE_FLDHDR_SZ];
- int i;
-
- if( !psDBF->bNoHeader )
- return;
-
- psDBF->bNoHeader = FALSE;
-
-/* -------------------------------------------------------------------- */
-/* Initialize the file header information. */
-/* -------------------------------------------------------------------- */
- for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
- abyHeader[i] = 0;
-
- abyHeader[0] = 0x03; /* memo field? - just copying */
-
- /* write out a dummy date */
- abyHeader[1] = 95; /* YY */
- abyHeader[2] = 7; /* MM */
- abyHeader[3] = 26; /* DD */
-
- /* record count preset at zero */
-
- abyHeader[8] = (unsigned char) (psDBF->nHeaderLength % 256);
- abyHeader[9] = (unsigned char) (psDBF->nHeaderLength / 256);
-
- abyHeader[10] = (unsigned char) (psDBF->nRecordLength % 256);
- abyHeader[11] = (unsigned char) (psDBF->nRecordLength / 256);
-
- abyHeader[29] = (unsigned char) (psDBF->iLanguageDriver);
-
-/* -------------------------------------------------------------------- */
-/* Write the initial 32 byte file header, and all the field */
-/* descriptions. */
-/* -------------------------------------------------------------------- */
- psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
- psDBF->sHooks.FWrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
- psDBF->sHooks.FWrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields,
- psDBF->fp );
-
-/* -------------------------------------------------------------------- */
-/* Write out the newline character if there is room for it. */
-/* -------------------------------------------------------------------- */
- if( psDBF->nHeaderLength > 32*psDBF->nFields + 32 )
- {
- char cNewline;
-
- cNewline = 0x0d;
- psDBF->sHooks.FWrite( &cNewline, 1, 1, psDBF->fp );
- }
-}
-
-/************************************************************************/
-/* DBFFlushRecord() */
-/* */
-/* Write out the current record if there is one. */
-/************************************************************************/
-
-static int DBFFlushRecord( DBFHandle psDBF )
-
-{
- SAOffset nRecordOffset;
-
- if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
- {
- psDBF->bCurrentRecordModified = FALSE;
-
- nRecordOffset =
- psDBF->nRecordLength * (SAOffset) psDBF->nCurrentRecord
- + psDBF->nHeaderLength;
-
- if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 ) != 0
- || psDBF->sHooks.FWrite( psDBF->pszCurrentRecord,
- psDBF->nRecordLength,
- 1, psDBF->fp ) != 1 )
- {
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_FileIO,
- "Failure writing DBF record %d.",
- psDBF->nCurrentRecord );
-#else
- fprintf( stderr, "Failure writing DBF record %d.",
- psDBF->nCurrentRecord );
-#endif
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-/************************************************************************/
-/* DBFLoadRecord() */
-/************************************************************************/
-
-static int DBFLoadRecord( DBFHandle psDBF, int iRecord )
-
-{
- if( psDBF->nCurrentRecord != iRecord )
- {
- SAOffset nRecordOffset;
-
- if( !DBFFlushRecord( psDBF ) )
- return FALSE;
-
- nRecordOffset =
- psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
-
- if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, SEEK_SET ) != 0 )
- {
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_FileIO,
- "fseek(%ld) failed on DBF file.\n",
- (long) nRecordOffset );
-#else
- fprintf( stderr, "fseek(%ld) failed on DBF file.\n",
- (long) nRecordOffset );
-#endif
- return FALSE;
- }
-
- if( psDBF->sHooks.FRead( psDBF->pszCurrentRecord,
- psDBF->nRecordLength, 1, psDBF->fp ) != 1 )
- {
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_FileIO,
- "fread(%d) failed on DBF file.\n",
- psDBF->nRecordLength );
-#else
- fprintf( stderr, "fread(%d) failed on DBF file.\n",
- psDBF->nRecordLength );
-#endif
- return FALSE;
- }
-
- psDBF->nCurrentRecord = iRecord;
- }
-
- return TRUE;
-}
-
-/************************************************************************/
-/* DBFUpdateHeader() */
-/************************************************************************/
-
-void SHPAPI_CALL
-DBFUpdateHeader( DBFHandle psDBF )
-
-{
- unsigned char abyFileHeader[32];
-
- if( psDBF->bNoHeader )
- DBFWriteHeader( psDBF );
-
- DBFFlushRecord( psDBF );
-
- psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
- psDBF->sHooks.FRead( abyFileHeader, 32, 1, psDBF->fp );
-
- abyFileHeader[4] = (unsigned char) (psDBF->nRecords % 256);
- abyFileHeader[5] = (unsigned char) ((psDBF->nRecords/256) % 256);
- abyFileHeader[6] = (unsigned char) ((psDBF->nRecords/(256*256)) % 256);
- abyFileHeader[7] = (unsigned char) ((psDBF->nRecords/(256*256*256)) % 256);
-
- psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
- psDBF->sHooks.FWrite( abyFileHeader, 32, 1, psDBF->fp );
-
- psDBF->sHooks.FFlush( psDBF->fp );
-}
-
-/************************************************************************/
-/* DBFOpen() */
-/* */
-/* Open a .dbf file. */
-/************************************************************************/
-
-DBFHandle SHPAPI_CALL
-DBFOpen( const char * pszFilename, const char * pszAccess )
-
-{
- SAHooks sHooks;
-
- SASetupDefaultHooks( &sHooks );
-
- return DBFOpenLL( pszFilename, pszAccess, &sHooks );
-}
-
-/************************************************************************/
-/* DBFOpen() */
-/* */
-/* Open a .dbf file. */
-/************************************************************************/
-
-DBFHandle SHPAPI_CALL
-DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
-
-{
- DBFHandle psDBF;
- SAFile pfCPG;
- unsigned char *pabyBuf;
- int nFields, nHeadLen, iField, i;
- char *pszBasename, *pszFullname;
- int nBufSize = 500;
-
-/* -------------------------------------------------------------------- */
-/* We only allow the access strings "rb" and "r+". */
-/* -------------------------------------------------------------------- */
- if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
- && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
- && strcmp(pszAccess,"r+b") != 0 )
- return( NULL );
-
- if( strcmp(pszAccess,"r") == 0 )
- pszAccess = "rb";
-
- if( strcmp(pszAccess,"r+") == 0 )
- pszAccess = "rb+";
-
-/* -------------------------------------------------------------------- */
-/* Compute the base (layer) name. If there is any extension */
-/* on the passed in filename we will strip it off. */
-/* -------------------------------------------------------------------- */
- pszBasename = (char *) malloc(strlen(pszFilename)+5);
- strcpy( pszBasename, pszFilename );
- for( i = strlen(pszBasename)-1;
- i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
- && pszBasename[i] != '\\';
- i-- ) {}
-
- if( pszBasename[i] == '.' )
- pszBasename[i] = '\0';
-
- pszFullname = (char *) malloc(strlen(pszBasename) + 5);
- sprintf( pszFullname, "%s.dbf", pszBasename );
-
- psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
- psDBF->fp = psHooks->FOpen( pszFullname, pszAccess );
- memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
-
- if( psDBF->fp == NULL )
- {
- sprintf( pszFullname, "%s.DBF", pszBasename );
- psDBF->fp = psDBF->sHooks.FOpen(pszFullname, pszAccess );
- }
-
- sprintf( pszFullname, "%s.cpg", pszBasename );
- pfCPG = psHooks->FOpen( pszFullname, "r" );
- if( pfCPG == NULL )
- {
- sprintf( pszFullname, "%s.CPG", pszBasename );
- pfCPG = psHooks->FOpen( pszFullname, "r" );
- }
-
- free( pszBasename );
- free( pszFullname );
-
- if( psDBF->fp == NULL )
- {
- free( psDBF );
- if( pfCPG ) psHooks->FClose( pfCPG );
- return( NULL );
- }
-
- psDBF->bNoHeader = FALSE;
- psDBF->nCurrentRecord = -1;
- psDBF->bCurrentRecordModified = FALSE;
-
-/* -------------------------------------------------------------------- */
-/* Read Table Header info */
-/* -------------------------------------------------------------------- */
- pabyBuf = (unsigned char *) malloc(nBufSize);
- if( psDBF->sHooks.FRead( pabyBuf, 32, 1, psDBF->fp ) != 1 )
- {
- psDBF->sHooks.FClose( psDBF->fp );
- if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
- free( pabyBuf );
- free( psDBF );
- return NULL;
- }
-
- psDBF->nRecords =
- pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;
-
- psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
- psDBF->nRecordLength = pabyBuf[10] + pabyBuf[11]*256;
- psDBF->iLanguageDriver = pabyBuf[29];
-
- psDBF->nFields = nFields = (nHeadLen - 32) / 32;
-
- psDBF->pszCurrentRecord = (char *) malloc(psDBF->nRecordLength);
-
-/* -------------------------------------------------------------------- */
-/* Figure out the code page from the LDID and CPG */
-/* -------------------------------------------------------------------- */
-
- psDBF->pszCodePage = NULL;
- if( pfCPG )
- {
- size_t n;
- char *buffer = (char *) pabyBuf;
- buffer[0] = '\0';
- psDBF->sHooks.FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
- n = strcspn( (char *) pabyBuf, "\n\r" );
- if( n > 0 )
- {
- pabyBuf[n] = '\0';
- psDBF->pszCodePage = (char *) malloc(n + 1);
- memcpy( psDBF->pszCodePage, pabyBuf, n + 1 );
- }
- psDBF->sHooks.FClose( pfCPG );
- }
- if( psDBF->pszCodePage == NULL && pabyBuf[29] != 0 )
- {
- sprintf( (char *) pabyBuf, "LDID/%d", psDBF->iLanguageDriver );
- psDBF->pszCodePage = (char *) malloc(strlen((char*)pabyBuf) + 1);
- strcpy( psDBF->pszCodePage, (char *) pabyBuf );
- }
-
-/* -------------------------------------------------------------------- */
-/* Read in Field Definitions */
-/* -------------------------------------------------------------------- */
-
- pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
- psDBF->pszHeader = (char *) pabyBuf;
-
- psDBF->sHooks.FSeek( psDBF->fp, 32, 0 );
- if( psDBF->sHooks.FRead( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
- {
- psDBF->sHooks.FClose( psDBF->fp );
- free( pabyBuf );
- free( psDBF->pszCurrentRecord );
- free( psDBF );
- return NULL;
- }
-
- psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
- psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
- psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
- psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);
-
- for( iField = 0; iField < nFields; iField++ )
- {
- unsigned char *pabyFInfo;
-
- pabyFInfo = pabyBuf+iField*32;
-
- if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
- {
- psDBF->panFieldSize[iField] = pabyFInfo[16];
- psDBF->panFieldDecimals[iField] = pabyFInfo[17];
- }
- else
- {
- psDBF->panFieldSize[iField] = pabyFInfo[16];
- psDBF->panFieldDecimals[iField] = 0;
-
-/*
-** The following seemed to be used sometimes to handle files with long
-** string fields, but in other cases (such as bug 1202) the decimals field
-** just seems to indicate some sort of preferred formatting, not very
-** wide fields. So I have disabled this code. FrankW.
- psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
- psDBF->panFieldDecimals[iField] = 0;
-*/
- }
-
- psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
- if( iField == 0 )
- psDBF->panFieldOffset[iField] = 1;
- else
- psDBF->panFieldOffset[iField] =
- psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
- }
-
- return( psDBF );
-}
-
-/************************************************************************/
-/* DBFClose() */
-/************************************************************************/
-
-void SHPAPI_CALL
-DBFClose(DBFHandle psDBF)
-{
- if( psDBF == NULL )
- return;
-
-/* -------------------------------------------------------------------- */
-/* Write out header if not already written. */
-/* -------------------------------------------------------------------- */
- if( psDBF->bNoHeader )
- DBFWriteHeader( psDBF );
-
- DBFFlushRecord( psDBF );
-
-/* -------------------------------------------------------------------- */
-/* Update last access date, and number of records if we have */
-/* write access. */
-/* -------------------------------------------------------------------- */
- if( psDBF->bUpdated )
- DBFUpdateHeader( psDBF );
-
-/* -------------------------------------------------------------------- */
-/* Close, and free resources. */
-/* -------------------------------------------------------------------- */
- psDBF->sHooks.FClose( psDBF->fp );
-
- if( psDBF->panFieldOffset != NULL )
- {
- free( psDBF->panFieldOffset );
- free( psDBF->panFieldSize );
- free( psDBF->panFieldDecimals );
- free( psDBF->pachFieldType );
- }
-
- if( psDBF->pszWorkField != NULL )
- free( psDBF->pszWorkField );
-
- free( psDBF->pszHeader );
- free( psDBF->pszCurrentRecord );
- free( psDBF->pszCodePage );
-
- free( psDBF );
-}
-
-/************************************************************************/
-/* DBFCreate() */
-/* */
-/* Create a new .dbf file with default code page LDID/87 (0x57) */
-/************************************************************************/
-
-DBFHandle SHPAPI_CALL
-DBFCreate( const char * pszFilename )
-
-{
- return DBFCreateEx( pszFilename, "LDID/87" ); // 0x57
-}
-
-/************************************************************************/
-/* DBFCreateEx() */
-/* */
-/* Create a new .dbf file. */
-/************************************************************************/
-
-DBFHandle SHPAPI_CALL
-DBFCreateEx( const char * pszFilename, const char* pszCodePage )
-
-{
- SAHooks sHooks;
-
- SASetupDefaultHooks( &sHooks );
-
- return DBFCreateLL( pszFilename, pszCodePage , &sHooks );
-}
-
-/************************************************************************/
-/* DBFCreate() */
-/* */
-/* Create a new .dbf file. */
-/************************************************************************/
-
-DBFHandle SHPAPI_CALL
-DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHooks )
-
-{
- DBFHandle psDBF;
- SAFile fp;
- char *pszFullname, *pszBasename;
- int i, ldid = -1;
- char chZero = '\0';
-
-/* -------------------------------------------------------------------- */
-/* Compute the base (layer) name. If there is any extension */
-/* on the passed in filename we will strip it off. */
-/* -------------------------------------------------------------------- */
- pszBasename = (char *) malloc(strlen(pszFilename)+5);
- strcpy( pszBasename, pszFilename );
- for( i = strlen(pszBasename)-1;
- i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
- && pszBasename[i] != '\\';
- i-- ) {}
-
- if( pszBasename[i] == '.' )
- pszBasename[i] = '\0';
-
- pszFullname = (char *) malloc(strlen(pszBasename) + 5);
- sprintf( pszFullname, "%s.dbf", pszBasename );
-
-/* -------------------------------------------------------------------- */
-/* Create the file. */
-/* -------------------------------------------------------------------- */
- fp = psHooks->FOpen( pszFullname, "wb" );
- if( fp == NULL )
- return( NULL );
-
- psHooks->FWrite( &chZero, 1, 1, fp );
- psHooks->FClose( fp );
-
- fp = psHooks->FOpen( pszFullname, "rb+" );
- if( fp == NULL )
- return( NULL );
-
-
- sprintf( pszFullname, "%s.cpg", pszBasename );
- if( pszCodePage != NULL )
- {
- if( strncmp( pszCodePage, "LDID/", 5 ) == 0 )
- {
- ldid = atoi( pszCodePage + 5 );
- if( ldid > 255 )
- ldid = -1; // don't use 0 to indicate out of range as LDID/0 is a valid one
- }
- if( ldid < 0 )
- {
- SAFile fpCPG = psHooks->FOpen( pszFullname, "w" );
- psHooks->FWrite( (char*) pszCodePage, strlen(pszCodePage), 1, fpCPG );
- psHooks->FClose( fpCPG );
- }
- }
- if( pszCodePage == NULL || ldid >= 0 )
- {
- psHooks->Remove( pszFullname );
- }
-
- free( pszBasename );
- free( pszFullname );
-
-/* -------------------------------------------------------------------- */
-/* Create the info structure. */
-/* -------------------------------------------------------------------- */
- psDBF = (DBFHandle) calloc(1,sizeof(DBFInfo));
-
- memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
- psDBF->fp = fp;
- psDBF->nRecords = 0;
- psDBF->nFields = 0;
- psDBF->nRecordLength = 1;
- psDBF->nHeaderLength = 33;
-
- psDBF->panFieldOffset = NULL;
- psDBF->panFieldSize = NULL;
- psDBF->panFieldDecimals = NULL;
- psDBF->pachFieldType = NULL;
- psDBF->pszHeader = NULL;
-
- psDBF->nCurrentRecord = -1;
- psDBF->bCurrentRecordModified = FALSE;
- psDBF->pszCurrentRecord = NULL;
-
- psDBF->bNoHeader = TRUE;
-
- psDBF->iLanguageDriver = ldid > 0 ? ldid : 0;
- psDBF->pszCodePage = NULL;
- if( pszCodePage )
- {
- psDBF->pszCodePage = (char * ) malloc( strlen(pszCodePage) + 1 );
- strcpy( psDBF->pszCodePage, pszCodePage );
- }
-
- return( psDBF );
-}
-
-/************************************************************************/
-/* DBFAddField() */
-/* */
-/* Add a field to a newly created .dbf or to an existing one */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFAddField(DBFHandle psDBF, const char * pszFieldName,
- DBFFieldType eType, int nWidth, int nDecimals )
-
-{
- char chNativeType = 'C';
-
- if( eType == FTLogical )
- chNativeType = 'L';
- else if( eType == FTString )
- chNativeType = 'C';
- else
- chNativeType = 'N';
-
- return DBFAddNativeFieldType( psDBF, pszFieldName, chNativeType,
- nWidth, nDecimals );
-}
-
-/************************************************************************/
-/* DBFAddField() */
-/* */
-/* Add a field to a newly created .dbf file before any records */
-/* are written. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
- char chType, int nWidth, int nDecimals )
-
-{
- char *pszFInfo;
- int i;
- int nOldRecordLength, nOldHeaderLength;
- char *pszRecord;
- char chFieldFill;
- SAOffset nRecordOffset;
-
-/* -------------------------------------------------------------------- */
-/* Do some checking to ensure we can add records to this file. */
-/* -------------------------------------------------------------------- */
- if( nWidth < 1 )
- return -1;
-
- if( nWidth > 255 )
- nWidth = 255;
-
- nOldRecordLength = psDBF->nRecordLength;
- nOldHeaderLength = psDBF->nHeaderLength;
-
-/* -------------------------------------------------------------------- */
-/* SfRealloc all the arrays larger to hold the additional field */
-/* information. */
-/* -------------------------------------------------------------------- */
- psDBF->nFields++;
-
- psDBF->panFieldOffset = (int *)
- SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
-
- psDBF->panFieldSize = (int *)
- SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
-
- psDBF->panFieldDecimals = (int *)
- SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
-
- psDBF->pachFieldType = (char *)
- SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
-
-/* -------------------------------------------------------------------- */
-/* Assign the new field information fields. */
-/* -------------------------------------------------------------------- */
- psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
- psDBF->nRecordLength += nWidth;
- psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
- psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
- psDBF->pachFieldType[psDBF->nFields-1] = chType;
-
-/* -------------------------------------------------------------------- */
-/* Extend the required header information. */
-/* -------------------------------------------------------------------- */
- psDBF->nHeaderLength += 32;
- psDBF->bUpdated = FALSE;
-
- psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
-
- pszFInfo = psDBF->pszHeader + 32 * (psDBF->nFields-1);
-
- for( i = 0; i < 32; i++ )
- pszFInfo[i] = '\0';
-
- if( (int) strlen(pszFieldName) < 10 )
- strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
- else
- strncpy( pszFInfo, pszFieldName, 10);
-
- pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
-
- if( chType == 'C' )
- {
- pszFInfo[16] = (unsigned char) (nWidth % 256);
- pszFInfo[17] = (unsigned char) (nWidth / 256);
- }
- else
- {
- pszFInfo[16] = (unsigned char) nWidth;
- pszFInfo[17] = (unsigned char) nDecimals;
- }
-
-/* -------------------------------------------------------------------- */
-/* Make the current record buffer appropriately larger. */
-/* -------------------------------------------------------------------- */
- psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
- psDBF->nRecordLength);
-
- /* we're done if dealing with new .dbf */
- if( psDBF->bNoHeader )
- return( psDBF->nFields - 1 );
-
-/* -------------------------------------------------------------------- */
-/* For existing .dbf file, shift records */
-/* -------------------------------------------------------------------- */
-
- /* alloc record */
- pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
-
- switch (chType)
- {
- case 'N':
- case 'F':
- chFieldFill = '*';
- break;
- case 'D':
- chFieldFill = '0';
- break;
- case 'L':
- chFieldFill = '?';
- break;
- default:
- chFieldFill = ' ';
- break;
- }
-
- for (i = psDBF->nRecords-1; i >= 0; --i)
- {
- nRecordOffset = nOldRecordLength * (SAOffset) i + nOldHeaderLength;
-
- /* load record */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
-
- /* set new field's value to NULL */
- memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
-
- nRecordOffset = psDBF->nRecordLength * (SAOffset) i + psDBF->nHeaderLength;
-
- /* move record to the new place*/
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
- }
-
- /* free record */
- free(pszRecord);
-
- /* force update of header with new header, record length and new field */
- psDBF->bNoHeader = TRUE;
- DBFUpdateHeader( psDBF );
-
- return( psDBF->nFields-1 );
-}
-
-/************************************************************************/
-/* DBFReadAttribute() */
-/* */
-/* Read one of the attribute fields of a record. */
-/************************************************************************/
-
-static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
- char chReqType )
-
-{
- unsigned char *pabyRec;
- void *pReturnField = NULL;
-
-/* -------------------------------------------------------------------- */
-/* Verify selection. */
-/* -------------------------------------------------------------------- */
- if( hEntity < 0 || hEntity >= psDBF->nRecords )
- return( NULL );
-
- if( iField < 0 || iField >= psDBF->nFields )
- return( NULL );
-
-/* -------------------------------------------------------------------- */
-/* Have we read the record? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, hEntity ) )
- return NULL;
-
- pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
-
-/* -------------------------------------------------------------------- */
-/* Ensure we have room to extract the target field. */
-/* -------------------------------------------------------------------- */
- if( psDBF->panFieldSize[iField] >= psDBF->nWorkFieldLength )
- {
- psDBF->nWorkFieldLength = psDBF->panFieldSize[iField] + 100;
- if( psDBF->pszWorkField == NULL )
- psDBF->pszWorkField = (char *) malloc(psDBF->nWorkFieldLength);
- else
- psDBF->pszWorkField = (char *) realloc(psDBF->pszWorkField,
- psDBF->nWorkFieldLength);
- }
-
-/* -------------------------------------------------------------------- */
-/* Extract the requested field. */
-/* -------------------------------------------------------------------- */
- strncpy( psDBF->pszWorkField,
- ((const char *) pabyRec) + psDBF->panFieldOffset[iField],
- psDBF->panFieldSize[iField] );
- psDBF->pszWorkField[psDBF->panFieldSize[iField]] = '\0';
-
- pReturnField = psDBF->pszWorkField;
-
-/* -------------------------------------------------------------------- */
-/* Decode the field. */
-/* -------------------------------------------------------------------- */
- if( chReqType == 'N' )
- {
- psDBF->dfDoubleField = psDBF->sHooks.Atof(psDBF->pszWorkField);
-
- pReturnField = &(psDBF->dfDoubleField);
- }
-
-/* -------------------------------------------------------------------- */
-/* Should we trim white space off the string attribute value? */
-/* -------------------------------------------------------------------- */
-#ifdef TRIM_DBF_WHITESPACE
- else
- {
- char *pchSrc, *pchDst;
-
- pchDst = pchSrc = psDBF->pszWorkField;
- while( *pchSrc == ' ' )
- pchSrc++;
-
- while( *pchSrc != '\0' )
- *(pchDst++) = *(pchSrc++);
- *pchDst = '\0';
-
- while( pchDst != psDBF->pszWorkField && *(--pchDst) == ' ' )
- *pchDst = '\0';
- }
-#endif
-
- return( pReturnField );
-}
-
-/************************************************************************/
-/* DBFReadIntAttribute() */
-/* */
-/* Read an integer attribute. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
-
-{
- double *pdValue;
-
- pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
-
- if( pdValue == NULL )
- return 0;
- else
- return( (int) *pdValue );
-}
-
-/************************************************************************/
-/* DBFReadDoubleAttribute() */
-/* */
-/* Read a double attribute. */
-/************************************************************************/
-
-double SHPAPI_CALL
-DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
-
-{
- double *pdValue;
-
- pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
-
- if( pdValue == NULL )
- return 0.0;
- else
- return( *pdValue );
-}
-
-/************************************************************************/
-/* DBFReadStringAttribute() */
-/* */
-/* Read a string attribute. */
-/************************************************************************/
-
-const char SHPAPI_CALL1(*)
-DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
-
-{
- return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
-}
-
-/************************************************************************/
-/* DBFReadLogicalAttribute() */
-/* */
-/* Read a logical attribute. */
-/************************************************************************/
-
-const char SHPAPI_CALL1(*)
-DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
-
-{
- return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
-}
-
-/************************************************************************/
-/* DBFIsAttributeNULL() */
-/* */
-/* Return TRUE if value for field is NULL. */
-/* */
-/* Contributed by Jim Matthews. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
-
-{
- const char *pszValue;
- int i;
-
- pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
-
- if( pszValue == NULL )
- return TRUE;
-
- switch(psDBF->pachFieldType[iField])
- {
- case 'N':
- case 'F':
- /*
- ** We accept all asterisks or all blanks as NULL
- ** though according to the spec I think it should be all
- ** asterisks.
- */
- if( pszValue[0] == '*' )
- return TRUE;
-
- for( i = 0; pszValue[i] != '\0'; i++ )
- {
- if( pszValue[i] != ' ' )
- return FALSE;
- }
- return TRUE;
-
- case 'D':
- /* NULL date fields have value "00000000" */
- return strncmp(pszValue,"00000000",8) == 0;
-
- case 'L':
- /* NULL boolean fields have value "?" */
- return pszValue[0] == '?';
-
- default:
- /* empty string fields are considered NULL */
- return strlen(pszValue) == 0;
- }
-}
-
-/************************************************************************/
-/* DBFGetFieldCount() */
-/* */
-/* Return the number of fields in this table. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFGetFieldCount( DBFHandle psDBF )
-
-{
- return( psDBF->nFields );
-}
-
-/************************************************************************/
-/* DBFGetRecordCount() */
-/* */
-/* Return the number of records in this table. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFGetRecordCount( DBFHandle psDBF )
-
-{
- return( psDBF->nRecords );
-}
-
-/************************************************************************/
-/* DBFGetFieldInfo() */
-/* */
-/* Return any requested information about the field. */
-/************************************************************************/
-
-DBFFieldType SHPAPI_CALL
-DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
- int * pnWidth, int * pnDecimals )
-
-{
- if( iField < 0 || iField >= psDBF->nFields )
- return( FTInvalid );
-
- if( pnWidth != NULL )
- *pnWidth = psDBF->panFieldSize[iField];
-
- if( pnDecimals != NULL )
- *pnDecimals = psDBF->panFieldDecimals[iField];
-
- if( pszFieldName != NULL )
- {
- int i;
-
- strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*32, 11 );
- pszFieldName[11] = '\0';
- for( i = 10; i > 0 && pszFieldName[i] == ' '; i-- )
- pszFieldName[i] = '\0';
- }
-
- if ( psDBF->pachFieldType[iField] == 'L' )
- return( FTLogical);
-
- else if( psDBF->pachFieldType[iField] == 'N'
- || psDBF->pachFieldType[iField] == 'F' )
- {
- if( psDBF->panFieldDecimals[iField] > 0
- || psDBF->panFieldSize[iField] > 10 )
- return( FTDouble );
- else
- return( FTInteger );
- }
- else
- {
- return( FTString );
- }
-}
-
-/************************************************************************/
-/* DBFWriteAttribute() */
-/* */
-/* Write an attribute record to the file. */
-/************************************************************************/
-
-static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
- void * pValue )
-
-{
- int i, j, nRetResult = TRUE;
- unsigned char *pabyRec;
- char szSField[400], szFormat[20];
-
-/* -------------------------------------------------------------------- */
-/* Is this a valid record? */
-/* -------------------------------------------------------------------- */
- if( hEntity < 0 || hEntity > psDBF->nRecords )
- return( FALSE );
-
- if( psDBF->bNoHeader )
- DBFWriteHeader(psDBF);
-
-/* -------------------------------------------------------------------- */
-/* Is this a brand new record? */
-/* -------------------------------------------------------------------- */
- if( hEntity == psDBF->nRecords )
- {
- if( !DBFFlushRecord( psDBF ) )
- return FALSE;
-
- psDBF->nRecords++;
- for( i = 0; i < psDBF->nRecordLength; i++ )
- psDBF->pszCurrentRecord[i] = ' ';
-
- psDBF->nCurrentRecord = hEntity;
- }
-
-/* -------------------------------------------------------------------- */
-/* Is this an existing record, but different than the last one */
-/* we accessed? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, hEntity ) )
- return FALSE;
-
- pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
-
- psDBF->bCurrentRecordModified = TRUE;
- psDBF->bUpdated = TRUE;
-
-/* -------------------------------------------------------------------- */
-/* Translate NULL value to valid DBF file representation. */
-/* */
-/* Contributed by Jim Matthews. */
-/* -------------------------------------------------------------------- */
- if( pValue == NULL )
- {
- switch(psDBF->pachFieldType[iField])
- {
- case 'N':
- case 'F':
- /* NULL numeric fields have value "****************" */
- memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '*',
- psDBF->panFieldSize[iField] );
- break;
-
- case 'D':
- /* NULL date fields have value "00000000" */
- memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '0',
- psDBF->panFieldSize[iField] );
- break;
-
- case 'L':
- /* NULL boolean fields have value "?" */
- memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '?',
- psDBF->panFieldSize[iField] );
- break;
-
- default:
- /* empty string fields are considered NULL */
- memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), ' ',
- psDBF->panFieldSize[iField] );
- break;
- }
- return TRUE;
- }
-
-/* -------------------------------------------------------------------- */
-/* Assign all the record fields. */
-/* -------------------------------------------------------------------- */
- switch( psDBF->pachFieldType[iField] )
- {
- case 'D':
- case 'N':
- case 'F':
- if( psDBF->panFieldDecimals[iField] == 0 )
- {
- int nWidth = psDBF->panFieldSize[iField];
-
- if( (int) sizeof(szSField)-2 < nWidth )
- nWidth = sizeof(szSField)-2;
-
- sprintf( szFormat, "%%%dd", nWidth );
- sprintf(szSField, szFormat, (int) *((double *) pValue) );
- if( (int)strlen(szSField) > psDBF->panFieldSize[iField] )
- {
- szSField[psDBF->panFieldSize[iField]] = '\0';
- nRetResult = FALSE;
- }
-
- strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
- szSField, strlen(szSField) );
- }
- else
- {
- int nWidth = psDBF->panFieldSize[iField];
-
- if( (int) sizeof(szSField)-2 < nWidth )
- nWidth = sizeof(szSField)-2;
-
- sprintf( szFormat, "%%%d.%df",
- nWidth, psDBF->panFieldDecimals[iField] );
- sprintf(szSField, szFormat, *((double *) pValue) );
- if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
- {
- szSField[psDBF->panFieldSize[iField]] = '\0';
- nRetResult = FALSE;
- }
- strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
- szSField, strlen(szSField) );
- }
- break;
-
- case 'L':
- if (psDBF->panFieldSize[iField] >= 1 &&
- (*(char*)pValue == 'F' || *(char*)pValue == 'T'))
- *(pabyRec+psDBF->panFieldOffset[iField]) = *(char*)pValue;
- break;
-
- default:
- if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] )
- {
- j = psDBF->panFieldSize[iField];
- nRetResult = FALSE;
- }
- else
- {
- memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
- psDBF->panFieldSize[iField] );
- j = strlen((char *) pValue);
- }
-
- strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
- (char *) pValue, j );
- break;
- }
-
- return( nRetResult );
-}
-
-/************************************************************************/
-/* DBFWriteAttributeDirectly() */
-/* */
-/* Write an attribute record to the file, but without any */
-/* reformatting based on type. The provided buffer is written */
-/* as is to the field position in the record. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
- void * pValue )
-
-{
- int i, j;
- unsigned char *pabyRec;
-
-/* -------------------------------------------------------------------- */
-/* Is this a valid record? */
-/* -------------------------------------------------------------------- */
- if( hEntity < 0 || hEntity > psDBF->nRecords )
- return( FALSE );
-
- if( psDBF->bNoHeader )
- DBFWriteHeader(psDBF);
-
-/* -------------------------------------------------------------------- */
-/* Is this a brand new record? */
-/* -------------------------------------------------------------------- */
- if( hEntity == psDBF->nRecords )
- {
- if( !DBFFlushRecord( psDBF ) )
- return FALSE;
-
- psDBF->nRecords++;
- for( i = 0; i < psDBF->nRecordLength; i++ )
- psDBF->pszCurrentRecord[i] = ' ';
-
- psDBF->nCurrentRecord = hEntity;
- }
-
-/* -------------------------------------------------------------------- */
-/* Is this an existing record, but different than the last one */
-/* we accessed? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, hEntity ) )
- return FALSE;
-
- pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
-
-/* -------------------------------------------------------------------- */
-/* Assign all the record fields. */
-/* -------------------------------------------------------------------- */
- if( (int)strlen((char *) pValue) > psDBF->panFieldSize[iField] )
- j = psDBF->panFieldSize[iField];
- else
- {
- memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
- psDBF->panFieldSize[iField] );
- j = strlen((char *) pValue);
- }
-
- strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
- (char *) pValue, j );
-
- psDBF->bCurrentRecordModified = TRUE;
- psDBF->bUpdated = TRUE;
-
- return( TRUE );
-}
-
-/************************************************************************/
-/* DBFWriteDoubleAttribute() */
-/* */
-/* Write a double attribute. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
- double dValue )
-
-{
- return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
-}
-
-/************************************************************************/
-/* DBFWriteIntegerAttribute() */
-/* */
-/* Write a integer attribute. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
- int nValue )
-
-{
- double dValue = nValue;
-
- return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
-}
-
-/************************************************************************/
-/* DBFWriteStringAttribute() */
-/* */
-/* Write a string attribute. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
- const char * pszValue )
-
-{
- return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) pszValue ) );
-}
-
-/************************************************************************/
-/* DBFWriteNULLAttribute() */
-/* */
-/* Write a string attribute. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
-
-{
- return( DBFWriteAttribute( psDBF, iRecord, iField, NULL ) );
-}
-
-/************************************************************************/
-/* DBFWriteLogicalAttribute() */
-/* */
-/* Write a logical attribute. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFWriteLogicalAttribute( DBFHandle psDBF, int iRecord, int iField,
- const char lValue)
-
-{
- return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) (&lValue) ) );
-}
-
-/************************************************************************/
-/* DBFWriteTuple() */
-/* */
-/* Write an attribute record to the file. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
-
-{
- int i;
- unsigned char *pabyRec;
-
-/* -------------------------------------------------------------------- */
-/* Is this a valid record? */
-/* -------------------------------------------------------------------- */
- if( hEntity < 0 || hEntity > psDBF->nRecords )
- return( FALSE );
-
- if( psDBF->bNoHeader )
- DBFWriteHeader(psDBF);
-
-/* -------------------------------------------------------------------- */
-/* Is this a brand new record? */
-/* -------------------------------------------------------------------- */
- if( hEntity == psDBF->nRecords )
- {
- if( !DBFFlushRecord( psDBF ) )
- return FALSE;
-
- psDBF->nRecords++;
- for( i = 0; i < psDBF->nRecordLength; i++ )
- psDBF->pszCurrentRecord[i] = ' ';
-
- psDBF->nCurrentRecord = hEntity;
- }
-
-/* -------------------------------------------------------------------- */
-/* Is this an existing record, but different than the last one */
-/* we accessed? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, hEntity ) )
- return FALSE;
-
- pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
-
- memcpy ( pabyRec, pRawTuple, psDBF->nRecordLength );
-
- psDBF->bCurrentRecordModified = TRUE;
- psDBF->bUpdated = TRUE;
-
- return( TRUE );
-}
-
-/************************************************************************/
-/* DBFReadTuple() */
-/* */
-/* Read a complete record. Note that the result is only valid */
-/* till the next record read for any reason. */
-/************************************************************************/
-
-const char SHPAPI_CALL1(*)
-DBFReadTuple(DBFHandle psDBF, int hEntity )
-
-{
- if( hEntity < 0 || hEntity >= psDBF->nRecords )
- return( NULL );
-
- if( !DBFLoadRecord( psDBF, hEntity ) )
- return NULL;
-
- return (const char *) psDBF->pszCurrentRecord;
-}
-
-/************************************************************************/
-/* DBFCloneEmpty() */
-/* */
-/* Read one of the attribute fields of a record. */
-/************************************************************************/
-
-DBFHandle SHPAPI_CALL
-DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
-{
- DBFHandle newDBF;
-
- newDBF = DBFCreateEx ( pszFilename, psDBF->pszCodePage );
- if ( newDBF == NULL ) return ( NULL );
-
- newDBF->nFields = psDBF->nFields;
- newDBF->nRecordLength = psDBF->nRecordLength;
- newDBF->nHeaderLength = psDBF->nHeaderLength;
-
- newDBF->pszHeader = (char *) malloc ( newDBF->nHeaderLength );
- memcpy ( newDBF->pszHeader, psDBF->pszHeader, newDBF->nHeaderLength );
-
- newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields );
- memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
- newDBF->panFieldSize = (int *) malloc ( sizeof(int) * psDBF->nFields );
- memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
- newDBF->panFieldDecimals = (int *) malloc ( sizeof(int) * psDBF->nFields );
- memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
- newDBF->pachFieldType = (char *) malloc ( sizeof(char) * psDBF->nFields );
- memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(char)*psDBF->nFields );
-
- newDBF->bNoHeader = TRUE;
- newDBF->bUpdated = TRUE;
-
- DBFWriteHeader ( newDBF );
- DBFClose ( newDBF );
-
- newDBF = DBFOpen ( pszFilename, "rb+" );
-
- return ( newDBF );
-}
-
-/************************************************************************/
-/* DBFGetNativeFieldType() */
-/* */
-/* Return the DBase field type for the specified field. */
-/* */
-/* Value can be one of: 'C' (String), 'D' (Date), 'F' (Float), */
-/* 'N' (Numeric, with or without decimal), */
-/* 'L' (Logical), */
-/* 'M' (Memo: 10 digits .DBT block ptr) */
-/************************************************************************/
-
-char SHPAPI_CALL
-DBFGetNativeFieldType( DBFHandle psDBF, int iField )
-
-{
- if( iField >=0 && iField < psDBF->nFields )
- return psDBF->pachFieldType[iField];
-
- return ' ';
-}
-
-/************************************************************************/
-/* str_to_upper() */
-/************************************************************************/
-
-static void str_to_upper (char *string)
-{
- int len;
- short i = -1;
-
- len = strlen (string);
-
- while (++i < len)
- if (isalpha(string[i]) && islower(string[i]))
- string[i] = (char) toupper ((int)string[i]);
-}
-
-/************************************************************************/
-/* DBFGetFieldIndex() */
-/* */
-/* Get the index number for a field in a .dbf file. */
-/* */
-/* Contributed by Jim Matthews. */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
-
-{
- char name[12], name1[12], name2[12];
- int i;
-
- strncpy(name1, pszFieldName,11);
- name1[11] = '\0';
- str_to_upper(name1);
-
- for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
- {
- DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
- strncpy(name2,name,11);
- str_to_upper(name2);
-
- if(!strncmp(name1,name2,10))
- return(i);
- }
- return(-1);
-}
-
-/************************************************************************/
-/* DBFIsRecordDeleted() */
-/* */
-/* Returns TRUE if the indicated record is deleted, otherwise */
-/* it returns FALSE. */
-/************************************************************************/
-
-int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape )
-
-{
-/* -------------------------------------------------------------------- */
-/* Verify selection. */
-/* -------------------------------------------------------------------- */
- if( iShape < 0 || iShape >= psDBF->nRecords )
- return TRUE;
-
-/* -------------------------------------------------------------------- */
-/* Have we read the record? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, iShape ) )
- return FALSE;
-
-/* -------------------------------------------------------------------- */
-/* '*' means deleted. */
-/* -------------------------------------------------------------------- */
- return psDBF->pszCurrentRecord[0] == '*';
-}
-
-/************************************************************************/
-/* DBFMarkRecordDeleted() */
-/************************************************************************/
-
-int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
- int bIsDeleted )
-
-{
- char chNewFlag;
-
-/* -------------------------------------------------------------------- */
-/* Verify selection. */
-/* -------------------------------------------------------------------- */
- if( iShape < 0 || iShape >= psDBF->nRecords )
- return FALSE;
-
-/* -------------------------------------------------------------------- */
-/* Is this an existing record, but different than the last one */
-/* we accessed? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, iShape ) )
- return FALSE;
-
-/* -------------------------------------------------------------------- */
-/* Assign value, marking record as dirty if it changes. */
-/* -------------------------------------------------------------------- */
- if( bIsDeleted )
- chNewFlag = '*';
- else
- chNewFlag = ' ';
-
- if( psDBF->pszCurrentRecord[0] != chNewFlag )
- {
- psDBF->bCurrentRecordModified = TRUE;
- psDBF->bUpdated = TRUE;
- psDBF->pszCurrentRecord[0] = chNewFlag;
- }
-
- return TRUE;
-}
-
-/************************************************************************/
-/* DBFGetCodePage */
-/************************************************************************/
-
-const char SHPAPI_CALL1(*)
-DBFGetCodePage(DBFHandle psDBF )
-{
- if( psDBF == NULL )
- return NULL;
- return psDBF->pszCodePage;
-}
-
-/************************************************************************/
-/* DBFDeleteField() */
-/* */
-/* Remove a field from a .dbf file */
-/************************************************************************/
-
-int SHPAPI_CALL
-DBFDeleteField(DBFHandle psDBF, int iField)
-{
- int nOldRecordLength, nOldHeaderLength;
- int nDeletedFieldOffset, nDeletedFieldSize;
- SAOffset nRecordOffset;
- char* pszRecord;
- int i, iRecord;
-
- if (iField < 0 || iField >= psDBF->nFields)
- return FALSE;
-
- /* make sure that everything is written in .dbf */
- if( !DBFFlushRecord( psDBF ) )
- return FALSE;
-
- /* get information about field to be deleted */
- nOldRecordLength = psDBF->nRecordLength;
- nOldHeaderLength = psDBF->nHeaderLength;
- nDeletedFieldOffset = psDBF->panFieldOffset[iField];
- nDeletedFieldSize = psDBF->panFieldSize[iField];
-
- /* update fields info */
- for (i = iField + 1; i < psDBF->nFields; i++)
- {
- psDBF->panFieldOffset[i-1] = psDBF->panFieldOffset[i] - nDeletedFieldSize;
- psDBF->panFieldSize[i-1] = psDBF->panFieldSize[i];
- psDBF->panFieldDecimals[i-1] = psDBF->panFieldDecimals[i];
- psDBF->pachFieldType[i-1] = psDBF->pachFieldType[i];
- }
-
- /* resize fields arrays */
- psDBF->nFields--;
-
- psDBF->panFieldOffset = (int *)
- SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
-
- psDBF->panFieldSize = (int *)
- SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
-
- psDBF->panFieldDecimals = (int *)
- SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
-
- psDBF->pachFieldType = (char *)
- SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
-
- /* update header information */
- psDBF->nHeaderLength -= 32;
- psDBF->nRecordLength -= nDeletedFieldSize;
-
- /* overwrite field information in header */
- memcpy(psDBF->pszHeader + iField*32,
- psDBF->pszHeader + (iField+1)*32,
- sizeof(char) * (psDBF->nFields - iField)*32);
-
- psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
-
- /* update size of current record appropriately */
- psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
- psDBF->nRecordLength);
-
- /* we're done if we're dealing with not yet created .dbf */
- if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
- return TRUE;
-
- /* force update of header with new header and record length */
- psDBF->bNoHeader = TRUE;
- DBFUpdateHeader( psDBF );
-
- /* alloc record */
- pszRecord = (char *) malloc(sizeof(char) * nOldRecordLength);
-
- /* shift records to their new positions */
- for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
- {
- nRecordOffset =
- nOldRecordLength * (SAOffset) iRecord + nOldHeaderLength;
-
- /* load record */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
-
- nRecordOffset =
- psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
-
- /* move record in two steps */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FWrite( pszRecord, nDeletedFieldOffset, 1, psDBF->fp );
- psDBF->sHooks.FWrite( pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
- nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize,
- 1, psDBF->fp );
-
- }
-
- /* TODO: truncate file */
-
- /* free record */
- free(pszRecord);
-
- return TRUE;
-}
diff --git a/navit/map/shapefile/shapefil.h b/navit/map/shapefile/shapefil.h
deleted file mode 100644
index 059244b03..000000000
--- a/navit/map/shapefile/shapefil.h
+++ /dev/null
@@ -1,609 +0,0 @@
-#ifndef SHAPEFILE_H_INCLUDED
-#define SHAPEFILE_H_INCLUDED
-
-/******************************************************************************
- * $Id: shapefil.h 15715 2008-11-12 15:15:21Z warmerdam $
- *
- * Project: Shapelib
- * Purpose: Primary include file for Shapelib.
- * Author: Frank Warmerdam, warmerdam@pobox.com
- *
- ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
- *
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL). 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.
- ******************************************************************************
- *
- * $Log: shapefil.h,v $
- * Revision 1.46 2008/11/12 14:28:15 fwarmerdam
- * DBFCreateField() now works on files with records
- *
- * Revision 1.45 2008/11/11 17:47:10 fwarmerdam
- * added DBFDeleteField() function
- *
- * Revision 1.44 2008/01/16 20:05:19 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.43 2008/01/10 16:35:30 fwarmerdam
- * avoid _ prefix on #defined symbols (bug 1840)
- *
- * Revision 1.42 2007/12/18 18:28:14 bram
- * - create hook for client specific atof (bugzilla ticket 1615)
- * - check for NULL handle before closing cpCPG file, and close after reading.
- *
- * Revision 1.41 2007/12/15 20:25:32 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/<number>") or as the
- * content of an accompanying .CPG file. When creating a DBF file, the code can
- * be set using DBFCreateEx.
- *
- * Revision 1.40 2007/12/06 07:00:25 fwarmerdam
- * dbfopen now using SAHooks for fileio
- *
- * Revision 1.39 2007/12/04 20:37:56 fwarmerdam
- * preliminary implementation of hooks api for io and errors
- *
- * Revision 1.38 2007/11/21 22:39:56 fwarmerdam
- * close shx file in readonly mode (GDAL #1956)
- *
- * Revision 1.37 2007/10/27 03:31:14 fwarmerdam
- * limit default depth of tree to 12 levels (gdal ticket #1594)
- *
- * Revision 1.36 2007/09/10 23:33:15 fwarmerdam
- * Upstreamed support for visibility flag in SHPAPI_CALL for the needs
- * of GDAL (gdal ticket #1810).
- *
- * Revision 1.35 2007/09/03 19:48:10 fwarmerdam
- * move DBFReadAttribute() static dDoubleField into dbfinfo
- *
- * Revision 1.34 2006/06/17 15:33:32 fwarmerdam
- * added pszWorkField - bug 1202 (rso)
- *
- * Revision 1.33 2006/02/15 01:14:30 fwarmerdam
- * added DBFAddNativeFieldType
- *
- * Revision 1.32 2006/01/26 15:07:32 fwarmerdam
- * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
- *
- * Revision 1.31 2006/01/05 01:27:27 fwarmerdam
- * added dbf deletion mark/fetch
- *
- * Revision 1.30 2005/01/03 22:30:13 fwarmerdam
- * added support for saved quadtrees
- *
- * Revision 1.29 2004/09/26 20:09:35 fwarmerdam
- * avoid rcsid warnings
- *
- * Revision 1.28 2003/12/29 06:02:18 fwarmerdam
- * added cpl_error.h option
- *
- * Revision 1.27 2003/04/21 18:30:37 warmerda
- * added header write/update public methods
- *
- * Revision 1.26 2002/09/29 00:00:08 warmerda
- * added FTLogical and logical attribute read/write calls
- *
- * Revision 1.25 2002/05/07 13:46:30 warmerda
- * added DBFWriteAttributeDirectly().
- *
- * Revision 1.24 2002/04/10 16:59:54 warmerda
- * added SHPRewindObject
- *
- * Revision 1.23 2002/01/15 14:36:07 warmerda
- * updated email address
- *
- * Revision 1.22 2002/01/15 14:32:00 warmerda
- * try to improve SHPAPI_CALL docs
- */
-
-#include <stdio.h>
-
-#ifdef USE_DBMALLOC
-#include <dbmalloc.h>
-#endif
-
-#ifdef USE_CPL
-#include "cpl_error.h"
-#include "cpl_vsi.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/************************************************************************/
-/* Configuration options. */
-/************************************************************************/
-
-/* -------------------------------------------------------------------- */
-/* Should the DBFReadStringAttribute() strip leading and */
-/* trailing white space? */
-/* -------------------------------------------------------------------- */
-#define TRIM_DBF_WHITESPACE
-
-/* -------------------------------------------------------------------- */
-/* Should we write measure values to the Multipatch object? */
-/* Reportedly ArcView crashes if we do write it, so for now it */
-/* is disabled. */
-/* -------------------------------------------------------------------- */
-#define DISABLE_MULTIPATCH_MEASURE
-
-/* -------------------------------------------------------------------- */
-/* SHPAPI_CALL */
-/* */
-/* The following two macros are present to allow forcing */
-/* 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 */
-/* be modified to define: */
-/* */
-/* /DSHPAPI_CALL=__stdcall */
-/* */
-/* If it is desired to force export of the Shapelib API without */
-/* using the shapelib.def file, use the following definition. */
-/* */
-/* /DSHAPELIB_DLLEXPORT */
-/* */
-/* To get both at once it will be necessary to hack this */
-/* include file to define: */
-/* */
-/* #define SHPAPI_CALL __declspec(dllexport) __stdcall */
-/* #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall */
-/* */
-/* The complexity of the situtation is partly caused by the */
-/* peculiar requirement of Visual C++ that __stdcall appear */
-/* after any "*"'s in the return value of a function while the */
-/* __declspec(dllexport) must appear before them. */
-/* -------------------------------------------------------------------- */
-
-#ifdef SHAPELIB_DLLEXPORT
-# define SHPAPI_CALL __declspec(dllexport)
-# define SHPAPI_CALL1(x) __declspec(dllexport) x
-#endif
-
-#ifndef SHPAPI_CALL
-# if defined(USE_GCC_VISIBILITY_FLAG)
-# define SHPAPI_CALL __attribute__ ((visibility("default")))
-# define SHPAPI_CALL1(x) __attribute__ ((visibility("default"))) x
-# else
-# define SHPAPI_CALL
-# endif
-#endif
-
-#ifndef SHPAPI_CALL1
-# 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
-# define SHP_CVSID(string) static char cpl_cvsid[] = string; \
-static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
-#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)
-# define SHPAPI_WINDOWS
-# define SHPAPI_UTF8_HOOKS
-#endif
-
-/* -------------------------------------------------------------------- */
-/* IO/Error hook functions. */
-/* -------------------------------------------------------------------- */
-typedef int *SAFile;
-
-#ifndef SAOffset
-typedef unsigned long SAOffset;
-#endif
-
-typedef struct {
- SAFile (*FOpen) ( const char *filename, const char *access);
- SAOffset (*FRead) ( void *p, SAOffset size, SAOffset nmemb, SAFile file);
- SAOffset (*FWrite)( 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 );
-
- void (*Error) ( const char *message );
- double (*Atof) ( const char *str );
-} SAHooks;
-
-void SHPAPI_CALL SASetupDefaultHooks( SAHooks *psHooks );
-#ifdef SHPAPI_UTF8_HOOKS
-void SHPAPI_CALL SASetupUtf8Hooks( SAHooks *psHooks );
-#endif
-
-/************************************************************************/
-/* SHP Support. */
-/************************************************************************/
-typedef struct
-{
- SAHooks sHooks;
-
- SAFile fpSHP;
- SAFile fpSHX;
-
- int nShapeType; /* SHPT_* */
-
- int nFileSize; /* SHP file */
-
- int nRecords;
- int nMaxRecords;
- int *panRecOffset;
- int *panRecSize;
-
- double adBoundsMin[4];
- double adBoundsMax[4];
-
- int bUpdated;
-
- unsigned char *pabyRec;
- int nBufSize;
-} SHPInfo;
-
-typedef SHPInfo * SHPHandle;
-
-/* -------------------------------------------------------------------- */
-/* Shape types (nSHPType) */
-/* -------------------------------------------------------------------- */
-#define SHPT_NULL 0
-#define SHPT_POINT 1
-#define SHPT_ARC 3
-#define SHPT_POLYGON 5
-#define SHPT_MULTIPOINT 8
-#define SHPT_POINTZ 11
-#define SHPT_ARCZ 13
-#define SHPT_POLYGONZ 15
-#define SHPT_MULTIPOINTZ 18
-#define SHPT_POINTM 21
-#define SHPT_ARCM 23
-#define SHPT_POLYGONM 25
-#define SHPT_MULTIPOINTM 28
-#define SHPT_MULTIPATCH 31
-
-
-/* -------------------------------------------------------------------- */
-/* Part types - everything but SHPT_MULTIPATCH just uses */
-/* SHPP_RING. */
-/* -------------------------------------------------------------------- */
-
-#define SHPP_TRISTRIP 0
-#define SHPP_TRIFAN 1
-#define SHPP_OUTERRING 2
-#define SHPP_INNERRING 3
-#define SHPP_FIRSTRING 4
-#define SHPP_RING 5
-
-/* -------------------------------------------------------------------- */
-/* SHPObject - represents on shape (without attributes) read */
-/* from the .shp file. */
-/* -------------------------------------------------------------------- */
-typedef struct
-{
- int nSHPType;
-
- int nShapeId; /* -1 is unknown/unassigned */
-
- int nParts;
- int *panPartStart;
- int *panPartType;
-
- int nVertices;
- double *padfX;
- double *padfY;
- double *padfZ;
- double *padfM;
-
- double dfXMin;
- double dfYMin;
- double dfZMin;
- double dfMMin;
-
- double dfXMax;
- double dfYMax;
- double dfZMax;
- double dfMMax;
-
- int bMeasureIsUsed;
-} SHPObject;
-
-/* -------------------------------------------------------------------- */
-/* SHP API Prototypes */
-/* -------------------------------------------------------------------- */
-
-/* If pszAccess is read-only, the fpSHX field of the returned structure */
-/* 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 );
-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 );
-
-SHPObject SHPAPI_CALL1(*)
- SHPReadObject( SHPHandle hSHP, int iShape );
-int SHPAPI_CALL
- SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
-
-void SHPAPI_CALL
- SHPDestroyObject( SHPObject * psObject );
-void SHPAPI_CALL
- SHPComputeExtents( SHPObject * psObject );
-SHPObject SHPAPI_CALL1(*)
- SHPCreateObject( int nSHPType, int nShapeId, int nParts,
- const int * panPartStart, const int * panPartType,
- int nVertices,
- const double * padfX, const double * padfY,
- const double * padfZ, const double * padfM );
-SHPObject SHPAPI_CALL1(*)
- SHPCreateSimpleObject( int nSHPType, int nVertices,
- const double * padfX,
- const double * padfY,
- const double * padfZ );
-
-int SHPAPI_CALL
- SHPRewindObject( SHPHandle hSHP, SHPObject * psObject );
-
-void SHPAPI_CALL SHPClose( SHPHandle hSHP );
-void SHPAPI_CALL SHPWriteHeader( SHPHandle hSHP );
-
-const char SHPAPI_CALL1(*)
- SHPTypeName( int nSHPType );
-const char SHPAPI_CALL1(*)
- SHPPartTypeName( int nPartType );
-
-/* -------------------------------------------------------------------- */
-/* Shape quadtree indexing API. */
-/* -------------------------------------------------------------------- */
-
-/* this can be two or four for binary or quad tree */
-#define MAX_SUBNODE 4
-
-/* upper limit of tree levels for automatic estimation */
-#define MAX_DEFAULT_TREE_DEPTH 12
-
-typedef struct shape_tree_node
-{
- /* region covered by this node */
- double adfBoundsMin[4];
- double adfBoundsMax[4];
-
- /* list of shapes stored at this node. The papsShapeObj pointers
- or the whole list can be NULL */
- int nShapeCount;
- int *panShapeIds;
- SHPObject **papsShapeObj;
-
- int nSubNodes;
- struct shape_tree_node *apsSubNode[MAX_SUBNODE];
-
-} SHPTreeNode;
-
-typedef struct
-{
- SHPHandle hSHP;
-
- int nMaxDepth;
- int nDimension;
- int nTotalCount;
-
- SHPTreeNode *psRoot;
-} SHPTree;
-
-SHPTree SHPAPI_CALL1(*)
- SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
- double *padfBoundsMin, double *padfBoundsMax );
-void SHPAPI_CALL
- SHPDestroyTree( SHPTree * hTree );
-
-int SHPAPI_CALL
- SHPWriteTree( SHPTree *hTree, const char * pszFilename );
-SHPTree SHPAPI_CALL
- SHPReadTree( const char * pszFilename );
-
-int SHPAPI_CALL
- SHPTreeAddObject( SHPTree * hTree, SHPObject * psObject );
-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,
- double * padfBoundsMax,
- int * );
-int SHPAPI_CALL
- SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
-
-int SHPAPI_CALL1(*)
-SHPSearchDiskTree( FILE *fp,
- double *padfBoundsMin, double *padfBoundsMax,
- int *pnShapeCount );
-
-/************************************************************************/
-/* DBF Support. */
-/************************************************************************/
-typedef struct
-{
- SAHooks sHooks;
-
- SAFile fp;
-
- int nRecords;
-
- int nRecordLength;
- int nHeaderLength;
- int nFields;
- int *panFieldOffset;
- int *panFieldSize;
- int *panFieldDecimals;
- char *pachFieldType;
-
- char *pszHeader;
-
- int nCurrentRecord;
- int bCurrentRecordModified;
- char *pszCurrentRecord;
-
- int nWorkFieldLength;
- char *pszWorkField;
-
- int bNoHeader;
- int bUpdated;
-
- double dfDoubleField;
-
- int iLanguageDriver;
- char *pszCodePage;
-} DBFInfo;
-
-typedef DBFInfo * DBFHandle;
-
-typedef enum {
- FTString,
- FTInteger,
- FTDouble,
- FTLogical,
- FTInvalid
-} DBFFieldType;
-
-#define XBASE_FLDHDR_SZ 32
-
-
-DBFHandle SHPAPI_CALL
- DBFOpen( const char * pszDBFFile, const char * pszAccess );
-DBFHandle SHPAPI_CALL
- DBFOpenLL( const char * pszDBFFile, const char * pszAccess,
- 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 );
-
-int SHPAPI_CALL
- DBFGetFieldCount( DBFHandle psDBF );
-int SHPAPI_CALL
- DBFGetRecordCount( DBFHandle psDBF );
-int SHPAPI_CALL
- DBFAddField( DBFHandle hDBF, const char * pszFieldName,
- DBFFieldType eType, int nWidth, int nDecimals );
-
-int SHPAPI_CALL
- DBFAddNativeFieldType( DBFHandle hDBF, const char * pszFieldName,
- char chType, int nWidth, int nDecimals );
-
-int SHPAPI_CALL
- DBFDeleteField( DBFHandle hDBF, int iField );
-
-DBFFieldType SHPAPI_CALL
- DBFGetFieldInfo( DBFHandle psDBF, int iField,
- char * pszFieldName, int * pnWidth, int * pnDecimals );
-
-int SHPAPI_CALL
- DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
-
-int SHPAPI_CALL
- DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
-double SHPAPI_CALL
- DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
-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 );
-
-int SHPAPI_CALL
- DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
- int nFieldValue );
-int SHPAPI_CALL
- DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
- double dFieldValue );
-int SHPAPI_CALL
- DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
- const char * pszFieldValue );
-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
- DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
- void * pValue );
-const char SHPAPI_CALL1(*)
- DBFReadTuple(DBFHandle psDBF, int hEntity );
-int SHPAPI_CALL
- DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
-
-int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape );
-int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
- int bIsDeleted );
-
-DBFHandle SHPAPI_CALL
- DBFCloneEmpty(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 );
-
-const char SHPAPI_CALL1(*)
- DBFGetCodePage(DBFHandle psDBF );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ndef SHAPEFILE_H_INCLUDED */
diff --git a/navit/map/shapefile/shpopen.c b/navit/map/shapefile/shpopen.c
deleted file mode 100644
index da5365281..000000000
--- a/navit/map/shapefile/shpopen.c
+++ /dev/null
@@ -1,2283 +0,0 @@
-/******************************************************************************
- * $Id: shpopen.c,v 1.59 2008/03/14 05:25:31 fwarmerdam Exp $
- *
- * Project: Shapelib
- * Purpose: Implementation of core Shapefile read/write functions.
- * Author: Frank Warmerdam, warmerdam@pobox.com
- *
- ******************************************************************************
- * Copyright (c) 1999, 2001, Frank Warmerdam
- *
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL). 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.
- ******************************************************************************
- *
- * $Log: shpopen.c,v $
- * Revision 1.59 2008/03/14 05:25:31 fwarmerdam
- * Correct crash on buggy geometries (gdal #2218)
- *
- * Revision 1.58 2008/01/08 23:28:26 bram
- * on line 2095, use a float instead of a double to avoid a compiler warning
- *
- * Revision 1.57 2007/12/06 07:00:25 fwarmerdam
- * dbfopen now using SAHooks for fileio
- *
- * Revision 1.56 2007/12/04 20:37:56 fwarmerdam
- * preliminary implementation of hooks api for io and errors
- *
- * Revision 1.55 2007/11/21 22:39:56 fwarmerdam
- * close shx file in readonly mode (GDAL #1956)
- *
- * Revision 1.54 2007/11/15 00:12:47 mloskot
- * Backported recent changes from GDAL (Ticket #1415) to Shapelib.
- *
- * Revision 1.53 2007/11/14 22:31:08 fwarmerdam
- * checks after mallocs to detect for corrupted/voluntary broken shapefiles.
- * http://trac.osgeo.org/gdal/ticket/1991
- *
- * Revision 1.52 2007/06/21 15:58:33 fwarmerdam
- * fix for SHPRewindObject when rings touch at one vertex (gdal #976)
- *
- * Revision 1.51 2006/09/04 15:24:01 fwarmerdam
- * Fixed up log message for 1.49.
- *
- * Revision 1.50 2006/09/04 15:21:39 fwarmerdam
- * fix of last fix
- *
- * Revision 1.49 2006/09/04 15:21:00 fwarmerdam
- * MLoskot: Added stronger test of Shapefile reading failures, e.g. truncated
- * files. The problem was discovered by Tim Sutton and reported here
- * https://svn.qgis.org/trac/ticket/200
- *
- * Revision 1.48 2006/01/26 15:07:32 fwarmerdam
- * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
- *
- * Revision 1.47 2006/01/04 20:07:23 fwarmerdam
- * In SHPWriteObject() make sure that the record length is updated
- * when rewriting an existing record.
- *
- * Revision 1.46 2005/02/11 17:17:46 fwarmerdam
- * added panPartStart[0] validation
- *
- * Revision 1.45 2004/09/26 20:09:48 fwarmerdam
- * const correctness changes
- *
- * Revision 1.44 2003/12/29 00:18:39 fwarmerdam
- * added error checking for failed IO and optional CPL error reporting
- *
- * Revision 1.43 2003/12/01 16:20:08 warmerda
- * be careful of zero vertex shapes
- *
- * Revision 1.42 2003/12/01 14:58:27 warmerda
- * added degenerate object check in SHPRewindObject()
- *
- * Revision 1.41 2003/07/08 15:22:43 warmerda
- * avoid warning
- *
- * Revision 1.40 2003/04/21 18:30:37 warmerda
- * added header write/update public methods
- *
- * Revision 1.39 2002/08/26 06:46:56 warmerda
- * avoid c++ comments
- *
- * Revision 1.38 2002/05/07 16:43:39 warmerda
- * Removed debugging printf.
- *
- * Revision 1.37 2002/04/10 17:35:22 warmerda
- * fixed bug in ring reversal code
- *
- * Revision 1.36 2002/04/10 16:59:54 warmerda
- * added SHPRewindObject
- *
- * Revision 1.35 2001/12/07 15:10:44 warmerda
- * fix if .shx fails to open
- *
- * Revision 1.34 2001/11/01 16:29:55 warmerda
- * move pabyRec into SHPInfo for thread safety
- *
- * Revision 1.33 2001/07/03 12:18:15 warmerda
- * Improved cleanup if SHX not found, provied by Riccardo Cohen.
- *
- * Revision 1.32 2001/06/22 01:58:07 warmerda
- * be more careful about establishing initial bounds in face of NULL shapes
- *
- * Revision 1.31 2001/05/31 19:35:29 warmerda
- * added support for writing null shapes
- *
- * Revision 1.30 2001/05/28 12:46:29 warmerda
- * Add some checking on reasonableness of record count when opening.
- *
- * Revision 1.29 2001/05/23 13:36:52 warmerda
- * added use of SHPAPI_CALL
- *
- * Revision 1.28 2001/02/06 22:25:06 warmerda
- * fixed memory leaks when SHPOpen() fails
- *
- * Revision 1.27 2000/07/18 15:21:33 warmerda
- * added better enforcement of -1 for append in SHPWriteObject
- *
- * Revision 1.26 2000/02/16 16:03:51 warmerda
- * added null shape support
- *
- * Revision 1.25 1999/12/15 13:47:07 warmerda
- * Fixed record size settings in .shp file (was 4 words too long)
- * Added stdlib.h.
- *
- * Revision 1.24 1999/11/05 14:12:04 warmerda
- * updated license terms
- *
- * Revision 1.23 1999/07/27 00:53:46 warmerda
- * added support for rewriting shapes
- *
- * Revision 1.22 1999/06/11 19:19:11 warmerda
- * Cleanup pabyRec static buffer on SHPClose().
- *
- * Revision 1.21 1999/06/02 14:57:56 kshih
- * Remove unused variables
- *
- * Revision 1.20 1999/04/19 21:04:17 warmerda
- * Fixed syntax error.
- *
- * Revision 1.19 1999/04/19 21:01:57 warmerda
- * Force access string to binary in SHPOpen().
- *
- * Revision 1.18 1999/04/01 18:48:07 warmerda
- * Try upper case extensions if lower case doesn't work.
- *
- * Revision 1.17 1998/12/31 15:29:39 warmerda
- * Disable writing measure values to multipatch objects if
- * DISABLE_MULTIPATCH_MEASURE is defined.
- *
- * Revision 1.16 1998/12/16 05:14:33 warmerda
- * Added support to write MULTIPATCH. Fixed reading Z coordinate of
- * MULTIPATCH. Fixed record size written for all feature types.
- *
- * Revision 1.15 1998/12/03 16:35:29 warmerda
- * r+b is proper binary access string, not rb+.
- *
- * Revision 1.14 1998/12/03 15:47:56 warmerda
- * Fixed setting of nVertices in SHPCreateObject().
- *
- * Revision 1.13 1998/12/03 15:33:54 warmerda
- * Made SHPCalculateExtents() separately callable.
- *
- * Revision 1.12 1998/11/11 20:01:50 warmerda
- * Fixed bug writing ArcM/Z, and PolygonM/Z for big endian machines.
- *
- * Revision 1.11 1998/11/09 20:56:44 warmerda
- * Fixed up handling of file wide bounds.
- *
- * Revision 1.10 1998/11/09 20:18:51 warmerda
- * Converted to support 3D shapefiles, and use of SHPObject.
- *
- * Revision 1.9 1998/02/24 15:09:05 warmerda
- * Fixed memory leak.
- *
- * Revision 1.8 1997/12/04 15:40:29 warmerda
- * Fixed byte swapping of record number, and record length fields in the
- * .shp file.
- *
- * Revision 1.7 1995/10/21 03:15:58 warmerda
- * Added support for binary file access, the magic cookie 9997
- * and tried to improve the int32 selection logic for 16bit systems.
- *
- * Revision 1.6 1995/09/04 04:19:41 warmerda
- * Added fix for file bounds.
- *
- * Revision 1.5 1995/08/25 15:16:44 warmerda
- * Fixed a couple of problems with big endian systems ... one with bounds
- * and the other with multipart polygons.
- *
- * Revision 1.4 1995/08/24 18:10:17 warmerda
- * Switch to use SfRealloc() to avoid problems with pre-ANSI realloc()
- * functions (such as on the Sun).
- *
- * Revision 1.3 1995/08/23 02:23:15 warmerda
- * Added support for reading bounds, and fixed up problems in setting the
- * file wide bounds.
- *
- * Revision 1.2 1995/08/04 03:16:57 warmerda
- * Added header.
- *
- */
-
-#include "shapefil.h"
-
-#include <math.h>
-#include <limits.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <glib.h>
-
-typedef unsigned char uchar;
-
-#if UINT_MAX == 65535
-typedef long int32;
-#else
-typedef int int32;
-#endif
-
-#ifndef FALSE
-# define FALSE 0
-# define TRUE 1
-#endif
-
-#define ByteCopy( a, b, c ) memcpy( b, a, c )
-#ifndef MAX
-# define MIN(a,b) ((a<b) ? a : b)
-# define MAX(a,b) ((a>b) ? a : b)
-#endif
-
-static int bBigEndian;
-
-
-/************************************************************************/
-/* SwapWord() */
-/* */
-/* Swap a 2, 4 or 8 byte word. */
-/************************************************************************/
-
-static void SwapWord( int length, void * wordP )
-
-{
- int i;
- uchar temp;
-
- for( i=0; i < length/2; i++ )
- {
- temp = ((uchar *) wordP)[i];
- ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1];
- ((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 == NULL )
- return( (void *) malloc(nNewSize) );
- else
- return( (void *) realloc(pMem,nNewSize) );
-}
-
-/************************************************************************/
-/* SHPWriteHeader() */
-/* */
-/* Write out a header for the .shp and .shx files as well as the */
-/* contents of the index (.shx) file. */
-/************************************************************************/
-
-void SHPWriteHeader( SHPHandle psSHP )
-
-{
- uchar abyHeader[100];
- int i;
- int32 i32;
- double dValue;
- int32 *panSHX;
-
- if (psSHP->fpSHX == NULL)
- {
- psSHP->sHooks.Error( "SHPWriteHeader failed : SHX file is closed");
- return;
- }
-
-/* -------------------------------------------------------------------- */
-/* Prepare header block for .shp file. */
-/* -------------------------------------------------------------------- */
- for( i = 0; i < 100; i++ )
- abyHeader[i] = 0;
-
- abyHeader[2] = 0x27; /* magic cookie */
- abyHeader[3] = 0x0a;
-
- i32 = psSHP->nFileSize/2; /* file size */
- ByteCopy( &i32, abyHeader+24, 4 );
- if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
-
- i32 = 1000; /* version */
- ByteCopy( &i32, abyHeader+28, 4 );
- if( bBigEndian ) SwapWord( 4, abyHeader+28 );
-
- i32 = psSHP->nShapeType; /* shape type */
- ByteCopy( &i32, abyHeader+32, 4 );
- if( bBigEndian ) SwapWord( 4, abyHeader+32 );
-
- dValue = psSHP->adBoundsMin[0]; /* set bounds */
- ByteCopy( &dValue, abyHeader+36, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+36 );
-
- dValue = psSHP->adBoundsMin[1];
- ByteCopy( &dValue, abyHeader+44, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+44 );
-
- dValue = psSHP->adBoundsMax[0];
- ByteCopy( &dValue, abyHeader+52, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+52 );
-
- dValue = psSHP->adBoundsMax[1];
- ByteCopy( &dValue, abyHeader+60, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+60 );
-
- dValue = psSHP->adBoundsMin[2]; /* z */
- ByteCopy( &dValue, abyHeader+68, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+68 );
-
- dValue = psSHP->adBoundsMax[2];
- ByteCopy( &dValue, abyHeader+76, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+76 );
-
- dValue = psSHP->adBoundsMin[3]; /* m */
- ByteCopy( &dValue, abyHeader+84, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+84 );
-
- dValue = psSHP->adBoundsMax[3];
- ByteCopy( &dValue, abyHeader+92, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+92 );
-
-/* -------------------------------------------------------------------- */
-/* Write .shp file header. */
-/* -------------------------------------------------------------------- */
- if( psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 0 ) != 0
- || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHP ) != 1 )
- {
- psSHP->sHooks.Error( "Failure writing .shp header" );
- return;
- }
-
-/* -------------------------------------------------------------------- */
-/* Prepare, and write .shx file header. */
-/* -------------------------------------------------------------------- */
- i32 = (psSHP->nRecords * 2 * sizeof(int32) + 100)/2; /* file size */
- ByteCopy( &i32, abyHeader+24, 4 );
- if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
-
- if( psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 0 ) != 0
- || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHX ) != 1 )
- {
- psSHP->sHooks.Error( "Failure writing .shx header" );
- return;
- }
-
-/* -------------------------------------------------------------------- */
-/* Write out the .shx contents. */
-/* -------------------------------------------------------------------- */
- panSHX = (int32 *) malloc(sizeof(int32) * 2 * psSHP->nRecords);
-
- for( 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( (int)psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX )
- != psSHP->nRecords )
- {
- psSHP->sHooks.Error( "Failure writing .shx contents" );
- }
-
- free( panSHX );
-
-/* -------------------------------------------------------------------- */
-/* Flush to disk. */
-/* -------------------------------------------------------------------- */
- psSHP->sHooks.FFlush( psSHP->fpSHP );
- psSHP->sHooks.FFlush( psSHP->fpSHX );
-}
-
-/************************************************************************/
-/* SHPOpen() */
-/************************************************************************/
-
-SHPHandle SHPAPI_CALL
-SHPOpen( const char * pszLayer, const char * pszAccess )
-
-{
- SAHooks sHooks;
-
- SASetupDefaultHooks( &sHooks );
-
- return SHPOpenLL( pszLayer, pszAccess, &sHooks );
-}
-
-/************************************************************************/
-/* SHPOpen() */
-/* */
-/* Open the .shp and .shx files based on the basename of the */
-/* files or either file name. */
-/************************************************************************/
-
-SHPHandle SHPAPI_CALL
-SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
-
-{
- char *pszFullname, *pszBasename;
- SHPHandle psSHP;
-
- uchar *pabyBuf;
- int i;
- double dValue;
-
-/* -------------------------------------------------------------------- */
-/* Ensure the access string is one of the legal ones. We */
-/* ensure the result string indicates binary to avoid common */
-/* problems on Windows. */
-/* -------------------------------------------------------------------- */
- if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
- || strcmp(pszAccess,"r+") == 0 )
- pszAccess = "r+b";
- else
- pszAccess = "rb";
-
-/* -------------------------------------------------------------------- */
-/* Establish the byte order on this machine. */
-/* -------------------------------------------------------------------- */
- i = 1;
- if( *((uchar *) &i) == 1 )
- bBigEndian = FALSE;
- else
- bBigEndian = TRUE;
-
-/* -------------------------------------------------------------------- */
-/* Initialize the info structure. */
-/* -------------------------------------------------------------------- */
- psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1);
-
- psSHP->bUpdated = FALSE;
- memcpy( &(psSHP->sHooks), psHooks, sizeof(SAHooks) );
-
-/* -------------------------------------------------------------------- */
-/* Compute the base (layer) name. If there is any extension */
-/* on the passed in filename we will strip it off. */
-/* -------------------------------------------------------------------- */
- pszBasename = (char *) malloc(strlen(pszLayer)+5);
- strcpy( pszBasename, pszLayer );
- for( i = strlen(pszBasename)-1;
- i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
- && pszBasename[i] != '\\';
- i-- ) {}
-
- if( pszBasename[i] == '.' )
- pszBasename[i] = '\0';
-
-/* -------------------------------------------------------------------- */
-/* Open the .shp and .shx files. Note that files pulled from */
-/* a PC to Unix with upper case filenames won't work! */
-/* -------------------------------------------------------------------- */
- pszFullname = (char *) malloc(strlen(pszBasename) + 5);
- sprintf( pszFullname, "%s.shp", pszBasename ) ;
- psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
- if( psSHP->fpSHP == NULL )
- {
- sprintf( pszFullname, "%s.SHP", pszBasename );
- psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
- }
-
- if( psSHP->fpSHP == NULL )
- {
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_OpenFailed,
- "Unable to open %s.shp or %s.SHP.",
- pszBasename, pszBasename );
-#endif
- free( psSHP );
- free( pszBasename );
- free( pszFullname );
- return( NULL );
- }
-
- sprintf( pszFullname, "%s.shx", pszBasename );
- psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
- if( psSHP->fpSHX == NULL )
- {
- sprintf( pszFullname, "%s.SHX", pszBasename );
- psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
- }
-
- if( psSHP->fpSHX == NULL )
- {
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_OpenFailed,
- "Unable to open %s.shx or %s.SHX.",
- pszBasename, pszBasename );
-#endif
- psSHP->sHooks.FClose( psSHP->fpSHP );
- free( psSHP );
- free( pszBasename );
- free( pszFullname );
- return( NULL );
- }
-
- free( pszFullname );
- free( pszBasename );
-
-/* -------------------------------------------------------------------- */
-/* Read the file size from the SHP file. */
-/* -------------------------------------------------------------------- */
- pabyBuf = (uchar *) malloc(100);
- psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP );
-
- psSHP->nFileSize = (pabyBuf[24] * 256 * 256 * 256
- + pabyBuf[25] * 256 * 256
- + pabyBuf[26] * 256
- + pabyBuf[27]) * 2;
-
-/* -------------------------------------------------------------------- */
-/* Read SHX file Header info */
-/* -------------------------------------------------------------------- */
- if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHX ) != 1
- || pabyBuf[0] != 0
- || pabyBuf[1] != 0
- || pabyBuf[2] != 0x27
- || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
- {
- psSHP->sHooks.Error( ".shx file is unreadable, or corrupt." );
- psSHP->sHooks.FClose( psSHP->fpSHP );
- psSHP->sHooks.FClose( psSHP->fpSHX );
- free( psSHP );
-
- return( NULL );
- }
-
- psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
- + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
- psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8;
-
- psSHP->nShapeType = pabyBuf[32];
-
- if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
- {
- char szError[200];
-
- sprintf( szError,
- "Record count in .shp header is %d, which seems\n"
- "unreasonable. Assuming header is corrupt.",
- psSHP->nRecords );
- psSHP->sHooks.Error( szError );
- psSHP->sHooks.FClose( psSHP->fpSHP );
- psSHP->sHooks.FClose( psSHP->fpSHX );
- free( psSHP );
- free(pabyBuf);
-
- return( NULL );
- }
-
-/* -------------------------------------------------------------------- */
-/* Read the bounds. */
-/* -------------------------------------------------------------------- */
- if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
- memcpy( &dValue, pabyBuf+36, 8 );
- psSHP->adBoundsMin[0] = dValue;
-
- if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
- memcpy( &dValue, pabyBuf+44, 8 );
- psSHP->adBoundsMin[1] = dValue;
-
- if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
- memcpy( &dValue, pabyBuf+52, 8 );
- psSHP->adBoundsMax[0] = dValue;
-
- if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
- memcpy( &dValue, pabyBuf+60, 8 );
- psSHP->adBoundsMax[1] = dValue;
-
- if( bBigEndian ) SwapWord( 8, pabyBuf+68 ); /* z */
- memcpy( &dValue, pabyBuf+68, 8 );
- psSHP->adBoundsMin[2] = dValue;
-
- if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
- memcpy( &dValue, pabyBuf+76, 8 );
- psSHP->adBoundsMax[2] = dValue;
-
- if( bBigEndian ) SwapWord( 8, pabyBuf+84 ); /* z */
- memcpy( &dValue, pabyBuf+84, 8 );
- psSHP->adBoundsMin[3] = dValue;
-
- if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
- memcpy( &dValue, pabyBuf+92, 8 );
- psSHP->adBoundsMax[3] = dValue;
-
- free( pabyBuf );
-
-/* -------------------------------------------------------------------- */
-/* Read the .shx file to get the offsets to each record in */
-/* the .shp file. */
-/* -------------------------------------------------------------------- */
- psSHP->nMaxRecords = psSHP->nRecords;
-
- psSHP->panRecOffset =
- (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
- psSHP->panRecSize =
- (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
- pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
-
- if (psSHP->panRecOffset == NULL ||
- psSHP->panRecSize == NULL ||
- pabyBuf == NULL)
- {
- char szError[200];
-
- sprintf(szError,
- "Not enough memory to allocate requested memory (nRecords=%d).\n"
- "Probably broken SHP file",
- psSHP->nRecords );
- psSHP->sHooks.Error( szError );
- psSHP->sHooks.FClose( psSHP->fpSHP );
- psSHP->sHooks.FClose( psSHP->fpSHX );
- if (psSHP->panRecOffset) free( psSHP->panRecOffset );
- if (psSHP->panRecSize) free( psSHP->panRecSize );
- if (pabyBuf) free( pabyBuf );
- free( psSHP );
- return( NULL );
- }
-
- if( (int) psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX )
- != psSHP->nRecords )
- {
- char szError[200];
-
- sprintf( szError,
- "Failed to read all values for %d records in .shx file.",
- psSHP->nRecords );
- psSHP->sHooks.Error( szError );
-
- /* SHX is short or unreadable for some reason. */
- psSHP->sHooks.FClose( psSHP->fpSHP );
- psSHP->sHooks.FClose( psSHP->fpSHX );
- free( psSHP->panRecOffset );
- free( psSHP->panRecSize );
- free( pabyBuf );
- free( psSHP );
-
- return( NULL );
- }
-
- /* In read-only mode, we can close the SHX now */
- if (strcmp(pszAccess, "rb") == 0)
- {
- psSHP->sHooks.FClose( psSHP->fpSHX );
- psSHP->fpSHX = NULL;
- }
-
- for( i = 0; i < psSHP->nRecords; i++ )
- {
- int32 nOffset, nLength;
-
- memcpy( &nOffset, pabyBuf + i * 8, 4 );
- if( !bBigEndian ) SwapWord( 4, &nOffset );
-
- memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
- if( !bBigEndian ) SwapWord( 4, &nLength );
-
- psSHP->panRecOffset[i] = nOffset*2;
- psSHP->panRecSize[i] = nLength*2;
- }
- free( pabyBuf );
-
- return( psSHP );
-}
-
-/************************************************************************/
-/* SHPClose() */
-/* */
-/* Close the .shp and .shx files. */
-/************************************************************************/
-
-void SHPAPI_CALL
-SHPClose(SHPHandle psSHP )
-
-{
- if( psSHP == NULL )
- return;
-
-/* -------------------------------------------------------------------- */
-/* Update the header if we have modified anything. */
-/* -------------------------------------------------------------------- */
- if( psSHP->bUpdated )
- SHPWriteHeader( psSHP );
-
-/* -------------------------------------------------------------------- */
-/* Free all resources, and close files. */
-/* -------------------------------------------------------------------- */
- free( psSHP->panRecOffset );
- free( psSHP->panRecSize );
-
- if ( psSHP->fpSHX != NULL)
- psSHP->sHooks.FClose( psSHP->fpSHX );
- psSHP->sHooks.FClose( psSHP->fpSHP );
-
- if( psSHP->pabyRec != NULL )
- {
- free( psSHP->pabyRec );
- }
-
- free( psSHP );
-}
-
-/************************************************************************/
-/* SHPGetInfo() */
-/* */
-/* Fetch general information about the shape file. */
-/************************************************************************/
-
-void SHPAPI_CALL
-SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
- double * padfMinBound, double * padfMaxBound )
-
-{
- int i;
-
- if( psSHP == NULL )
- return;
-
- if( pnEntities != NULL )
- *pnEntities = psSHP->nRecords;
-
- if( pnShapeType != NULL )
- *pnShapeType = psSHP->nShapeType;
-
- for( i = 0; i < 4; i++ )
- {
- if( padfMinBound != NULL )
- padfMinBound[i] = psSHP->adBoundsMin[i];
- if( padfMaxBound != NULL )
- padfMaxBound[i] = psSHP->adBoundsMax[i];
- }
-}
-
-/************************************************************************/
-/* SHPCreate() */
-/* */
-/* Create a new shape file and return a handle to the open */
-/* shape file with read/write access. */
-/************************************************************************/
-
-SHPHandle SHPAPI_CALL
-SHPCreate( const char * pszLayer, int nShapeType )
-
-{
- SAHooks sHooks;
-
- SASetupDefaultHooks( &sHooks );
-
- return SHPCreateLL( pszLayer, nShapeType, &sHooks );
-}
-
-/************************************************************************/
-/* SHPCreate() */
-/* */
-/* Create a new shape file and return a handle to the open */
-/* shape file with read/write access. */
-/************************************************************************/
-
-SHPHandle SHPAPI_CALL
-SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
-
-{
- char *pszBasename, *pszFullname;
- int i;
- SAFile fpSHP, fpSHX;
- uchar abyHeader[100];
- int32 i32;
- double dValue;
-
-/* -------------------------------------------------------------------- */
-/* Establish the byte order on this system. */
-/* -------------------------------------------------------------------- */
- i = 1;
- if( *((uchar *) &i) == 1 )
- bBigEndian = FALSE;
- else
- bBigEndian = TRUE;
-
-/* -------------------------------------------------------------------- */
-/* Compute the base (layer) name. If there is any extension */
-/* on the passed in filename we will strip it off. */
-/* -------------------------------------------------------------------- */
- pszBasename = (char *) malloc(strlen(pszLayer)+5);
- strcpy( pszBasename, pszLayer );
- for( i = strlen(pszBasename)-1;
- i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
- && pszBasename[i] != '\\';
- i-- ) {}
-
- if( pszBasename[i] == '.' )
- pszBasename[i] = '\0';
-
-/* -------------------------------------------------------------------- */
-/* Open the two files so we can write their headers. */
-/* -------------------------------------------------------------------- */
- pszFullname = (char *) malloc(strlen(pszBasename) + 5);
- sprintf( pszFullname, "%s.shp", pszBasename );
- fpSHP = psHooks->FOpen(pszFullname, "wb" );
- if( fpSHP == NULL )
- {
- psHooks->Error( "Failed to create file .shp file." );
- return( NULL );
- }
-
- sprintf( pszFullname, "%s.shx", pszBasename );
- fpSHX = psHooks->FOpen(pszFullname, "wb" );
- if( fpSHX == NULL )
- {
- psHooks->Error( "Failed to create file .shx file." );
- return( NULL );
- }
-
- free( pszFullname );
- free( pszBasename );
-
-/* -------------------------------------------------------------------- */
-/* Prepare header block for .shp file. */
-/* -------------------------------------------------------------------- */
- for( i = 0; i < 100; i++ )
- abyHeader[i] = 0;
-
- abyHeader[2] = 0x27; /* magic cookie */
- abyHeader[3] = 0x0a;
-
- i32 = 50; /* file size */
- ByteCopy( &i32, abyHeader+24, 4 );
- if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
-
- i32 = 1000; /* version */
- ByteCopy( &i32, abyHeader+28, 4 );
- if( bBigEndian ) SwapWord( 4, abyHeader+28 );
-
- i32 = nShapeType; /* shape type */
- ByteCopy( &i32, abyHeader+32, 4 );
- if( bBigEndian ) SwapWord( 4, abyHeader+32 );
-
- dValue = 0.0; /* set bounds */
- ByteCopy( &dValue, abyHeader+36, 8 );
- ByteCopy( &dValue, abyHeader+44, 8 );
- ByteCopy( &dValue, abyHeader+52, 8 );
- ByteCopy( &dValue, abyHeader+60, 8 );
-
-/* -------------------------------------------------------------------- */
-/* Write .shp file header. */
-/* -------------------------------------------------------------------- */
- if( psHooks->FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
- {
- psHooks->Error( "Failed to write .shp header." );
- return NULL;
- }
-
-/* -------------------------------------------------------------------- */
-/* Prepare, and write .shx file header. */
-/* -------------------------------------------------------------------- */
- i32 = 50; /* file size */
- ByteCopy( &i32, abyHeader+24, 4 );
- if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
-
- if( psHooks->FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
- {
- psHooks->Error( "Failed to write .shx header." );
- return NULL;
- }
-
-/* -------------------------------------------------------------------- */
-/* Close the files, and then open them as regular existing files. */
-/* -------------------------------------------------------------------- */
- psHooks->FClose( fpSHP );
- psHooks->FClose( fpSHX );
-
- return( SHPOpenLL( pszLayer, "r+b", psHooks ) );
-}
-
-/************************************************************************/
-/* _SHPSetBounds() */
-/* */
-/* Compute a bounds rectangle for a shape, and set it into the */
-/* indicated location in the record. */
-/************************************************************************/
-
-static void _SHPSetBounds( uchar * pabyRec, 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 );
- }
-}
-
-/************************************************************************/
-/* SHPComputeExtents() */
-/* */
-/* Recompute the extents of a shape. Automatically done by */
-/* SHPCreateObject(). */
-/************************************************************************/
-
-void SHPAPI_CALL
-SHPComputeExtents( SHPObject * psObject )
-
-{
- int i;
-
-/* -------------------------------------------------------------------- */
-/* Build extents for this object. */
-/* -------------------------------------------------------------------- */
- if( psObject->nVertices > 0 )
- {
- psObject->dfXMin = psObject->dfXMax = psObject->padfX[0];
- psObject->dfYMin = psObject->dfYMax = psObject->padfY[0];
- psObject->dfZMin = psObject->dfZMax = psObject->padfZ[0];
- psObject->dfMMin = psObject->dfMMax = psObject->padfM[0];
- }
-
- for( i = 0; i < psObject->nVertices; i++ )
- {
- psObject->dfXMin = MIN(psObject->dfXMin, psObject->padfX[i]);
- psObject->dfYMin = MIN(psObject->dfYMin, psObject->padfY[i]);
- psObject->dfZMin = MIN(psObject->dfZMin, psObject->padfZ[i]);
- psObject->dfMMin = MIN(psObject->dfMMin, psObject->padfM[i]);
-
- psObject->dfXMax = MAX(psObject->dfXMax, psObject->padfX[i]);
- psObject->dfYMax = MAX(psObject->dfYMax, psObject->padfY[i]);
- psObject->dfZMax = MAX(psObject->dfZMax, psObject->padfZ[i]);
- psObject->dfMMax = MAX(psObject->dfMMax, psObject->padfM[i]);
- }
-}
-
-/************************************************************************/
-/* SHPCreateObject() */
-/* */
-/* Create a shape object. It should be freed with */
-/* SHPDestroyObject(). */
-/************************************************************************/
-
-SHPObject SHPAPI_CALL1(*)
-SHPCreateObject( int nSHPType, int nShapeId, int nParts,
- const int * panPartStart, const int * panPartType,
- int nVertices, const double *padfX, const double *padfY,
- const double * padfZ, const double * padfM )
-
-{
- SHPObject *psObject;
- int i, bHasM, bHasZ;
-
- psObject = (SHPObject *) calloc(1,sizeof(SHPObject));
- psObject->nSHPType = nSHPType;
- psObject->nShapeId = nShapeId;
- psObject->bMeasureIsUsed = FALSE;
-
-/* -------------------------------------------------------------------- */
-/* Establish whether this shape type has M, and Z values. */
-/* -------------------------------------------------------------------- */
- if( nSHPType == SHPT_ARCM
- || nSHPType == SHPT_POINTM
- || nSHPType == SHPT_POLYGONM
- || nSHPType == SHPT_MULTIPOINTM )
- {
- bHasM = TRUE;
- bHasZ = FALSE;
- }
- else if( nSHPType == SHPT_ARCZ
- || nSHPType == SHPT_POINTZ
- || nSHPType == SHPT_POLYGONZ
- || nSHPType == SHPT_MULTIPOINTZ
- || nSHPType == SHPT_MULTIPATCH )
- {
- bHasM = TRUE;
- bHasZ = TRUE;
- }
- else
- {
- bHasM = FALSE;
- bHasZ = FALSE;
- }
-
-/* -------------------------------------------------------------------- */
-/* Capture parts. Note that part type is optional, and */
-/* defaults to ring. */
-/* -------------------------------------------------------------------- */
- if( nSHPType == SHPT_ARC || nSHPType == SHPT_POLYGON
- || nSHPType == SHPT_ARCM || nSHPType == SHPT_POLYGONM
- || nSHPType == SHPT_ARCZ || nSHPType == SHPT_POLYGONZ
- || nSHPType == SHPT_MULTIPATCH )
- {
- psObject->nParts = MAX(1,nParts);
-
- psObject->panPartStart = (int *)
- malloc(sizeof(int) * psObject->nParts);
- psObject->panPartType = (int *)
- malloc(sizeof(int) * psObject->nParts);
-
- psObject->panPartStart[0] = 0;
- psObject->panPartType[0] = SHPP_RING;
-
- for( i = 0; i < nParts; i++ )
- {
- psObject->panPartStart[i] = panPartStart[i];
-
- if( panPartType != NULL )
- psObject->panPartType[i] = panPartType[i];
- else
- psObject->panPartType[i] = SHPP_RING;
- }
-
- if( psObject->panPartStart[0] != 0 )
- psObject->panPartStart[0] = 0;
- }
-
-/* -------------------------------------------------------------------- */
-/* Capture vertices. Note that Z and M are optional, but X and */
-/* Y are not. */
-/* -------------------------------------------------------------------- */
- if( nVertices > 0 )
- {
- psObject->padfX = (double *) calloc(sizeof(double),nVertices);
- psObject->padfY = (double *) calloc(sizeof(double),nVertices);
- psObject->padfZ = (double *) calloc(sizeof(double),nVertices);
- psObject->padfM = (double *) calloc(sizeof(double),nVertices);
-
- assert( padfX != NULL );
- assert( padfY != NULL );
-
- for( i = 0; i < nVertices; i++ )
- {
- psObject->padfX[i] = padfX[i];
- psObject->padfY[i] = padfY[i];
- if( padfZ != NULL && bHasZ )
- psObject->padfZ[i] = padfZ[i];
- if( padfM != NULL && bHasM )
- psObject->padfM[i] = padfM[i];
- }
- if( padfM != NULL && bHasM )
- psObject->bMeasureIsUsed = TRUE;
- }
-
-/* -------------------------------------------------------------------- */
-/* Compute the extents. */
-/* -------------------------------------------------------------------- */
- psObject->nVertices = nVertices;
- SHPComputeExtents( psObject );
-
- return( psObject );
-}
-
-/************************************************************************/
-/* SHPCreateSimpleObject() */
-/* */
-/* Create a simple (common) shape object. Destroy with */
-/* SHPDestroyObject(). */
-/************************************************************************/
-
-SHPObject SHPAPI_CALL1(*)
-SHPCreateSimpleObject( int nSHPType, int nVertices,
- const double * padfX, const double * padfY,
- const double * padfZ )
-
-{
- return( SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
- nVertices, padfX, padfY, padfZ, NULL ) );
-}
-
-/************************************************************************/
-/* SHPWriteObject() */
-/* */
-/* Write out the vertices of a new structure. Note that it is */
-/* only possible to write vertices at the end of the file. */
-/************************************************************************/
-
-int SHPAPI_CALL
-SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
-
-{
- int nRecordOffset, i, nRecordSize=0;
- uchar *pabyRec;
- int32 i32;
-
- psSHP->bUpdated = TRUE;
-
-/* -------------------------------------------------------------------- */
-/* Ensure that shape object matches the type of the file it is */
-/* being written to. */
-/* -------------------------------------------------------------------- */
- assert( psObject->nSHPType == psSHP->nShapeType
- || psObject->nSHPType == SHPT_NULL );
-
-/* -------------------------------------------------------------------- */
-/* Ensure that -1 is used for appends. Either blow an */
-/* assertion, or if they are disabled, set the shapeid to -1 */
-/* for appends. */
-/* -------------------------------------------------------------------- */
- assert( nShapeId == -1
- || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
-
- if( nShapeId != -1 && nShapeId >= psSHP->nRecords )
- nShapeId = -1;
-
-/* -------------------------------------------------------------------- */
-/* Add the new entity to the in memory index. */
-/* -------------------------------------------------------------------- */
- if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
- {
- psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
-
- psSHP->panRecOffset = (int *)
- SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords );
- psSHP->panRecSize = (int *)
- SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords );
- }
-
-/* -------------------------------------------------------------------- */
-/* Initialize record. */
-/* -------------------------------------------------------------------- */
- pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double)
- + psObject->nParts * 8 + 128);
-
-/* -------------------------------------------------------------------- */
-/* Extract vertices for a Polygon or Arc. */
-/* -------------------------------------------------------------------- */
- if( psObject->nSHPType == SHPT_POLYGON
- || psObject->nSHPType == SHPT_POLYGONZ
- || psObject->nSHPType == SHPT_POLYGONM
- || psObject->nSHPType == SHPT_ARC
- || psObject->nSHPType == SHPT_ARCZ
- || psObject->nSHPType == SHPT_ARCM
- || psObject->nSHPType == SHPT_MULTIPATCH )
- {
- int32 nPoints, nParts;
- int i;
-
- nPoints = psObject->nVertices;
- nParts = psObject->nParts;
-
- _SHPSetBounds( pabyRec + 12, psObject );
-
- if( bBigEndian ) SwapWord( 4, &nPoints );
- if( bBigEndian ) SwapWord( 4, &nParts );
-
- ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
- ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
-
- nRecordSize = 52;
-
- /*
- * Write part start positions.
- */
- ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
- 4 * psObject->nParts );
- for( i = 0; i < psObject->nParts; i++ )
- {
- if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
- nRecordSize += 4;
- }
-
- /*
- * Write multipatch part types if needed.
- */
- if( psObject->nSHPType == SHPT_MULTIPATCH )
- {
- memcpy( pabyRec + nRecordSize, psObject->panPartType,
- 4*psObject->nParts );
- for( i = 0; i < psObject->nParts; i++ )
- {
- if( bBigEndian ) SwapWord( 4, pabyRec + nRecordSize );
- nRecordSize += 4;
- }
- }
-
- /*
- * Write the (x,y) vertex values.
- */
- for( i = 0; i < psObject->nVertices; i++ )
- {
- 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 );
-
- nRecordSize += 2 * 8;
- }
-
- /*
- * Write the Z coordinates (if any).
- */
- if( psObject->nSHPType == SHPT_POLYGONZ
- || psObject->nSHPType == SHPT_ARCZ
- || psObject->nSHPType == SHPT_MULTIPATCH )
- {
- ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
-
- ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
-
- for( i = 0; i < psObject->nVertices; i++ )
- {
- ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
- }
- }
-
- /*
- * Write the M values, if any.
- */
- if( psObject->bMeasureIsUsed
- && (psObject->nSHPType == SHPT_POLYGONM
- || psObject->nSHPType == SHPT_ARCM
-#ifndef DISABLE_MULTIPATCH_MEASURE
- || psObject->nSHPType == SHPT_MULTIPATCH
-#endif
- || psObject->nSHPType == SHPT_POLYGONZ
- || psObject->nSHPType == SHPT_ARCZ) )
- {
- ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
-
- ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
-
- for( i = 0; i < psObject->nVertices; i++ )
- {
- ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
- }
- }
- }
-
-/* -------------------------------------------------------------------- */
-/* Extract vertices for a MultiPoint. */
-/* -------------------------------------------------------------------- */
- else if( psObject->nSHPType == SHPT_MULTIPOINT
- || psObject->nSHPType == SHPT_MULTIPOINTZ
- || psObject->nSHPType == SHPT_MULTIPOINTM )
- {
- int32 nPoints;
- int i;
-
- nPoints = psObject->nVertices;
-
- _SHPSetBounds( pabyRec + 12, psObject );
-
- if( bBigEndian ) SwapWord( 4, &nPoints );
- ByteCopy( &nPoints, pabyRec + 44, 4 );
-
- for( 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 );
- }
-
- nRecordSize = 48 + 16 * psObject->nVertices;
-
- if( psObject->nSHPType == SHPT_MULTIPOINTZ )
- {
- ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
-
- ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
-
- for( i = 0; i < psObject->nVertices; i++ )
- {
- ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
- }
- }
-
- if( psObject->bMeasureIsUsed
- && (psObject->nSHPType == SHPT_MULTIPOINTZ
- || psObject->nSHPType == SHPT_MULTIPOINTM) )
- {
- ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
-
- ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
-
- for( i = 0; i < psObject->nVertices; i++ )
- {
- ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- nRecordSize += 8;
- }
- }
- }
-
-/* -------------------------------------------------------------------- */
-/* Write point. */
-/* -------------------------------------------------------------------- */
- else if( psObject->nSHPType == SHPT_POINT
- || psObject->nSHPType == SHPT_POINTZ
- || psObject->nSHPType == SHPT_POINTM )
- {
- ByteCopy( psObject->padfX, pabyRec + 12, 8 );
- ByteCopy( psObject->padfY, pabyRec + 20, 8 );
-
- if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
- if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
-
- nRecordSize = 28;
-
- if( psObject->nSHPType == SHPT_POINTZ )
- {
- ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
- 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 );
- nRecordSize += 8;
- }
- }
-
-/* -------------------------------------------------------------------- */
-/* Not much to do for null geometries. */
-/* -------------------------------------------------------------------- */
- else if( psObject->nSHPType == SHPT_NULL )
- {
- nRecordSize = 12;
- }
-
- else
- {
- /* unknown type */
- assert( FALSE );
- }
-
-/* -------------------------------------------------------------------- */
-/* Establish where we are going to put this record. If we are */
-/* rewriting and existing record, and it will fit, then put it */
-/* back where the original came from. Otherwise write at the end. */
-/* -------------------------------------------------------------------- */
- if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
- {
- if( nShapeId == -1 )
- nShapeId = psSHP->nRecords++;
-
- psSHP->panRecOffset[nShapeId] = nRecordOffset = psSHP->nFileSize;
- psSHP->panRecSize[nShapeId] = nRecordSize-8;
- psSHP->nFileSize += nRecordSize;
- }
- else
- {
- nRecordOffset = psSHP->panRecOffset[nShapeId];
- psSHP->panRecSize[nShapeId] = nRecordSize-8;
- }
-
-/* -------------------------------------------------------------------- */
-/* Set the shape type, record number, and record size. */
-/* -------------------------------------------------------------------- */
- i32 = nShapeId+1; /* record # */
- if( !bBigEndian ) SwapWord( 4, &i32 );
- ByteCopy( &i32, pabyRec, 4 );
-
- i32 = (nRecordSize-8)/2; /* record size */
- if( !bBigEndian ) SwapWord( 4, &i32 );
- ByteCopy( &i32, pabyRec + 4, 4 );
-
- i32 = psObject->nSHPType; /* shape type */
- if( bBigEndian ) SwapWord( 4, &i32 );
- ByteCopy( &i32, pabyRec + 8, 4 );
-
-/* -------------------------------------------------------------------- */
-/* Write out record. */
-/* -------------------------------------------------------------------- */
- if( psSHP->sHooks.FSeek( psSHP->fpSHP, nRecordOffset, 0 ) != 0
- || psSHP->sHooks.FWrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
- {
- psSHP->sHooks.Error( "Error in psSHP->sHooks.FSeek() or fwrite() writing object to .shp file." );
- free( pabyRec );
- return -1;
- }
-
- free( pabyRec );
-
-/* -------------------------------------------------------------------- */
-/* Expand file wide bounds based on this shape. */
-/* -------------------------------------------------------------------- */
- if( psSHP->adBoundsMin[0] == 0.0
- && psSHP->adBoundsMax[0] == 0.0
- && psSHP->adBoundsMin[1] == 0.0
- && psSHP->adBoundsMax[1] == 0.0 )
- {
- if( psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0 )
- {
- psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = 0.0;
- psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = 0.0;
- psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = 0.0;
- psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = 0.0;
- }
- else
- {
- psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
- psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
- psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
- psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
- }
- }
-
- for( i = 0; i < psObject->nVertices; i++ )
- {
- psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
- psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
- psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
- psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
- psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
- psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
- psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
- psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
- }
-
- return( nShapeId );
-}
-
-/************************************************************************/
-/* SHPReadObject() */
-/* */
-/* Read the vertices, parts, and other non-attribute information */
-/* for one shape. */
-/************************************************************************/
-
-SHPObject SHPAPI_CALL1(*)
-SHPReadObject( SHPHandle psSHP, int hEntity )
-
-{
- int nEntitySize, nRequiredSize;
- SHPObject *psShape;
- char pszErrorMsg[128];
-
-/* -------------------------------------------------------------------- */
-/* Validate the record/entity number. */
-/* -------------------------------------------------------------------- */
- if( hEntity < 0 || hEntity >= psSHP->nRecords )
- return( NULL );
-
-/* -------------------------------------------------------------------- */
-/* Ensure our record buffer is large enough. */
-/* -------------------------------------------------------------------- */
- nEntitySize = psSHP->panRecSize[hEntity]+8;
- if( nEntitySize > psSHP->nBufSize )
- {
- psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,nEntitySize);
- if (psSHP->pabyRec == NULL)
- {
- char szError[200];
-
- /* Reallocate previous successfull size for following features */
- psSHP->pabyRec = malloc(psSHP->nBufSize);
-
- sprintf( szError,
- "Not enough memory to allocate requested memory (nBufSize=%d). "
- "Probably broken SHP file", psSHP->nBufSize );
- psSHP->sHooks.Error( szError );
- return NULL;
- }
-
- /* Only set new buffer size after successfull alloc */
- psSHP->nBufSize = nEntitySize;
- }
-
- /* In case we were not able to reallocate the buffer on a previous step */
- if (psSHP->pabyRec == NULL)
- {
- return NULL;
- }
-
-/* -------------------------------------------------------------------- */
-/* Read the record. */
-/* -------------------------------------------------------------------- */
- if( psSHP->sHooks.FSeek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0
- || psSHP->sHooks.FRead( psSHP->pabyRec, nEntitySize, 1,
- psSHP->fpSHP ) != 1 )
- {
- /*
- * TODO - mloskot: Consider detailed diagnostics of shape file,
- * for example to detect if file is truncated.
- */
-
- psSHP->sHooks.Error( "Error in fseek() or fread() reading object from .shp file." );
- return NULL;
- }
-
-/* -------------------------------------------------------------------- */
-/* Allocate and minimally initialize the object. */
-/* -------------------------------------------------------------------- */
- psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
- psShape->nShapeId = hEntity;
- psShape->bMeasureIsUsed = FALSE;
-
- if ( 8 + 4 > nEntitySize )
- {
- g_snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
- hEntity, nEntitySize);
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
- memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 );
-
- if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
-
-/* ==================================================================== */
-/* Extract vertices for a Polygon or Arc. */
-/* ==================================================================== */
- if( psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC
- || psShape->nSHPType == SHPT_POLYGONZ
- || psShape->nSHPType == SHPT_POLYGONM
- || psShape->nSHPType == SHPT_ARCZ
- || psShape->nSHPType == SHPT_ARCM
- || psShape->nSHPType == SHPT_MULTIPATCH )
- {
- int32 nPoints, nParts;
- int i, nOffset;
-
- if ( 40 + 8 + 4 > nEntitySize )
- {
- g_snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
- hEntity, nEntitySize);
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
-/* -------------------------------------------------------------------- */
-/* 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) );
-
-/* -------------------------------------------------------------------- */
-/* Extract part/point count, and build vertex and part arrays */
-/* to proper size. */
-/* -------------------------------------------------------------------- */
- memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
- memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
-
- if( bBigEndian ) SwapWord( 4, &nPoints );
- if( bBigEndian ) SwapWord( 4, &nParts );
-
- if (nPoints < 0 || nParts < 0 ||
- nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
- {
- g_snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d.",
- hEntity, nPoints, nParts);
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
-
- /* With the previous checks on nPoints and nParts, */
- /* we should not overflow here and after */
- /* since 50 M * (16 + 8 + 8) = 1 600 MB */
- nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
- if ( psShape->nSHPType == SHPT_POLYGONZ
- || psShape->nSHPType == SHPT_ARCZ
- || psShape->nSHPType == SHPT_MULTIPATCH )
- {
- nRequiredSize += 16 + 8 * nPoints;
- }
- if( psShape->nSHPType == SHPT_MULTIPATCH )
- {
- nRequiredSize += 4 * nParts;
- }
- if (nRequiredSize > nEntitySize)
- {
- g_snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d, nEntitySize=%d.",
- hEntity, nPoints, nParts, nEntitySize);
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
-
- psShape->nVertices = nPoints;
- psShape->padfX = (double *) calloc(nPoints,sizeof(double));
- psShape->padfY = (double *) calloc(nPoints,sizeof(double));
- psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
- psShape->padfM = (double *) calloc(nPoints,sizeof(double));
-
- psShape->nParts = nParts;
- psShape->panPartStart = (int *) calloc(nParts,sizeof(int));
- psShape->panPartType = (int *) calloc(nParts,sizeof(int));
-
- if (psShape->padfX == NULL ||
- psShape->padfY == NULL ||
- psShape->padfZ == NULL ||
- psShape->padfM == NULL ||
- psShape->panPartStart == NULL ||
- psShape->panPartType == NULL)
- {
- g_snprintf(pszErrorMsg, 128,
- "Not enough memory to allocate requested memory (nPoints=%d, nParts=%d) for shape %d. "
- "Probably broken SHP file", hEntity, nPoints, nParts );
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
-
- for( i = 0; i < nParts; i++ )
- psShape->panPartType[i] = SHPP_RING;
-
-/* -------------------------------------------------------------------- */
-/* Copy out the part array from the record. */
-/* -------------------------------------------------------------------- */
- memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
- for( i = 0; i < nParts; i++ )
- {
- if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
-
- /* We check that the offset is inside the vertex array */
- if (psShape->panPartStart[i] < 0 ||
- psShape->panPartStart[i] >= psShape->nVertices)
- {
- g_snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
- hEntity, i, psShape->panPartStart[i], psShape->nVertices);
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
- if (i > 0 && psShape->panPartStart[i] <= psShape->panPartStart[i-1])
- {
- g_snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
- hEntity, i, psShape->panPartStart[i], i - 1, psShape->panPartStart[i - 1]);
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
- }
-
- nOffset = 44 + 8 + 4*nParts;
-
-/* -------------------------------------------------------------------- */
-/* If this is a multipatch, we will also have parts types. */
-/* -------------------------------------------------------------------- */
- if( psShape->nSHPType == SHPT_MULTIPATCH )
- {
- memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
- for( i = 0; i < nParts; i++ )
- {
- if( bBigEndian ) SwapWord( 4, psShape->panPartType+i );
- }
-
- nOffset += 4*nParts;
- }
-
-/* -------------------------------------------------------------------- */
-/* Copy out the vertices from the record. */
-/* -------------------------------------------------------------------- */
- for( i = 0; i < nPoints; i++ )
- {
- 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 );
- }
-
- nOffset += 16*nPoints;
-
-/* -------------------------------------------------------------------- */
-/* If we have a Z coordinate, collect that now. */
-/* -------------------------------------------------------------------- */
- 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( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
-
- for( i = 0; i < nPoints; i++ )
- {
- memcpy( psShape->padfZ + i,
- psSHP->pabyRec + nOffset + 16 + i*8, 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
- }
-
- nOffset += 16 + 8*nPoints;
- }
-
-/* -------------------------------------------------------------------- */
-/* If we have a M measure value, then read it now. We assume */
-/* that the measure can be present for any shape if the size is */
-/* big enough, but really it will only occur for the Z shapes */
-/* (options), and the M shapes. */
-/* -------------------------------------------------------------------- */
- if( nEntitySize >= 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) );
-
- for( i = 0; i < nPoints; i++ )
- {
- memcpy( psShape->padfM + i,
- psSHP->pabyRec + nOffset + 16 + i*8, 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
- }
- psShape->bMeasureIsUsed = TRUE;
- }
- }
-
-/* ==================================================================== */
-/* Extract vertices for a MultiPoint. */
-/* ==================================================================== */
- else if( psShape->nSHPType == SHPT_MULTIPOINT
- || psShape->nSHPType == SHPT_MULTIPOINTM
- || psShape->nSHPType == SHPT_MULTIPOINTZ )
- {
- int32 nPoints;
- int i, nOffset;
-
- if ( 44 + 4 > nEntitySize )
- {
- g_snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
- hEntity, nEntitySize);
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
- memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
-
- if( bBigEndian ) SwapWord( 4, &nPoints );
-
- if (nPoints < 0 || nPoints > 50 * 1000 * 1000)
- {
- g_snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nPoints = %d",
- hEntity, nPoints);
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
-
- nRequiredSize = 48 + nPoints * 16;
- if( psShape->nSHPType == SHPT_MULTIPOINTZ )
- {
- nRequiredSize += 16 + nPoints * 8;
- }
- if (nRequiredSize > nEntitySize)
- {
- g_snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d",
- hEntity, nPoints, nEntitySize);
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
-
- psShape->nVertices = nPoints;
- psShape->padfX = (double *) calloc(nPoints,sizeof(double));
- psShape->padfY = (double *) calloc(nPoints,sizeof(double));
- psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
- psShape->padfM = (double *) calloc(nPoints,sizeof(double));
-
- if (psShape->padfX == NULL ||
- psShape->padfY == NULL ||
- psShape->padfZ == NULL ||
- psShape->padfM == NULL)
- {
- g_snprintf(pszErrorMsg, 128,
- "Not enough memory to allocate requested memory (nPoints=%d) for shape %d. "
- "Probably broken SHP file", hEntity, nPoints );
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
-
- for( i = 0; i < nPoints; i++ )
- {
- 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 );
- }
-
- nOffset = 48 + 16*nPoints;
-
-/* -------------------------------------------------------------------- */
-/* 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 we have a Z coordinate, collect that now. */
-/* -------------------------------------------------------------------- */
- 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) );
-
- for( i = 0; i < nPoints; i++ )
- {
- memcpy( psShape->padfZ + i,
- psSHP->pabyRec + nOffset + 16 + i*8, 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
- }
-
- nOffset += 16 + 8*nPoints;
- }
-
-/* -------------------------------------------------------------------- */
-/* If we have a M measure value, then read it now. We assume */
-/* that the measure can be present for any shape if the size is */
-/* big enough, but really it will only occur for the Z shapes */
-/* (options), and the M shapes. */
-/* -------------------------------------------------------------------- */
- if( nEntitySize >= 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) );
-
- for( i = 0; i < nPoints; i++ )
- {
- memcpy( psShape->padfM + i,
- psSHP->pabyRec + nOffset + 16 + i*8, 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
- }
- psShape->bMeasureIsUsed = TRUE;
- }
- }
-
-/* ==================================================================== */
-/* Extract vertices for a point. */
-/* ==================================================================== */
- else if( psShape->nSHPType == SHPT_POINT
- || psShape->nSHPType == SHPT_POINTM
- || psShape->nSHPType == SHPT_POINTZ )
- {
- int nOffset;
-
- psShape->nVertices = 1;
- psShape->padfX = (double *) calloc(1,sizeof(double));
- psShape->padfY = (double *) calloc(1,sizeof(double));
- psShape->padfZ = (double *) calloc(1,sizeof(double));
- psShape->padfM = (double *) calloc(1,sizeof(double));
-
- if (20 + 8 + (( psShape->nSHPType == SHPT_POINTZ ) ? 8 : 0)> nEntitySize)
- {
- g_snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
- hEntity, nEntitySize);
- psSHP->sHooks.Error( pszErrorMsg );
- SHPDestroyObject(psShape);
- return NULL;
- }
- 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 );
-
- nOffset = 20 + 8;
-
-/* -------------------------------------------------------------------- */
-/* If we have a Z coordinate, collect that now. */
-/* -------------------------------------------------------------------- */
- if( psShape->nSHPType == SHPT_POINTZ )
- {
- memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
-
- if( bBigEndian ) SwapWord( 8, psShape->padfZ );
-
- nOffset += 8;
- }
-
-/* -------------------------------------------------------------------- */
-/* If we have a M measure value, then read it now. We assume */
-/* that the measure can be present for any shape if the size is */
-/* big enough, but really it will only occur for the Z shapes */
-/* (options), and the M shapes. */
-/* -------------------------------------------------------------------- */
- if( nEntitySize >= nOffset + 8 )
- {
- memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
-
- if( bBigEndian ) SwapWord( 8, psShape->padfM );
- psShape->bMeasureIsUsed = TRUE;
- }
-
-/* -------------------------------------------------------------------- */
-/* Since no extents are supplied in the record, we will apply */
-/* them from the single vertex. */
-/* -------------------------------------------------------------------- */
- psShape->dfXMin = psShape->dfXMax = psShape->padfX[0];
- psShape->dfYMin = psShape->dfYMax = psShape->padfY[0];
- psShape->dfZMin = psShape->dfZMax = psShape->padfZ[0];
- psShape->dfMMin = psShape->dfMMax = psShape->padfM[0];
- }
-
- return( psShape );
-}
-
-/************************************************************************/
-/* SHPTypeName() */
-/************************************************************************/
-
-const char SHPAPI_CALL1(*)
-SHPTypeName( int nSHPType )
-
-{
- switch( nSHPType )
- {
- case SHPT_NULL:
- return "NullShape";
-
- case SHPT_POINT:
- return "Point";
-
- case SHPT_ARC:
- return "Arc";
-
- case SHPT_POLYGON:
- return "Polygon";
-
- case SHPT_MULTIPOINT:
- return "MultiPoint";
-
- case SHPT_POINTZ:
- return "PointZ";
-
- case SHPT_ARCZ:
- return "ArcZ";
-
- case SHPT_POLYGONZ:
- return "PolygonZ";
-
- case SHPT_MULTIPOINTZ:
- return "MultiPointZ";
-
- case SHPT_POINTM:
- return "PointM";
-
- case SHPT_ARCM:
- return "ArcM";
-
- case SHPT_POLYGONM:
- return "PolygonM";
-
- case SHPT_MULTIPOINTM:
- return "MultiPointM";
-
- case SHPT_MULTIPATCH:
- return "MultiPatch";
-
- default:
- return "UnknownShapeType";
- }
-}
-
-/************************************************************************/
-/* SHPPartTypeName() */
-/************************************************************************/
-
-const char SHPAPI_CALL1(*)
-SHPPartTypeName( int nPartType )
-
-{
- switch( nPartType )
- {
- case SHPP_TRISTRIP:
- return "TriangleStrip";
-
- case SHPP_TRIFAN:
- return "TriangleFan";
-
- case SHPP_OUTERRING:
- return "OuterRing";
-
- case SHPP_INNERRING:
- return "InnerRing";
-
- case SHPP_FIRSTRING:
- return "FirstRing";
-
- case SHPP_RING:
- return "Ring";
-
- default:
- return "UnknownPartType";
- }
-}
-
-/************************************************************************/
-/* SHPDestroyObject() */
-/************************************************************************/
-
-void SHPAPI_CALL
-SHPDestroyObject( SHPObject * psShape )
-
-{
- if( psShape == NULL )
- return;
-
- if( psShape->padfX != NULL )
- free( psShape->padfX );
- if( psShape->padfY != NULL )
- free( psShape->padfY );
- if( psShape->padfZ != NULL )
- free( psShape->padfZ );
- if( psShape->padfM != NULL )
- free( psShape->padfM );
-
- if( psShape->panPartStart != NULL )
- free( psShape->panPartStart );
- if( psShape->panPartType != NULL )
- free( psShape->panPartType );
-
- free( psShape );
-}
-
-/************************************************************************/
-/* SHPRewindObject() */
-/* */
-/* Reset the winding of polygon objects to adhere to the */
-/* specification. */
-/************************************************************************/
-
-int SHPAPI_CALL
-SHPRewindObject( SHPHandle hSHP, SHPObject * psObject )
-
-{
- int iOpRing, bAltered = 0;
-
-/* -------------------------------------------------------------------- */
-/* Do nothing if this is not a polygon object. */
-/* -------------------------------------------------------------------- */
- if( psObject->nSHPType != SHPT_POLYGON
- && psObject->nSHPType != SHPT_POLYGONZ
- && psObject->nSHPType != SHPT_POLYGONM )
- return 0;
-
- if( psObject->nVertices == 0 || psObject->nParts == 0 )
- return 0;
-
-/* -------------------------------------------------------------------- */
-/* Process each of the rings. */
-/* -------------------------------------------------------------------- */
- for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ )
- {
- int bInner, iVert, nVertCount, nVertStart, iCheckRing;
- double dfSum, dfTestX, dfTestY;
-
-/* -------------------------------------------------------------------- */
-/* Determine if this ring is an inner ring or an outer ring */
-/* relative to all the other rings. For now we assume the */
-/* first ring is outer and all others are inner, but eventually */
-/* we need to fix this to handle multiple island polygons and */
-/* unordered sets of rings. */
-/* */
-/* -------------------------------------------------------------------- */
-
- /* Use point in the middle of segment to avoid testing
- * common points of rings.
- */
- dfTestX = ( psObject->padfX[psObject->panPartStart[iOpRing]]
- + psObject->padfX[psObject->panPartStart[iOpRing] + 1] ) / 2;
- dfTestY = ( psObject->padfY[psObject->panPartStart[iOpRing]]
- + psObject->padfY[psObject->panPartStart[iOpRing] + 1] ) / 2;
-
- bInner = FALSE;
- for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
- {
- int iEdge;
-
- if( iCheckRing == iOpRing )
- continue;
-
- nVertStart = psObject->panPartStart[iCheckRing];
-
- if( iCheckRing == psObject->nParts-1 )
- nVertCount = psObject->nVertices
- - psObject->panPartStart[iCheckRing];
- else
- nVertCount = psObject->panPartStart[iCheckRing+1]
- - psObject->panPartStart[iCheckRing];
-
- for( iEdge = 0; iEdge < nVertCount; iEdge++ )
- {
- int iNext;
-
- if( iEdge < nVertCount-1 )
- iNext = iEdge+1;
- else
- iNext = 0;
-
- /* Rule #1:
- * Test whether the edge 'straddles' the horizontal ray from the test point (dfTestY,dfTestY)
- * The rule #1 also excludes edges collinear with the ray.
- */
- if ( ( psObject->padfY[iEdge+nVertStart] < dfTestY
- && dfTestY <= psObject->padfY[iNext+nVertStart] )
- || ( psObject->padfY[iNext+nVertStart] < dfTestY
- && dfTestY <= psObject->padfY[iEdge+nVertStart] ) )
- {
- /* Rule #2:
- * Test if edge-ray intersection is on the right from the test point (dfTestY,dfTestY)
- */
- double const intersect =
- ( psObject->padfX[iEdge+nVertStart]
- + ( dfTestY - psObject->padfY[iEdge+nVertStart] )
- / ( psObject->padfY[iNext+nVertStart] - psObject->padfY[iEdge+nVertStart] )
- * ( psObject->padfX[iNext+nVertStart] - psObject->padfX[iEdge+nVertStart] ) );
-
- if (intersect < dfTestX)
- {
- bInner = !bInner;
- }
- }
- }
- } /* for iCheckRing */
-
-/* -------------------------------------------------------------------- */
-/* Determine the current order of this ring so we will know if */
-/* it has to be reversed. */
-/* -------------------------------------------------------------------- */
- nVertStart = psObject->panPartStart[iOpRing];
-
- if( iOpRing == psObject->nParts-1 )
- nVertCount = psObject->nVertices - psObject->panPartStart[iOpRing];
- else
- nVertCount = psObject->panPartStart[iOpRing+1]
- - psObject->panPartStart[iOpRing];
-
- dfSum = 0.0;
- for( iVert = nVertStart; iVert < nVertStart+nVertCount-1; iVert++ )
- {
- dfSum += psObject->padfX[iVert] * psObject->padfY[iVert+1]
- - psObject->padfY[iVert] * psObject->padfX[iVert+1];
- }
-
- dfSum += psObject->padfX[iVert] * psObject->padfY[nVertStart]
- - psObject->padfY[iVert] * psObject->padfX[nVertStart];
-
-/* -------------------------------------------------------------------- */
-/* Reverse if necessary. */
-/* -------------------------------------------------------------------- */
- if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
- {
- int i;
-
- bAltered++;
- for( i = 0; i < nVertCount/2; i++ )
- {
- double dfSaved;
-
- /* Swap X */
- dfSaved = psObject->padfX[nVertStart+i];
- psObject->padfX[nVertStart+i] =
- psObject->padfX[nVertStart+nVertCount-i-1];
- psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved;
-
- /* Swap Y */
- dfSaved = psObject->padfY[nVertStart+i];
- psObject->padfY[nVertStart+i] =
- psObject->padfY[nVertStart+nVertCount-i-1];
- psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved;
-
- /* Swap Z */
- if( psObject->padfZ )
- {
- dfSaved = psObject->padfZ[nVertStart+i];
- psObject->padfZ[nVertStart+i] =
- psObject->padfZ[nVertStart+nVertCount-i-1];
- psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved;
- }
-
- /* Swap M */
- if( psObject->padfM )
- {
- dfSaved = psObject->padfM[nVertStart+i];
- psObject->padfM[nVertStart+i] =
- psObject->padfM[nVertStart+nVertCount-i-1];
- psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved;
- }
- }
- }
- }
-
- return bAltered;
-}
diff --git a/navit/map/shapefile/shptree.c b/navit/map/shapefile/shptree.c
deleted file mode 100644
index 56d33b227..000000000
--- a/navit/map/shapefile/shptree.c
+++ /dev/null
@@ -1,1050 +0,0 @@
-/******************************************************************************
- * $Id: shptree.c,v 1.12 2008/11/12 15:39:50 fwarmerdam Exp $
- *
- * Project: Shapelib
- * Purpose: Implementation of quadtree building and searching functions.
- * Author: Frank Warmerdam, warmerdam@pobox.com
- *
- ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
- *
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL). 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.
- ******************************************************************************
- *
- * $Log: shptree.c,v $
- * Revision 1.12 2008/11/12 15:39:50 fwarmerdam
- * improve safety in face of buggy .shp file.
- *
- * Revision 1.11 2007/10/27 03:31:14 fwarmerdam
- * limit default depth of tree to 12 levels (gdal ticket #1594)
- *
- * Revision 1.10 2005/01/03 22:30:13 fwarmerdam
- * added support for saved quadtrees
- *
- * Revision 1.9 2003/01/28 15:53:41 warmerda
- * Avoid build warnings.
- *
- * Revision 1.8 2002/05/07 13:07:45 warmerda
- * use qsort() - patch from Bernhard Herzog
- *
- * Revision 1.7 2002/01/15 14:36:07 warmerda
- * updated email address
- *
- * Revision 1.6 2001/05/23 13:36:52 warmerda
- * added use of SHPAPI_CALL
- *
- * Revision 1.5 1999/11/05 14:12:05 warmerda
- * updated license terms
- *
- * Revision 1.4 1999/06/02 18:24:21 warmerda
- * added trimming code
- *
- * Revision 1.3 1999/06/02 17:56:12 warmerda
- * added quad'' subnode support for trees
- *
- * Revision 1.2 1999/05/18 19:11:11 warmerda
- * Added example searching capability
- *
- * Revision 1.1 1999/05/18 17:49:20 warmerda
- * New
- *
- */
-
-#include "shapefil.h"
-
-#include <math.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef USE_CPL
-#include <cpl_error.h>
-#endif
-
-#if 0
-SHP_CVSID("$Id: shptree.c,v 1.12 2008/11/12 15:39:50 fwarmerdam Exp $")
-#endif
-
-#ifndef TRUE
-# define TRUE 1
-# define FALSE 0
-#endif
-
-static int bBigEndian = 0;
-
-void SHPAPI_CALL SHPTreeSplitBounds( double *padfBoundsMinIn, double *padfBoundsMaxIn, double *padfBoundsMin1, double * padfBoundsMax1, double *padfBoundsMin2, double * padfBoundsMax2 );
-void SHPAPI_CALL SHPTreeCollectShapeIds( SHPTree *hTree, SHPTreeNode * psTreeNode, double * padfBoundsMin, double * padfBoundsMax, int * pnShapeCount, int * pnMaxShapes, int ** ppanShapeList );
-
-
-/* -------------------------------------------------------------------- */
-/* If the following is 0.5, nodes will be split in half. If it */
-/* is 0.6 then each subnode will contain 60% of the parent */
-/* node, with 20% representing overlap. This can be help to */
-/* prevent small objects on a boundary from shifting too high */
-/* up the tree. */
-/* -------------------------------------------------------------------- */
-
-#define SHP_SPLIT_RATIO 0.55
-
-/************************************************************************/
-/* SfRealloc() */
-/* */
-/* A realloc cover function that will access a NULL pointer as */
-/* a valid input. */
-/************************************************************************/
-
-static void * SfRealloc( void * pMem, int nNewSize )
-
-{
- if( pMem == NULL )
- return( (void *) malloc(nNewSize) );
- else
- return( (void *) realloc(pMem,nNewSize) );
-}
-
-/************************************************************************/
-/* SHPTreeNodeInit() */
-/* */
-/* Initialize a tree node. */
-/************************************************************************/
-
-static SHPTreeNode *SHPTreeNodeCreate( double * padfBoundsMin,
- double * padfBoundsMax )
-
-{
- SHPTreeNode *psTreeNode;
-
- psTreeNode = (SHPTreeNode *) malloc(sizeof(SHPTreeNode));
- if( NULL == psTreeNode )
- {
-#ifdef USE_CPL
- CPLError( CE_Fatal, CPLE_OutOfMemory, "Memory allocation failure");
-#endif
- return NULL;
- }
-
- psTreeNode->nShapeCount = 0;
- psTreeNode->panShapeIds = NULL;
- psTreeNode->papsShapeObj = NULL;
-
- psTreeNode->nSubNodes = 0;
-
- if( padfBoundsMin != NULL )
- memcpy( psTreeNode->adfBoundsMin, padfBoundsMin, sizeof(double) * 4 );
-
- if( padfBoundsMax != NULL )
- memcpy( psTreeNode->adfBoundsMax, padfBoundsMax, sizeof(double) * 4 );
-
- return psTreeNode;
-}
-
-
-/************************************************************************/
-/* SHPCreateTree() */
-/************************************************************************/
-
-SHPTree SHPAPI_CALL1(*)
-SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
- double *padfBoundsMin, double *padfBoundsMax )
-
-{
- SHPTree *psTree;
-
- if( padfBoundsMin == NULL && hSHP == NULL )
- return NULL;
-
-/* -------------------------------------------------------------------- */
-/* Allocate the tree object */
-/* -------------------------------------------------------------------- */
- psTree = (SHPTree *) malloc(sizeof(SHPTree));
- if( NULL == psTree )
- {
-#ifdef USE_CPL
- CPLError( CE_Fatal, CPLE_OutOfMemory, "Memory allocation failure");
-#endif
- return NULL;
- }
-
- psTree->hSHP = hSHP;
- psTree->nMaxDepth = nMaxDepth;
- psTree->nDimension = nDimension;
- psTree->nTotalCount = 0;
-
-/* -------------------------------------------------------------------- */
-/* If no max depth was defined, try to select a reasonable one */
-/* that implies approximately 8 shapes per node. */
-/* -------------------------------------------------------------------- */
- if( psTree->nMaxDepth == 0 && hSHP != NULL )
- {
- int nMaxNodeCount = 1;
- int nShapeCount;
-
- SHPGetInfo( hSHP, &nShapeCount, NULL, NULL, NULL );
- while( nMaxNodeCount*4 < nShapeCount )
- {
- psTree->nMaxDepth += 1;
- nMaxNodeCount = nMaxNodeCount * 2;
- }
-
-#ifdef USE_CPL
- CPLDebug( "Shape",
- "Estimated spatial index tree depth: %d",
- psTree->nMaxDepth );
-#endif
-
- /* NOTE: Due to problems with memory allocation for deep trees,
- * automatically estimated depth is limited up to 12 levels.
- * See Ticket #1594 for detailed discussion.
- */
- if( psTree->nMaxDepth > MAX_DEFAULT_TREE_DEPTH )
- {
- psTree->nMaxDepth = MAX_DEFAULT_TREE_DEPTH;
-
-#ifdef USE_CPL
- CPLDebug( "Shape",
- "Falling back to max number of allowed index tree levels (%d).",
- MAX_DEFAULT_TREE_DEPTH );
-#endif
- }
- }
-
-/* -------------------------------------------------------------------- */
-/* Allocate the root node. */
-/* -------------------------------------------------------------------- */
- psTree->psRoot = SHPTreeNodeCreate( padfBoundsMin, padfBoundsMax );
- if( NULL == psTree->psRoot )
- {
- return NULL;
- }
-
-/* -------------------------------------------------------------------- */
-/* Assign the bounds to the root node. If none are passed in, */
-/* use the bounds of the provided file otherwise the create */
-/* function will have already set the bounds. */
-/* -------------------------------------------------------------------- */
- assert( NULL != psTree );
- assert( NULL != psTree->psRoot );
-
- if( padfBoundsMin == NULL )
- {
- SHPGetInfo( hSHP, NULL, NULL,
- psTree->psRoot->adfBoundsMin,
- psTree->psRoot->adfBoundsMax );
- }
-
-/* -------------------------------------------------------------------- */
-/* If we have a file, insert all it's shapes into the tree. */
-/* -------------------------------------------------------------------- */
- if( hSHP != NULL )
- {
- int iShape, nShapeCount;
-
- SHPGetInfo( hSHP, &nShapeCount, NULL, NULL, NULL );
-
- for( iShape = 0; iShape < nShapeCount; iShape++ )
- {
- SHPObject *psShape;
-
- psShape = SHPReadObject( hSHP, iShape );
- if( psShape != NULL )
- {
- SHPTreeAddShapeId( psTree, psShape );
- SHPDestroyObject( psShape );
- }
- }
- }
-
- return psTree;
-}
-
-/************************************************************************/
-/* SHPDestroyTreeNode() */
-/************************************************************************/
-
-static void SHPDestroyTreeNode( SHPTreeNode * psTreeNode )
-
-{
- int i;
-
- assert( NULL != psTreeNode );
-
- for( i = 0; i < psTreeNode->nSubNodes; i++ )
- {
- if( psTreeNode->apsSubNode[i] != NULL )
- SHPDestroyTreeNode( psTreeNode->apsSubNode[i] );
- }
-
- if( psTreeNode->panShapeIds != NULL )
- free( psTreeNode->panShapeIds );
-
- if( psTreeNode->papsShapeObj != NULL )
- {
- for( i = 0; i < psTreeNode->nShapeCount; i++ )
- {
- if( psTreeNode->papsShapeObj[i] != NULL )
- SHPDestroyObject( psTreeNode->papsShapeObj[i] );
- }
-
- free( psTreeNode->papsShapeObj );
- }
-
- free( psTreeNode );
-}
-
-/************************************************************************/
-/* SHPDestroyTree() */
-/************************************************************************/
-
-void SHPAPI_CALL
-SHPDestroyTree( SHPTree * psTree )
-
-{
- SHPDestroyTreeNode( psTree->psRoot );
- free( psTree );
-}
-
-/************************************************************************/
-/* SHPCheckBoundsOverlap() */
-/* */
-/* Do the given boxes overlap at all? */
-/************************************************************************/
-
-int SHPAPI_CALL
-SHPCheckBoundsOverlap( double * padfBox1Min, double * padfBox1Max,
- double * padfBox2Min, double * padfBox2Max,
- int nDimension )
-
-{
- int iDim;
-
- for( iDim = 0; iDim < nDimension; iDim++ )
- {
- if( padfBox2Max[iDim] < padfBox1Min[iDim] )
- return FALSE;
-
- if( padfBox1Max[iDim] < padfBox2Min[iDim] )
- return FALSE;
- }
-
- return TRUE;
-}
-
-/************************************************************************/
-/* SHPCheckObjectContained() */
-/* */
-/* Does the given shape fit within the indicated extents? */
-/************************************************************************/
-
-static int SHPCheckObjectContained( SHPObject * psObject, int nDimension,
- double * padfBoundsMin, double * padfBoundsMax )
-
-{
- if( psObject->dfXMin < padfBoundsMin[0]
- || psObject->dfXMax > padfBoundsMax[0] )
- return FALSE;
-
- if( psObject->dfYMin < padfBoundsMin[1]
- || psObject->dfYMax > padfBoundsMax[1] )
- return FALSE;
-
- if( nDimension == 2 )
- return TRUE;
-
- if( psObject->dfZMin < padfBoundsMin[2]
- || psObject->dfZMax < padfBoundsMax[2] )
- return FALSE;
-
- if( nDimension == 3 )
- return TRUE;
-
- if( psObject->dfMMin < padfBoundsMin[3]
- || psObject->dfMMax < padfBoundsMax[3] )
- return FALSE;
-
- return TRUE;
-}
-
-/************************************************************************/
-/* SHPTreeSplitBounds() */
-/* */
-/* Split a region into two subregion evenly, cutting along the */
-/* longest dimension. */
-/************************************************************************/
-
-void SHPAPI_CALL
-SHPTreeSplitBounds( double *padfBoundsMinIn, double *padfBoundsMaxIn,
- double *padfBoundsMin1, double * padfBoundsMax1,
- double *padfBoundsMin2, double * padfBoundsMax2 )
-
-{
-/* -------------------------------------------------------------------- */
-/* The output bounds will be very similar to the input bounds, */
-/* so just copy over to start. */
-/* -------------------------------------------------------------------- */
- memcpy( padfBoundsMin1, padfBoundsMinIn, sizeof(double) * 4 );
- memcpy( padfBoundsMax1, padfBoundsMaxIn, sizeof(double) * 4 );
- memcpy( padfBoundsMin2, padfBoundsMinIn, sizeof(double) * 4 );
- memcpy( padfBoundsMax2, padfBoundsMaxIn, sizeof(double) * 4 );
-
-/* -------------------------------------------------------------------- */
-/* Split in X direction. */
-/* -------------------------------------------------------------------- */
- if( (padfBoundsMaxIn[0] - padfBoundsMinIn[0])
- > (padfBoundsMaxIn[1] - padfBoundsMinIn[1]) )
- {
- double dfRange = padfBoundsMaxIn[0] - padfBoundsMinIn[0];
-
- padfBoundsMax1[0] = padfBoundsMinIn[0] + dfRange * SHP_SPLIT_RATIO;
- padfBoundsMin2[0] = padfBoundsMaxIn[0] - dfRange * SHP_SPLIT_RATIO;
- }
-
-/* -------------------------------------------------------------------- */
-/* Otherwise split in Y direction. */
-/* -------------------------------------------------------------------- */
- else
- {
- double dfRange = padfBoundsMaxIn[1] - padfBoundsMinIn[1];
-
- padfBoundsMax1[1] = padfBoundsMinIn[1] + dfRange * SHP_SPLIT_RATIO;
- padfBoundsMin2[1] = padfBoundsMaxIn[1] - dfRange * SHP_SPLIT_RATIO;
- }
-}
-
-/************************************************************************/
-/* SHPTreeNodeAddShapeId() */
-/************************************************************************/
-
-static int
-SHPTreeNodeAddShapeId( SHPTreeNode * psTreeNode, SHPObject * psObject,
- int nMaxDepth, int nDimension )
-
-{
- int i;
-
-/* -------------------------------------------------------------------- */
-/* If there are subnodes, then consider wiether this object */
-/* will fit in them. */
-/* -------------------------------------------------------------------- */
- if( nMaxDepth > 1 && psTreeNode->nSubNodes > 0 )
- {
- for( i = 0; i < psTreeNode->nSubNodes; i++ )
- {
- if( SHPCheckObjectContained(psObject, nDimension,
- psTreeNode->apsSubNode[i]->adfBoundsMin,
- psTreeNode->apsSubNode[i]->adfBoundsMax))
- {
- return SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[i],
- psObject, nMaxDepth-1,
- nDimension );
- }
- }
- }
-
-/* -------------------------------------------------------------------- */
-/* Otherwise, consider creating four subnodes if could fit into */
-/* them, and adding to the appropriate subnode. */
-/* -------------------------------------------------------------------- */
-#if MAX_SUBNODE == 4
- else if( nMaxDepth > 1 && psTreeNode->nSubNodes == 0 )
- {
- double adfBoundsMinH1[4], adfBoundsMaxH1[4];
- double adfBoundsMinH2[4], adfBoundsMaxH2[4];
- double adfBoundsMin1[4], adfBoundsMax1[4];
- double adfBoundsMin2[4], adfBoundsMax2[4];
- double adfBoundsMin3[4], adfBoundsMax3[4];
- double adfBoundsMin4[4], adfBoundsMax4[4];
-
- SHPTreeSplitBounds( psTreeNode->adfBoundsMin,
- psTreeNode->adfBoundsMax,
- adfBoundsMinH1, adfBoundsMaxH1,
- adfBoundsMinH2, adfBoundsMaxH2 );
-
- SHPTreeSplitBounds( adfBoundsMinH1, adfBoundsMaxH1,
- adfBoundsMin1, adfBoundsMax1,
- adfBoundsMin2, adfBoundsMax2 );
-
- SHPTreeSplitBounds( adfBoundsMinH2, adfBoundsMaxH2,
- adfBoundsMin3, adfBoundsMax3,
- adfBoundsMin4, adfBoundsMax4 );
-
- if( SHPCheckObjectContained(psObject, nDimension,
- adfBoundsMin1, adfBoundsMax1)
- || SHPCheckObjectContained(psObject, nDimension,
- adfBoundsMin2, adfBoundsMax2)
- || SHPCheckObjectContained(psObject, nDimension,
- adfBoundsMin3, adfBoundsMax3)
- || SHPCheckObjectContained(psObject, nDimension,
- adfBoundsMin4, adfBoundsMax4) )
- {
- psTreeNode->nSubNodes = 4;
- psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
- adfBoundsMax1 );
- psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
- adfBoundsMax2 );
- psTreeNode->apsSubNode[2] = SHPTreeNodeCreate( adfBoundsMin3,
- adfBoundsMax3 );
- psTreeNode->apsSubNode[3] = SHPTreeNodeCreate( adfBoundsMin4,
- adfBoundsMax4 );
-
- /* recurse back on this node now that it has subnodes */
- return( SHPTreeNodeAddShapeId( psTreeNode, psObject,
- nMaxDepth, nDimension ) );
- }
- }
-#endif /* MAX_SUBNODE == 4 */
-
-/* -------------------------------------------------------------------- */
-/* Otherwise, consider creating two subnodes if could fit into */
-/* them, and adding to the appropriate subnode. */
-/* -------------------------------------------------------------------- */
-#if MAX_SUBNODE == 2
- else if( nMaxDepth > 1 && psTreeNode->nSubNodes == 0 )
- {
- double adfBoundsMin1[4], adfBoundsMax1[4];
- double adfBoundsMin2[4], adfBoundsMax2[4];
-
- SHPTreeSplitBounds( psTreeNode->adfBoundsMin, psTreeNode->adfBoundsMax,
- adfBoundsMin1, adfBoundsMax1,
- adfBoundsMin2, adfBoundsMax2 );
-
- if( SHPCheckObjectContained(psObject, nDimension,
- adfBoundsMin1, adfBoundsMax1))
- {
- psTreeNode->nSubNodes = 2;
- psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
- adfBoundsMax1 );
- psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
- adfBoundsMax2 );
-
- return( SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[0], psObject,
- nMaxDepth - 1, nDimension ) );
- }
- else if( SHPCheckObjectContained(psObject, nDimension,
- adfBoundsMin2, adfBoundsMax2) )
- {
- psTreeNode->nSubNodes = 2;
- psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
- adfBoundsMax1 );
- psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
- adfBoundsMax2 );
-
- return( SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[1], psObject,
- nMaxDepth - 1, nDimension ) );
- }
- }
-#endif /* MAX_SUBNODE == 2 */
-
-/* -------------------------------------------------------------------- */
-/* If none of that worked, just add it to this nodes list. */
-/* -------------------------------------------------------------------- */
- psTreeNode->nShapeCount++;
-
- psTreeNode->panShapeIds = (int *)
- SfRealloc( psTreeNode->panShapeIds,
- sizeof(int) * psTreeNode->nShapeCount );
- psTreeNode->panShapeIds[psTreeNode->nShapeCount-1] = psObject->nShapeId;
-
- if( psTreeNode->papsShapeObj != NULL )
- {
- psTreeNode->papsShapeObj = (SHPObject **)
- SfRealloc( psTreeNode->papsShapeObj,
- sizeof(void *) * psTreeNode->nShapeCount );
- psTreeNode->papsShapeObj[psTreeNode->nShapeCount-1] = NULL;
- }
-
- return TRUE;
-}
-
-/************************************************************************/
-/* SHPTreeAddShapeId() */
-/* */
-/* Add a shape to the tree, but don't keep a pointer to the */
-/* object data, just keep the shapeid. */
-/************************************************************************/
-
-int SHPAPI_CALL
-SHPTreeAddShapeId( SHPTree * psTree, SHPObject * psObject )
-
-{
- psTree->nTotalCount++;
-
- return( SHPTreeNodeAddShapeId( psTree->psRoot, psObject,
- psTree->nMaxDepth, psTree->nDimension ) );
-}
-
-/************************************************************************/
-/* SHPTreeCollectShapesIds() */
-/* */
-/* Work function implementing SHPTreeFindLikelyShapes() on a */
-/* tree node by tree node basis. */
-/************************************************************************/
-
-void SHPAPI_CALL
-SHPTreeCollectShapeIds( SHPTree *hTree, SHPTreeNode * psTreeNode,
- double * padfBoundsMin, double * padfBoundsMax,
- int * pnShapeCount, int * pnMaxShapes,
- int ** ppanShapeList )
-
-{
- int i;
-
-/* -------------------------------------------------------------------- */
-/* Does this node overlap the area of interest at all? If not, */
-/* return without adding to the list at all. */
-/* -------------------------------------------------------------------- */
- if( !SHPCheckBoundsOverlap( psTreeNode->adfBoundsMin,
- psTreeNode->adfBoundsMax,
- padfBoundsMin,
- padfBoundsMax,
- hTree->nDimension ) )
- return;
-
-/* -------------------------------------------------------------------- */
-/* Grow the list to hold the shapes on this node. */
-/* -------------------------------------------------------------------- */
- if( *pnShapeCount + psTreeNode->nShapeCount > *pnMaxShapes )
- {
- *pnMaxShapes = (*pnShapeCount + psTreeNode->nShapeCount) * 2 + 20;
- *ppanShapeList = (int *)
- SfRealloc(*ppanShapeList,sizeof(int) * *pnMaxShapes);
- }
-
-/* -------------------------------------------------------------------- */
-/* Add the local nodes shapeids to the list. */
-/* -------------------------------------------------------------------- */
- for( i = 0; i < psTreeNode->nShapeCount; i++ )
- {
- (*ppanShapeList)[(*pnShapeCount)++] = psTreeNode->panShapeIds[i];
- }
-
-/* -------------------------------------------------------------------- */
-/* Recurse to subnodes if they exist. */
-/* -------------------------------------------------------------------- */
- for( i = 0; i < psTreeNode->nSubNodes; i++ )
- {
- if( psTreeNode->apsSubNode[i] != NULL )
- SHPTreeCollectShapeIds( hTree, psTreeNode->apsSubNode[i],
- padfBoundsMin, padfBoundsMax,
- pnShapeCount, pnMaxShapes,
- ppanShapeList );
- }
-}
-
-/************************************************************************/
-/* SHPTreeFindLikelyShapes() */
-/* */
-/* Find all shapes within tree nodes for which the tree node */
-/* bounding box overlaps the search box. The return value is */
-/* an array of shapeids terminated by a -1. The shapeids will */
-/* be in order, as hopefully this will result in faster (more */
-/* sequential) reading from the file. */
-/************************************************************************/
-
-/* helper for qsort */
-static int
-compare_ints( const void * a, const void * b)
-{
- return (*(int*)a) - (*(int*)b);
-}
-
-int SHPAPI_CALL1(*)
-SHPTreeFindLikelyShapes( SHPTree * hTree,
- double * padfBoundsMin, double * padfBoundsMax,
- int * pnShapeCount )
-
-{
- int *panShapeList=NULL, nMaxShapes = 0;
-
-/* -------------------------------------------------------------------- */
-/* Perform the search by recursive descent. */
-/* -------------------------------------------------------------------- */
- *pnShapeCount = 0;
-
- SHPTreeCollectShapeIds( hTree, hTree->psRoot,
- padfBoundsMin, padfBoundsMax,
- pnShapeCount, &nMaxShapes,
- &panShapeList );
-
-/* -------------------------------------------------------------------- */
-/* Sort the id array */
-/* -------------------------------------------------------------------- */
-
- qsort(panShapeList, *pnShapeCount, sizeof(int), compare_ints);
-
- return panShapeList;
-}
-
-/************************************************************************/
-/* SHPTreeNodeTrim() */
-/* */
-/* This is the recurve version of SHPTreeTrimExtraNodes() that */
-/* walks the tree cleaning it up. */
-/************************************************************************/
-
-static int SHPTreeNodeTrim( SHPTreeNode * psTreeNode )
-
-{
- int i;
-
-/* -------------------------------------------------------------------- */
-/* Trim subtrees, and free subnodes that come back empty. */
-/* -------------------------------------------------------------------- */
- for( i = 0; i < psTreeNode->nSubNodes; i++ )
- {
- if( SHPTreeNodeTrim( psTreeNode->apsSubNode[i] ) )
- {
- SHPDestroyTreeNode( psTreeNode->apsSubNode[i] );
-
- psTreeNode->apsSubNode[i] =
- psTreeNode->apsSubNode[psTreeNode->nSubNodes-1];
-
- psTreeNode->nSubNodes--;
-
- i--; /* process the new occupant of this subnode entry */
- }
- }
-
-/* -------------------------------------------------------------------- */
-/* We should be trimmed if we have no subnodes, and no shapes. */
-/* -------------------------------------------------------------------- */
- return( psTreeNode->nSubNodes == 0 && psTreeNode->nShapeCount == 0 );
-}
-
-/************************************************************************/
-/* SHPTreeTrimExtraNodes() */
-/* */
-/* Trim empty nodes from the tree. Note that we never trim an */
-/* empty root node. */
-/************************************************************************/
-
-void SHPAPI_CALL
-SHPTreeTrimExtraNodes( SHPTree * hTree )
-
-{
- SHPTreeNodeTrim( hTree->psRoot );
-}
-
-/************************************************************************/
-/* SwapWord() */
-/* */
-/* Swap a 2, 4 or 8 byte word. */
-/************************************************************************/
-
-static void SwapWord( int length, void * wordP )
-
-{
- int i;
- unsigned char temp;
-
- for( i=0; i < length/2; i++ )
- {
- temp = ((unsigned char *) wordP)[i];
- ((unsigned char *)wordP)[i] = ((unsigned char *) wordP)[length-i-1];
- ((unsigned char *) wordP)[length-i-1] = temp;
- }
-}
-
-/************************************************************************/
-/* SHPSearchDiskTreeNode() */
-/************************************************************************/
-
-static int
-SHPSearchDiskTreeNode( FILE *fp, double *padfBoundsMin, double *padfBoundsMax,
- int **ppanResultBuffer, int *pnBufferMax,
- int *pnResultCount, int bNeedSwap )
-
-{
- int i;
- int offset;
- int numshapes, numsubnodes;
- double adfNodeBoundsMin[2], adfNodeBoundsMax[2];
-
-/* -------------------------------------------------------------------- */
-/* Read and unswap first part of node info. */
-/* -------------------------------------------------------------------- */
- fread( &offset, 4, 1, fp );
- if ( bNeedSwap ) SwapWord ( 4, &offset );
-
- fread( adfNodeBoundsMin, sizeof(double), 2, fp );
- fread( adfNodeBoundsMax, sizeof(double), 2, fp );
- if ( bNeedSwap )
- {
- SwapWord( 8, adfNodeBoundsMin + 0 );
- SwapWord( 8, adfNodeBoundsMin + 1 );
- SwapWord( 8, adfNodeBoundsMax + 0 );
- SwapWord( 8, adfNodeBoundsMax + 1 );
- }
-
- fread( &numshapes, 4, 1, fp );
- if ( bNeedSwap ) SwapWord ( 4, &numshapes );
-
-/* -------------------------------------------------------------------- */
-/* If we don't overlap this node at all, we can just fseek() */
-/* pass this node info and all subnodes. */
-/* -------------------------------------------------------------------- */
- if( !SHPCheckBoundsOverlap( adfNodeBoundsMin, adfNodeBoundsMax,
- padfBoundsMin, padfBoundsMax, 2 ) )
- {
- offset += numshapes*sizeof(int) + sizeof(int);
- fseek(fp, offset, SEEK_CUR);
- return TRUE;
- }
-
-/* -------------------------------------------------------------------- */
-/* Add all the shapeids at this node to our list. */
-/* -------------------------------------------------------------------- */
- if(numshapes > 0)
- {
- if( *pnResultCount + numshapes > *pnBufferMax )
- {
- *pnBufferMax = (int) ((*pnResultCount + numshapes + 100) * 1.25);
- *ppanResultBuffer = (int *)
- SfRealloc( *ppanResultBuffer, *pnBufferMax * sizeof(int) );
- }
-
- fread( *ppanResultBuffer + *pnResultCount,
- sizeof(int), numshapes, fp );
-
- if (bNeedSwap )
- {
- for( i=0; i<numshapes; i++ )
- SwapWord( 4, *ppanResultBuffer + *pnResultCount + i );
- }
-
- *pnResultCount += numshapes;
- }
-
-/* -------------------------------------------------------------------- */
-/* Process the subnodes. */
-/* -------------------------------------------------------------------- */
- fread( &numsubnodes, 4, 1, fp );
- if ( bNeedSwap ) SwapWord ( 4, &numsubnodes );
-
- for(i=0; i<numsubnodes; i++)
- {
- if( !SHPSearchDiskTreeNode( fp, padfBoundsMin, padfBoundsMax,
- ppanResultBuffer, pnBufferMax,
- pnResultCount, bNeedSwap ) )
- return FALSE;
- }
-
- return TRUE;
-}
-
-/************************************************************************/
-/* SHPSearchDiskTree() */
-/************************************************************************/
-
-int SHPAPI_CALL1(*)
-SHPSearchDiskTree( FILE *fp,
- double *padfBoundsMin, double *padfBoundsMax,
- int *pnShapeCount )
-
-{
- int i, bNeedSwap, nBufferMax = 0;
- unsigned char abyBuf[16];
- int *panResultBuffer = NULL;
-
- *pnShapeCount = 0;
-
-/* -------------------------------------------------------------------- */
-/* Establish the byte order on this machine. */
-/* -------------------------------------------------------------------- */
- i = 1;
- if( *((unsigned char *) &i) == 1 )
- bBigEndian = FALSE;
- else
- bBigEndian = TRUE;
-
-/* -------------------------------------------------------------------- */
-/* Read the header. */
-/* -------------------------------------------------------------------- */
- fseek( fp, 0, SEEK_SET );
- fread( abyBuf, 16, 1, fp );
-
- if( memcmp( abyBuf, "SQT", 3 ) != 0 )
- return NULL;
-
- if( (abyBuf[3] == 2 && bBigEndian)
- || (abyBuf[3] == 1 && !bBigEndian) )
- bNeedSwap = FALSE;
- else
- bNeedSwap = TRUE;
-
-/* -------------------------------------------------------------------- */
-/* Search through root node and it's decendents. */
-/* -------------------------------------------------------------------- */
- if( !SHPSearchDiskTreeNode( fp, padfBoundsMin, padfBoundsMax,
- &panResultBuffer, &nBufferMax,
- pnShapeCount, bNeedSwap ) )
- {
- if( panResultBuffer != NULL )
- free( panResultBuffer );
- *pnShapeCount = 0;
- return NULL;
- }
-/* -------------------------------------------------------------------- */
-/* Sort the id array */
-/* -------------------------------------------------------------------- */
- qsort(panResultBuffer, *pnShapeCount, sizeof(int), compare_ints);
-
- return panResultBuffer;
-}
-
-/************************************************************************/
-/* SHPGetSubNodeOffset() */
-/* */
-/* Determine how big all the subnodes of this node (and their */
-/* children) will be. This will allow disk based searchers to */
-/* seek past them all efficiently. */
-/************************************************************************/
-
-static int SHPGetSubNodeOffset( SHPTreeNode *node)
-{
- int i;
- long offset=0;
-
- for(i=0; i<node->nSubNodes; i++ )
- {
- if(node->apsSubNode[i])
- {
- offset += 4*sizeof(double)
- + (node->apsSubNode[i]->nShapeCount+3)*sizeof(int);
- offset += SHPGetSubNodeOffset(node->apsSubNode[i]);
- }
- }
-
- return(offset);
-}
-
-/************************************************************************/
-/* SHPWriteTreeNode() */
-/************************************************************************/
-
-static void SHPWriteTreeNode( FILE *fp, SHPTreeNode *node)
-{
- int i,j;
- int offset;
- unsigned char *pabyRec = NULL;
- assert( NULL != node );
-
- offset = SHPGetSubNodeOffset(node);
-
- pabyRec = (unsigned char *)
- malloc(sizeof(double) * 4
- + (3 * sizeof(int)) + (node->nShapeCount * sizeof(int)) );
- if( NULL == pabyRec )
- {
-#ifdef USE_CPL
- CPLError( CE_Fatal, CPLE_OutOfMemory, "Memory allocation failure");
-#endif
- assert( 0 );
- }
- assert( NULL != pabyRec );
-
- memcpy( pabyRec, &offset, 4);
-
- /* minx, miny, maxx, maxy */
- memcpy( pabyRec+ 4, node->adfBoundsMin+0, sizeof(double) );
- memcpy( pabyRec+12, node->adfBoundsMin+1, sizeof(double) );
- memcpy( pabyRec+20, node->adfBoundsMax+0, sizeof(double) );
- memcpy( pabyRec+28, node->adfBoundsMax+1, sizeof(double) );
-
- memcpy( pabyRec+36, &node->nShapeCount, 4);
- j = node->nShapeCount * sizeof(int);
- memcpy( pabyRec+40, node->panShapeIds, j);
- memcpy( pabyRec+j+40, &node->nSubNodes, 4);
-
- fwrite( pabyRec, 44+j, 1, fp );
- free (pabyRec);
-
- for(i=0; i<node->nSubNodes; i++ )
- {
- if(node->apsSubNode[i])
- SHPWriteTreeNode( fp, node->apsSubNode[i]);
- }
-}
-
-/************************************************************************/
-/* SHPWriteTree() */
-/************************************************************************/
-
-int SHPWriteTree(SHPTree *tree, const char *filename )
-{
- char signature[4] = "SQT";
- int i;
- char abyBuf[32];
- FILE *fp;
-
-/* -------------------------------------------------------------------- */
-/* Open the output file. */
-/* -------------------------------------------------------------------- */
- fp = fopen(filename, "wb");
- if( fp == NULL )
- {
- return FALSE;
- }
-
-/* -------------------------------------------------------------------- */
-/* Establish the byte order on this machine. */
-/* -------------------------------------------------------------------- */
- i = 1;
- if( *((unsigned char *) &i) == 1 )
- bBigEndian = FALSE;
- else
- bBigEndian = TRUE;
-
-/* -------------------------------------------------------------------- */
-/* Write the header. */
-/* -------------------------------------------------------------------- */
- memcpy( abyBuf+0, signature, 3 );
-
- if( bBigEndian )
- abyBuf[3] = 2; /* New MSB */
- else
- abyBuf[3] = 1; /* New LSB */
-
- abyBuf[4] = 1; /* version */
- abyBuf[5] = 0; /* next 3 reserved */
- abyBuf[6] = 0;
- abyBuf[7] = 0;
-
- fwrite( abyBuf, 8, 1, fp );
-
- fwrite( &(tree->nTotalCount), 4, 1, fp );
-
- /* write maxdepth */
-
- fwrite( &(tree->nMaxDepth), 4, 1, fp );
-
-/* -------------------------------------------------------------------- */
-/* Write all the nodes "in order". */
-/* -------------------------------------------------------------------- */
-
- SHPWriteTreeNode( fp, tree->psRoot );
-
- fclose( fp );
-
- return TRUE;
-}