160 #include <grass/shapefil.h> 168 #include "cpl_string.h" 170 #define CPLsprintf sprintf 173 #if defined(WIN32) || defined(_WIN32) 175 # define snprintf _snprintf 193 static void * SfRealloc(
void * pMem,
int nNewSize )
197 return( (
void *)
malloc(nNewSize) );
199 return( (
void *) realloc(pMem,nNewSize) );
211 static void DBFWriteHeader(
DBFHandle psDBF)
233 abyHeader[3] = (
unsigned char) psDBF->
nUpdateDay;
240 abyHeader[10] = (
unsigned char) (psDBF->
nRecordLength % 256);
241 abyHeader[11] = (
unsigned char) (psDBF->
nRecordLength / 256);
272 static int DBFFlushRecord(
DBFHandle psDBF )
288 1, psDBF->
fp ) != 1 )
291 snprintf( szMessage,
sizeof(szMessage),
"Failure writing DBF record %d.",
305 static int DBFLoadRecord(
DBFHandle psDBF,
int iRecord )
312 if( !DBFFlushRecord( psDBF ) )
318 if( psDBF->
sHooks.
FSeek( psDBF->
fp, nRecordOffset, SEEK_SET ) != 0 )
321 snprintf( szMessage,
sizeof(szMessage),
"fseek(%ld) failed on DBF file.\n",
322 (
long) nRecordOffset );
331 snprintf( szMessage,
sizeof(szMessage),
"fread(%d) failed on DBF file.\n",
351 unsigned char abyFileHeader[32];
354 DBFWriteHeader( psDBF );
356 if( !DBFFlushRecord( psDBF ) )
364 abyFileHeader[3] = (
unsigned char) psDBF->
nUpdateDay;
365 abyFileHeader[4] = (
unsigned char) (psDBF->
nRecords % 256);
366 abyFileHeader[5] = (
unsigned char) ((psDBF->
nRecords/256) % 256);
367 abyFileHeader[6] = (
unsigned char) ((psDBF->
nRecords/(256*256)) % 256);
368 abyFileHeader[7] = (
unsigned char) ((psDBF->
nRecords/(256*256*256)) % 256);
395 DBFOpen(
const char * pszFilename,
const char * pszAccess )
402 return DBFOpenLL( pszFilename, pszAccess, &sHooks );
417 unsigned char *pabyBuf;
418 int nFields, nHeadLen, iField, i;
419 char *pszBasename, *pszFullname;
426 if( strcmp(pszAccess,
"r") != 0 && strcmp(pszAccess,
"r+") != 0
427 && strcmp(pszAccess,
"rb") != 0 && strcmp(pszAccess,
"rb+") != 0
428 && strcmp(pszAccess,
"r+b") != 0 )
431 if( strcmp(pszAccess,
"r") == 0 )
434 if( strcmp(pszAccess,
"r+") == 0 )
441 pszBasename = (
char *)
malloc(strlen(pszFilename)+5);
442 strcpy( pszBasename, pszFilename );
443 for( i = (
int)strlen(pszBasename)-1;
444 i > 0 && pszBasename[i] !=
'.' && pszBasename[i] !=
'/' 445 && pszBasename[i] !=
'\\';
448 if( pszBasename[i] ==
'.' )
449 pszBasename[i] =
'\0';
451 nFullnameLen = strlen(pszBasename) + 5;
452 pszFullname = (
char *)
malloc(nFullnameLen);
453 snprintf( pszFullname, nFullnameLen,
"%s.dbf", pszBasename );
456 psDBF->
fp = psHooks->
FOpen( pszFullname, pszAccess );
461 snprintf( pszFullname, nFullnameLen,
"%s.DBF", pszBasename );
465 snprintf( pszFullname, nFullnameLen,
"%s.cpg", pszBasename );
466 pfCPG = psHooks->
FOpen( pszFullname,
"r" );
469 snprintf( pszFullname, nFullnameLen,
"%s.CPG", pszBasename );
470 pfCPG = psHooks->
FOpen( pszFullname,
"r" );
479 if( pfCPG ) psHooks->
FClose( pfCPG );
490 pabyBuf = (
unsigned char *)
malloc(nBufSize);
503 pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + (pabyBuf[7] & 0x7f) *256*256*256;
505 psDBF->
nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
518 psDBF->
nFields = nFields = (nHeadLen - 32) / 32;
530 memset( pabyBuf, 0, nBufSize);
531 psDBF->
sHooks.
FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
532 n = strcspn( (
char *) pabyBuf,
"\n\r" );
543 snprintf( (
char *) pabyBuf, nBufSize,
"LDID/%d", psDBF->
iLanguageDriver );
552 pabyBuf = (
unsigned char *) SfRealloc(pabyBuf,nHeadLen);
556 if( psDBF->
sHooks.
FRead( pabyBuf, nHeadLen-32, 1, psDBF->
fp ) != 1 )
570 for( iField = 0; iField < nFields; iField++ )
572 unsigned char *pabyFInfo;
574 pabyFInfo = pabyBuf+iField*32;
576 if( pabyFInfo[11] ==
'N' || pabyFInfo[11] ==
'F' )
621 DBFWriteHeader( psDBF );
623 DBFFlushRecord( psDBF );
682 return DBFCreateLL( pszFilename, pszCodePage , &sHooks );
697 char *pszFullname, *pszBasename;
706 pszBasename = (
char *)
malloc(strlen(pszFilename)+5);
707 strcpy( pszBasename, pszFilename );
708 for( i = (
int)strlen(pszBasename)-1;
709 i > 0 && pszBasename[i] !=
'.' && pszBasename[i] !=
'/' 710 && pszBasename[i] !=
'\\';
713 if( pszBasename[i] ==
'.' )
714 pszBasename[i] =
'\0';
716 nFullnameLen = strlen(pszBasename) + 5;
717 pszFullname = (
char *)
malloc(nFullnameLen);
718 snprintf( pszFullname, nFullnameLen,
"%s.dbf", pszBasename );
723 fp = psHooks->
FOpen( pszFullname,
"wb" );
731 psHooks->
FWrite( &chZero, 1, 1, fp );
734 fp = psHooks->
FOpen( pszFullname,
"rb+" );
742 snprintf( pszFullname, nFullnameLen,
"%s.cpg", pszBasename );
743 if( pszCodePage !=
NULL )
745 if( strncmp( pszCodePage,
"LDID/", 5 ) == 0 )
747 ldid = atoi( pszCodePage + 5 );
754 psHooks->
FWrite( (
char*) pszCodePage, strlen(pszCodePage), 1, fpCPG );
758 if( pszCodePage ==
NULL || ldid >= 0 )
760 psHooks->
Remove( pszFullname );
813 char chNativeType =
'C';
830 static char DBFGetNullCharacter(
char chType)
855 char chType,
int nWidth,
int nDecimals )
860 int nOldRecordLength, nOldHeaderLength;
866 if( !DBFFlushRecord( psDBF ) )
918 for( i = 0; i < 32; i++ )
921 if( (
int) strlen(pszFieldName) < 10 )
922 strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
924 strncpy( pszFInfo, pszFieldName, 10);
930 pszFInfo[16] = (
unsigned char) (nWidth % 256);
931 pszFInfo[17] = (
unsigned char) (nWidth / 256);
935 pszFInfo[16] = (
unsigned char) nWidth;
936 pszFInfo[17] = (
unsigned char) nDecimals;
956 chFieldFill = DBFGetNullCharacter(chType);
958 for (i = psDBF->
nRecords-1; i >= 0; --i)
960 nRecordOffset = nOldRecordLength * (
SAOffset) i + nOldHeaderLength;
964 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
967 memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
996 static void *DBFReadAttribute(
DBFHandle psDBF,
int hEntity,
int iField,
1000 unsigned char *pabyRec;
1001 void *pReturnField =
NULL;
1006 if( hEntity < 0 || hEntity >= psDBF->
nRecords )
1009 if( iField < 0 || iField >= psDBF->
nFields )
1015 if( !DBFLoadRecord( psDBF, hEntity ) )
1046 if( chReqType ==
'I' )
1052 else if( chReqType ==
'N' )
1062 #ifdef TRIM_DBF_WHITESPACE 1065 char *pchSrc, *pchDst;
1068 while( *pchSrc ==
' ' )
1071 while( *pchSrc !=
'\0' )
1072 *(pchDst++) = *(pchSrc++);
1075 while( pchDst != psDBF->
pszWorkField && *(--pchDst) ==
' ' )
1080 return( pReturnField );
1095 pnValue = (
int *) DBFReadAttribute( psDBF, iRecord, iField,
'I' );
1097 if( pnValue ==
NULL )
1115 pdValue = (
double *) DBFReadAttribute( psDBF, iRecord, iField,
'N' );
1117 if( pdValue ==
NULL )
1133 return( (
const char *) DBFReadAttribute( psDBF, iRecord, iField,
'C' ) );
1146 return( (
const char *) DBFReadAttribute( psDBF, iRecord, iField,
'L' ) );
1156 static int DBFIsValueNULL(
char chType,
const char* pszValue )
1160 if( pszValue ==
NULL )
1172 if( pszValue[0] ==
'*' )
1175 for( i = 0; pszValue[i] !=
'\0'; i++ )
1177 if( pszValue[i] !=
' ' )
1184 return strncmp(pszValue,
"00000000",8) == 0;
1188 return pszValue[0] ==
'?';
1192 return strlen(pszValue) == 0;
1208 const char *pszValue;
1212 if( pszValue ==
NULL )
1215 return DBFIsValueNULL( psDBF->
pachFieldType[iField], pszValue );
1252 int * pnWidth,
int * pnDecimals )
1255 if( iField < 0 || iField >= psDBF->
nFields )
1258 if( pnWidth !=
NULL )
1261 if( pnDecimals !=
NULL )
1264 if( pszFieldName !=
NULL )
1268 strncpy( pszFieldName, (
char *) psDBF->
pszHeader+iField*32, 11 );
1269 pszFieldName[11] =
'\0';
1270 for( i = 10; i > 0 && pszFieldName[i] ==
' '; i-- )
1271 pszFieldName[i] =
'\0';
1298 static int DBFWriteAttribute(
DBFHandle psDBF,
int hEntity,
int iField,
1302 int i, j, nRetResult =
TRUE;
1303 unsigned char *pabyRec;
1304 char szSField[400], szFormat[20];
1309 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1313 DBFWriteHeader(psDBF);
1320 if( !DBFFlushRecord( psDBF ) )
1334 if( !DBFLoadRecord( psDBF, hEntity ) )
1347 if( pValue ==
NULL )
1366 if( (
int)
sizeof(szSField)-2 < nWidth )
1367 nWidth =
sizeof(szSField)-2;
1369 snprintf( szFormat,
sizeof(szFormat),
"%%%d.%df",
1371 snprintf(szSField,
sizeof(szSField), szFormat, *((
double *) pValue) );
1372 if( (
int) strlen(szSField) > psDBF->
panFieldSize[iField] )
1378 szSField, strlen(szSField) );
1384 (*(
char*)pValue ==
'F' || *(
char*)pValue ==
'T'))
1389 if( (
int) strlen((
char *) pValue) > psDBF->
panFieldSize[iField] )
1398 j = (int)strlen((
char *) pValue);
1402 (
char *) pValue, j );
1406 return( nRetResult );
1423 unsigned char *pabyRec;
1428 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1432 DBFWriteHeader(psDBF);
1439 if( !DBFFlushRecord( psDBF ) )
1453 if( !DBFLoadRecord( psDBF, hEntity ) )
1461 if( (
int)strlen((
char *) pValue) > psDBF->
panFieldSize[iField] )
1467 j = (int)strlen((
char *) pValue);
1471 (
char *) pValue, j );
1490 return( DBFWriteAttribute( psDBF, iRecord, iField, (
void *) &dValue ) );
1504 double dValue = nValue;
1506 return( DBFWriteAttribute( psDBF, iRecord, iField, (
void *) &dValue ) );
1517 const char * pszValue )
1520 return( DBFWriteAttribute( psDBF, iRecord, iField, (
void *) pszValue ) );
1533 return( DBFWriteAttribute( psDBF, iRecord, iField,
NULL ) );
1547 return( DBFWriteAttribute( psDBF, iRecord, iField, (
void *) (&lValue) ) );
1561 unsigned char *pabyRec;
1566 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1570 DBFWriteHeader(psDBF);
1577 if( !DBFFlushRecord( psDBF ) )
1591 if( !DBFLoadRecord( psDBF, hEntity ) )
1615 if( hEntity < 0 || hEntity >= psDBF->
nRecords )
1618 if( !DBFLoadRecord( psDBF, hEntity ) )
1636 if ( newDBF ==
NULL )
return (
NULL );
1660 DBFWriteHeader ( newDBF );
1663 newDBF =
DBFOpen ( pszFilename,
"rb+" );
1683 if( iField >=0 && iField < psDBF->nFields )
1693 static void str_to_upper (
char *
string)
1698 len = (int)strlen (
string);
1701 if (isalpha(
string[i]) && islower(
string[i]))
1702 string[i] = (
char) toupper ((
int)
string[i]);
1717 char name[12], name1[12], name2[12];
1720 strncpy(name1, pszFieldName,11);
1722 str_to_upper(name1);
1727 strncpy(name2,name,11);
1728 str_to_upper(name2);
1730 if(!strncmp(name1,name2,10))
1749 if( iShape < 0 || iShape >= psDBF->
nRecords )
1755 if( !DBFLoadRecord( psDBF, iShape ) )
1777 if( iShape < 0 || iShape >= psDBF->
nRecords )
1784 if( !DBFLoadRecord( psDBF, iShape ) )
1814 return psDBF->pszCodePage;
1826 int nOldRecordLength, nOldHeaderLength;
1827 int nDeletedFieldOffset, nDeletedFieldSize;
1832 if (iField < 0 || iField >= psDBF->
nFields)
1836 if( !DBFFlushRecord( psDBF ) )
1846 for (i = iField + 1; i < psDBF->
nFields; i++)
1876 sizeof(
char) * (psDBF->
nFields - iField)*32);
1893 pszRecord = (
char *)
malloc(
sizeof(
char) * nOldRecordLength);
1896 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
1899 nOldRecordLength * (
SAOffset) iRecord + nOldHeaderLength;
1903 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
1910 psDBF->
sHooks.
FWrite( pszRecord, nDeletedFieldOffset, 1, psDBF->
fp );
1911 psDBF->
sHooks.
FWrite( pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
1912 nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize,
1944 int *panFieldOffsetNew;
1945 int *panFieldSizeNew;
1946 int *panFieldDecimalsNew;
1947 char *pachFieldTypeNew;
1956 if( !DBFFlushRecord( psDBF ) )
1960 panFieldOffsetNew = (
int *) calloc(
sizeof(
int), psDBF->
nFields);
1961 panFieldSizeNew = (
int *)
malloc(
sizeof(
int) * psDBF->
nFields);
1962 panFieldDecimalsNew = (
int *)
malloc(
sizeof(
int) * psDBF->
nFields);
1963 pachFieldTypeNew = (
char *)
malloc(
sizeof(
char) * psDBF->
nFields);
1964 pszHeaderNew = (
char*)
malloc(
sizeof(
char) * 32 * psDBF->
nFields);
1967 for(i=0; i < psDBF->
nFields; i++)
1972 memcpy(pszHeaderNew + i * 32,
1975 panFieldOffsetNew[0] = 1;
1976 for(i=1; i < psDBF->
nFields; i++)
1978 panFieldOffsetNew[i] = panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
1996 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
2005 pszRecordNew[0] = pszRecord[0];
2007 for(i=0; i < psDBF->
nFields; i++)
2009 memcpy(pszRecordNew + panFieldOffsetNew[i],
2050 char chType,
int nWidth,
int nDecimals )
2056 int nOldRecordLength;
2063 if (iField < 0 || iField >= psDBF->
nFields)
2067 if( !DBFFlushRecord( psDBF ) )
2070 chFieldFill = DBFGetNullCharacter(chType);
2096 pszFInfo = psDBF->
pszHeader + 32 * iField;
2098 for( i = 0; i < 32; i++ )
2101 if( (
int) strlen(pszFieldName) < 10 )
2102 strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
2104 strncpy( pszFInfo, pszFieldName, 10);
2110 pszFInfo[16] = (
unsigned char) (nWidth % 256);
2111 pszFInfo[17] = (
unsigned char) (nWidth / 256);
2115 pszFInfo[16] = (
unsigned char) nWidth;
2116 pszFInfo[17] = (
unsigned char) nDecimals;
2122 if (nWidth != nOldWidth)
2124 for (i = iField + 1; i < psDBF->
nFields; i++)
2140 if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
2142 char* pszRecord = (
char *)
malloc(
sizeof(
char) * nOldRecordLength);
2143 char* pszOldField = (
char *)
malloc(
sizeof(
char) * (nOldWidth + 1));
2145 pszOldField[nOldWidth] = 0;
2148 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
2155 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
2157 memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2158 bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
2160 if (nWidth != nOldWidth)
2162 if ((chOldType ==
'N' || chOldType ==
'F') && pszOldField[0] ==
' ')
2165 memmove( pszRecord + nOffset,
2166 pszRecord + nOffset + nOldWidth - nWidth,
2169 if (nOffset + nOldWidth < nOldRecordLength)
2171 memmove( pszRecord + nOffset + nWidth,
2172 pszRecord + nOffset + nOldWidth,
2173 nOldRecordLength - (nOffset + nOldWidth));
2180 memset( pszRecord + nOffset, chFieldFill, nWidth);
2194 else if (nWidth > nOldWidth)
2197 char* pszOldField = (
char *)
malloc(
sizeof(
char) * (nOldWidth + 1));
2199 pszOldField[nOldWidth] = 0;
2202 for (iRecord = psDBF->
nRecords - 1; iRecord >= 0; iRecord--)
2209 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
2211 memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2212 bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
2214 if (nOffset + nOldWidth < nOldRecordLength)
2216 memmove( pszRecord + nOffset + nWidth,
2217 pszRecord + nOffset + nOldWidth,
2218 nOldRecordLength - (nOffset + nOldWidth));
2224 memset( pszRecord + nOffset, chFieldFill, nWidth);
2228 if ((chOldType ==
'N' || chOldType ==
'F'))
2231 memmove( pszRecord + nOffset + nWidth - nOldWidth,
2232 pszRecord + nOffset, nOldWidth );
2233 memset( pszRecord + nOffset,
' ', nWidth - nOldWidth );
2238 memset(pszRecord + nOffset + nOldWidth,
' ', nWidth - nOldWidth);
int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName, char chType, int nWidth, int nDecimals)
int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle psDBF, int iRecord, int iField, int nValue)
double SHPAPI_CALL DBFReadDoubleAttribute(DBFHandle psDBF, int iRecord, int iField)
int(* Remove)(const char *filename)
union DBFInfo::@15 fieldValue
void SHPAPI_CALL DBFClose(DBFHandle psDBF)
void SHPAPI_CALL DBFSetLastModifiedDate(DBFHandle psDBF, int nYYSince1900, int nMM, int nDD)
int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape, int bIsDeleted)
void SHPAPI_CALL DBFUpdateHeader(DBFHandle psDBF)
int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF)
DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename, const char *pszCodePage, SAHooks *psHooks)
DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF, const char *pszFilename)
char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle psDBF, int iField)
int(* FFlush)(SAFile file)
int SHPAPI_CALL DBFAddField(DBFHandle psDBF, const char *pszFieldName, DBFFieldType eType, int nWidth, int nDecimals)
int SHPAPI_CALL DBFWriteLogicalAttribute(DBFHandle psDBF, int iRecord, int iField, const char lValue)
int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF)
DBFHandle SHPAPI_CALL DBFCreateEx(const char *pszFilename, const char *pszCodePage)
DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField, char *pszFieldName, int *pnWidth, int *pnDecimals)
SAOffset(* FSeek)(SAFile file, SAOffset offset, int whence)
int SHPAPI_CALL DBFWriteDoubleAttribute(DBFHandle psDBF, int iRecord, int iField, double dValue)
int SHPAPI_CALL DBFWriteStringAttribute(DBFHandle psDBF, int iRecord, int iField, const char *pszValue)
int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle psDBF, int iRecord, int iField)
DBFHandle SHPAPI_CALL DBFOpen(const char *pszFilename, const char *pszAccess)
const char SHPAPI_CALL1 * DBFReadStringAttribute(DBFHandle psDBF, int iRecord, int iField){ return((const char *) DBFReadAttribute(psDBF, iRecord, iField, 'C')
int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, int *panMap)
int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape)
int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
void SASetupDefaultHooks(SAHooks *psHooks)
SAOffset(* FWrite)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
SAFile(* FOpen)(const char *filename, const char *access)
int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField, const char *pszFieldName, char chType, int nWidth, int nDecimals)
DBFHandle SHPAPI_CALL DBFCreate(const char *pszFilename)
void(* Error)(const char *message)
DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess, SAHooks *psHooks)
#define SHP_CVSID(string)
double(* Atof)(const char *str)
const char SHPAPI_CALL1 * DBFGetCodePage(DBFHandle psDBF){ if(psDBF==NULL) return NULL;return psDBF->pszCodePage;}int SHPAPI_CALLDBFDeleteField(DBFHandle psDBF, int iField
int SHPAPI_CALL DBFDeleteField(DBFHandle hDBF, int iField)
int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity, void *pRawTuple)
const char SHPAPI_CALL1 * DBFReadLogicalAttribute(DBFHandle psDBF, int iRecord, int iField){ return((const char *) DBFReadAttribute(psDBF, iRecord, iField, 'L')
int SHPAPI_CALL DBFReadIntegerAttribute(DBFHandle psDBF, int iRecord, int iField)
const char SHPAPI_CALL1 * DBFReadTuple(DBFHandle psDBF, int hEntity){ if(hEntity< 0||hEntity >=psDBF->nRecords) return(NULL
int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField, void *pValue)
SAOffset(* FRead)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
int bCurrentRecordModified
int(* FClose)(SAFile file)
int SHPAPI_CALL DBFWriteNULLAttribute(DBFHandle psDBF, int iRecord, int iField)