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