PostGIS 3.6.2dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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
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;
2287 psDBF->bUpdated = TRUE;
2288
2289 return TRUE;
2290}
static int DBFIsValueNULL(char chType, const char *pszValue)
Definition dbfopen.c:1168
static void * SfRealloc(void *pMem, int nNewSize)
Definition dbfopen.c:109
#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 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: