PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ DBFAddNativeFieldType()

int SHPAPI_CALL DBFAddNativeFieldType ( DBFHandle  hDBF,
const char *  pszFieldName,
char  chType,
int  nWidth,
int  nDecimals 
)

Definition at line 844 of file dbfopen.c.

847 {
848  char *pszFInfo;
849  int i;
850  int nOldRecordLength, nOldHeaderLength;
851  char *pszRecord;
852  char chFieldFill;
853  SAOffset nRecordOffset;
854 
855  /* make sure that everything is written in .dbf */
856  if( !DBFFlushRecord( psDBF ) )
857  return -1;
858 
859  if( psDBF->nHeaderLength + XBASE_FLDHDR_SZ > 65535 )
860  {
861  char szMessage[128];
862  snprintf( szMessage, sizeof(szMessage),
863  "Cannot add field %s. Header length limit reached "
864  "(max 65535 bytes, 2046 fields).",
865  pszFieldName );
866  psDBF->sHooks.Error( szMessage );
867  return -1;
868  }
869 
870 /* -------------------------------------------------------------------- */
871 /* Do some checking to ensure we can add records to this file. */
872 /* -------------------------------------------------------------------- */
873  if( nWidth < 1 )
874  return -1;
875 
876  if( nWidth > XBASE_FLD_MAX_WIDTH )
877  nWidth = XBASE_FLD_MAX_WIDTH;
878 
879  if( psDBF->nRecordLength + nWidth > 65535 )
880  {
881  char szMessage[128];
882  snprintf( szMessage, sizeof(szMessage),
883  "Cannot add field %s. Record length limit reached "
884  "(max 65535 bytes).",
885  pszFieldName );
886  psDBF->sHooks.Error( szMessage );
887  return -1;
888  }
889 
890  nOldRecordLength = psDBF->nRecordLength;
891  nOldHeaderLength = psDBF->nHeaderLength;
892 
893 /* -------------------------------------------------------------------- */
894 /* SfRealloc all the arrays larger to hold the additional field */
895 /* information. */
896 /* -------------------------------------------------------------------- */
897  psDBF->nFields++;
898 
899  psDBF->panFieldOffset = STATIC_CAST(int *,
900  SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields ));
901 
902  psDBF->panFieldSize = STATIC_CAST(int *,
903  SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields ));
904 
905  psDBF->panFieldDecimals = STATIC_CAST(int *,
906  SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields ));
907 
908  psDBF->pachFieldType = STATIC_CAST(char *,
909  SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields ));
910 
911 /* -------------------------------------------------------------------- */
912 /* Assign the new field information fields. */
913 /* -------------------------------------------------------------------- */
914  psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
915  psDBF->nRecordLength += nWidth;
916  psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
917  psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
918  psDBF->pachFieldType[psDBF->nFields-1] = chType;
919 
920 /* -------------------------------------------------------------------- */
921 /* Extend the required header information. */
922 /* -------------------------------------------------------------------- */
923  psDBF->nHeaderLength += XBASE_FLDHDR_SZ;
924  psDBF->bUpdated = FALSE;
925 
926  psDBF->pszHeader = STATIC_CAST(char *, SfRealloc(psDBF->pszHeader,
927  psDBF->nFields*XBASE_FLDHDR_SZ));
928 
929  pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields-1);
930 
931  for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
932  pszFInfo[i] = '\0';
933 
934  strncpy( pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE );
935 
936  pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
937 
938  if( chType == 'C' )
939  {
940  pszFInfo[16] = STATIC_CAST(unsigned char, nWidth % 256);
941  pszFInfo[17] = STATIC_CAST(unsigned char, nWidth / 256);
942  }
943  else
944  {
945  pszFInfo[16] = STATIC_CAST(unsigned char, nWidth);
946  pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
947  }
948 
949 /* -------------------------------------------------------------------- */
950 /* Make the current record buffer appropriately larger. */
951 /* -------------------------------------------------------------------- */
952  psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
953  psDBF->nRecordLength));
954 
955  /* we're done if dealing with new .dbf */
956  if( psDBF->bNoHeader )
957  return( psDBF->nFields - 1 );
958 
959 /* -------------------------------------------------------------------- */
960 /* For existing .dbf file, shift records */
961 /* -------------------------------------------------------------------- */
962 
963  /* alloc record */
964  pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
965 
966  chFieldFill = DBFGetNullCharacter(chType);
967 
968  for (i = psDBF->nRecords-1; i >= 0; --i)
969  {
970  nRecordOffset = nOldRecordLength * STATIC_CAST(SAOffset, i) + nOldHeaderLength;
971 
972  /* load record */
973  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
974  psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
975 
976  /* set new field's value to NULL */
977  memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
978 
979  nRecordOffset = psDBF->nRecordLength * STATIC_CAST(SAOffset, i) + psDBF->nHeaderLength;
980 
981  /* move record to the new place*/
982  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
983  psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
984  }
985 
986  if( psDBF->bWriteEndOfFileChar )
987  {
988  char ch = END_OF_FILE_CHARACTER;
989 
990  nRecordOffset =
991  psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
992 
993  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
994  psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
995  }
996 
997  /* free record */
998  free(pszRecord);
999 
1000  /* force update of header with new header, record length and new field */
1001  psDBF->bNoHeader = TRUE;
1002  DBFUpdateHeader( psDBF );
1003 
1004  psDBF->nCurrentRecord = -1;
1005  psDBF->bCurrentRecordModified = FALSE;
1006  psDBF->bUpdated = TRUE;
1007 
1008  return( psDBF->nFields-1 );
1009 }
#define STATIC_CAST(type, x)
Definition: dbfopen.c:96
#define TRUE
Definition: dbfopen.c:73
#define FALSE
Definition: dbfopen.c:72
#define END_OF_FILE_CHARACTER
Definition: dbfopen.c:82
static void * SfRealloc(void *pMem, int nNewSize)
Definition: dbfopen.c:109
static char DBFGetNullCharacter(char chType)
Definition: dbfopen.c:820
static int DBFFlushRecord(DBFHandle psDBF)
Definition: dbfopen.c:195
void SHPAPI_CALL DBFUpdateHeader(DBFHandle psDBF)
Definition: dbfopen.c:304
void * malloc(YYSIZE_T)
void free(void *)
#define XBASE_FLDNAME_LEN_WRITE
Definition: shapefil.h:652
#define XBASE_FLDHDR_SZ
Definition: shapefil.h:648
#define XBASE_FLD_MAX_WIDTH
Definition: shapefil.h:654
unsigned long SAOffset
Definition: shapefil.h:286

References DBFInfo::bCurrentRecordModified, DBFInfo::bNoHeader, DBFInfo::bUpdated, DBFInfo::bWriteEndOfFileChar, DBFFlushRecord(), DBFGetNullCharacter(), DBFUpdateHeader(), END_OF_FILE_CHARACTER, SAHooks::Error, FALSE, DBFInfo::fp, SAHooks::FRead, free(), SAHooks::FSeek, SAHooks::FWrite, malloc(), DBFInfo::nCurrentRecord, DBFInfo::nFields, DBFInfo::nHeaderLength, DBFInfo::nRecordLength, DBFInfo::nRecords, DBFInfo::pachFieldType, DBFInfo::panFieldDecimals, DBFInfo::panFieldOffset, DBFInfo::panFieldSize, DBFInfo::pszCurrentRecord, DBFInfo::pszHeader, SfRealloc(), DBFInfo::sHooks, STATIC_CAST, TRUE, XBASE_FLD_MAX_WIDTH, XBASE_FLDHDR_SZ, and XBASE_FLDNAME_LEN_WRITE.

Referenced by DBFAddField().

Here is the call graph for this function:
Here is the caller graph for this function: