PostGIS  3.4.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 2059 of file dbfopen.c.

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