LCOV - code coverage report
Current view: directory - frmts/grib/degrib18/degrib - memendian.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 109 48 44.0 %
Date: 2010-01-09 Functions: 5 3 60.0 %

       1                 : /*****************************************************************************
       2                 :  * memendian.c
       3                 :  *
       4                 :  * DESCRIPTION
       5                 :  *    This file contains all the utility functions that the Driver uses to
       6                 :  * solve endian'ness related issues.
       7                 :  *
       8                 :  * HISTORY
       9                 :  *   9/2002 Arthur Taylor (MDL / RSIS): Created.
      10                 :  *  12/2002 Rici Yu, Fangyu Chi, Mark Armstrong, & Tim Boyer
      11                 :  *          (RY,FC,MA,&TB): Code Review 2.
      12                 :  *
      13                 :  * NOTES
      14                 :  *****************************************************************************
      15                 :  */
      16                 : #include <stdio.h>
      17                 : #include <string.h>
      18                 : #include "memendian.h"
      19                 : 
      20                 : /*****************************************************************************
      21                 :  * memswp() -- Review 12/2002
      22                 :  *
      23                 :  * Arthur Taylor / MDL
      24                 :  *
      25                 :  * PURPOSE
      26                 :  *   To swap memory in the Data array based on the knownledge that there are
      27                 :  * "num_elem" elements, each of size "elem_size".
      28                 :  *
      29                 :  * ARGUMENTS
      30                 :  *      Data = A pointer to the data to be swapped. (Input/Output)
      31                 :  * elem_size = The size of an individual element. (Input)
      32                 :  *  num_elem = The number of elements to swap. (Input)
      33                 :  *
      34                 :  * FILES/DATABASES: None
      35                 :  *
      36                 :  * RETURNS: void
      37                 :  *
      38                 :  * HISTORY
      39                 :  *   9/2002 Arthur Taylor (MDL/RSIS): Created.
      40                 :  *  12/2002 (RY,FC,MA,&TB): Code Review.
      41                 :  *
      42                 :  * NOTES
      43                 :  * 1) A similar routine was provided with the GRIB2 library.  It was called:
      44                 :  * "unpk_swap".  Since it had the restriction that it only dealt with long
      45                 :  * ints, I felt that I needed more flexibility.  In addition this procedure
      46                 :  * may be more efficient.  I did an operation count for swapping an array
      47                 :  * that consisted of 1 4 byte int.
      48                 :  * "unpk_swap" = 46 operations, "memswp" = 33.
      49                 :  * 2) Could try this with exclusive or?
      50                 :  *****************************************************************************
      51                 :  */
      52               6 : void memswp (void *Data, const size_t elem_size, const size_t num_elem)
      53                 : {
      54                 :    size_t j;            /* Element count */
      55                 :    char *data;          /* Allows us to treat Data as an array of char. */
      56                 :    char temp;           /* A temporary holder of a byte when swapping. */
      57                 :    char *ptr, *ptr2;    /* Pointers to the two bytes to swap. */
      58                 : 
      59               6 :    if (elem_size == 1) {
      60               0 :       return;
      61                 :    }
      62               6 :    data = (char *) Data;
      63          137004 :    for (j = 0; j < elem_size * num_elem; j += elem_size) {
      64          136998 :       ptr = data + j;
      65          136998 :       ptr2 = ptr + elem_size - 1;
      66          547992 :       while (ptr2 > ptr) {
      67          273996 :          temp = *ptr;
      68          273996 :          *(ptr++) = *ptr2;
      69          273996 :          *(ptr2--) = temp;
      70                 :       }
      71                 :    }
      72                 : }
      73                 : 
      74                 : /*****************************************************************************
      75                 :  * revmemcpy() -- Review 12/2002
      76                 :  *
      77                 :  * Arthur Taylor / MDL
      78                 :  *
      79                 :  * PURPOSE
      80                 :  *   To copy memory similar to memcpy, but in a reverse manner.  In order to
      81                 :  * have the same arguments as memcpy, this can not handle arrays... For
      82                 :  * arrays use revmemcpyRay().  Returns the same thing that memcpy does.
      83                 :  *
      84                 :  * ARGUMENTS
      85                 :  * Dst = The destination for the data. (Output)
      86                 :  * Src = The source of the data. (Input)
      87                 :  * len = The length of Src in bytes. (Input)
      88                 :  *
      89                 :  * FILES/DATABASES: None
      90                 :  *
      91                 :  * RETURNS: void *
      92                 :  *
      93                 :  * HISTORY
      94                 :  *   9/2002 Arthur Taylor (MDL/RSIS): Created.
      95                 :  *  12/2002 (RY,FC,MA,&TB): Code Review.
      96                 :  *
      97                 :  * NOTES
      98                 :  * 1) This came about as I was trying to improve on the use of memcpy.  I
      99                 :  *    figured that revmemcpy would be faster than memcpy followed by memswp.
     100                 :  * 2) Assumes that Dst is allocated to a size of Src.
     101                 :  * 3) Problems with MEMCPY if len != sizeof (dst)... Is it left or right
     102                 :  *    justified?
     103                 :  *****************************************************************************
     104                 :  */
     105              63 : void *revmemcpy (void *Dst, void *Src, const size_t len)
     106                 : {
     107                 :    size_t j;            /* Byte count */
     108              63 :    char *src = (char *) Src; /* Allows us to treat Src as an array of char. */
     109              63 :    char *dst = (char *) Dst; /* Allows us to treat Dst as an array of char. */
     110                 : 
     111              63 :    src = src + len - 1;
     112             291 :    for (j = 0; j < len; ++j) {
     113             228 :       *(dst++) = *(src--);
     114                 :    }
     115              63 :    return Dst;
     116                 : }
     117                 : 
     118                 : /*****************************************************************************
     119                 :  * revmemcpyRay() -- Review 12/2002
     120                 :  *
     121                 :  * Arthur Taylor / MDL
     122                 :  *
     123                 :  * PURPOSE
     124                 :  *   To copy memory similar to memcpy, but in a reverse manner.  This handles
     125                 :  * the case when we need to reverse memcpy an array of data.
     126                 :  *
     127                 :  * ARGUMENTS
     128                 :  *       Dst = The destination for the data. (Output)
     129                 :  *       Src = The source of the data. (Input)
     130                 :  * elem_size = The size of a single element. (Input)
     131                 :  *  num_elem = The number of elements in Src. (Input)
     132                 :  *
     133                 :  * FILES/DATABASES: None
     134                 :  *
     135                 :  * RETURNS: void *
     136                 :  *
     137                 :  * HISTORY
     138                 :  *   9/2002 Arthur Taylor (MDL/RSIS): Created.
     139                 :  *  12/2002 (RY,FC,MA,&TB): Code Review.
     140                 :  *
     141                 :  * NOTES
     142                 :  * 1) Assumes that Dst is allocated to a size of Src.
     143                 :  *****************************************************************************
     144                 :  */
     145               0 : void *revmemcpyRay (void *Dst, void *Src, const size_t elem_size,
     146                 :                     const size_t num_elem)
     147                 : {
     148                 :    size_t i;            /* Element count. */
     149                 :    size_t j;            /* Byte count. */
     150               0 :    char *src = (char *) Src; /* Allows us to treat Src as an array of char. */
     151               0 :    char *dst = (char *) Dst; /* Allows us to treat Dst as an array of char. */
     152                 : 
     153               0 :    if (elem_size == 1) {
     154               0 :       return memcpy (Dst, Src, num_elem);
     155                 :    }
     156               0 :    src -= (elem_size + 1);
     157               0 :    for (i = 0; i < num_elem; ++i) {
     158               0 :       src += 2 * elem_size;
     159               0 :       for (j = 0; j < elem_size; ++j) {
     160               0 :          *(dst++) = *(src--);
     161                 :       }
     162                 :    }
     163               0 :    return Dst;
     164                 : }
     165                 : 
     166                 : /*****************************************************************************
     167                 :  * memBitRead() --
     168                 :  *
     169                 :  * Arthur Taylor / MDL
     170                 :  *
     171                 :  * PURPOSE
     172                 :  *   To read bits from an uChar buffer array of memory.  Assumes BufLoc is
     173                 :  * valid before first call.  Typically this means do a "bufLoc = 8;" before
     174                 :  * the first call.
     175                 :  *
     176                 :  * ARGUMENTS
     177                 :  *       Dst = Where to put the results. (Output)
     178                 :  *    dstLen = Length in bytes of Dst. (Input)
     179                 :  *       Src = The data to read the bits from. (Input)
     180                 :  *   numBits = How many bits to read. (Input)
     181                 :  *    BufLoc = Which bit to start reading from in Src.
     182                 :  *             Starts at 8 goes to 1. (Input/Output)
     183                 :  *   numUsed = How many bytes from Src were used while reading (Output)
     184                 :  *
     185                 :  * FILES/DATABASES: None
     186                 :  *
     187                 :  * RETURNS:
     188                 :  *   Returns 1 on error, 0 if ok.
     189                 :  *
     190                 :  * HISTORY
     191                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Created
     192                 :  *   5/2004 AAT: Bug in call to MEMCPY_BIG when numBytes != dstLen.
     193                 :  *          On big endian machines we need to right justify the number.
     194                 :  *
     195                 :  * NOTES
     196                 :  * 1) Assumes binary bit stream is "big endian". Resulting in no byte
     197                 :  *    boundaries ie 00100110101101 => 001001 | 10101101
     198                 :  *****************************************************************************
     199                 :  */
     200           10848 : char memBitRead (void *Dst, size_t dstLen, void *Src, size_t numBits,
     201                 :                  uChar * bufLoc, size_t * numUsed)
     202                 : {
     203           10848 :    uChar *src = (uChar *) Src; /* Allows us to treat Src as an array of
     204                 :                                 * char. */
     205           10848 :    uChar *dst = (uChar *) Dst; /* Allows us to treat Dst as an array of
     206                 :                                 * char. */
     207                 :    size_t numBytes;     /* How many bytes are needed in dst. */
     208                 :    uChar dstLoc;        /* Where we are writing to in dst. */
     209                 :    uChar *ptr;          /* Current byte we are writing to in dst. */
     210                 :    static uChar BitMask[] = {
     211                 :       0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
     212                 :    };
     213                 : 
     214           10848 :    if (numBits == 0) {
     215               0 :       memset (Dst, 0, dstLen);
     216               0 :       (*numUsed) = 0;
     217               0 :       return 0;
     218                 :    }
     219           10848 :    numBytes = ((numBits - 1) / 8) + 1;
     220           10848 :    if (dstLen < numBytes) {
     221               0 :       return 1;
     222                 :    }
     223           10848 :    memset (Dst, 0, dstLen);
     224           10848 :    dstLoc = ((numBits - 1) % 8) + 1;
     225           10848 :    if ((*bufLoc == 8) && (dstLoc == 8)) {
     226                 : #ifdef LITTLE_ENDIAN
     227               0 :       MEMCPY_BIG (Dst, Src, numBytes);
     228                 : #else
     229                 :       /* If numBytes != dstLen, then we need to right justify the ans */
     230                 :       MEMCPY_BIG (dst + (dstLen - numBytes), Src, numBytes);
     231                 : #endif
     232               0 :       (*numUsed) = numBytes;
     233               0 :       return 0;
     234                 :    }
     235                 : #ifdef LITTLE_ENDIAN
     236           10848 :    ptr = dst + (numBytes - 1);
     237                 : #else
     238                 :    ptr = dst + (dstLen - numBytes);
     239                 : #endif
     240                 : 
     241           10848 :    *numUsed = 0;
     242                 :    /* Deal with most significant byte in dst. */
     243           10848 :    if (*bufLoc >= dstLoc) {
     244                 : #ifdef LITTLE_ENDIAN
     245            8106 :       (*ptr--) |= ((*src & BitMask[*bufLoc]) >> (*bufLoc - dstLoc));
     246                 : #else
     247                 :       (*ptr++) |= ((*src & BitMask[*bufLoc]) >> (*bufLoc - dstLoc));
     248                 : #endif
     249            8106 :       (*bufLoc) -= dstLoc;
     250                 :    } else {
     251            2742 :       if (*bufLoc != 0) {
     252            2742 :          *ptr |= ((*src & BitMask[*bufLoc]) << (dstLoc - *bufLoc));
     253                 :          /* Assert: dstLoc should now be dstLoc - InitBufLoc */
     254            2742 :          dstLoc = dstLoc - *bufLoc;
     255                 :          /* Assert: bufLoc should now be 0 */
     256                 :       }
     257            2742 :       src++;
     258            2742 :       (*numUsed)++;
     259                 :       /* Assert: bufLoc should now be 8 */
     260                 :       /* Assert: We want to >> by bufLoc - dstLoc = 8 - dstLoc */
     261                 : #ifdef LITTLE_ENDIAN
     262            2742 :       *(ptr--) |= (*src >> (8 - dstLoc));
     263                 : #else
     264                 :       *(ptr++) |= (*src >> (8 - dstLoc));
     265                 : #endif
     266            2742 :       (*bufLoc) = 8 - dstLoc;
     267                 :    }
     268                 :    /* Assert: dstLoc should now be 8, but we don't use again in procedure. */
     269                 : 
     270                 :    /* We have now reached the state which we want after each iteration of
     271                 :     * the loop.  That is initDstLoc == 8, initBufLoc = bufLoc < dstLoc. */
     272                 : #ifdef LITTLE_ENDIAN
     273           32544 :    while (ptr >= dst) {
     274                 : #else
     275                 :    while (ptr < dst + dstLen) {
     276                 : #endif
     277           10848 :       if (*bufLoc != 0) {
     278            9219 :          *ptr |= ((*src & BitMask[*bufLoc]) << (8 - *bufLoc));
     279                 :          /* Assert: dstLoc should now be initDstLoc (8) - initBufLoc */
     280                 :          /* Assert: bufLoc should now be 0 */
     281                 :       }
     282           10848 :       src++;
     283           10848 :       (*numUsed)++;
     284                 :       /* Assert: bufLoc should now be 8 */
     285                 :       /* Assert: dstLoc should now be initDstLoc (8) - initBufLoc */
     286                 :       /* Assert: We want to >> by bufLoc - dstLoc = (8 - (8 - initbufLoc)). */
     287                 : #ifdef LITTLE_ENDIAN
     288           10848 :       *(ptr--) |= (*src >> *bufLoc);
     289                 : #else
     290                 :       *(ptr++) |= (*src >> *bufLoc);
     291                 : #endif
     292                 :    }
     293           10848 :    if (*bufLoc == 0) {
     294            1629 :       (*numUsed)++;
     295            1629 :       *bufLoc = 8;
     296                 :    }
     297           10848 :    return 0;
     298                 : }
     299                 : 
     300                 : /*****************************************************************************
     301                 :  * memBitWrite() --
     302                 :  *
     303                 :  * Arthur Taylor / MDL
     304                 :  *
     305                 :  * PURPOSE
     306                 :  *   To write bits from a data structure to an array of uChar.
     307                 :  *   Assumes that the part of Dst we don't write to have been correctly
     308                 :  * initialized.  Typically this means do a "memset (dst, 0, sizeof (dst));"
     309                 :  * before the first call.
     310                 :  *   Also assumes BufLoc is valid before first call.  Typically this means do
     311                 :  * a "bufLoc = 8;" before the first call.
     312                 :  *
     313                 :  * ARGUMENTS
     314                 :  *       Src = The data to read from. (Input)
     315                 :  *    srcLen = Length in bytes of Src. (Input)
     316                 :  *       Dst = The char buffer to write the bits to. (Output)
     317                 :  *   numBits = How many bits to write. (Input)
     318                 :  *    BufLoc = Which bit in Dst to start writing to.
     319                 :  *             Starts at 8 goes to 1. (Input/Output)
     320                 :  *   numUsed = How many bytes were written to Dst. (Output)
     321                 :  *
     322                 :  * FILES/DATABASES: None
     323                 :  *
     324                 :  * RETURNS:
     325                 :  *   Returns 1 on error, 0 if ok.
     326                 :  *
     327                 :  * HISTORY
     328                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Created
     329                 :  *
     330                 :  * NOTES
     331                 :  * 1) Assumes binary bit stream should be "big endian". Resulting in no byte
     332                 :  *    boundaries ie 00100110101101 => 001001 | 1010110
     333                 :  * 2) Assumes that Dst is already zero'ed out.
     334                 :  *****************************************************************************
     335                 :  */
     336               0 : char memBitWrite (void *Src, size_t srcLen, void *Dst, size_t numBits,
     337                 :                   uChar * bufLoc, size_t * numUsed)
     338                 : {
     339               0 :    uChar *src = (uChar *) Src; /* Allows us to treat Src as an array of
     340                 :                                 * char. */
     341               0 :    uChar *dst = (uChar *) Dst; /* Allows us to treat Dst as an array of
     342                 :                                 * char. */
     343                 :    size_t numBytes;     /* How many bytes are needed from src. */
     344                 :    uChar srcLoc;        /* Which bit we are reading from in src. */
     345                 :    uChar *ptr;          /* Current byte we are reading from in src. */
     346                 :    static uChar BitMask[] = {
     347                 :       0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
     348                 :    };
     349                 : 
     350               0 :    if (numBits == 0) {
     351               0 :       return 0;
     352                 :    }
     353               0 :    numBytes = ((numBits - 1) / 8) + 1;
     354               0 :    if (srcLen < numBytes) {
     355               0 :       return 1;
     356                 :    }
     357               0 :    srcLoc = ((numBits - 1) % 8) + 1;
     358                 : 
     359               0 :    if ((*bufLoc == 8) && (srcLoc == 8)) {
     360               0 :       MEMCPY_BIG (Dst, Src, numBytes);
     361               0 :       (*numUsed) = numBytes;
     362               0 :       return 0;
     363                 :    }
     364                 : #ifdef LITTLE_ENDIAN
     365               0 :    ptr = src + (numBytes - 1);
     366                 : #else
     367                 :    ptr = src + (srcLen - numBytes);
     368                 : #endif
     369                 : 
     370               0 :    *numUsed = 0;
     371                 :    /* Deal with most significant byte in src. */
     372               0 :    if (*bufLoc >= srcLoc) {
     373                 : #ifdef LITTLE_ENDIAN
     374               0 :       (*dst) |= ((*(ptr--) & BitMask[srcLoc]) << (*bufLoc - srcLoc));
     375                 : #else
     376                 :       (*dst) |= ((*(ptr++) & BitMask[srcLoc]) << (*bufLoc - srcLoc));
     377                 : #endif
     378               0 :       (*bufLoc) -= srcLoc;
     379                 :    } else {
     380               0 :       if (*bufLoc != 0) {
     381               0 :          (*dst) |= ((*ptr & BitMask[srcLoc]) >> (srcLoc - *bufLoc));
     382                 :          /* Assert: srcLoc should now be srcLoc - InitBufLoc */
     383               0 :          srcLoc = srcLoc - *bufLoc;
     384                 :          /* Assert: bufLoc should now be 0 */
     385                 :       }
     386               0 :       dst++;
     387               0 :       (*dst) = 0;
     388               0 :       (*numUsed)++;
     389                 :       /* Assert: bufLoc should now be 8 */
     390                 :       /* Assert: We want to >> by bufLoc - srcLoc = 8 - srcLoc */
     391                 : #ifdef LITTLE_ENDIAN
     392               0 :       (*dst) |= (*(ptr--) << (8 - srcLoc));
     393                 : #else
     394                 :       (*dst) |= (*(ptr++) << (8 - srcLoc));
     395                 : #endif
     396               0 :       (*bufLoc) = 8 - srcLoc;
     397                 :    }
     398                 :    /* Assert: dstLoc should now be 8, but we don't use again in procedure. */
     399                 : 
     400                 :    /* We have now reached the state which we want after each iteration of
     401                 :     * the loop.  That is initSrcLoc == 8, initBufLoc = bufLoc < srcLoc. */
     402                 : #ifdef LITTLE_ENDIAN
     403               0 :    while (ptr >= src) {
     404                 : #else
     405                 :    while (ptr < src + srcLen) {
     406                 : #endif
     407               0 :       if (*bufLoc == 0) {
     408               0 :          dst++;
     409               0 :          (*numUsed)++;
     410                 : #ifdef LITTLE_ENDIAN
     411               0 :          (*dst) = *(ptr--);
     412                 : #else
     413                 :          (*dst) = *(ptr++);
     414                 : #endif
     415                 :       } else {
     416               0 :          (*dst) |= ((*ptr) >> (8 - *bufLoc));
     417               0 :          dst++;
     418               0 :          (*numUsed)++;
     419               0 :          (*dst) = 0;
     420                 : #ifdef LITTLE_ENDIAN
     421               0 :          (*dst) |= (*(ptr--) << *bufLoc);
     422                 : #else
     423                 :          (*dst) |= (*(ptr++) << *bufLoc);
     424                 : #endif
     425                 :       }
     426                 :    }
     427               0 :    if (*bufLoc == 0) {
     428               0 :       dst++;
     429               0 :       (*numUsed)++;
     430               0 :       (*bufLoc) = 8;
     431               0 :       (*dst) = 0;
     432                 :    }
     433               0 :    return 0;
     434                 : }
     435                 : 
     436                 : /*****************************************************************************
     437                 :  * main() --
     438                 :  *
     439                 :  * Arthur Taylor / MDL
     440                 :  *
     441                 :  * PURPOSE
     442                 :  *   To test the memBitRead, and memBitWrite routines, to make sure that they
     443                 :  * function correctly on some sample data..
     444                 :  *
     445                 :  * ARGUMENTS
     446                 :  * argc = The number of arguments on the command line. (Input)
     447                 :  * argv = The arguments on the command line. (Input)
     448                 :  *
     449                 :  * FILES/DATABASES: None
     450                 :  *
     451                 :  * RETURNS: void
     452                 :  *
     453                 :  * HISTORY
     454                 :  *    4/2003 Arthur Taylor (MDL/RSIS): Created.
     455                 :  *
     456                 :  * NOTES
     457                 :  *****************************************************************************
     458                 :  */
     459                 : #ifdef DEBUG_ENDIAN
     460                 : int main (int argc, char **argv)
     461                 : {
     462                 :    uChar buff[5], buff2[5];
     463                 :    uChar bufLoc = 8;
     464                 :    uChar *ptr, *ptr2;
     465                 :    int numUsed;
     466                 : 
     467                 :    buff[0] = 0x8f;
     468                 :    buff[1] = 0x8f;
     469                 :    buff[2] = 0x8f;
     470                 :    buff[3] = 0x8f;
     471                 :    buff[4] = 0x8f;
     472                 : 
     473                 :    bufLoc = 7;
     474                 :    memBitRead (buff2, sizeof (buff2), buff, 39, &bufLoc, &numUsed);
     475                 :    printf ("%d %d %d %d %d ", buff2[0], buff2[1], buff2[2], buff2[3],
     476                 :            buff2[4]);
     477                 :    printf ("-------should be----- ");
     478                 :    printf ("143 143 143 143 15\n");
     479                 : 
     480                 :    memset (buff, 0, sizeof (buff));
     481                 :    bufLoc = 8;
     482                 :    ptr = buff;
     483                 :    ptr2 = buff2;
     484                 :    memBitWrite (ptr2, sizeof (buff2), ptr, 9, &bufLoc, &numUsed);
     485                 :    ptr += numUsed;
     486                 :    ptr2++;
     487                 :    memBitWrite (ptr2, sizeof (buff2), ptr, 7, &bufLoc, &numUsed);
     488                 :    ptr += numUsed;
     489                 :    ptr2++;
     490                 :    memBitWrite (ptr2, sizeof (buff2), ptr, 7, &bufLoc, &numUsed);
     491                 :    ptr += numUsed;
     492                 :    ptr2++;
     493                 :    memBitWrite (ptr2, sizeof (buff2), ptr, 9, &bufLoc, &numUsed);
     494                 :    ptr += numUsed;
     495                 :    ptr2++;
     496                 :    memBitWrite (ptr2, sizeof (buff2), ptr, 8, &bufLoc, &numUsed);
     497                 :    ptr += numUsed;
     498                 :    printf ("%d %d %d %d %d ", buff[0], buff[1], buff[2], buff[3], buff[4]);
     499                 :    printf ("-------should be----- ");
     500                 :    printf ("199 143 31 143 15\n");
     501                 :    return 0;
     502                 : }
     503                 : #endif

Generated by: LCOV version 1.7