LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/avc - avc_e00gen.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 11 420 2.6 %
Date: 2024-11-21 22:18:42 Functions: 2 17 11.8 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  * $Id$
       3             :  *
       4             :  * Name:     avc_e00gen.c
       5             :  * Project:  Arc/Info vector coverage (AVC)  BIN->E00 conversion library
       6             :  * Language: ANSI C
       7             :  * Purpose:  Functions to generate ASCII E00 lines form binary structures.
       8             :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
       9             :  *
      10             :  **********************************************************************
      11             :  * Copyright (c) 1999-2005, Daniel Morissette
      12             :  *
      13             :  * SPDX-License-Identifier: MIT
      14             :  **********************************************************************
      15             :  *
      16             :  * $Log: avc_e00gen.c,v $
      17             :  * Revision 1.18  2008/07/23 20:51:38  dmorissette
      18             :  * Fixed GCC 4.1.x compile warnings related to use of char vs unsigned char
      19             :  * (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2495)
      20             :  *
      21             :  * Revision 1.17  2006/06/14 15:01:33  daniel
      22             :  * Remove any embedded '\0' from data line in AVCE00GenTableRec()
      23             :  *
      24             :  * Revision 1.16  2005/06/03 03:49:58  daniel
      25             :  * Update email address, website url, and copyright dates
      26             :  *
      27             :  * Revision 1.15  2004/08/19 17:48:20  warmerda
      28             :  * Avoid uninitialized variable warnings.
      29             :  *
      30             :  * Revision 1.14  2001/11/25 21:15:23  daniel
      31             :  * Added hack (AVC_MAP_TYPE40_TO_DOUBLE) to map type 40 fields bigger than 8
      32             :  * digits to double precision as we generate E00 output (bug599)
      33             :  *
      34             :  * Revision 1.13  2001/11/19 20:39:48  daniel
      35             :  * Change to correctly format 0-arc PAL records, so that they have a
      36             :  * single "filler" arc record
      37             :  *
      38             :  * Revision 1.12  2000/09/26 20:21:04  daniel
      39             :  * Added AVCCoverPC write
      40             :  *
      41             :  * Revision 1.11  2000/09/22 19:45:20  daniel
      42             :  * Switch to MIT-style license
      43             :  *
      44             :  * Revision 1.10  2000/02/04 04:54:03  daniel
      45             :  * Fixed warnings
      46             :  *
      47             :  * Revision 1.9  2000/02/03 07:21:02  daniel
      48             :  * TXT/TX6 with string longer than 80 chars: split string in 80 chars chunks
      49             :  *
      50             :  * Revision 1.8  2000/02/02 04:28:00  daniel
      51             :  * Fixed support of TX6/RXP/RPL coming from "weird" coverages
      52             :  *
      53             :  * Revision 1.7  1999/08/23 18:20:49  daniel
      54             :  * Fixed support for attribute fields type 40
      55             :  *
      56             :  * Revision 1.6  1999/05/17 16:19:39  daniel
      57             :  * Made sure ACVE00GenTableRec() removes all spaces at the end of a
      58             :  * table record line (it used to leave one space)
      59             :  *
      60             :  * Revision 1.5  1999/05/11 02:08:17  daniel
      61             :  * Simple changes related to the addition of coverage write support.
      62             :  *
      63             :  * Revision 1.4  1999/03/03 02:06:38  daniel
      64             :  * Properly handle 8 bytes floats inside single precision tables.
      65             :  *
      66             :  * Revision 1.3  1999/02/25 17:01:58  daniel
      67             :  * Added support for 16 bit integers in INFO tables (type=50, size=2)
      68             :  *
      69             :  * Revision 1.2  1999/02/25 04:17:51  daniel
      70             :  * Added TXT, TX6/TX7, RXP and RPL support + some minor changes
      71             :  *
      72             :  * Revision 1.1  1999/01/29 16:28:52  daniel
      73             :  * Initial revision
      74             :  *
      75             :  **********************************************************************/
      76             : 
      77             : #include "avc.h"
      78             : 
      79             : #include <ctype.h> /* toupper() */
      80             : 
      81             : /**********************************************************************
      82             :  *                          AVCE00GenInfoAlloc()
      83             :  *
      84             :  * Allocate and initialize a new AVCE00GenInfo structure.
      85             :  *
      86             :  * The structure will eventually have to be freed with AVCE00GenInfoFree().
      87             :  **********************************************************************/
      88           3 : AVCE00GenInfo *AVCE00GenInfoAlloc(int nCoverPrecision)
      89             : {
      90             :     AVCE00GenInfo *psInfo;
      91             : 
      92           3 :     psInfo = (AVCE00GenInfo *)CPLCalloc(1, sizeof(AVCE00GenInfo));
      93             : 
      94             :     /* Allocate output buffer.
      95             :      * 2k should be enough... the biggest thing we'll need to store
      96             :      * in it will be 1 complete INFO table record.
      97             :      */
      98           3 :     psInfo->nBufSize = 2048;
      99           3 :     psInfo->pszBuf = (char *)CPLMalloc(psInfo->nBufSize * sizeof(char));
     100             : 
     101           3 :     psInfo->nPrecision = nCoverPrecision;
     102             : 
     103           3 :     return psInfo;
     104             : }
     105             : 
     106             : /**********************************************************************
     107             :  *                          AVCE00GenInfoFree()
     108             :  *
     109             :  * Free any memory associated with a AVCE00GenInfo structure.
     110             :  **********************************************************************/
     111           3 : void AVCE00GenInfoFree(AVCE00GenInfo *psInfo)
     112             : {
     113           3 :     if (psInfo)
     114           3 :         CPLFree(psInfo->pszBuf);
     115           3 :     CPLFree(psInfo);
     116           3 : }
     117             : 
     118             : /**********************************************************************
     119             :  *                          AVCE00GenReset()
     120             :  *
     121             :  * Reset the fields in the AVCE00GenInfo structure so that further calls
     122             :  * with bCont = TRUE (ex: AVCE00GenArc(psInfo, TRUE)) would return nullptr.
     123             :  **********************************************************************/
     124           0 : void AVCE00GenReset(AVCE00GenInfo *psInfo)
     125             : {
     126             :     /* Reinitialize counters so that further calls with bCont = TRUE,
     127             :      * like AVCE00GenArc(psInfo, TRUE) would return nullptr.
     128             :      */
     129           0 :     psInfo->iCurItem = psInfo->numItems = 0;
     130           0 : }
     131             : 
     132             : /**********************************************************************
     133             :  *                          AVCE00GenStartSection()
     134             :  *
     135             :  * Generate the first line of an E00 section.
     136             :  *
     137             :  * pszClassName applies only to JABBERWOCKY type of sections.
     138             :  **********************************************************************/
     139           0 : const char *AVCE00GenStartSection(AVCE00GenInfo *psInfo, AVCFileType eType,
     140             :                                   const char *pszClassName)
     141             : {
     142           0 :     const char *pszName = "UNK";
     143             : 
     144           0 :     AVCE00GenReset(psInfo);
     145             : 
     146           0 :     if (eType == AVCFileTX6 || eType == AVCFileRXP || eType == AVCFileRPL)
     147             :     {
     148             :         /* TX6/RXP/RPL sections start with the class name (the basename
     149             :          * of the file) in uppercase.
     150             :          * ex:  The section for "cities.txt" would start with "CITIES"
     151             :          */
     152             :         int i;
     153           0 :         for (i = 0; pszClassName[i] != '\0'; i++)
     154             :         {
     155           0 :             psInfo->pszBuf[i] =
     156           0 :                 (char)CPLToupper(static_cast<unsigned char>(pszClassName[i]));
     157             :         }
     158           0 :         psInfo->pszBuf[i] = '\0';
     159             :     }
     160             :     else
     161             :     {
     162             :         /* In most cases, the section starts with a 3 letters code followed
     163             :          * by the precision code (2 or 3)
     164             :          */
     165           0 :         switch (eType)
     166             :         {
     167           0 :             case AVCFileARC:
     168           0 :                 pszName = "ARC";
     169           0 :                 break;
     170           0 :             case AVCFilePAL:
     171           0 :                 pszName = "PAL";
     172           0 :                 break;
     173           0 :             case AVCFileCNT:
     174           0 :                 pszName = "CNT";
     175           0 :                 break;
     176           0 :             case AVCFileLAB:
     177           0 :                 pszName = "LAB";
     178           0 :                 break;
     179           0 :             case AVCFileTOL:
     180           0 :                 pszName = "TOL";
     181           0 :                 break;
     182           0 :             case AVCFilePRJ:
     183           0 :                 pszName = "PRJ";
     184           0 :                 break;
     185           0 :             case AVCFileTXT:
     186           0 :                 pszName = "TXT";
     187           0 :                 break;
     188           0 :             default:
     189           0 :                 CPLError(CE_Failure, CPLE_NotSupported,
     190             :                          "Unsupported E00 section type!");
     191             :         }
     192             : 
     193           0 :         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     194           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize, "%s  3", pszName);
     195             :         else
     196           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize, "%s  2", pszName);
     197             :     }
     198             : 
     199           0 :     return psInfo->pszBuf;
     200             : }
     201             : 
     202             : /**********************************************************************
     203             :  *                          AVCE00GenEndSection()
     204             :  *
     205             :  * Generate the last line(s) of an E00 section.
     206             :  *
     207             :  * This function should be called once with bCont=FALSE to get the
     208             :  * first "end of section" line for the current section, and then call
     209             :  * with bCont=TRUE to get all the other lines.
     210             :  *
     211             :  * The function returns nullptr when there are no more lines to generate
     212             :  * for this "end of section".
     213             :  **********************************************************************/
     214           0 : const char *AVCE00GenEndSection(AVCE00GenInfo *psInfo, AVCFileType eType,
     215             :                                 GBool bCont)
     216             : {
     217           0 :     if (bCont == FALSE)
     218             :     {
     219             :         /*-------------------------------------------------------------
     220             :          * Most section types end with only 1 line.
     221             :          *------------------------------------------------------------*/
     222           0 :         AVCE00GenReset(psInfo);
     223           0 :         psInfo->iCurItem = 0;
     224             : 
     225           0 :         if (eType == AVCFileARC || eType == AVCFilePAL || eType == AVCFileRPL ||
     226           0 :             eType == AVCFileCNT || eType == AVCFileTOL || eType == AVCFileTXT ||
     227             :             eType == AVCFileTX6)
     228             :         {
     229           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize,
     230             :                      "        -1         0         0         0         0       "
     231             :                      "  0         0");
     232             :         }
     233           0 :         else if (eType == AVCFileLAB)
     234             :         {
     235           0 :             if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     236           0 :                 snprintf(psInfo->pszBuf, psInfo->nBufSize,
     237             :                          "        -1         0 0.00000000000000E+00 "
     238             :                          "0.00000000000000E+00");
     239             :             else
     240           0 :                 snprintf(psInfo->pszBuf, psInfo->nBufSize,
     241             :                          "        -1         0 0.0000000E+00 0.0000000E+00");
     242             :         }
     243           0 :         else if (eType == AVCFilePRJ)
     244             :         {
     245           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize, "EOP");
     246             :         }
     247           0 :         else if (eType == AVCFileRXP)
     248             :         {
     249           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize, "        -1         0");
     250             :         }
     251             :         else
     252             :         {
     253           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     254             :                      "Unsupported E00 section type!");
     255           0 :             return nullptr;
     256             :         }
     257             :     }
     258           0 :     else if (psInfo->iCurItem == 0 && psInfo->nPrecision == AVC_DOUBLE_PREC &&
     259           0 :              (eType == AVCFilePAL || eType == AVCFileRPL))
     260             :     {
     261             :         /*---------------------------------------------------------
     262             :          * Return the 2nd line for the end of a PAL or RPL section.
     263             :          *--------------------------------------------------------*/
     264           0 :         snprintf(psInfo->pszBuf, psInfo->nBufSize,
     265             :                  " 0.00000000000000E+00 0.00000000000000E+00");
     266             : 
     267           0 :         psInfo->iCurItem++;
     268             :     }
     269             :     else
     270             :     {
     271             :         /*-----------------------------------------------------
     272             :          * All other section types end with only one line, and thus
     273             :          * we return nullptr when bCont==TRUE
     274             :          *----------------------------------------------------*/
     275           0 :         return nullptr;
     276             :     }
     277             : 
     278           0 :     return psInfo->pszBuf;
     279             : }
     280             : 
     281             : /**********************************************************************
     282             :  *                          AVCE00GenObject()
     283             :  *
     284             :  * Cover function on top of AVCE00GenArc/Pal/Cnt/Lab() that will
     285             :  * call the right function according to argument eType.
     286             :  *
     287             :  * Since there is no compiler type checking on psObj, you have to
     288             :  * be very careful to make sure you pass an object of the right type
     289             :  * when you use this function!
     290             :  *
     291             :  * The function returns nullptr when there are no more lines to generate
     292             :  * for this ARC.
     293             :  **********************************************************************/
     294           0 : const char *AVCE00GenObject(AVCE00GenInfo *psInfo, AVCFileType eType,
     295             :                             void *psObj, GBool bCont)
     296             : {
     297           0 :     const char *pszLine = nullptr;
     298             : 
     299           0 :     switch (eType)
     300             :     {
     301           0 :         case AVCFileARC:
     302           0 :             pszLine = AVCE00GenArc(psInfo, (AVCArc *)psObj, bCont);
     303           0 :             break;
     304           0 :         case AVCFilePAL:
     305             :         case AVCFileRPL:
     306           0 :             pszLine = AVCE00GenPal(psInfo, (AVCPal *)psObj, bCont);
     307           0 :             break;
     308           0 :         case AVCFileCNT:
     309           0 :             pszLine = AVCE00GenCnt(psInfo, (AVCCnt *)psObj, bCont);
     310           0 :             break;
     311           0 :         case AVCFileLAB:
     312           0 :             pszLine = AVCE00GenLab(psInfo, (AVCLab *)psObj, bCont);
     313           0 :             break;
     314           0 :         case AVCFileTOL:
     315           0 :             pszLine = AVCE00GenTol(psInfo, (AVCTol *)psObj, bCont);
     316           0 :             break;
     317           0 :         case AVCFileTXT:
     318           0 :             pszLine = AVCE00GenTxt(psInfo, (AVCTxt *)psObj, bCont);
     319           0 :             break;
     320           0 :         case AVCFileTX6:
     321           0 :             pszLine = AVCE00GenTx6(psInfo, (AVCTxt *)psObj, bCont);
     322           0 :             break;
     323           0 :         case AVCFilePRJ:
     324           0 :             pszLine = AVCE00GenPrj(psInfo, (char **)psObj, bCont);
     325           0 :             break;
     326           0 :         case AVCFileRXP:
     327           0 :             pszLine = AVCE00GenRxp(psInfo, (AVCRxp *)psObj, bCont);
     328           0 :             break;
     329           0 :         default:
     330           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     331             :                      "AVCE00GenObject(): Unsupported file type!");
     332             :     }
     333             : 
     334           0 :     return pszLine;
     335             : }
     336             : 
     337             : /*=====================================================================
     338             :                             ARC stuff
     339             :  =====================================================================*/
     340             : 
     341             : /**********************************************************************
     342             :  *                          AVCE00GenArc()
     343             :  *
     344             :  * Generate the next line of an E00 ARC.
     345             :  *
     346             :  * This function should be called once with bCont=FALSE to get the
     347             :  * first E00 line for the current ARC, and then call with bCont=TRUE
     348             :  * to get all the other lines for this ARC.
     349             :  *
     350             :  * The function returns nullptr when there are no more lines to generate
     351             :  * for this ARC.
     352             :  **********************************************************************/
     353           0 : const char *AVCE00GenArc(AVCE00GenInfo *psInfo, AVCArc *psArc, GBool bCont)
     354             : {
     355           0 :     if (bCont == FALSE)
     356             :     {
     357             :         /* Initialize the psInfo structure with info about the
     358             :          * current ARC.
     359             :          */
     360           0 :         psInfo->iCurItem = 0;
     361           0 :         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     362           0 :             psInfo->numItems = psArc->numVertices;
     363             :         else
     364           0 :             psInfo->numItems = (psArc->numVertices + 1) / 2;
     365             : 
     366             :         /* And return the ARC header line
     367             :          */
     368           0 :         snprintf(psInfo->pszBuf, psInfo->nBufSize,
     369             :                  "%10d%10d%10d%10d%10d%10d%10d", psArc->nArcId, psArc->nUserId,
     370             :                  psArc->nFNode, psArc->nTNode, psArc->nLPoly, psArc->nRPoly,
     371             :                  psArc->numVertices);
     372             :     }
     373           0 :     else if (psInfo->iCurItem < psInfo->numItems)
     374             :     {
     375             :         int iVertex;
     376             : 
     377             :         /* return the next set of vertices for the ARC.
     378             :          */
     379           0 :         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     380             :         {
     381           0 :             iVertex = psInfo->iCurItem;
     382             : 
     383           0 :             psInfo->pszBuf[0] = '\0';
     384           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     385             :                               psInfo->nPrecision, AVCFileARC,
     386           0 :                               psArc->pasVertices[iVertex].x);
     387           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     388             :                               psInfo->nPrecision, AVCFileARC,
     389           0 :                               psArc->pasVertices[iVertex].y);
     390             :         }
     391             :         else
     392             :         {
     393           0 :             iVertex = psInfo->iCurItem * 2;
     394             : 
     395           0 :             psInfo->pszBuf[0] = '\0';
     396           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     397             :                               psInfo->nPrecision, AVCFileARC,
     398           0 :                               psArc->pasVertices[iVertex].x);
     399           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     400             :                               psInfo->nPrecision, AVCFileARC,
     401           0 :                               psArc->pasVertices[iVertex].y);
     402             : 
     403             :             /* Check because if we have a odd number of vertices then
     404             :              * the last line contains only one pair of vertices.
     405             :              */
     406           0 :             if (iVertex + 1 < psArc->numVertices)
     407             :             {
     408           0 :                 AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     409             :                                   psInfo->nPrecision, AVCFileARC,
     410           0 :                                   psArc->pasVertices[iVertex + 1].x);
     411           0 :                 AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     412             :                                   psInfo->nPrecision, AVCFileARC,
     413           0 :                                   psArc->pasVertices[iVertex + 1].y);
     414             :             }
     415             :         }
     416           0 :         psInfo->iCurItem++;
     417             :     }
     418             :     else
     419             :     {
     420             :         /* No more lines to generate for this ARC.
     421             :          */
     422           0 :         return nullptr;
     423             :     }
     424             : 
     425           0 :     return psInfo->pszBuf;
     426             : }
     427             : 
     428             : /*=====================================================================
     429             :                             PAL stuff
     430             :  =====================================================================*/
     431             : 
     432             : /**********************************************************************
     433             :  *                          AVCE00GenPal()
     434             :  *
     435             :  * Generate the next line of an E00 PAL (Polygon Arc List) entry.
     436             :  *
     437             :  * This function should be called once with bCont=FALSE to get the
     438             :  * first E00 line for the current PAL, and then call with bCont=TRUE
     439             :  * to get all the other lines for this PAL.
     440             :  *
     441             :  * The function returns nullptr when there are no more lines to generate
     442             :  * for this PAL entry.
     443             :  **********************************************************************/
     444           0 : const char *AVCE00GenPal(AVCE00GenInfo *psInfo, AVCPal *psPal, GBool bCont)
     445             : {
     446           0 :     if (bCont == FALSE)
     447             :     {
     448             :         /* Initialize the psInfo structure with info about the
     449             :          * current PAL.  (Number of lines excluding header)
     450             :          */
     451           0 :         psInfo->numItems = (psPal->numArcs + 1) / 2;
     452             : 
     453             :         /* And return the PAL header line.
     454             :          */
     455           0 :         snprintf(psInfo->pszBuf, psInfo->nBufSize, "%10d", psPal->numArcs);
     456             : 
     457           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
     458             :                           AVCFilePAL, psPal->sMin.x);
     459           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
     460             :                           AVCFilePAL, psPal->sMin.y);
     461             : 
     462             :         /* Double precision PAL entries have their header on 2 lines!
     463             :          */
     464           0 :         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     465             :         {
     466           0 :             psInfo->iCurItem = -1; /* Means 1 line left in header */
     467             :         }
     468             :         else
     469             :         {
     470           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     471             :                               psInfo->nPrecision, AVCFilePAL, psPal->sMax.x);
     472           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     473             :                               psInfo->nPrecision, AVCFilePAL, psPal->sMax.y);
     474           0 :             psInfo->iCurItem = 0; /* Next thing = first Arc entry */
     475             :         }
     476             :     }
     477           0 :     else if (psInfo->iCurItem == -1)
     478             :     {
     479             :         /* Second (and last) header line for double precision coverages
     480             :          */
     481           0 :         psInfo->pszBuf[0] = '\0';
     482           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
     483             :                           AVCFilePAL, psPal->sMax.x);
     484           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
     485             :                           AVCFilePAL, psPal->sMax.y);
     486             : 
     487           0 :         if (psInfo->numItems == 0)
     488             :         {
     489           0 :             psInfo->iCurItem = -2; /* We have a 0-arc polygon, which needs
     490             :                                       an arc list with one "0 0 0" element */
     491             :         }
     492             :         else
     493             :         {
     494           0 :             psInfo->iCurItem = 0; /* Next thing = first Arc entry */
     495             :         }
     496             :     }
     497           0 :     else if (psInfo->iCurItem == -2)
     498             :     {
     499           0 :         snprintf(psInfo->pszBuf, psInfo->nBufSize, "%10d%10d%10d", 0, 0, 0);
     500           0 :         psInfo->iCurItem = 0; /* Next thing = first Arc entry */
     501             :     }
     502           0 :     else if (psInfo->iCurItem < psInfo->numItems)
     503             :     {
     504             :         /* Return PAL Arc entries...
     505             :          */
     506             :         int iArc;
     507             : 
     508           0 :         iArc = psInfo->iCurItem * 2;
     509             : 
     510             :         /* If we have a odd number of arcs then
     511             :          * the last line contains only one arc entry.
     512             :          */
     513           0 :         if (iArc + 1 < psPal->numArcs)
     514             :         {
     515           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize,
     516           0 :                      "%10d%10d%10d%10d%10d%10d", psPal->pasArcs[iArc].nArcId,
     517           0 :                      psPal->pasArcs[iArc].nFNode, psPal->pasArcs[iArc].nAdjPoly,
     518           0 :                      psPal->pasArcs[iArc + 1].nArcId,
     519           0 :                      psPal->pasArcs[iArc + 1].nFNode,
     520           0 :                      psPal->pasArcs[iArc + 1].nAdjPoly);
     521             :         }
     522             :         else
     523             :         {
     524           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize, "%10d%10d%10d",
     525           0 :                      psPal->pasArcs[iArc].nArcId, psPal->pasArcs[iArc].nFNode,
     526           0 :                      psPal->pasArcs[iArc].nAdjPoly);
     527             :         }
     528           0 :         psInfo->iCurItem++;
     529             :     }
     530             :     else
     531             :     {
     532             :         /* No more lines to generate for this PAL.
     533             :          */
     534           0 :         return nullptr;
     535             :     }
     536             : 
     537           0 :     return psInfo->pszBuf;
     538             : }
     539             : 
     540             : /*=====================================================================
     541             :                             CNT stuff
     542             :  =====================================================================*/
     543             : 
     544             : /**********************************************************************
     545             :  *                          AVCE00GenCnt()
     546             :  *
     547             :  * Generate the next line of an E00 CNT (Polygon Centroid) entry.
     548             :  *
     549             :  * This function should be called once with bCont=FALSE to get the
     550             :  * first E00 line for the current CNT, and then call with bCont=TRUE
     551             :  * to get all the other lines for this CNT.
     552             :  *
     553             :  * The function returns nullptr when there are no more lines to generate
     554             :  * for this CNT entry.
     555             :  **********************************************************************/
     556           0 : const char *AVCE00GenCnt(AVCE00GenInfo *psInfo, AVCCnt *psCnt, GBool bCont)
     557             : {
     558           0 :     if (bCont == FALSE)
     559             :     {
     560             :         /* Initialize the psInfo structure with info about the
     561             :          * current CNT.
     562             :          */
     563           0 :         psInfo->iCurItem = 0;
     564           0 :         psInfo->numItems = (psCnt->numLabels + 7) / 8;
     565             : 
     566             :         /* And return the CNT header line.
     567             :          */
     568           0 :         snprintf(psInfo->pszBuf, psInfo->nBufSize, "%10d", psCnt->numLabels);
     569             : 
     570           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
     571             :                           AVCFileCNT, psCnt->sCoord.x);
     572           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
     573             :                           AVCFileCNT, psCnt->sCoord.y);
     574             :     }
     575           0 :     else if (psInfo->iCurItem < psInfo->numItems)
     576             :     {
     577             :         /* Return CNT Label Ids, 8 label Ids per line...
     578             :          */
     579             :         int i, nFirstLabel, numLabels;
     580             : 
     581           0 :         nFirstLabel = psInfo->iCurItem * 8;
     582           0 :         numLabels = MIN(8, (psCnt->numLabels - nFirstLabel));
     583             : 
     584           0 :         psInfo->pszBuf[0] = '\0';
     585           0 :         for (i = 0; i < numLabels; i++)
     586             :         {
     587           0 :             snprintf(psInfo->pszBuf + strlen(psInfo->pszBuf),
     588           0 :                      psInfo->nBufSize - strlen(psInfo->pszBuf), "%10d",
     589           0 :                      psCnt->panLabelIds[nFirstLabel + i]);
     590             :         }
     591             : 
     592           0 :         psInfo->iCurItem++;
     593             :     }
     594             :     else
     595             :     {
     596             :         /* No more lines to generate for this CNT.
     597             :          */
     598           0 :         return nullptr;
     599             :     }
     600             : 
     601           0 :     return psInfo->pszBuf;
     602             : }
     603             : 
     604             : /*=====================================================================
     605             :                             LAB stuff
     606             :  =====================================================================*/
     607             : 
     608             : /**********************************************************************
     609             :  *                          AVCE00GenLab()
     610             :  *
     611             :  * Generate the next line of an E00 LAB (Label) entry.
     612             :  *
     613             :  * This function should be called once with bCont=FALSE to get the
     614             :  * first E00 line for the current LAB, and then call with bCont=TRUE
     615             :  * to get all the other lines for this LAB.
     616             :  *
     617             :  * The function returns nullptr when there are no more lines to generate
     618             :  * for this LAB entry.
     619             :  **********************************************************************/
     620           0 : const char *AVCE00GenLab(AVCE00GenInfo *psInfo, AVCLab *psLab, GBool bCont)
     621             : {
     622           0 :     if (bCont == FALSE)
     623             :     {
     624             :         /* Initialize the psInfo structure with info about the
     625             :          * current LAB. (numItems = Number of lines excluding header)
     626             :          */
     627           0 :         psInfo->iCurItem = 0;
     628           0 :         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     629           0 :             psInfo->numItems = 2;
     630             :         else
     631           0 :             psInfo->numItems = 1;
     632             : 
     633             :         /* And return the LAB header line.
     634             :          */
     635           0 :         snprintf(psInfo->pszBuf, psInfo->nBufSize, "%10d%10d", psLab->nValue,
     636             :                  psLab->nPolyId);
     637             : 
     638           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
     639             :                           AVCFileLAB, psLab->sCoord1.x);
     640           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
     641             :                           AVCFileLAB, psLab->sCoord1.y);
     642             :     }
     643           0 :     else if (psInfo->iCurItem < psInfo->numItems)
     644             :     {
     645             :         /* Return next Label coordinates...
     646             :          */
     647           0 :         if (psInfo->nPrecision != AVC_DOUBLE_PREC)
     648             :         {
     649             :             /* Single precision, all on the same line
     650             :              */
     651           0 :             psInfo->pszBuf[0] = '\0';
     652           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     653             :                               psInfo->nPrecision, AVCFileLAB, psLab->sCoord2.x);
     654           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     655             :                               psInfo->nPrecision, AVCFileLAB, psLab->sCoord2.y);
     656           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     657             :                               psInfo->nPrecision, AVCFileLAB, psLab->sCoord3.x);
     658           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     659             :                               psInfo->nPrecision, AVCFileLAB, psLab->sCoord3.y);
     660             :         }
     661           0 :         else if (psInfo->iCurItem == 0)
     662             :         {
     663             :             /* 2nd line, in a double precision coverage
     664             :              */
     665           0 :             psInfo->pszBuf[0] = '\0';
     666           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     667             :                               psInfo->nPrecision, AVCFileLAB, psLab->sCoord2.x);
     668           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     669             :                               psInfo->nPrecision, AVCFileLAB, psLab->sCoord2.y);
     670             :         }
     671             :         else
     672             :         {
     673             :             /* 3rd line, in a double precision coverage
     674             :              */
     675           0 :             psInfo->pszBuf[0] = '\0';
     676           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     677             :                               psInfo->nPrecision, AVCFileLAB, psLab->sCoord3.x);
     678           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     679             :                               psInfo->nPrecision, AVCFileLAB, psLab->sCoord3.y);
     680             :         }
     681             : 
     682           0 :         psInfo->iCurItem++;
     683             :     }
     684             :     else
     685             :     {
     686             :         /* No more lines to generate for this LAB.
     687             :          */
     688           0 :         return nullptr;
     689             :     }
     690             : 
     691           0 :     return psInfo->pszBuf;
     692             : }
     693             : 
     694             : /*=====================================================================
     695             :                             TOL stuff
     696             :  =====================================================================*/
     697             : 
     698             : /**********************************************************************
     699             :  *                          AVCE00GenTol()
     700             :  *
     701             :  * Generate the next line of an E00 TOL (Tolerance) entry.
     702             :  *
     703             :  * This function should be called once with bCont=FALSE to get the
     704             :  * first E00 line for the current TOL, and then call with bCont=TRUE
     705             :  * to get all the other lines for this TOL.
     706             :  *
     707             :  * The function returns nullptr when there are no more lines to generate
     708             :  * for this TOL entry.
     709             :  **********************************************************************/
     710           0 : const char *AVCE00GenTol(AVCE00GenInfo *psInfo, AVCTol *psTol, GBool bCont)
     711             : {
     712           0 :     if (bCont == TRUE)
     713             :     {
     714             :         /*---------------------------------------------------------
     715             :          * TOL entries are only 1 line, we support the bCont flag
     716             :          * only for compatibility with the other AVCE00Gen*() functions.
     717             :          *--------------------------------------------------------*/
     718           0 :         return nullptr;
     719             :     }
     720             : 
     721           0 :     snprintf(psInfo->pszBuf, psInfo->nBufSize, "%10d%10d", psTol->nIndex,
     722             :              psTol->nFlag);
     723           0 :     AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
     724             :                       AVCFileTOL, psTol->dValue);
     725             : 
     726           0 :     return psInfo->pszBuf;
     727             : }
     728             : 
     729             : /*=====================================================================
     730             :                             PRJ stuff
     731             :  =====================================================================*/
     732             : 
     733             : /**********************************************************************
     734             :  *                          AVCE00GenPrj()
     735             :  *
     736             :  * Generate the next line of an E00 PRJ (Projection) section.
     737             :  *
     738             :  * This function should be called once with bCont=FALSE to get the
     739             :  * first E00 line for the current PRJ, and then call with bCont=TRUE
     740             :  * to get all the other lines for this PRJ.
     741             :  *
     742             :  * The function returns nullptr when there are no more lines to generate
     743             :  * for this PRJ entry.
     744             :  **********************************************************************/
     745           0 : const char *AVCE00GenPrj(AVCE00GenInfo *psInfo, char **papszPrj, GBool bCont)
     746             : {
     747           0 :     if (bCont == FALSE)
     748             :     {
     749             :         /*---------------------------------------------------------
     750             :          * Initialize the psInfo structure with info about the
     751             :          * current PRJ. (numItems = Number of lines to output)
     752             :          *--------------------------------------------------------*/
     753           0 :         psInfo->iCurItem = 0;
     754           0 :         psInfo->numItems = CSLCount(papszPrj) * 2;
     755             :     }
     756             : 
     757           0 :     if (psInfo->iCurItem < psInfo->numItems)
     758             :     {
     759             :         /*---------------------------------------------------------
     760             :          * Return the next PRJ section line.  Note that every
     761             :          * second line of the output is only a "~".
     762             :          *--------------------------------------------------------*/
     763             : 
     764           0 :         if (psInfo->iCurItem % 2 == 0)
     765             :         {
     766             :             /*-----------------------------------------------------
     767             :              * In theory we should split lines longer than 80 chars on
     768             :              * several lines, but I won't do it for now since I never
     769             :              * saw any projection line longer than 80 chars.
     770             :              *----------------------------------------------------*/
     771           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize, "%s",
     772           0 :                      papszPrj[psInfo->iCurItem / 2]);
     773             :         }
     774             :         else
     775             :         {
     776             :             /*-----------------------------------------------------
     777             :              * Every second line in a PRJ section contains only a "~",
     778             :              * this is a way to tell that the previous line was complete.
     779             :              *----------------------------------------------------*/
     780           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize, "~");
     781             :         }
     782             : 
     783           0 :         psInfo->iCurItem++;
     784             :     }
     785             :     else
     786             :     {
     787             :         /* No more lines to generate for this PRJ.
     788             :          */
     789           0 :         return nullptr;
     790             :     }
     791             : 
     792           0 :     return psInfo->pszBuf;
     793             : }
     794             : 
     795             : /*=====================================================================
     796             :                             TXT stuff
     797             :  =====================================================================*/
     798             : 
     799             : /**********************************************************************
     800             :  *                          AVCE00GenTxt()
     801             :  *
     802             :  * Generate the next line of an E00 TXT (Annotation) entry.
     803             :  *
     804             :  * This function should be called once with bCont=FALSE to get the
     805             :  * first E00 line for the current TXT, and then call with bCont=TRUE
     806             :  * to get all the other lines for this TXT.
     807             :  *
     808             :  * The function returns nullptr when there are no more lines to generate
     809             :  * for this TXT entry.
     810             :  **********************************************************************/
     811           0 : const char *AVCE00GenTxt(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
     812             : {
     813             :     int numFixedLines;
     814             : 
     815             :     /* numFixedLines is the number of lines to generate before the line(s)
     816             :      * with the text string
     817             :      */
     818           0 :     if (psInfo->nPrecision == AVC_SINGLE_PREC)
     819           0 :         numFixedLines = 4;
     820             :     else
     821           0 :         numFixedLines = 6;
     822             : 
     823           0 :     if (bCont == FALSE)
     824             :     {
     825             :         /*-------------------------------------------------------------
     826             :          * Initialize the psInfo structure with info about the
     827             :          * current TXT. (numItems = Number of lines excluding header)
     828             :          *------------------------------------------------------------*/
     829           0 :         psInfo->iCurItem = 0;
     830           0 :         psInfo->numItems = numFixedLines + ((psTxt->numChars - 1) / 80 + 1);
     831             : 
     832             :         /* And return the TXT header line.
     833             :          */
     834           0 :         snprintf(psInfo->pszBuf, psInfo->nBufSize, "%10d%10d%10d%10d%10d",
     835           0 :                  psTxt->nLevel, psTxt->numVerticesLine - 1,
     836             :                  psTxt->numVerticesArrow, psTxt->nSymbol, psTxt->numChars);
     837             :     }
     838           0 :     else if (psInfo->iCurItem < psInfo->numItems &&
     839           0 :              psInfo->iCurItem < numFixedLines - 1)
     840             :     {
     841             :         /*-------------------------------------------------------------
     842             :          * Return next line of coordinates... start by placing the coord.
     843             :          * values in the order that they should appear, and then generate the
     844             :          * current line
     845             :          * (This is a little bit less efficient, but will give much easier
     846             :          *  code to read ;-)
     847             :          *------------------------------------------------------------*/
     848           0 :         double dXY[15] = {0.0};
     849             :         int i, nFirstValue, numValuesPerLine;
     850             : 
     851           0 :         dXY[14] = psTxt->dHeight;
     852             : 
     853             :         /* note that the first vertex in the vertices list is never exported
     854             :          */
     855           0 :         for (i = 0; i < 4 && i < (psTxt->numVerticesLine - 1); i++)
     856             :         {
     857           0 :             dXY[i] = psTxt->pasVertices[i + 1].x;
     858           0 :             dXY[i + 4] = psTxt->pasVertices[i + 1].y;
     859             :         }
     860           0 :         for (i = 0; i < 3 && i < ABS(psTxt->numVerticesArrow); i++)
     861             :         {
     862           0 :             dXY[i + 8] = psTxt->pasVertices[i + psTxt->numVerticesLine].x;
     863           0 :             dXY[i + 11] = psTxt->pasVertices[i + psTxt->numVerticesLine].y;
     864             :         }
     865             : 
     866             :         /* OK, now that we prepared the coord. values, return the next line
     867             :          * of coordinates.  The only difference between double and single
     868             :          * precision is the number of coordinates per line.
     869             :          */
     870           0 :         if (psInfo->nPrecision != AVC_DOUBLE_PREC)
     871             :         {
     872             :             /* Single precision
     873             :              */
     874           0 :             numValuesPerLine = 5;
     875             :         }
     876             :         else
     877             :         {
     878             :             /* Double precision
     879             :              */
     880           0 :             numValuesPerLine = 3;
     881             :         }
     882             : 
     883           0 :         nFirstValue = psInfo->iCurItem * numValuesPerLine;
     884           0 :         psInfo->pszBuf[0] = '\0';
     885           0 :         for (i = 0; i < numValuesPerLine; i++)
     886             :         {
     887           0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,
     888             :                               psInfo->nPrecision, AVCFileTXT,
     889           0 :                               dXY[nFirstValue + i]);
     890             :         }
     891             : 
     892           0 :         psInfo->iCurItem++;
     893             :     }
     894           0 :     else if (psInfo->iCurItem < psInfo->numItems &&
     895           0 :              psInfo->iCurItem == numFixedLines - 1)
     896             :     {
     897             :         /*-------------------------------------------------------------
     898             :          * Line with a -1.000E+02 value, ALWAYS SINGLE PRECISION !!!
     899             :          *------------------------------------------------------------*/
     900           0 :         psInfo->pszBuf[0] = '\0';
     901           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, AVC_SINGLE_PREC,
     902           0 :                           AVCFileTXT, psTxt->f_1e2);
     903           0 :         psInfo->iCurItem++;
     904             :     }
     905           0 :     else if (psInfo->iCurItem < psInfo->numItems &&
     906           0 :              psInfo->iCurItem >= numFixedLines)
     907             :     {
     908             :         /*-------------------------------------------------------------
     909             :          * Last line, contains the text string
     910             :          * Strings longer than 80 chars have to be in 80 chars chunks
     911             :          *------------------------------------------------------------*/
     912             :         int numLines, iLine;
     913           0 :         numLines = (psTxt->numChars - 1) / 80 + 1;
     914           0 :         iLine = numLines - (psInfo->numItems - psInfo->iCurItem);
     915             : 
     916           0 :         if ((int)strlen((char *)psTxt->pszText) > (iLine * 80))
     917           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize, "%-.80s",
     918           0 :                      psTxt->pszText + (iLine * 80));
     919             :         else
     920           0 :             psInfo->pszBuf[0] = '\0';
     921             : 
     922           0 :         psInfo->iCurItem++;
     923             :     }
     924             :     else
     925             :     {
     926             :         /* No more lines to generate for this TXT.
     927             :          */
     928           0 :         return nullptr;
     929             :     }
     930             : 
     931           0 :     return psInfo->pszBuf;
     932             : }
     933             : 
     934             : /*=====================================================================
     935             :                             TX6 stuff
     936             :  =====================================================================*/
     937             : 
     938             : /**********************************************************************
     939             :  *                          AVCE00GenTx6()
     940             :  *
     941             :  * Generate the next line of an E00 TX6 (Annotation) entry.
     942             :  *
     943             :  * This function should be called once with bCont=FALSE to get the
     944             :  * first E00 line for the current TX6, and then call with bCont=TRUE
     945             :  * to get all the other lines for this TX6.
     946             :  *
     947             :  * Note that E00 files can also contain TX7 sections, they seem identical
     948             :  * to TX6 sections, except for one value in each entry, and it was
     949             :  * impossible to find where this value comes from... so we will always
     950             :  * generate TX6 sections and not bother with TX7.
     951             :  *
     952             :  * The function returns nullptr when there are no more lines to generate
     953             :  * for this TX6 entry.
     954             :  **********************************************************************/
     955           0 : const char *AVCE00GenTx6(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
     956             : {
     957           0 :     if (bCont == FALSE)
     958             :     {
     959             :         /*-------------------------------------------------------------
     960             :          * Initialize the psInfo structure with info about the
     961             :          * current TX6. (numItems = Number of lines excluding header)
     962             :          *------------------------------------------------------------*/
     963           0 :         psInfo->iCurItem = 0;
     964           0 :         psInfo->numItems = 8 + psTxt->numVerticesLine +
     965           0 :                            ABS(psTxt->numVerticesArrow) +
     966           0 :                            ((psTxt->numChars - 1) / 80 + 1);
     967             : 
     968             :         /* And return the TX6 header line.
     969             :          */
     970           0 :         snprintf(psInfo->pszBuf, psInfo->nBufSize,
     971             :                  "%10d%10d%10d%10d%10d%10d%10d", psTxt->nUserId, psTxt->nLevel,
     972             :                  psTxt->numVerticesLine, psTxt->numVerticesArrow,
     973             :                  psTxt->nSymbol, psTxt->n28, psTxt->numChars);
     974             :     }
     975           0 :     else if (psInfo->iCurItem < psInfo->numItems && psInfo->iCurItem < 6)
     976             :     {
     977             :         /*-------------------------------------------------------------
     978             :          * Text Justification stuff... 2 sets of 20 int16 values.
     979             :          *------------------------------------------------------------*/
     980             :         GInt16 *pValue;
     981             : 
     982           0 :         if (psInfo->iCurItem < 3)
     983           0 :             pValue = psTxt->anJust2 + psInfo->iCurItem * 7;
     984             :         else
     985           0 :             pValue = psTxt->anJust1 + (psInfo->iCurItem - 3) * 7;
     986             : 
     987           0 :         if (psInfo->iCurItem == 2 || psInfo->iCurItem == 5)
     988             :         {
     989           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize,
     990           0 :                      "%10d%10d%10d%10d%10d%10d", pValue[0], pValue[1],
     991           0 :                      pValue[2], pValue[3], pValue[4], pValue[5]);
     992             :         }
     993             :         else
     994             :         {
     995             :             /* coverity[overrun-local] */
     996           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize,
     997           0 :                      "%10d%10d%10d%10d%10d%10d%10d", pValue[0], pValue[1],
     998           0 :                      pValue[2], pValue[3], pValue[4], pValue[5], pValue[6]);
     999             :         }
    1000             : 
    1001           0 :         psInfo->iCurItem++;
    1002             :     }
    1003           0 :     else if (psInfo->iCurItem < psInfo->numItems && psInfo->iCurItem == 6)
    1004             :     {
    1005             :         /*-------------------------------------------------------------
    1006             :          * Line with a -1.000E+02 value, ALWAYS SINGLE PRECISION !!!
    1007             :          *------------------------------------------------------------*/
    1008           0 :         psInfo->pszBuf[0] = '\0';
    1009           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, AVC_SINGLE_PREC,
    1010           0 :                           AVCFileTX6, psTxt->f_1e2);
    1011           0 :         psInfo->iCurItem++;
    1012             :     }
    1013           0 :     else if (psInfo->iCurItem < psInfo->numItems && psInfo->iCurItem == 7)
    1014             :     {
    1015             :         /*-------------------------------------------------------------
    1016             :          * Line with 3 values, 1st value is probably text height.
    1017             :          *------------------------------------------------------------*/
    1018           0 :         psInfo->pszBuf[0] = '\0';
    1019           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
    1020             :                           AVCFileTX6, psTxt->dHeight);
    1021           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
    1022             :                           AVCFileTX6, psTxt->dV2);
    1023           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
    1024             :                           AVCFileTX6, psTxt->dV3);
    1025           0 :         psInfo->iCurItem++;
    1026             :     }
    1027           0 :     else if (psInfo->iCurItem <
    1028           0 :              psInfo->numItems - ((psTxt->numChars - 1) / 80 + 1))
    1029             :     {
    1030             :         /*-------------------------------------------------------------
    1031             :          * One line for each pair of X,Y coordinates
    1032             :          *------------------------------------------------------------*/
    1033           0 :         psInfo->pszBuf[0] = '\0';
    1034             : 
    1035           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
    1036             :                           AVCFileTX6,
    1037           0 :                           psTxt->pasVertices[psInfo->iCurItem - 8].x);
    1038           0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision,
    1039             :                           AVCFileTX6,
    1040           0 :                           psTxt->pasVertices[psInfo->iCurItem - 8].y);
    1041             : 
    1042           0 :         psInfo->iCurItem++;
    1043             :     }
    1044           0 :     else if (psInfo->iCurItem < psInfo->numItems /* &&
    1045             :              psInfo->iCurItem >= psInfo->numItems-((psTxt->numChars-1)/80 + 1) */ )
    1046             :     {
    1047             :         /*-------------------------------------------------------------
    1048             :          * Last line, contains the text string
    1049             :          * Strings longer than 80 chars have to be in 80 chars chunks
    1050             :          *------------------------------------------------------------*/
    1051             :         int numLines, iLine;
    1052           0 :         numLines = (psTxt->numChars - 1) / 80 + 1;
    1053           0 :         iLine = numLines - (psInfo->numItems - psInfo->iCurItem);
    1054             : 
    1055           0 :         if ((int)strlen((char *)psTxt->pszText) > (iLine * 80))
    1056           0 :             snprintf(psInfo->pszBuf, psInfo->nBufSize, "%-.80s",
    1057           0 :                      psTxt->pszText + (iLine * 80));
    1058             :         else
    1059           0 :             psInfo->pszBuf[0] = '\0';
    1060             : 
    1061           0 :         psInfo->iCurItem++;
    1062             :     }
    1063             :     else
    1064             :     {
    1065             :         /* No more lines to generate for this TX6.
    1066             :          */
    1067           0 :         return nullptr;
    1068             :     }
    1069             : 
    1070           0 :     return psInfo->pszBuf;
    1071             : }
    1072             : 
    1073             : /*=====================================================================
    1074             :                             RXP stuff
    1075             :  =====================================================================*/
    1076             : 
    1077             : /**********************************************************************
    1078             :  *                          AVCE00GenRxp()
    1079             :  *
    1080             :  * Generate the next line of an E00 RXP entry (RXPs are related to regions).
    1081             :  *
    1082             :  * This function should be called once with bCont=FALSE to get the
    1083             :  * first E00 line for the current RXP, and then call with bCont=TRUE
    1084             :  * to get all the other lines for this RXP.
    1085             :  *
    1086             :  * The function returns nullptr when there are no more lines to generate
    1087             :  * for this RXP entry.
    1088             :  **********************************************************************/
    1089           0 : const char *AVCE00GenRxp(AVCE00GenInfo *psInfo, AVCRxp *psRxp, GBool bCont)
    1090             : {
    1091           0 :     if (bCont == TRUE)
    1092             :     {
    1093             :         /*---------------------------------------------------------
    1094             :          * RXP entries are only 1 line, we support the bCont flag
    1095             :          * only for compatibility with the other AVCE00Gen*() functions.
    1096             :          *--------------------------------------------------------*/
    1097           0 :         return nullptr;
    1098             :     }
    1099             : 
    1100           0 :     snprintf(psInfo->pszBuf, psInfo->nBufSize, "%10d%10d", psRxp->n1,
    1101             :              psRxp->n2);
    1102             : 
    1103           0 :     return psInfo->pszBuf;
    1104             : }
    1105             : 
    1106             : /*=====================================================================
    1107             :                             TABLE stuff
    1108             :  =====================================================================*/
    1109             : 
    1110             : /**********************************************************************
    1111             :  *                          AVCE00GenTableHdr()
    1112             :  *
    1113             :  * Generate the next line of an E00 Table header.
    1114             :  *
    1115             :  * This function should be called once with bCont=FALSE to get the
    1116             :  * first E00 line for the current table header, and then call with
    1117             :  * bCont=TRUE to get all the other lines.
    1118             :  *
    1119             :  * The function returns nullptr when there are no more lines to generate.
    1120             :  **********************************************************************/
    1121           0 : const char *AVCE00GenTableHdr(AVCE00GenInfo *psInfo, AVCTableDef *psDef,
    1122             :                               GBool bCont)
    1123             : {
    1124           0 :     if (bCont == FALSE)
    1125             :     {
    1126             :         int nRecSize;
    1127             :         /* Initialize the psInfo structure with info about the
    1128             :          * current Table Header
    1129             :          */
    1130           0 :         psInfo->iCurItem = 0;
    1131           0 :         psInfo->numItems = psDef->numFields;
    1132             : 
    1133           0 :         nRecSize = psDef->nRecSize;
    1134             : #ifdef AVC_MAP_TYPE40_TO_DOUBLE
    1135             :         {
    1136             :             /* Adjust Table record size if we're remapping type 40 fields */
    1137             :             int i;
    1138             :             for (i = 0; i < psDef->numFields; i++)
    1139             :             {
    1140             :                 if (psDef->pasFieldDef[i].nType1 * 10 == AVC_FT_FIXNUM &&
    1141             :                     psDef->pasFieldDef[i].nSize > 8)
    1142             :                 {
    1143             :                     nRecSize -= psDef->pasFieldDef[i].nSize;
    1144             :                     nRecSize += 8;
    1145             :                 }
    1146             :             }
    1147             :             nRecSize = ((nRecSize + 1) / 2) * 2;
    1148             :         }
    1149             : #endif
    1150             : 
    1151             :         /* And return the header's header line(!).
    1152             :          */
    1153           0 :         snprintf(psInfo->pszBuf, psInfo->nBufSize, "%-32.32s%s%4d%4d%4d%10d",
    1154           0 :                  psDef->szTableName, psDef->szExternal, psDef->numFields,
    1155           0 :                  psDef->numFields, nRecSize, psDef->numRecords);
    1156             :     }
    1157           0 :     else if (psInfo->iCurItem < psInfo->numItems)
    1158             :     {
    1159             :         int nSize, nType, nOffset;
    1160             : 
    1161           0 :         nSize = psDef->pasFieldDef[psInfo->iCurItem].nSize;
    1162           0 :         nType = psDef->pasFieldDef[psInfo->iCurItem].nType1 * 10;
    1163           0 :         nOffset = psDef->pasFieldDef[psInfo->iCurItem].nOffset;
    1164             : 
    1165             : #ifdef AVC_MAP_TYPE40_TO_DOUBLE
    1166             :         /* Type 40 fields with more than 12 digits written to E00 by Arc/Info
    1167             :          * will lose some digits of precision (and we starts losing them at 8
    1168             :          * with the way AVC lib writes type 40).  This (optional) hack will
    1169             :          * remap type 40 fields with more than 8 digits to double precision
    1170             :          * floats which can carry up to 18 digits of precision.  (bug 599)
    1171             :          */
    1172             :         if (nType == AVC_FT_FIXNUM && nSize > 8)
    1173             :         {
    1174             :             /* Remap to double-precision float */
    1175             :             nType = AVC_FT_BINFLOAT;
    1176             :             nSize = 8;
    1177             :         }
    1178             : 
    1179             :         /* Adjust field offset if this field is preceded by any type40 fields
    1180             :          * that were remapped.
    1181             :          */
    1182             :         {
    1183             :             int i;
    1184             :             for (i = 0; i < psInfo->iCurItem; i++)
    1185             :             {
    1186             :                 if (psDef->pasFieldDef[i].nType1 * 10 == AVC_FT_FIXNUM &&
    1187             :                     psDef->pasFieldDef[i].nSize > 8)
    1188             :                 {
    1189             :                     nOffset -= psDef->pasFieldDef[i].nSize;
    1190             :                     nOffset += 8;
    1191             :                 }
    1192             :             }
    1193             :         }
    1194             : #endif
    1195             :         /* Return next Field definition line
    1196             :          */
    1197           0 :         snprintf(psInfo->pszBuf, psInfo->nBufSize,
    1198             :                  "%-16.16s%3d%2d%4d%1d%2d%4d%2d%3d%2d%4d%4d%2d%-16.16s%4d-",
    1199           0 :                  psDef->pasFieldDef[psInfo->iCurItem].szName, nSize,
    1200           0 :                  psDef->pasFieldDef[psInfo->iCurItem].v2, nOffset,
    1201           0 :                  psDef->pasFieldDef[psInfo->iCurItem].v4,
    1202           0 :                  psDef->pasFieldDef[psInfo->iCurItem].v5,
    1203           0 :                  psDef->pasFieldDef[psInfo->iCurItem].nFmtWidth,
    1204           0 :                  psDef->pasFieldDef[psInfo->iCurItem].nFmtPrec, nType,
    1205           0 :                  psDef->pasFieldDef[psInfo->iCurItem].v10,
    1206           0 :                  psDef->pasFieldDef[psInfo->iCurItem].v11,
    1207           0 :                  psDef->pasFieldDef[psInfo->iCurItem].v12,
    1208           0 :                  psDef->pasFieldDef[psInfo->iCurItem].v13,
    1209           0 :                  psDef->pasFieldDef[psInfo->iCurItem].szAltName,
    1210           0 :                  psDef->pasFieldDef[psInfo->iCurItem].nIndex);
    1211             : 
    1212           0 :         psInfo->iCurItem++;
    1213             :     }
    1214             :     else
    1215             :     {
    1216             :         /* No more lines to generate.
    1217             :          */
    1218           0 :         return nullptr;
    1219             :     }
    1220             : 
    1221           0 :     return psInfo->pszBuf;
    1222             : }
    1223             : 
    1224             : /**********************************************************************
    1225             :  *                          AVCE00GenTableRec()
    1226             :  *
    1227             :  * Generate the next line of an E00 Table Data Record.
    1228             :  *
    1229             :  * This function should be called once with bCont=FALSE to get the
    1230             :  * first E00 line for the current table record, and then call with
    1231             :  * bCont=TRUE to get all the other lines.
    1232             :  *
    1233             :  * The function returns nullptr when there are no more lines to generate.
    1234             :  **********************************************************************/
    1235           0 : const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
    1236             :                               AVCFieldInfo *pasDef, AVCField *pasFields,
    1237             :                               GBool bCont)
    1238             : {
    1239             :     int i, nSize, nType, nLen;
    1240             :     char *pszBuf2;
    1241             : 
    1242           0 :     if (bCont == FALSE)
    1243             :     {
    1244             :         /*-------------------------------------------------------------
    1245             :          * Initialize the psInfo structure to be ready to process this
    1246             :          * new Table Record
    1247             :          *------------------------------------------------------------*/
    1248           0 :         psInfo->iCurItem = 0;
    1249             : #ifdef AVC_MAP_TYPE40_TO_DOUBLE
    1250             :         psInfo->numItems = _AVCE00ComputeRecSize(numFields, pasDef, TRUE);
    1251             : #else
    1252           0 :         psInfo->numItems = _AVCE00ComputeRecSize(numFields, pasDef, FALSE);
    1253             : #endif
    1254             : 
    1255             :         /*-------------------------------------------------------------
    1256             :          * First, we need to make sure that the output buffer is big
    1257             :          * enough to hold the whole record, plus 81 chars to hold
    1258             :          * the line that we'll return to the caller.
    1259             :          *------------------------------------------------------------*/
    1260           0 :         nSize = psInfo->numItems + 1 + 81;
    1261             : 
    1262           0 :         if (psInfo->nBufSize < nSize)
    1263             :         {
    1264           0 :             psInfo->pszBuf =
    1265           0 :                 (char *)CPLRealloc(psInfo->pszBuf, nSize * sizeof(char));
    1266           0 :             psInfo->nBufSize = nSize;
    1267             :         }
    1268             : 
    1269             :         /*-------------------------------------------------------------
    1270             :          * Generate the whole record now, and we'll return it to the
    1271             :          * caller by chunks of 80 chars.
    1272             :          * The first 80 chars of the buffer will be used to return
    1273             :          * one line at a time, and the rest of the buffer is used to
    1274             :          * hold the whole record.
    1275             :          *------------------------------------------------------------*/
    1276           0 :         pszBuf2 = psInfo->pszBuf + 81;
    1277             : 
    1278           0 :         for (i = 0; i < numFields; i++)
    1279             :         {
    1280           0 :             nType = pasDef[i].nType1 * 10;
    1281           0 :             nSize = pasDef[i].nSize;
    1282             : 
    1283           0 :             if (nType == AVC_FT_DATE || nType == AVC_FT_CHAR ||
    1284             :                 nType == AVC_FT_FIXINT)
    1285             :             {
    1286           0 :                 memcpy(pszBuf2, pasFields[i].pszStr, nSize * sizeof(char));
    1287           0 :                 pszBuf2 += nSize;
    1288             :             }
    1289             : #ifdef AVC_MAP_TYPE40_TO_DOUBLE
    1290             :             /* See explanation in AVCE00GenTableHdr() about this hack to remap
    1291             :              * type 40 fields to double precision floats.
    1292             :              */
    1293             :             else if (nType == AVC_FT_FIXNUM && nSize > 8)
    1294             :             {
    1295             :                 pszBuf2[0] = '\0';
    1296             :                 /* NOTE: The E00 representation for a binary float is
    1297             :                  * defined by its binary size, not by the coverage's
    1298             :                  * precision.
    1299             :                  */
    1300             :                 nLen = AVCPrintRealValue(
    1301             :                     pszBuf2, psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf),
    1302             :                     AVC_DOUBLE_PREC, AVCFileTABLE,
    1303             :                     CPLAtof((char *)pasFields[i].pszStr));
    1304             :                 pszBuf2 += nLen;
    1305             :             }
    1306             : #endif
    1307           0 :             else if (nType == AVC_FT_FIXNUM)
    1308             :             {
    1309             :                 /* TYPE 40 attributes are stored with 1 byte per digit
    1310             :                  * in binary format, and as single precision floats in
    1311             :                  * E00 tables, even in double precision coverages.
    1312             :                  */
    1313           0 :                 pszBuf2[0] = '\0';
    1314           0 :                 nLen = AVCPrintRealValue(
    1315           0 :                     pszBuf2, psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf),
    1316             :                     AVC_SINGLE_PREC, AVCFileTABLE,
    1317           0 :                     CPLAtof((char *)pasFields[i].pszStr));
    1318           0 :                 pszBuf2 += nLen;
    1319             :             }
    1320           0 :             else if (nType == AVC_FT_BININT && nSize == 4)
    1321             :             {
    1322           0 :                 snprintf(pszBuf2, psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf),
    1323           0 :                          "%11d", pasFields[i].nInt32);
    1324           0 :                 pszBuf2 += 11;
    1325             :             }
    1326           0 :             else if (nType == AVC_FT_BININT && nSize == 2)
    1327             :             {
    1328           0 :                 snprintf(pszBuf2, psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf),
    1329           0 :                          "%6d", pasFields[i].nInt16);
    1330           0 :                 pszBuf2 += 6;
    1331             :             }
    1332           0 :             else if (nType == AVC_FT_BINFLOAT && nSize == 4)
    1333             :             {
    1334           0 :                 pszBuf2[0] = '\0';
    1335             :                 /* NOTE: The E00 representation for a binary float is
    1336             :                  * defined by its binary size, not by the coverage's
    1337             :                  * precision.
    1338             :                  */
    1339           0 :                 nLen = AVCPrintRealValue(
    1340           0 :                     pszBuf2, psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf),
    1341           0 :                     AVC_SINGLE_PREC, AVCFileTABLE, pasFields[i].fFloat);
    1342           0 :                 pszBuf2 += nLen;
    1343             :             }
    1344           0 :             else if (nType == AVC_FT_BINFLOAT && nSize == 8)
    1345             :             {
    1346           0 :                 pszBuf2[0] = '\0';
    1347             :                 /* NOTE: The E00 representation for a binary float is
    1348             :                  * defined by its binary size, not by the coverage's
    1349             :                  * precision.
    1350             :                  */
    1351           0 :                 nLen = AVCPrintRealValue(
    1352           0 :                     pszBuf2, psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf),
    1353           0 :                     AVC_DOUBLE_PREC, AVCFileTABLE, pasFields[i].dDouble);
    1354           0 :                 pszBuf2 += nLen;
    1355             :             }
    1356             :             else
    1357             :             {
    1358             :                 /*-----------------------------------------------------
    1359             :                  * Hummm... unsupported field type...
    1360             :                  *----------------------------------------------------*/
    1361           0 :                 CPLError(CE_Failure, CPLE_NotSupported,
    1362             :                          "Unsupported field type: (type=%d, size=%d)", nType,
    1363             :                          nSize);
    1364           0 :                 return nullptr;
    1365             :             }
    1366             :         }
    1367             : 
    1368           0 :         *pszBuf2 = '\0';
    1369             : 
    1370             :         /* Make sure that we remove any embedded NUL characters from the
    1371             :          * data line before returning it, otherwise we may be accidentally
    1372             :          * truncating results.
    1373             :          */
    1374           0 :         while (--pszBuf2 >= psInfo->pszBuf + 81)
    1375             :         {
    1376           0 :             if (*pszBuf2 == '\0')
    1377             :             {
    1378           0 :                 *pszBuf2 = ' ';
    1379             :             }
    1380             :         }
    1381             :     }
    1382             : 
    1383           0 :     if (psInfo->iCurItem < psInfo->numItems)
    1384             :     {
    1385             :         /*-------------------------------------------------------------
    1386             :          * Return the next 80 chars chunk.
    1387             :          * The first 80 chars of the buffer is used to return
    1388             :          * one line at a time, and the rest of the buffer (chars 81+)
    1389             :          * is used to hold the whole record.
    1390             :          *------------------------------------------------------------*/
    1391           0 :         nLen = psInfo->numItems - psInfo->iCurItem;
    1392             : 
    1393           0 :         if (nLen > 80)
    1394           0 :             nLen = 80;
    1395             : 
    1396           0 :         strncpy(psInfo->pszBuf, psInfo->pszBuf + (81 + psInfo->iCurItem), nLen);
    1397           0 :         psInfo->pszBuf[nLen] = '\0';
    1398             : 
    1399           0 :         psInfo->iCurItem += nLen;
    1400             : 
    1401             :         /*-------------------------------------------------------------
    1402             :          * Arc/Info removes spaces at the end of the lines... let's
    1403             :          * remove them as well since it can reduce the E00 file size.
    1404             :          *------------------------------------------------------------*/
    1405           0 :         nLen--;
    1406           0 :         while (nLen >= 0 && psInfo->pszBuf[nLen] == ' ')
    1407             :         {
    1408           0 :             psInfo->pszBuf[nLen] = '\0';
    1409           0 :             nLen--;
    1410             :         }
    1411             :     }
    1412             :     else
    1413             :     {
    1414             :         /* No more lines to generate.
    1415             :          */
    1416           0 :         return nullptr;
    1417             :     }
    1418             : 
    1419           0 :     return psInfo->pszBuf;
    1420             : }

Generated by: LCOV version 1.14