PostGIS  2.2.8dev-r@@SVN_REVISION@@

◆ DBFAlterFieldDefn()

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

Definition at line 2031 of file dbfopen.c.

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

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