/[thuban]/branches/WIP-pyshapelib-bramz/libraries/shapelib/dbfopen.c
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/libraries/shapelib/dbfopen.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1769 - (hide annotations)
Thu Oct 2 15:15:16 2003 UTC (21 years, 5 months ago) by bh
Original Path: trunk/thuban/libraries/shapelib/dbfopen.c
File MIME type: text/plain
File size: 52587 byte(s)
Update to shapelib 1.2.10

1 jan 1612 /******************************************************************************
2     * $Id$
3     *
4     * Project: Shapelib
5     * Purpose: Implementation of .dbf access API documented in dbf_api.html.
6 bh 1769 * Author: Frank Warmerdam, [email protected]
7 jan 1612 *
8     ******************************************************************************
9     * Copyright (c) 1999, Frank Warmerdam
10     *
11     * This software is available under the following "MIT Style" license,
12     * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
13     * option is discussed in more detail in shapelib.html.
14     *
15     * --
16     *
17     * Permission is hereby granted, free of charge, to any person obtaining a
18     * copy of this software and associated documentation files (the "Software"),
19     * to deal in the Software without restriction, including without limitation
20     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21     * and/or sell copies of the Software, and to permit persons to whom the
22     * Software is furnished to do so, subject to the following conditions:
23     *
24     * The above copyright notice and this permission notice shall be included
25     * in all copies or substantial portions of the Software.
26     *
27     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33     * DEALINGS IN THE SOFTWARE.
34     ******************************************************************************
35     *
36     * $Log$
37 bh 1769 * Revision 1.2 2003/10/02 15:15:16 bh
38     * Update to shapelib 1.2.10
39 jan 1612 *
40 bh 1769 * Revision 1.48 2003/03/10 14:51:27 warmerda
41     * DBFWrite* calls now return FALSE if they have to truncate
42 jan 1612 *
43 bh 1769 * Revision 1.47 2002/11/20 03:32:22 warmerda
44     * Ensure field name in DBFGetFieldIndex() is properly terminated.
45 jan 1612 *
46 bh 1769 * Revision 1.46 2002/10/09 13:10:21 warmerda
47     * Added check that width is positive.
48     *
49     * Revision 1.45 2002/09/29 00:00:08 warmerda
50     * added FTLogical and logical attribute read/write calls
51     *
52     * Revision 1.44 2002/05/07 13:46:11 warmerda
53     * Added DBFWriteAttributeDirectly().
54     *
55     * Revision 1.43 2002/02/13 19:39:21 warmerda
56     * Fix casting issues in DBFCloneEmpty().
57     *
58     * Revision 1.42 2002/01/15 14:36:07 warmerda
59     * updated email address
60     *
61     * Revision 1.41 2002/01/15 14:31:49 warmerda
62     * compute rather than copying nHeaderLength in DBFCloneEmpty()
63     *
64     * Revision 1.40 2002/01/09 04:32:35 warmerda
65     * fixed to read correct amount of header
66     *
67     * Revision 1.39 2001/12/11 22:41:03 warmerda
68     * improve io related error checking when reading header
69     *
70     * Revision 1.38 2001/11/28 16:07:31 warmerda
71     * Cleanup to avoid compiler warnings as suggested by Richard Hash.
72     *
73 jan 1612 * Revision 1.37 2001/07/04 05:18:09 warmerda
74     * do last fix properly
75     *
76     * Revision 1.36 2001/07/04 05:16:09 warmerda
77     * fixed fieldname comparison in DBFGetFieldIndex
78     *
79     * Revision 1.35 2001/06/22 02:10:06 warmerda
80     * fixed NULL shape support with help from Jim Matthews
81     *
82     * Revision 1.33 2001/05/31 19:20:13 warmerda
83     * added DBFGetFieldIndex()
84     *
85     * Revision 1.32 2001/05/31 18:15:40 warmerda
86     * Added support for NULL fields in DBF files
87     *
88     * Revision 1.31 2001/05/23 13:36:52 warmerda
89     * added use of SHPAPI_CALL
90     *
91     * Revision 1.30 2000/12/05 14:43:38 warmerda
92     * DBReadAttribute() white space trimming bug fix
93     *
94     * Revision 1.29 2000/10/05 14:36:44 warmerda
95     * fix bug with writing very wide numeric fields
96     *
97     * Revision 1.28 2000/09/25 14:18:07 warmerda
98     * Added some casts of strlen() return result to fix warnings on some
99     * systems, as submitted by Daniel.
100     *
101     * Revision 1.27 2000/09/25 14:15:51 warmerda
102     * added DBFGetNativeFieldType()
103     *
104     * Revision 1.26 2000/07/07 13:39:45 warmerda
105     * removed unused variables, and added system include files
106     *
107     * Revision 1.25 2000/05/29 18:19:13 warmerda
108     * avoid use of uchar, and adding casting fix
109     *
110     * Revision 1.24 2000/05/23 13:38:27 warmerda
111     * Added error checks on return results of fread() and fseek().
112     *
113     * Revision 1.23 2000/05/23 13:25:49 warmerda
114     * Avoid crashing if field or record are out of range in dbfread*attribute().
115     *
116     * Revision 1.22 1999/12/15 13:47:24 warmerda
117     * Added stdlib.h to ensure that atof() is prototyped.
118     *
119     * Revision 1.21 1999/12/13 17:25:46 warmerda
120     * Added support for upper case .DBF extention.
121     *
122     * Revision 1.20 1999/11/30 16:32:11 warmerda
123     * Use atof() instead of sscanf().
124     *
125     * Revision 1.19 1999/11/05 14:12:04 warmerda
126     * updated license terms
127     *
128     * Revision 1.18 1999/07/27 00:53:28 warmerda
129     * ensure that whole old field value clear on write of string
130     *
131     * Revision 1.1 1999/07/05 18:58:07 warmerda
132     * New
133     *
134     * Revision 1.17 1999/06/11 19:14:12 warmerda
135     * Fixed some memory leaks.
136     *
137     * Revision 1.16 1999/06/11 19:04:11 warmerda
138     * Remoted some unused variables.
139     *
140     * Revision 1.15 1999/05/11 03:19:28 warmerda
141     * added new Tuple api, and improved extension handling - add from candrsn
142     *
143     * Revision 1.14 1999/05/04 15:01:48 warmerda
144     * Added 'F' support.
145     *
146     * Revision 1.13 1999/03/23 17:38:59 warmerda
147     * DBFAddField() now actually does return the new field number, or -1 if
148     * it fails.
149     *
150     * Revision 1.12 1999/03/06 02:54:46 warmerda
151     * Added logic to convert shapefile name to dbf filename in DBFOpen()
152     * for convenience.
153     *
154     * Revision 1.11 1998/12/31 15:30:34 warmerda
155     * Improved the interchangability of numeric and string attributes. Add
156     * white space trimming option for attributes.
157     *
158     * Revision 1.10 1998/12/03 16:36:44 warmerda
159     * Use r+b instead of rb+ for binary access.
160     *
161     * Revision 1.9 1998/12/03 15:34:23 warmerda
162     * Updated copyright message.
163     *
164     * Revision 1.8 1997/12/04 15:40:15 warmerda
165     * Added newline character after field definitions.
166     *
167     * Revision 1.7 1997/03/06 14:02:10 warmerda
168     * Ensure bUpdated is initialized.
169     *
170     * Revision 1.6 1996/02/12 04:54:41 warmerda
171     * Ensure that DBFWriteAttribute() returns TRUE if it succeeds.
172     *
173     * Revision 1.5 1995/10/21 03:15:12 warmerda
174     * Changed to use binary file access, and ensure that the
175     * field name field is zero filled, and limited to 10 chars.
176     *
177     * Revision 1.4 1995/08/24 18:10:42 warmerda
178     * Added use of SfRealloc() to avoid pre-ANSI realloc() functions such
179     * as on the Sun.
180     *
181     * Revision 1.3 1995/08/04 03:15:16 warmerda
182     * Fixed up header.
183     *
184     * Revision 1.2 1995/08/04 03:14:43 warmerda
185     * Added header.
186     */
187    
188     static char rcsid[] =
189     "$Id$";
190    
191     #include "shapefil.h"
192    
193     #include <math.h>
194     #include <stdlib.h>
195     #include <ctype.h>
196     #include <string.h>
197    
198     #ifndef FALSE
199     # define FALSE 0
200     # define TRUE 1
201     #endif
202    
203     static int nStringFieldLen = 0;
204     static char * pszStringField = NULL;
205    
206     /************************************************************************/
207     /* SfRealloc() */
208     /* */
209     /* A realloc cover function that will access a NULL pointer as */
210     /* a valid input. */
211     /************************************************************************/
212    
213     static void * SfRealloc( void * pMem, int nNewSize )
214    
215     {
216     if( pMem == NULL )
217     return( (void *) malloc(nNewSize) );
218     else
219     return( (void *) realloc(pMem,nNewSize) );
220     }
221    
222     /************************************************************************/
223     /* DBFWriteHeader() */
224     /* */
225     /* This is called to write out the file header, and field */
226     /* descriptions before writing any actual data records. This */
227     /* also computes all the DBFDataSet field offset/size/decimals */
228     /* and so forth values. */
229     /************************************************************************/
230    
231     static void DBFWriteHeader(DBFHandle psDBF)
232    
233     {
234     unsigned char abyHeader[XBASE_FLDHDR_SZ];
235     int i;
236    
237     if( !psDBF->bNoHeader )
238     return;
239    
240     psDBF->bNoHeader = FALSE;
241    
242     /* -------------------------------------------------------------------- */
243     /* Initialize the file header information. */
244     /* -------------------------------------------------------------------- */
245     for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
246     abyHeader[i] = 0;
247    
248     abyHeader[0] = 0x03; /* memo field? - just copying */
249    
250     /* date updated on close, record count preset at zero */
251    
252     abyHeader[8] = psDBF->nHeaderLength % 256;
253     abyHeader[9] = psDBF->nHeaderLength / 256;
254    
255     abyHeader[10] = psDBF->nRecordLength % 256;
256     abyHeader[11] = psDBF->nRecordLength / 256;
257    
258     /* -------------------------------------------------------------------- */
259     /* Write the initial 32 byte file header, and all the field */
260     /* descriptions. */
261     /* -------------------------------------------------------------------- */
262     fseek( psDBF->fp, 0, 0 );
263     fwrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
264     fwrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields, psDBF->fp );
265    
266     /* -------------------------------------------------------------------- */
267     /* Write out the newline character if there is room for it. */
268     /* -------------------------------------------------------------------- */
269     if( psDBF->nHeaderLength > 32*psDBF->nFields + 32 )
270     {
271     char cNewline;
272    
273     cNewline = 0x0d;
274     fwrite( &cNewline, 1, 1, psDBF->fp );
275     }
276     }
277    
278     /************************************************************************/
279     /* DBFFlushRecord() */
280     /* */
281     /* Write out the current record if there is one. */
282     /************************************************************************/
283    
284     static void DBFFlushRecord( DBFHandle psDBF )
285    
286     {
287     int nRecordOffset;
288    
289     if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
290     {
291     psDBF->bCurrentRecordModified = FALSE;
292    
293     nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord
294     + psDBF->nHeaderLength;
295    
296     fseek( psDBF->fp, nRecordOffset, 0 );
297     fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
298     }
299     }
300    
301     /************************************************************************/
302     /* DBFOpen() */
303     /* */
304     /* Open a .dbf file. */
305     /************************************************************************/
306    
307     DBFHandle SHPAPI_CALL
308     DBFOpen( const char * pszFilename, const char * pszAccess )
309    
310     {
311     DBFHandle psDBF;
312     unsigned char *pabyBuf;
313 bh 1769 int nFields, nHeadLen, nRecLen, iField, i;
314 jan 1612 char *pszBasename, *pszFullname;
315    
316     /* -------------------------------------------------------------------- */
317     /* We only allow the access strings "rb" and "r+". */
318     /* -------------------------------------------------------------------- */
319     if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
320     && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
321     && strcmp(pszAccess,"r+b") != 0 )
322     return( NULL );
323    
324     if( strcmp(pszAccess,"r") == 0 )
325     pszAccess = "rb";
326    
327     if( strcmp(pszAccess,"r+") == 0 )
328     pszAccess = "rb+";
329    
330     /* -------------------------------------------------------------------- */
331     /* Compute the base (layer) name. If there is any extension */
332     /* on the passed in filename we will strip it off. */
333     /* -------------------------------------------------------------------- */
334     pszBasename = (char *) malloc(strlen(pszFilename)+5);
335     strcpy( pszBasename, pszFilename );
336     for( i = strlen(pszBasename)-1;
337     i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
338     && pszBasename[i] != '\\';
339     i-- ) {}
340    
341     if( pszBasename[i] == '.' )
342     pszBasename[i] = '\0';
343    
344     pszFullname = (char *) malloc(strlen(pszBasename) + 5);
345     sprintf( pszFullname, "%s.dbf", pszBasename );
346    
347     psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
348     psDBF->fp = fopen( pszFullname, pszAccess );
349    
350     if( psDBF->fp == NULL )
351     {
352     sprintf( pszFullname, "%s.DBF", pszBasename );
353     psDBF->fp = fopen(pszFullname, pszAccess );
354     }
355    
356     free( pszBasename );
357     free( pszFullname );
358    
359     if( psDBF->fp == NULL )
360     {
361     free( psDBF );
362     return( NULL );
363     }
364    
365     psDBF->bNoHeader = FALSE;
366     psDBF->nCurrentRecord = -1;
367     psDBF->bCurrentRecordModified = FALSE;
368    
369     /* -------------------------------------------------------------------- */
370     /* Read Table Header info */
371     /* -------------------------------------------------------------------- */
372     pabyBuf = (unsigned char *) malloc(500);
373 bh 1769 if( fread( pabyBuf, 32, 1, psDBF->fp ) != 1 )
374     {
375     fclose( psDBF->fp );
376     free( pabyBuf );
377     free( psDBF );
378     return NULL;
379     }
380 jan 1612
381 bh 1769 psDBF->nRecords =
382 jan 1612 pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;
383    
384     psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
385     psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;
386    
387     psDBF->nFields = nFields = (nHeadLen - 32) / 32;
388    
389     psDBF->pszCurrentRecord = (char *) malloc(nRecLen);
390    
391     /* -------------------------------------------------------------------- */
392     /* Read in Field Definitions */
393     /* -------------------------------------------------------------------- */
394    
395     pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
396     psDBF->pszHeader = (char *) pabyBuf;
397    
398     fseek( psDBF->fp, 32, 0 );
399 bh 1769 if( fread( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
400     {
401     fclose( psDBF->fp );
402     free( pabyBuf );
403     free( psDBF );
404     return NULL;
405     }
406 jan 1612
407     psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
408     psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
409     psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
410     psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);
411    
412     for( iField = 0; iField < nFields; iField++ )
413     {
414     unsigned char *pabyFInfo;
415    
416     pabyFInfo = pabyBuf+iField*32;
417    
418     if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
419     {
420     psDBF->panFieldSize[iField] = pabyFInfo[16];
421     psDBF->panFieldDecimals[iField] = pabyFInfo[17];
422     }
423     else
424     {
425     psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
426     psDBF->panFieldDecimals[iField] = 0;
427     }
428    
429     psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
430     if( iField == 0 )
431     psDBF->panFieldOffset[iField] = 1;
432     else
433     psDBF->panFieldOffset[iField] =
434     psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
435     }
436    
437     return( psDBF );
438     }
439    
440     /************************************************************************/
441     /* DBFClose() */
442     /************************************************************************/
443    
444     void SHPAPI_CALL
445     DBFClose(DBFHandle psDBF)
446     {
447     /* -------------------------------------------------------------------- */
448     /* Write out header if not already written. */
449     /* -------------------------------------------------------------------- */
450     if( psDBF->bNoHeader )
451     DBFWriteHeader( psDBF );
452    
453     DBFFlushRecord( psDBF );
454    
455     /* -------------------------------------------------------------------- */
456     /* Update last access date, and number of records if we have */
457     /* write access. */
458     /* -------------------------------------------------------------------- */
459     if( psDBF->bUpdated )
460     {
461     unsigned char abyFileHeader[32];
462    
463     fseek( psDBF->fp, 0, 0 );
464     fread( abyFileHeader, 32, 1, psDBF->fp );
465    
466     abyFileHeader[1] = 95; /* YY */
467     abyFileHeader[2] = 7; /* MM */
468     abyFileHeader[3] = 26; /* DD */
469    
470     abyFileHeader[4] = psDBF->nRecords % 256;
471     abyFileHeader[5] = (psDBF->nRecords/256) % 256;
472     abyFileHeader[6] = (psDBF->nRecords/(256*256)) % 256;
473     abyFileHeader[7] = (psDBF->nRecords/(256*256*256)) % 256;
474    
475     fseek( psDBF->fp, 0, 0 );
476     fwrite( abyFileHeader, 32, 1, psDBF->fp );
477     }
478    
479     /* -------------------------------------------------------------------- */
480     /* Close, and free resources. */
481     /* -------------------------------------------------------------------- */
482     fclose( psDBF->fp );
483    
484     if( psDBF->panFieldOffset != NULL )
485     {
486     free( psDBF->panFieldOffset );
487     free( psDBF->panFieldSize );
488     free( psDBF->panFieldDecimals );
489     free( psDBF->pachFieldType );
490     }
491    
492     free( psDBF->pszHeader );
493     free( psDBF->pszCurrentRecord );
494    
495     free( psDBF );
496    
497     if( pszStringField != NULL )
498     {
499     free( pszStringField );
500     pszStringField = NULL;
501     nStringFieldLen = 0;
502     }
503     }
504    
505     /************************************************************************/
506     /* DBFCreate() */
507     /* */
508     /* Create a new .dbf file. */
509     /************************************************************************/
510    
511     DBFHandle SHPAPI_CALL
512     DBFCreate( const char * pszFilename )
513    
514     {
515     DBFHandle psDBF;
516     FILE *fp;
517     char *pszFullname, *pszBasename;
518     int i;
519    
520     /* -------------------------------------------------------------------- */
521     /* Compute the base (layer) name. If there is any extension */
522     /* on the passed in filename we will strip it off. */
523     /* -------------------------------------------------------------------- */
524     pszBasename = (char *) malloc(strlen(pszFilename)+5);
525     strcpy( pszBasename, pszFilename );
526     for( i = strlen(pszBasename)-1;
527     i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
528     && pszBasename[i] != '\\';
529     i-- ) {}
530    
531     if( pszBasename[i] == '.' )
532     pszBasename[i] = '\0';
533    
534     pszFullname = (char *) malloc(strlen(pszBasename) + 5);
535     sprintf( pszFullname, "%s.dbf", pszBasename );
536     free( pszBasename );
537    
538     /* -------------------------------------------------------------------- */
539     /* Create the file. */
540     /* -------------------------------------------------------------------- */
541     fp = fopen( pszFullname, "wb" );
542     if( fp == NULL )
543     return( NULL );
544    
545     fputc( 0, fp );
546     fclose( fp );
547    
548     fp = fopen( pszFullname, "rb+" );
549     if( fp == NULL )
550     return( NULL );
551    
552     free( pszFullname );
553    
554     /* -------------------------------------------------------------------- */
555     /* Create the info structure. */
556     /* -------------------------------------------------------------------- */
557     psDBF = (DBFHandle) malloc(sizeof(DBFInfo));
558    
559     psDBF->fp = fp;
560     psDBF->nRecords = 0;
561     psDBF->nFields = 0;
562     psDBF->nRecordLength = 1;
563     psDBF->nHeaderLength = 33;
564    
565     psDBF->panFieldOffset = NULL;
566     psDBF->panFieldSize = NULL;
567     psDBF->panFieldDecimals = NULL;
568     psDBF->pachFieldType = NULL;
569     psDBF->pszHeader = NULL;
570    
571     psDBF->nCurrentRecord = -1;
572     psDBF->bCurrentRecordModified = FALSE;
573     psDBF->pszCurrentRecord = NULL;
574    
575     psDBF->bNoHeader = TRUE;
576    
577     return( psDBF );
578     }
579    
580     /************************************************************************/
581     /* DBFAddField() */
582     /* */
583     /* Add a field to a newly created .dbf file before any records */
584     /* are written. */
585     /************************************************************************/
586    
587     int SHPAPI_CALL
588     DBFAddField(DBFHandle psDBF, const char * pszFieldName,
589     DBFFieldType eType, int nWidth, int nDecimals )
590    
591     {
592     char *pszFInfo;
593     int i;
594    
595     /* -------------------------------------------------------------------- */
596     /* Do some checking to ensure we can add records to this file. */
597     /* -------------------------------------------------------------------- */
598     if( psDBF->nRecords > 0 )
599     return( -1 );
600    
601     if( !psDBF->bNoHeader )
602     return( -1 );
603    
604     if( eType != FTDouble && nDecimals != 0 )
605     return( -1 );
606    
607 bh 1769 if( nWidth < 1 )
608     return -1;
609    
610 jan 1612 /* -------------------------------------------------------------------- */
611     /* SfRealloc all the arrays larger to hold the additional field */
612     /* information. */
613     /* -------------------------------------------------------------------- */
614     psDBF->nFields++;
615    
616     psDBF->panFieldOffset = (int *)
617     SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
618    
619     psDBF->panFieldSize = (int *)
620     SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
621    
622     psDBF->panFieldDecimals = (int *)
623     SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
624    
625     psDBF->pachFieldType = (char *)
626     SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
627    
628     /* -------------------------------------------------------------------- */
629     /* Assign the new field information fields. */
630     /* -------------------------------------------------------------------- */
631     psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
632     psDBF->nRecordLength += nWidth;
633     psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
634     psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
635    
636 bh 1769 if( eType == FTLogical )
637     psDBF->pachFieldType[psDBF->nFields-1] = 'L';
638     else if( eType == FTString )
639 jan 1612 psDBF->pachFieldType[psDBF->nFields-1] = 'C';
640     else
641     psDBF->pachFieldType[psDBF->nFields-1] = 'N';
642    
643     /* -------------------------------------------------------------------- */
644     /* Extend the required header information. */
645     /* -------------------------------------------------------------------- */
646     psDBF->nHeaderLength += 32;
647     psDBF->bUpdated = FALSE;
648    
649     psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
650    
651     pszFInfo = psDBF->pszHeader + 32 * (psDBF->nFields-1);
652    
653     for( i = 0; i < 32; i++ )
654     pszFInfo[i] = '\0';
655    
656     if( (int) strlen(pszFieldName) < 10 )
657     strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
658     else
659     strncpy( pszFInfo, pszFieldName, 10);
660    
661     pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
662    
663     if( eType == FTString )
664     {
665     pszFInfo[16] = nWidth % 256;
666     pszFInfo[17] = nWidth / 256;
667     }
668     else
669     {
670     pszFInfo[16] = nWidth;
671     pszFInfo[17] = nDecimals;
672     }
673    
674     /* -------------------------------------------------------------------- */
675     /* Make the current record buffer appropriately larger. */
676     /* -------------------------------------------------------------------- */
677     psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
678     psDBF->nRecordLength);
679    
680     return( psDBF->nFields-1 );
681     }
682    
683     /************************************************************************/
684     /* DBFReadAttribute() */
685     /* */
686     /* Read one of the attribute fields of a record. */
687     /************************************************************************/
688    
689     static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
690     char chReqType )
691    
692     {
693     int nRecordOffset;
694     unsigned char *pabyRec;
695     void *pReturnField = NULL;
696    
697     static double dDoubleField;
698    
699     /* -------------------------------------------------------------------- */
700     /* Verify selection. */
701     /* -------------------------------------------------------------------- */
702     if( hEntity < 0 || hEntity >= psDBF->nRecords )
703     return( NULL );
704    
705     if( iField < 0 || iField >= psDBF->nFields )
706     return( NULL );
707    
708     /* -------------------------------------------------------------------- */
709     /* Have we read the record? */
710     /* -------------------------------------------------------------------- */
711     if( psDBF->nCurrentRecord != hEntity )
712     {
713     DBFFlushRecord( psDBF );
714    
715     nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
716    
717     if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 )
718     {
719     fprintf( stderr, "fseek(%d) failed on DBF file.\n",
720     nRecordOffset );
721     return NULL;
722     }
723    
724     if( fread( psDBF->pszCurrentRecord, psDBF->nRecordLength,
725     1, psDBF->fp ) != 1 )
726     {
727     fprintf( stderr, "fread(%d) failed on DBF file.\n",
728     psDBF->nRecordLength );
729     return NULL;
730     }
731    
732     psDBF->nCurrentRecord = hEntity;
733     }
734    
735     pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
736    
737     /* -------------------------------------------------------------------- */
738     /* Ensure our field buffer is large enough to hold this buffer. */
739     /* -------------------------------------------------------------------- */
740     if( psDBF->panFieldSize[iField]+1 > nStringFieldLen )
741     {
742     nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10;
743     pszStringField = (char *) SfRealloc(pszStringField,nStringFieldLen);
744     }
745    
746     /* -------------------------------------------------------------------- */
747     /* Extract the requested field. */
748     /* -------------------------------------------------------------------- */
749     strncpy( pszStringField,
750     ((const char *) pabyRec) + psDBF->panFieldOffset[iField],
751     psDBF->panFieldSize[iField] );
752     pszStringField[psDBF->panFieldSize[iField]] = '\0';
753    
754     pReturnField = pszStringField;
755    
756     /* -------------------------------------------------------------------- */
757     /* Decode the field. */
758     /* -------------------------------------------------------------------- */
759     if( chReqType == 'N' )
760     {
761     dDoubleField = atof(pszStringField);
762    
763     pReturnField = &dDoubleField;
764     }
765    
766     /* -------------------------------------------------------------------- */
767     /* Should we trim white space off the string attribute value? */
768     /* -------------------------------------------------------------------- */
769     #ifdef TRIM_DBF_WHITESPACE
770     else
771     {
772     char *pchSrc, *pchDst;
773    
774     pchDst = pchSrc = pszStringField;
775     while( *pchSrc == ' ' )
776     pchSrc++;
777    
778     while( *pchSrc != '\0' )
779     *(pchDst++) = *(pchSrc++);
780     *pchDst = '\0';
781    
782     while( pchDst != pszStringField && *(--pchDst) == ' ' )
783     *pchDst = '\0';
784     }
785     #endif
786    
787     return( pReturnField );
788     }
789    
790     /************************************************************************/
791     /* DBFReadIntAttribute() */
792     /* */
793     /* Read an integer attribute. */
794     /************************************************************************/
795    
796     int SHPAPI_CALL
797     DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
798    
799     {
800     double *pdValue;
801    
802     pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
803    
804     if( pdValue == NULL )
805     return 0;
806     else
807     return( (int) *pdValue );
808     }
809    
810     /************************************************************************/
811     /* DBFReadDoubleAttribute() */
812     /* */
813     /* Read a double attribute. */
814     /************************************************************************/
815    
816     double SHPAPI_CALL
817     DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
818    
819     {
820     double *pdValue;
821    
822     pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
823    
824     if( pdValue == NULL )
825     return 0.0;
826     else
827     return( *pdValue );
828     }
829    
830     /************************************************************************/
831     /* DBFReadStringAttribute() */
832     /* */
833     /* Read a string attribute. */
834     /************************************************************************/
835    
836     const char SHPAPI_CALL1(*)
837     DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
838    
839     {
840     return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
841     }
842    
843     /************************************************************************/
844 bh 1769 /* DBFReadLogicalAttribute() */
845     /* */
846     /* Read a logical attribute. */
847     /************************************************************************/
848    
849     const char SHPAPI_CALL1(*)
850     DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
851    
852     {
853     return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
854     }
855    
856     /************************************************************************/
857 jan 1612 /* DBFIsAttributeNULL() */
858     /* */
859     /* Return TRUE if value for field is NULL. */
860     /* */
861     /* Contributed by Jim Matthews. */
862     /************************************************************************/
863    
864     int SHPAPI_CALL
865     DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
866    
867     {
868     const char *pszValue;
869    
870     pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
871    
872     switch(psDBF->pachFieldType[iField])
873     {
874     case 'N':
875     case 'F':
876     /* NULL numeric fields have value "****************" */
877     return pszValue[0] == '*';
878    
879     case 'D':
880     /* NULL date fields have value "00000000" */
881     return strncmp(pszValue,"00000000",8) == 0;
882    
883     case 'L':
884     /* NULL boolean fields have value "?" */
885     return pszValue[0] == '?';
886    
887     default:
888     /* empty string fields are considered NULL */
889     return strlen(pszValue) == 0;
890     }
891     }
892    
893     /************************************************************************/
894     /* DBFGetFieldCount() */
895     /* */
896     /* Return the number of fields in this table. */
897     /************************************************************************/
898    
899     int SHPAPI_CALL
900     DBFGetFieldCount( DBFHandle psDBF )
901    
902     {
903     return( psDBF->nFields );
904     }
905    
906     /************************************************************************/
907     /* DBFGetRecordCount() */
908     /* */
909     /* Return the number of records in this table. */
910     /************************************************************************/
911    
912     int SHPAPI_CALL
913     DBFGetRecordCount( DBFHandle psDBF )
914    
915     {
916     return( psDBF->nRecords );
917     }
918    
919     /************************************************************************/
920     /* DBFGetFieldInfo() */
921     /* */
922     /* Return any requested information about the field. */
923     /************************************************************************/
924    
925     DBFFieldType SHPAPI_CALL
926     DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
927     int * pnWidth, int * pnDecimals )
928    
929     {
930     if( iField < 0 || iField >= psDBF->nFields )
931     return( FTInvalid );
932    
933     if( pnWidth != NULL )
934     *pnWidth = psDBF->panFieldSize[iField];
935    
936     if( pnDecimals != NULL )
937     *pnDecimals = psDBF->panFieldDecimals[iField];
938    
939     if( pszFieldName != NULL )
940     {
941     int i;
942    
943     strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*32, 11 );
944     pszFieldName[11] = '\0';
945     for( i = 10; i > 0 && pszFieldName[i] == ' '; i-- )
946     pszFieldName[i] = '\0';
947     }
948    
949 bh 1769 if ( psDBF->pachFieldType[iField] == 'L' )
950     return( FTLogical);
951    
952     else if( psDBF->pachFieldType[iField] == 'N'
953     || psDBF->pachFieldType[iField] == 'F'
954     || psDBF->pachFieldType[iField] == 'D' )
955 jan 1612 {
956     if( psDBF->panFieldDecimals[iField] > 0 )
957     return( FTDouble );
958     else
959     return( FTInteger );
960     }
961     else
962     {
963     return( FTString );
964     }
965     }
966    
967     /************************************************************************/
968     /* DBFWriteAttribute() */
969     /* */
970     /* Write an attribute record to the file. */
971     /************************************************************************/
972    
973     static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
974     void * pValue )
975    
976     {
977 bh 1769 int nRecordOffset, i, j, nRetResult = TRUE;
978 jan 1612 unsigned char *pabyRec;
979     char szSField[400], szFormat[20];
980    
981     /* -------------------------------------------------------------------- */
982     /* Is this a valid record? */
983     /* -------------------------------------------------------------------- */
984     if( hEntity < 0 || hEntity > psDBF->nRecords )
985     return( FALSE );
986    
987     if( psDBF->bNoHeader )
988     DBFWriteHeader(psDBF);
989    
990     /* -------------------------------------------------------------------- */
991     /* Is this a brand new record? */
992     /* -------------------------------------------------------------------- */
993     if( hEntity == psDBF->nRecords )
994     {
995     DBFFlushRecord( psDBF );
996    
997     psDBF->nRecords++;
998     for( i = 0; i < psDBF->nRecordLength; i++ )
999     psDBF->pszCurrentRecord[i] = ' ';
1000    
1001     psDBF->nCurrentRecord = hEntity;
1002     }
1003    
1004     /* -------------------------------------------------------------------- */
1005     /* Is this an existing record, but different than the last one */
1006     /* we accessed? */
1007     /* -------------------------------------------------------------------- */
1008     if( psDBF->nCurrentRecord != hEntity )
1009     {
1010     DBFFlushRecord( psDBF );
1011    
1012     nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
1013    
1014     fseek( psDBF->fp, nRecordOffset, 0 );
1015     fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
1016    
1017     psDBF->nCurrentRecord = hEntity;
1018     }
1019    
1020     pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
1021    
1022     psDBF->bCurrentRecordModified = TRUE;
1023     psDBF->bUpdated = TRUE;
1024    
1025     /* -------------------------------------------------------------------- */
1026     /* Translate NULL value to valid DBF file representation. */
1027     /* */
1028     /* Contributed by Jim Matthews. */
1029     /* -------------------------------------------------------------------- */
1030     if( pValue == NULL )
1031     {
1032     switch(psDBF->pachFieldType[iField])
1033     {
1034     case 'N':
1035     case 'F':
1036     /* NULL numeric fields have value "****************" */
1037     memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '*',
1038     psDBF->panFieldSize[iField] );
1039     break;
1040    
1041     case 'D':
1042     /* NULL date fields have value "00000000" */
1043     memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '0',
1044     psDBF->panFieldSize[iField] );
1045     break;
1046    
1047     case 'L':
1048     /* NULL boolean fields have value "?" */
1049     memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '?',
1050     psDBF->panFieldSize[iField] );
1051     break;
1052    
1053     default:
1054     /* empty string fields are considered NULL */
1055     memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '\0',
1056     psDBF->panFieldSize[iField] );
1057     break;
1058     }
1059     return TRUE;
1060     }
1061    
1062     /* -------------------------------------------------------------------- */
1063     /* Assign all the record fields. */
1064     /* -------------------------------------------------------------------- */
1065     switch( psDBF->pachFieldType[iField] )
1066     {
1067     case 'D':
1068     case 'N':
1069     case 'F':
1070     if( psDBF->panFieldDecimals[iField] == 0 )
1071     {
1072     int nWidth = psDBF->panFieldSize[iField];
1073    
1074     if( sizeof(szSField)-2 < nWidth )
1075     nWidth = sizeof(szSField)-2;
1076    
1077     sprintf( szFormat, "%%%dd", nWidth );
1078     sprintf(szSField, szFormat, (int) *((double *) pValue) );
1079     if( (int)strlen(szSField) > psDBF->panFieldSize[iField] )
1080 bh 1769 {
1081 jan 1612 szSField[psDBF->panFieldSize[iField]] = '\0';
1082 bh 1769 nRetResult = FALSE;
1083     }
1084 jan 1612
1085     strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
1086     szSField, strlen(szSField) );
1087     }
1088     else
1089     {
1090     int nWidth = psDBF->panFieldSize[iField];
1091    
1092     if( sizeof(szSField)-2 < nWidth )
1093     nWidth = sizeof(szSField)-2;
1094    
1095     sprintf( szFormat, "%%%d.%df",
1096     nWidth, psDBF->panFieldDecimals[iField] );
1097     sprintf(szSField, szFormat, *((double *) pValue) );
1098     if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
1099 bh 1769 {
1100 jan 1612 szSField[psDBF->panFieldSize[iField]] = '\0';
1101 bh 1769 nRetResult = FALSE;
1102     }
1103 jan 1612 strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
1104     szSField, strlen(szSField) );
1105     }
1106     break;
1107    
1108 bh 1769 case 'L':
1109     if (psDBF->panFieldSize[iField] >= 1 &&
1110     (*(char*)pValue == 'F' || *(char*)pValue == 'T'))
1111     *(pabyRec+psDBF->panFieldOffset[iField]) = *(char*)pValue;
1112     break;
1113    
1114 jan 1612 default:
1115     if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] )
1116 bh 1769 {
1117 jan 1612 j = psDBF->panFieldSize[iField];
1118 bh 1769 nRetResult = FALSE;
1119     }
1120 jan 1612 else
1121     {
1122     memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
1123     psDBF->panFieldSize[iField] );
1124     j = strlen((char *) pValue);
1125     }
1126    
1127     strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
1128     (char *) pValue, j );
1129     break;
1130     }
1131    
1132 bh 1769 return( nRetResult );
1133     }
1134    
1135     /************************************************************************/
1136     /* DBFWriteAttributeDirectly() */
1137     /* */
1138     /* Write an attribute record to the file, but without any */
1139     /* reformatting based on type. The provided buffer is written */
1140     /* as is to the field position in the record. */
1141     /************************************************************************/
1142    
1143     int DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
1144     void * pValue )
1145    
1146     {
1147     int nRecordOffset, i, j;
1148     unsigned char *pabyRec;
1149    
1150     /* -------------------------------------------------------------------- */
1151     /* Is this a valid record? */
1152     /* -------------------------------------------------------------------- */
1153     if( hEntity < 0 || hEntity > psDBF->nRecords )
1154     return( FALSE );
1155    
1156     if( psDBF->bNoHeader )
1157     DBFWriteHeader(psDBF);
1158    
1159     /* -------------------------------------------------------------------- */
1160     /* Is this a brand new record? */
1161     /* -------------------------------------------------------------------- */
1162     if( hEntity == psDBF->nRecords )
1163     {
1164     DBFFlushRecord( psDBF );
1165    
1166     psDBF->nRecords++;
1167     for( i = 0; i < psDBF->nRecordLength; i++ )
1168     psDBF->pszCurrentRecord[i] = ' ';
1169    
1170     psDBF->nCurrentRecord = hEntity;
1171     }
1172    
1173     /* -------------------------------------------------------------------- */
1174     /* Is this an existing record, but different than the last one */
1175     /* we accessed? */
1176     /* -------------------------------------------------------------------- */
1177     if( psDBF->nCurrentRecord != hEntity )
1178     {
1179     DBFFlushRecord( psDBF );
1180    
1181     nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
1182    
1183     fseek( psDBF->fp, nRecordOffset, 0 );
1184     fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
1185    
1186     psDBF->nCurrentRecord = hEntity;
1187     }
1188    
1189     pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
1190    
1191     /* -------------------------------------------------------------------- */
1192     /* Assign all the record fields. */
1193     /* -------------------------------------------------------------------- */
1194     if( (int)strlen((char *) pValue) > psDBF->panFieldSize[iField] )
1195     j = psDBF->panFieldSize[iField];
1196     else
1197     {
1198     memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
1199     psDBF->panFieldSize[iField] );
1200     j = strlen((char *) pValue);
1201     }
1202    
1203     strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
1204     (char *) pValue, j );
1205    
1206     psDBF->bCurrentRecordModified = TRUE;
1207     psDBF->bUpdated = TRUE;
1208    
1209 jan 1612 return( TRUE );
1210     }
1211    
1212     /************************************************************************/
1213     /* DBFWriteDoubleAttribute() */
1214     /* */
1215     /* Write a double attribute. */
1216     /************************************************************************/
1217    
1218     int SHPAPI_CALL
1219     DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
1220     double dValue )
1221    
1222     {
1223     return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
1224     }
1225    
1226     /************************************************************************/
1227     /* DBFWriteIntegerAttribute() */
1228     /* */
1229     /* Write a integer attribute. */
1230     /************************************************************************/
1231    
1232     int SHPAPI_CALL
1233     DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
1234     int nValue )
1235    
1236     {
1237     double dValue = nValue;
1238    
1239     return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
1240     }
1241    
1242     /************************************************************************/
1243     /* DBFWriteStringAttribute() */
1244     /* */
1245     /* Write a string attribute. */
1246     /************************************************************************/
1247    
1248     int SHPAPI_CALL
1249     DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
1250     const char * pszValue )
1251    
1252     {
1253     return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) pszValue ) );
1254     }
1255    
1256     /************************************************************************/
1257     /* DBFWriteNULLAttribute() */
1258     /* */
1259     /* Write a string attribute. */
1260     /************************************************************************/
1261    
1262     int SHPAPI_CALL
1263     DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
1264    
1265     {
1266     return( DBFWriteAttribute( psDBF, iRecord, iField, NULL ) );
1267     }
1268    
1269     /************************************************************************/
1270 bh 1769 /* DBFWriteLogicalAttribute() */
1271     /* */
1272     /* Write a logical attribute. */
1273     /************************************************************************/
1274    
1275     int SHPAPI_CALL
1276     DBFWriteLogicalAttribute( DBFHandle psDBF, int iRecord, int iField,
1277     const char lValue)
1278    
1279     {
1280     return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) (&lValue) ) );
1281     }
1282    
1283     /************************************************************************/
1284 jan 1612 /* DBFWriteTuple() */
1285     /* */
1286     /* Write an attribute record to the file. */
1287     /************************************************************************/
1288    
1289     int SHPAPI_CALL
1290     DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
1291    
1292     {
1293     int nRecordOffset, i;
1294     unsigned char *pabyRec;
1295    
1296     /* -------------------------------------------------------------------- */
1297     /* Is this a valid record? */
1298     /* -------------------------------------------------------------------- */
1299     if( hEntity < 0 || hEntity > psDBF->nRecords )
1300     return( FALSE );
1301    
1302     if( psDBF->bNoHeader )
1303     DBFWriteHeader(psDBF);
1304    
1305     /* -------------------------------------------------------------------- */
1306     /* Is this a brand new record? */
1307     /* -------------------------------------------------------------------- */
1308     if( hEntity == psDBF->nRecords )
1309     {
1310     DBFFlushRecord( psDBF );
1311    
1312     psDBF->nRecords++;
1313     for( i = 0; i < psDBF->nRecordLength; i++ )
1314     psDBF->pszCurrentRecord[i] = ' ';
1315    
1316     psDBF->nCurrentRecord = hEntity;
1317     }
1318    
1319     /* -------------------------------------------------------------------- */
1320     /* Is this an existing record, but different than the last one */
1321     /* we accessed? */
1322     /* -------------------------------------------------------------------- */
1323     if( psDBF->nCurrentRecord != hEntity )
1324     {
1325     DBFFlushRecord( psDBF );
1326    
1327     nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
1328    
1329     fseek( psDBF->fp, nRecordOffset, 0 );
1330     fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
1331    
1332     psDBF->nCurrentRecord = hEntity;
1333     }
1334    
1335     pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
1336    
1337     memcpy ( pabyRec, pRawTuple, psDBF->nRecordLength );
1338    
1339     psDBF->bCurrentRecordModified = TRUE;
1340     psDBF->bUpdated = TRUE;
1341    
1342     return( TRUE );
1343     }
1344    
1345     /************************************************************************/
1346     /* DBFReadTuple() */
1347     /* */
1348     /* Read one of the attribute fields of a record. */
1349     /************************************************************************/
1350    
1351     const char SHPAPI_CALL1(*)
1352     DBFReadTuple(DBFHandle psDBF, int hEntity )
1353    
1354     {
1355     int nRecordOffset;
1356     unsigned char *pabyRec;
1357     static char *pReturnTuple = NULL;
1358    
1359     static int nTupleLen = 0;
1360    
1361     /* -------------------------------------------------------------------- */
1362     /* Have we read the record? */
1363     /* -------------------------------------------------------------------- */
1364     if( hEntity < 0 || hEntity >= psDBF->nRecords )
1365     return( NULL );
1366    
1367     if( psDBF->nCurrentRecord != hEntity )
1368     {
1369     DBFFlushRecord( psDBF );
1370    
1371     nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
1372    
1373     fseek( psDBF->fp, nRecordOffset, 0 );
1374     fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
1375    
1376     psDBF->nCurrentRecord = hEntity;
1377     }
1378    
1379     pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
1380    
1381     if ( nTupleLen < psDBF->nRecordLength) {
1382     nTupleLen = psDBF->nRecordLength;
1383     pReturnTuple = (char *) SfRealloc(pReturnTuple, psDBF->nRecordLength);
1384     }
1385    
1386     memcpy ( pReturnTuple, pabyRec, psDBF->nRecordLength );
1387    
1388     return( pReturnTuple );
1389     }
1390    
1391     /************************************************************************/
1392     /* DBFCloneEmpty() */
1393     /* */
1394     /* Read one of the attribute fields of a record. */
1395     /************************************************************************/
1396    
1397     DBFHandle SHPAPI_CALL
1398     DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
1399     {
1400     DBFHandle newDBF;
1401    
1402     newDBF = DBFCreate ( pszFilename );
1403     if ( newDBF == NULL ) return ( NULL );
1404    
1405 bh 1769 newDBF->pszHeader = (char *) malloc ( 32 * psDBF->nFields );
1406 jan 1612 memcpy ( newDBF->pszHeader, psDBF->pszHeader, 32 * psDBF->nFields );
1407    
1408     newDBF->nFields = psDBF->nFields;
1409     newDBF->nRecordLength = psDBF->nRecordLength;
1410 bh 1769 newDBF->nHeaderLength = 32 * (psDBF->nFields+1);
1411 jan 1612
1412 bh 1769 newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields );
1413 jan 1612 memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
1414 bh 1769 newDBF->panFieldSize = (int *) malloc ( sizeof(int) * psDBF->nFields );
1415 jan 1612 memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
1416 bh 1769 newDBF->panFieldDecimals = (int *) malloc ( sizeof(int) * psDBF->nFields );
1417 jan 1612 memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
1418 bh 1769 newDBF->pachFieldType = (char *) malloc ( sizeof(int) * psDBF->nFields );
1419 jan 1612 memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(int) * psDBF->nFields );
1420    
1421     newDBF->bNoHeader = TRUE;
1422     newDBF->bUpdated = TRUE;
1423    
1424     DBFWriteHeader ( newDBF );
1425     DBFClose ( newDBF );
1426    
1427     newDBF = DBFOpen ( pszFilename, "rb+" );
1428    
1429     return ( newDBF );
1430     }
1431    
1432     /************************************************************************/
1433     /* DBFGetNativeFieldType() */
1434     /* */
1435     /* Return the DBase field type for the specified field. */
1436     /* */
1437     /* Value can be one of: 'C' (String), 'D' (Date), 'F' (Float), */
1438     /* 'N' (Numeric, with or without decimal), */
1439     /* 'L' (Logical), */
1440     /* 'M' (Memo: 10 digits .DBT block ptr) */
1441     /************************************************************************/
1442    
1443     char SHPAPI_CALL
1444     DBFGetNativeFieldType( DBFHandle psDBF, int iField )
1445    
1446     {
1447     if( iField >=0 && iField < psDBF->nFields )
1448     return psDBF->pachFieldType[iField];
1449    
1450     return ' ';
1451     }
1452    
1453     /************************************************************************/
1454     /* str_to_upper() */
1455     /************************************************************************/
1456    
1457     static void str_to_upper (char *string)
1458     {
1459     int len;
1460     short i = -1;
1461    
1462     len = strlen (string);
1463    
1464     while (++i < len)
1465     if (isalpha(string[i]) && islower(string[i]))
1466     string[i] = toupper ((int)string[i]);
1467     }
1468    
1469     /************************************************************************/
1470     /* DBFGetFieldIndex() */
1471     /* */
1472     /* Get the index number for a field in a .dbf file. */
1473     /* */
1474     /* Contributed by Jim Matthews. */
1475     /************************************************************************/
1476    
1477     int SHPAPI_CALL
1478     DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
1479    
1480     {
1481     char name[12], name1[12], name2[12];
1482     int i;
1483    
1484     strncpy(name1, pszFieldName,11);
1485 bh 1769 name1[11] = '\0';
1486 jan 1612 str_to_upper(name1);
1487    
1488     for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
1489     {
1490     DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
1491     strncpy(name2,name,11);
1492     str_to_upper(name2);
1493    
1494     if(!strncmp(name1,name2,10))
1495     return(i);
1496     }
1497     return(-1);
1498     }
1499    
1500     /************************************************************************/
1501     /* DBFCommit() */
1502     /* */
1503     /* Write any changes made into the file. */
1504     /* */
1505     /************************************************************************/
1506     int SHPAPI_CALL
1507     DBFCommit( DBFHandle psDBF )
1508    
1509     {
1510     DBFFlushRecord( psDBF );
1511     if (fflush( psDBF->fp ) == EOF)
1512     return FALSE;
1513    
1514     return TRUE;
1515     }

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26