LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/avc - avc_misc.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 139 51 36.7 %
Date: 2011-12-18 Functions: 7 5 71.4 %

       1                 : /**********************************************************************
       2                 :  * $Id: avc_misc.c,v 1.9 2005/06/03 03:49:59 daniel Exp $
       3                 :  *
       4                 :  * Name:     avc_misc.c
       5                 :  * Project:  Arc/Info vector coverage (AVC)  BIN<->E00 conversion library
       6                 :  * Language: ANSI C
       7                 :  * Purpose:  Misc. functions used by several parts of the library
       8                 :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
       9                 :  *
      10                 :  **********************************************************************
      11                 :  * Copyright (c) 1999-2005, Daniel Morissette
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  * 
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  * 
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      24                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  **********************************************************************
      31                 :  *
      32                 :  * $Log: avc_misc.c,v $
      33                 :  * Revision 1.9  2005/06/03 03:49:59  daniel
      34                 :  * Update email address, website url, and copyright dates
      35                 :  *
      36                 :  * Revision 1.8  2004/08/31 21:00:20  warmerda
      37                 :  * Applied Carl Anderson's patch to reduce the amount of stating while
      38                 :  * trying to discover filename "case" on Unix in AVCAdjustCaseSensitiveFilename.
      39                 :  * http://bugzilla.remotesensing.org/show_bug.cgi?id=314
      40                 :  *
      41                 :  * Revision 1.7  2001/11/25 21:38:01  daniel
      42                 :  * Remap '\\' to '/' in AVCAdjustCaseSensitiveFilename() on Unix.
      43                 :  *
      44                 :  * Revision 1.6  2001/11/25 21:15:23  daniel
      45                 :  * Added hack (AVC_MAP_TYPE40_TO_DOUBLE) to map type 40 fields bigger than 8
      46                 :  * digits to double precision as we generate E00 output (bug599)
      47                 :  *
      48                 :  * Revision 1.5  2000/09/26 20:21:04  daniel
      49                 :  * Added AVCCoverPC write
      50                 :  *
      51                 :  * Revision 1.4  2000/09/22 19:45:21  daniel
      52                 :  * Switch to MIT-style license
      53                 :  *
      54                 :  * Revision 1.3  2000/01/10 02:53:21  daniel
      55                 :  * Added AVCAdjustCaseSensitiveFilename() and AVCFileExists()
      56                 :  *
      57                 :  * Revision 1.2  1999/08/23 18:24:27  daniel
      58                 :  * Fixed support for attribute fields of type 40
      59                 :  *
      60                 :  * Revision 1.1  1999/05/11 02:34:46  daniel
      61                 :  * Initial revision
      62                 :  *
      63                 :  **********************************************************************/
      64                 : 
      65                 : #include "avc.h"
      66                 : 
      67                 : 
      68                 : /**********************************************************************
      69                 :  *                          AVCE00ComputeRecSize()
      70                 :  *
      71                 :  * Computes the number of chars required to generate a E00 attribute
      72                 :  * table record.
      73                 :  *
      74                 :  * Returns -1 on error, i.e. if it encounters an unsupported field type.
      75                 :  **********************************************************************/
      76               8 : int _AVCE00ComputeRecSize(int numFields, AVCFieldInfo *pasDef,
      77                 :                           GBool bMapType40ToDouble)
      78                 : {
      79               8 :     int i, nType, nBufSize=0;
      80                 : 
      81                 :     /*------------------------------------------------------------- 
      82                 :      * Add up the nbr of chars used by each field
      83                 :      *------------------------------------------------------------*/
      84              54 :     for(i=0; i < numFields; i++)
      85                 :     {
      86              46 :         nType = pasDef[i].nType1*10;
      87              50 :         if (nType ==  AVC_FT_DATE || nType == AVC_FT_CHAR ||
      88                 :             nType == AVC_FT_FIXINT )
      89                 :         {
      90               4 :             nBufSize += pasDef[i].nSize;
      91                 :         }
      92              56 :         else if (nType == AVC_FT_BININT && pasDef[i].nSize == 4)
      93              14 :             nBufSize += 11;
      94              28 :         else if (nType == AVC_FT_BININT && pasDef[i].nSize == 2)
      95               0 :             nBufSize += 6;
      96              28 :         else if (bMapType40ToDouble && 
      97               0 :                  nType == AVC_FT_FIXNUM && pasDef[i].nSize > 8)
      98                 :         {
      99                 :             /* See explanation in AVCE00GenTableHdr() about this hack to remap
     100                 :              * type 40 fields to double precision floats.
     101                 :              */
     102               0 :             nBufSize += 24;  /* Remap to double float */
     103                 :         }
     104              56 :         else if ((nType == AVC_FT_BINFLOAT && pasDef[i].nSize == 4) ||
     105                 :                   nType == AVC_FT_FIXNUM )
     106              28 :             nBufSize += 14;
     107               0 :         else if (nType == AVC_FT_BINFLOAT && pasDef[i].nSize == 8)
     108               0 :             nBufSize += 24;
     109                 :         else
     110                 :         {
     111                 :             /*-----------------------------------------------------
     112                 :              * Hummm... unsupported field type...
     113                 :              *----------------------------------------------------*/
     114               0 :             CPLError(CE_Failure, CPLE_NotSupported,
     115                 :                      "_AVCE00ComputeRecSize(): Unsupported field type: "
     116                 :                      "(type=%d, size=%d)",
     117               0 :                      nType, pasDef[i].nSize);
     118               0 :             return -1;
     119                 :         }
     120                 :     }
     121                 : 
     122               8 :     return nBufSize;
     123                 : }
     124                 : 
     125                 : 
     126                 : 
     127                 : /**********************************************************************
     128                 :  *                          _AVCDestroyTableFields()
     129                 :  *
     130                 :  * Release all memory associated with an array of AVCField structures.
     131                 :  **********************************************************************/
     132               9 : void _AVCDestroyTableFields(AVCTableDef *psTableDef, AVCField *pasFields)
     133                 : {
     134                 :     int     i, nFieldType;
     135                 : 
     136               9 :     if (pasFields)
     137                 :     {
     138              57 :         for(i=0; i<psTableDef->numFields; i++)
     139                 :         {
     140              48 :             nFieldType = psTableDef->pasFieldDef[i].nType1*10;
     141              48 :             if (nFieldType == AVC_FT_DATE   ||
     142                 :                 nFieldType == AVC_FT_CHAR   ||
     143                 :                 nFieldType == AVC_FT_FIXINT ||
     144                 :                 nFieldType == AVC_FT_FIXNUM)
     145                 :             {
     146               4 :                 CPLFree(pasFields[i].pszStr);
     147                 :             }
     148                 :         }
     149               9 :         CPLFree(pasFields);
     150                 :     }
     151                 : 
     152               9 : }
     153                 : 
     154                 : /**********************************************************************
     155                 :  *                          _AVCDestroyTableDef()
     156                 :  *
     157                 :  * Release all memory associated with a AVCTableDef structure.
     158                 :  *
     159                 :  **********************************************************************/
     160               9 : void _AVCDestroyTableDef(AVCTableDef *psTableDef)
     161                 : {
     162               9 :     if (psTableDef)
     163                 :     {
     164               9 :         CPLFree(psTableDef->pasFieldDef);
     165               9 :         CPLFree(psTableDef);
     166                 :     }
     167               9 : }
     168                 : 
     169                 : 
     170                 : /**********************************************************************
     171                 :  *                          _AVCDupTableDef()
     172                 :  *
     173                 :  * Create a new copy of a AVCTableDef structure.
     174                 :  **********************************************************************/
     175               0 : AVCTableDef *_AVCDupTableDef(AVCTableDef *psSrcDef)
     176                 : {
     177                 :     AVCTableDef *psNewDef;
     178                 : 
     179               0 :     if (psSrcDef == NULL)
     180               0 :         return NULL;
     181                 : 
     182               0 :     psNewDef = (AVCTableDef*)CPLMalloc(1*sizeof(AVCTableDef));
     183                 : 
     184               0 :     memcpy(psNewDef, psSrcDef, sizeof(AVCTableDef));
     185                 : 
     186               0 :     psNewDef->pasFieldDef = (AVCFieldInfo*)CPLMalloc(psSrcDef->numFields*
     187                 :                                                      sizeof(AVCFieldInfo));
     188                 : 
     189               0 :     memcpy(psNewDef->pasFieldDef, psSrcDef->pasFieldDef, 
     190                 :            psSrcDef->numFields*sizeof(AVCFieldInfo));
     191                 : 
     192               0 :    return psNewDef;
     193                 : }
     194                 : 
     195                 : 
     196                 : /**********************************************************************
     197                 :  *                          AVCFileExists()
     198                 :  *
     199                 :  * Returns TRUE if a file with the specified name exists in the
     200                 :  * specified directory.
     201                 :  *
     202                 :  * For now I simply try to fopen() the file ... would it be more
     203                 :  * efficient to use stat() ???
     204                 :  **********************************************************************/
     205               2 : GBool AVCFileExists(const char *pszPath, const char *pszName)
     206                 : {
     207                 :     char        *pszBuf;
     208               2 :     GBool       bFileExists = FALSE;
     209                 :     FILE        *fp;
     210                 : 
     211               2 :     pszBuf = (char*)CPLMalloc((strlen(pszPath)+strlen(pszName)+1)*
     212                 :                               sizeof(char));
     213               2 :     sprintf(pszBuf, "%s%s", pszPath, pszName);
     214                 : 
     215               2 :     AVCAdjustCaseSensitiveFilename(pszBuf);
     216                 : 
     217               2 :     if ((fp = VSIFOpen(pszBuf, "rb")) != NULL)
     218                 :     {
     219               2 :         bFileExists = TRUE;
     220               2 :         VSIFClose(fp);
     221                 :     }
     222                 : 
     223               2 :     CPLFree(pszBuf);
     224                 : 
     225               2 :     return bFileExists;
     226                 : }
     227                 : 
     228                 : /**********************************************************************
     229                 :  *                     AVCAdjustCaseSensitiveFilename()
     230                 :  *
     231                 :  * Scan a filename and its path, adjust uppercase/lowercases if
     232                 :  * necessary, and return a reference to that filename.
     233                 :  *
     234                 :  * This function works on the original buffer and returns a reference to it.
     235                 :  * It does nothing on Windows systems where filenames are not case sensitive.
     236                 :  *
     237                 :  * NFW: It seems like this could be made somewhat more efficient by
     238                 :  * getting a directory listing and doing a case insensitive search in 
     239                 :  * that list rather than all this stating that can be very expensive
     240                 :  * in some circumstances.  However, at least with Carl's fix this is
     241                 :  * somewhat faster.
     242                 :  * see: http://buzilla.remotesensing.org/show_bug.cgi?id=314
     243                 :  **********************************************************************/
     244              21 : char *AVCAdjustCaseSensitiveFilename(char *pszFname)
     245                 : {
     246                 : 
     247                 : #ifdef _WIN32
     248                 :     /*-----------------------------------------------------------------
     249                 :      * Nothing to do on Windows
     250                 :      *----------------------------------------------------------------*/
     251                 :     return pszFname;
     252                 : 
     253                 : #else
     254                 :     /*-----------------------------------------------------------------
     255                 :      * Unix case.
     256                 :      *----------------------------------------------------------------*/
     257                 :     VSIStatBuf  sStatBuf;
     258              21 :     char        *pszTmpPath = NULL;
     259                 :     int         nTotalLen, iTmpPtr;
     260                 :     GBool       bValidPath;
     261                 : 
     262                 :     /*-----------------------------------------------------------------
     263                 :      * Remap '\\' to '/'
     264                 :      *----------------------------------------------------------------*/
     265             734 :     for(pszTmpPath = pszFname; *pszTmpPath != '\0'; pszTmpPath++)
     266                 :     {
     267             713 :         if (*pszTmpPath == '\\')
     268               0 :             *pszTmpPath = '/';
     269                 :     }
     270                 : 
     271                 :     /*-----------------------------------------------------------------
     272                 :      * First check if the filename is OK as is.
     273                 :      *----------------------------------------------------------------*/
     274              21 :     if (VSIStat(pszFname, &sStatBuf) == 0)
     275                 :     {
     276              13 :         return pszFname;
     277                 :     }
     278                 : 
     279               8 :     pszTmpPath = CPLStrdup(pszFname);
     280               8 :     nTotalLen = strlen(pszTmpPath);
     281                 : 
     282                 :     /*-----------------------------------------------------------------
     283                 :      * Try all lower case, check if the filename is OK as that.
     284                 :      *----------------------------------------------------------------*/
     285             312 :     for (iTmpPtr=0; iTmpPtr< nTotalLen; iTmpPtr++)
     286                 :     {
     287             304 :         if ( pszTmpPath[iTmpPtr] >= 0x41 && pszTmpPath[iTmpPtr] <= 0x5a )
     288              24 :             pszTmpPath[iTmpPtr] += 32;
     289                 :     }
     290                 : 
     291               8 :     if (VSIStat(pszTmpPath, &sStatBuf) == 0)
     292                 :     {
     293               8 :         strcpy(pszFname, pszTmpPath);
     294               8 :         CPLFree(pszTmpPath);
     295               8 :         return pszFname;
     296                 :     }
     297                 : 
     298                 :     /*-----------------------------------------------------------------
     299                 :      * Try all upper case, check if the filename is OK as that.
     300                 :      *----------------------------------------------------------------*/
     301               0 :     for (iTmpPtr=0; iTmpPtr< nTotalLen; iTmpPtr++)
     302                 :     {
     303               0 :         if ( pszTmpPath[iTmpPtr] >= 0x61 && pszTmpPath[iTmpPtr] <= 0x7a )
     304               0 :             pszTmpPath[iTmpPtr] -= 32;
     305                 :     }
     306                 : 
     307               0 :     if (VSIStat(pszTmpPath, &sStatBuf) == 0)
     308                 :     {
     309               0 :         strcpy(pszFname, pszTmpPath);
     310               0 :         CPLFree(pszTmpPath);
     311               0 :         return pszFname;
     312                 :     }
     313                 : 
     314                 :     /*-----------------------------------------------------------------
     315                 :      * OK, file either does not exist or has the wrong cases... we'll
     316                 :      * go backwards until we find a portion of the path that is valid.
     317                 :      *----------------------------------------------------------------*/
     318               0 :     iTmpPtr = nTotalLen;
     319               0 :     bValidPath = FALSE;
     320                 : 
     321               0 :     while(iTmpPtr > 0 && !bValidPath)
     322                 :     {
     323                 :         /*-------------------------------------------------------------
     324                 :          * Move back to the previous '/' separator
     325                 :          *------------------------------------------------------------*/
     326               0 :         pszTmpPath[--iTmpPtr] = '\0';
     327               0 :         while( iTmpPtr > 0 && pszTmpPath[iTmpPtr-1] != '/' )
     328                 :         {
     329               0 :             pszTmpPath[--iTmpPtr] = '\0';
     330                 :         }
     331                 : 
     332               0 :         if (iTmpPtr > 0 && VSIStat(pszTmpPath, &sStatBuf) == 0)
     333               0 :             bValidPath = TRUE;
     334                 :     }
     335                 : 
     336               0 :     CPLAssert(iTmpPtr >= 0);
     337                 : 
     338                 :     /*-----------------------------------------------------------------
     339                 :      * Assume that CWD is valid... so an empty path is a valid path
     340                 :      *----------------------------------------------------------------*/
     341               0 :     if (iTmpPtr == 0)
     342               0 :         bValidPath = TRUE;
     343                 : 
     344                 :     /*-----------------------------------------------------------------
     345                 :      * OK, now that we have a valid base, reconstruct the whole path
     346                 :      * by scanning all the sub-directories.  
     347                 :      * If we get to a point where a path component does not exist then
     348                 :      * we simply return the rest of the path as is.
     349                 :      *----------------------------------------------------------------*/
     350               0 :     while(bValidPath && strlen(pszTmpPath) < nTotalLen)
     351                 :     {
     352               0 :         char    **papszDir=NULL;
     353                 :         int     iEntry, iLastPartStart;
     354                 : 
     355               0 :         iLastPartStart = iTmpPtr;
     356               0 :         papszDir = CPLReadDir(pszTmpPath);
     357                 : 
     358                 :         /*-------------------------------------------------------------
     359                 :          * Add one component to the current path
     360                 :          *------------------------------------------------------------*/
     361               0 :         pszTmpPath[iTmpPtr] = pszFname[iTmpPtr];
     362               0 :         iTmpPtr++;
     363               0 :         for( ; pszFname[iTmpPtr] != '\0' && pszFname[iTmpPtr]!='/'; iTmpPtr++)
     364                 :         {
     365               0 :             pszTmpPath[iTmpPtr] = pszFname[iTmpPtr];
     366                 :         }
     367                 : 
     368               0 :         while(iLastPartStart < iTmpPtr && pszTmpPath[iLastPartStart] == '/')
     369               0 :             iLastPartStart++;
     370                 : 
     371                 :         /*-------------------------------------------------------------
     372                 :          * And do a case insensitive search in the current dir...
     373                 :          *------------------------------------------------------------*/
     374               0 :         for(iEntry=0; papszDir && papszDir[iEntry]; iEntry++)
     375                 :         {
     376               0 :             if (EQUAL(pszTmpPath+iLastPartStart, papszDir[iEntry]))
     377                 :             {
     378                 :                 /* Fount it! */
     379               0 :                 strcpy(pszTmpPath+iLastPartStart, papszDir[iEntry]);
     380               0 :                 break;
     381                 :             }
     382                 :         }
     383                 : 
     384               0 :         if (iTmpPtr > 0 && VSIStat(pszTmpPath, &sStatBuf) != 0)
     385               0 :             bValidPath = FALSE;
     386                 : 
     387               0 :         CSLDestroy(papszDir);
     388                 :     }
     389                 : 
     390                 :     /*-----------------------------------------------------------------
     391                 :      * We reached the last valid path component... just copy the rest
     392                 :      * of the path as is.
     393                 :      *----------------------------------------------------------------*/
     394               0 :     if (iTmpPtr < nTotalLen-1)
     395                 :     {
     396               0 :         strncpy(pszTmpPath+iTmpPtr, pszFname+iTmpPtr, nTotalLen-iTmpPtr);
     397                 :     }
     398                 : 
     399                 :     /*-----------------------------------------------------------------
     400                 :      * Update the source buffer and return.
     401                 :      *----------------------------------------------------------------*/
     402               0 :     strcpy(pszFname, pszTmpPath);
     403               0 :     CPLFree(pszTmpPath);
     404                 : 
     405               0 :     return pszFname;
     406                 : 
     407                 : #endif
     408                 : }
     409                 : 
     410                 : 
     411                 : 
     412                 : /**********************************************************************
     413                 :  *                          AVCPrintRealValue()
     414                 :  *
     415                 :  * Format a floating point value according to the specified coverage
     416                 :  * precision (AVC_SINGLE/DOUBLE_PREC),  and append the formatted value 
     417                 :  * to the end of the pszBuf buffer.
     418                 :  *
     419                 :  * The function returns the number of characters added to the buffer.
     420                 :  **********************************************************************/
     421               0 : int  AVCPrintRealValue(char *pszBuf, int nPrecision, AVCFileType eType,
     422                 :                         double dValue)
     423                 : {
     424                 :     static int numExpDigits=-1;
     425               0 :     int        nLen = 0;
     426                 : 
     427                 :     /* WIN32 systems' printf for floating point output generates 3
     428                 :      * digits exponents (ex: 1.23E+012), but E00 files must have 2 digits
     429                 :      * exponents (ex: 1.23E+12).
     430                 :      * Run a test (only once per prg execution) to establish the number
     431                 :      * of exponent digits on the current platform.
     432                 :      */
     433               0 :     if (numExpDigits == -1)
     434                 :     {
     435                 :         char szBuf[50];
     436                 :         int  i;
     437                 : 
     438               0 :         sprintf(szBuf, "%10.7E", 123.45);
     439               0 :         numExpDigits = 0;
     440               0 :         for(i=strlen(szBuf)-1; i>0; i--)
     441                 :         {
     442               0 :             if (szBuf[i] == '+' || szBuf[i] == '-')
     443                 :                 break;
     444               0 :             numExpDigits++;
     445                 :         }
     446                 :     }
     447                 : 
     448                 :     /* We will append the value at the end of the current buffer contents.
     449                 :      */
     450               0 :     pszBuf = pszBuf+strlen(pszBuf);
     451                 : 
     452               0 :     if (dValue < 0.0)
     453                 :     {
     454               0 :         *pszBuf = '-';
     455               0 :         dValue = -1.0*dValue;
     456                 :     }
     457                 :     else
     458               0 :         *pszBuf = ' ';
     459                 : 
     460                 : 
     461                 :     /* Just to make things more complicated, double values are 
     462                 :      * output in a different format in attribute tables than in 
     463                 :      * the other files!
     464                 :      */
     465               0 :     if (nPrecision == AVC_FORMAT_DBF_FLOAT)
     466                 :     {
     467                 :         /* Float stored in DBF table in PC coverages */
     468               0 :         sprintf(pszBuf+1, "%9.6E", dValue);
     469               0 :         nLen = 13;
     470                 :     }
     471               0 :     else if (nPrecision == AVC_DOUBLE_PREC && eType == AVCFileTABLE)
     472                 :     {
     473               0 :         sprintf(pszBuf+1, "%20.17E", dValue);
     474               0 :         nLen = 24;
     475                 :     }
     476               0 :     else if (nPrecision == AVC_DOUBLE_PREC)
     477                 :     {
     478               0 :         sprintf(pszBuf+1, "%17.14E", dValue);
     479               0 :         nLen = 21;
     480                 :     }
     481                 :     else 
     482                 :     {
     483               0 :         sprintf(pszBuf+1, "%10.7E", dValue);
     484               0 :         nLen = 14;
     485                 :     }
     486                 : 
     487                 :     /* Adjust number of exponent digits if necessary
     488                 :      */
     489               0 :     if (numExpDigits > 2)
     490                 :     {
     491                 :         int n;
     492               0 :         n = strlen(pszBuf);
     493                 :         
     494               0 :         pszBuf[n - numExpDigits]    = pszBuf[n-2];
     495               0 :         pszBuf[n - numExpDigits +1] = pszBuf[n-1];
     496               0 :         pszBuf[n - numExpDigits +2] = '\0';
     497                 :     }
     498                 : 
     499                 :     /* Just make sure that the actual output length is what we expected.
     500                 :      */
     501               0 :     CPLAssert(strlen(pszBuf) == nLen);
     502                 : 
     503               0 :     return nLen;
     504                 : }
     505                 : 
     506                 : 

Generated by: LCOV version 1.7