PostGIS  2.1.10dev-r@@SVN_REVISION@@
int SHPAPI_CALL DBFAlterFieldDefn ( DBFHandle  psDBF,
int  iField,
const char *  pszFieldName,
char  chType,
int  nWidth,
int  nDecimals 
)

Definition at line 2032 of file dbfopen.c.

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

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

Here is the call graph for this function: