PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ DBFAddNativeFieldType()

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

Definition at line 835 of file dbfopen.c.

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