PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ DBFAlterFieldDefn()

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

Definition at line 2035 of file dbfopen.c.

References DBFFlushRecord(), DBFGetNullCharacter(), DBFIsValueNULL(), DBFUpdateHeader(), FALSE, free(), malloc(), SfRealloc(), and TRUE.

2037 {
2038  int i;
2039  int iRecord;
2040  int nOffset;
2041  int nOldWidth;
2042  int nOldRecordLength;
2043  int nRecordOffset;
2044  char* pszFInfo;
2045  char chOldType;
2046  int bIsNULL;
2047  char chFieldFill;
2048 
2049  if (iField < 0 || iField >= psDBF->nFields)
2050  return FALSE;
2051 
2052  /* make sure that everything is written in .dbf */
2053  if( !DBFFlushRecord( psDBF ) )
2054  return FALSE;
2055 
2056  chFieldFill = DBFGetNullCharacter(chType);
2057 
2058  chOldType = psDBF->pachFieldType[iField];
2059  nOffset = psDBF->panFieldOffset[iField];
2060  nOldWidth = psDBF->panFieldSize[iField];
2061  nOldRecordLength = psDBF->nRecordLength;
2062 
2063 /* -------------------------------------------------------------------- */
2064 /* Do some checking to ensure we can add records to this file. */
2065 /* -------------------------------------------------------------------- */
2066  if( nWidth < 1 )
2067  return -1;
2068 
2069  if( nWidth > 255 )
2070  nWidth = 255;
2071 
2072 /* -------------------------------------------------------------------- */
2073 /* Assign the new field information fields. */
2074 /* -------------------------------------------------------------------- */
2075  psDBF->panFieldSize[iField] = nWidth;
2076  psDBF->panFieldDecimals[iField] = nDecimals;
2077  psDBF->pachFieldType[iField] = chType;
2078 
2079 /* -------------------------------------------------------------------- */
2080 /* Update the header information. */
2081 /* -------------------------------------------------------------------- */
2082  pszFInfo = psDBF->pszHeader + 32 * iField;
2083 
2084  for( i = 0; i < 32; i++ )
2085  pszFInfo[i] = '\0';
2086 
2087  if( (int) strlen(pszFieldName) < 10 )
2088  strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
2089  else
2090  strncpy( pszFInfo, pszFieldName, 10);
2091 
2092  pszFInfo[11] = psDBF->pachFieldType[iField];
2093 
2094  if( chType == 'C' )
2095  {
2096  pszFInfo[16] = (unsigned char) (nWidth % 256);
2097  pszFInfo[17] = (unsigned char) (nWidth / 256);
2098  }
2099  else
2100  {
2101  pszFInfo[16] = (unsigned char) nWidth;
2102  pszFInfo[17] = (unsigned char) nDecimals;
2103  }
2104 
2105 /* -------------------------------------------------------------------- */
2106 /* Update offsets */
2107 /* -------------------------------------------------------------------- */
2108  if (nWidth != nOldWidth)
2109  {
2110  for (i = iField + 1; i < psDBF->nFields; i++)
2111  psDBF->panFieldOffset[i] += nWidth - nOldWidth;
2112  psDBF->nRecordLength += nWidth - nOldWidth;
2113 
2114  psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
2115  psDBF->nRecordLength);
2116  }
2117 
2118  /* we're done if we're dealing with not yet created .dbf */
2119  if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
2120  return TRUE;
2121 
2122  /* force update of header with new header and record length */
2123  psDBF->bNoHeader = TRUE;
2124  DBFUpdateHeader( psDBF );
2125 
2126  if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
2127  {
2128  char* pszRecord = (char *) malloc(sizeof(char) * nOldRecordLength);
2129  char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
2130 
2131  pszOldField[nOldWidth] = 0;
2132 
2133  /* move records to their new positions */
2134  for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
2135  {
2136  nRecordOffset =
2137  nOldRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
2138 
2139  /* load record */
2140  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2141  psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
2142 
2143  memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2144  bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
2145 
2146  if (nWidth != nOldWidth)
2147  {
2148  if ((chOldType == 'N' || chOldType == 'F') && pszOldField[0] == ' ')
2149  {
2150  /* Strip leading spaces when truncating a numeric field */
2151  memmove( pszRecord + nOffset,
2152  pszRecord + nOffset + nOldWidth - nWidth,
2153  nWidth );
2154  }
2155  if (nOffset + nOldWidth < nOldRecordLength)
2156  {
2157  memmove( pszRecord + nOffset + nWidth,
2158  pszRecord + nOffset + nOldWidth,
2159  nOldRecordLength - (nOffset + nOldWidth));
2160  }
2161  }
2162 
2163  /* Convert null value to the appropriate value of the new type */
2164  if (bIsNULL)
2165  {
2166  memset( pszRecord + nOffset, chFieldFill, nWidth);
2167  }
2168 
2169  nRecordOffset =
2170  psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
2171 
2172  /* write record */
2173  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2174  psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
2175  }
2176 
2177  free(pszRecord);
2178  free(pszOldField);
2179  }
2180  else if (nWidth > nOldWidth)
2181  {
2182  char* pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
2183  char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
2184 
2185  pszOldField[nOldWidth] = 0;
2186 
2187  /* move records to their new positions */
2188  for (iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
2189  {
2190  nRecordOffset =
2191  nOldRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
2192 
2193  /* load record */
2194  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2195  psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
2196 
2197  memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2198  bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
2199 
2200  if (nOffset + nOldWidth < nOldRecordLength)
2201  {
2202  memmove( pszRecord + nOffset + nWidth,
2203  pszRecord + nOffset + nOldWidth,
2204  nOldRecordLength - (nOffset + nOldWidth));
2205  }
2206 
2207  /* Convert null value to the appropriate value of the new type */
2208  if (bIsNULL)
2209  {
2210  memset( pszRecord + nOffset, chFieldFill, nWidth);
2211  }
2212  else
2213  {
2214  if ((chOldType == 'N' || chOldType == 'F'))
2215  {
2216  /* Add leading spaces when expanding a numeric field */
2217  memmove( pszRecord + nOffset + nWidth - nOldWidth,
2218  pszRecord + nOffset, nOldWidth );
2219  memset( pszRecord + nOffset, ' ', nWidth - nOldWidth );
2220  }
2221  else
2222  {
2223  /* Add trailing spaces */
2224  memset(pszRecord + nOffset + nOldWidth, ' ', nWidth - nOldWidth);
2225  }
2226  }
2227 
2228  nRecordOffset =
2229  psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
2230 
2231  /* write record */
2232  psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2233  psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
2234  }
2235 
2236  free(pszRecord);
2237  free(pszOldField);
2238  }
2239 
2240  psDBF->nCurrentRecord = -1;
2241  psDBF->bCurrentRecordModified = FALSE;
2242 
2243  return TRUE;
2244 }
static void * SfRealloc(void *pMem, int nNewSize)
Definition: dbfopen.c:179
unsigned long SAOffset
Definition: shapefil.h:250
static int DBFIsValueNULL(char chType, const char *pszValue)
Definition: dbfopen.c:1115
static int DBFFlushRecord(DBFHandle psDBF)
Definition: dbfopen.c:258
#define FALSE
Definition: dbfopen.c:168
static char DBFGetNullCharacter(char chType)
Definition: dbfopen.c:796
void free(void *)
void * malloc(YYSIZE_T)
#define TRUE
Definition: dbfopen.c:169
void SHPAPI_CALL DBFUpdateHeader(DBFHandle psDBF)
Definition: dbfopen.c:334
Here is the call graph for this function: