PostGIS 3.7.0dev-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 2079 of file dbfopen.c.

2081{
2082 int i;
2083 int iRecord;
2084 int nOffset;
2085 int nOldWidth;
2086 int nOldRecordLength;
2087 SAOffset nRecordOffset;
2088 char* pszFInfo;
2089 char chOldType;
2090 int bIsNULL;
2091 char chFieldFill;
2092
2093 if (iField < 0 || iField >= psDBF->nFields)
2094 return FALSE;
2095
2096 /* make sure that everything is written in .dbf */
2097 if( !DBFFlushRecord( psDBF ) )
2098 return FALSE;
2099
2100 chFieldFill = DBFGetNullCharacter(chType);
2101
2102 chOldType = psDBF->pachFieldType[iField];
2103 nOffset = psDBF->panFieldOffset[iField];
2104 nOldWidth = psDBF->panFieldSize[iField];
2105 nOldRecordLength = psDBF->nRecordLength;
2106
2107/* -------------------------------------------------------------------- */
2108/* Do some checking to ensure we can add records to this file. */
2109/* -------------------------------------------------------------------- */
2110 if( nWidth < 1 )
2111 return -1;
2112
2113 if( nWidth > XBASE_FLD_MAX_WIDTH )
2114 nWidth = XBASE_FLD_MAX_WIDTH;
2115
2116/* -------------------------------------------------------------------- */
2117/* Assign the new field information fields. */
2118/* -------------------------------------------------------------------- */
2119 psDBF->panFieldSize[iField] = nWidth;
2120 psDBF->panFieldDecimals[iField] = nDecimals;
2121 psDBF->pachFieldType[iField] = chType;
2122
2123/* -------------------------------------------------------------------- */
2124/* Update the header information. */
2125/* -------------------------------------------------------------------- */
2126 pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * iField;
2127
2128 for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
2129 pszFInfo[i] = '\0';
2130
2131 strncpy( pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE );
2132
2133 pszFInfo[11] = psDBF->pachFieldType[iField];
2134
2135 if( chType == 'C' )
2136 {
2137 pszFInfo[16] = STATIC_CAST(unsigned char, nWidth % 256);
2138 pszFInfo[17] = STATIC_CAST(unsigned char, nWidth / 256);
2139 }
2140 else
2141 {
2142 pszFInfo[16] = STATIC_CAST(unsigned char, nWidth);
2143 pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
2144 }
2145
2146/* -------------------------------------------------------------------- */
2147/* Update offsets */
2148/* -------------------------------------------------------------------- */
2149 if (nWidth != nOldWidth)
2150 {
2151 for (i = iField + 1; i < psDBF->nFields; i++)
2152 psDBF->panFieldOffset[i] += nWidth - nOldWidth;
2153 psDBF->nRecordLength += nWidth - nOldWidth;
2154
2156 psDBF->nRecordLength));
2157 }
2158
2159 /* we're done if we're dealing with not yet created .dbf */
2160 if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
2161 return TRUE;
2162
2163 /* force update of header with new header and record length */
2164 psDBF->bNoHeader = TRUE;
2165 DBFUpdateHeader( psDBF );
2166
2167 if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
2168 {
2169 char* pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
2170 char* pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
2171
2172 /* cppcheck-suppress uninitdata */
2173 pszOldField[nOldWidth] = 0;
2174
2175 /* move records to their new positions */
2176 for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
2177 {
2178 nRecordOffset =
2179 nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
2180
2181 /* load record */
2182 psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2183 psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
2184
2185 memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2186 bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
2187
2188 if (nWidth != nOldWidth)
2189 {
2190 if ((chOldType == 'N' || chOldType == 'F' || chOldType == 'D') && pszOldField[0] == ' ')
2191 {
2192 /* Strip leading spaces when truncating a numeric field */
2193 memmove( pszRecord + nOffset,
2194 pszRecord + nOffset + nOldWidth - nWidth,
2195 nWidth );
2196 }
2197 if (nOffset + nOldWidth < nOldRecordLength)
2198 {
2199 memmove( pszRecord + nOffset + nWidth,
2200 pszRecord + nOffset + nOldWidth,
2201 nOldRecordLength - (nOffset + nOldWidth));
2202 }
2203 }
2204
2205 /* Convert null value to the appropriate value of the new type */
2206 if (bIsNULL)
2207 {
2208 memset( pszRecord + nOffset, chFieldFill, nWidth);
2209 }
2210
2211 nRecordOffset =
2212 psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
2213
2214 /* write record */
2215 psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2216 psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
2217 }
2218
2219 if( psDBF->bWriteEndOfFileChar )
2220 {
2221 char ch = END_OF_FILE_CHARACTER;
2222
2223 nRecordOffset =
2224 psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
2225
2226 psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2227 psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
2228 }
2229 /* TODO: truncate file */
2230
2231 free(pszRecord);
2232 free(pszOldField);
2233 }
2234 else if (nWidth > nOldWidth)
2235 {
2236 char* pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
2237 char* pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
2238
2239 /* cppcheck-suppress uninitdata */
2240 pszOldField[nOldWidth] = 0;
2241
2242 /* move records to their new positions */
2243 for (iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
2244 {
2245 nRecordOffset =
2246 nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
2247
2248 /* load record */
2249 psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2250 psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
2251
2252 memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
2253 bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
2254
2255 if (nOffset + nOldWidth < nOldRecordLength)
2256 {
2257 memmove( pszRecord + nOffset + nWidth,
2258 pszRecord + nOffset + nOldWidth,
2259 nOldRecordLength - (nOffset + nOldWidth));
2260 }
2261
2262 /* Convert null value to the appropriate value of the new type */
2263 if (bIsNULL)
2264 {
2265 memset( pszRecord + nOffset, chFieldFill, nWidth);
2266 }
2267 else
2268 {
2269 if ((chOldType == 'N' || chOldType == 'F'))
2270 {
2271 /* Add leading spaces when expanding a numeric field */
2272 memmove( pszRecord + nOffset + nWidth - nOldWidth,
2273 pszRecord + nOffset, nOldWidth );
2274 memset( pszRecord + nOffset, ' ', nWidth - nOldWidth );
2275 }
2276 else
2277 {
2278 /* Add trailing spaces */
2279 memset(pszRecord + nOffset + nOldWidth, ' ', nWidth - nOldWidth);
2280 }
2281 }
2282
2283 nRecordOffset =
2284 psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
2285
2286 /* write record */
2287 psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2288 psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
2289 }
2290
2291 if( psDBF->bWriteEndOfFileChar )
2292 {
2293 char ch = END_OF_FILE_CHARACTER;
2294
2295 nRecordOffset =
2296 psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
2297
2298 psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
2299 psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
2300 }
2301
2302 free(pszRecord);
2303 free(pszOldField);
2304 }
2305
2306 psDBF->nCurrentRecord = -1;
2308 psDBF->bUpdated = TRUE;
2309
2310 return TRUE;
2311}
static int DBFIsValueNULL(char chType, const char *pszValue)
Definition dbfopen.c:1177
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:820
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: