PostGIS  3.6.1dev-r@@SVN_REVISION@@

◆ DBFAlterFieldDefn()

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

Definition at line 2058 of file dbfopen.c.

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