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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1769 - (show 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 /******************************************************************************
2 * $Id$
3 *
4 * Project: Shapelib
5 * Purpose: Implementation of .dbf access API documented in dbf_api.html.
6 * Author: Frank Warmerdam, [email protected]
7 *
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 * Revision 1.2 2003/10/02 15:15:16 bh
38 * Update to shapelib 1.2.10
39 *
40 * Revision 1.48 2003/03/10 14:51:27 warmerda
41 * DBFWrite* calls now return FALSE if they have to truncate
42 *
43 * Revision 1.47 2002/11/20 03:32:22 warmerda
44 * Ensure field name in DBFGetFieldIndex() is properly terminated.
45 *
46 * 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 * 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 int nFields, nHeadLen, nRecLen, iField, i;
314 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 if( fread( pabyBuf, 32, 1, psDBF->fp ) != 1 )
374 {
375 fclose( psDBF->fp );
376 free( pabyBuf );
377 free( psDBF );
378 return NULL;
379 }
380
381 psDBF->nRecords =
382 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 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
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 if( nWidth < 1 )
608 return -1;
609
610 /* -------------------------------------------------------------------- */
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 if( eType == FTLogical )
637 psDBF->pachFieldType[psDBF->nFields-1] = 'L';
638 else if( eType == FTString )
639 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 /* 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 /* 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 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 {
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 int nRecordOffset, i, j, nRetResult = TRUE;
978 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 {
1081 szSField[psDBF->panFieldSize[iField]] = '\0';
1082 nRetResult = FALSE;
1083 }
1084
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 {
1100 szSField[psDBF->panFieldSize[iField]] = '\0';
1101 nRetResult = FALSE;
1102 }
1103 strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
1104 szSField, strlen(szSField) );
1105 }
1106 break;
1107
1108 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 default:
1115 if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] )
1116 {
1117 j = psDBF->panFieldSize[iField];
1118 nRetResult = FALSE;
1119 }
1120 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 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 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 /* 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 /* 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 newDBF->pszHeader = (char *) malloc ( 32 * psDBF->nFields );
1406 memcpy ( newDBF->pszHeader, psDBF->pszHeader, 32 * psDBF->nFields );
1407
1408 newDBF->nFields = psDBF->nFields;
1409 newDBF->nRecordLength = psDBF->nRecordLength;
1410 newDBF->nHeaderLength = 32 * (psDBF->nFields+1);
1411
1412 newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields );
1413 memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
1414 newDBF->panFieldSize = (int *) malloc ( sizeof(int) * psDBF->nFields );
1415 memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
1416 newDBF->panFieldDecimals = (int *) malloc ( sizeof(int) * psDBF->nFields );
1417 memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
1418 newDBF->pachFieldType = (char *) malloc ( sizeof(int) * psDBF->nFields );
1419 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 name1[11] = '\0';
1486 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