PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ DBFAlterFieldDefn()

int SHPAPI_CALL DBFAlterFieldDefn ( DBFHandle  psDBF,
int  iField,
const char *  pszFieldName,
char  chType,
int  nWidth,
int  nDecimals 
)

Definition at line 2079 of file dbfopen.c.

2081 {
2082  int i;
2083  int iRecord;
2084  int nOffset;
2085  int nOldWidth;
2086  int nOldRecordLength;
2087  SAOffset nRecordOffset;
2088  char* pszFInfo;
2089  char chOldType;
2090  int bIsNULL;
2091  char chFieldFill;
2092 
2093  if (iField < 0 || iField >= psDBF->nFields)
2094  return FALSE;
2095 
2096  /* make sure that everything is written in .dbf */
2097  if( !DBFFlushRecord( psDBF ) )
2098  return FALSE;
2099 
2100  chFieldFill = DBFGetNullCharacter(chType);
2101 
2102  chOldType = psDBF->pachFieldType[iField];
2103  nOffset = psDBF->panFieldOffset[iField];
2104  nOldWidth = psDBF->panFieldSize[iField];
2105  nOldRecordLength = psDBF->nRecordLength;
2106 
2107 /* -------------------------------------------------------------------- */
2108 /* Do some checking to ensure we can add records to this file. */
2109 /* -------------------------------------------------------------------- */
2110  if( nWidth < 1 )
2111  return -1;
2112 
2113  if( nWidth > XBASE_FLD_MAX_WIDTH )
2114  nWidth = XBASE_FLD_MAX_WIDTH;
2115 
2116 /* -------------------------------------------------------------------- */
2117 /* Assign the new field information fields. */
2118 /* -------------------------------------------------------------------- */
2119  psDBF->panFieldSize[iField] = nWidth;
2120  psDBF->panFieldDecimals[iField] = nDecimals;
2121  psDBF->pachFieldType[iField] = chType;
2122 
2123 /* -------------------------------------------------------------------- */
2124 /* Update the header information. */
2125 /* -------------------------------------------------------------------- */
2126  pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * iField;
2127 
2128  for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
2129  pszFInfo[i] = '\0';
2130 
2131  strncpy( pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE );
2132 
2133  pszFInfo[11] = psDBF->pachFieldType[iField];
2134 
2135  if( chType == 'C' )
2136  {
2137  pszFInfo[16] = STATIC_CAST(unsigned char, nWidth % 256);
2138  pszFInfo[17] = STATIC_CAST(unsigned char, nWidth / 256);
2139  }
2140  else
2141  {
2142  pszFInfo[16] = STATIC_CAST(unsigned char, nWidth);
2143  pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
2144  }
2145 
2146 /* -------------------------------------------------------------------- */
2147 /* Update offsets */
2148 /* -------------------------------------------------------------------- */
2149  if (nWidth != nOldWidth)
2150  {
2151  for (i = iField + 1; i < psDBF->nFields; i++)
2152  psDBF->panFieldOffset[i] += nWidth - nOldWidth;
2153  psDBF->nRecordLength += nWidth - nOldWidth;
2154 
2155  psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
2156  psDBF->nRecordLength));
2157  }
2158 
2159  /* we're done if we're dealing with not yet created .dbf */
2160  if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
2161  return TRUE;
2162 
2163  /* force update of header with new header and record length */
2164  psDBF->bNoHeader = TRUE;
2165  DBFUpdateHeader( psDBF );
2166 
2167  if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
2168  {
2169  char* pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
2170  char* pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
2171 
2172  /* cppcheck-suppress uninitdata */
2173  pszOldField[nOldWidth] = 0;
2174 
2175  /* move records to their new positions */
2176  for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
2177  {
2178  nRecordOffset =
2179  nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
2180 
2181  /* load record */
2182  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2183  psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
2184 
2185  memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2186  bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
2187 
2188  if (nWidth != nOldWidth)
2189  {
2190  if ((chOldType == 'N' || chOldType == 'F' || chOldType == 'D') && pszOldField[0] == ' ')
2191  {
2192  /* Strip leading spaces when truncating a numeric field */
2193  memmove( pszRecord + nOffset,
2194  pszRecord + nOffset + nOldWidth - nWidth,
2195  nWidth );
2196  }
2197  if (nOffset + nOldWidth < nOldRecordLength)
2198  {
2199  memmove( pszRecord + nOffset + nWidth,
2200  pszRecord + nOffset + nOldWidth,
2201  nOldRecordLength - (nOffset + nOldWidth));
2202  }
2203  }
2204 
2205  /* Convert null value to the appropriate value of the new type */
2206  if (bIsNULL)
2207  {
2208  memset( pszRecord + nOffset, chFieldFill, nWidth);
2209  }
2210 
2211  nRecordOffset =
2212  psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
2213 
2214  /* write record */
2215  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2216  psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
2217  }
2218 
2219  if( psDBF->bWriteEndOfFileChar )
2220  {
2221  char ch = END_OF_FILE_CHARACTER;
2222 
2223  nRecordOffset =
2224  psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
2225 
2226  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2227  psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
2228  }
2229  /* TODO: truncate file */
2230 
2231  free(pszRecord);
2232  free(pszOldField);
2233  }
2234  else if (nWidth > nOldWidth)
2235  {
2236  char* pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
2237  char* pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
2238 
2239  /* cppcheck-suppress uninitdata */
2240  pszOldField[nOldWidth] = 0;
2241 
2242  /* move records to their new positions */
2243  for (iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
2244  {
2245  nRecordOffset =
2246  nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
2247 
2248  /* load record */
2249  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2250  psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
2251 
2252  memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2253  bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
2254 
2255  if (nOffset + nOldWidth < nOldRecordLength)
2256  {
2257  memmove( pszRecord + nOffset + nWidth,
2258  pszRecord + nOffset + nOldWidth,
2259  nOldRecordLength - (nOffset + nOldWidth));
2260  }
2261 
2262  /* Convert null value to the appropriate value of the new type */
2263  if (bIsNULL)
2264  {
2265  memset( pszRecord + nOffset, chFieldFill, nWidth);
2266  }
2267  else
2268  {
2269  if ((chOldType == 'N' || chOldType == 'F'))
2270  {
2271  /* Add leading spaces when expanding a numeric field */
2272  memmove( pszRecord + nOffset + nWidth - nOldWidth,
2273  pszRecord + nOffset, nOldWidth );
2274  memset( pszRecord + nOffset, ' ', nWidth - nOldWidth );
2275  }
2276  else
2277  {
2278  /* Add trailing spaces */
2279  memset(pszRecord + nOffset + nOldWidth, ' ', nWidth - nOldWidth);
2280  }
2281  }
2282 
2283  nRecordOffset =
2284  psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
2285 
2286  /* write record */
2287  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2288  psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
2289  }
2290 
2291  if( psDBF->bWriteEndOfFileChar )
2292  {
2293  char ch = END_OF_FILE_CHARACTER;
2294 
2295  nRecordOffset =
2296  psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
2297 
2298  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2299  psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
2300  }
2301 
2302  free(pszRecord);
2303  free(pszOldField);
2304  }
2305 
2306  psDBF->nCurrentRecord = -1;
2307  psDBF->bCurrentRecordModified = FALSE;
2308  psDBF->bUpdated = TRUE;
2309 
2310  return TRUE;
2311 }
static int DBFIsValueNULL(char chType, const char *pszValue)
Definition: dbfopen.c:1177
#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
int bWriteEndOfFileChar
Definition: shapefil.h:631
int nRecordLength
Definition: shapefil.h:596
int * panFieldOffset
Definition: shapefil.h:601
int * panFieldDecimals
Definition: shapefil.h:603
int nFields
Definition: shapefil.h:600
int bUpdated
Definition: shapefil.h:616
int nHeaderLength
Definition: shapefil.h:597
int * panFieldSize
Definition: shapefil.h:602
char * pszCurrentRecord
Definition: shapefil.h:610
int bCurrentRecordModified
Definition: shapefil.h:609
char * pszHeader
Definition: shapefil.h:606
SAFile fp
Definition: shapefil.h:592
char * pachFieldType
Definition: shapefil.h:604
SAHooks sHooks
Definition: shapefil.h:590
int bNoHeader
Definition: shapefil.h:615
int nRecords
Definition: shapefil.h:594
int nCurrentRecord
Definition: shapefil.h:608
SAOffset(* FWrite)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
Definition: shapefil.h:292
SAOffset(* FRead)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
Definition: shapefil.h:291
SAOffset(* FSeek)(SAFile file, SAOffset offset, int whence)
Definition: shapefil.h:293

References DBFInfo::bCurrentRecordModified, DBFInfo::bNoHeader, DBFInfo::bUpdated, DBFInfo::bWriteEndOfFileChar, DBFFlushRecord(), DBFGetNullCharacter(), DBFIsValueNULL(), DBFUpdateHeader(), END_OF_FILE_CHARACTER, 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.

Here is the call graph for this function: