208 #include "cpl_string.h"
211 #if defined(WIN32) || defined(_WIN32)
212 # define STRCASECMP(a,b) (stricmp(a,b))
215 # define STRCASECMP(a,b) (strcasecmp(a,b))
218 #if defined(_MSC_VER)
220 # define snprintf _snprintf
222 #elif defined(WIN32) || defined(_WIN32)
224 # define snprintf _snprintf
228 #define CPLsprintf sprintf
229 #define CPLsnprintf snprintf
240 #define XBASE_FILEHDR_SZ 32
242 #define HEADER_RECORD_TERMINATOR 0x0D
245 #define END_OF_FILE_CHARACTER 0x1A
250 #define CPL_IGNORE_RET_VAL_INT(x) x
254 #define STATIC_CAST(type,x) static_cast<type>(x)
255 #define REINTERPRET_CAST(type,x) reinterpret_cast<type>(x)
256 #define CONST_CAST(type,x) const_cast<type>(x)
257 #define SHPLIB_NULLPTR nullptr
259 #define STATIC_CAST(type,x) ((type)(x))
260 #define REINTERPRET_CAST(type,x) ((type)(x))
261 #define CONST_CAST(type,x) ((type)(x))
262 #define SHPLIB_NULLPTR NULL
276 return malloc(nNewSize);
278 return realloc(pMem,nNewSize);
374 1, psDBF->
fp ) != 1 )
377 snprintf( szMessage,
sizeof(szMessage),
"Failure writing DBF record %d.",
416 snprintf( szMessage,
sizeof(szMessage),
"fseek(%ld) failed on DBF file.",
426 snprintf( szMessage,
sizeof(szMessage),
"fread(%d) failed on DBF file.",
455 psDBF->
sHooks.
FRead( abyFileHeader,
sizeof(abyFileHeader), 1, psDBF->
fp );
466 psDBF->
sHooks.
FWrite( abyFileHeader,
sizeof(abyFileHeader), 1, psDBF->
fp );
490 DBFOpen(
const char * pszFilename,
const char * pszAccess )
497 return DBFOpenLL( pszFilename, pszAccess, &sHooks );
509 i > 0 && pszBasename[i] !=
'/' && pszBasename[i] !=
'\\';
512 if( pszBasename[i] ==
'.' )
532 unsigned char *pabyBuf;
533 int nFields, nHeadLen, iField;
536 int nLenWithoutExtension;
541 if( strcmp(pszAccess,
"r") != 0 && strcmp(pszAccess,
"r+") != 0
542 && strcmp(pszAccess,
"rb") != 0 && strcmp(pszAccess,
"rb+") != 0
543 && strcmp(pszAccess,
"r+b") != 0 )
546 if( strcmp(pszAccess,
"r") == 0 )
549 if( strcmp(pszAccess,
"r+") == 0 )
557 pszFullname =
STATIC_CAST(
char *, malloc(nLenWithoutExtension + 5));
558 memcpy(pszFullname, pszFilename, nLenWithoutExtension);
559 memcpy(pszFullname + nLenWithoutExtension,
".dbf", 5);
562 psDBF->
fp = psHooks->
FOpen( pszFullname, pszAccess );
567 memcpy(pszFullname + nLenWithoutExtension,
".DBF", 5);
571 memcpy(pszFullname + nLenWithoutExtension,
".cpg", 5);
572 pfCPG = psHooks->
FOpen( pszFullname,
"r" );
575 memcpy(pszFullname + nLenWithoutExtension,
".CPG", 5);
576 pfCPG = psHooks->
FOpen( pszFullname,
"r" );
584 if( pfCPG ) psHooks->
FClose( pfCPG );
595 pabyBuf =
STATIC_CAST(
unsigned char *, malloc(nBufSize));
608 pabyBuf[4]|(pabyBuf[5]<<8)|(pabyBuf[6]<<16)|((pabyBuf[7]&0x7f)<<24);
610 psDBF->
nHeaderLength = nHeadLen = pabyBuf[8]|(pabyBuf[9]<<8);
636 memset( pabyBuf, 0, nBufSize);
637 psDBF->
sHooks.
FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
678 for( iField = 0; iField < nFields; iField++ )
680 unsigned char *pabyFInfo;
689 if( pabyFInfo[11] ==
'N' || pabyFInfo[11] ==
'F' )
806 return DBFCreateLL( pszFilename, pszCodePage , &sHooks );
824 int nLenWithoutExtension;
831 pszFullname =
STATIC_CAST(
char *, malloc(nLenWithoutExtension + 5));
832 memcpy(pszFullname, pszFilename, nLenWithoutExtension);
833 memcpy(pszFullname + nLenWithoutExtension,
".dbf", 5);
838 fp = psHooks->
FOpen( pszFullname,
"wb" );
845 psHooks->
FWrite( &chZero, 1, 1, fp );
848 fp = psHooks->
FOpen( pszFullname,
"rb+" );
855 memcpy(pszFullname + nLenWithoutExtension,
".cpg", 5);
858 if( strncmp( pszCodePage,
"LDID/", 5 ) == 0 )
860 ldid = atoi( pszCodePage + 5 );
873 psHooks->
Remove( pszFullname );
927 char chNativeType =
'C';
931 else if( eType ==
FTDate )
971 char chType,
int nWidth,
int nDecimals )
976 int nOldRecordLength, nOldHeaderLength;
988 snprintf( szMessage,
sizeof(szMessage),
989 "Cannot add field %s. Header length limit reached "
990 "(max 65535 bytes, 2046 fields).",
1007 char szMessage[128];
1008 snprintf( szMessage,
sizeof(szMessage),
1009 "Cannot add field %s. Record length limit reached "
1010 "(max 65535 bytes).",
1066 pszFInfo[16] =
STATIC_CAST(
unsigned char, nWidth % 256);
1067 pszFInfo[17] =
STATIC_CAST(
unsigned char, nWidth / 256);
1071 pszFInfo[16] =
STATIC_CAST(
unsigned char, nWidth);
1072 pszFInfo[17] =
STATIC_CAST(
unsigned char, nDecimals);
1094 for (i = psDBF->
nRecords-1; i >= 0; --i)
1100 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
1103 memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
1147 unsigned char *pabyRec;
1153 if( hEntity < 0 || hEntity >= psDBF->
nRecords )
1156 if( iField < 0 || iField >= psDBF->
nFields )
1193 if( chReqType ==
'I' )
1199 else if( chReqType ==
'N' )
1209 #ifdef TRIM_DBF_WHITESPACE
1212 char *pchSrc, *pchDst;
1215 while( *pchSrc ==
' ' )
1218 while( *pchSrc !=
'\0' )
1219 *(pchDst++) = *(pchSrc++);
1222 while( pchDst != psDBF->
pszWorkField && *(--pchDst) ==
' ' )
1227 return pReturnField;
1319 if( pszValue[0] ==
'*' )
1322 for( i = 0; pszValue[i] !=
'\0'; i++ )
1324 if( pszValue[i] !=
' ' )
1331 return strncmp(pszValue,
"00000000",8) == 0;
1335 return pszValue[0] ==
'?';
1339 return strlen(pszValue) == 0;
1355 const char *pszValue;
1401 int * pnWidth,
int * pnDecimals )
1404 if( iField < 0 || iField >= psDBF->
nFields )
1421 pszFieldName[i] =
'\0';
1455 int i, j, nRetResult =
TRUE;
1456 unsigned char *pabyRec;
1462 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1519 if(
STATIC_CAST(
int,
sizeof(szSField))-2 < nWidth )
1520 nWidth =
sizeof(szSField)-2;
1522 snprintf( szFormat,
sizeof(szFormat),
"%%%d.%df",
1525 szSField[
sizeof(szSField)-1] =
'\0';
1532 szSField, strlen(szSField) );
1560 return( nRetResult );
1577 unsigned char *pabyRec;
1582 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1658 double dValue = nValue;
1671 const char * pszValue )
1715 unsigned char *pabyRec;
1720 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1769 if( hEntity < 0 || hEntity >= psDBF->nRecords )
1775 return STATIC_CAST(
const char *, psDBF->pszCurrentRecord);
1818 newDBF =
DBFOpen ( pszFilename,
"rb+" );
1839 if( iField >=0 && iField < psDBF->nFields )
1882 if( iShape < 0 || iShape >= psDBF->
nRecords )
1910 if( iShape < 0 || iShape >= psDBF->
nRecords )
1947 return psDBF->pszCodePage;
1959 int nOldRecordLength, nOldHeaderLength;
1960 int nDeletedFieldOffset, nDeletedFieldSize;
1965 if (iField < 0 || iField >= psDBF->
nFields)
1979 for (i = iField + 1; i < psDBF->
nFields; i++)
2027 pszRecord =
STATIC_CAST(
char *, malloc(
sizeof(
char) * nOldRecordLength));
2030 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
2037 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
2044 psDBF->
sHooks.
FWrite( pszRecord, nDeletedFieldOffset, 1, psDBF->
fp );
2045 psDBF->
sHooks.
FWrite( pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
2046 nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize,
2088 int *panFieldOffsetNew;
2089 int *panFieldSizeNew;
2090 int *panFieldDecimalsNew;
2091 char *pachFieldTypeNew;
2112 for(i=0; i < psDBF->
nFields; i++)
2120 panFieldOffsetNew[0] = 1;
2121 for(i=1; i < psDBF->
nFields; i++)
2123 panFieldOffsetNew[i] = panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
2141 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
2150 pszRecordNew[0] = pszRecord[0];
2152 for(i=0; i < psDBF->
nFields; i++)
2154 memcpy(pszRecordNew + panFieldOffsetNew[i],
2195 char chType,
int nWidth,
int nDecimals )
2201 int nOldRecordLength;
2208 if (iField < 0 || iField >= psDBF->
nFields)
2252 pszFInfo[16] =
STATIC_CAST(
unsigned char, nWidth % 256);
2253 pszFInfo[17] =
STATIC_CAST(
unsigned char, nWidth / 256);
2257 pszFInfo[16] =
STATIC_CAST(
unsigned char, nWidth);
2258 pszFInfo[17] =
STATIC_CAST(
unsigned char, nDecimals);
2264 if (nWidth != nOldWidth)
2266 for (i = iField + 1; i < psDBF->
nFields; i++)
2282 if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
2284 char* pszRecord =
STATIC_CAST(
char *, malloc(
sizeof(
char) * nOldRecordLength));
2285 char* pszOldField =
STATIC_CAST(
char *, malloc(
sizeof(
char) * (nOldWidth + 1)));
2288 pszOldField[nOldWidth] = 0;
2291 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
2298 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
2300 memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2303 if (nWidth != nOldWidth)
2305 if ((chOldType ==
'N' || chOldType ==
'F' || chOldType ==
'D') && pszOldField[0] ==
' ')
2308 memmove( pszRecord + nOffset,
2309 pszRecord + nOffset + nOldWidth - nWidth,
2312 if (nOffset + nOldWidth < nOldRecordLength)
2314 memmove( pszRecord + nOffset + nWidth,
2315 pszRecord + nOffset + nOldWidth,
2316 nOldRecordLength - (nOffset + nOldWidth));
2323 memset( pszRecord + nOffset, chFieldFill, nWidth);
2349 else if (nWidth > nOldWidth)
2352 char* pszOldField =
STATIC_CAST(
char *, malloc(
sizeof(
char) * (nOldWidth + 1)));
2355 pszOldField[nOldWidth] = 0;
2358 for (iRecord = psDBF->
nRecords - 1; iRecord >= 0; iRecord--)
2365 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
2367 memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2370 if (nOffset + nOldWidth < nOldRecordLength)
2372 memmove( pszRecord + nOffset + nWidth,
2373 pszRecord + nOffset + nOldWidth,
2374 nOldRecordLength - (nOffset + nOldWidth));
2380 memset( pszRecord + nOffset, chFieldFill, nWidth);
2384 if ((chOldType ==
'N' || chOldType ==
'F'))
2387 memmove( pszRecord + nOffset + nWidth - nOldWidth,
2388 pszRecord + nOffset, nOldWidth );
2389 memset( pszRecord + nOffset,
' ', nWidth - nOldWidth );
2394 memset(pszRecord + nOffset + nOldWidth,
' ', nWidth - nOldWidth);
const char * DBFReadStringAttribute(DBFHandle psDBF, int iRecord, int iField)
static int DBFIsValueNULL(char chType, const char *pszValue)
int DBFWriteIntegerAttribute(DBFHandle psDBF, int iRecord, int iField, int nValue)
int DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
const char * DBFGetCodePage(DBFHandle psDBF)
int DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField, void *pValue)
DBFHandle DBFCreate(const char *pszFilename)
static int DBFLoadRecord(DBFHandle psDBF, int iRecord)
int DBFWriteStringAttribute(DBFHandle psDBF, int iRecord, int iField, const char *pszValue)
char DBFGetNativeFieldType(DBFHandle psDBF, int iField)
int DBFMarkRecordDeleted(DBFHandle psDBF, int iShape, int bIsDeleted)
int DBFWriteLogicalAttribute(DBFHandle psDBF, int iRecord, int iField, const char lValue)
int DBFDeleteField(DBFHandle psDBF, int iField)
void DBFClose(DBFHandle psDBF)
int DBFAddField(DBFHandle psDBF, const char *pszFieldName, DBFFieldType eType, int nWidth, int nDecimals)
static int DBFGetLenWithoutExtension(const char *pszBasename)
int DBFWriteTuple(DBFHandle psDBF, int hEntity, void *pRawTuple)
int DBFAlterFieldDefn(DBFHandle psDBF, int iField, const char *pszFieldName, char chType, int nWidth, int nDecimals)
int DBFWriteNULLAttribute(DBFHandle psDBF, int iRecord, int iField)
void DBFSetWriteEndOfFileChar(DBFHandle psDBF, int bWriteFlag)
DBFHandle DBFOpenLL(const char *pszFilename, const char *pszAccess, SAHooks *psHooks)
int DBFReadIntegerAttribute(DBFHandle psDBF, int iRecord, int iField)
DBFHandle DBFCreateEx(const char *pszFilename, const char *pszCodePage)
DBFHandle DBFCloneEmpty(DBFHandle psDBF, const char *pszFilename)
DBFHandle DBFCreateLL(const char *pszFilename, const char *pszCodePage, SAHooks *psHooks)
static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField, void *pValue)
const char * DBFReadTuple(DBFHandle psDBF, int hEntity)
#define STATIC_CAST(type, x)
int DBFWriteDoubleAttribute(DBFHandle psDBF, int iRecord, int iField, double dValue)
double DBFReadDoubleAttribute(DBFHandle psDBF, int iRecord, int iField)
#define HEADER_RECORD_TERMINATOR
void DBFSetLastModifiedDate(DBFHandle psDBF, int nYYSince1900, int nMM, int nDD)
int DBFGetRecordCount(DBFHandle psDBF)
#define REINTERPRET_CAST(type, x)
void DBFUpdateHeader(DBFHandle psDBF)
int DBFReorderFields(DBFHandle psDBF, int *panMap)
static void DBFWriteHeader(DBFHandle psDBF)
int DBFGetFieldCount(DBFHandle psDBF)
int DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName, char chType, int nWidth, int nDecimals)
int DBFIsRecordDeleted(DBFHandle psDBF, int iShape)
DBFFieldType DBFGetFieldInfo(DBFHandle psDBF, int iField, char *pszFieldName, int *pnWidth, int *pnDecimals)
#define END_OF_FILE_CHARACTER
static void * SfRealloc(void *pMem, int nNewSize)
static char DBFGetNullCharacter(char chType)
int DBFIsAttributeNULL(DBFHandle psDBF, int iRecord, int iField)
static int DBFFlushRecord(DBFHandle psDBF)
#define CONST_CAST(type, x)
DBFHandle DBFOpen(const char *pszFilename, const char *pszAccess)
const char * DBFReadLogicalAttribute(DBFHandle psDBF, int iRecord, int iField)
static void * DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField, char chReqType)
#define CPL_IGNORE_RET_VAL_INT(x)
void SASetupDefaultHooks(SAHooks *psHooks)
#define SHP_CVSID(string)
#define XBASE_FLDNAME_LEN_WRITE
#define XBASE_FLDNAME_LEN_READ
#define XBASE_FLD_MAX_WIDTH
union DBFInfo::@42 fieldValue
int bCurrentRecordModified
void(* Error)(const char *message)
SAFile(* FOpen)(const char *filename, const char *access)
int(* FFlush)(SAFile file)
SAOffset(* FWrite)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
double(* Atof)(const char *str)
int(* Remove)(const char *filename)
int(* FClose)(SAFile file)
SAOffset(* FRead)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
SAOffset(* FSeek)(SAFile file, SAOffset offset, int whence)