LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/mitab - mitab_utils.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 155
Code covered: 47.7 % Executed lines: 74

       1                 : /**********************************************************************
       2                 :  * $Id: mitab_utils.cpp,v 1.22 2008/07/21 16:04:58 dmorissette Exp $
       3                 :  *
       4                 :  * Name:     mitab_utils.cpp
       5                 :  * Project:  MapInfo TAB Read/Write library
       6                 :  * Language: C++
       7                 :  * Purpose:  Misc. util. functions for the library
       8                 :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
       9                 :  *
      10                 :  **********************************************************************
      11                 :  * Copyright (c) 1999-2001, 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: mitab_utils.cpp,v $
      33                 :  * Revision 1.22  2008/07/21 16:04:58  dmorissette
      34                 :  * Fixed const char * warnings with GCC 4.3 (GDAL ticket #2325)
      35                 :  *
      36                 :  * Revision 1.21  2006/12/01 16:53:15  dmorissette
      37                 :  * Wrapped <mbctype.h> stuff with !defined(WIN32CE) (done by mloskot in OGR)
      38                 :  *
      39                 :  * Revision 1.20  2005/08/07 21:02:14  fwarmerdam
      40                 :  * avoid warnings about testing for characters > 255.
      41                 :  *
      42                 :  * Revision 1.19  2004/06/30 20:29:04  dmorissette
      43                 :  * Fixed refs to old address danmo@videotron.ca
      44                 :  *
      45                 :  * Revision 1.18  2002/08/28 14:19:22  warmerda
      46                 :  * fix TABGetBasename() for mixture of path divider types like 'mi/abc\def.tab'
      47                 :  *
      48                 :  * Revision 1.17  2001/06/27 19:52:54  warmerda
      49                 :  * avoid multi byte support if _WIN32 and unix defined for cygwin support
      50                 :  *
      51                 :  * Revision 1.16  2001/01/23 21:23:42  daniel
      52                 :  * Added projection bounds lookup table, called from TABFile::SetProjInfo()
      53                 :  *
      54                 :  * Revision 1.15  2001/01/19 06:06:18  daniel
      55                 :  * Don't filter chars in TABCleanFieldName() if we're on a DBCS system
      56                 :  *
      57                 :  * Revision 1.14  2000/09/28 16:39:44  warmerda
      58                 :  * avoid warnings for unused, and unitialized variables
      59                 :  *
      60                 :  * Revision 1.13  2000/09/20 18:35:51  daniel
      61                 :  * Fixed TABAdjustFilenameExtension() to also handle basename and path
      62                 :  * using TABAdjustCaseSensitiveFilename()
      63                 :  *
      64                 :  * Revision 1.12  2000/04/18 04:19:22  daniel
      65                 :  * Now accept extended chars with accents in TABCleanFieldName()
      66                 :  *
      67                 :  * Revision 1.11  2000/02/28 17:08:56  daniel
      68                 :  * Avoid using isalnum() in TABCleanFieldName
      69                 :  *
      70                 :  * Revision 1.10  2000/02/18 20:46:35  daniel
      71                 :  * Added TABCleanFieldName()
      72                 :  *
      73                 :  * Revision 1.9  2000/01/15 22:30:45  daniel
      74                 :  * Switch to MIT/X-Consortium OpenSource license
      75                 :  *
      76                 :  * Revision 1.8  2000/01/14 23:46:59  daniel
      77                 :  * Added TABEscapeString()/TABUnEscapeString()
      78                 :  *
      79                 :  * Revision 1.7  1999/12/16 06:10:24  daniel
      80                 :  * TABGetBasename(): make sure last '/' of path is removed
      81                 :  *
      82                 :  * Revision 1.6  1999/12/14 02:08:37  daniel
      83                 :  * Added TABGetBasename() + TAB_CSLLoad()
      84                 :  *
      85                 :  * Revision 1.5  1999/11/08 04:30:59  stephane
      86                 :  * Modify TABGenerateArc()
      87                 :  *
      88                 :  * Revision 1.4  1999/09/29 17:59:21  daniel
      89                 :  * Definition for PI was gone on Windows
      90                 :  *
      91                 :  * Revision 1.3  1999/09/16 02:39:17  daniel
      92                 :  * Completed read support for most feature types
      93                 :  *
      94                 :  * Revision 1.2  1999/07/12 05:44:59  daniel
      95                 :  * Added include math.h for VC++
      96                 :  *
      97                 :  * Revision 1.1  1999/07/12 04:18:25  daniel
      98                 :  * Initial checkin
      99                 :  *
     100                 :  **********************************************************************/
     101                 : 
     102                 : #include "mitab.h"
     103                 : #include "mitab_utils.h"
     104                 : #include "cpl_conv.h"
     105                 : 
     106                 : #include <math.h>       /* sin()/cos() */
     107                 : #include <ctype.h>      /* toupper()/tolower() */
     108                 : 
     109                 : #if defined(_WIN32) && !defined(unix) && !defined(WIN32CE)
     110                 : #  include <mbctype.h>  /* Multibyte chars stuff */
     111                 : #endif
     112                 : 
     113                 : 
     114                 : /**********************************************************************
     115                 :  *                       TABGenerateArc()
     116                 :  *
     117                 :  * Generate the coordinates for an arc and ADD the coordinates to the 
     118                 :  * geometry object.  If the geometry already contains some points then
     119                 :  * these won't be lost.
     120                 :  *
     121                 :  * poLine can be a OGRLineString or one of its derived classes, such as 
     122                 :  *        OGRLinearRing
     123                 :  * numPoints is the number of points to generate.
     124                 :  * Angles are specified in radians, valid values are in the range [0..2*PI]
     125                 :  *
     126                 :  * Arcs are always generated counterclockwise, even if StartAngle > EndAngle
     127                 :  *
     128                 :  * Returns 0 on success, -1 on error.
     129                 :  **********************************************************************/
     130                 : int TABGenerateArc(OGRLineString *poLine, int numPoints, 
     131                 :                    double dCenterX, double dCenterY,
     132                 :                    double dXRadius, double dYRadius,
     133               0 :                    double dStartAngle, double dEndAngle)
     134                 : {
     135               0 :     double dX, dY, dAngleStep, dAngle=0.0;
     136                 :     int i;
     137                 : 
     138                 :     // Adjust angles to go counterclockwise
     139               0 :     if (dEndAngle < dStartAngle)
     140               0 :         dEndAngle += 2.0*PI;
     141                 : 
     142               0 :     dAngleStep = (dEndAngle-dStartAngle)/(numPoints-1.0);
     143                 : 
     144               0 :     for(i=0; i<numPoints; i++)
     145                 :     {
     146               0 :         dAngle = (dStartAngle + (double)i*dAngleStep);
     147               0 :         dX = dCenterX + dXRadius*cos(dAngle);
     148               0 :         dY = dCenterY + dYRadius*sin(dAngle);
     149               0 :         poLine->addPoint(dX, dY);
     150                 :     }
     151                 : 
     152                 :     // Complete the arc with the last EndAngle, to make sure that 
     153                 :     // the arc is correcly close.
     154                 : 
     155               0 :     dX = dCenterX + dXRadius*cos(dAngle);
     156               0 :     dY = dCenterY + dYRadius*sin(dAngle);
     157               0 :     poLine->addPoint(dX,dY);
     158                 : 
     159                 : 
     160               0 :     return 0;
     161                 : }
     162                 : 
     163                 : 
     164                 : /**********************************************************************
     165                 :  *                       TABCloseRing()
     166                 :  *
     167                 :  * Check if a ring is closed, and add a point to close it if necessary.
     168                 :  *
     169                 :  * Returns 0 on success, -1 on error.
     170                 :  **********************************************************************/
     171               0 : int TABCloseRing(OGRLineString *poRing)
     172                 : {
     173               0 :     if ( poRing->getNumPoints() > 0 && !poRing->get_IsClosed() )
     174                 :     {
     175               0 :         poRing->addPoint(poRing->getX(0), poRing->getY(0));
     176                 :     }
     177                 : 
     178               0 :     return 0;
     179                 : }
     180                 : 
     181                 : /**********************************************************************
     182                 :  *                     TABAdjustCaseSensitiveFilename()
     183                 :  *
     184                 :  * Scan a filename and its path, adjust uppercase/lowercases if
     185                 :  * necessary.
     186                 :  *
     187                 :  * Returns TRUE if file found, or FALSE if it could not be located with
     188                 :  * a case-insensitive search.
     189                 :  *
     190                 :  * This function works on the original buffer and returns a reference to it.
     191                 :  * It does nothing on Windows systems where filenames are not case sensitive.
     192                 :  **********************************************************************/
     193              24 : GBool TABAdjustCaseSensitiveFilename(char *pszFname)
     194                 : {
     195                 : 
     196                 : #ifdef _WIN32
     197                 :     /*-----------------------------------------------------------------
     198                 :      * Nothing to do on Windows
     199                 :      *----------------------------------------------------------------*/
     200                 :     return TRUE;
     201                 : 
     202                 : #else
     203                 :     /*-----------------------------------------------------------------
     204                 :      * Unix case.
     205                 :      *----------------------------------------------------------------*/
     206                 :     VSIStatBuf  sStatBuf;
     207              24 :     char        *pszTmpPath = NULL;
     208                 :     int         nTotalLen, iTmpPtr;
     209                 :     GBool       bValidPath;
     210                 : 
     211                 :     /*-----------------------------------------------------------------
     212                 :      * First check if the filename is OK as is.
     213                 :      *----------------------------------------------------------------*/
     214              24 :     if (VSIStat(pszFname, &sStatBuf) == 0)
     215                 :     {
     216               0 :         return TRUE;
     217                 :     }
     218                 : 
     219                 :     /*-----------------------------------------------------------------
     220                 :      * OK, file either does not exist or has the wrong cases... we'll
     221                 :      * go backwards until we find a portion of the path that is valid.
     222                 :      *----------------------------------------------------------------*/
     223              24 :     pszTmpPath = CPLStrdup(pszFname);
     224              24 :     nTotalLen = strlen(pszTmpPath);
     225              24 :     iTmpPtr = nTotalLen;
     226              24 :     bValidPath = FALSE;
     227                 : 
     228              72 :     while(iTmpPtr > 0 && !bValidPath)
     229                 :     {
     230                 :         /*-------------------------------------------------------------
     231                 :          * Move back to the previous '/' separator
     232                 :          *------------------------------------------------------------*/
     233              24 :         pszTmpPath[--iTmpPtr] = '\0';
     234             314 :         while( iTmpPtr > 0 && pszTmpPath[iTmpPtr-1] != '/' )
     235                 :         {
     236             266 :             pszTmpPath[--iTmpPtr] = '\0';
     237                 :         }
     238                 : 
     239              24 :         if (iTmpPtr > 0 && VSIStat(pszTmpPath, &sStatBuf) == 0)
     240              20 :             bValidPath = TRUE;
     241                 :     }
     242                 : 
     243              24 :     CPLAssert(iTmpPtr >= 0);
     244                 : 
     245                 :     /*-----------------------------------------------------------------
     246                 :      * Assume that CWD is valid... so an empty path is a valid path
     247                 :      *----------------------------------------------------------------*/
     248              24 :     if (iTmpPtr == 0)
     249               4 :         bValidPath = TRUE;
     250                 : 
     251                 :     /*-----------------------------------------------------------------
     252                 :      * OK, now that we have a valid base, reconstruct the whole path
     253                 :      * by scanning all the sub-directories.  
     254                 :      * If we get to a point where a path component does not exist then
     255                 :      * we simply return the rest of the path as is.
     256                 :      *----------------------------------------------------------------*/
     257              72 :     while(bValidPath && (int)strlen(pszTmpPath) < nTotalLen)
     258                 :     {
     259              24 :         char    **papszDir=NULL;
     260                 :         int     iEntry, iLastPartStart;
     261                 : 
     262              24 :         iLastPartStart = iTmpPtr;
     263              24 :         papszDir = CPLReadDir(pszTmpPath);
     264                 : 
     265                 :         /*-------------------------------------------------------------
     266                 :          * Add one component to the current path
     267                 :          *------------------------------------------------------------*/
     268              24 :         pszTmpPath[iTmpPtr] = pszFname[iTmpPtr];
     269              24 :         iTmpPtr++;
     270             290 :         for( ; pszFname[iTmpPtr] != '\0' && pszFname[iTmpPtr]!='/'; iTmpPtr++)
     271                 :         {
     272             266 :             pszTmpPath[iTmpPtr] = pszFname[iTmpPtr];
     273                 :         }
     274                 : 
     275              48 :         while(iLastPartStart < iTmpPtr && pszTmpPath[iLastPartStart] == '/')
     276               0 :             iLastPartStart++;
     277                 : 
     278                 :         /*-------------------------------------------------------------
     279                 :          * And do a case insensitive search in the current dir...
     280                 :          *------------------------------------------------------------*/
     281             553 :         for(iEntry=0; papszDir && papszDir[iEntry]; iEntry++)
     282                 :         {
     283             529 :             if (EQUAL(pszTmpPath+iLastPartStart, papszDir[iEntry]))
     284                 :             {
     285                 :                 /* Fount it! */
     286               0 :                 strcpy(pszTmpPath+iLastPartStart, papszDir[iEntry]);
     287               0 :                 break;
     288                 :             }
     289                 :         }
     290                 : 
     291              24 :         if (iTmpPtr > 0 && VSIStat(pszTmpPath, &sStatBuf) != 0)
     292              24 :             bValidPath = FALSE;
     293                 : 
     294              24 :         CSLDestroy(papszDir);
     295                 :     }
     296                 : 
     297                 :     /*-----------------------------------------------------------------
     298                 :      * We reached the last valid path component... just copy the rest
     299                 :      * of the path as is.
     300                 :      *----------------------------------------------------------------*/
     301              24 :     if (iTmpPtr < nTotalLen-1)
     302                 :     {
     303               0 :         strncpy(pszTmpPath+iTmpPtr, pszFname+iTmpPtr, nTotalLen-iTmpPtr);
     304                 :     }
     305                 : 
     306                 :     /*-----------------------------------------------------------------
     307                 :      * Update the source buffer and return.
     308                 :      *----------------------------------------------------------------*/
     309              24 :     strcpy(pszFname, pszTmpPath);
     310              24 :     CPLFree(pszTmpPath);
     311                 : 
     312              24 :     return bValidPath;
     313                 : 
     314                 : #endif
     315                 : }
     316                 : 
     317                 : 
     318                 : 
     319                 : 
     320                 : /**********************************************************************
     321                 :  *                       TABAdjustFilenameExtension()
     322                 :  *
     323                 :  * Because Unix filenames are case sensitive and MapInfo datasets often have
     324                 :  * mixed cases filenames, we use this function to find the right filename
     325                 :  * to use ot open a specific file.
     326                 :  *
     327                 :  * This function works directly on the source string, so the filename it
     328                 :  * contains at the end of the call is the one that should be used.
     329                 :  *
     330                 :  * Returns TRUE if one of the extensions worked, and FALSE otherwise.
     331                 :  * If none of the extensions worked then the original extension will NOT be
     332                 :  * restored.
     333                 :  **********************************************************************/
     334              65 : GBool TABAdjustFilenameExtension(char *pszFname)
     335                 : {
     336                 :     VSIStatBuf  sStatBuf;
     337                 :     int         i;
     338                 :     
     339                 :     /*-----------------------------------------------------------------
     340                 :      * First try using filename as provided
     341                 :      *----------------------------------------------------------------*/
     342              65 :     if (VSIStat(pszFname, &sStatBuf) == 0)
     343                 :     {
     344              41 :         return TRUE;
     345                 :     }     
     346                 : 
     347                 :     /*-----------------------------------------------------------------
     348                 :      * Try using uppercase extension (we assume that fname contains a '.')
     349                 :      *----------------------------------------------------------------*/
     350              94 :     for(i = strlen(pszFname)-1; i >= 0 && pszFname[i] != '.'; i--)
     351                 :     {
     352              70 :         pszFname[i] = toupper(pszFname[i]);
     353                 :     }
     354                 : 
     355              24 :     if (VSIStat(pszFname, &sStatBuf) == 0)
     356                 :     {
     357               0 :         return TRUE;
     358                 :     }     
     359                 :     
     360                 :     /*-----------------------------------------------------------------
     361                 :      * Try using lowercase extension
     362                 :      *----------------------------------------------------------------*/
     363              94 :     for(i = strlen(pszFname)-1; i >= 0 && pszFname[i] != '.'; i--)
     364                 :     {
     365              70 :         pszFname[i] = tolower(pszFname[i]);
     366                 :     }
     367                 : 
     368              24 :     if (VSIStat(pszFname, &sStatBuf) == 0)
     369                 :     {
     370               0 :         return TRUE;
     371                 :     }     
     372                 : 
     373                 :     /*-----------------------------------------------------------------
     374                 :      * None of the extensions worked!  
     375                 :      * Try adjusting cases in the whole path and filename 
     376                 :      *----------------------------------------------------------------*/
     377              24 :     return TABAdjustCaseSensitiveFilename(pszFname);
     378                 : }
     379                 : 
     380                 : 
     381                 : 
     382                 : /**********************************************************************
     383                 :  *                       TABGetBasename()
     384                 :  *
     385                 :  * Extract the basename part of a complete file path.
     386                 :  *
     387                 :  * Returns a newly allocated string without the leading path (dirs) and
     388                 :  * the extenstion.  The returned string should be freed using CPLFree().
     389                 :  **********************************************************************/
     390              22 : char *TABGetBasename(const char *pszFname)
     391                 : {
     392              22 :     const char *pszTmp = NULL;
     393                 : 
     394                 :     /*-----------------------------------------------------------------
     395                 :      * Skip leading path or use whole name if no path dividers are
     396                 :      * encountered.
     397                 :      *----------------------------------------------------------------*/
     398              22 :     pszTmp = pszFname + strlen(pszFname) - 1;
     399             313 :     while ( pszTmp != pszFname 
     400                 :             && *pszTmp != '/' && *pszTmp != '\\' ) 
     401             269 :         pszTmp--;
     402                 : 
     403              22 :     if( pszTmp != pszFname )
     404              20 :         pszTmp++;
     405                 : 
     406                 :     /*-----------------------------------------------------------------
     407                 :      * Now allocate our own copy and remove extension
     408                 :      *----------------------------------------------------------------*/
     409              22 :     char *pszBasename = CPLStrdup(pszTmp);
     410                 :     int i;
     411             205 :     for(i=0; pszBasename[i] != '\0'; i++)
     412                 :     {
     413             205 :         if (pszBasename[i] == '.')
     414                 :         {
     415              22 :             pszBasename[i] = '\0';
     416              22 :             break;
     417                 :         }
     418                 :     }
     419                 : 
     420              22 :     return pszBasename;
     421                 : }
     422                 : 
     423                 : 
     424                 : 
     425                 : /**********************************************************************
     426                 :  *                       TAB_CSLLoad()
     427                 :  *
     428                 :  * Same as CSLLoad(), but does not produce an error if it fails... it
     429                 :  * just returns NULL silently instead.
     430                 :  *
     431                 :  * Load a test file into a stringlist.
     432                 :  *
     433                 :  * Lines are limited in length by the size fo the CPLReadLine() buffer.
     434                 :  **********************************************************************/
     435               2 : char **TAB_CSLLoad(const char *pszFname)
     436                 : {
     437                 :     FILE        *fp;
     438                 :     const char  *pszLine;
     439               2 :     char        **papszStrList=NULL;
     440                 : 
     441               2 :     fp = VSIFOpen(pszFname, "rt");
     442                 : 
     443               2 :     if (fp)
     444                 :     {
     445              24 :         while(!VSIFEof(fp))
     446                 :         {
     447              20 :             if ( (pszLine = CPLReadLine(fp)) != NULL )
     448                 :             {
     449              18 :                 papszStrList = CSLAddString(papszStrList, pszLine);
     450                 :             }
     451                 :         }
     452                 : 
     453               2 :         VSIFClose(fp);
     454                 :     }
     455                 : 
     456               2 :     return papszStrList;
     457                 : }
     458                 : 
     459                 : 
     460                 : 
     461                 : /**********************************************************************
     462                 :  *                       TABUnEscapeString()
     463                 :  *
     464                 :  * Convert a string that can possibly contain escaped "\n" chars in
     465                 :  * into into a new one with binary newlines in it.
     466                 :  *
     467                 :  * Tries to work on hte original buffer unless bSrcIsConst=TRUE, in
     468                 :  * which case the original is always untouched and a copy is allocated
     469                 :  * ONLY IF NECESSARY.  This means that the caller should compare the
     470                 :  * return value and the source (pszString) to see if a copy was returned,
     471                 :  * in which case the caller becomes responsible of freeing both the
     472                 :  * source and the copy.
     473                 :  **********************************************************************/
     474               0 : char *TABUnEscapeString(char *pszString, GBool bSrcIsConst)
     475                 : {
     476                 : 
     477                 :     /*-----------------------------------------------------------------
     478                 :      * First check if we need to do any replacement
     479                 :      *----------------------------------------------------------------*/
     480               0 :     if (pszString == NULL || strstr(pszString, "\\n") == NULL)
     481                 :     {
     482               0 :         return pszString;
     483                 :     }
     484                 : 
     485                 :     /*-----------------------------------------------------------------
     486                 :      * Yes, we need to replace at least one "\n"
     487                 :      * We try to work on the original buffer unless we have bSrcIsConst=TRUE
     488                 :      *
     489                 :      * Note that we do not worry about freeing the source buffer when we
     490                 :      * return a copy... it is up to the caller to decide if he needs to 
     491                 :      * free the source based on context and by comparing pszString with 
     492                 :      * the returned pointer (pszWorkString) to see if they are identical.
     493                 :      *----------------------------------------------------------------*/
     494               0 :     char *pszWorkString = NULL;
     495               0 :     int i =0;
     496               0 :     int j =0;
     497                 : 
     498               0 :     if (bSrcIsConst)
     499                 :     {
     500                 :         // We have to create a copy to work on.
     501                 :         pszWorkString = (char *)CPLMalloc(sizeof(char) * 
     502               0 :                                           (strlen(pszString) +1));
     503                 :     }
     504                 :     else
     505                 :     {
     506                 :         // We'll work on the original.
     507               0 :         pszWorkString = pszString;
     508                 :     }
     509                 : 
     510                 : 
     511               0 :     while (pszString[i])
     512                 :     {
     513               0 :         if (pszString[i] =='\\' && 
     514                 :             pszString[i+1] == 'n')
     515                 :         {
     516               0 :             pszWorkString[j++] = '\n';
     517               0 :             i+= 2;
     518                 :         }
     519               0 :         else if (pszString[i] =='\\' && 
     520                 :                  pszString[i+1] == '\\')
     521                 :         {
     522               0 :             pszWorkString[j++] = '\\';
     523               0 :             i+= 2;
     524                 :         }
     525                 :         else
     526                 :         {
     527               0 :             pszWorkString[j++] = pszString[i++];
     528                 :         }
     529                 :     }
     530               0 :     pszWorkString[j++] = '\0';
     531                 :    
     532               0 :     return pszWorkString;
     533                 : }
     534                 : 
     535                 : /**********************************************************************
     536                 :  *                       TABEscapeString()
     537                 :  *
     538                 :  * Convert a string that can possibly contain binary "\n" chars in
     539                 :  * into into a new one with escaped newlines ("\\" + "n") in it.
     540                 :  *
     541                 :  * The function returns the original string pointer if it did not need to
     542                 :  * be modified, or a copy that has to be freed by the caller if the
     543                 :  * string had to be modified.
     544                 :  *
     545                 :  * It is up to the caller to decide if he needs to free the returned 
     546                 :  * string by comparing the source (pszString) pointer with the returned
     547                 :  * pointer (pszWorkString) to see if they are identical.
     548                 :  **********************************************************************/
     549               0 : char *TABEscapeString(char *pszString)
     550                 : {
     551                 :     /*-----------------------------------------------------------------
     552                 :      * First check if we need to do any replacement
     553                 :      *----------------------------------------------------------------*/
     554               0 :     if (pszString == NULL || strchr(pszString, '\n') == NULL)
     555                 :     {
     556               0 :         return pszString;
     557                 :     }
     558                 : 
     559                 :     /*-----------------------------------------------------------------
     560                 :      * OK, we need to do some replacements... alloc a copy big enough
     561                 :      * to hold the worst possible case
     562                 :      *----------------------------------------------------------------*/
     563                 :     char *pszWorkString = (char *)CPLMalloc(2*sizeof(char) * 
     564               0 :                                             (strlen(pszString) +1));
     565                 : 
     566               0 :     int i =0;
     567               0 :     int j =0;
     568                 : 
     569               0 :     while (pszString[i])
     570                 :     {
     571               0 :         if (pszString[i] =='\n')
     572                 :         {
     573               0 :             pszWorkString[j++] = '\\';
     574               0 :             pszWorkString[j++] = 'n';
     575               0 :             i++;
     576                 :         }
     577               0 :         else if (pszString[i] =='\\')
     578                 :         {
     579               0 :             pszWorkString[j++] = '\\';
     580               0 :             pszWorkString[j++] = '\\';
     581               0 :             i++;
     582                 :         }
     583                 :         else
     584                 :         {
     585               0 :             pszWorkString[j++] = pszString[i++];
     586                 :         }
     587                 :     }
     588               0 :     pszWorkString[j++] = '\0';
     589                 : 
     590               0 :     return pszWorkString;
     591                 : }
     592                 : 
     593                 : /**********************************************************************
     594                 :  *                       TABCleanFieldName()
     595                 :  *
     596                 :  * Return a copy of pszSrcName that contains only valid characters for a
     597                 :  * TAB field name.  All invalid characters are replaced by '_'.
     598                 :  *
     599                 :  * The returned string should be freed by the caller.
     600                 :  **********************************************************************/
     601              64 : char *TABCleanFieldName(const char *pszSrcName)
     602                 : {
     603                 :     char *pszNewName;
     604              64 :     int numInvalidChars = 0;
     605                 : 
     606              64 :     pszNewName = CPLStrdup(pszSrcName);
     607                 : 
     608              64 :     if (strlen(pszNewName) > 31)
     609                 :     {
     610               0 :         pszNewName[31] = '\0';
     611                 :         CPLError(CE_Warning, TAB_WarningInvalidFieldName,
     612                 :                  "Field name '%s' is longer than the max of 31 characters. "
     613               0 :                  "'%s' will be used instead.", pszSrcName, pszNewName);
     614                 :     }
     615                 : 
     616                 : #if defined(_WIN32) && !defined(unix) && !defined(WIN32CE)
     617                 :     /*-----------------------------------------------------------------
     618                 :      * On Windows, check if we're using a double-byte codepage, and
     619                 :      * if so then just keep the field name as is... 
     620                 :      *----------------------------------------------------------------*/
     621                 :     if (_getmbcp() != 0)
     622                 :         return pszNewName;
     623                 : #endif
     624                 : 
     625                 :     /*-----------------------------------------------------------------
     626                 :      * According to the MapInfo User's Guide (p. 240, v5.5)
     627                 :      * New Table Command:
     628                 :      *  Name:
     629                 :      * Displays the field name in the name box. You can also enter new field
     630                 :      * names here. Defaults are Field1, Field2, etc. A field name can contain
     631                 :      * up to 31 alphanumeric characters. Use letters, numbers, and the 
     632                 :      * underscore. Do not use spaces; instead, use the underscore character
     633                 :      * (_) to separate words in a field name. Use upper and lower case for
     634                 :      * legibility, but MapInfo is not case-sensitive.
     635                 :      *
     636                 :      * It was also verified that extended chars with accents are also 
     637                 :      * accepted.
     638                 :      *----------------------------------------------------------------*/
     639             448 :     for(int i=0; pszSrcName && pszSrcName[i] != '\0'; i++)
     640                 :     {
     641             384 :         if ( !( pszSrcName[i] == '_' ||
     642                 :                 (pszSrcName[i]>='0' && pszSrcName[i]<='9') || 
     643                 :                 (pszSrcName[i]>='a' && pszSrcName[i]<='z') || 
     644                 :                 (pszSrcName[i]>='A' && pszSrcName[i]<='Z') ||
     645                 :                 (GByte)pszSrcName[i]>=192 ) )
     646                 :         {
     647               0 :             pszNewName[i] = '_';
     648               0 :             numInvalidChars++;
     649                 :         }
     650                 :     }
     651                 : 
     652              64 :     if (numInvalidChars > 0)
     653                 :     {
     654                 :         CPLError(CE_Warning, TAB_WarningInvalidFieldName,
     655                 :                  "Field name '%s' contains invalid characters. "
     656               0 :                  "'%s' will be used instead.", pszSrcName, pszNewName);
     657                 :     }
     658                 : 
     659              64 :     return pszNewName;
     660                 : }
     661                 : 
     662                 : 
     663                 : /**********************************************************************
     664                 :  * MapInfo Units string to numeric ID conversion
     665                 :  **********************************************************************/
     666                 : typedef struct 
     667                 : {
     668                 :     int         nUnitId;
     669                 :     const char *pszAbbrev;
     670                 : } MapInfoUnitsInfo;
     671                 : 
     672                 : static MapInfoUnitsInfo gasUnitsList[] = 
     673                 : {
     674                 :     {0, "mi"},
     675                 :     {1, "km"},
     676                 :     {2, "in"},
     677                 :     {3, "ft"},
     678                 :     {4, "yd"},
     679                 :     {5, "mm"},
     680                 :     {6, "cm"},
     681                 :     {7, "m"},
     682                 :     {8, "survey ft"},
     683                 :     {9, "nmi"},
     684                 :     {30, "li"},
     685                 :     {31, "ch"},
     686                 :     {32, "rd"},
     687                 :     {-1, NULL}
     688                 : };
     689                 : 
     690                 : 
     691                 : /**********************************************************************
     692                 :  *                       TABUnitIdToString()
     693                 :  *
     694                 :  * Return the MIF units name for specified units id.
     695                 :  * Return "" if no match found.
     696                 :  *
     697                 :  * The returned string should not be freed by the caller.
     698                 :  **********************************************************************/
     699               0 : const char *TABUnitIdToString(int nId)
     700                 : {
     701                 :     MapInfoUnitsInfo *psList;
     702                 : 
     703               0 :     psList = gasUnitsList;
     704                 : 
     705               0 :     while(psList->nUnitId != -1)
     706                 :     {
     707               0 :         if (psList->nUnitId == nId) 
     708               0 :             return psList->pszAbbrev;
     709               0 :         psList++;
     710                 :     }
     711                 : 
     712               0 :     return "";
     713                 : }
     714                 : 
     715                 : /**********************************************************************
     716                 :  *                       TABUnitIdFromString()
     717                 :  *
     718                 :  * Return the units ID for specified MIF units name
     719                 :  *
     720                 :  * Returns -1 if no match found.
     721                 :  **********************************************************************/
     722               0 : int TABUnitIdFromString(const char *pszName)
     723                 : {
     724                 :     MapInfoUnitsInfo *psList;
     725                 : 
     726               0 :     psList = gasUnitsList;
     727                 : 
     728               0 :     while(psList->nUnitId != -1)
     729                 :     {
     730               0 :         if (EQUAL(psList->pszAbbrev, pszName)) 
     731               0 :             return psList->nUnitId;
     732               0 :         psList++;
     733                 :     }
     734                 : 
     735               0 :     return -1;
     736                 : }
     737                 : 

Generated by: LTP GCOV extension version 1.5