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 )
421 memcpy(pszFullname, pszFilename, nLenWithoutExtension);
422 memcpy(pszFullname + nLenWithoutExtension,
".dbf", 5);
430 psDBF->
fp = psHooks->
FOpen( pszFullname, pszAccess );
435 memcpy(pszFullname + nLenWithoutExtension,
".DBF", 5);
439 memcpy(pszFullname + nLenWithoutExtension,
".cpg", 5);
440 pfCPG = psHooks->
FOpen( pszFullname,
"r" );
443 memcpy(pszFullname + nLenWithoutExtension,
".CPG", 5);
444 pfCPG = psHooks->
FOpen( pszFullname,
"r" );
452 if( pfCPG ) psHooks->
FClose( pfCPG );
476 pabyBuf[4]|(pabyBuf[5]<<8)|(pabyBuf[6]<<16)|((pabyBuf[7]&0x7f)<<24);
478 psDBF->
nHeaderLength = nHeadLen = pabyBuf[8]|(pabyBuf[9]<<8);
504 memset( pabyBuf, 0, nBufSize);
505 psDBF->
sHooks.
FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
546 for( iField = 0; iField < nFields; iField++ )
548 unsigned char *pabyFInfo;
557 if( pabyFInfo[11] ==
'N' || pabyFInfo[11] ==
'F' )
676 return DBFCreateLL( pszFilename, pszCodePage , &sHooks );
694 int nLenWithoutExtension;
704 memcpy(pszFullname, pszFilename, nLenWithoutExtension);
705 memcpy(pszFullname + nLenWithoutExtension,
".dbf", 5);
710 fp = psHooks->
FOpen( pszFullname,
"wb" );
717 psHooks->
FWrite( &chZero, 1, 1, fp );
720 fp = psHooks->
FOpen( pszFullname,
"rb+" );
727 memcpy(pszFullname + nLenWithoutExtension,
".cpg", 5);
730 if( strncmp( pszCodePage,
"LDID/", 5 ) == 0 )
732 ldid = atoi( pszCodePage + 5 );
745 psHooks->
Remove( pszFullname );
801 char chNativeType =
'C';
805 else if( eType ==
FTDate )
845 char chType,
int nWidth,
int nDecimals )
850 int nOldRecordLength, nOldHeaderLength;
862 snprintf( szMessage,
sizeof(szMessage),
863 "Cannot add field %s. Header length limit reached "
864 "(max 65535 bytes, 2046 fields).",
882 snprintf( szMessage,
sizeof(szMessage),
883 "Cannot add field %s. Record length limit reached "
884 "(max 65535 bytes).",
940 pszFInfo[16] =
STATIC_CAST(
unsigned char, nWidth % 256);
941 pszFInfo[17] =
STATIC_CAST(
unsigned char, nWidth / 256);
946 pszFInfo[17] =
STATIC_CAST(
unsigned char, nDecimals);
968 for (i = psDBF->
nRecords-1; i >= 0; --i)
974 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
977 memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
1021 unsigned char *pabyRec;
1027 if( hEntity < 0 || hEntity >= psDBF->
nRecords )
1030 if( iField < 0 || iField >= psDBF->
nFields )
1067 if( chReqType ==
'I' )
1073 else if( chReqType ==
'N' )
1083 #ifdef TRIM_DBF_WHITESPACE
1086 char *pchSrc, *pchDst;
1089 while( *pchSrc ==
' ' )
1092 while( *pchSrc !=
'\0' )
1093 *(pchDst++) = *(pchSrc++);
1096 while( pchDst != psDBF->
pszWorkField && *(--pchDst) ==
' ' )
1101 return pReturnField;
1193 if( pszValue[0] ==
'*' )
1196 for( i = 0; pszValue[i] !=
'\0'; i++ )
1198 if( pszValue[i] !=
' ' )
1205 return strncmp(pszValue,
"00000000",8) == 0;
1209 return pszValue[0] ==
'?';
1213 return strlen(pszValue) == 0;
1229 const char *pszValue;
1275 int * pnWidth,
int * pnDecimals )
1278 if( iField < 0 || iField >= psDBF->
nFields )
1295 pszFieldName[i] =
'\0';
1329 int i, j, nRetResult =
TRUE;
1330 unsigned char *pabyRec;
1336 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1393 if(
STATIC_CAST(
int,
sizeof(szSField))-2 < nWidth )
1394 nWidth =
sizeof(szSField)-2;
1396 snprintf( szFormat,
sizeof(szFormat),
"%%%d.%df",
1399 szSField[
sizeof(szSField)-1] =
'\0';
1406 szSField, strlen(szSField) );
1434 return( nRetResult );
1451 unsigned char *pabyRec;
1456 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1532 double dValue = nValue;
1545 const char * pszValue )
1589 unsigned char *pabyRec;
1594 if( hEntity < 0 || hEntity > psDBF->
nRecords )
1643 if( hEntity < 0 || hEntity >= psDBF->nRecords )
1649 return STATIC_CAST(
const char *, psDBF->pszCurrentRecord);
1692 newDBF =
DBFOpen ( pszFilename,
"rb+" );
1713 if( iField >=0 && iField < psDBF->nFields )
1784 if( iShape < 0 || iShape >= psDBF->
nRecords )
1821 return psDBF->pszCodePage;
1833 int nOldRecordLength, nOldHeaderLength;
1834 int nDeletedFieldOffset, nDeletedFieldSize;
1839 if (iField < 0 || iField >= psDBF->
nFields)
1853 for (i = iField + 1; i < psDBF->
nFields; i++)
1904 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
1911 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
1918 psDBF->
sHooks.
FWrite( pszRecord, nDeletedFieldOffset, 1, psDBF->
fp );
1919 psDBF->
sHooks.
FWrite( pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
1920 nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize,
1962 int *panFieldOffsetNew;
1963 int *panFieldSizeNew;
1964 int *panFieldDecimalsNew;
1965 char *pachFieldTypeNew;
1988 free( panFieldOffsetNew );
1989 free( panFieldSizeNew );
1990 free( panFieldDecimalsNew );
1991 free( pachFieldTypeNew );
1992 free( pszHeaderNew );
1997 for(i=0; i < psDBF->
nFields; i++)
2005 panFieldOffsetNew[0] = 1;
2006 for(i=1; i < psDBF->
nFields; i++)
2008 panFieldOffsetNew[i] = panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
2026 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
2035 pszRecordNew[0] = pszRecord[0];
2037 for(i=0; i < psDBF->
nFields; i++)
2039 memcpy(pszRecordNew + panFieldOffsetNew[i],
2080 char chType,
int nWidth,
int nDecimals )
2086 int nOldRecordLength;
2093 if (iField < 0 || iField >= psDBF->
nFields)
2137 pszFInfo[16] =
STATIC_CAST(
unsigned char, nWidth % 256);
2138 pszFInfo[17] =
STATIC_CAST(
unsigned char, nWidth / 256);
2142 pszFInfo[16] =
STATIC_CAST(
unsigned char, nWidth);
2143 pszFInfo[17] =
STATIC_CAST(
unsigned char, nDecimals);
2149 if (nWidth != nOldWidth)
2151 for (i = iField + 1; i < psDBF->
nFields; i++)
2167 if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
2170 char* pszOldField =
STATIC_CAST(
char *,
malloc(
sizeof(
char) * (nOldWidth + 1)));
2173 pszOldField[nOldWidth] = 0;
2176 for (iRecord = 0; iRecord < psDBF->
nRecords; iRecord++)
2183 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
2185 memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2188 if (nWidth != nOldWidth)
2190 if ((chOldType ==
'N' || chOldType ==
'F' || chOldType ==
'D') && pszOldField[0] ==
' ')
2193 memmove( pszRecord + nOffset,
2194 pszRecord + nOffset + nOldWidth - nWidth,
2197 if (nOffset + nOldWidth < nOldRecordLength)
2199 memmove( pszRecord + nOffset + nWidth,
2200 pszRecord + nOffset + nOldWidth,
2201 nOldRecordLength - (nOffset + nOldWidth));
2208 memset( pszRecord + nOffset, chFieldFill, nWidth);
2234 else if (nWidth > nOldWidth)
2237 char* pszOldField =
STATIC_CAST(
char *,
malloc(
sizeof(
char) * (nOldWidth + 1)));
2240 pszOldField[nOldWidth] = 0;
2243 for (iRecord = psDBF->
nRecords - 1; iRecord >= 0; iRecord--)
2250 psDBF->
sHooks.
FRead( pszRecord, nOldRecordLength, 1, psDBF->
fp );
2252 memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2255 if (nOffset + nOldWidth < nOldRecordLength)
2257 memmove( pszRecord + nOffset + nWidth,
2258 pszRecord + nOffset + nOldWidth,
2259 nOldRecordLength - (nOffset + nOldWidth));
2265 memset( pszRecord + nOffset, chFieldFill, nWidth);
2269 if ((chOldType ==
'N' || chOldType ==
'F'))
2272 memmove( pszRecord + nOffset + nWidth - nOldWidth,
2273 pszRecord + nOffset, nOldWidth );
2274 memset( pszRecord + nOffset,
' ', nWidth - nOldWidth );
2279 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
union DBFInfo::@5 fieldValue
int bCurrentRecordModified
int bRequireNextWriteSeek
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)