LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/mitab - mitab_imapinfofile.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 146 95 65.1 %
Date: 2012-04-28 Functions: 11 6 54.5 %

       1                 : /**********************************************************************
       2                 :  * $Id: mitab_imapinfofile.cpp,v 1.31 2010-01-07 20:39:12 aboudreault Exp $
       3                 :  *
       4                 :  * Name:     mitab_imapinfo
       5                 :  * Project:  MapInfo mid/mif Tab Read/Write library
       6                 :  * Language: C++
       7                 :  * Purpose:  Implementation of the IMapInfoFile class, super class of
       8                 :  *           of MIFFile and TABFile
       9                 :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
      10                 :  *
      11                 :  **********************************************************************
      12                 :  * Copyright (c) 1999-2008, Daniel Morissette
      13                 :  *
      14                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      15                 :  * copy of this software and associated documentation files (the "Software"),
      16                 :  * to deal in the Software without restriction, including without limitation
      17                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18                 :  * and/or sell copies of the Software, and to permit persons to whom the
      19                 :  * Software is furnished to do so, subject to the following conditions:
      20                 :  * 
      21                 :  * The above copyright notice and this permission notice shall be included
      22                 :  * in all copies or substantial portions of the Software.
      23                 :  * 
      24                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      25                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      27                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      30                 :  * DEALINGS IN THE SOFTWARE.
      31                 :  **********************************************************************
      32                 :  *
      33                 :  * $Log: mitab_imapinfofile.cpp,v $
      34                 :  * Revision 1.31  2010-01-07 20:39:12  aboudreault
      35                 :  * Added support to handle duplicate field names, Added validation to check if a field name start with a number (bug 2141)
      36                 :  *
      37                 :  * Revision 1.30  2009-01-23 16:50:27  aboudreault
      38                 :  * Fixed wrong return value of IMapInfoFile::SetCharset() method (bug 1987)
      39                 :  *
      40                 :  * Revision 1.29  2008/11/27 20:50:22  aboudreault
      41                 :  * Improved support for OGR date/time types. New Read/Write methods (bug 1948)
      42                 :  * Added support of OGR date/time types for MIF features.
      43                 :  *
      44                 :  * Revision 1.28  2008/11/17 22:06:21  aboudreault
      45                 :  * Added support to use OFTDateTime/OFTDate/OFTTime type when compiled with
      46                 :  * OGR and fixed reading/writing support for these types.
      47                 :  *
      48                 :  * Revision 1.27  2008/09/26 14:40:24  aboudreault
      49                 :  * Fixed bug: MITAB doesn't support writing DateTime type (bug 1948)
      50                 :  *
      51                 :  * Revision 1.26  2008/03/07 20:16:17  dmorissette
      52                 :  * Fixed typos in comments
      53                 :  *
      54                 :  * Revision 1.25  2008/03/05 20:35:39  dmorissette
      55                 :  * Replace MITAB 1.x SetFeature() with a CreateFeature() for V2.x (bug 1859)
      56                 :  *
      57                 :  * Revision 1.24  2007/06/21 14:00:23  dmorissette
      58                 :  * Added missing cast in isspace() calls to avoid failed assertion on Windows
      59                 :  * (MITAB bug 1737, GDAL ticket 1678))
      60                 :  *
      61                 :  * Revision 1.23  2007/06/12 14:43:19  dmorissette
      62                 :  * Use iswspace instead of sispace in IMapInfoFile::SmartOpen() (bug 1737)
      63                 :  *
      64                 :  * Revision 1.22  2007/06/12 13:52:37  dmorissette
      65                 :  * Added IMapInfoFile::SetCharset() method (bug 1734)
      66                 :  *
      67                 :  * Revision 1.21  2005/05/19 21:10:50  fwarmerdam
      68                 :  * changed to use OGRLayers spatial filter support
      69                 :  *
      70                 :  * Revision 1.20  2005/05/19 15:27:00  jlacroix
      71                 :  * Implement a method to set the StyleString of a TABFeature.
      72                 :  * This is done via the ITABFeaturePen, Brush and Symbol classes.
      73                 :  *
      74                 :  * Revision 1.19  2004/06/30 20:29:04  dmorissette
      75                 :  * Fixed refs to old address danmo@videotron.ca
      76                 :  *
      77                 :  * Revision 1.18  2003/12/19 07:55:55  fwarmerdam
      78                 :  * treat 3D features as 2D on write
      79                 :  *
      80                 :  * Revision 1.17  2001/09/14 19:14:43  warmerda
      81                 :  * added attribute query support
      82                 :  *
      83                 :  * Revision 1.16  2001/09/14 03:23:55  warmerda
      84                 :  * Substantial upgrade to support spatial queries using spatial indexes
      85                 :  *
      86                 :  * Revision 1.15  2001/07/03 23:11:21  daniel
      87                 :  * Test for NULL geometries if spatial filter enabled in GetNextFeature().
      88                 :  *
      89                 :  * Revision 1.14  2001/03/09 04:16:02  daniel
      90                 :  * Added TABSeamless for reading seamless TAB files
      91                 :  *
      92                 :  * Revision 1.13  2001/02/27 19:59:05  daniel
      93                 :  * Enabled spatial filter in IMapInfoFile::GetNextFeature(), and avoid
      94                 :  * unnecessary feature cloning in GetNextFeature() and GetFeature()
      95                 :  *
      96                 :  * Revision 1.12  2001/02/06 22:03:24  warmerda
      97                 :  * fixed memory leak of whole features in CreateFeature
      98                 :  *
      99                 :  * Revision 1.11  2001/01/23 21:23:42  daniel
     100                 :  * Added projection bounds lookup table, called from TABFile::SetProjInfo()
     101                 :  *
     102                 :  * Revision 1.10  2001/01/22 16:03:58  warmerda
     103                 :  * expanded tabs
     104                 :  *
     105                 :  * Revision 1.9  2000/11/30 20:27:56  warmerda
     106                 :  * make variable length string fields 254 wide, not 255
     107                 :  *
     108                 :  * Revision 1.8  2000/02/28 03:11:35  warmerda
     109                 :  * fix support for zero width fields
     110                 :  *
     111                 :  * Revision 1.7  2000/02/02 20:14:03  warmerda
     112                 :  * made safer when encountering geometryless features
     113                 :  *
     114                 :  * Revision 1.6  2000/01/26 18:17:35  warmerda
     115                 :  * added CreateField method
     116                 :  *
     117                 :  * Revision 1.5  2000/01/15 22:30:44  daniel
     118                 :  * Switch to MIT/X-Consortium OpenSource license
     119                 :  *
     120                 :  * Revision 1.4  2000/01/11 19:06:25  daniel
     121                 :  * Added support for conversion of collections in CreateFeature()
     122                 :  *
     123                 :  * Revision 1.3  1999/12/14 02:14:50  daniel
     124                 :  * Added static SmartOpen() method + TABView support
     125                 :  *
     126                 :  * Revision 1.2  1999/11/08 19:15:44  stephane
     127                 :  * Add headers method
     128                 :  *
     129                 :  * Revision 1.1  1999/11/08 04:17:27  stephane
     130                 :  * First Revision
     131                 :  *
     132                 :  **********************************************************************/
     133                 : 
     134                 : #include "mitab.h"
     135                 : #include "mitab_utils.h"
     136                 : 
     137                 : #ifdef __HP_aCC
     138                 : #  include <wchar.h>      /* iswspace() */
     139                 : #else
     140                 : #  include <wctype.h>      /* iswspace() */
     141                 : #endif
     142                 : 
     143                 : /**********************************************************************
     144                 :  *                   IMapInfoFile::IMapInfoFile()
     145                 :  *
     146                 :  * Constructor.
     147                 :  **********************************************************************/
     148              52 : IMapInfoFile::IMapInfoFile()
     149                 : {
     150              52 :     m_nCurFeatureId = 0;
     151              52 :     m_poCurFeature = NULL;
     152              52 :     m_bBoundsSet = FALSE;
     153              52 :     m_pszCharset = NULL;
     154              52 : }
     155                 : 
     156                 : 
     157                 : /**********************************************************************
     158                 :  *                   IMapInfoFile::~IMapInfoFile()
     159                 :  *
     160                 :  * Destructor.
     161                 :  **********************************************************************/
     162              52 : IMapInfoFile::~IMapInfoFile()
     163                 : {
     164              52 :     if (m_poCurFeature)
     165                 :     {
     166               0 :         delete m_poCurFeature;
     167               0 :         m_poCurFeature = NULL;
     168                 :     }
     169                 : 
     170              52 :     CPLFree(m_pszCharset);
     171              52 :     m_pszCharset = NULL;
     172              52 : }
     173                 : 
     174                 : /**********************************************************************
     175                 :  *                   IMapInfoFile::SmartOpen()
     176                 :  *
     177                 :  * Use this static method to automatically open any flavour of MapInfo
     178                 :  * dataset.  This method will detect the file type, create an object
     179                 :  * of the right type, and open the file.
     180                 :  *
     181                 :  * Call GetFileClass() on the returned object if you need to find out
     182                 :  * its exact type.  (To access format-specific methods for instance)
     183                 :  *
     184                 :  * Returns the new object ptr. , or NULL if the open failed.
     185                 :  **********************************************************************/
     186             828 : IMapInfoFile *IMapInfoFile::SmartOpen(const char *pszFname,
     187                 :                                       GBool bTestOpenNoError /*=FALSE*/)
     188                 : {
     189             828 :     IMapInfoFile *poFile = NULL;
     190             828 :     int nLen = 0;
     191                 : 
     192             828 :     if (pszFname)
     193             828 :         nLen = strlen(pszFname);
     194                 : 
     195             852 :     if (nLen > 4 && (EQUAL(pszFname + nLen-4, ".MIF") ||
     196                 :                      EQUAL(pszFname + nLen-4, ".MID") ) )
     197                 :     {
     198                 :         /*-------------------------------------------------------------
     199                 :          * MIF/MID file
     200                 :          *------------------------------------------------------------*/
     201              24 :         poFile = new MIFFile;
     202                 :     }
     203             804 :     else if (nLen > 4 && EQUAL(pszFname + nLen-4, ".TAB"))
     204                 :     {
     205                 :         /*-------------------------------------------------------------
     206                 :          * .TAB file ... is it a TABFileView or a TABFile?
     207                 :          * We have to read the .tab header to find out.
     208                 :          *------------------------------------------------------------*/
     209                 :         FILE *fp;
     210                 :         const char *pszLine;
     211               6 :         char *pszAdjFname = CPLStrdup(pszFname);
     212               6 :         GBool bFoundFields = FALSE, bFoundView=FALSE, bFoundSeamless=FALSE;
     213                 : 
     214               6 :         TABAdjustFilenameExtension(pszAdjFname);
     215               6 :         fp = VSIFOpen(pszAdjFname, "r");
     216              70 :         while(fp && (pszLine = CPLReadLine(fp)) != NULL)
     217                 :         {
     218              58 :             while (isspace((unsigned char)*pszLine))  pszLine++;
     219              58 :             if (EQUALN(pszLine, "Fields", 6))
     220               6 :                 bFoundFields = TRUE;
     221              52 :             else if (EQUALN(pszLine, "create view", 11))
     222               0 :                 bFoundView = TRUE;
     223              52 :             else if (EQUALN(pszLine, "\"\\IsSeamless\" = \"TRUE\"", 21))
     224               0 :                 bFoundSeamless = TRUE;
     225                 :         }
     226                 : 
     227               6 :         if (bFoundView)
     228               0 :             poFile = new TABView;
     229               6 :         else if (bFoundFields && bFoundSeamless)
     230               0 :             poFile = new TABSeamless;
     231               6 :         else if (bFoundFields)
     232               6 :             poFile = new TABFile;
     233                 : 
     234               6 :         if (fp)
     235               6 :             VSIFClose(fp);
     236                 : 
     237               6 :         CPLFree(pszAdjFname);
     238                 :     }
     239                 : 
     240                 :     /*-----------------------------------------------------------------
     241                 :      * Perform the open() call
     242                 :      *----------------------------------------------------------------*/
     243             828 :     if (poFile && poFile->Open(pszFname, "r", bTestOpenNoError) != 0)
     244                 :     {
     245               0 :         delete poFile;
     246               0 :         poFile = NULL;
     247                 :     }
     248                 : 
     249             828 :     if (!bTestOpenNoError && poFile == NULL)
     250                 :     {
     251                 :         CPLError(CE_Failure, CPLE_FileIO,
     252               0 :                  "%s could not be opened as a MapInfo dataset.", pszFname);
     253                 :     }
     254                 : 
     255             828 :     return poFile;
     256                 : }
     257                 : 
     258                 : 
     259                 : 
     260                 : /**********************************************************************
     261                 :  *                   IMapInfoFile::GetNextFeature()
     262                 :  *
     263                 :  * Standard OGR GetNextFeature implementation.  This method is used
     264                 :  * to retreive the next OGRFeature.
     265                 :  **********************************************************************/
     266             138 : OGRFeature *IMapInfoFile::GetNextFeature()
     267                 : {
     268                 :     OGRFeature *poFeatureRef;
     269                 :     OGRGeometry *poGeom;
     270                 :     int nFeatureId;
     271                 : 
     272             352 :     while( (nFeatureId = GetNextFeatureId(m_nCurFeatureId)) != -1 )
     273                 :     {
     274             194 :         poFeatureRef = GetFeatureRef(nFeatureId);
     275             194 :         if (poFeatureRef == NULL)
     276               0 :             return NULL;
     277             194 :         else if( (m_poFilterGeom == NULL ||
     278                 :                   ((poGeom = poFeatureRef->GetGeometryRef()) != NULL &&
     279                 :                    FilterGeometry( poGeom )))
     280                 :                  && (m_poAttrQuery == NULL
     281                 :                      || m_poAttrQuery->Evaluate( poFeatureRef )) )
     282                 :         {
     283                 :             // Avoid cloning feature... return the copy owned by the class
     284             118 :             CPLAssert(poFeatureRef == m_poCurFeature);
     285             118 :             m_poCurFeature = NULL;  
     286             118 :             return poFeatureRef;
     287                 :         }
     288                 :     }
     289              20 :     return NULL;
     290                 : }
     291                 : 
     292                 : /**********************************************************************
     293                 :  *                   IMapInfoFile::CreateFeature()
     294                 :  *
     295                 :  * Standard OGR CreateFeature implementation.  This method is used
     296                 :  * to create a new feature in current dataset 
     297                 :  **********************************************************************/
     298              70 : OGRErr     IMapInfoFile::CreateFeature(OGRFeature *poFeature)
     299                 : {
     300                 :     TABFeature *poTABFeature;
     301                 :     OGRGeometry   *poGeom;
     302                 :     OGRwkbGeometryType eGType;
     303                 :     OGRErr  eErr;
     304              70 :     TABPoint *poTABPointFeature = NULL;
     305              70 :     TABRegion *poTABRegionFeature = NULL;
     306              70 :     TABPolyline *poTABPolylineFeature = NULL;
     307                 : 
     308                 :     /*-----------------------------------------------------------------
     309                 :      * MITAB won't accept new features unless they are in a type derived
     310                 :      * from TABFeature... so we have to do our best to map to the right
     311                 :      * feature type based on the geometry type.
     312                 :      *----------------------------------------------------------------*/
     313              70 :     poGeom = poFeature->GetGeometryRef();
     314              70 :     if( poGeom != NULL )
     315              52 :         eGType = poGeom->getGeometryType();
     316                 :     else
     317              18 :         eGType = wkbNone;
     318                 : 
     319              70 :     switch( wkbFlatten(eGType) )
     320                 :     {
     321                 :       /*-------------------------------------------------------------
     322                 :        * POINT
     323                 :        *------------------------------------------------------------*/
     324                 :       case wkbPoint:
     325               8 :         poTABFeature = new TABPoint(poFeature->GetDefnRef());
     326               8 :         if(poFeature->GetStyleString())
     327                 :         {
     328               0 :             poTABPointFeature = (TABPoint*)poTABFeature;
     329                 :             poTABPointFeature->SetSymbolFromStyleString(
     330               0 :                 poFeature->GetStyleString());
     331                 :         }
     332               8 :         break;
     333                 :       /*-------------------------------------------------------------
     334                 :        * REGION
     335                 :        *------------------------------------------------------------*/
     336                 :       case wkbPolygon:
     337                 :       case wkbMultiPolygon:
     338              42 :         poTABFeature = new TABRegion(poFeature->GetDefnRef());
     339              42 :         if(poFeature->GetStyleString())
     340                 :         {
     341               0 :             poTABRegionFeature = (TABRegion*)poTABFeature;
     342                 :             poTABRegionFeature->SetPenFromStyleString(
     343               0 :                 poFeature->GetStyleString());
     344                 : 
     345                 :             poTABRegionFeature->SetBrushFromStyleString(
     346               0 :                 poFeature->GetStyleString());
     347                 :         }
     348              42 :         break;
     349                 :       /*-------------------------------------------------------------
     350                 :        * LINE/PLINE/MULTIPLINE
     351                 :        *------------------------------------------------------------*/
     352                 :       case wkbLineString:
     353                 :       case wkbMultiLineString:
     354               2 :         poTABFeature = new TABPolyline(poFeature->GetDefnRef());
     355               2 :         if(poFeature->GetStyleString())
     356                 :         {
     357               0 :             poTABPolylineFeature = (TABPolyline*)poTABFeature;
     358                 :             poTABPolylineFeature->SetPenFromStyleString(
     359               0 :                 poFeature->GetStyleString());
     360                 :         }
     361               2 :         break;
     362                 :       /*-------------------------------------------------------------
     363                 :        * Collection types that are not directly supported... convert
     364                 :        * to multiple features in output file through recursive calls.
     365                 :        *------------------------------------------------------------*/
     366                 :       case wkbGeometryCollection:
     367                 :       case wkbMultiPoint:
     368                 :       {
     369               0 :           OGRErr eStatus = OGRERR_NONE;
     370                 :           int i;
     371               0 :           OGRGeometryCollection *poColl = (OGRGeometryCollection*)poGeom;
     372               0 :           OGRFeature *poTmpFeature = poFeature->Clone();
     373                 : 
     374               0 :           for (i=0; eStatus==OGRERR_NONE && i<poColl->getNumGeometries(); i++)
     375                 :           {
     376               0 :               poTmpFeature->SetGeometry(poColl->getGeometryRef(i));
     377               0 :               eStatus = CreateFeature(poTmpFeature);
     378                 :           }
     379               0 :           delete poTmpFeature;
     380               0 :           return eStatus;
     381                 :         }
     382                 :         break;
     383                 :       /*-------------------------------------------------------------
     384                 :        * Unsupported type.... convert to MapInfo geometry NONE
     385                 :        *------------------------------------------------------------*/
     386                 :       case wkbUnknown:
     387                 :       default:
     388              18 :          poTABFeature = new TABFeature(poFeature->GetDefnRef()); 
     389                 :         break;
     390                 :     }
     391                 : 
     392              70 :     if( poGeom != NULL )
     393              52 :         poTABFeature->SetGeometryDirectly(poGeom->clone());
     394                 :     
     395             240 :     for (int i=0; i< poFeature->GetDefnRef()->GetFieldCount();i++)
     396                 :     {
     397             170 :         poTABFeature->SetField(i,poFeature->GetRawFieldRef( i ));
     398                 :     }
     399                 :     
     400                 : 
     401              70 :     eErr = CreateFeature(poTABFeature);
     402                 : 
     403              70 :     delete poTABFeature;
     404                 :     
     405              70 :     return eErr;
     406                 : }
     407                 : 
     408                 : /**********************************************************************
     409                 :  *                   IMapInfoFile::GetFeature()
     410                 :  *
     411                 :  * Standard OGR GetFeature implementation.  This method is used
     412                 :  * to get the wanted (nFeatureId) feature, a NULL value will be 
     413                 :  * returned on error.
     414                 :  **********************************************************************/
     415               0 : OGRFeature *IMapInfoFile::GetFeature(long nFeatureId)
     416                 : {
     417                 :     OGRFeature *poFeatureRef;
     418                 : 
     419               0 :     poFeatureRef = GetFeatureRef(nFeatureId);
     420               0 :     if (poFeatureRef)
     421                 :     {
     422                 :         // Avoid cloning feature... return the copy owned by the class
     423               0 :         CPLAssert(poFeatureRef == m_poCurFeature);
     424               0 :         m_poCurFeature = NULL;  
     425                 : 
     426               0 :         return poFeatureRef;
     427                 :     }
     428                 :     else
     429               0 :       return NULL;
     430                 : }
     431                 : 
     432                 : /************************************************************************/
     433                 : /*                            CreateField()                             */
     434                 : /*                                                                      */
     435                 : /*      Create a native field based on a generic OGR definition.        */
     436                 : /************************************************************************/
     437                 : 
     438              50 : OGRErr IMapInfoFile::CreateField( OGRFieldDefn *poField, int bApproxOK )
     439                 : 
     440                 : {
     441                 :     TABFieldType        eTABType;
     442              50 :     int                 nWidth = poField->GetWidth();
     443                 : 
     444              50 :     if( poField->GetType() == OFTInteger )
     445                 :     {
     446              14 :         eTABType = TABFInteger;
     447              14 :         if( nWidth == 0 )
     448               6 :             nWidth = 12;
     449                 :     }
     450              36 :     else if( poField->GetType() == OFTReal )
     451                 :     {
     452              14 :         if( nWidth == 0 && poField->GetPrecision() == 0)
     453                 :         {
     454              10 :             eTABType = TABFFloat;
     455              10 :             nWidth = 32;
     456                 :         }
     457                 :         else
     458                 :         {
     459               4 :             eTABType = TABFDecimal;
     460                 :         }
     461                 :     }
     462              22 :     else if( poField->GetType() == OFTDate )
     463                 :     {
     464               0 :         eTABType = TABFDate;
     465               0 :         if( nWidth == 0 )
     466               0 :             nWidth = 10;
     467                 :     }
     468              22 :     else if( poField->GetType() == OFTTime )
     469                 :     {
     470               0 :         eTABType = TABFTime;
     471               0 :         if( nWidth == 0 )
     472               0 :             nWidth = 9;
     473                 :     }
     474              22 :     else if( poField->GetType() == OFTDateTime )
     475                 :     {
     476               0 :         eTABType = TABFDateTime;
     477               0 :         if( nWidth == 0 )
     478               0 :             nWidth = 19;
     479                 :     }
     480              22 :     else if( poField->GetType() == OFTString )
     481                 :     {
     482              22 :         eTABType = TABFChar;
     483              22 :         if( nWidth == 0 )
     484              22 :             nWidth = 254;
     485                 :         else
     486               0 :             nWidth = MIN(254,nWidth);
     487                 :     }
     488                 :     else
     489                 :     {
     490                 :         CPLError( CE_Failure, CPLE_AppDefined,
     491                 :                   "IMapInfoFile::CreateField() called with unsupported field"
     492                 :                   " type %d.\n"
     493                 :                   "Note that Mapinfo files don't support list field types.\n",
     494               0 :                   poField->GetType() );
     495                 : 
     496               0 :         return OGRERR_FAILURE;
     497                 :     }
     498                 : 
     499              50 :     if( AddFieldNative( poField->GetNameRef(), eTABType,
     500              50 :                         nWidth, poField->GetPrecision(), FALSE, FALSE, bApproxOK ) > -1 )
     501              50 :         return OGRERR_NONE;
     502                 :     else
     503               0 :         return OGRERR_FAILURE;
     504                 : }
     505                 : 
     506                 : 
     507                 : /**********************************************************************
     508                 :  *                   IMapInfoFile::SetCharset()
     509                 :  *
     510                 :  * Set the charset for the tab header. 
     511                 :  *
     512                 :  *
     513                 :  * Returns 0 on success, -1 on error.
     514                 :  **********************************************************************/
     515               0 : int IMapInfoFile::SetCharset(const char* pszCharset)
     516                 : {
     517               0 :     if(pszCharset && strlen(pszCharset) > 0)
     518                 :     {
     519               0 :         CPLFree(m_pszCharset);
     520               0 :         m_pszCharset = CPLStrdup(pszCharset);
     521               0 :         return 0;
     522                 :     }
     523               0 :     return -1;
     524                 : }
     525                 : 

Generated by: LCOV version 1.7