1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576 |
- /******************************************************************************
- * $Id$
- *
- * 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.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 <grass/shapefil.h>
- #include <math.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- SHP_CVSID("$Id$")
- #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);
- /* -------------------------------------------------------------------- */
- /* 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;
- unsigned char *pabyBuf;
- int nFields, nHeadLen, iField, i;
- char *pszBasename, *pszFullname;
- /* -------------------------------------------------------------------- */
- /* 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 );
- }
-
- free( pszBasename );
- free( pszFullname );
-
- if( psDBF->fp == NULL )
- {
- free( psDBF );
- return( NULL );
- }
- psDBF->bNoHeader = FALSE;
- psDBF->nCurrentRecord = -1;
- psDBF->bCurrentRecordModified = FALSE;
- /* -------------------------------------------------------------------- */
- /* Read Table Header info */
- /* -------------------------------------------------------------------- */
- pabyBuf = (unsigned char *) malloc(500);
- if( psDBF->sHooks.FRead( pabyBuf, 32, 1, psDBF->fp ) != 1 )
- {
- psDBF->sHooks.FClose( psDBF->fp );
- 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->nFields = nFields = (nHeadLen - 32) / 32;
- psDBF->pszCurrentRecord = (char *) malloc(psDBF->nRecordLength);
- /* -------------------------------------------------------------------- */
- /* 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)
- {
- /* -------------------------------------------------------------------- */
- /* 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 );
- }
- /************************************************************************/
- /* DBFCreate() */
- /* */
- /* Create a new .dbf file. */
- /************************************************************************/
- DBFHandle SHPAPI_CALL
- DBFCreate( const char * pszFilename )
- {
- SAHooks sHooks;
- SASetupDefaultHooks( &sHooks );
- return DBFCreateLL( pszFilename, &sHooks );
- }
- /************************************************************************/
- /* DBFCreate() */
- /* */
- /* Create a new .dbf file. */
- /************************************************************************/
- DBFHandle SHPAPI_CALL
- DBFCreateLL( const char * pszFilename, SAHooks *psHooks )
- {
- DBFHandle psDBF;
- SAFile fp;
- char *pszFullname, *pszBasename;
- int i;
- 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 );
- free( 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 );
- 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;
- return( psDBF );
- }
- /************************************************************************/
- /* DBFAddField() */
- /* */
- /* Add a field to a newly created .dbf file before any records */
- /* are written. */
- /************************************************************************/
- 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;
- /* -------------------------------------------------------------------- */
- /* Do some checking to ensure we can add records to this file. */
- /* -------------------------------------------------------------------- */
- if( psDBF->nRecords > 0 )
- return( -1 );
- if( !psDBF->bNoHeader )
- return( -1 );
- if( nWidth < 1 )
- return -1;
- if( nWidth > 255 )
- nWidth = 255;
- /* -------------------------------------------------------------------- */
- /* 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);
- 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 = 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 ) */ /* GDAL bug #809 */
- 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 = DBFCreate ( pszFilename );
- 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;
- }
|