1 : /* $Id: avc_binwr.c,v 1.18 2008/07/23 20:51:38 dmorissette Exp $
2 : *
3 : * Name: avc_binwr.c
4 : * Project: Arc/Info vector coverage (AVC) E00->BIN conversion library
5 : * Language: ANSI C
6 : * Purpose: Binary files access functions (write mode).
7 : * Author: Daniel Morissette, dmorissette@dmsolutions.ca
8 : *
9 : **********************************************************************
10 : * Copyright (c) 1999-2001, Daniel Morissette
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : **********************************************************************
30 : *
31 : * $Log: avc_binwr.c,v $
32 : * Revision 1.18 2008/07/23 20:51:38 dmorissette
33 : * Fixed GCC 4.1.x compile warnings related to use of char vs unsigned char
34 : * (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2495)
35 : *
36 : * Revision 1.17 2006/06/14 16:31:28 daniel
37 : * Added support for AVCCoverPC2 type (bug 1491)
38 : *
39 : * Revision 1.16 2005/06/03 03:49:58 daniel
40 : * Update email address, website url, and copyright dates
41 : *
42 : * Revision 1.15 2001/07/06 05:09:33 daniel
43 : * Removed #ifdef around fseek to fix NT4 drive problem since ANSI-C requires
44 : * an fseek() between read and write operations so this applies to Unix too.
45 : *
46 : * Revision 1.14 2001/07/06 04:25:00 daniel
47 : * Fixed a problem writing arc.dir on NT4 networked drives in an empty dir.
48 : *
49 : * Revision 1.13 2000/10/16 16:13:29 daniel
50 : * Fixed sHeader.nPrecision when writing PC TXT files
51 : *
52 : * Revision 1.12 2000/09/26 21:40:18 daniel
53 : * Fixed writing of PC Coverage TXT... they're different from V7 TXT
54 : *
55 : * Revision 1.11 2000/09/26 20:21:04 daniel
56 : * Added AVCCoverPC write
57 : *
58 : * Revision 1.10 2000/09/22 19:45:20 daniel
59 : * Switch to MIT-style license
60 : *
61 : * Revision 1.9 2000/05/29 15:31:30 daniel
62 : * Added Japanese DBCS support
63 : *
64 : * Revision 1.8 2000/01/10 02:55:12 daniel
65 : * Added call to AVCAdjustCaseSensitiveFilename() when creating tables
66 : *
67 : * Revision 1.7 1999/12/24 07:18:34 daniel
68 : * Added PC Arc/Info coverages support
69 : *
70 : * Revision 1.6 1999/08/26 17:26:09 daniel
71 : * Removed printf() messages used in Windows tests
72 : *
73 : * Revision 1.5 1999/08/23 18:18:51 daniel
74 : * Fixed memory leak and some VC++ warnings
75 : *
76 : * Revision 1.4 1999/06/08 22:08:14 daniel
77 : * Modified CreateTable() to overwrite existing arc.dir entries if necessary
78 : *
79 : * Revision 1.3 1999/06/08 18:24:32 daniel
80 : * Fixed some problems with '/' vs '\\' on Windows
81 : *
82 : * Revision 1.2 1999/05/17 16:17:36 daniel
83 : * Added RXP + TXT/TX6/TX7 write support
84 : *
85 : * Revision 1.1 1999/05/11 02:34:46 daniel
86 : * Initial revision
87 : *
88 : **********************************************************************/
89 :
90 : #include "avc.h"
91 :
92 : #include <ctype.h> /* tolower() */
93 :
94 : /*=====================================================================
95 : * Stuff related to writing the binary coverage files
96 : *====================================================================*/
97 :
98 : static void _AVCBinWriteCloseTable(AVCBinFile *psFile);
99 :
100 : static AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
101 : const char *pszCoverName,
102 : AVCTableDef *psSrcTableDef,
103 : AVCCoverType eCoverType,
104 : int nPrecision,
105 : AVCDBCSInfo *psDBCSInfo);
106 :
107 : /**********************************************************************
108 : * AVCBinWriteCreate()
109 : *
110 : * Open a coverage file for writing, write a header if applicable, and
111 : * initialize the handle to be ready to write objects to the file.
112 : *
113 : * pszPath is the coverage (or info directory) path, terminated by
114 : * a '/' or a '\\'
115 : * pszName is the name of the file to create relative to this directory.
116 : *
117 : * Note: For most file types except tables, passing pszPath="" and
118 : * including the coverage path as part of pszName instead would work.
119 : *
120 : * Returns a valid AVCBinFile handle, or NULL if the file could
121 : * not be created.
122 : *
123 : * AVCBinClose() will eventually have to be called to release the
124 : * resources used by the AVCBinFile structure.
125 : **********************************************************************/
126 0 : AVCBinFile *AVCBinWriteCreate(const char *pszPath, const char *pszName,
127 : AVCCoverType eCoverType,
128 : AVCFileType eType, int nPrecision,
129 : AVCDBCSInfo *psDBCSInfo)
130 : {
131 : AVCBinFile *psFile;
132 0 : char *pszFname = NULL, *pszExt;
133 0 : GBool bCreateIndex = FALSE;
134 : int nLen;
135 :
136 : /*-----------------------------------------------------------------
137 : * Make sure precision value is valid (AVC_DEFAULT_PREC is NOT valid)
138 : *----------------------------------------------------------------*/
139 0 : if (nPrecision!=AVC_SINGLE_PREC && nPrecision!=AVC_DOUBLE_PREC)
140 : {
141 0 : CPLError(CE_Failure, CPLE_IllegalArg,
142 : "AVCBinWriteCreate(): Invalid precision parameter "
143 : "(value must be AVC_SINGLE_PREC or AVC_DOUBLE_PREC)");
144 0 : return NULL;
145 : }
146 :
147 : /*-----------------------------------------------------------------
148 : * The case of INFO tables is a bit different...
149 : * tables have to be created through a separate function.
150 : *----------------------------------------------------------------*/
151 0 : if (eType == AVCFileTABLE)
152 : {
153 0 : CPLError(CE_Failure, CPLE_AssertionFailed,
154 : "AVCBinWriteCreate(): TABLEs must be created using "
155 : "AVCBinWriteCreateTable()");
156 0 : return NULL;
157 : }
158 :
159 : /*-----------------------------------------------------------------
160 : * Alloc and init the AVCBinFile struct.
161 : *----------------------------------------------------------------*/
162 0 : psFile = (AVCBinFile*)CPLCalloc(1, sizeof(AVCBinFile));
163 :
164 0 : psFile->eFileType = eType;
165 0 : psFile->nPrecision = nPrecision;
166 :
167 0 : psFile->pszFilename = (char*)CPLMalloc((strlen(pszPath)+strlen(pszName)+1)*
168 : sizeof(char));
169 0 : sprintf(psFile->pszFilename, "%s%s", pszPath, pszName);
170 :
171 0 : psFile->eCoverType = eCoverType;
172 :
173 : /*-----------------------------------------------------------------
174 : * PRJ files are text files... we won't use the AVCRawBin*()
175 : * functions for them... the file will be created and closed
176 : * inside AVCBinWritePrj().
177 : *----------------------------------------------------------------*/
178 0 : if (eType == AVCFilePRJ)
179 : {
180 0 : return psFile;
181 : }
182 :
183 : /*-----------------------------------------------------------------
184 : * All other file types share a very similar creation method.
185 : *----------------------------------------------------------------*/
186 0 : psFile->psRawBinFile = AVCRawBinOpen(psFile->pszFilename, "w",
187 0 : AVC_COVER_BYTE_ORDER(psFile->eCoverType),
188 : psDBCSInfo);
189 :
190 0 : if (psFile->psRawBinFile == NULL)
191 : {
192 : /* Failed to open file... just return NULL since an error message
193 : * has already been issued by AVCRawBinOpen()
194 : */
195 0 : CPLFree(psFile->pszFilename);
196 0 : CPLFree(psFile);
197 0 : return NULL;
198 : }
199 :
200 : /*-----------------------------------------------------------------
201 : * Create an Index file if applicable for current file type.
202 : * Yep, we'll have a problem if filenames come in as uppercase, but
203 : * this should not happen in a normal situation.
204 : * For each type there is 3 possibilities, e.g. "pal", "pal.adf", "ttt.pal"
205 : *----------------------------------------------------------------*/
206 0 : pszFname = CPLStrdup(psFile->pszFilename);
207 0 : nLen = strlen(pszFname);
208 0 : if (eType == AVCFileARC &&
209 0 : ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "arc", 3)) ||
210 0 : (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "arc.adf", 7)) ) )
211 : {
212 0 : strncpy(pszExt, "arx", 3);
213 0 : bCreateIndex = TRUE;
214 : }
215 0 : else if ((eType == AVCFilePAL || eType == AVCFileRPL) &&
216 0 : ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "pal", 3)) ||
217 0 : (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "pal.adf", 7)) ) )
218 : {
219 0 : strncpy(pszExt, "pax", 3);
220 0 : bCreateIndex = TRUE;
221 : }
222 0 : else if (eType == AVCFileCNT &&
223 0 : ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "cnt", 3)) ||
224 0 : (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "cnt.adf", 7)) ) )
225 : {
226 0 : strncpy(pszExt, "cnx", 3);
227 0 : bCreateIndex = TRUE;
228 : }
229 0 : else if ((eType == AVCFileTXT || eType == AVCFileTX6) &&
230 0 : ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "txt", 3)) ||
231 0 : (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "txt.adf", 7)) ) )
232 : {
233 0 : strncpy(pszExt, "txx", 3);
234 0 : bCreateIndex = TRUE;
235 : }
236 :
237 0 : if (bCreateIndex)
238 : {
239 0 : psFile->psIndexFile = AVCRawBinOpen(pszFname, "w",
240 0 : AVC_COVER_BYTE_ORDER(psFile->eCoverType),
241 : psDBCSInfo);
242 : }
243 :
244 0 : CPLFree(pszFname);
245 :
246 : /*-----------------------------------------------------------------
247 : * Generate the appropriate headers for the main file and its index
248 : * if one was created.
249 : *----------------------------------------------------------------*/
250 0 : if (AVCBinWriteHeader(psFile) == -1)
251 : {
252 : /* Failed! Return NULL */
253 0 : AVCBinWriteClose(psFile);
254 0 : psFile = NULL;
255 : }
256 :
257 0 : return psFile;
258 : }
259 :
260 :
261 : /**********************************************************************
262 : * _AVCBinWriteHeader()
263 : *
264 : * (This function is for internal library use... external calls should
265 : * go to AVCBinWriteHeader() instead)
266 : *
267 : * Generate a 100 bytes header using the info in psHeader.
268 : *
269 : * Note: PC Coverage files have an initial 256 bytes header followed by the
270 : * regular 100 bytes header.
271 : *
272 : * This function assumes that the file pointer is currently located at
273 : * the beginning of the file.
274 : *
275 : * Returns 0 on success or -1 on error.
276 : **********************************************************************/
277 0 : int _AVCBinWriteHeader(AVCRawBinFile *psFile, AVCBinHeader *psHeader,
278 : AVCCoverType eCoverType)
279 : {
280 0 : int nStatus = 0;
281 :
282 0 : if (eCoverType == AVCCoverPC)
283 : {
284 : /* PC Coverage header starts with an initial 256 bytes header
285 : */
286 0 : AVCRawBinWriteInt16(psFile, 0x0400); /* Signature??? */
287 0 : AVCRawBinWriteInt32(psFile, psHeader->nLength);
288 :
289 0 : AVCRawBinWriteZeros(psFile, 250);
290 : }
291 :
292 0 : AVCRawBinWriteInt32(psFile, psHeader->nSignature);
293 0 : AVCRawBinWriteInt32(psFile, psHeader->nPrecision);
294 0 : AVCRawBinWriteInt32(psFile, psHeader->nRecordSize);
295 0 : AVCRawBinWriteZeros(psFile, 12);
296 0 : AVCRawBinWriteInt32(psFile, psHeader->nLength);
297 :
298 : /* Pad the rest of the header with zeros
299 : */
300 0 : AVCRawBinWriteZeros(psFile, 72);
301 :
302 0 : if (CPLGetLastErrorNo() != 0)
303 0 : nStatus = -1;
304 :
305 0 : return nStatus;
306 : }
307 :
308 :
309 : /**********************************************************************
310 : * AVCBinWriteHeader()
311 : *
312 : * Write a header to the specified file using the values that apply to
313 : * this file's type. The function simply does nothing if it is called
314 : * for a file type that requires no header.
315 : *
316 : * Returns 0 on success or -1 on error.
317 : **********************************************************************/
318 0 : int AVCBinWriteHeader(AVCBinFile *psFile)
319 : {
320 : AVCBinHeader sHeader;
321 0 : int nStatus=0;
322 0 : GBool bHeader = TRUE;
323 :
324 : /*-----------------------------------------------------------------
325 : * Set the appropriate header information for this file type.
326 : *----------------------------------------------------------------*/
327 0 : sHeader.nPrecision = sHeader.nRecordSize = sHeader.nLength = 0;
328 0 : sHeader.nSignature = 9994;
329 0 : switch(psFile->eFileType)
330 : {
331 : case AVCFileARC:
332 0 : sHeader.nPrecision = (psFile->nPrecision == AVC_DOUBLE_PREC)? -1 : 1;
333 0 : break;
334 : case AVCFilePAL:
335 : case AVCFileRPL:
336 0 : sHeader.nPrecision = (psFile->nPrecision == AVC_DOUBLE_PREC)? -11 : 11;
337 0 : break;
338 : case AVCFileLAB:
339 0 : sHeader.nSignature = 9993;
340 0 : sHeader.nPrecision = (psFile->nPrecision == AVC_DOUBLE_PREC)? -2 : 2;
341 0 : sHeader.nRecordSize = (psFile->nPrecision == AVC_DOUBLE_PREC)? 28 : 16;
342 0 : break;
343 : case AVCFileCNT:
344 0 : sHeader.nPrecision = (psFile->nPrecision == AVC_DOUBLE_PREC)? -14 : 14;
345 0 : break;
346 : case AVCFileTOL:
347 : /* single prec: tol.adf has no header
348 : * double prec: par.adf has a header
349 : */
350 0 : if (psFile->nPrecision == AVC_DOUBLE_PREC)
351 : {
352 0 : sHeader.nSignature = 9993;
353 0 : sHeader.nPrecision = 40;
354 0 : sHeader.nRecordSize = 8;
355 : }
356 : else
357 : {
358 0 : bHeader = FALSE;
359 : }
360 0 : break;
361 : case AVCFileTXT:
362 : case AVCFileTX6:
363 0 : if (psFile->eCoverType == AVCCoverPC)
364 0 : sHeader.nPrecision = 1;
365 : else
366 0 : sHeader.nPrecision = (psFile->nPrecision==AVC_DOUBLE_PREC)? -67:67;
367 0 : break;
368 : default:
369 : /* Other file types don't need a header */
370 0 : bHeader = FALSE;
371 : }
372 :
373 : /*-----------------------------------------------------------------
374 : * Write a header only if applicable.
375 : *----------------------------------------------------------------*/
376 0 : if (bHeader)
377 0 : nStatus = _AVCBinWriteHeader(psFile->psRawBinFile, &sHeader,
378 : psFile->eCoverType);
379 :
380 : /*-----------------------------------------------------------------
381 : * Write a header for the index file... it is identical to the main
382 : * file's header.
383 : *----------------------------------------------------------------*/
384 0 : if (nStatus == 0 && bHeader && psFile->psIndexFile)
385 0 : nStatus = _AVCBinWriteHeader(psFile->psIndexFile, &sHeader,
386 : psFile->eCoverType);
387 :
388 0 : return nStatus;
389 : }
390 :
391 : /**********************************************************************
392 : * AVCBinWriteClose()
393 : *
394 : * Close a coverage file opened for wirting, and release all memory
395 : * (object strcut., buffers, etc.) associated with this file.
396 : **********************************************************************/
397 :
398 0 : void AVCBinWriteClose(AVCBinFile *psFile)
399 : {
400 0 : if (psFile->eFileType == AVCFileTABLE)
401 : {
402 0 : _AVCBinWriteCloseTable(psFile);
403 0 : return;
404 : }
405 :
406 : /*-----------------------------------------------------------------
407 : * Write the file size (nbr of 2 byte words) in the header at
408 : * byte 24 in the 100 byte header (only if applicable)
409 : * (And write the same value at byte 2-5 in the first header of PC Cover)
410 : *----------------------------------------------------------------*/
411 0 : if (psFile->psRawBinFile &&
412 0 : (psFile->eFileType == AVCFileARC ||
413 0 : psFile->eFileType == AVCFilePAL ||
414 0 : psFile->eFileType == AVCFileRPL ||
415 0 : psFile->eFileType == AVCFileLAB ||
416 0 : psFile->eFileType == AVCFileCNT ||
417 0 : psFile->eFileType == AVCFileTXT ||
418 0 : psFile->eFileType == AVCFileTX6 ||
419 0 : (psFile->eFileType == AVCFileTOL &&
420 0 : psFile->nPrecision == AVC_DOUBLE_PREC) ) )
421 : {
422 : GInt32 n32Size;
423 0 : n32Size = psFile->psRawBinFile->nCurPos/2;
424 :
425 0 : if (psFile->eCoverType == AVCCoverPC)
426 : {
427 : /* PC Cover... Pad to multiple of 512 bytes and write 2 headers
428 : * extra bytes at EOF are not included in the size written in
429 : * header.
430 : * The first 256 bytes header is not counted in the file size
431 : * written in both headers
432 : */
433 0 : n32Size -= 128; /* minus 256 bytes */
434 :
435 0 : if (psFile->psRawBinFile->nCurPos%512 != 0)
436 0 : AVCRawBinWriteZeros(psFile->psRawBinFile,
437 0 : 512 - psFile->psRawBinFile->nCurPos%512);
438 :
439 0 : VSIFSeek(psFile->psRawBinFile->fp, 2, SEEK_SET);
440 0 : AVCRawBinWriteInt32(psFile->psRawBinFile, n32Size);
441 :
442 0 : VSIFSeek(psFile->psRawBinFile->fp, 256+24, SEEK_SET);
443 0 : AVCRawBinWriteInt32(psFile->psRawBinFile, n32Size);
444 : }
445 : else
446 : {
447 : /* V7 Cover ... only 1 header */
448 0 : VSIFSeek(psFile->psRawBinFile->fp, 24, SEEK_SET);
449 0 : AVCRawBinWriteInt32(psFile->psRawBinFile, n32Size);
450 : }
451 : }
452 :
453 0 : AVCRawBinClose(psFile->psRawBinFile);
454 0 : psFile->psRawBinFile = NULL;
455 :
456 : /*-----------------------------------------------------------------
457 : * Same for the index file if it exists.
458 : *----------------------------------------------------------------*/
459 0 : if (psFile->psIndexFile)
460 : {
461 : GInt32 n32Size;
462 0 : n32Size = psFile->psIndexFile->nCurPos/2;
463 :
464 0 : if (psFile->eCoverType == AVCCoverPC)
465 : {
466 : /* PC Cover... Pad to multiple of 512 bytes and write 2 headers
467 : * extra bytes at EOF are not included in the size written in
468 : * header
469 : */
470 0 : n32Size -= 128; /* minus 256 bytes */
471 :
472 0 : if (psFile->psIndexFile->nCurPos%512 != 0)
473 0 : AVCRawBinWriteZeros(psFile->psIndexFile,
474 0 : 512 - psFile->psIndexFile->nCurPos%512);
475 :
476 0 : VSIFSeek(psFile->psIndexFile->fp, 2, SEEK_SET);
477 0 : AVCRawBinWriteInt32(psFile->psIndexFile, n32Size);
478 :
479 0 : VSIFSeek(psFile->psIndexFile->fp, 256+24, SEEK_SET);
480 0 : AVCRawBinWriteInt32(psFile->psIndexFile, n32Size);
481 : }
482 : else
483 : {
484 : /* V7 Cover ... only 1 header */
485 0 : VSIFSeek(psFile->psIndexFile->fp, 24, SEEK_SET);
486 0 : AVCRawBinWriteInt32(psFile->psIndexFile, n32Size);
487 : }
488 :
489 0 : AVCRawBinClose(psFile->psIndexFile);
490 0 : psFile->psIndexFile = NULL;
491 : }
492 :
493 0 : CPLFree(psFile->pszFilename);
494 :
495 0 : CPLFree(psFile);
496 : }
497 :
498 :
499 :
500 : /**********************************************************************
501 : * _AVCBinWriteIndexEntry()
502 : *
503 : * (This function is for internal library use... the index entries
504 : * are automatically handled by the AVCBinWrite*() functions)
505 : *
506 : * Write an Index Entry at the current position in the file.
507 : *
508 : * Position is relative to the beginning of the file, including the header.
509 : * Both position and size are specified in number of 2 byte words.
510 : *
511 : * Returns 0 on success or -1 on error.
512 : **********************************************************************/
513 0 : int _AVCBinWriteIndexEntry(AVCRawBinFile *psFile,
514 : int nPosition, int nSize)
515 : {
516 0 : AVCRawBinWriteInt32(psFile, nPosition);
517 0 : AVCRawBinWriteInt32(psFile, nSize);
518 :
519 0 : if (CPLGetLastErrorNo() != 0)
520 0 : return -1;
521 :
522 0 : return 0;
523 : }
524 :
525 : /**********************************************************************
526 : * AVCBinWriteObject()
527 : *
528 : * Write a CNT (Polygon Centroid) structure to the fin object to a
529 : * coverage file.
530 : *
531 : * Simply redirects the call to the right function based on the value
532 : * of psFile->eFileType.
533 : *
534 : * Returns 0 on success or -1 on error.
535 : *
536 : * If a problem happens, then CPLError() will be called by the lower-level
537 : * functions and CPLGetLastErrorNo() can be used to find out what happened.
538 : **********************************************************************/
539 0 : int AVCBinWriteObject(AVCBinFile *psFile, void *psObj)
540 : {
541 0 : int nStatus = 0;
542 0 : switch(psFile->eFileType)
543 : {
544 : case AVCFileARC:
545 0 : nStatus = AVCBinWriteArc(psFile, (AVCArc *)psObj);
546 0 : break;
547 : case AVCFilePAL:
548 : case AVCFileRPL:
549 0 : nStatus = AVCBinWritePal(psFile, (AVCPal *)psObj);
550 0 : break;
551 : case AVCFileCNT:
552 0 : nStatus = AVCBinWriteCnt(psFile, (AVCCnt *)psObj);
553 0 : break;
554 : case AVCFileLAB:
555 0 : nStatus = AVCBinWriteLab(psFile, (AVCLab *)psObj);
556 0 : break;
557 : case AVCFileTOL:
558 0 : nStatus = AVCBinWriteTol(psFile, (AVCTol *)psObj);
559 0 : break;
560 : case AVCFilePRJ:
561 0 : nStatus = AVCBinWritePrj(psFile, (char **)psObj);
562 0 : break;
563 : case AVCFileTXT:
564 : case AVCFileTX6:
565 0 : nStatus = AVCBinWriteTxt(psFile, (AVCTxt *)psObj);
566 0 : break;
567 : case AVCFileRXP:
568 0 : nStatus = AVCBinWriteRxp(psFile, (AVCRxp *)psObj);
569 0 : break;
570 : case AVCFileTABLE:
571 0 : nStatus = AVCBinWriteTableRec(psFile, (AVCField *)psObj);
572 0 : break;
573 : default:
574 0 : CPLError(CE_Failure, CPLE_IllegalArg,
575 : "AVCBinWriteObject(): Unsupported file type!");
576 0 : nStatus = -1;
577 : }
578 :
579 0 : return nStatus;
580 : }
581 :
582 :
583 : /*=====================================================================
584 : * ARC
585 : *====================================================================*/
586 :
587 : /**********************************************************************
588 : * _AVCBinWriteArc()
589 : *
590 : * (This function is for internal library use... external calls should
591 : * go to AVCBinWriteNextArc() instead)
592 : *
593 : * Write an Arc structure to the file.
594 : *
595 : * The contents of the psArc structure is assumed to be valid... this
596 : * function performs no validation on the consistency of what it is
597 : * given as input.
598 : *
599 : * Returns 0 on success or -1 on error.
600 : **********************************************************************/
601 0 : int _AVCBinWriteArc(AVCRawBinFile *psFile, AVCArc *psArc,
602 : int nPrecision, AVCRawBinFile *psIndexFile)
603 : {
604 : int i, nRecSize, nCurPos;
605 :
606 0 : nCurPos = psFile->nCurPos/2; /* Value in 2 byte words */
607 :
608 0 : AVCRawBinWriteInt32(psFile, psArc->nArcId);
609 0 : if (CPLGetLastErrorNo() != 0)
610 0 : return -1;
611 :
612 : /*-----------------------------------------------------------------
613 : * Record size is expressed in 2 byte words, and does not count the
614 : * first 8 bytes of the ARC entry.
615 : *----------------------------------------------------------------*/
616 0 : nRecSize = (6 * 4 + psArc->numVertices*2 *
617 : ((nPrecision == AVC_SINGLE_PREC)? 4 : 8)) / 2;
618 0 : AVCRawBinWriteInt32(psFile, nRecSize);
619 0 : AVCRawBinWriteInt32(psFile, psArc->nUserId);
620 0 : AVCRawBinWriteInt32(psFile, psArc->nFNode);
621 0 : AVCRawBinWriteInt32(psFile, psArc->nTNode);
622 0 : AVCRawBinWriteInt32(psFile, psArc->nLPoly);
623 0 : AVCRawBinWriteInt32(psFile, psArc->nRPoly);
624 0 : AVCRawBinWriteInt32(psFile, psArc->numVertices);
625 :
626 0 : if (nPrecision == AVC_SINGLE_PREC)
627 : {
628 0 : for(i=0; i<psArc->numVertices; i++)
629 : {
630 0 : AVCRawBinWriteFloat(psFile, (float)psArc->pasVertices[i].x);
631 0 : AVCRawBinWriteFloat(psFile, (float)psArc->pasVertices[i].y);
632 : }
633 : }
634 : else
635 : {
636 0 : for(i=0; i<psArc->numVertices; i++)
637 : {
638 0 : AVCRawBinWriteDouble(psFile, psArc->pasVertices[i].x);
639 0 : AVCRawBinWriteDouble(psFile, psArc->pasVertices[i].y);
640 : }
641 :
642 : }
643 :
644 : /*-----------------------------------------------------------------
645 : * Write index entry (arx.adf)
646 : *----------------------------------------------------------------*/
647 0 : if (psIndexFile)
648 : {
649 0 : _AVCBinWriteIndexEntry(psIndexFile, nCurPos, nRecSize);
650 : }
651 :
652 0 : if (CPLGetLastErrorNo() != 0)
653 0 : return -1;
654 :
655 0 : return 0;
656 : }
657 :
658 : /**********************************************************************
659 : * AVCBinWriteArc()
660 : *
661 : * Write the next Arc structure to the file.
662 : *
663 : * The contents of the psArc structure is assumed to be valid... this
664 : * function performs no validation on the consistency of what it is
665 : * given as input.
666 : *
667 : * Returns 0 on success or -1 on error.
668 : *
669 : * If a problem happens, then CPLError() will be called by the lower-level
670 : * functions and CPLGetLastErrorNo() can be used to find out what happened.
671 : **********************************************************************/
672 0 : int AVCBinWriteArc(AVCBinFile *psFile, AVCArc *psArc)
673 : {
674 0 : if (psFile->eFileType != AVCFileARC)
675 0 : return -1;
676 :
677 0 : return _AVCBinWriteArc(psFile->psRawBinFile, psArc,
678 : psFile->nPrecision, psFile->psIndexFile);
679 : }
680 :
681 :
682 : /*=====================================================================
683 : * PAL
684 : *====================================================================*/
685 :
686 : /**********************************************************************
687 : * _AVCBinWritePal()
688 : *
689 : * (This function is for internal library use... external calls should
690 : * go to AVCBinWritePal() instead)
691 : *
692 : * Write a PAL (Polygon Arc List) structure to the file.
693 : *
694 : * The contents of the psPal structure is assumed to be valid... this
695 : * function performs no validation on the consistency of what it is
696 : * given as input.
697 : *
698 : * Returns 0 on success or -1 on error.
699 : **********************************************************************/
700 0 : int _AVCBinWritePal(AVCRawBinFile *psFile, AVCPal *psPal,
701 : int nPrecision, AVCRawBinFile *psIndexFile)
702 : {
703 : int i, nRecSize, nCurPos;
704 :
705 0 : nCurPos = psFile->nCurPos/2; /* Value in 2 byte words */
706 :
707 0 : AVCRawBinWriteInt32(psFile, psPal->nPolyId);
708 0 : if (CPLGetLastErrorNo() != 0)
709 0 : return -1;
710 :
711 : /*-----------------------------------------------------------------
712 : * Record size is expressed in 2 byte words, and does not count the
713 : * first 8 bytes of the PAL entry.
714 : *----------------------------------------------------------------*/
715 0 : nRecSize = ( 4 + psPal->numArcs*3 * 4 +
716 0 : 4 * ((nPrecision == AVC_SINGLE_PREC)? 4 : 8)) / 2;
717 :
718 0 : AVCRawBinWriteInt32(psFile, nRecSize);
719 :
720 0 : if (nPrecision == AVC_SINGLE_PREC)
721 : {
722 0 : AVCRawBinWriteFloat(psFile, (float)psPal->sMin.x);
723 0 : AVCRawBinWriteFloat(psFile, (float)psPal->sMin.y);
724 0 : AVCRawBinWriteFloat(psFile, (float)psPal->sMax.x);
725 0 : AVCRawBinWriteFloat(psFile, (float)psPal->sMax.y);
726 : }
727 : else
728 : {
729 0 : AVCRawBinWriteDouble(psFile, psPal->sMin.x);
730 0 : AVCRawBinWriteDouble(psFile, psPal->sMin.y);
731 0 : AVCRawBinWriteDouble(psFile, psPal->sMax.x);
732 0 : AVCRawBinWriteDouble(psFile, psPal->sMax.y);
733 : }
734 :
735 0 : AVCRawBinWriteInt32(psFile, psPal->numArcs);
736 :
737 0 : for(i=0; i<psPal->numArcs; i++)
738 : {
739 0 : AVCRawBinWriteInt32(psFile, psPal->pasArcs[i].nArcId);
740 0 : AVCRawBinWriteInt32(psFile, psPal->pasArcs[i].nFNode);
741 0 : AVCRawBinWriteInt32(psFile, psPal->pasArcs[i].nAdjPoly);
742 : }
743 :
744 : /*-----------------------------------------------------------------
745 : * Write index entry (pax.adf)
746 : *----------------------------------------------------------------*/
747 0 : if (psIndexFile)
748 : {
749 0 : _AVCBinWriteIndexEntry(psIndexFile, nCurPos, nRecSize);
750 : }
751 :
752 0 : if (CPLGetLastErrorNo() != 0)
753 0 : return -1;
754 :
755 0 : return 0;
756 : }
757 :
758 : /**********************************************************************
759 : * AVCBinWritePal()
760 : *
761 : * Write a PAL (Polygon Arc List) structure to the file.
762 : *
763 : * The contents of the psPal structure is assumed to be valid... this
764 : * function performs no validation on the consistency of what it is
765 : * given as input.
766 : *
767 : * Returns 0 on success or -1 on error.
768 : *
769 : * If a problem happens, then CPLError() will be called by the lower-level
770 : * functions and CPLGetLastErrorNo() can be used to find out what happened.
771 : **********************************************************************/
772 0 : int AVCBinWritePal(AVCBinFile *psFile, AVCPal *psPal)
773 : {
774 0 : if (psFile->eFileType != AVCFilePAL && psFile->eFileType != AVCFileRPL)
775 0 : return -1;
776 :
777 0 : return _AVCBinWritePal(psFile->psRawBinFile, psPal,
778 : psFile->nPrecision, psFile->psIndexFile);
779 : }
780 :
781 : /*=====================================================================
782 : * CNT
783 : *====================================================================*/
784 :
785 : /**********************************************************************
786 : * _AVCBinWriteCnt()
787 : *
788 : * (This function is for internal library use... external calls should
789 : * go to AVCBinWriteCnt() instead)
790 : *
791 : * Write a CNT (Polygon Centroid) structure to the file.
792 : *
793 : * Returns 0 on success or -1 on error.
794 : **********************************************************************/
795 0 : int _AVCBinWriteCnt(AVCRawBinFile *psFile, AVCCnt *psCnt,
796 : int nPrecision, AVCRawBinFile *psIndexFile)
797 : {
798 : int i, nRecSize, nCurPos;
799 :
800 0 : nCurPos = psFile->nCurPos/2; /* Value in 2 byte words */
801 :
802 0 : AVCRawBinWriteInt32(psFile, psCnt->nPolyId);
803 0 : if (CPLGetLastErrorNo() != 0)
804 0 : return -1;
805 :
806 : /*-----------------------------------------------------------------
807 : * Record size is expressed in 2 byte words, and does not count the
808 : * first 8 bytes of the CNT entry.
809 : *----------------------------------------------------------------*/
810 0 : nRecSize = ( 4 + psCnt->numLabels * 4 +
811 0 : 2 * ((nPrecision == AVC_SINGLE_PREC)? 4 : 8)) / 2;
812 :
813 0 : AVCRawBinWriteInt32(psFile, nRecSize);
814 :
815 0 : if (nPrecision == AVC_SINGLE_PREC)
816 : {
817 0 : AVCRawBinWriteFloat(psFile, (float)psCnt->sCoord.x);
818 0 : AVCRawBinWriteFloat(psFile, (float)psCnt->sCoord.y);
819 : }
820 : else
821 : {
822 0 : AVCRawBinWriteDouble(psFile, psCnt->sCoord.x);
823 0 : AVCRawBinWriteDouble(psFile, psCnt->sCoord.y);
824 : }
825 :
826 0 : AVCRawBinWriteInt32(psFile, psCnt->numLabels);
827 :
828 0 : for(i=0; i<psCnt->numLabels; i++)
829 : {
830 0 : AVCRawBinWriteInt32(psFile, psCnt->panLabelIds[i]);
831 : }
832 :
833 : /*-----------------------------------------------------------------
834 : * Write index entry (cnx.adf)
835 : *----------------------------------------------------------------*/
836 0 : if (psIndexFile)
837 : {
838 0 : _AVCBinWriteIndexEntry(psIndexFile, nCurPos, nRecSize);
839 : }
840 :
841 0 : if (CPLGetLastErrorNo() != 0)
842 0 : return -1;
843 :
844 0 : return 0;
845 : }
846 :
847 : /**********************************************************************
848 : * AVCBinWriteCnt()
849 : *
850 : * Write a CNT (Polygon Centroid) structure to the file.
851 : *
852 : * The contents of the psCnt structure is assumed to be valid... this
853 : * function performs no validation on the consistency of what it is
854 : * given as input.
855 : *
856 : * Returns 0 on success or -1 on error.
857 : *
858 : * If a problem happens, then CPLError() will be called by the lower-level
859 : * functions and CPLGetLastErrorNo() can be used to find out what happened.
860 : **********************************************************************/
861 0 : int AVCBinWriteCnt(AVCBinFile *psFile, AVCCnt *psCnt)
862 : {
863 0 : if (psFile->eFileType != AVCFileCNT)
864 0 : return -1;
865 :
866 0 : return _AVCBinWriteCnt(psFile->psRawBinFile, psCnt,
867 : psFile->nPrecision, psFile->psIndexFile);
868 : }
869 :
870 : /*=====================================================================
871 : * LAB
872 : *====================================================================*/
873 :
874 : /**********************************************************************
875 : * _AVCBinWriteLab()
876 : *
877 : * (This function is for internal library use... external calls should
878 : * go to AVCBinWriteLab() instead)
879 : *
880 : * Write a LAB (Centroid Label) structure to the file.
881 : *
882 : * The contents of the psLab structure is assumed to be valid... this
883 : * function performs no validation on the consistency of what it is
884 : * given as input.
885 : *
886 : * Returns 0 on success or -1 on error.
887 : **********************************************************************/
888 0 : int _AVCBinWriteLab(AVCRawBinFile *psFile, AVCLab *psLab,
889 : int nPrecision)
890 : {
891 :
892 0 : AVCRawBinWriteInt32(psFile, psLab->nValue);
893 0 : if (CPLGetLastErrorNo() != 0)
894 0 : return -1;
895 :
896 0 : AVCRawBinWriteInt32(psFile, psLab->nPolyId);
897 :
898 0 : if (nPrecision == AVC_SINGLE_PREC)
899 : {
900 0 : AVCRawBinWriteFloat(psFile, (float)psLab->sCoord1.x);
901 0 : AVCRawBinWriteFloat(psFile, (float)psLab->sCoord1.y);
902 0 : AVCRawBinWriteFloat(psFile, (float)psLab->sCoord2.x);
903 0 : AVCRawBinWriteFloat(psFile, (float)psLab->sCoord2.y);
904 0 : AVCRawBinWriteFloat(psFile, (float)psLab->sCoord3.x);
905 0 : AVCRawBinWriteFloat(psFile, (float)psLab->sCoord3.y);
906 : }
907 : else
908 : {
909 0 : AVCRawBinWriteDouble(psFile, psLab->sCoord1.x);
910 0 : AVCRawBinWriteDouble(psFile, psLab->sCoord1.y);
911 0 : AVCRawBinWriteDouble(psFile, psLab->sCoord2.x);
912 0 : AVCRawBinWriteDouble(psFile, psLab->sCoord2.y);
913 0 : AVCRawBinWriteDouble(psFile, psLab->sCoord3.x);
914 0 : AVCRawBinWriteDouble(psFile, psLab->sCoord3.y);
915 : }
916 :
917 0 : if (CPLGetLastErrorNo() != 0)
918 0 : return -1;
919 :
920 0 : return 0;
921 : }
922 :
923 :
924 : /**********************************************************************
925 : * AVCBinWriteLab()
926 : *
927 : * Write a LAB (Centroid Label) structure to the file.
928 : *
929 : * The contents of the psLab structure is assumed to be valid... this
930 : * function performs no validation on the consistency of what it is
931 : * given as input.
932 : *
933 : * Returns 0 on success or -1 on error.
934 : *
935 : * If a problem happens, then CPLError() will be called by the lower-level
936 : * functions and CPLGetLastErrorNo() can be used to find out what happened.
937 : **********************************************************************/
938 0 : int AVCBinWriteLab(AVCBinFile *psFile, AVCLab *psLab)
939 : {
940 0 : if (psFile->eFileType != AVCFileLAB)
941 0 : return -1;
942 :
943 0 : return _AVCBinWriteLab(psFile->psRawBinFile, psLab,
944 : psFile->nPrecision);
945 : }
946 :
947 : /*=====================================================================
948 : * TOL
949 : *====================================================================*/
950 :
951 : /**********************************************************************
952 : * _AVCBinWriteTol()
953 : *
954 : * (This function is for internal library use... external calls should
955 : * go to AVCBinWriteTol() instead)
956 : *
957 : * Write a TOL (tolerance) structure to the file.
958 : *
959 : * The contents of the psTol structure is assumed to be valid... this
960 : * function performs no validation on the consistency of what it is
961 : * given as input.
962 : *
963 : * Returns 0 on success or -1 on error.
964 : **********************************************************************/
965 0 : int _AVCBinWriteTol(AVCRawBinFile *psFile, AVCTol *psTol,
966 : int nPrecision)
967 : {
968 :
969 0 : AVCRawBinWriteInt32(psFile, psTol->nIndex);
970 0 : if (CPLGetLastErrorNo() != 0)
971 0 : return -1;
972 :
973 0 : AVCRawBinWriteInt32(psFile, psTol->nFlag);
974 :
975 0 : if (nPrecision == AVC_SINGLE_PREC)
976 : {
977 0 : AVCRawBinWriteFloat(psFile, (float)psTol->dValue);
978 : }
979 : else
980 : {
981 0 : AVCRawBinWriteDouble(psFile, psTol->dValue);
982 : }
983 :
984 0 : if (CPLGetLastErrorNo() != 0)
985 0 : return -1;
986 :
987 0 : return 0;
988 : }
989 :
990 : /**********************************************************************
991 : * AVCBinWriteTol()
992 : *
993 : * Write a TOL (tolerance) structure to the file.
994 : *
995 : * The contents of the psTol structure is assumed to be valid... this
996 : * function performs no validation on the consistency of what it is
997 : * given as input.
998 : *
999 : * Returns 0 on success or -1 on error.
1000 : *
1001 : * If a problem happens, then CPLError() will be called by the lower-level
1002 : * functions and CPLGetLastErrorNo() can be used to find out what happened.
1003 : **********************************************************************/
1004 0 : int AVCBinWriteTol(AVCBinFile *psFile, AVCTol *psTol)
1005 : {
1006 0 : if (psFile->eFileType != AVCFileTOL)
1007 0 : return -1;
1008 :
1009 0 : return _AVCBinWriteTol(psFile->psRawBinFile, psTol,
1010 : psFile->nPrecision);
1011 : }
1012 :
1013 : /*=====================================================================
1014 : * PRJ
1015 : *====================================================================*/
1016 :
1017 : /**********************************************************************
1018 : * AVCBinWritePrj()
1019 : *
1020 : * Write a PRJ (Projection info) to the file.
1021 : *
1022 : * Since a PRJ file is a simple text file and there is only ONE projection
1023 : * info per prj.adf file, this function behaves differently from the
1024 : * other ones... all the job is done here, including creating and closing
1025 : * the output file.
1026 : *
1027 : * The contents of the papszPrj is assumed to be valid... this
1028 : * function performs no validation on the consistency of what it is
1029 : * given as input.
1030 : *
1031 : * Returns 0 on success or -1 on error.
1032 : *
1033 : * If a problem happens, then CPLError() will be called by the lower-level
1034 : * functions and CPLGetLastErrorNo() can be used to find out what happened.
1035 : **********************************************************************/
1036 0 : int AVCBinWritePrj(AVCBinFile *psFile, char **papszPrj)
1037 : {
1038 0 : if (psFile->eFileType != AVCFilePRJ)
1039 0 : return -1;
1040 :
1041 0 : CSLSave(papszPrj, psFile->pszFilename);
1042 :
1043 0 : if (CPLGetLastErrorNo() != 0)
1044 0 : return -1;
1045 :
1046 0 : return 0;
1047 : }
1048 :
1049 :
1050 : /*=====================================================================
1051 : * TXT/TX6/TX7
1052 : *====================================================================*/
1053 :
1054 : /**********************************************************************
1055 : * _AVCBinWriteTxt()
1056 : *
1057 : * (This function is for internal library use... external calls should
1058 : * go to AVCBinWriteTxt() instead)
1059 : *
1060 : * Write a TXT/TX6/TX7 (Annotation) structure to the file.
1061 : *
1062 : * The contents of the psTxt structure is assumed to be valid... this
1063 : * function performs no validation on the consistency of what it is
1064 : * given as input.
1065 : *
1066 : * Returns 0 on success or -1 on error.
1067 : **********************************************************************/
1068 0 : int _AVCBinWriteTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
1069 : int nPrecision, AVCRawBinFile *psIndexFile)
1070 : {
1071 : int i, nRecSize, nCurPos, nStrLen, numVertices;
1072 :
1073 0 : nCurPos = psFile->nCurPos/2; /* Value in 2 byte words */
1074 :
1075 0 : AVCRawBinWriteInt32(psFile, psTxt->nTxtId);
1076 0 : if (CPLGetLastErrorNo() != 0)
1077 0 : return -1;
1078 :
1079 : /*-----------------------------------------------------------------
1080 : * Record size is expressed in 2 byte words, and does not count the
1081 : * first 8 bytes of the TXT entry.
1082 : *----------------------------------------------------------------*/
1083 : /* String uses a multiple of 4 bytes of storage */
1084 0 : if (psTxt->pszText)
1085 0 : nStrLen = ((strlen((char*)psTxt->pszText) + 3)/4)*4;
1086 : else
1087 0 : nStrLen = 0;
1088 :
1089 0 : numVertices = ABS(psTxt->numVerticesLine) + ABS(psTxt->numVerticesArrow);
1090 0 : nRecSize = (112 + 8 + nStrLen +
1091 0 : (numVertices*2+3)* ((nPrecision == AVC_SINGLE_PREC)?4:8)) / 2;
1092 :
1093 0 : AVCRawBinWriteInt32(psFile, nRecSize);
1094 :
1095 0 : AVCRawBinWriteInt32(psFile, psTxt->nUserId );
1096 0 : AVCRawBinWriteInt32(psFile, psTxt->nLevel );
1097 0 : AVCRawBinWriteFloat(psFile, psTxt->f_1e2 );
1098 0 : AVCRawBinWriteInt32(psFile, psTxt->nSymbol );
1099 0 : AVCRawBinWriteInt32(psFile, psTxt->numVerticesLine );
1100 0 : AVCRawBinWriteInt32(psFile, psTxt->n28 );
1101 0 : AVCRawBinWriteInt32(psFile, psTxt->numChars );
1102 0 : AVCRawBinWriteInt32(psFile, psTxt->numVerticesArrow );
1103 :
1104 0 : for(i=0; i<20; i++)
1105 : {
1106 0 : AVCRawBinWriteInt16(psFile, psTxt->anJust1[i] );
1107 : }
1108 0 : for(i=0; i<20; i++)
1109 : {
1110 0 : AVCRawBinWriteInt16(psFile, psTxt->anJust2[i] );
1111 : }
1112 :
1113 0 : if (nPrecision == AVC_SINGLE_PREC)
1114 : {
1115 0 : AVCRawBinWriteFloat(psFile, (float)psTxt->dHeight);
1116 0 : AVCRawBinWriteFloat(psFile, (float)psTxt->dV2);
1117 0 : AVCRawBinWriteFloat(psFile, (float)psTxt->dV3);
1118 : }
1119 : else
1120 : {
1121 0 : AVCRawBinWriteDouble(psFile, psTxt->dHeight);
1122 0 : AVCRawBinWriteDouble(psFile, psTxt->dV2);
1123 0 : AVCRawBinWriteDouble(psFile, psTxt->dV3);
1124 : }
1125 :
1126 0 : if (nStrLen > 0)
1127 0 : AVCRawBinWritePaddedString(psFile, nStrLen, psTxt->pszText);
1128 :
1129 0 : if (nPrecision == AVC_SINGLE_PREC)
1130 : {
1131 0 : for(i=0; i<numVertices; i++)
1132 : {
1133 0 : AVCRawBinWriteFloat(psFile, (float)psTxt->pasVertices[i].x);
1134 0 : AVCRawBinWriteFloat(psFile, (float)psTxt->pasVertices[i].y);
1135 : }
1136 : }
1137 : else
1138 : {
1139 0 : for(i=0; i<numVertices; i++)
1140 : {
1141 0 : AVCRawBinWriteDouble(psFile, psTxt->pasVertices[i].x);
1142 0 : AVCRawBinWriteDouble(psFile, psTxt->pasVertices[i].y);
1143 : }
1144 : }
1145 :
1146 0 : AVCRawBinWriteZeros(psFile, 8);
1147 :
1148 : /*-----------------------------------------------------------------
1149 : * Write index entry (cnx.adf)
1150 : *----------------------------------------------------------------*/
1151 0 : if (psIndexFile)
1152 : {
1153 0 : _AVCBinWriteIndexEntry(psIndexFile, nCurPos, nRecSize);
1154 : }
1155 :
1156 0 : if (CPLGetLastErrorNo() != 0)
1157 0 : return -1;
1158 :
1159 0 : return 0;
1160 : }
1161 :
1162 : /**********************************************************************
1163 : * _AVCBinWritePCCoverageTxt()
1164 : *
1165 : * (This function is for internal library use... external calls should
1166 : * go to AVCBinWriteTxt() instead)
1167 : *
1168 : * Write a TXT (Annotation) structure to a AVCCoverPC file.
1169 : *
1170 : * The contents of the psTxt structure is assumed to be valid... this
1171 : * function performs no validation on the consistency of what it is
1172 : * given as input.
1173 : *
1174 : * This function assumes that PC Coverages are always single precision.
1175 : *
1176 : * Returns 0 on success or -1 on error.
1177 : **********************************************************************/
1178 0 : int _AVCBinWritePCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
1179 : int nPrecision, AVCRawBinFile *psIndexFile)
1180 : {
1181 : int i, nRecSize, nCurPos, nStrLen, numVertices;
1182 :
1183 0 : CPLAssert(nPrecision == AVC_SINGLE_PREC);
1184 :
1185 0 : nCurPos = psFile->nCurPos/2; /* Value in 2 byte words */
1186 :
1187 0 : AVCRawBinWriteInt32(psFile, psTxt->nTxtId);
1188 0 : if (CPLGetLastErrorNo() != 0)
1189 0 : return -1;
1190 :
1191 : /*-----------------------------------------------------------------
1192 : * Record size is expressed in 2 byte words, and does not count the
1193 : * first 8 bytes of the TXT entry.
1194 : *----------------------------------------------------------------*/
1195 : /* String uses a multiple of 4 bytes of storage,
1196 : * And if text is already a multiple of 4 bytes then we include 4 extra
1197 : * spaces anyways (was probably a bug in the software!).
1198 : */
1199 0 : if (psTxt->pszText)
1200 0 : nStrLen = ((strlen((char*)psTxt->pszText) + 4)/4)*4;
1201 : else
1202 0 : nStrLen = 4;
1203 :
1204 0 : nRecSize = (92 - 8 + nStrLen) / 2;
1205 :
1206 0 : AVCRawBinWriteInt32(psFile, nRecSize);
1207 0 : AVCRawBinWriteInt32(psFile, psTxt->nLevel );
1208 :
1209 : /*-----------------------------------------------------------------
1210 : * Number of vertices to write:
1211 : * Note that because of the way V7 binary TXT files work, the rest of the
1212 : * lib expects to receive duplicate coords for the first vertex, so
1213 : * we will also receive an additional vertex for that but we won't write
1214 : * it. We also ignore the arrow vertices if there is any.
1215 : *----------------------------------------------------------------*/
1216 0 : numVertices = ABS(psTxt->numVerticesLine) -1;
1217 0 : numVertices = MIN(4, numVertices); /* Maximum of 4 points */
1218 :
1219 0 : AVCRawBinWriteInt32(psFile, numVertices );
1220 :
1221 0 : for(i=0; i<numVertices; i++)
1222 : {
1223 0 : AVCRawBinWriteFloat(psFile, (float)psTxt->pasVertices[i+1].x);
1224 0 : AVCRawBinWriteFloat(psFile, (float)psTxt->pasVertices[i+1].y);
1225 : }
1226 :
1227 0 : AVCRawBinWriteZeros(psFile, (4-numVertices)*4*2 + 28);
1228 :
1229 0 : AVCRawBinWriteFloat(psFile, (float)psTxt->dHeight);
1230 0 : AVCRawBinWriteFloat(psFile, psTxt->f_1e2 );
1231 0 : AVCRawBinWriteInt32(psFile, psTxt->nSymbol );
1232 0 : AVCRawBinWriteInt32(psFile, psTxt->numChars );
1233 :
1234 0 : if (nStrLen > 0)
1235 0 : AVCRawBinWritePaddedString(psFile, nStrLen, psTxt->pszText);
1236 :
1237 : /*-----------------------------------------------------------------
1238 : * Write index entry (cnx.adf)
1239 : *----------------------------------------------------------------*/
1240 0 : if (psIndexFile)
1241 : {
1242 0 : _AVCBinWriteIndexEntry(psIndexFile, nCurPos, nRecSize);
1243 : }
1244 :
1245 0 : if (CPLGetLastErrorNo() != 0)
1246 0 : return -1;
1247 :
1248 0 : return 0;
1249 : }
1250 :
1251 :
1252 : /**********************************************************************
1253 : * AVCBinWriteTxt()
1254 : *
1255 : * Write a TXT/TX6/TX7 (Annotation) structure to the file.
1256 : *
1257 : * The contents of the psTxt structure is assumed to be valid... this
1258 : * function performs no validation on the consistency of what it is
1259 : * given as input.
1260 : *
1261 : * Returns 0 on success or -1 on error.
1262 : *
1263 : * If a problem happens, then CPLError() will be called by the lower-level
1264 : * functions and CPLGetLastErrorNo() can be used to find out what happened.
1265 : **********************************************************************/
1266 0 : int AVCBinWriteTxt(AVCBinFile *psFile, AVCTxt *psTxt)
1267 : {
1268 0 : if (psFile->eFileType != AVCFileTXT && psFile->eFileType != AVCFileTX6)
1269 0 : return -1;
1270 :
1271 : /* AVCCoverPC and AVCCoverWeird have a different TXT format than AVCCoverV7
1272 : */
1273 0 : if (psFile->eCoverType == AVCCoverPC ||
1274 0 : psFile->eCoverType == AVCCoverWeird)
1275 : {
1276 0 : return _AVCBinWritePCCoverageTxt(psFile->psRawBinFile, psTxt,
1277 : psFile->nPrecision,
1278 : psFile->psIndexFile);
1279 : }
1280 : else
1281 : {
1282 0 : return _AVCBinWriteTxt(psFile->psRawBinFile, psTxt,
1283 : psFile->nPrecision, psFile->psIndexFile);
1284 : }
1285 : }
1286 :
1287 : /*=====================================================================
1288 : * RXP
1289 : *====================================================================*/
1290 :
1291 : /**********************************************************************
1292 : * _AVCBinWriteRxp()
1293 : *
1294 : * (This function is for internal library use... external calls should
1295 : * go to AVCBinWriteRxp() instead)
1296 : *
1297 : * Write a RXP (Region something...) structure to the file.
1298 : *
1299 : * The contents of the psRxp structure is assumed to be valid... this
1300 : * function performs no validation on the consistency of what it is
1301 : * given as input.
1302 : *
1303 : * Returns 0 on success or -1 on error.
1304 : **********************************************************************/
1305 0 : int _AVCBinWriteRxp(AVCRawBinFile *psFile, AVCRxp *psRxp,
1306 : int nPrecision)
1307 : {
1308 :
1309 0 : AVCRawBinWriteInt32(psFile, psRxp->n1);
1310 0 : if (CPLGetLastErrorNo() != 0)
1311 0 : return -1;
1312 :
1313 0 : AVCRawBinWriteInt32(psFile, psRxp->n2);
1314 :
1315 0 : if (CPLGetLastErrorNo() != 0)
1316 0 : return -1;
1317 :
1318 0 : return 0;
1319 : }
1320 :
1321 : /**********************************************************************
1322 : * AVCBinWriteRxp()
1323 : *
1324 : * Write a RXP (Region something...) structure to the file.
1325 : *
1326 : * The contents of the psRxp structure is assumed to be valid... this
1327 : * function performs no validation on the consistency of what it is
1328 : * given as input.
1329 : *
1330 : * Returns 0 on success or -1 on error.
1331 : *
1332 : * If a problem happens, then CPLError() will be called by the lower-level
1333 : * functions and CPLGetLastErrorNo() can be used to find out what happened.
1334 : **********************************************************************/
1335 0 : int AVCBinWriteRxp(AVCBinFile *psFile, AVCRxp *psRxp)
1336 : {
1337 0 : if (psFile->eFileType != AVCFileRXP)
1338 0 : return -1;
1339 :
1340 0 : return _AVCBinWriteRxp(psFile->psRawBinFile, psRxp,
1341 : psFile->nPrecision);
1342 : }
1343 :
1344 :
1345 : /*=====================================================================
1346 : * TABLES
1347 : *====================================================================*/
1348 :
1349 : /**********************************************************************
1350 : * _AVCBinWriteArcDir()
1351 : *
1352 : * (This function is for internal library use... external calls should
1353 : * go to AVCBinWriteCreateTable() instead)
1354 : *
1355 : * Write an ARC.DIR entry at the current position in file.
1356 : *
1357 : * The contents of the psTableDef structure is assumed to be valid... this
1358 : * function performs no validation on the consistency of what it is
1359 : * given as input.
1360 : *
1361 : * Returns 0 on success or -1 on error.
1362 : **********************************************************************/
1363 0 : int _AVCBinWriteArcDir(AVCRawBinFile *psFile, AVCTableDef *psTableDef)
1364 : {
1365 : /* STRING values MUST be padded with spaces.
1366 : */
1367 0 : AVCRawBinWritePaddedString(psFile, 32, (GByte*)psTableDef->szTableName);
1368 0 : if (CPLGetLastErrorNo() != 0)
1369 0 : return -1;
1370 :
1371 0 : AVCRawBinWritePaddedString(psFile, 8, (GByte*)psTableDef->szInfoFile);
1372 :
1373 0 : AVCRawBinWriteInt16(psFile, psTableDef->numFields);
1374 :
1375 : /* Record size must be a multiple of 2 bytes */
1376 0 : AVCRawBinWriteInt16(psFile, (GInt16)(((psTableDef->nRecSize+1)/2)*2));
1377 :
1378 : /* ??? Unknown values ??? */
1379 0 : AVCRawBinWritePaddedString(psFile, 16, (GByte*)" ");
1380 0 : AVCRawBinWriteInt16(psFile, 132);
1381 0 : AVCRawBinWriteInt16(psFile, 0);
1382 :
1383 0 : AVCRawBinWriteInt32(psFile, psTableDef->numRecords);
1384 :
1385 0 : AVCRawBinWriteZeros(psFile, 10);
1386 :
1387 0 : AVCRawBinWritePaddedString(psFile, 2, (GByte*)psTableDef->szExternal);
1388 :
1389 0 : AVCRawBinWriteZeros(psFile, 238);
1390 0 : AVCRawBinWritePaddedString(psFile, 8, (GByte*)" ");
1391 0 : AVCRawBinWriteZeros(psFile, 54);
1392 :
1393 0 : if (CPLGetLastErrorNo() != 0)
1394 0 : return -1;
1395 :
1396 0 : return 0;
1397 : }
1398 :
1399 :
1400 : /**********************************************************************
1401 : * _AVCBinWriteArcNit()
1402 : *
1403 : * (This function is for internal library use... external calls should
1404 : * go to AVCBinWriteCreateTable() instead)
1405 : *
1406 : * Write an ARC####.NIT entry at the current position in file.
1407 : *
1408 : * The contents of the psTableDef structure is assumed to be valid... this
1409 : * function performs no validation on the consistency of what it is
1410 : * given as input.
1411 : *
1412 : * Returns 0 on success or -1 on error.
1413 : **********************************************************************/
1414 0 : int _AVCBinWriteArcNit(AVCRawBinFile *psFile, AVCFieldInfo *psField)
1415 : {
1416 : /* STRING values MUST be padded with spaces.
1417 : */
1418 0 : AVCRawBinWritePaddedString(psFile, 16, (GByte*)psField->szName);
1419 0 : if (CPLGetLastErrorNo() != 0)
1420 0 : return -1;
1421 :
1422 0 : AVCRawBinWriteInt16(psFile, psField->nSize);
1423 0 : AVCRawBinWriteInt16(psFile, psField->v2);
1424 0 : AVCRawBinWriteInt16(psFile, psField->nOffset);
1425 0 : AVCRawBinWriteInt16(psFile, psField->v4);
1426 0 : AVCRawBinWriteInt16(psFile, psField->v5);
1427 0 : AVCRawBinWriteInt16(psFile, psField->nFmtWidth);
1428 0 : AVCRawBinWriteInt16(psFile, psField->nFmtPrec);
1429 0 : AVCRawBinWriteInt16(psFile, psField->nType1);
1430 0 : AVCRawBinWriteInt16(psFile, psField->nType2);
1431 0 : AVCRawBinWriteInt16(psFile, psField->v10);
1432 0 : AVCRawBinWriteInt16(psFile, psField->v11);
1433 0 : AVCRawBinWriteInt16(psFile, psField->v12);
1434 0 : AVCRawBinWriteInt16(psFile, psField->v13);
1435 :
1436 0 : AVCRawBinWritePaddedString(psFile, 16, (GByte*)psField->szAltName);
1437 :
1438 0 : AVCRawBinWriteZeros(psFile, 56);
1439 :
1440 0 : AVCRawBinWriteInt16(psFile, psField->nIndex);
1441 :
1442 0 : AVCRawBinWriteZeros(psFile, 28);
1443 :
1444 0 : if (CPLGetLastErrorNo() != 0)
1445 0 : return -1;
1446 :
1447 0 : return 0;
1448 : }
1449 :
1450 :
1451 : /**********************************************************************
1452 : * _AVCBinWriteCreateArcDirEntry()
1453 : *
1454 : * Add an entry in the ARC.DIR for the table defined in psSrcTableDef.
1455 : *
1456 : * If an entry with the same table name already exists then this entry
1457 : * will be reused and overwritten.
1458 : *
1459 : * Note: there could be a problem if 2 processes try to add an entry
1460 : * at the exact same time... does Arc/Info do any locking on that file???
1461 : *
1462 : * Returns an integer value corresponding to the new table index (ARC####)
1463 : * or -1 if something failed.
1464 : **********************************************************************/
1465 :
1466 : /* Prototype for _AVCBinReadNextArcDir() from avc_bin.c
1467 : */
1468 : int _AVCBinReadNextArcDir(AVCRawBinFile *psFile, AVCTableDef *psArcDir);
1469 :
1470 0 : int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
1471 : AVCTableDef *psTableDef,
1472 : AVCDBCSInfo *psDBCSInfo)
1473 : {
1474 0 : int iEntry, numDirEntries=0, nTableIndex = 0;
1475 : VSIStatBuf sStatBuf;
1476 : AVCRawBinFile *hRawBinFile;
1477 : GBool bFound;
1478 : AVCTableDef sEntry;
1479 :
1480 : /*-----------------------------------------------------------------
1481 : * Open and Scan the ARC.DIR to establish the table index (ARC####)
1482 : *----------------------------------------------------------------*/
1483 : #ifdef _WIN32
1484 : /*-----------------------------------------------------------------
1485 : * Note, DM, 20010507 - We used to use VSIFStat() to establish the
1486 : * size of arc.dir, but when working on a WinNT4 networked drive, the
1487 : * stat() information was not always right, and we sometimes ended
1488 : * up overwriting arc.dir entries. The solution: open and scan arc.dir
1489 : * until EOF to establish its size.
1490 : * That trick also seems to fix another network buffer problem: when
1491 : * writing a coverage in a new empty dir (with no info dir yet), we
1492 : * would get an error in fwrite() while writing the 3rd arc.dir
1493 : * entry of the coverage. That second problem could also have been
1494 : * fixed by forcing a VSIFSeek() before the first fwrite()... we've
1495 : * added it below.
1496 : *----------------------------------------------------------------*/
1497 : FILE *fp;
1498 : if ((fp = VSIFOpen(pszArcDirFile, "r")) != NULL)
1499 : {
1500 : char buf[380];
1501 : while (!VSIFEof(fp))
1502 : {
1503 : if (VSIFRead(buf, 380, 1, fp) == 1)
1504 : numDirEntries++;
1505 : }
1506 : VSIFClose(fp);
1507 : hRawBinFile = AVCRawBinOpen(pszArcDirFile, "r+",
1508 : AVC_COVER_BYTE_ORDER(AVCCoverV7),
1509 : psDBCSInfo);
1510 : }
1511 : else
1512 : #endif
1513 : /* On Unix we can still use fstat() */
1514 0 : if ( VSIStat(pszArcDirFile, &sStatBuf) != -1 )
1515 : {
1516 0 : numDirEntries = sStatBuf.st_size/380;
1517 0 : hRawBinFile = AVCRawBinOpen(pszArcDirFile, "r+",
1518 : AVC_COVER_BYTE_ORDER(AVCCoverV7),
1519 : psDBCSInfo);
1520 : }
1521 : else
1522 : {
1523 0 : numDirEntries = 0;
1524 0 : hRawBinFile = AVCRawBinOpen(pszArcDirFile, "w",
1525 : AVC_COVER_BYTE_ORDER(AVCCoverV7),
1526 : psDBCSInfo);
1527 : }
1528 :
1529 0 : if (hRawBinFile == NULL)
1530 : {
1531 : /* Failed to open file... just return -1 since an error message
1532 : * has already been issued by AVCRawBinOpen()
1533 : */
1534 0 : return -1;
1535 : }
1536 :
1537 : /* Init nTableIndex at -1 so that first table created should have
1538 : * index 0
1539 : */
1540 0 : nTableIndex = -1;
1541 0 : iEntry = 0;
1542 0 : bFound = FALSE;
1543 0 : while(!bFound && iEntry<numDirEntries &&
1544 0 : _AVCBinReadNextArcDir(hRawBinFile, &sEntry) == 0)
1545 : {
1546 0 : nTableIndex = atoi(sEntry.szInfoFile+3);
1547 0 : if (EQUALN(psTableDef->szTableName, sEntry.szTableName,
1548 : strlen(psTableDef->szTableName)))
1549 : {
1550 0 : bFound = TRUE;
1551 0 : break;
1552 : }
1553 0 : iEntry++;
1554 : }
1555 :
1556 : /*-----------------------------------------------------------------
1557 : * Reposition the file pointer and write the entry.
1558 : *
1559 : * We use VSIFSeek() directly since the AVCRawBin*() functions do
1560 : * not support random access yet... it is OK to do so here since the
1561 : * ARC.DIR does not have a header and we will close it right away.
1562 : *----------------------------------------------------------------*/
1563 0 : if (bFound)
1564 0 : VSIFSeek(hRawBinFile->fp, iEntry*380, SEEK_SET);
1565 : else
1566 : {
1567 : /* Not found... Use the next logical table index */
1568 0 : nTableIndex++;
1569 :
1570 : /* We're already at EOF so we shouldn't need to fseek here, but
1571 : * ANSI-C requires that a file positioning function be called
1572 : * between read and writes... this had never been a problem before
1573 : * on any system except with NT4 network drives.
1574 : */
1575 0 : VSIFSeek(hRawBinFile->fp, numDirEntries*380, SEEK_SET);
1576 : }
1577 :
1578 0 : sprintf(psTableDef->szInfoFile, "ARC%4.4d", nTableIndex);
1579 0 : _AVCBinWriteArcDir(hRawBinFile, psTableDef);
1580 :
1581 0 : AVCRawBinClose(hRawBinFile);
1582 :
1583 0 : return nTableIndex;
1584 : }
1585 :
1586 :
1587 : /**********************************************************************
1588 : * AVCBinWriteCreateTable()
1589 : *
1590 : * Open an INFO table for writing:
1591 : *
1592 : * - Add an entry for the new table in the info/arc.dir
1593 : * - Write the attributes definitions to the info/arc####.nit
1594 : * - Create the data file, ready to write data records to it
1595 : * - If necessary, set the arc####.dat to point to the location of
1596 : * the data file.
1597 : *
1598 : * pszInfoPath is the info directory path, terminated by a '/' or a '\\'
1599 : * It is assumed that this 'info' directory already exists and is writable.
1600 : *
1601 : * psTableDef should contain a valid table definition for this coverage.
1602 : * This function will create and maintain its own copy of the structure.
1603 : *
1604 : * The name of the file to create and its location will be based on the
1605 : * table name and the external ("XX") flag values in the psTableDef
1606 : * structure, so you have to make sure that these values are valid.
1607 : *
1608 : * If a table with the same name is already present in the arc.dir, then
1609 : * the same arc.dir entry will be used and overwritten. This happens
1610 : * when a coverage directory is deleted by hand. The behavior implemented
1611 : * here correspond to Arc/Info's behavior.
1612 : *
1613 : * For internal tables, the data file goes directly in the info directory, so
1614 : * there is not much to worry about.
1615 : *
1616 : * For external tables, the table name is composed of 3 parts:
1617 : *
1618 : * <COVERNAME>.<EXT><SUBCLASSNAME>
1619 : *
1620 : * - <COVERNAME>:
1621 : * The first part of the table name (before the '.') is the
1622 : * name of the coverage to which the table belongs, and the data file
1623 : * will be created in this coverage's directory... so it is assumed that
1624 : * the directory "../<covername>" already exists and is writable.
1625 : * - <EXT>:
1626 : * The coverage name is followed by a 3 chars extension that will be
1627 : * used to build the name of the external table to create.
1628 : * - <SUBCLASSNAME>:
1629 : * For some table types, the extension is followed by a subclass name.
1630 : *
1631 : * When <SUBCLASSNAME> is present, then the data file name will be:
1632 : * "../<covername>/<subclassname>.<ext>"
1633 : *
1634 : * e.g. The table named "TEST.PATCOUNTY" would be stored in the file
1635 : * "../test/county.pat" (this path is realtive to the info directory)
1636 : *
1637 : * When the <SUBCLASSNAME> is not present, then the name of the data file
1638 : * will be the "../<covername>/<ext>.adf"
1639 : *
1640 : * e.g. The table named "TEST.PAT" would be stored in the file
1641 : * "../test/pat.adf"
1642 : *
1643 : * Of course, it would be too easy if there were no exceptions to these
1644 : * rules! Single precision ".TIC" and ".BND" follow the above rules and
1645 : * will be named "tic.adf" and "bnd.adf" but in double precision coverages,
1646 : * they will be named "dbltic.adf" and "dblbnd.adf".
1647 : *
1648 : * Returns a valid AVCBinFile handle, or NULL if the table could
1649 : * not be created.
1650 : *
1651 : * AVCBinClose() will eventually have to be called to release the
1652 : * resources used by the AVCBinFile structure.
1653 : **********************************************************************/
1654 0 : AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
1655 : const char *pszCoverName,
1656 : AVCTableDef *psSrcTableDef,
1657 : AVCCoverType eCoverType,
1658 : int nPrecision, AVCDBCSInfo *psDBCSInfo)
1659 : {
1660 : AVCBinFile *psFile;
1661 : AVCRawBinFile *hRawBinFile;
1662 0 : AVCTableDef *psTableDef = NULL;
1663 0 : char *pszFname = NULL, szInfoFile[8]="";
1664 0 : int i, nTableIndex = 0;
1665 :
1666 0 : if (eCoverType == AVCCoverPC || eCoverType == AVCCoverPC2)
1667 0 : return _AVCBinWriteCreateDBFTable(pszInfoPath, pszCoverName,
1668 : psSrcTableDef, eCoverType,
1669 : nPrecision, psDBCSInfo);
1670 :
1671 : /*-----------------------------------------------------------------
1672 : * Make sure precision value is valid (AVC_DEFAULT_PREC is NOT valid)
1673 : *----------------------------------------------------------------*/
1674 0 : if (nPrecision!=AVC_SINGLE_PREC && nPrecision!=AVC_DOUBLE_PREC)
1675 : {
1676 0 : CPLError(CE_Failure, CPLE_IllegalArg,
1677 : "AVCBinWriteCreateTable(): Invalid precision parameter "
1678 : "(value must be AVC_SINGLE_PREC or AVC_DOUBLE_PREC)");
1679 0 : return NULL;
1680 : }
1681 :
1682 : /* Alloc a buffer big enough for the longest possible filename...
1683 : */
1684 0 : pszFname = (char*)CPLMalloc((strlen(pszInfoPath)+81)*sizeof(char));
1685 :
1686 :
1687 : /*-----------------------------------------------------------------
1688 : * Alloc and init the AVCBinFile struct.
1689 : *----------------------------------------------------------------*/
1690 0 : psFile = (AVCBinFile*)CPLCalloc(1, sizeof(AVCBinFile));
1691 :
1692 0 : psFile->eFileType = AVCFileTABLE;
1693 : /* Precision is not important for tables */
1694 0 : psFile->nPrecision = nPrecision;
1695 0 : psFile->eCoverType = eCoverType;
1696 :
1697 0 : psFile->hdr.psTableDef = psTableDef = _AVCDupTableDef(psSrcTableDef);
1698 :
1699 : /*-----------------------------------------------------------------
1700 : * Add a record for this table in the "arc.dir"
1701 : * Note: there could be a problem if 2 processes try to add an entry
1702 : * at the exact same time... does Arc/Info do any locking on that file???
1703 : *----------------------------------------------------------------*/
1704 0 : sprintf(pszFname, "%sarc.dir", pszInfoPath);
1705 :
1706 0 : nTableIndex = _AVCBinWriteCreateArcDirEntry(pszFname, psTableDef,
1707 : psDBCSInfo);
1708 :
1709 0 : if (nTableIndex < 0)
1710 : {
1711 : /* Failed to add arc.dir entry... just return NULL since an error
1712 : * message has already been issued by _AVCBinWriteCreateArcDirEntry()
1713 : */
1714 0 : _AVCDestroyTableDef(psTableDef);
1715 0 : CPLFree(psFile);
1716 0 : CPLFree(pszFname);
1717 0 : return NULL;
1718 : }
1719 :
1720 0 : sprintf(szInfoFile, "arc%4.4d", nTableIndex);
1721 :
1722 : /*-----------------------------------------------------------------
1723 : * Create the "arc####.nit" with the attribute definitions.
1724 : *----------------------------------------------------------------*/
1725 0 : sprintf(pszFname, "%s%s.nit", pszInfoPath, szInfoFile);
1726 :
1727 0 : hRawBinFile = AVCRawBinOpen(pszFname, "w",
1728 : AVC_COVER_BYTE_ORDER(AVCCoverV7),
1729 : psDBCSInfo);
1730 :
1731 0 : if (hRawBinFile == NULL)
1732 : {
1733 : /* Failed to open file... just return NULL since an error message
1734 : * has already been issued by AVCRawBinOpen()
1735 : */
1736 0 : _AVCDestroyTableDef(psTableDef);
1737 0 : CPLFree(psFile);
1738 0 : CPLFree(pszFname);
1739 0 : return NULL;
1740 : }
1741 :
1742 0 : for(i=0; i<psTableDef->numFields; i++)
1743 : {
1744 0 : _AVCBinWriteArcNit(hRawBinFile, &(psTableDef->pasFieldDef[i]));
1745 : }
1746 :
1747 0 : AVCRawBinClose(hRawBinFile);
1748 0 : hRawBinFile = NULL;
1749 :
1750 : /*-----------------------------------------------------------------
1751 : * The location of the data file depends on the external flag.
1752 : *----------------------------------------------------------------*/
1753 0 : if (EQUAL(psTableDef->szExternal, " "))
1754 : {
1755 : /*-------------------------------------------------------------
1756 : * Internal table: data goes directly in "arc####.dat"
1757 : *------------------------------------------------------------*/
1758 0 : psTableDef->szDataFile[0] = '\0';
1759 0 : sprintf(pszFname, "%s%s.dat", pszInfoPath, szInfoFile);
1760 0 : psFile->pszFilename = CPLStrdup(pszFname);
1761 : }
1762 : else
1763 : {
1764 : /*-------------------------------------------------------------
1765 : * External table: data stored in the coverage directory, and
1766 : * the path to the data file is written to "arc####.dat"
1767 : *... start by extracting the info to build the data file name...
1768 : *------------------------------------------------------------*/
1769 0 : char szCoverName[40]="", szExt[4]="", szSubclass[40]="", *pszPtr;
1770 : int nLen;
1771 : FILE *fpOut;
1772 :
1773 0 : nLen = strlen(psTableDef->szTableName);
1774 0 : CPLAssert(nLen <= 32);
1775 0 : if (nLen > 32) return NULL;
1776 0 : pszPtr = psTableDef->szTableName;
1777 :
1778 0 : for(i=0; *pszPtr!='\0' && *pszPtr!='.' && *pszPtr!=' '; i++, pszPtr++)
1779 : {
1780 0 : szCoverName[i] = tolower(*pszPtr);
1781 : }
1782 0 : szCoverName[i] = '\0';
1783 :
1784 0 : if (*pszPtr == '.')
1785 0 : pszPtr++;
1786 :
1787 0 : for(i=0; i<3 && *pszPtr!='\0' && *pszPtr!=' '; i++, pszPtr++)
1788 : {
1789 0 : szExt[i] = tolower(*pszPtr);
1790 : }
1791 0 : szExt[i] = '\0';
1792 :
1793 0 : for(i=0; *pszPtr!='\0' && *pszPtr!=' '; i++, pszPtr++)
1794 : {
1795 0 : szSubclass[i] = tolower(*pszPtr);
1796 : }
1797 0 : szSubclass[i] = '\0';
1798 :
1799 : /*-------------------------------------------------------------
1800 : * ... and build the data file name based on what we extracted
1801 : *------------------------------------------------------------*/
1802 0 : if (strlen(szSubclass) == 0)
1803 : {
1804 0 : if (nPrecision == AVC_DOUBLE_PREC &&
1805 0 : (EQUAL(szExt, "TIC") || EQUAL(szExt, "BND")) )
1806 : {
1807 : /* "../<covername>/dbl<ext>.adf" */
1808 0 : sprintf(psTableDef->szDataFile,
1809 : "../%s/dbl%s.adf", szCoverName, szExt);
1810 : }
1811 : else
1812 : {
1813 : /* "../<covername>/<ext>.adf" */
1814 0 : sprintf(psTableDef->szDataFile,
1815 : "../%s/%s.adf", szCoverName, szExt);
1816 : }
1817 : }
1818 : else
1819 : {
1820 : /* "../<covername>/<subclass>.<ext>" */
1821 0 : sprintf(psTableDef->szDataFile,
1822 : "../%s/%s.%s", szCoverName, szSubclass, szExt);
1823 : }
1824 :
1825 : /*-------------------------------------------------------------
1826 : * Write it to the arc####.dat
1827 : * Note that the path that is written in the arc####.dat contains
1828 : * '/' as a directory delimiter, even on Windows systems.
1829 : *------------------------------------------------------------*/
1830 0 : sprintf(pszFname, "%s%s.dat", pszInfoPath, szInfoFile);
1831 0 : fpOut = VSIFOpen(pszFname, "wt");
1832 0 : if (fpOut)
1833 : {
1834 0 : VSIFPrintf(fpOut, "%-80.80s", psTableDef->szDataFile);
1835 0 : VSIFClose(fpOut);
1836 : }
1837 : else
1838 : {
1839 0 : CPLError(CE_Failure, CPLE_OpenFailed,
1840 : "Failed creating file %s.", pszFname);
1841 0 : CPLFree(pszFname);
1842 0 : _AVCDestroyTableDef(psTableDef);
1843 0 : CPLFree(psFile);
1844 0 : return NULL;
1845 : }
1846 :
1847 0 : sprintf(pszFname, "%s%s",
1848 : pszInfoPath, psTableDef->szDataFile);
1849 0 : psFile->pszFilename = CPLStrdup(pszFname);
1850 :
1851 : #ifdef WIN32
1852 : /*-------------------------------------------------------------
1853 : * On a Windows system, we have to change the '/' to '\\' in the
1854 : * data file path.
1855 : *------------------------------------------------------------*/
1856 : for(i=0; psFile->pszFilename[i] != '\0'; i++)
1857 : if (psFile->pszFilename[i] == '/')
1858 : psFile->pszFilename[i] = '\\';
1859 : #endif /* WIN32 */
1860 :
1861 : }/* if "XX" */
1862 :
1863 : /*-----------------------------------------------------------------
1864 : * OK, now we're ready to create the actual data file.
1865 : *----------------------------------------------------------------*/
1866 0 : AVCAdjustCaseSensitiveFilename(psFile->pszFilename);
1867 0 : psFile->psRawBinFile = AVCRawBinOpen(psFile->pszFilename, "w",
1868 : AVC_COVER_BYTE_ORDER(AVCCoverV7),
1869 : psDBCSInfo);
1870 :
1871 0 : if (psFile->psRawBinFile == NULL)
1872 : {
1873 : /* Failed to open file... just return NULL since an error message
1874 : * has already been issued by AVCRawBinOpen()
1875 : */
1876 0 : CPLFree(pszFname);
1877 0 : CPLFree(psFile->pszFilename);
1878 0 : _AVCDestroyTableDef(psTableDef);
1879 0 : CPLFree(psFile);
1880 0 : return NULL;
1881 : }
1882 :
1883 0 : CPLFree(pszFname);
1884 :
1885 0 : return psFile;
1886 : }
1887 :
1888 :
1889 : /**********************************************************************
1890 : * _AVCBinWriteCreateDBFTable()
1891 : *
1892 : * Create a table (DBF file) in a PC Coverage and write the attribute defns to
1893 : * the file. The file will then be ready to write records to.
1894 : *
1895 : * In PC Coverages, only the following tables appear to be supported:
1896 : * - TEST.AAT -> AAT.DBF
1897 : * - TEST.PAT -> PAT.DBF
1898 : * - TEST.BND -> BND.DBF
1899 : * - TEST.TIC -> TIC.DBF
1900 : *
1901 : * However, this function will not fail if it is passed a table name not
1902 : * supported by PC Arc/Info.
1903 : * e.g. TEST.PATCOUNTY would be written as PATCOUNTY.DBF even if PC Arc/Info
1904 : * would probably not recognize that name.
1905 : *
1906 : * Returns a valid AVCBinFile handle, or NULL if the table could
1907 : * not be created.
1908 : *
1909 : * AVCBinClose() will eventually have to be called to release the
1910 : * resources used by the AVCBinFile structure.
1911 : **********************************************************************/
1912 0 : AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
1913 : const char *pszCoverName,
1914 : AVCTableDef *psSrcTableDef,
1915 : AVCCoverType eCoverType,
1916 : int nPrecision, AVCDBCSInfo *psDBCSInfo)
1917 : {
1918 : AVCBinFile *psFile;
1919 0 : AVCTableDef *psTableDef = NULL;
1920 : AVCFieldInfo *pasDef;
1921 : char *pszDBFBasename, szFieldName[12];
1922 : int i, j, nType;
1923 :
1924 : /*-----------------------------------------------------------------
1925 : * Alloc and init the AVCBinFile struct.
1926 : *----------------------------------------------------------------*/
1927 0 : psFile = (AVCBinFile*)CPLCalloc(1, sizeof(AVCBinFile));
1928 :
1929 0 : psFile->eFileType = AVCFileTABLE;
1930 : /* Precision is not important for tables */
1931 0 : psFile->nPrecision = nPrecision;
1932 0 : psFile->eCoverType = eCoverType;
1933 :
1934 0 : psFile->hdr.psTableDef = psTableDef = _AVCDupTableDef(psSrcTableDef);
1935 :
1936 : /* nCurDBFRecord is used to keep track of the 0-based index of the
1937 : * last record we read from the DBF file... this is to emulate
1938 : * sequential access which is assumed by the rest of the lib.
1939 : * Since the first record (record 0) has not been written yet, then
1940 : * we init the index at -1.
1941 : */
1942 0 : psFile->nCurDBFRecord = -1;
1943 :
1944 : /*-----------------------------------------------------------------
1945 : * Establish name of file to create.
1946 : *----------------------------------------------------------------*/
1947 0 : psFile->pszFilename = (char*)CPLCalloc(strlen(psSrcTableDef->szTableName)+
1948 0 : strlen(pszPath)+10, sizeof(char));
1949 :
1950 0 : if (EQUALN(psSrcTableDef->szTableName, pszCoverName, strlen(pszCoverName))
1951 0 : && psSrcTableDef->szTableName[strlen(pszCoverName)] == '.')
1952 : {
1953 0 : pszDBFBasename = psSrcTableDef->szTableName + strlen(pszCoverName)+1;
1954 : }
1955 : else
1956 : {
1957 0 : pszDBFBasename = psSrcTableDef->szTableName;
1958 : }
1959 :
1960 0 : strcpy(psFile->pszFilename, pszPath);
1961 :
1962 0 : for(i=strlen(psFile->pszFilename); *pszDBFBasename; i++, pszDBFBasename++)
1963 : {
1964 0 : psFile->pszFilename[i] = tolower(*pszDBFBasename);
1965 : }
1966 :
1967 0 : strcat(psFile->pszFilename, ".dbf");
1968 :
1969 : /*-----------------------------------------------------------------
1970 : * OK, let's try to create the DBF file.
1971 : *----------------------------------------------------------------*/
1972 0 : AVCAdjustCaseSensitiveFilename(psFile->pszFilename);
1973 0 : psFile->hDBFFile = DBFCreate(psFile->pszFilename);
1974 :
1975 0 : if (psFile->hDBFFile == NULL)
1976 : {
1977 0 : CPLError(CE_Failure, CPLE_OpenFailed,
1978 : "Failed creating file %s.", psFile->pszFilename);
1979 0 : CPLFree(psFile->pszFilename);
1980 0 : _AVCDestroyTableDef(psTableDef);
1981 0 : CPLFree(psFile);
1982 0 : return NULL;
1983 : }
1984 :
1985 : /*-----------------------------------------------------------------
1986 : * Create fields.
1987 : *----------------------------------------------------------------*/
1988 0 : pasDef = psTableDef->pasFieldDef;
1989 0 : for(i=0; i<psTableDef->numFields; i++)
1990 : {
1991 0 : nType = pasDef[i].nType1*10;
1992 :
1993 : /*-------------------------------------------------------------
1994 : * Special characters '#' and '-' in field names have to be replaced
1995 : * with '_'. PC Field names are limited to 10 chars.
1996 : *------------------------------------------------------------*/
1997 0 : strncpy(szFieldName, pasDef[i].szName, 10);
1998 0 : szFieldName[10] = '\0';
1999 0 : for(j=0; szFieldName[j]; j++)
2000 : {
2001 0 : if (szFieldName[j] == '#' || szFieldName[j] == '-')
2002 0 : szFieldName[j] = '_';
2003 : }
2004 :
2005 0 : if (nType == AVC_FT_DATE || nType == AVC_FT_CHAR)
2006 : {
2007 : /*---------------------------------------------------------
2008 : * Values stored as strings
2009 : *--------------------------------------------------------*/
2010 0 : DBFAddField(psFile->hDBFFile, szFieldName, FTString,
2011 0 : pasDef[i].nSize, 0);
2012 : }
2013 0 : else if (nType == AVC_FT_FIXINT || nType == AVC_FT_FIXNUM)
2014 : {
2015 : /*---------------------------------------------------------
2016 : * Numerics (internally stored as strings)
2017 : *--------------------------------------------------------*/
2018 0 : DBFAddField(psFile->hDBFFile, szFieldName, FTDouble,
2019 0 : pasDef[i].nSize, pasDef[i].nFmtPrec);
2020 : }
2021 0 : else if (nType == AVC_FT_BININT)
2022 : {
2023 : /*---------------------------------------------------------
2024 : * Integers (16 and 32 bits)
2025 : *--------------------------------------------------------*/
2026 0 : DBFAddField(psFile->hDBFFile, szFieldName, FTInteger, 11, 0);
2027 : }
2028 0 : else if (nType == AVC_FT_BINFLOAT)
2029 : {
2030 : /*---------------------------------------------------------
2031 : * Single + Double precision floats
2032 : * Set them as width=13, prec=6 in the header like PC/Arc does
2033 : *--------------------------------------------------------*/
2034 0 : DBFAddField(psFile->hDBFFile, szFieldName, FTDouble,
2035 : 13, 6);
2036 : }
2037 : else
2038 : {
2039 : /*---------------------------------------------------------
2040 : * Hummm... unsupported field type...
2041 : *--------------------------------------------------------*/
2042 0 : CPLError(CE_Failure, CPLE_NotSupported,
2043 : "Unsupported field type: (field=%s, type=%d, size=%d)",
2044 0 : szFieldName, nType, pasDef[i].nSize);
2045 0 : _AVCBinWriteCloseTable(psFile);
2046 0 : return NULL;
2047 : }
2048 : }
2049 :
2050 0 : return psFile;
2051 : }
2052 :
2053 :
2054 : /**********************************************************************
2055 : * _AVCBinWriteCloseTable()
2056 : *
2057 : * (This function is for internal library use... external calls should
2058 : * go to AVCBinWriteClose() instead)
2059 : *
2060 : * Close an info table opened for wirting, and release all memory
2061 : * (object struct., buffers, etc.) associated with this file.
2062 : **********************************************************************/
2063 0 : static void _AVCBinWriteCloseTable(AVCBinFile *psFile)
2064 : {
2065 0 : if (psFile->eFileType != AVCFileTABLE)
2066 0 : return;
2067 :
2068 : /*-----------------------------------------------------------------
2069 : * Close the data file
2070 : *----------------------------------------------------------------*/
2071 0 : if (psFile->hDBFFile)
2072 : {
2073 : /*-------------------------------------------------------------
2074 : * The case of DBF files is simple!
2075 : *------------------------------------------------------------*/
2076 0 : DBFClose(psFile->hDBFFile);
2077 0 : psFile->hDBFFile = NULL;
2078 : }
2079 0 : else if (psFile->psRawBinFile)
2080 : {
2081 : /*-------------------------------------------------------------
2082 : * __TODO__ make sure ARC.DIR entry contains accurate info about the
2083 : * number of records written, etc.
2084 : *------------------------------------------------------------*/
2085 0 : AVCRawBinClose(psFile->psRawBinFile);
2086 0 : psFile->psRawBinFile = NULL;
2087 : }
2088 :
2089 : /*-----------------------------------------------------------------
2090 : * Release other memory
2091 : *----------------------------------------------------------------*/
2092 0 : _AVCDestroyTableDef(psFile->hdr.psTableDef);
2093 :
2094 0 : CPLFree(psFile->pszFilename);
2095 :
2096 0 : CPLFree(psFile);
2097 : }
2098 :
2099 :
2100 : /**********************************************************************
2101 : * _AVCBinWriteTableRec()
2102 : *
2103 : * (This function is for internal library use... external calls should
2104 : * go to AVCBinWriteTableRec() instead)
2105 : *
2106 : * Write a table data record at the current position in file.
2107 : *
2108 : * The contents of the pasDef and pasFields structures is assumed to
2109 : * be valid... this function performs no validation on the consistency
2110 : * of what it is given as input.
2111 : *
2112 : * Returns 0 on success or -1 on error.
2113 : **********************************************************************/
2114 0 : int _AVCBinWriteTableRec(AVCRawBinFile *psFile, int nFields,
2115 : AVCFieldInfo *pasDef, AVCField *pasFields,
2116 : int nRecordSize, const char *pszFname)
2117 : {
2118 0 : int i, nType, nBytesWritten=0;
2119 :
2120 0 : if (psFile == NULL)
2121 0 : return -1;
2122 :
2123 0 : for(i=0; i<nFields; i++)
2124 : {
2125 0 : if (CPLGetLastErrorNo() != 0)
2126 0 : return -1;
2127 :
2128 0 : nType = pasDef[i].nType1*10;
2129 :
2130 0 : if (nType == AVC_FT_DATE || nType == AVC_FT_CHAR ||
2131 : nType == AVC_FT_FIXINT || nType == AVC_FT_FIXNUM)
2132 : {
2133 : /*---------------------------------------------------------
2134 : * Values stored as strings (MUST be padded with spaces)
2135 : *--------------------------------------------------------*/
2136 0 : AVCRawBinWritePaddedString(psFile, pasDef[i].nSize,
2137 0 : pasFields[i].pszStr);
2138 : }
2139 0 : else if (nType == AVC_FT_BININT && pasDef[i].nSize == 4)
2140 : {
2141 : /*---------------------------------------------------------
2142 : * 32 bit binary integers
2143 : *--------------------------------------------------------*/
2144 0 : AVCRawBinWriteInt32(psFile, pasFields[i].nInt32);
2145 : }
2146 0 : else if (nType == AVC_FT_BININT && pasDef[i].nSize == 2)
2147 : {
2148 : /*---------------------------------------------------------
2149 : * 16 bit binary integers
2150 : *--------------------------------------------------------*/
2151 0 : AVCRawBinWriteInt16(psFile, pasFields[i].nInt16);
2152 : }
2153 0 : else if (nType == AVC_FT_BINFLOAT && pasDef[i].nSize == 4)
2154 : {
2155 : /*---------------------------------------------------------
2156 : * Single precision floats
2157 : *--------------------------------------------------------*/
2158 0 : AVCRawBinWriteFloat(psFile, pasFields[i].fFloat);
2159 : }
2160 0 : else if (nType == AVC_FT_BINFLOAT && pasDef[i].nSize == 8)
2161 : {
2162 : /*---------------------------------------------------------
2163 : * Double precision floats
2164 : *--------------------------------------------------------*/
2165 0 : AVCRawBinWriteDouble(psFile, pasFields[i].dDouble);
2166 : }
2167 : else
2168 : {
2169 : /*---------------------------------------------------------
2170 : * Hummm... unsupported field type...
2171 : *--------------------------------------------------------*/
2172 0 : CPLError(CE_Failure, CPLE_NotSupported,
2173 : "Unsupported field type in %s: (type=%d, size=%d)",
2174 0 : pszFname, nType, pasDef[i].nSize);
2175 0 : return -1;
2176 : }
2177 :
2178 0 : nBytesWritten += pasDef[i].nSize;
2179 : }
2180 :
2181 : /*-----------------------------------------------------------------
2182 : * Record size is rounded to a multiple of 2 bytes.
2183 : * Check the number of bytes written, and pad with zeros if
2184 : * necessary.
2185 : *----------------------------------------------------------------*/
2186 0 : nRecordSize = ((nRecordSize+1)/2)*2;
2187 0 : if (nBytesWritten < nRecordSize)
2188 0 : AVCRawBinWriteZeros(psFile, nRecordSize - nBytesWritten);
2189 :
2190 0 : if (CPLGetLastErrorNo() != 0)
2191 0 : return -1;
2192 :
2193 0 : return 0;
2194 : }
2195 :
2196 : /**********************************************************************
2197 : * _AVCBinWriteDBFTableRec()
2198 : *
2199 : * (This function is for internal library use... external calls should
2200 : * go to AVCBinWriteTableRec() instead)
2201 : *
2202 : * Write a table data record at the current position in DBF file.
2203 : *
2204 : * The contents of the pasDef and pasFields structures is assumed to
2205 : * be valid... this function performs no validation on the consistency
2206 : * of what it is given as input.
2207 : *
2208 : * Returns 0 on success or -1 on error.
2209 : **********************************************************************/
2210 0 : int _AVCBinWriteDBFTableRec(DBFHandle hDBFFile, int nFields,
2211 : AVCFieldInfo *pasDef, AVCField *pasFields,
2212 : int *nCurDBFRecord, const char *pszFname)
2213 : {
2214 0 : int i, nType, nStatus = FALSE;
2215 :
2216 0 : if (hDBFFile == NULL)
2217 0 : return -1;
2218 :
2219 0 : (*nCurDBFRecord)++;
2220 :
2221 0 : for(i=0; i<nFields; i++)
2222 : {
2223 0 : if (CPLGetLastErrorNo() != 0)
2224 0 : return -1;
2225 :
2226 0 : nType = pasDef[i].nType1*10;
2227 :
2228 0 : if (nType == AVC_FT_DATE || nType == AVC_FT_CHAR)
2229 : {
2230 : /*---------------------------------------------------------
2231 : * Values stored as strings
2232 : *--------------------------------------------------------*/
2233 0 : nStatus = DBFWriteStringAttribute(hDBFFile, *nCurDBFRecord, i,
2234 0 : (char *)pasFields[i].pszStr);
2235 : }
2236 0 : else if (nType == AVC_FT_FIXINT || nType == AVC_FT_FIXNUM)
2237 : {
2238 : /*---------------------------------------------------------
2239 : * Numbers stored as strings
2240 : *--------------------------------------------------------*/
2241 0 : nStatus = DBFWriteAttributeDirectly(hDBFFile, *nCurDBFRecord, i,
2242 0 : pasFields[i].pszStr);
2243 : }
2244 0 : else if (nType == AVC_FT_BININT && pasDef[i].nSize == 4)
2245 : {
2246 : /*---------------------------------------------------------
2247 : * 32 bit binary integers
2248 : *--------------------------------------------------------*/
2249 0 : nStatus = DBFWriteIntegerAttribute(hDBFFile, *nCurDBFRecord, i,
2250 0 : pasFields[i].nInt32);
2251 : }
2252 0 : else if (nType == AVC_FT_BININT && pasDef[i].nSize == 2)
2253 : {
2254 : /*---------------------------------------------------------
2255 : * 16 bit binary integers
2256 : *--------------------------------------------------------*/
2257 0 : nStatus = DBFWriteIntegerAttribute(hDBFFile, *nCurDBFRecord, i,
2258 0 : pasFields[i].nInt16);
2259 : }
2260 0 : else if (nType == AVC_FT_BINFLOAT)
2261 : {
2262 : /*---------------------------------------------------------
2263 : * Single+double precision floats
2264 : *--------------------------------------------------------*/
2265 0 : char szBuf[32] = "";
2266 : int nLen;
2267 :
2268 0 : if (pasDef[i].nSize == 4)
2269 0 : nLen = AVCPrintRealValue(szBuf, AVC_FORMAT_DBF_FLOAT,
2270 0 : AVCFileTABLE, pasFields[i].fFloat);
2271 : else
2272 0 : nLen = AVCPrintRealValue(szBuf, AVC_FORMAT_DBF_FLOAT,
2273 0 : AVCFileTABLE, pasFields[i].dDouble);
2274 :
2275 0 : szBuf[nLen] = '\0';
2276 :
2277 0 : nStatus = DBFWriteAttributeDirectly(hDBFFile, *nCurDBFRecord, i,
2278 : szBuf);
2279 : }
2280 : else
2281 : {
2282 : /*---------------------------------------------------------
2283 : * Hummm... unsupported field type...
2284 : *--------------------------------------------------------*/
2285 0 : CPLError(CE_Failure, CPLE_NotSupported,
2286 : "Unsupported field type in %s: (type=%d, size=%d)",
2287 0 : pszFname, nType, pasDef[i].nSize);
2288 0 : return -1;
2289 : }
2290 :
2291 0 : if (nStatus != TRUE)
2292 : {
2293 0 : CPLError(CE_Failure, CPLE_FileIO,
2294 : "Failed writing table field %d to record %d in %s",
2295 : i, *nCurDBFRecord, pszFname);
2296 0 : return -1;
2297 : }
2298 :
2299 : }
2300 :
2301 0 : return 0;
2302 : }
2303 :
2304 : /**********************************************************************
2305 : * AVCBinWriteTableRec()
2306 : *
2307 : * Write a table data record at the current position in file.
2308 : *
2309 : * The contents of the pasDef and pasFields structures is assumed to
2310 : * be valid... this function performs no validation on the consistency
2311 : * of what it is given as input.
2312 : *
2313 : * Returns 0 on success or -1 on error.
2314 : *
2315 : * If a problem happens, then CPLError() will be called by the lower-level
2316 : * functions and CPLGetLastErrorNo() can be used to find out what happened.
2317 : **********************************************************************/
2318 0 : int AVCBinWriteTableRec(AVCBinFile *psFile, AVCField *pasFields)
2319 : {
2320 0 : if (psFile->eFileType != AVCFileTABLE||
2321 0 : psFile->hdr.psTableDef->numRecords == 0)
2322 0 : return -1;
2323 :
2324 0 : if (psFile->eCoverType == AVCCoverPC || psFile->eCoverType == AVCCoverPC2)
2325 0 : return _AVCBinWriteDBFTableRec(psFile->hDBFFile,
2326 0 : psFile->hdr.psTableDef->numFields,
2327 0 : psFile->hdr.psTableDef->pasFieldDef,
2328 : pasFields,
2329 : &(psFile->nCurDBFRecord),
2330 0 : psFile->pszFilename);
2331 : else
2332 0 : return _AVCBinWriteTableRec(psFile->psRawBinFile,
2333 0 : psFile->hdr.psTableDef->numFields,
2334 0 : psFile->hdr.psTableDef->pasFieldDef,
2335 : pasFields,
2336 0 : psFile->hdr.psTableDef->nRecSize,
2337 0 : psFile->pszFilename);
2338 : }
2339 :
|