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

Generated by: LCOV version 1.14