00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 static char rcsid[] =
00186 "$Id: dbfopen.c,v 1.48 2003/03/10 14:51:27 warmerda Exp $";
00187
00188 #include "shapefil.h"
00189
00190 #include <math.h>
00191 #include <stdlib.h>
00192 #include <ctype.h>
00193 #include <string.h>
00194
00195 #ifndef FALSE
00196 # define FALSE 0
00197 # define TRUE 1
00198 #endif
00199
00200 static int nStringFieldLen = 0;
00201 static char * pszStringField = NULL;
00202
00203
00204
00205
00206
00207
00208
00209
00210 static void * SfRealloc( void * pMem, int nNewSize )
00211
00212 {
00213 if( pMem == NULL )
00214 return( (void *) malloc(nNewSize) );
00215 else
00216 return( (void *) realloc(pMem,nNewSize) );
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 static void DBFWriteHeader(DBFHandle psDBF)
00229
00230 {
00231 unsigned char abyHeader[XBASE_FLDHDR_SZ];
00232 int i;
00233
00234 if( !psDBF->bNoHeader )
00235 return;
00236
00237 psDBF->bNoHeader = FALSE;
00238
00239
00240
00241
00242 for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
00243 abyHeader[i] = 0;
00244
00245 abyHeader[0] = 0x03;
00246
00247
00248
00249 abyHeader[8] = psDBF->nHeaderLength % 256;
00250 abyHeader[9] = psDBF->nHeaderLength / 256;
00251
00252 abyHeader[10] = psDBF->nRecordLength % 256;
00253 abyHeader[11] = psDBF->nRecordLength / 256;
00254
00255
00256
00257
00258
00259 fseek( psDBF->fp, 0, 0 );
00260 fwrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
00261 fwrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields, psDBF->fp );
00262
00263
00264
00265
00266 if( psDBF->nHeaderLength > 32*psDBF->nFields + 32 )
00267 {
00268 char cNewline;
00269
00270 cNewline = 0x0d;
00271 fwrite( &cNewline, 1, 1, psDBF->fp );
00272 }
00273 }
00274
00275
00276
00277
00278
00279
00280
00281 static void DBFFlushRecord( DBFHandle psDBF )
00282
00283 {
00284 int nRecordOffset;
00285
00286 if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
00287 {
00288 psDBF->bCurrentRecordModified = FALSE;
00289
00290 nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord
00291 + psDBF->nHeaderLength;
00292
00293 fseek( psDBF->fp, nRecordOffset, 0 );
00294 fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303
00304 DBFHandle SHPAPI_CALL
00305 DBFOpen( const char * pszFilename, const char * pszAccess )
00306
00307 {
00308 DBFHandle psDBF;
00309 unsigned char *pabyBuf;
00310 int nFields, nHeadLen, nRecLen, iField, i;
00311 char *pszBasename, *pszFullname;
00312
00313
00314
00315
00316 if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
00317 && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
00318 && strcmp(pszAccess,"r+b") != 0 )
00319 return( NULL );
00320
00321 if( strcmp(pszAccess,"r") == 0 )
00322 pszAccess = "rb";
00323
00324 if( strcmp(pszAccess,"r+") == 0 )
00325 pszAccess = "rb+";
00326
00327
00328
00329
00330
00331 pszBasename = (char *) malloc(strlen(pszFilename)+5);
00332 strcpy( pszBasename, pszFilename );
00333 for( i = strlen(pszBasename)-1;
00334 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
00335 && pszBasename[i] != '\\';
00336 i-- ) {}
00337
00338 if( pszBasename[i] == '.' )
00339 pszBasename[i] = '\0';
00340
00341 pszFullname = (char *) malloc(strlen(pszBasename) + 5);
00342 sprintf( pszFullname, "%s.dbf", pszBasename );
00343
00344 psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
00345 psDBF->fp = fopen( pszFullname, pszAccess );
00346
00347 if( psDBF->fp == NULL )
00348 {
00349 sprintf( pszFullname, "%s.DBF", pszBasename );
00350 psDBF->fp = fopen(pszFullname, pszAccess );
00351 }
00352
00353 free( pszBasename );
00354 free( pszFullname );
00355
00356 if( psDBF->fp == NULL )
00357 {
00358 free( psDBF );
00359 return( NULL );
00360 }
00361
00362 psDBF->bNoHeader = FALSE;
00363 psDBF->nCurrentRecord = -1;
00364 psDBF->bCurrentRecordModified = FALSE;
00365
00366
00367
00368
00369 pabyBuf = (unsigned char *) malloc(500);
00370 if( fread( pabyBuf, 32, 1, psDBF->fp ) != 1 )
00371 {
00372 fclose( psDBF->fp );
00373 free( pabyBuf );
00374 free( psDBF );
00375 return NULL;
00376 }
00377
00378 psDBF->nRecords =
00379 pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;
00380
00381 psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
00382 psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;
00383
00384 psDBF->nFields = nFields = (nHeadLen - 32) / 32;
00385
00386 psDBF->pszCurrentRecord = (char *) malloc(nRecLen);
00387
00388
00389
00390
00391
00392 pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
00393 psDBF->pszHeader = (char *) pabyBuf;
00394
00395 fseek( psDBF->fp, 32, 0 );
00396 if( fread( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
00397 {
00398 fclose( psDBF->fp );
00399 free( pabyBuf );
00400 free( psDBF );
00401 return NULL;
00402 }
00403
00404 psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
00405 psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
00406 psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
00407 psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);
00408
00409 for( iField = 0; iField < nFields; iField++ )
00410 {
00411 unsigned char *pabyFInfo;
00412
00413 pabyFInfo = pabyBuf+iField*32;
00414
00415 if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
00416 {
00417 psDBF->panFieldSize[iField] = pabyFInfo[16];
00418 psDBF->panFieldDecimals[iField] = pabyFInfo[17];
00419 }
00420 else
00421 {
00422 psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
00423 psDBF->panFieldDecimals[iField] = 0;
00424 }
00425
00426 psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
00427 if( iField == 0 )
00428 psDBF->panFieldOffset[iField] = 1;
00429 else
00430 psDBF->panFieldOffset[iField] =
00431 psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
00432 }
00433
00434 return( psDBF );
00435 }
00436
00437
00438
00439
00440
00441 void SHPAPI_CALL
00442 DBFClose(DBFHandle psDBF)
00443 {
00444
00445
00446
00447 if( psDBF->bNoHeader )
00448 DBFWriteHeader( psDBF );
00449
00450 DBFFlushRecord( psDBF );
00451
00452
00453
00454
00455
00456 if( psDBF->bUpdated )
00457 {
00458 unsigned char abyFileHeader[32];
00459
00460 fseek( psDBF->fp, 0, 0 );
00461 fread( abyFileHeader, 32, 1, psDBF->fp );
00462
00463 abyFileHeader[1] = 95;
00464 abyFileHeader[2] = 7;
00465 abyFileHeader[3] = 26;
00466
00467 abyFileHeader[4] = psDBF->nRecords % 256;
00468 abyFileHeader[5] = (psDBF->nRecords/256) % 256;
00469 abyFileHeader[6] = (psDBF->nRecords/(256*256)) % 256;
00470 abyFileHeader[7] = (psDBF->nRecords/(256*256*256)) % 256;
00471
00472 fseek( psDBF->fp, 0, 0 );
00473 fwrite( abyFileHeader, 32, 1, psDBF->fp );
00474 }
00475
00476
00477
00478
00479 fclose( psDBF->fp );
00480
00481 if( psDBF->panFieldOffset != NULL )
00482 {
00483 free( psDBF->panFieldOffset );
00484 free( psDBF->panFieldSize );
00485 free( psDBF->panFieldDecimals );
00486 free( psDBF->pachFieldType );
00487 }
00488
00489 free( psDBF->pszHeader );
00490 free( psDBF->pszCurrentRecord );
00491
00492 free( psDBF );
00493
00494 if( pszStringField != NULL )
00495 {
00496 free( pszStringField );
00497 pszStringField = NULL;
00498 nStringFieldLen = 0;
00499 }
00500 }
00501
00502
00503
00504
00505
00506
00507
00508 DBFHandle SHPAPI_CALL
00509 DBFCreate( const char * pszFilename )
00510
00511 {
00512 DBFHandle psDBF;
00513 FILE *fp;
00514 char *pszFullname, *pszBasename;
00515 int i;
00516
00517
00518
00519
00520
00521 pszBasename = (char *) malloc(strlen(pszFilename)+5);
00522 strcpy( pszBasename, pszFilename );
00523 for( i = strlen(pszBasename)-1;
00524 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
00525 && pszBasename[i] != '\\';
00526 i-- ) {}
00527
00528 if( pszBasename[i] == '.' )
00529 pszBasename[i] = '\0';
00530
00531 pszFullname = (char *) malloc(strlen(pszBasename) + 5);
00532 sprintf( pszFullname, "%s.dbf", pszBasename );
00533 free( pszBasename );
00534
00535
00536
00537
00538 fp = fopen( pszFullname, "wb" );
00539 if( fp == NULL )
00540 return( NULL );
00541
00542 fputc( 0, fp );
00543 fclose( fp );
00544
00545 fp = fopen( pszFullname, "rb+" );
00546 if( fp == NULL )
00547 return( NULL );
00548
00549 free( pszFullname );
00550
00551
00552
00553
00554 psDBF = (DBFHandle) malloc(sizeof(DBFInfo));
00555
00556 psDBF->fp = fp;
00557 psDBF->nRecords = 0;
00558 psDBF->nFields = 0;
00559 psDBF->nRecordLength = 1;
00560 psDBF->nHeaderLength = 33;
00561
00562 psDBF->panFieldOffset = NULL;
00563 psDBF->panFieldSize = NULL;
00564 psDBF->panFieldDecimals = NULL;
00565 psDBF->pachFieldType = NULL;
00566 psDBF->pszHeader = NULL;
00567
00568 psDBF->nCurrentRecord = -1;
00569 psDBF->bCurrentRecordModified = FALSE;
00570 psDBF->pszCurrentRecord = NULL;
00571
00572 psDBF->bNoHeader = TRUE;
00573
00574 return( psDBF );
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584 int SHPAPI_CALL
00585 DBFAddField(DBFHandle psDBF, const char * pszFieldName,
00586 DBFFieldType eType, int nWidth, int nDecimals )
00587
00588 {
00589 char *pszFInfo;
00590 int i;
00591
00592
00593
00594
00595 if( psDBF->nRecords > 0 )
00596 return( -1 );
00597
00598 if( !psDBF->bNoHeader )
00599 return( -1 );
00600
00601 if( eType != FTDouble && nDecimals != 0 )
00602 return( -1 );
00603
00604 if( nWidth < 1 )
00605 return -1;
00606
00607
00608
00609
00610
00611 psDBF->nFields++;
00612
00613 psDBF->panFieldOffset = (int *)
00614 SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
00615
00616 psDBF->panFieldSize = (int *)
00617 SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
00618
00619 psDBF->panFieldDecimals = (int *)
00620 SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
00621
00622 psDBF->pachFieldType = (char *)
00623 SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
00624
00625
00626
00627
00628 psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
00629 psDBF->nRecordLength += nWidth;
00630 psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
00631 psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
00632
00633 if( eType == FTLogical )
00634 psDBF->pachFieldType[psDBF->nFields-1] = 'L';
00635 else if( eType == FTString )
00636 psDBF->pachFieldType[psDBF->nFields-1] = 'C';
00637 else
00638 psDBF->pachFieldType[psDBF->nFields-1] = 'N';
00639
00640
00641
00642
00643 psDBF->nHeaderLength += 32;
00644 psDBF->bUpdated = FALSE;
00645
00646 psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
00647
00648 pszFInfo = psDBF->pszHeader + 32 * (psDBF->nFields-1);
00649
00650 for( i = 0; i < 32; i++ )
00651 pszFInfo[i] = '\0';
00652
00653 if( (int) strlen(pszFieldName) < 10 )
00654 strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
00655 else
00656 strncpy( pszFInfo, pszFieldName, 10);
00657
00658 pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
00659
00660 if( eType == FTString )
00661 {
00662 pszFInfo[16] = nWidth % 256;
00663 pszFInfo[17] = nWidth / 256;
00664 }
00665 else
00666 {
00667 pszFInfo[16] = nWidth;
00668 pszFInfo[17] = nDecimals;
00669 }
00670
00671
00672
00673
00674 psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
00675 psDBF->nRecordLength);
00676
00677 return( psDBF->nFields-1 );
00678 }
00679
00680
00681
00682
00683
00684
00685
00686 static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
00687 char chReqType )
00688
00689 {
00690 int nRecordOffset;
00691 unsigned char *pabyRec;
00692 void *pReturnField = NULL;
00693
00694 static double dDoubleField;
00695
00696
00697
00698
00699 if( hEntity < 0 || hEntity >= psDBF->nRecords )
00700 return( NULL );
00701
00702 if( iField < 0 || iField >= psDBF->nFields )
00703 return( NULL );
00704
00705
00706
00707
00708 if( psDBF->nCurrentRecord != hEntity )
00709 {
00710 DBFFlushRecord( psDBF );
00711
00712 nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
00713
00714 if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 )
00715 {
00716 fprintf( stderr, "fseek(%d) failed on DBF file.\n",
00717 nRecordOffset );
00718 return NULL;
00719 }
00720
00721 if( fread( psDBF->pszCurrentRecord, psDBF->nRecordLength,
00722 1, psDBF->fp ) != 1 )
00723 {
00724 fprintf( stderr, "fread(%d) failed on DBF file.\n",
00725 psDBF->nRecordLength );
00726 return NULL;
00727 }
00728
00729 psDBF->nCurrentRecord = hEntity;
00730 }
00731
00732 pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
00733
00734
00735
00736
00737 if( psDBF->panFieldSize[iField]+1 > nStringFieldLen )
00738 {
00739 nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10;
00740 pszStringField = (char *) SfRealloc(pszStringField,nStringFieldLen);
00741 }
00742
00743
00744
00745
00746 strncpy( pszStringField,
00747 ((const char *) pabyRec) + psDBF->panFieldOffset[iField],
00748 psDBF->panFieldSize[iField] );
00749 pszStringField[psDBF->panFieldSize[iField]] = '\0';
00750
00751 pReturnField = pszStringField;
00752
00753
00754
00755
00756 if( chReqType == 'N' )
00757 {
00758 dDoubleField = atof(pszStringField);
00759
00760 pReturnField = &dDoubleField;
00761 }
00762
00763
00764
00765
00766 #ifdef TRIM_DBF_WHITESPACE
00767 else
00768 {
00769 char *pchSrc, *pchDst;
00770
00771 pchDst = pchSrc = pszStringField;
00772 while( *pchSrc == ' ' )
00773 pchSrc++;
00774
00775 while( *pchSrc != '\0' )
00776 *(pchDst++) = *(pchSrc++);
00777 *pchDst = '\0';
00778
00779 while( pchDst != pszStringField && *(--pchDst) == ' ' )
00780 *pchDst = '\0';
00781 }
00782 #endif
00783
00784 return( pReturnField );
00785 }
00786
00787
00788
00789
00790
00791
00792
00793 int SHPAPI_CALL
00794 DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
00795
00796 {
00797 double *pdValue;
00798
00799 pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
00800
00801 if( pdValue == NULL )
00802 return 0;
00803 else
00804 return( (int) *pdValue );
00805 }
00806
00807
00808
00809
00810
00811
00812
00813 double SHPAPI_CALL
00814 DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
00815
00816 {
00817 double *pdValue;
00818
00819 pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
00820
00821 if( pdValue == NULL )
00822 return 0.0;
00823 else
00824 return( *pdValue );
00825 }
00826
00827
00828
00829
00830
00831
00832
00833 const char SHPAPI_CALL1(*)
00834 DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
00835
00836 {
00837 return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
00838 }
00839
00840
00841
00842
00843
00844
00845
00846 const char SHPAPI_CALL1(*)
00847 DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
00848
00849 {
00850 return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
00851 }
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861 int SHPAPI_CALL
00862 DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
00863
00864 {
00865 const char *pszValue;
00866
00867 pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
00868
00869 switch(psDBF->pachFieldType[iField])
00870 {
00871 case 'N':
00872 case 'F':
00873
00874 return pszValue[0] == '*';
00875
00876 case 'D':
00877
00878 return strncmp(pszValue,"00000000",8) == 0;
00879
00880 case 'L':
00881
00882 return pszValue[0] == '?';
00883
00884 default:
00885
00886 return strlen(pszValue) == 0;
00887 }
00888 }
00889
00890
00891
00892
00893
00894
00895
00896 int SHPAPI_CALL
00897 DBFGetFieldCount( DBFHandle psDBF )
00898
00899 {
00900 return( psDBF->nFields );
00901 }
00902
00903
00904
00905
00906
00907
00908
00909 int SHPAPI_CALL
00910 DBFGetRecordCount( DBFHandle psDBF )
00911
00912 {
00913 return( psDBF->nRecords );
00914 }
00915
00916
00917
00918
00919
00920
00921
00922 DBFFieldType SHPAPI_CALL
00923 DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
00924 int * pnWidth, int * pnDecimals )
00925
00926 {
00927 if( iField < 0 || iField >= psDBF->nFields )
00928 return( FTInvalid );
00929
00930 if( pnWidth != NULL )
00931 *pnWidth = psDBF->panFieldSize[iField];
00932
00933 if( pnDecimals != NULL )
00934 *pnDecimals = psDBF->panFieldDecimals[iField];
00935
00936 if( pszFieldName != NULL )
00937 {
00938 int i;
00939
00940 strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*32, 11 );
00941 pszFieldName[11] = '\0';
00942 for( i = 10; i > 0 && pszFieldName[i] == ' '; i-- )
00943 pszFieldName[i] = '\0';
00944 }
00945
00946 if ( psDBF->pachFieldType[iField] == 'L' )
00947 return( FTLogical);
00948
00949 else if( psDBF->pachFieldType[iField] == 'N'
00950 || psDBF->pachFieldType[iField] == 'F'
00951 || psDBF->pachFieldType[iField] == 'D' )
00952 {
00953 if( psDBF->panFieldDecimals[iField] > 0 )
00954 return( FTDouble );
00955 else
00956 return( FTInteger );
00957 }
00958 else
00959 {
00960 return( FTString );
00961 }
00962 }
00963
00964
00965
00966
00967
00968
00969
00970 static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
00971 void * pValue )
00972
00973 {
00974 int nRecordOffset, i, j, nRetResult = TRUE;
00975 unsigned char *pabyRec;
00976 char szSField[400], szFormat[20];
00977
00978
00979
00980
00981 if( hEntity < 0 || hEntity > psDBF->nRecords )
00982 return( FALSE );
00983
00984 if( psDBF->bNoHeader )
00985 DBFWriteHeader(psDBF);
00986
00987
00988
00989
00990 if( hEntity == psDBF->nRecords )
00991 {
00992 DBFFlushRecord( psDBF );
00993
00994 psDBF->nRecords++;
00995 for( i = 0; i < psDBF->nRecordLength; i++ )
00996 psDBF->pszCurrentRecord[i] = ' ';
00997
00998 psDBF->nCurrentRecord = hEntity;
00999 }
01000
01001
01002
01003
01004
01005 if( psDBF->nCurrentRecord != hEntity )
01006 {
01007 DBFFlushRecord( psDBF );
01008
01009 nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
01010
01011 fseek( psDBF->fp, nRecordOffset, 0 );
01012 fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
01013
01014 psDBF->nCurrentRecord = hEntity;
01015 }
01016
01017 pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
01018
01019 psDBF->bCurrentRecordModified = TRUE;
01020 psDBF->bUpdated = TRUE;
01021
01022
01023
01024
01025
01026
01027 if( pValue == NULL )
01028 {
01029 switch(psDBF->pachFieldType[iField])
01030 {
01031 case 'N':
01032 case 'F':
01033
01034 memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '*',
01035 psDBF->panFieldSize[iField] );
01036 break;
01037
01038 case 'D':
01039
01040 memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '0',
01041 psDBF->panFieldSize[iField] );
01042 break;
01043
01044 case 'L':
01045
01046 memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '?',
01047 psDBF->panFieldSize[iField] );
01048 break;
01049
01050 default:
01051
01052 memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '\0',
01053 psDBF->panFieldSize[iField] );
01054 break;
01055 }
01056 return TRUE;
01057 }
01058
01059
01060
01061
01062 switch( psDBF->pachFieldType[iField] )
01063 {
01064 case 'D':
01065 case 'N':
01066 case 'F':
01067 if( psDBF->panFieldDecimals[iField] == 0 )
01068 {
01069 int nWidth = psDBF->panFieldSize[iField];
01070
01071 if( sizeof(szSField)-2 < nWidth )
01072 nWidth = sizeof(szSField)-2;
01073
01074 sprintf( szFormat, "%%%dd", nWidth );
01075 sprintf(szSField, szFormat, (int) *((double *) pValue) );
01076 if( (int)strlen(szSField) > psDBF->panFieldSize[iField] )
01077 {
01078 szSField[psDBF->panFieldSize[iField]] = '\0';
01079 nRetResult = FALSE;
01080 }
01081
01082 strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
01083 szSField, strlen(szSField) );
01084 }
01085 else
01086 {
01087 int nWidth = psDBF->panFieldSize[iField];
01088
01089 if( sizeof(szSField)-2 < nWidth )
01090 nWidth = sizeof(szSField)-2;
01091
01092 sprintf( szFormat, "%%%d.%df",
01093 nWidth, psDBF->panFieldDecimals[iField] );
01094 sprintf(szSField, szFormat, *((double *) pValue) );
01095 if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
01096 {
01097 szSField[psDBF->panFieldSize[iField]] = '\0';
01098 nRetResult = FALSE;
01099 }
01100 strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
01101 szSField, strlen(szSField) );
01102 }
01103 break;
01104
01105 case 'L':
01106 if (psDBF->panFieldSize[iField] >= 1 &&
01107 (*(char*)pValue == 'F' || *(char*)pValue == 'T'))
01108 *(pabyRec+psDBF->panFieldOffset[iField]) = *(char*)pValue;
01109 break;
01110
01111 default:
01112 if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] )
01113 {
01114 j = psDBF->panFieldSize[iField];
01115 nRetResult = FALSE;
01116 }
01117 else
01118 {
01119 memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
01120 psDBF->panFieldSize[iField] );
01121 j = strlen((char *) pValue);
01122 }
01123
01124 strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
01125 (char *) pValue, j );
01126 break;
01127 }
01128
01129 return( nRetResult );
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 int DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
01141 void * pValue )
01142
01143 {
01144 int nRecordOffset, i, j;
01145 unsigned char *pabyRec;
01146
01147
01148
01149
01150 if( hEntity < 0 || hEntity > psDBF->nRecords )
01151 return( FALSE );
01152
01153 if( psDBF->bNoHeader )
01154 DBFWriteHeader(psDBF);
01155
01156
01157
01158
01159 if( hEntity == psDBF->nRecords )
01160 {
01161 DBFFlushRecord( psDBF );
01162
01163 psDBF->nRecords++;
01164 for( i = 0; i < psDBF->nRecordLength; i++ )
01165 psDBF->pszCurrentRecord[i] = ' ';
01166
01167 psDBF->nCurrentRecord = hEntity;
01168 }
01169
01170
01171
01172
01173
01174 if( psDBF->nCurrentRecord != hEntity )
01175 {
01176 DBFFlushRecord( psDBF );
01177
01178 nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
01179
01180 fseek( psDBF->fp, nRecordOffset, 0 );
01181 fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
01182
01183 psDBF->nCurrentRecord = hEntity;
01184 }
01185
01186 pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
01187
01188
01189
01190
01191 if( (int)strlen((char *) pValue) > psDBF->panFieldSize[iField] )
01192 j = psDBF->panFieldSize[iField];
01193 else
01194 {
01195 memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
01196 psDBF->panFieldSize[iField] );
01197 j = strlen((char *) pValue);
01198 }
01199
01200 strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
01201 (char *) pValue, j );
01202
01203 psDBF->bCurrentRecordModified = TRUE;
01204 psDBF->bUpdated = TRUE;
01205
01206 return( TRUE );
01207 }
01208
01209
01210
01211
01212
01213
01214
01215 int SHPAPI_CALL
01216 DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
01217 double dValue )
01218
01219 {
01220 return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
01221 }
01222
01223
01224
01225
01226
01227
01228
01229 int SHPAPI_CALL
01230 DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
01231 int nValue )
01232
01233 {
01234 double dValue = nValue;
01235
01236 return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
01237 }
01238
01239
01240
01241
01242
01243
01244
01245 int SHPAPI_CALL
01246 DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
01247 const char * pszValue )
01248
01249 {
01250 return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) pszValue ) );
01251 }
01252
01253
01254
01255
01256
01257
01258
01259 int SHPAPI_CALL
01260 DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
01261
01262 {
01263 return( DBFWriteAttribute( psDBF, iRecord, iField, NULL ) );
01264 }
01265
01266
01267
01268
01269
01270
01271
01272 int SHPAPI_CALL
01273 DBFWriteLogicalAttribute( DBFHandle psDBF, int iRecord, int iField,
01274 const char lValue)
01275
01276 {
01277 return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) (&lValue) ) );
01278 }
01279
01280
01281
01282
01283
01284
01285
01286 int SHPAPI_CALL
01287 DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
01288
01289 {
01290 int nRecordOffset, i;
01291 unsigned char *pabyRec;
01292
01293
01294
01295
01296 if( hEntity < 0 || hEntity > psDBF->nRecords )
01297 return( FALSE );
01298
01299 if( psDBF->bNoHeader )
01300 DBFWriteHeader(psDBF);
01301
01302
01303
01304
01305 if( hEntity == psDBF->nRecords )
01306 {
01307 DBFFlushRecord( psDBF );
01308
01309 psDBF->nRecords++;
01310 for( i = 0; i < psDBF->nRecordLength; i++ )
01311 psDBF->pszCurrentRecord[i] = ' ';
01312
01313 psDBF->nCurrentRecord = hEntity;
01314 }
01315
01316
01317
01318
01319
01320 if( psDBF->nCurrentRecord != hEntity )
01321 {
01322 DBFFlushRecord( psDBF );
01323
01324 nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
01325
01326 fseek( psDBF->fp, nRecordOffset, 0 );
01327 fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
01328
01329 psDBF->nCurrentRecord = hEntity;
01330 }
01331
01332 pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
01333
01334 memcpy ( pabyRec, pRawTuple, psDBF->nRecordLength );
01335
01336 psDBF->bCurrentRecordModified = TRUE;
01337 psDBF->bUpdated = TRUE;
01338
01339 return( TRUE );
01340 }
01341
01342
01343
01344
01345
01346
01347
01348 const char SHPAPI_CALL1(*)
01349 DBFReadTuple(DBFHandle psDBF, int hEntity )
01350
01351 {
01352 int nRecordOffset;
01353 unsigned char *pabyRec;
01354 static char *pReturnTuple = NULL;
01355
01356 static int nTupleLen = 0;
01357
01358
01359
01360
01361 if( hEntity < 0 || hEntity >= psDBF->nRecords )
01362 return( NULL );
01363
01364 if( psDBF->nCurrentRecord != hEntity )
01365 {
01366 DBFFlushRecord( psDBF );
01367
01368 nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
01369
01370 fseek( psDBF->fp, nRecordOffset, 0 );
01371 fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
01372
01373 psDBF->nCurrentRecord = hEntity;
01374 }
01375
01376 pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
01377
01378 if ( nTupleLen < psDBF->nRecordLength) {
01379 nTupleLen = psDBF->nRecordLength;
01380 pReturnTuple = (char *) SfRealloc(pReturnTuple, psDBF->nRecordLength);
01381 }
01382
01383 memcpy ( pReturnTuple, pabyRec, psDBF->nRecordLength );
01384
01385 return( pReturnTuple );
01386 }
01387
01388
01389
01390
01391
01392
01393
01394 DBFHandle SHPAPI_CALL
01395 DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
01396 {
01397 DBFHandle newDBF;
01398
01399 newDBF = DBFCreate ( pszFilename );
01400 if ( newDBF == NULL ) return ( NULL );
01401
01402 newDBF->pszHeader = (char *) malloc ( 32 * psDBF->nFields );
01403 memcpy ( newDBF->pszHeader, psDBF->pszHeader, 32 * psDBF->nFields );
01404
01405 newDBF->nFields = psDBF->nFields;
01406 newDBF->nRecordLength = psDBF->nRecordLength;
01407 newDBF->nHeaderLength = 32 * (psDBF->nFields+1);
01408
01409 newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields );
01410 memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
01411 newDBF->panFieldSize = (int *) malloc ( sizeof(int) * psDBF->nFields );
01412 memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
01413 newDBF->panFieldDecimals = (int *) malloc ( sizeof(int) * psDBF->nFields );
01414 memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
01415 newDBF->pachFieldType = (char *) malloc ( sizeof(int) * psDBF->nFields );
01416 memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(int) * psDBF->nFields );
01417
01418 newDBF->bNoHeader = TRUE;
01419 newDBF->bUpdated = TRUE;
01420
01421 DBFWriteHeader ( newDBF );
01422 DBFClose ( newDBF );
01423
01424 newDBF = DBFOpen ( pszFilename, "rb+" );
01425
01426 return ( newDBF );
01427 }
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440 char SHPAPI_CALL
01441 DBFGetNativeFieldType( DBFHandle psDBF, int iField )
01442
01443 {
01444 if( iField >=0 && iField < psDBF->nFields )
01445 return psDBF->pachFieldType[iField];
01446
01447 return ' ';
01448 }
01449
01450
01451
01452
01453
01454 static void str_to_upper (char *string)
01455 {
01456 int len;
01457 short i = -1;
01458
01459 len = strlen (string);
01460
01461 while (++i < len)
01462 if (isalpha(string[i]) && islower(string[i]))
01463 string[i] = toupper ((int)string[i]);
01464 }
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474 int SHPAPI_CALL
01475 DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
01476
01477 {
01478 char name[12], name1[12], name2[12];
01479 int i;
01480
01481 strncpy(name1, pszFieldName,11);
01482 name1[11] = '\0';
01483 str_to_upper(name1);
01484
01485 for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
01486 {
01487 DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
01488 strncpy(name2,name,11);
01489 str_to_upper(name2);
01490
01491 if(!strncmp(name1,name2,10))
01492 return(i);
01493 }
01494 return(-1);
01495 }