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: 2025-01-18 12:42:00 Functions: 2 17 11.8 %

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

Generated by: LCOV version 1.14