45 #include "cpl_string.h"
48 #if defined(WIN32) || defined(_WIN32)
49 # define STRCASECMP(a,b) (stricmp(a,b))
52 # define STRCASECMP(a,b) (strcasecmp(a,b))
57 # define snprintf _snprintf
59 #elif defined(WIN32) || defined(_WIN32)
61 # define snprintf _snprintf
65 #define CPLsprintf sprintf
66 #define CPLsnprintf snprintf
77 #define XBASE_FILEHDR_SZ 32
79 #define HEADER_RECORD_TERMINATOR 0x0D
82 #define END_OF_FILE_CHARACTER 0x1A
87 #define CPL_IGNORE_RET_VAL_INT(x) x
91 #define STATIC_CAST(type,x) static_cast<type>(x)
92 #define REINTERPRET_CAST(type,x) reinterpret_cast<type>(x)
93 #define CONST_CAST(type,x) const_cast<type>(x)
94 #define SHPLIB_NULLPTR nullptr
96 #define STATIC_CAST(type,x) ((type)(x))
97 #define REINTERPRET_CAST(type,x) ((type)(x))
98 #define CONST_CAST(type,x) ((type)(x))
99 #define SHPLIB_NULLPTR NULL
115 return realloc(pMem,nNewSize);
214 if ( psDBF->
sHooks.
FSeek( psDBF->
fp, nRecordOffset, 0 ) != 0 ) {
216 snprintf( szMessage,
sizeof(szMessage),
217 "Failure seeking to position before writing DBF record %d.",
226 1, psDBF->
fp ) != 1 )
229 snprintf( szMessage,
sizeof(szMessage),
"Failure writing DBF record %d.",
270 if( psDBF->
sHooks.
FSeek( psDBF->
fp, nRecordOffset, SEEK_SET ) != 0 )
273 snprintf( szMessage,
sizeof(szMessage),
"fseek(%ld) failed on DBF file.",
283 snprintf( szMessage,
sizeof(szMessage),
"fread(%d) failed on DBF file.",
316 psDBF->
sHooks.
FRead( abyFileHeader,
sizeof(abyFileHeader), 1, psDBF->
fp );
327 psDBF->
sHooks.
FWrite( abyFileHeader,
sizeof(abyFileHeader), 1, psDBF->
fp );
351 DBFOpen(
const char * pszFilename,
const char * pszAccess )
358 return DBFOpenLL( pszFilename, pszAccess, &sHooks );
370 i > 0 && pszBasename[i] !=
'/' && pszBasename[i] !=
'\\';
373 if( pszBasename[i] ==
'.' )
393 unsigned char *pabyBuf;
394 int nFields, nHeadLen, iField;
397 int nLenWithoutExtension;
402 if( strcmp(pszAccess,
"r") != 0 && strcmp(pszAccess,
"r+") != 0
403 && strcmp(pszAccess,
"rb") != 0 && strcmp(pszAccess,
"rb+") != 0
404 && strcmp(pszAccess,
"r+b") != 0 )
407 if( strcmp(pszAccess,
"r") == 0 )
410 if( strcmp(pszAccess,
"r+") == 0 )
419 memcpy(pszFullname, pszFilename, nLenWithoutExtension);
420 memcpy(pszFullname + nLenWithoutExtension,
".dbf", 5);
423 psDBF->
fp = psHooks->
FOpen( pszFullname, pszAccess );
428 memcpy(pszFullname + nLenWithoutExtension,
".DBF", 5);
432 memcpy(pszFullname + nLenWithoutExtension,
".cpg", 5);
433 pfCPG = psHooks->
FOpen( pszFullname,
"r" );
436 memcpy(pszFullname + nLenWithoutExtension,
".CPG", 5);
437 pfCPG = psHooks->
FOpen( pszFullname,
"r" );
445 if( pfCPG ) psHooks->
FClose( pfCPG );
469 pabyBuf[4]|(pabyBuf[5]<<8)|(pabyBuf[6]<<16)|((pabyBuf[7]&0x7f)<<24);
471 psDBF->
nHeaderLength = nHeadLen = pabyBuf[8]|(pabyBuf[9]<<8);
497 memset( pabyBuf, 0, nBufSize);
498 psDBF->
sHooks.
FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
539 for( iField = 0; iField < nFields; iField++ )
541 unsigned char *pabyFInfo;
550 if( pabyFInfo[11] ==
'N' || pabyFInfo[11] ==
'F' )
669 return DBFCreateLL( pszFilename, pszCodePage , &sHooks );
687 int nLenWithoutExtension;
695 memcpy(pszFullname, pszFilename, nLenWithoutExtension);
696 memcpy(pszFullname + nLenWithoutExtension,
".dbf", 5);
701 fp = psHooks->
FOpen( pszFullname,
"wb" );
708 psHooks->
FWrite( &chZero, 1, 1, fp );
711 fp = psHooks->
FOpen( pszFullname,
"rb+" );
718 memcpy(pszFullname + nLenWithoutExtension,
".cpg", 5);
721 if( strncmp( pszCodePage,
"LDID/", 5 ) == 0 )
723 ldid = atoi( pszCodePage + 5 );
736 psHooks->
Remove( pszFullname );
792 char chNativeType =
'C';
796 else if( eType ==
FTDate )
836 char chType,
int nWidth,
int nDecimals )
841 int nOldRecordLength, nOldHeaderLength;
853 snprintf( szMessage,
sizeof(szMessage),
854 "Cannot add field %s. Header length limit reached "
855 "(max 65535 bytes, 2046 fields).",
873 snprintf( szMessage,
sizeof(szMessage),
874 "Cannot add field %s. Record length limit reached "
875 "(max 65535 bytes).",
931 pszFInfo[16] =
STATIC_CAST(
unsigned char, nWidth % 256);
932 pszFInfo[17] =
STATIC_CAST(
unsigned char, nWidth / 256);
937 pszFInfo[17] =
STATIC_CAST(
unsigned char, nDecimals);
959 for (i = psDBF->
nRecords-1; i >= 0; --i)
965 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
968 memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
1012 unsigned char *pabyRec;
1018 if( hEntity < 0 || hEntity >= psDBF->
nRecords )
1021 if( iField < 0 || iField >= psDBF->
nFields )
1058 if( chReqType ==
'I' )
1064 else if( chReqType ==
'N' )
1074 #ifdef TRIM_DBF_WHITESPACE
1077 char *pchSrc, *pchDst;
1080 while( *pchSrc ==
' ' )
1083 while( *pchSrc !=
'\0' )
1084 *(pchDst++) = *(pchSrc++);
1087 while( pchDst != psDBF->
pszWorkField && *(--pchDst) ==
' ' )
1092 return pReturnField;
1184 if( pszValue[0] ==
'*' )
1187 for( i = 0; pszValue[i] !=
'\0'; i++ )
1189 if( pszValue[i] !=
' ' )
1196 return strncmp(pszValue,
"00000000",8) == 0;
1200 return pszValue[0] ==
'?';
1204 return strlen(pszValue) == 0;
1220 const char *pszValue;
1266 int * pnWidth,
int * pnDecimals )
1269 if( iField < 0 || iField >= psDBF->
nFields )
1286 pszFieldName[i] =
'\0';
1320 int i, j, nRetResult =
TRUE;
1321 unsigned char *pabyRec;
1327 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1384 if(
STATIC_CAST(
int,
sizeof(szSField))-2 < nWidth )
1385 nWidth =
sizeof(szSField)-2;
1387 snprintf( szFormat,
sizeof(szFormat),
"%%%d.%df",
1390 szSField[
sizeof(szSField)-1] =
'\0';
1397 szSField, strlen(szSField) );
1425 return( nRetResult );
1442 unsigned char *pabyRec;
1447 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1523 double dValue = nValue;
1536 const char * pszValue )
1580 unsigned char *pabyRec;
1585 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1634 if( hEntity < 0 || hEntity >= psDBF->nRecords )
1640 return STATIC_CAST(
const char *, psDBF->pszCurrentRecord);
1683 newDBF =
DBFOpen ( pszFilename,
"rb+" );
1704 if( iField >=0 && iField < psDBF->nFields )
1775 if( iShape < 0 || iShape >= psDBF->
nRecords )
1812 return psDBF->pszCodePage;
1824 int nOldRecordLength, nOldHeaderLength;
1825 int nDeletedFieldOffset, nDeletedFieldSize;
1830 if (iField < 0 || iField >= psDBF->
nFields)
1844 for (i = iField + 1; i < psDBF->
nFields; i++)
1895 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
1902 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
1909 psDBF->
sHooks.
FWrite( pszRecord, nDeletedFieldOffset, 1, psDBF->
fp );
1910 psDBF->
sHooks.
FWrite( pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
1911 nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize,
1953 int *panFieldOffsetNew;
1954 int *panFieldSizeNew;
1955 int *panFieldDecimalsNew;
1956 char *pachFieldTypeNew;
1977 for(i=0; i < psDBF->
nFields; i++)
1985 panFieldOffsetNew[0] = 1;
1986 for(i=1; i < psDBF->
nFields; i++)
1988 panFieldOffsetNew[i] = panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
2006 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
2015 pszRecordNew[0] = pszRecord[0];
2017 for(i=0; i < psDBF->
nFields; i++)
2019 memcpy(pszRecordNew + panFieldOffsetNew[i],
2060 char chType,
int nWidth,
int nDecimals )
2066 int nOldRecordLength;
2073 if (iField < 0 || iField >= psDBF->
nFields)
2117 pszFInfo[16] =
STATIC_CAST(
unsigned char, nWidth % 256);
2118 pszFInfo[17] =
STATIC_CAST(
unsigned char, nWidth / 256);
2122 pszFInfo[16] =
STATIC_CAST(
unsigned char, nWidth);
2123 pszFInfo[17] =
STATIC_CAST(
unsigned char, nDecimals);
2129 if (nWidth != nOldWidth)
2131 for (i = iField + 1; i < psDBF->
nFields; i++)
2147 if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
2150 char* pszOldField =
STATIC_CAST(
char *,
malloc(
sizeof(
char) * (nOldWidth + 1)));
2153 pszOldField[nOldWidth] = 0;
2156 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
2163 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
2165 memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2168 if (nWidth != nOldWidth)
2170 if ((chOldType ==
'N' || chOldType ==
'F' || chOldType ==
'D') && pszOldField[0] ==
' ')
2173 memmove( pszRecord + nOffset,
2174 pszRecord + nOffset + nOldWidth - nWidth,
2177 if (nOffset + nOldWidth < nOldRecordLength)
2179 memmove( pszRecord + nOffset + nWidth,
2180 pszRecord + nOffset + nOldWidth,
2181 nOldRecordLength - (nOffset + nOldWidth));
2188 memset( pszRecord + nOffset, chFieldFill, nWidth);
2214 else if (nWidth > nOldWidth)
2217 char* pszOldField =
STATIC_CAST(
char *,
malloc(
sizeof(
char) * (nOldWidth + 1)));
2220 pszOldField[nOldWidth] = 0;
2223 for (iRecord = psDBF->
nRecords - 1; iRecord >= 0; iRecord--)
2230 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
2232 memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2235 if (nOffset + nOldWidth < nOldRecordLength)
2237 memmove( pszRecord + nOffset + nWidth,
2238 pszRecord + nOffset + nOldWidth,
2239 nOldRecordLength - (nOffset + nOldWidth));
2245 memset( pszRecord + nOffset, chFieldFill, nWidth);
2249 if ((chOldType ==
'N' || chOldType ==
'F'))
2252 memmove( pszRecord + nOffset + nWidth - nOldWidth,
2253 pszRecord + nOffset, nOldWidth );
2254 memset( pszRecord + nOffset,
' ', nWidth - nOldWidth );
2259 memset(pszRecord + nOffset + nOldWidth,
' ', nWidth - nOldWidth);
static int DBFIsValueNULL(char chType, const char *pszValue)
int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape, int bIsDeleted)
int SHPAPI_CALL DBFWriteDoubleAttribute(DBFHandle psDBF, int iRecord, int iField, double dValue)
int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF)
int SHPAPI_CALL DBFReadIntegerAttribute(DBFHandle psDBF, int iRecord, int iField)
int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField, const char *pszFieldName, char chType, int nWidth, int nDecimals)
static int DBFLoadRecord(DBFHandle psDBF, int iRecord)
const char SHPAPI_CALL1 * DBFReadTuple(DBFHandle psDBF, int hEntity){ if(hEntity< 0||hEntity >=psDBF->nRecords) return SHPLIB_NULLPTR;if(!DBFLoadRecord(psDBF, hEntity)) return SHPLIB_NULLPTR;return STATIC_CAST(const char *, psDBF->pszCurrentRecord
const char SHPAPI_CALL1 * DBFGetCodePage(DBFHandle psDBF){ if(psDBF==SHPLIB_NULLPTR) return SHPLIB_NULLPTR;return psDBF->pszCodePage;}int SHPAPI_CALLDBFDeleteField(DBFHandle psDBF, int iField
DBFHandle SHPAPI_CALL DBFOpen(const char *pszFilename, const char *pszAccess)
double SHPAPI_CALL DBFReadDoubleAttribute(DBFHandle psDBF, int iRecord, int iField)
int SHPAPI_CALL DBFAddField(DBFHandle psDBF, const char *pszFieldName, DBFFieldType eType, int nWidth, int nDecimals)
const char SHPAPI_CALL1 * DBFReadLogicalAttribute(DBFHandle psDBF, int iRecord, int iField){ return STATIC_CAST(const char *, DBFReadAttribute(psDBF, iRecord, iField, 'L')
static int DBFGetLenWithoutExtension(const char *pszBasename)
DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF, const char *pszFilename)
DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename, const char *pszCodePage, SAHooks *psHooks)
static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField, void *pValue)
int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF)
int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle psDBF, int iRecord, int iField, int nValue)
#define STATIC_CAST(type, x)
int SHPAPI_CALL DBFWriteStringAttribute(DBFHandle psDBF, int iRecord, int iField, const char *pszValue)
DBFHandle SHPAPI_CALL DBFCreateEx(const char *pszFilename, const char *pszCodePage)
#define HEADER_RECORD_TERMINATOR
#define REINTERPRET_CAST(type, x)
void SHPAPI_CALL DBFClose(DBFHandle psDBF)
static void DBFWriteHeader(DBFHandle psDBF)
int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName, char chType, int nWidth, int nDecimals)
DBFHandle SHPAPI_CALL DBFCreate(const char *pszFilename)
#define END_OF_FILE_CHARACTER
void SHPAPI_CALL DBFSetLastModifiedDate(DBFHandle psDBF, int nYYSince1900, int nMM, int nDD)
void SHPAPI_CALL DBFSetWriteEndOfFileChar(DBFHandle psDBF, int bWriteFlag)
DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess, SAHooks *psHooks)
static void * SfRealloc(void *pMem, int nNewSize)
int SHPAPI_CALL DBFWriteNULLAttribute(DBFHandle psDBF, int iRecord, int iField)
static char DBFGetNullCharacter(char chType)
int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle psDBF, int iRecord, int iField)
int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity, void *pRawTuple)
int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField, void *pValue)
static int DBFFlushRecord(DBFHandle psDBF)
int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, int *panMap)
#define CONST_CAST(type, x)
int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape)
int SHPAPI_CALL DBFWriteLogicalAttribute(DBFHandle psDBF, int iRecord, int iField, const char lValue)
char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle psDBF, int iField)
const char SHPAPI_CALL1 * DBFReadStringAttribute(DBFHandle psDBF, int iRecord, int iField){ return STATIC_CAST(const char *, DBFReadAttribute(psDBF, iRecord, iField, 'C')
static void * DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField, char chReqType)
#define CPL_IGNORE_RET_VAL_INT(x)
void SHPAPI_CALL DBFUpdateHeader(DBFHandle psDBF)
DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField, char *pszFieldName, int *pnWidth, int *pnDecimals)
void SASetupDefaultHooks(SAHooks *psHooks)
int SHPAPI_CALL DBFDeleteField(DBFHandle hDBF, int iField)
#define XBASE_FLDNAME_LEN_WRITE
#define XBASE_FLDNAME_LEN_READ
#define XBASE_FLD_MAX_WIDTH
int bCurrentRecordModified
int bRequireNextWriteSeek
union DBFInfo::@4 fieldValue
void(* Error)(const char *message)
SAFile(* FOpen)(const char *filename, const char *access)
SAOffset(* FTell)(SAFile file)
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)