PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ DBFAlterFieldDefn()

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

Definition at line 1965 of file dbfopen.c.

1966 {
1967  int i;
1968  int iRecord;
1969  int nOffset;
1970  int nOldWidth;
1971  int nOldRecordLength;
1972  int nRecordOffset;
1973  char *pszFInfo;
1974  char chOldType;
1975  int bIsNULL;
1976  char chFieldFill;
1977 
1978  if (iField < 0 || iField >= psDBF->nFields)
1979  return FALSE;
1980 
1981  /* make sure that everything is written in .dbf */
1982  if (!DBFFlushRecord(psDBF))
1983  return FALSE;
1984 
1985  chFieldFill = DBFGetNullCharacter(chType);
1986 
1987  chOldType = psDBF->pachFieldType[iField];
1988  nOffset = psDBF->panFieldOffset[iField];
1989  nOldWidth = psDBF->panFieldSize[iField];
1990  nOldRecordLength = psDBF->nRecordLength;
1991 
1992  /* -------------------------------------------------------------------- */
1993  /* Do some checking to ensure we can add records to this file. */
1994  /* -------------------------------------------------------------------- */
1995  if (nWidth < 1)
1996  return -1;
1997 
1998  if (nWidth > 255)
1999  nWidth = 255;
2000 
2001  /* -------------------------------------------------------------------- */
2002  /* Assign the new field information fields. */
2003  /* -------------------------------------------------------------------- */
2004  psDBF->panFieldSize[iField] = nWidth;
2005  psDBF->panFieldDecimals[iField] = nDecimals;
2006  psDBF->pachFieldType[iField] = chType;
2007 
2008  /* -------------------------------------------------------------------- */
2009  /* Update the header information. */
2010  /* -------------------------------------------------------------------- */
2011  pszFInfo = psDBF->pszHeader + 32 * iField;
2012 
2013  for (i = 0; i < 32; i++)
2014  pszFInfo[i] = '\0';
2015 
2016  snprintf(pszFInfo, 10, "%s", pszFieldName);
2017 
2018  pszFInfo[11] = psDBF->pachFieldType[iField];
2019 
2020  if (chType == 'C')
2021  {
2022  pszFInfo[16] = (unsigned char)(nWidth % 256);
2023  pszFInfo[17] = (unsigned char)(nWidth / 256);
2024  }
2025  else
2026  {
2027  pszFInfo[16] = (unsigned char)nWidth;
2028  pszFInfo[17] = (unsigned char)nDecimals;
2029  }
2030 
2031  /* -------------------------------------------------------------------- */
2032  /* Update offsets */
2033  /* -------------------------------------------------------------------- */
2034  if (nWidth != nOldWidth)
2035  {
2036  for (i = iField + 1; i < psDBF->nFields; i++)
2037  psDBF->panFieldOffset[i] += nWidth - nOldWidth;
2038  psDBF->nRecordLength += nWidth - nOldWidth;
2039 
2040  psDBF->pszCurrentRecord = (char *)SfRealloc(psDBF->pszCurrentRecord, psDBF->nRecordLength);
2041  }
2042 
2043  /* we're done if we're dealing with not yet created .dbf */
2044  if (psDBF->bNoHeader && psDBF->nRecords == 0)
2045  return TRUE;
2046 
2047  /* force update of header with new header and record length */
2048  psDBF->bNoHeader = TRUE;
2049  DBFUpdateHeader(psDBF);
2050 
2051  if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
2052  {
2053  char *pszRecord = (char *)malloc(sizeof(char) * nOldRecordLength);
2054  char *pszOldField = (char *)malloc(sizeof(char) * (nOldWidth + 1));
2055 
2056  pszOldField[nOldWidth] = 0;
2057 
2058  /* move records to their new positions */
2059  for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
2060  {
2061  nRecordOffset = nOldRecordLength * (SAOffset)iRecord + psDBF->nHeaderLength;
2062 
2063  /* load record */
2064  psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
2065  psDBF->sHooks.FRead(pszRecord, nOldRecordLength, 1, psDBF->fp);
2066 
2067  memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2068  bIsNULL = DBFIsValueNULL(chOldType, pszOldField);
2069 
2070  if (nWidth != nOldWidth)
2071  {
2072  if ((chOldType == 'N' || chOldType == 'F') && pszOldField[0] == ' ')
2073  {
2074  /* Strip leading spaces when truncating a numeric field */
2075  memmove(pszRecord + nOffset, pszRecord + nOffset + nOldWidth - nWidth, nWidth);
2076  }
2077  if (nOffset + nOldWidth < nOldRecordLength)
2078  {
2079  memmove(pszRecord + nOffset + nWidth,
2080  pszRecord + nOffset + nOldWidth,
2081  nOldRecordLength - (nOffset + nOldWidth));
2082  }
2083  }
2084 
2085  /* Convert null value to the appropriate value of the new type */
2086  if (bIsNULL)
2087  {
2088  memset(pszRecord + nOffset, chFieldFill, nWidth);
2089  }
2090 
2091  nRecordOffset = psDBF->nRecordLength * (SAOffset)iRecord + psDBF->nHeaderLength;
2092 
2093  /* write record */
2094  psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
2095  psDBF->sHooks.FWrite(pszRecord, psDBF->nRecordLength, 1, psDBF->fp);
2096  }
2097 
2098  free(pszRecord);
2099  free(pszOldField);
2100  }
2101  else if (nWidth > nOldWidth)
2102  {
2103  char *pszRecord = (char *)malloc(sizeof(char) * psDBF->nRecordLength);
2104  char *pszOldField = (char *)malloc(sizeof(char) * (nOldWidth + 1));
2105 
2106  pszOldField[nOldWidth] = 0;
2107 
2108  /* move records to their new positions */
2109  for (iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
2110  {
2111  nRecordOffset = nOldRecordLength * (SAOffset)iRecord + psDBF->nHeaderLength;
2112 
2113  /* load record */
2114  psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
2115  psDBF->sHooks.FRead(pszRecord, nOldRecordLength, 1, psDBF->fp);
2116 
2117  memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2118  bIsNULL = DBFIsValueNULL(chOldType, pszOldField);
2119 
2120  if (nOffset + nOldWidth < nOldRecordLength)
2121  {
2122  memmove(pszRecord + nOffset + nWidth,
2123  pszRecord + nOffset + nOldWidth,
2124  nOldRecordLength - (nOffset + nOldWidth));
2125  }
2126 
2127  /* Convert null value to the appropriate value of the new type */
2128  if (bIsNULL)
2129  {
2130  memset(pszRecord + nOffset, chFieldFill, nWidth);
2131  }
2132  else
2133  {
2134  if ((chOldType == 'N' || chOldType == 'F'))
2135  {
2136  /* Add leading spaces when expanding a numeric field */
2137  memmove(
2138  pszRecord + nOffset + nWidth - nOldWidth, pszRecord + nOffset, nOldWidth);
2139  memset(pszRecord + nOffset, ' ', nWidth - nOldWidth);
2140  }
2141  else
2142  {
2143  /* Add trailing spaces */
2144  memset(pszRecord + nOffset + nOldWidth, ' ', nWidth - nOldWidth);
2145  }
2146  }
2147 
2148  nRecordOffset = psDBF->nRecordLength * (SAOffset)iRecord + psDBF->nHeaderLength;
2149 
2150  /* write record */
2151  psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
2152  psDBF->sHooks.FWrite(pszRecord, psDBF->nRecordLength, 1, psDBF->fp);
2153  }
2154 
2155  free(pszRecord);
2156  free(pszOldField);
2157  }
2158 
2159  psDBF->nCurrentRecord = -1;
2160  psDBF->bCurrentRecordModified = FALSE;
2161 
2162  return TRUE;
2163 }
static int DBFIsValueNULL(char chType, const char *pszValue)
Definition: dbfopen.c:1080
#define TRUE
Definition: dbfopen.c:169
#define FALSE
Definition: dbfopen.c:168
static void * SfRealloc(void *pMem, int nNewSize)
Definition: dbfopen.c:180
static char DBFGetNullCharacter(char chType)
Definition: dbfopen.c:778
static int DBFFlushRecord(DBFHandle psDBF)
Definition: dbfopen.c:258
void SHPAPI_CALL DBFUpdateHeader(DBFHandle psDBF)
Definition: dbfopen.c:324
void * malloc(YYSIZE_T)
void free(void *)
unsigned long SAOffset
Definition: shapefil.h:250

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

Here is the call graph for this function: