LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mitab - mitab_middatafile.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 109 121 90.1 %
Date: 2024-05-05 22:37:24 Functions: 19 19 100.0 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  *
       3             :  * Name:     mitab_datfile.cpp
       4             :  * Project:  MapInfo TAB Read/Write library
       5             :  * Language: C++
       6             :  * Purpose:  Implementation of the MIDDATAFile class used to handle
       7             :  *           reading/writing of the MID/MIF files
       8             :  * Author:   Stephane Villeneuve, stephane.v@videotron.ca
       9             :  *
      10             :  **********************************************************************
      11             :  * Copyright (c) 1999, 2000, Stephane Villeneuve
      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             : #include "cpl_port.h"
      33             : #include "mitab.h"
      34             : 
      35             : #include <cstdarg>
      36             : #include <cstddef>
      37             : 
      38             : #include "cpl_conv.h"
      39             : #include "cpl_csv.h"
      40             : #include "cpl_error.h"
      41             : #include "cpl_string.h"
      42             : #include "cpl_vsi.h"
      43             : #include "mitab_priv.h"
      44             : 
      45             : /*=====================================================================
      46             :  *                      class MIDDATAFile
      47             :  *
      48             :  *====================================================================*/
      49             : 
      50        1130 : MIDDATAFile::MIDDATAFile(const char *pszEncoding)
      51             :     : m_fp(nullptr), m_pszDelimiter("\t"),  // Encom 2003 (was NULL).
      52             :       m_pszFname(nullptr), m_eAccessMode(TABRead), m_dfXMultiplier(1.0),
      53             :       m_dfYMultiplier(1.0), m_dfXDisplacement(0.0), m_dfYDisplacement(0.0),
      54        1130 :       m_bEof(FALSE), m_osEncoding(pszEncoding)
      55             : {
      56        1130 : }
      57             : 
      58        1130 : MIDDATAFile::~MIDDATAFile()
      59             : {
      60        1130 :     Close();
      61        1130 : }
      62             : 
      63        2080 : void MIDDATAFile::SaveLine(const char *pszLine)
      64             : {
      65        2080 :     if (pszLine == nullptr)
      66             :     {
      67           0 :         m_osSavedLine.clear();
      68             :     }
      69             :     else
      70             :     {
      71        2080 :         m_osSavedLine = pszLine;
      72             :     }
      73        2080 : }
      74             : 
      75        2061 : const char *MIDDATAFile::GetSavedLine()
      76             : {
      77        2061 :     return m_osSavedLine.c_str();
      78             : }
      79             : 
      80        1130 : int MIDDATAFile::Open(const char *pszFname, const char *pszAccess)
      81             : {
      82        1130 :     if (m_fp)
      83             :     {
      84           0 :         return -1;
      85             :     }
      86             : 
      87             :     // Validate access mode and make sure we use Text access.
      88        1130 :     if (STARTS_WITH_CI(pszAccess, "r"))
      89             :     {
      90         962 :         m_eAccessMode = TABRead;
      91         962 :         pszAccess = "rt";
      92             :     }
      93         168 :     else if (STARTS_WITH_CI(pszAccess, "w"))
      94             :     {
      95         168 :         m_eAccessMode = TABWrite;
      96         168 :         pszAccess = "wt";
      97             :     }
      98             :     else
      99             :     {
     100           0 :         return -1;
     101             :     }
     102             : 
     103             :     // Open file for reading.
     104        1130 :     m_pszFname = CPLStrdup(pszFname);
     105        1130 :     m_fp = VSIFOpenL(m_pszFname, pszAccess);
     106             : 
     107        1130 :     if (m_fp == nullptr)
     108             :     {
     109           4 :         CPLFree(m_pszFname);
     110           4 :         m_pszFname = nullptr;
     111           4 :         return -1;
     112             :     }
     113             : 
     114        1126 :     SetEof(FALSE);
     115        1126 :     return 0;
     116             : }
     117             : 
     118         971 : int MIDDATAFile::Rewind()
     119             : {
     120         971 :     if (m_fp == nullptr || m_eAccessMode == TABWrite)
     121           0 :         return -1;
     122             : 
     123             :     else
     124             :     {
     125         971 :         VSIRewindL(m_fp);
     126         971 :         SetEof(FALSE);
     127             :     }
     128         971 :     return 0;
     129             : }
     130             : 
     131        2256 : int MIDDATAFile::Close()
     132             : {
     133        2256 :     if (m_fp == nullptr)
     134        1130 :         return 0;
     135             : 
     136             :     // Close file
     137        1126 :     VSIFCloseL(m_fp);
     138        1126 :     m_fp = nullptr;
     139             : 
     140             :     // clear readline buffer.
     141        1126 :     CPLReadLineL(nullptr);
     142             : 
     143        1126 :     CPLFree(m_pszFname);
     144        1126 :     m_pszFname = nullptr;
     145             : 
     146        1126 :     return 0;
     147             : }
     148             : 
     149       49987 : const char *MIDDATAFile::GetLine()
     150             : {
     151       49987 :     if (m_eAccessMode != TABRead)
     152             :     {
     153           0 :         CPLAssert(false);
     154             :         return nullptr;
     155             :     }
     156             : 
     157             :     static const int nMaxLineLength =
     158       49987 :         atoi(CPLGetConfigOption("MITAB_MAX_LINE_LENGTH", "1000000"));
     159       49987 :     const char *pszLine = CPLReadLine2L(m_fp, nMaxLineLength, nullptr);
     160             : 
     161       49987 :     if (pszLine == nullptr)
     162             :     {
     163         609 :         if (strstr(CPLGetLastErrorMsg(),
     164         609 :                    "Maximum number of characters allowed reached"))
     165             :         {
     166           0 :             CPLError(
     167             :                 CE_Failure, CPLE_AppDefined,
     168             :                 "Maximum number of characters allowed reached. "
     169             :                 "You can set the MITAB_MAX_LINE_LENGTH configuration option "
     170             :                 "to the desired number of bytes (or -1 for unlimited)");
     171             :         }
     172         609 :         SetEof(TRUE);
     173         609 :         m_osLastRead.clear();
     174             :     }
     175             :     else
     176             :     {
     177             :         // Skip leading spaces and tabs except if the delimiter is tab.
     178       84009 :         while (*pszLine == ' ' || (*m_pszDelimiter != '\t' && *pszLine == '\t'))
     179       34631 :             pszLine++;
     180             : 
     181       49378 :         m_osLastRead = pszLine;
     182             :     }
     183             : 
     184             : #if DEBUG_VERBOSE
     185             :     if (pszLine)
     186             :         CPLDebug("MITAB", "pszLine: %s", pszLine);
     187             : #endif
     188             : 
     189       49987 :     return pszLine;
     190             : }
     191             : 
     192       31992 : const char *MIDDATAFile::GetLastLine()
     193             : {
     194             :     // Return NULL if EOF.
     195       31992 :     if (GetEof())
     196             :     {
     197         888 :         return nullptr;
     198             :     }
     199       31104 :     if (m_eAccessMode == TABRead)
     200             :     {
     201             : #if DEBUG_VERBOSE
     202             :         CPLDebug("MITAB", "m_osLastRead: %s", m_osLastRead.c_str());
     203             : #endif
     204       31104 :         return m_osLastRead.c_str();
     205             :     }
     206             : 
     207             :     // We should never get here.  Read/Write mode not implemented.
     208           0 :     CPLAssert(false);
     209             :     return nullptr;
     210             : }
     211             : 
     212         356 : char **MIDDATAFile::GetTokenizedNextLine()
     213             : {
     214             :     static const int nMaxLineLength =
     215         356 :         atoi(CPLGetConfigOption("MITAB_MAX_LINE_LENGTH", "1000000"));
     216             :     char **papszTokens =
     217         356 :         CSVReadParseLine3L(m_fp, nMaxLineLength, m_pszDelimiter,
     218             :                            true,   // bHonourStrings
     219             :                            false,  // bKeepLeadingAndClosingQuotes
     220             :                            false,  // bMergeDelimiter
     221             :                            false   // bSkipBOM
     222             :         );
     223         356 :     if (papszTokens == nullptr)
     224             :     {
     225           0 :         if (strstr(CPLGetLastErrorMsg(),
     226           0 :                    "Maximum number of characters allowed reached"))
     227             :         {
     228           0 :             CPLError(
     229             :                 CE_Failure, CPLE_AppDefined,
     230             :                 "Maximum number of characters allowed reached. "
     231             :                 "You can set the MITAB_MAX_LINE_LENGTH configuration option "
     232             :                 "to the desired number of bytes (or -1 for unlimited)");
     233             :         }
     234           0 :         SetEof(TRUE);
     235             :     }
     236         356 :     return papszTokens;
     237             : }
     238             : 
     239        1701 : void MIDDATAFile::WriteLine(const char *pszFormat, ...)
     240             : {
     241             :     va_list args;
     242             : 
     243        1701 :     if (m_eAccessMode == TABWrite && m_fp)
     244             :     {
     245        1701 :         va_start(args, pszFormat);
     246        1701 :         CPLString osStr;
     247        1701 :         osStr.vPrintf(pszFormat, args);
     248        1701 :         VSIFWriteL(osStr.c_str(), 1, osStr.size(), m_fp);
     249        1701 :         va_end(args);
     250             :     }
     251             :     else
     252             :     {
     253           0 :         CPLAssert(false);
     254             :     }
     255        1701 : }
     256             : 
     257        1068 : void MIDDATAFile::SetTranslation(double dfXMul, double dfYMul, double dfXTran,
     258             :                                  double dfYTran)
     259             : {
     260        1068 :     m_dfXMultiplier = dfXMul;
     261        1068 :     m_dfYMultiplier = dfYMul;
     262        1068 :     m_dfXDisplacement = dfXTran;
     263        1068 :     m_dfYDisplacement = dfYTran;
     264        1068 : }
     265             : 
     266       21452 : double MIDDATAFile::GetXTrans(double dfX)
     267             : {
     268       21452 :     return (dfX * m_dfXMultiplier) + m_dfXDisplacement;
     269             : }
     270             : 
     271       20820 : double MIDDATAFile::GetYTrans(double dfY)
     272             : {
     273       20820 :     return (dfY * m_dfYMultiplier) + m_dfYDisplacement;
     274             : }
     275             : 
     276       23014 : GBool MIDDATAFile::IsValidFeature(const char *pszString)
     277             : {
     278       23014 :     char **papszToken = CSLTokenizeString(pszString);
     279             : 
     280       23014 :     if (CSLCount(papszToken) == 0)
     281             :     {
     282        8229 :         CSLDestroy(papszToken);
     283        8229 :         return FALSE;
     284             :     }
     285             : 
     286       14785 :     if (EQUAL(papszToken[0], "NONE") || EQUAL(papszToken[0], "POINT") ||
     287       11888 :         EQUAL(papszToken[0], "LINE") || EQUAL(papszToken[0], "PLINE") ||
     288        9452 :         EQUAL(papszToken[0], "REGION") || EQUAL(papszToken[0], "ARC") ||
     289        8226 :         EQUAL(papszToken[0], "TEXT") || EQUAL(papszToken[0], "RECT") ||
     290        7433 :         EQUAL(papszToken[0], "ROUNDRECT") || EQUAL(papszToken[0], "ELLIPSE") ||
     291        6590 :         EQUAL(papszToken[0], "MULTIPOINT") ||
     292        6407 :         EQUAL(papszToken[0], "COLLECTION"))
     293             :     {
     294        8477 :         CSLDestroy(papszToken);
     295        8477 :         return TRUE;
     296             :     }
     297             : 
     298        6308 :     CSLDestroy(papszToken);
     299        6308 :     return FALSE;
     300             : }
     301             : 
     302       31992 : GBool MIDDATAFile::GetEof()
     303             : {
     304       31992 :     return m_bEof;
     305             : }
     306             : 
     307         863 : const CPLString &MIDDATAFile::GetEncoding() const
     308             : {
     309         863 :     return m_osEncoding;
     310             : }
     311             : 
     312        1194 : void MIDDATAFile::SetEncoding(const CPLString &osEncoding)
     313             : {
     314        1194 :     m_osEncoding = osEncoding;
     315        1194 : }
     316             : 
     317        2706 : void MIDDATAFile::SetEof(GBool bEof)
     318             : {
     319        2706 :     m_bEof = bEof;
     320        2706 : }

Generated by: LCOV version 1.14