LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/avc - avc_rawbin.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 171 94 55.0 %
Date: 2012-12-26 Functions: 18 10 55.6 %

       1                 : /**********************************************************************
       2                 :  * $Id: avc_rawbin.c,v 1.14 2008/07/23 20:51:38 dmorissette Exp $
       3                 :  *
       4                 :  * Name:     avc_rawbin.c
       5                 :  * Project:  Arc/Info vector coverage (AVC)  BIN->E00 conversion library
       6                 :  * Language: ANSI C
       7                 :  * Purpose:  Raw Binary file access functions.
       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_rawbin.c,v $
      33                 :  * Revision 1.14  2008/07/23 20:51:38  dmorissette
      34                 :  * Fixed GCC 4.1.x compile warnings related to use of char vs unsigned char
      35                 :  * (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2495)
      36                 :  *
      37                 :  * Revision 1.13  2005/06/03 03:49:59  daniel
      38                 :  * Update email address, website url, and copyright dates
      39                 :  *
      40                 :  * Revision 1.12  2004/08/19 23:41:04  warmerda
      41                 :  * fixed pointer aliasing optimization bug
      42                 :  *
      43                 :  * Revision 1.11  2000/09/22 19:45:21  daniel
      44                 :  * Switch to MIT-style license
      45                 :  *
      46                 :  * Revision 1.10  2000/05/29 15:36:07  daniel
      47                 :  * Fixed compile warning
      48                 :  *
      49                 :  * Revision 1.9  2000/05/29 15:31:31  daniel
      50                 :  * Added Japanese DBCS support
      51                 :  *
      52                 :  * Revision 1.8  2000/01/10 02:59:11  daniel
      53                 :  * Fixed problem in AVCRawBinOpen() when file not found
      54                 :  *
      55                 :  * Revision 1.7  1999/12/24 07:18:34  daniel
      56                 :  * Added PC Arc/Info coverages support
      57                 :  *
      58                 :  * Revision 1.6  1999/08/29 15:05:43  daniel
      59                 :  * Added source filename in "Attempt to read past EOF" error message
      60                 :  *
      61                 :  * Revision 1.5  1999/06/08 22:09:03  daniel
      62                 :  * Allow opening file with "r+" (but no real random access support yet)
      63                 :  *
      64                 :  * Revision 1.4  1999/05/11 02:10:51  daniel
      65                 :  * Added write support
      66                 :  *
      67                 :  * Revision 1.3  1999/03/03 19:55:21  daniel
      68                 :  * Fixed syntax error in the CPL_MSB version of AVCRawBinReadInt32()
      69                 :  *
      70                 :  * Revision 1.2  1999/02/25 04:20:08  daniel
      71                 :  * Modified AVCRawBinEOF() to detect EOF even if AVCRawBinFSeek() was used.
      72                 :  *
      73                 :  * Revision 1.1  1999/01/29 16:28:52  daniel
      74                 :  * Initial revision
      75                 :  *
      76                 :  **********************************************************************/
      77                 : 
      78                 : #include "avc.h"
      79                 : #include "avc_mbyte.h"
      80                 : 
      81                 : /*---------------------------------------------------------------------
      82                 :  * Define a static flag and set it with the byte ordering on this machine
      83                 :  * we will then compare with this value to decide if we nned to swap
      84                 :  * bytes or not.
      85                 :  *
      86                 :  * CPL_MSB or CPL_LSB should be set in the makefile... the default is
      87                 :  * CPL_LSB.
      88                 :  *--------------------------------------------------------------------*/
      89                 : #ifndef CPL_LSB
      90                 : static AVCByteOrder geSystemByteOrder = AVCBigEndian;
      91                 : #else
      92                 : static AVCByteOrder geSystemByteOrder = AVCLittleEndian;
      93                 : #endif
      94                 : 
      95                 : /*=====================================================================
      96                 :  * Stuff related to buffered reading of raw binary files
      97                 :  *====================================================================*/
      98                 : 
      99                 : /**********************************************************************
     100                 :  *                          AVCRawBinOpen()
     101                 :  *
     102                 :  * Open a binary file for reading with buffering, or writing.
     103                 :  *
     104                 :  * Returns a valid AVCRawBinFile structure, or NULL if the file could
     105                 :  * not be opened or created.
     106                 :  *
     107                 :  * AVCRawBinClose() will eventually have to be called to release the 
     108                 :  * resources used by the AVCRawBinFile structure.
     109                 :  **********************************************************************/
     110              10 : AVCRawBinFile *AVCRawBinOpen(const char *pszFname, const char *pszAccess,
     111                 :                              AVCByteOrder eFileByteOrder,
     112                 :                              AVCDBCSInfo *psDBCSInfo)
     113                 : {
     114                 :     AVCRawBinFile *psFile;
     115                 : 
     116              10 :     psFile = (AVCRawBinFile*)CPLCalloc(1, sizeof(AVCRawBinFile));
     117                 : 
     118                 :     /*-----------------------------------------------------------------
     119                 :      * Validate access mode and open/create file.  
     120                 :      * For now we support only: "r" for read-only or "w" for write-only
     121                 :      * or "a" for append.
     122                 :      *
     123                 :      * A case for "r+" is included here, but random access is not
     124                 :      * properly supported yet... so this option should be used with care.
     125                 :      *----------------------------------------------------------------*/
     126              10 :     if (EQUALN(pszAccess, "r+", 2))
     127                 :     {
     128               0 :         psFile->eAccess = AVCReadWrite;
     129               0 :         psFile->fp = VSIFOpen(pszFname, "r+b");
     130                 :     }
     131              10 :     else if (EQUALN(pszAccess, "r", 1))
     132                 :     {
     133              10 :         psFile->eAccess = AVCRead;
     134              10 :         psFile->fp = VSIFOpen(pszFname, "rb");
     135                 :     }
     136               0 :     else if (EQUALN(pszAccess, "w", 1))
     137                 :     {
     138               0 :         psFile->eAccess = AVCWrite;
     139               0 :         psFile->fp = VSIFOpen(pszFname, "wb");
     140                 :     }
     141               0 :     else if (EQUALN(pszAccess, "a", 1))
     142                 :     {
     143               0 :         psFile->eAccess = AVCWrite;
     144               0 :         psFile->fp = VSIFOpen(pszFname, "ab");
     145                 :     }
     146                 :     else
     147                 :     {
     148               0 :         CPLError(CE_Failure, CPLE_IllegalArg,
     149                 :                  "Acces mode \"%s\" not supported.", pszAccess);
     150               0 :         CPLFree(psFile);
     151               0 :         return NULL;
     152                 :     }
     153                 : 
     154                 :     /*-----------------------------------------------------------------
     155                 :      * Check that file was opened succesfully, and init struct.
     156                 :      *----------------------------------------------------------------*/
     157              10 :     if (psFile->fp == NULL)
     158                 :     {
     159               0 :         CPLError(CE_Failure, CPLE_OpenFailed,
     160                 :                  "Failed to open file %s", pszFname);
     161               0 :         CPLFree(psFile);
     162               0 :         return NULL;
     163                 :     }
     164                 : 
     165                 :     /*-----------------------------------------------------------------
     166                 :      * OK... Init psFile struct
     167                 :      *----------------------------------------------------------------*/
     168              10 :     psFile->pszFname = CPLStrdup(pszFname);
     169                 : 
     170              10 :     psFile->eByteOrder = eFileByteOrder;
     171              10 :     psFile->psDBCSInfo = psDBCSInfo; /* Handle on dataset DBCS info */
     172                 : 
     173                 :     /*-----------------------------------------------------------------
     174                 :      * One can set nFileDataSize based on some header fields to force
     175                 :      * EOF beyond a given point in the file.  Useful for cases like
     176                 :      * PC Arc/Info where the physical file size is always a multiple of
     177                 :      * 256 bytes padded with some junk at the end.
     178                 :      *----------------------------------------------------------------*/
     179              10 :     psFile->nFileDataSize = -1;
     180                 : 
     181              10 :     return psFile;
     182                 : }
     183                 : 
     184                 : /**********************************************************************
     185                 :  *                          AVCRawBinClose()
     186                 :  *
     187                 :  * Close a binary file previously opened with AVCRawBinOpen() and release
     188                 :  * any memory used by the handle.
     189                 :  **********************************************************************/
     190              11 : void AVCRawBinClose(AVCRawBinFile *psFile)
     191                 : {
     192              11 :     if (psFile)
     193                 :     {
     194              10 :         if (psFile->fp)
     195              10 :             VSIFClose(psFile->fp);
     196              10 :         CPLFree(psFile->pszFname);
     197              10 :         CPLFree(psFile);
     198                 :     }
     199              11 : }
     200                 : 
     201                 : /**********************************************************************
     202                 :  *                          AVCRawBinSetFileDataSize()
     203                 :  *
     204                 :  * One can set nFileDataSize based on some header fields to force
     205                 :  * EOF beyond a given point in the file.  Useful for cases like
     206                 :  * PC Arc/Info where the physical file size is always a multiple of
     207                 :  * 256 bytes padded with some junk at the end.
     208                 :  *
     209                 :  * The default value is -1 which just looks for the real EOF. 
     210                 :  **********************************************************************/
     211               4 : void AVCRawBinSetFileDataSize(AVCRawBinFile *psFile, int nFileDataSize)
     212                 : {
     213               4 :     if (psFile)
     214                 :     {
     215               4 :         psFile->nFileDataSize = nFileDataSize;
     216                 :     }
     217               4 : }
     218                 : 
     219                 : /**********************************************************************
     220                 :  *                          AVCRawBinReadBytes()
     221                 :  *
     222                 :  * Copy the number of bytes from the input file to the specified 
     223                 :  * memory location.
     224                 :  **********************************************************************/
     225                 : static GBool bDisableReadBytesEOFError = FALSE;
     226                 : 
     227            5550 : void AVCRawBinReadBytes(AVCRawBinFile *psFile, int nBytesToRead, GByte *pBuf)
     228                 : {
     229            5550 :     int nTotalBytesToRead = nBytesToRead;
     230                 : 
     231                 :     /* Make sure file is opened with Read access
     232                 :      */
     233           11100 :     if (psFile == NULL || 
     234            5550 :         (psFile->eAccess != AVCRead && psFile->eAccess != AVCReadWrite))
     235                 :     {
     236               0 :         CPLError(CE_Failure, CPLE_FileIO,
     237                 :                 "AVCRawBinReadBytes(): call not compatible with access mode.");
     238               0 :         return;
     239                 :     }
     240                 : 
     241                 :     /* Quick method: check to see if we can satisfy the request with a
     242                 :      * simple memcpy... most calls should take this path.
     243                 :      */
     244            5550 :     if (psFile->nCurPos + nBytesToRead <= psFile->nCurSize)
     245                 :     {
     246            5474 :         memcpy(pBuf, psFile->abyBuf+psFile->nCurPos, nBytesToRead);
     247            5474 :         psFile->nCurPos += nBytesToRead;
     248            5474 :         return;
     249                 :     }
     250                 : 
     251                 :     /* This is the long method... it supports reading data that 
     252                 :      * overlaps the input buffer boundaries.
     253                 :      */
     254             227 :     while(nBytesToRead > 0)
     255                 :     {
     256                 :         /* If we reached the end of our memory buffer then read another
     257                 :          * chunk from the file
     258                 :          */
     259              76 :         CPLAssert(psFile->nCurPos <= psFile->nCurSize);
     260              76 :         if (psFile->nCurPos == psFile->nCurSize)
     261                 :         {
     262              76 :             psFile->nOffset += psFile->nCurSize;
     263              76 :             psFile->nCurSize = VSIFRead(psFile->abyBuf, sizeof(GByte),
     264                 :                                         AVCRAWBIN_READBUFSIZE, psFile->fp);
     265              76 :             psFile->nCurPos = 0;
     266                 :         }
     267                 : 
     268              76 :         if (psFile->nCurSize == 0)
     269                 :         {
     270                 :             /* Attempt to read past EOF... generate an error.
     271                 :              *
     272                 :              * Note: AVCRawBinEOF() can set bDisableReadBytesEOFError=TRUE
     273                 :              *       to disable the error message whils it is testing
     274                 :              *       for EOF.
     275                 :              *
     276                 :              * TODO: We are not resetting the buffer. Also, there is no easy
     277                 :              *       way to recover from the situation.
     278                 :              */
     279               1 :             if (bDisableReadBytesEOFError == FALSE)
     280               0 :                 CPLError(CE_Failure, CPLE_FileIO,
     281                 :                          "EOF encountered in %s after reading %d bytes while "
     282                 :                          "trying to read %d bytes. File may be corrupt.",
     283                 :                          psFile->pszFname, nTotalBytesToRead-nBytesToRead,
     284                 :                          nTotalBytesToRead);
     285               1 :             return;
     286                 :         }
     287                 : 
     288                 :         /* If the requested bytes are not all in the current buffer then
     289                 :          * just read the part that's in memory for now... the loop will 
     290                 :          * take care of the rest.
     291                 :          */
     292              75 :         if (psFile->nCurPos + nBytesToRead > psFile->nCurSize)
     293                 :         {
     294                 :             int nBytes;
     295               0 :             nBytes = psFile->nCurSize-psFile->nCurPos;
     296               0 :             memcpy(pBuf, psFile->abyBuf+psFile->nCurPos, nBytes);
     297               0 :             psFile->nCurPos += nBytes;
     298               0 :             pBuf += nBytes;
     299               0 :             nBytesToRead -= nBytes;
     300                 :         }
     301                 :         else
     302                 :         {
     303                 :             /* All the requested bytes are now in the buffer... 
     304                 :              * simply copy them and return.
     305                 :              */
     306              75 :             memcpy(pBuf, psFile->abyBuf+psFile->nCurPos, nBytesToRead);
     307              75 :             psFile->nCurPos += nBytesToRead;
     308                 : 
     309              75 :             nBytesToRead = 0;   /* Terminate the loop */
     310                 :         }
     311                 :     }
     312                 : }
     313                 : 
     314                 : /**********************************************************************
     315                 :  *                          AVCRawBinReadString()
     316                 :  *
     317                 :  * Same as AVCRawBinReadBytes() except that the string is run through
     318                 :  * the DBCS conversion function.
     319                 :  *
     320                 :  * pBuf should be allocated with a size of at least nBytesToRead+1 bytes.
     321                 :  **********************************************************************/
     322              22 : void AVCRawBinReadString(AVCRawBinFile *psFile, int nBytesToRead, GByte *pBuf)
     323                 : {
     324                 :     const GByte *pszConvBuf;
     325                 : 
     326              22 :     AVCRawBinReadBytes(psFile, nBytesToRead, pBuf);
     327                 : 
     328              22 :     pBuf[nBytesToRead] = '\0';
     329                 : 
     330              22 :     pszConvBuf = AVCE00ConvertFromArcDBCS(psFile->psDBCSInfo,
     331                 :                                           pBuf, 
     332                 :                                           nBytesToRead);
     333                 : 
     334              22 :     if (pszConvBuf != pBuf)
     335                 :     {
     336               0 :         memcpy(pBuf, pszConvBuf, nBytesToRead);
     337                 :     }
     338              22 : }
     339                 : 
     340                 : /**********************************************************************
     341                 :  *                          AVCRawBinFSeek()
     342                 :  *
     343                 :  * Move the read pointer to the specified location.
     344                 :  *
     345                 :  * As with fseek(), the specified position can be relative to the 
     346                 :  * beginning of the file (SEEK_SET), or the current position (SEEK_CUR).
     347                 :  * SEEK_END is not supported.
     348                 :  **********************************************************************/
     349              93 : void AVCRawBinFSeek(AVCRawBinFile *psFile, int nOffset, int nFrom)
     350                 : {
     351              93 :     int  nTarget = 0;
     352                 : 
     353              93 :     CPLAssert(nFrom == SEEK_SET || nFrom == SEEK_CUR);
     354                 : 
     355                 :     /* Supported only with read access for now
     356                 :      */
     357              93 :     CPLAssert(psFile && psFile->eAccess != AVCWrite);
     358              93 :     if (psFile == NULL || psFile->eAccess == AVCWrite)
     359               0 :         return;
     360                 : 
     361                 :     /* Compute destination relative to current memory buffer 
     362                 :      */
     363              93 :     if (nFrom == SEEK_SET)
     364              10 :         nTarget = nOffset - psFile->nOffset;
     365              83 :     else if (nFrom == SEEK_CUR)
     366              83 :         nTarget = nOffset + psFile->nCurPos;
     367                 : 
     368                 :     /* Is the destination located inside the current buffer?
     369                 :      */
     370             129 :     if (nTarget > 0 && nTarget <= psFile->nCurSize)
     371                 :     {
     372                 :         /* Requested location is already in memory... just move the 
     373                 :          * read pointer
     374                 :          */
     375              36 :         psFile->nCurPos = nTarget;
     376                 :     }
     377                 :     else
     378                 :     {
     379                 :         /* Requested location is not part of the memory buffer...
     380                 :          * move the FILE * to the right location and be ready to 
     381                 :          * read from there.
     382                 :          */
     383              57 :         VSIFSeek(psFile->fp, psFile->nOffset+nTarget, SEEK_SET);
     384              57 :         psFile->nCurPos = 0;
     385              57 :         psFile->nCurSize = 0;
     386              57 :         psFile->nOffset = psFile->nOffset+nTarget;
     387                 :     }
     388                 : 
     389                 : }
     390                 : 
     391                 : /**********************************************************************
     392                 :  *                          AVCRawBinEOF()
     393                 :  *
     394                 :  * Return TRUE if there is no more data to read from the file or
     395                 :  * FALSE otherwise.
     396                 :  **********************************************************************/
     397            7966 : GBool AVCRawBinEOF(AVCRawBinFile *psFile)
     398                 : {
     399            7966 :     if (psFile == NULL || psFile->fp == NULL)
     400               0 :         return TRUE;
     401                 : 
     402                 :     /* In write access mode, always return TRUE, since we always write
     403                 :      * at EOF for now.
     404                 :      */
     405            7966 :     if (psFile->eAccess != AVCRead && psFile->eAccess != AVCReadWrite)
     406               0 :         return TRUE;
     407                 : 
     408                 :     /* If file data size was specified, then check that we have not 
     409                 :      * passed that point yet...
     410                 :      */
     411            7983 :     if (psFile->nFileDataSize > 0 &&
     412              17 :         (psFile->nOffset+psFile->nCurPos) >= psFile->nFileDataSize)
     413               1 :         return TRUE;
     414                 : 
     415                 :     /* If the file pointer has been moved by AVCRawBinFSeek(), then
     416                 :      * we may be at a position past EOF, but VSIFeof() would still
     417                 :      * return FALSE. It also returns false if we have read just upto
     418                 :      * the end of the file. EOF marker would not have been set unless
     419                 :      * we try to read past that.
     420                 :      * 
     421                 :      * To prevent this situation, if the memory buffer is empty,
     422                 :      * we will try to read 1 byte from the file to force the next
     423                 :      * chunk of data to be loaded (and we'll move the the read pointer
     424                 :      * back by 1 char after of course!).  
     425                 :      * If we are at the end of the file, this will trigger the EOF flag.
     426                 :      */
     427           15925 :     if ((psFile->nCurPos == 0 && psFile->nCurSize == 0) ||
     428            7940 :         (psFile->nCurPos == AVCRAWBIN_READBUFSIZE &&
     429              20 :          psFile->nCurSize == AVCRAWBIN_READBUFSIZE))
     430                 :     {
     431                 :         GByte c;
     432                 :         /* Set bDisableReadBytesEOFError=TRUE to temporarily disable 
     433                 :          * the EOF error message from AVCRawBinReadBytes().
     434                 :          */
     435              45 :         bDisableReadBytesEOFError = TRUE;
     436              45 :         AVCRawBinReadBytes(psFile, 1, &c);
     437              45 :         bDisableReadBytesEOFError = FALSE;
     438                 : 
     439              45 :         if (psFile->nCurPos > 0)
     440              44 :             AVCRawBinFSeek(psFile, -1, SEEK_CUR);
     441                 :     }
     442                 : 
     443            8011 :     return (psFile->nCurPos == psFile->nCurSize && 
     444              46 :             VSIFEof(psFile->fp));
     445                 : }
     446                 : 
     447                 : 
     448                 : /**********************************************************************
     449                 :  *                          AVCRawBinRead<datatype>()
     450                 :  *
     451                 :  * Arc/Info files are binary files with MSB first (Motorola) byte 
     452                 :  * ordering.  The following functions will read from the input file
     453                 :  * and return a value with the bytes ordered properly for the current 
     454                 :  * platform.
     455                 :  **********************************************************************/
     456              55 : GInt16  AVCRawBinReadInt16(AVCRawBinFile *psFile)
     457                 : {
     458                 :     GInt16 n16Value;
     459                 : 
     460              55 :     AVCRawBinReadBytes(psFile, 2, (GByte*)(&n16Value));
     461                 : 
     462              55 :     if (psFile->eByteOrder != geSystemByteOrder)
     463                 :     {
     464              55 :         return (GInt16)CPL_SWAP16(n16Value);
     465                 :     }
     466                 : 
     467               0 :     return n16Value;
     468                 : }
     469                 : 
     470            5374 : GInt32  AVCRawBinReadInt32(AVCRawBinFile *psFile)
     471                 : {
     472                 :     GInt32 n32Value;
     473                 : 
     474            5374 :     AVCRawBinReadBytes(psFile, 4, (GByte*)(&n32Value));
     475                 : 
     476            5374 :     if (psFile->eByteOrder != geSystemByteOrder)
     477                 :     {
     478            5374 :         return (GInt32)CPL_SWAP32(n32Value);
     479                 :     }
     480                 : 
     481               0 :     return n32Value;
     482                 : }
     483                 : 
     484              44 : float   AVCRawBinReadFloat(AVCRawBinFile *psFile)
     485                 : {
     486                 :     float fValue;
     487                 : 
     488              44 :     AVCRawBinReadBytes(psFile, 4, (GByte*)(&fValue));
     489                 : 
     490              44 :     if (psFile->eByteOrder != geSystemByteOrder)
     491                 :     {
     492              44 :         CPL_SWAP32PTR( &fValue );
     493                 :     }
     494                 : 
     495              44 :     return fValue;
     496                 : }
     497                 : 
     498               0 : double  AVCRawBinReadDouble(AVCRawBinFile *psFile)
     499                 : {
     500                 :     double dValue;
     501                 : 
     502               0 :     AVCRawBinReadBytes(psFile, 8, (GByte*)(&dValue));
     503                 : 
     504               0 :     if (psFile->eByteOrder != geSystemByteOrder)
     505                 :     {
     506               0 :         CPL_SWAPDOUBLE(&dValue);
     507                 :     }
     508                 : 
     509               0 :     return dValue;
     510                 : }
     511                 : 
     512                 : 
     513                 : 
     514                 : /**********************************************************************
     515                 :  *                          AVCRawBinWriteBytes()
     516                 :  *
     517                 :  * Write the number of bytes from the buffer to the file.
     518                 :  *
     519                 :  * If a problem happens, then CPLError() will be called and 
     520                 :  * CPLGetLastErrNo() can be used to test if a write operation was 
     521                 :  * succesful.
     522                 :  **********************************************************************/
     523               0 : void AVCRawBinWriteBytes(AVCRawBinFile *psFile, int nBytesToWrite, 
     524                 :                          const GByte *pBuf)
     525                 : {
     526                 :     /*----------------------------------------------------------------
     527                 :      * Make sure file is opened with Write access
     528                 :      *---------------------------------------------------------------*/
     529               0 :     if (psFile == NULL || 
     530               0 :         (psFile->eAccess != AVCWrite && psFile->eAccess != AVCReadWrite))
     531                 :     {
     532               0 :         CPLError(CE_Failure, CPLE_FileIO,
     533                 :               "AVCRawBinWriteBytes(): call not compatible with access mode.");
     534               0 :         return;
     535                 :     }
     536                 : 
     537               0 :     if (VSIFWrite((void*)pBuf, nBytesToWrite, 1, psFile->fp) != 1)
     538               0 :         CPLError(CE_Failure, CPLE_FileIO,
     539                 :                  "Writing to %s failed.", psFile->pszFname);
     540                 : 
     541                 :     /*----------------------------------------------------------------
     542                 :      * In write mode, we keep track of current file position ( =nbr of
     543                 :      * bytes written) through psFile->nCurPos
     544                 :      *---------------------------------------------------------------*/
     545               0 :     psFile->nCurPos += nBytesToWrite;
     546                 : }
     547                 : 
     548                 : 
     549                 : /**********************************************************************
     550                 :  *                          AVCRawBinWrite<datatype>()
     551                 :  *
     552                 :  * Arc/Info files are binary files with MSB first (Motorola) byte 
     553                 :  * ordering.  The following functions will reorder the byte for the
     554                 :  * value properly and write that to the output file.
     555                 :  *
     556                 :  * If a problem happens, then CPLError() will be called and 
     557                 :  * CPLGetLastErrNo() can be used to test if a write operation was 
     558                 :  * succesful.
     559                 :  **********************************************************************/
     560               0 : void  AVCRawBinWriteInt16(AVCRawBinFile *psFile, GInt16 n16Value)
     561                 : {
     562               0 :     if (psFile->eByteOrder != geSystemByteOrder)
     563                 :     {
     564               0 :         n16Value = (GInt16)CPL_SWAP16(n16Value);
     565                 :     }
     566                 : 
     567               0 :     AVCRawBinWriteBytes(psFile, 2, (GByte*)&n16Value);
     568               0 : }
     569                 : 
     570               0 : void  AVCRawBinWriteInt32(AVCRawBinFile *psFile, GInt32 n32Value)
     571                 : {
     572               0 :     if (psFile->eByteOrder != geSystemByteOrder)
     573                 :     {
     574               0 :         n32Value = (GInt32)CPL_SWAP32(n32Value);
     575                 :     }
     576                 : 
     577               0 :     AVCRawBinWriteBytes(psFile, 4, (GByte*)&n32Value);
     578               0 : }
     579                 : 
     580               0 : void  AVCRawBinWriteFloat(AVCRawBinFile *psFile, float fValue)
     581                 : {
     582               0 :     if (psFile->eByteOrder != geSystemByteOrder)
     583                 :     {
     584               0 :         CPL_SWAP32PTR( &fValue );
     585                 :     }
     586                 : 
     587               0 :     AVCRawBinWriteBytes(psFile, 4, (GByte*)&fValue);
     588               0 : }
     589                 : 
     590               0 : void  AVCRawBinWriteDouble(AVCRawBinFile *psFile, double dValue)
     591                 : {
     592               0 :     if (psFile->eByteOrder != geSystemByteOrder)
     593                 :     {
     594               0 :         CPL_SWAPDOUBLE(&dValue);
     595                 :     }
     596                 : 
     597               0 :     AVCRawBinWriteBytes(psFile, 8, (GByte*)&dValue);
     598               0 : }
     599                 : 
     600                 : 
     601                 : /**********************************************************************
     602                 :  *                          AVCRawBinWriteZeros()
     603                 :  *
     604                 :  * Write a number of zeros (sepcified in bytes) at the current position 
     605                 :  * in the file.
     606                 :  *
     607                 :  * If a problem happens, then CPLError() will be called and 
     608                 :  * CPLGetLastErrNo() can be used to test if a write operation was 
     609                 :  * succesful.
     610                 :  **********************************************************************/
     611               0 : void AVCRawBinWriteZeros(AVCRawBinFile *psFile, int nBytesToWrite)
     612                 : {
     613               0 :     char acZeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
     614                 :     int i;
     615                 : 
     616                 :     /* Write by 8 bytes chunks.  The last chunk may be less than 8 bytes 
     617                 :      */
     618               0 :     for(i=0; i< nBytesToWrite; i+=8)
     619                 :     {
     620               0 :         AVCRawBinWriteBytes(psFile, MIN(8,(nBytesToWrite-i)), 
     621                 :                             (GByte*)acZeros);
     622                 :     }
     623               0 : }
     624                 : 
     625                 : /**********************************************************************
     626                 :  *                          AVCRawBinWritePaddedString()
     627                 :  *
     628                 :  * Write a string and pad the end of the field (up to nFieldSize) with
     629                 :  * spaces number of spaces at the current position in the file.
     630                 :  *
     631                 :  * If a problem happens, then CPLError() will be called and 
     632                 :  * CPLGetLastErrNo() can be used to test if a write operation was 
     633                 :  * succesful.
     634                 :  **********************************************************************/
     635               0 : void AVCRawBinWritePaddedString(AVCRawBinFile *psFile, int nFieldSize,
     636                 :                                 const GByte *pszString)
     637                 : {
     638               0 :     char acSpaces[8] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
     639                 :     int i, nLen, numSpaces;
     640                 : 
     641                 :     /* If we're on a system with a multibyte codepage then we have to
     642                 :      * convert strings to the proper multibyte encoding.
     643                 :      */
     644               0 :     pszString = AVCE00Convert2ArcDBCS(psFile->psDBCSInfo,
     645                 :                                       pszString, nFieldSize);
     646                 : 
     647               0 :     nLen = strlen((const char *)pszString);
     648               0 :     nLen = MIN(nLen, nFieldSize);
     649               0 :     numSpaces = nFieldSize - nLen;
     650                 : 
     651               0 :     if (nLen > 0)
     652               0 :         AVCRawBinWriteBytes(psFile, nLen, pszString);
     653                 : 
     654                 :     /* Write spaces by 8 bytes chunks.  The last chunk may be less than 8 bytes
     655                 :      */
     656               0 :     for(i=0; i< numSpaces; i+=8)
     657                 :     {
     658               0 :         AVCRawBinWriteBytes(psFile, MIN(8,(numSpaces-i)), 
     659                 :                             (GByte*)acSpaces);
     660                 :     }
     661               0 : }
     662                 : 

Generated by: LCOV version 1.7