LCOV - code coverage report
Current view: top level - third_party/LercLib - BitStuffer2.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 251 284 88.4 %
Date: 2024-05-06 22:33:47 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             : Copyright 2015 Esri
       3             : 
       4             : Licensed under the Apache License, Version 2.0 (the "License");
       5             : you may not use this file except in compliance with the License.
       6             : You may obtain a copy of the License at
       7             : 
       8             : http://www.apache.org/licenses/LICENSE-2.0
       9             : 
      10             : Unless required by applicable law or agreed to in writing, software
      11             : distributed under the License is distributed on an "AS IS" BASIS,
      12             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13             : See the License for the specific language governing permissions and
      14             : limitations under the License.
      15             : 
      16             : A local copy of the license and additional notices are located with the
      17             : source distribution at:
      18             : 
      19             : http://github.com/Esri/lerc/
      20             : 
      21             : Contributors:  Thomas Maurer
      22             : */
      23             : 
      24             : #include <algorithm>
      25             : #include <cassert>
      26             : #include "Defines.h"
      27             : #include "BitStuffer2.h"
      28             : 
      29             : using namespace std;
      30             : USING_NAMESPACE_LERC
      31             : 
      32             : // -------------------------------------------------------------------------- ;
      33             : 
      34             : // if you change Encode(...) / Decode(...), don't forget to update ComputeNumBytesNeeded(...)
      35             : 
      36       42549 : bool BitStuffer2::EncodeSimple(Byte** ppByte, const vector<unsigned int>& dataVec, int lerc2Version) const
      37             : {
      38       42549 :   if (!ppByte || dataVec.empty())
      39           0 :     return false;
      40             : 
      41       42549 :   unsigned int maxElem = *max_element(dataVec.begin(), dataVec.end());
      42       42549 :   int numBits = 0;
      43      150067 :   while ((numBits < 32) && (maxElem >> numBits))
      44      107518 :     numBits++;
      45             : 
      46       42549 :   if (numBits >= 32)
      47           0 :     return false;
      48             : 
      49       42549 :   Byte numBitsByte = (Byte)numBits;
      50       42549 :   unsigned int numElements = (unsigned int)dataVec.size();
      51       42549 :   unsigned int numUInts = (numElements * numBits + 31) / 32;
      52             : 
      53             :   // use the upper 2 bits to encode the type used for numElements: Byte, ushort, or uint
      54       42549 :   int n = NumBytesUInt(numElements);
      55       42549 :   int bits67 = (n == 4) ? 0 : 3 - n;
      56       42549 :   numBitsByte |= bits67 << 6;
      57             : 
      58             :   // bit5 = 0 means simple mode
      59             : 
      60       42549 :   **ppByte = numBitsByte;
      61       42549 :   (*ppByte)++;
      62             : 
      63       42549 :   if (!EncodeUInt(ppByte, numElements, n))
      64           0 :     return false;
      65             : 
      66       42549 :   if (numUInts > 0)    // numBits can be 0, then we only write the header
      67             :   {
      68       42549 :     if (lerc2Version >= 3)
      69       18287 :       BitStuff(ppByte, dataVec, numBits);
      70             :     else
      71       24262 :       BitStuff_Before_Lerc2v3(ppByte, dataVec, numBits);
      72             :   }
      73             : 
      74       42549 :   return true;
      75             : }
      76             : 
      77             : // -------------------------------------------------------------------------- ;
      78             : 
      79      220916 : bool BitStuffer2::EncodeLut(Byte** ppByte, const vector<pair<unsigned int, unsigned int> >& sortedDataVec, int lerc2Version) const
      80             : {
      81      220916 :   if (!ppByte || sortedDataVec.empty())
      82           0 :     return false;
      83             : 
      84      220916 :   if (sortedDataVec[0].first != 0)    // corresponds to min
      85           0 :     return false;
      86             : 
      87             :   // collect the different values for the lut
      88      220916 :   unsigned int numElem = (unsigned int)sortedDataVec.size();
      89      220916 :   unsigned int indexLut = 0;
      90             : 
      91      220916 :   m_tmpLutVec.resize(0);    // omit the 0 throughout that corresponds to min
      92      220916 :   m_tmpIndexVec.assign(numElem, 0);
      93             : 
      94    14708400 :   for (unsigned int i = 1; i < numElem; i++)
      95             :   {
      96    14487500 :     unsigned int prev = sortedDataVec[i - 1].first;
      97    14487500 :     m_tmpIndexVec[sortedDataVec[i - 1].second] = indexLut;
      98             : 
      99    14487500 :     if (sortedDataVec[i].first != prev)
     100             :     {
     101      320862 :       m_tmpLutVec.push_back(sortedDataVec[i].first);
     102      320862 :       indexLut++;
     103             :     }
     104             :   }
     105      220916 :   m_tmpIndexVec[sortedDataVec[numElem - 1].second] = indexLut;    // don't forget the last one
     106             : 
     107             :   // write first 2 data elements same as simple, but bit5 set to 1
     108      220916 :   unsigned int maxElem = m_tmpLutVec.back();
     109      220916 :   int numBits = 0;
     110     1182940 :   while ((numBits < 32) && (maxElem >> numBits))
     111      962025 :     numBits++;
     112             : 
     113      220916 :   if (numBits >= 32)
     114           0 :     return false;
     115             : 
     116      220916 :   Byte numBitsByte = (Byte)numBits;
     117             : 
     118             :   // use the upper 2 bits to encode the type used for numElem: byte, ushort, or uint
     119      220916 :   int n = NumBytesUInt(numElem);
     120      220916 :   int bits67 = (n == 4) ? 0 : 3 - n;
     121      220916 :   numBitsByte |= bits67 << 6;
     122             : 
     123      220916 :   numBitsByte |= (1 << 5);    // bit 5 = 1 means lut mode
     124             : 
     125      220916 :   **ppByte = numBitsByte;
     126      220916 :   (*ppByte)++;
     127             : 
     128      220916 :   if (!EncodeUInt(ppByte, numElem, n))    // numElements = numIndexes to lut
     129           0 :     return false;
     130             : 
     131      220916 :   unsigned int nLut = (unsigned int)m_tmpLutVec.size();
     132      220916 :   if (nLut < 1 || nLut >= 255)
     133           0 :     return false;
     134             : 
     135      220916 :   **ppByte = (Byte)nLut + 1;    // size of lut, incl the 0
     136      220916 :   (*ppByte)++;
     137             : 
     138      220916 :   if (lerc2Version >= 3)
     139        1112 :     BitStuff(ppByte, m_tmpLutVec, numBits);    // lut
     140             :   else
     141      219804 :     BitStuff_Before_Lerc2v3(ppByte, m_tmpLutVec, numBits);
     142             : 
     143      220916 :   int nBitsLut = 0;
     144      496289 :   while (nLut >> nBitsLut)    // indexes are in [0 .. nLut]
     145      275373 :     nBitsLut++;
     146             : 
     147      220916 :   if (lerc2Version >= 3)
     148        1112 :     BitStuff(ppByte, m_tmpIndexVec, nBitsLut);    // indexes
     149             :   else
     150      219804 :     BitStuff_Before_Lerc2v3(ppByte, m_tmpIndexVec, nBitsLut);
     151             : 
     152      220916 :   return true;
     153             : }
     154             : 
     155             : // -------------------------------------------------------------------------- ;
     156             : 
     157             : // if you change Encode(...) / Decode(...), don't forget to update ComputeNumBytesNeeded(...)
     158             : 
     159      113518 : bool BitStuffer2::Decode(const Byte** ppByte, size_t& nBytesRemaining, vector<unsigned int>& dataVec, size_t maxElementCount, int lerc2Version) const
     160             : {
     161      113518 :   if (!ppByte || nBytesRemaining < 1)
     162           0 :     return false;
     163             : 
     164      113518 :   Byte numBitsByte = **ppByte;
     165      113518 :   (*ppByte)++;
     166      113518 :   nBytesRemaining--;
     167             : 
     168      113518 :   int bits67 = numBitsByte >> 6;
     169      113518 :   int nb = (bits67 == 0) ? 4 : 3 - bits67;
     170             : 
     171      113518 :   bool doLut = (numBitsByte & (1 << 5)) ? true : false;    // bit 5
     172      113518 :   numBitsByte &= 31;    // bits 0-4;
     173      113518 :   int numBits = numBitsByte;
     174             : 
     175      113518 :   unsigned int numElements = 0;
     176      113518 :   if (!DecodeUInt(ppByte, nBytesRemaining, numElements, nb))
     177           0 :     return false;
     178      113518 :   if (numElements > maxElementCount)
     179           0 :     return false;
     180             : 
     181      113518 :   if (!doLut)
     182             :   {
     183       38554 :     if (numBits > 0)    // numBits can be 0
     184             :     {
     185       38554 :       if (lerc2Version >= 3)
     186             :       {
     187       30346 :         if (!BitUnStuff(ppByte, nBytesRemaining, dataVec, numElements, numBits))
     188           0 :           return false;
     189             :       }
     190             :       else
     191             :       {
     192        8208 :         if (!BitUnStuff_Before_Lerc2v3(ppByte, nBytesRemaining, dataVec, numElements, numBits))
     193           0 :           return false;
     194             :       }
     195             :     }
     196             :   }
     197             :   else
     198             :   {
     199       74964 :     if (numBits == 0)  // fail gracefully in case of corrupted blob for old version <= 2 which had no checksum
     200           0 :       return false;
     201       74964 :     if (nBytesRemaining < 1)
     202           0 :       return false;
     203             : 
     204       74964 :     Byte nLutByte = **ppByte;
     205       74964 :     (*ppByte)++;
     206       74964 :     nBytesRemaining--;
     207             : 
     208       74964 :     int nLut = nLutByte - 1;
     209             : 
     210             :     // unstuff lut w/o the 0
     211       74964 :     if (lerc2Version >= 3)
     212             :     {
     213         982 :       if (!BitUnStuff(ppByte, nBytesRemaining, m_tmpLutVec, nLut, numBits))
     214           0 :         return false;
     215             :     }
     216             :     else
     217             :     {
     218       73982 :       if (!BitUnStuff_Before_Lerc2v3(ppByte, nBytesRemaining, m_tmpLutVec, nLut, numBits))
     219           0 :         return false;
     220             :     }
     221             : 
     222       74964 :     int nBitsLut = 0;
     223      169423 :     while (nLut >> nBitsLut)
     224       94459 :       nBitsLut++;
     225       74964 :     if (nBitsLut == 0)
     226           0 :       return false;
     227             : 
     228       74964 :     if (lerc2Version >= 3)
     229             :     {
     230             :       // unstuff indexes
     231         982 :       if (!BitUnStuff(ppByte, nBytesRemaining, dataVec, numElements, nBitsLut))
     232           0 :         return false;
     233             : 
     234             :       // replace indexes by values
     235         982 :       m_tmpLutVec.insert(m_tmpLutVec.begin(), 0);    // put back in the 0
     236       61462 :       for (unsigned int i = 0; i < numElements; i++)
     237             :       {
     238             : #ifdef GDAL_COMPILATION
     239       60480 :         if (dataVec[i] >= m_tmpLutVec.size())
     240           0 :           return false;
     241             : #endif
     242       60480 :         dataVec[i] = m_tmpLutVec[dataVec[i]];
     243             :       }
     244             :     }
     245             :     else
     246             :     {
     247             :       // unstuff indexes
     248       73982 :       if (!BitUnStuff_Before_Lerc2v3(ppByte, nBytesRemaining, dataVec, numElements, nBitsLut))
     249           0 :         return false;
     250             : 
     251             :       // replace indexes by values
     252       73982 :       m_tmpLutVec.insert(m_tmpLutVec.begin(), 0);    // put back in the 0
     253     4992960 :       for (unsigned int i = 0; i < numElements; i++)
     254             :       {
     255     4918980 :         if (dataVec[i] >= m_tmpLutVec.size())
     256           0 :           return false;
     257             : 
     258     4918980 :         dataVec[i] = m_tmpLutVec[dataVec[i]];
     259             :       }
     260             :     }
     261             :   }
     262             : 
     263      113518 :   return true;
     264             : }
     265             : 
     266             : // -------------------------------------------------------------------------- ;
     267             : 
     268      709569 : unsigned int BitStuffer2::ComputeNumBytesNeededLut(const vector<pair<unsigned int, unsigned int> >& sortedDataVec, bool& doLut)
     269             : {
     270      709569 :   unsigned int maxElem = sortedDataVec.back().first;
     271      709569 :   unsigned int numElem = (unsigned int)sortedDataVec.size();
     272             : 
     273      709569 :   int numBits = 0;
     274     3591790 :   while ((numBits < 32) && (maxElem >> numBits))
     275     2882220 :     numBits++;
     276      709569 :   unsigned int numBytes = 1 + NumBytesUInt(numElem) + ((numElem * numBits + 7) >> 3);
     277             : 
     278             :   // go through and count how often the value changes
     279      709569 :   int nLut = 0;
     280    71172000 :   for (unsigned int i = 1; i < numElem; i++)
     281    70462500 :     if (sortedDataVec[i].first != sortedDataVec[i - 1].first)
     282     1145300 :       nLut++;
     283             : 
     284      709569 :   int nBitsLut = 0;
     285     1655040 :   while (nLut >> nBitsLut)
     286      945475 :     nBitsLut++;
     287             : 
     288      709569 :   unsigned int numBitsTotalLut = nLut * numBits;    // num bits w/o the 0
     289      709569 :   unsigned int numBytesLut = 1 + NumBytesUInt(numElem) + 1 + ((numBitsTotalLut + 7) >> 3) + ((numElem * nBitsLut + 7) >> 3);
     290             : 
     291      709569 :   doLut = numBytesLut < numBytes;
     292      709569 :   return min(numBytesLut, numBytes);
     293             : }
     294             : 
     295             : // -------------------------------------------------------------------------- ;
     296             : // -------------------------------------------------------------------------- ;
     297             : 
     298      463870 : void BitStuffer2::BitStuff_Before_Lerc2v3(Byte** ppByte, const vector<unsigned int>& dataVec, int numBits)
     299             : {
     300      463870 :   unsigned int numElements = (unsigned int)dataVec.size();
     301      463870 :   unsigned int numUInts = (numElements * numBits + 31) / 32;
     302      463870 :   unsigned int numBytes = numUInts * sizeof(unsigned int);
     303      463870 :   unsigned int* arr = (unsigned int*)(*ppByte);
     304             : 
     305      463870 :   memset(arr, 0, numBytes);
     306             : 
     307             :   // do the stuffing
     308      463870 :   const unsigned int* srcPtr = &dataVec[0];
     309      463870 :   unsigned int* dstPtr = arr;
     310      463870 :   int bitPos = 0;
     311             : 
     312    17363600 :   for (unsigned int i = 0; i < numElements; i++)
     313             :   {
     314    16899800 :     if (32 - bitPos >= numBits)
     315             :     {
     316             :       unsigned int dstValue;
     317    16897100 :       memcpy(&dstValue, dstPtr, sizeof(unsigned int));
     318    16897100 :       dstValue |= (*srcPtr++) << (32 - bitPos - numBits);
     319    16897100 :       memcpy(dstPtr, &dstValue, sizeof(unsigned int));
     320    16897100 :       bitPos += numBits;
     321    16897100 :       if (bitPos == 32)    // shift >= 32 is undefined
     322             :       {
     323      641691 :         bitPos = 0;
     324      641691 :         dstPtr++;
     325             :       }
     326             :     }
     327             :     else
     328             :     {
     329             :       unsigned int dstValue;
     330        2634 :       int n = numBits - (32 - bitPos);
     331        2634 :       memcpy(&dstValue, dstPtr, sizeof(unsigned int));
     332        2634 :       dstValue |= (*srcPtr) >> n;
     333        2634 :       memcpy(dstPtr, &dstValue, sizeof(unsigned int));
     334        2634 :       dstPtr++;
     335        2634 :       memcpy(&dstValue, dstPtr, sizeof(unsigned int));
     336        2634 :       dstValue |= (*srcPtr++) << (32 - n);
     337        2634 :       memcpy(dstPtr, &dstValue, sizeof(unsigned int));
     338        2634 :       bitPos = n;
     339             :     }
     340             :   }
     341             : 
     342             :   // save the 0-3 bytes not used in the last UInt
     343      463870 :   unsigned int numBytesNotNeeded = NumTailBytesNotNeeded(numElements, numBits);
     344      463870 :   unsigned int n = numBytesNotNeeded;
     345     1060330 :   for (; n; --n)
     346             :   {
     347             :     unsigned int dstValue;
     348      596462 :     memcpy(&dstValue, dstPtr, sizeof(unsigned int));
     349      596462 :     dstValue >>= 8;
     350      596462 :     memcpy(dstPtr, &dstValue, sizeof(unsigned int));
     351             :   }
     352             : 
     353      463870 :   *ppByte += numBytes - numBytesNotNeeded;
     354      463870 : }
     355             : 
     356             : // -------------------------------------------------------------------------- ;
     357             : 
     358      156172 : bool BitStuffer2::BitUnStuff_Before_Lerc2v3(const Byte** ppByte, size_t& nBytesRemaining,
     359             :     vector<unsigned int>& dataVec, unsigned int numElements, int numBits) const
     360             : {
     361      156172 :   if (numElements == 0 || numBits >= 32)
     362           0 :     return false;
     363      156172 :   unsigned long long numUIntsLL = ((unsigned long long)numElements * numBits + 31) / 32;
     364      156172 :   unsigned long long numBytesLL = numUIntsLL * sizeof(unsigned int);
     365      156172 :   size_t numBytes = (size_t)numBytesLL; // could theoretically overflow on 32 bit system
     366      156172 :   size_t numUInts = (size_t)numUIntsLL;
     367      156172 :   unsigned int ntbnn = NumTailBytesNotNeeded(numElements, numBits);
     368      156172 :   if (numBytes != numBytesLL || nBytesRemaining + ntbnn < numBytes)
     369           0 :     return false;
     370             : 
     371             :   try
     372             :   {
     373      156172 :     dataVec.resize(numElements, 0);    // init with 0
     374      156172 :     m_tmpBitStuffVec.resize(numUInts);
     375             :   }
     376           0 :   catch( const std::exception& )
     377             :   {
     378           0 :     return false;
     379             :   }
     380             : 
     381      156172 :   m_tmpBitStuffVec[numUInts - 1] = 0;    // set last uint to 0
     382             : 
     383      156172 :   unsigned int nBytesToCopy = (numElements * numBits + 7) / 8;
     384      156172 :   memcpy(&m_tmpBitStuffVec[0], *ppByte, nBytesToCopy);
     385             : 
     386      156172 :   unsigned int* pLastULong = &m_tmpBitStuffVec[numUInts - 1];
     387      356374 :   while (ntbnn)
     388             :   {
     389      200202 :     -- ntbnn;
     390      200202 :     *pLastULong <<= 8;
     391             :   }
     392             : 
     393      156172 :   unsigned int* srcPtr = &m_tmpBitStuffVec[0];
     394      156172 :   unsigned int* dstPtr = &dataVec[0];
     395      156172 :   int bitPos = 0;
     396             : 
     397     5855250 :   for (unsigned int i = 0; i < numElements; i++)
     398             :   {
     399     5699080 :     if (32 - bitPos >= numBits)
     400             :     {
     401             :       unsigned int val;
     402     5697570 :       memcpy(&val, srcPtr, sizeof(unsigned int));
     403     5697570 :       unsigned int n = val << bitPos;
     404     5697570 :       *dstPtr++ = n >> (32 - numBits);
     405     5697570 :       bitPos += numBits;
     406             : 
     407     5697570 :       if (bitPos == 32)    // shift >= 32 is undefined
     408             :       {
     409      216619 :         bitPos = 0;
     410      216619 :         srcPtr++;
     411             :       }
     412             :     }
     413             :     else
     414             :     {
     415             :       unsigned int val;
     416        1511 :       memcpy(&val, srcPtr, sizeof(unsigned int));
     417        1511 :       srcPtr++;
     418        1511 :       unsigned int n = val << bitPos;
     419        1511 :       *dstPtr = n >> (32 - numBits);
     420        1511 :       bitPos -= (32 - numBits);
     421        1511 :       memcpy(&val, srcPtr, sizeof(unsigned int));
     422        1511 :       *dstPtr++ |= val >> (32 - bitPos);
     423             :     }
     424             :   }
     425             : 
     426      156172 :   *ppByte += nBytesToCopy;
     427      156172 :   nBytesRemaining -= nBytesToCopy;
     428             : 
     429      156172 :   return true;
     430             : }
     431             : 
     432             : // -------------------------------------------------------------------------- ;
     433             : 
     434             : // starting with version Lerc2v3: integer >> into local uint buffer, plus final memcpy
     435             : 
     436       20511 : void BitStuffer2::BitStuff(Byte** ppByte, const vector<unsigned int>& dataVec, int numBits) const
     437             : {
     438       20511 :   unsigned int numElements = (unsigned int)dataVec.size();
     439       20511 :   unsigned int numUInts = (numElements * numBits + 31) / 32;
     440       20511 :   unsigned int numBytes = numUInts * sizeof(unsigned int);
     441             : 
     442       20511 :   m_tmpBitStuffVec.resize(numUInts);
     443       20511 :   unsigned int* dstPtr = &m_tmpBitStuffVec[0];
     444             : 
     445       20511 :   memset(dstPtr, 0, numBytes);
     446             : 
     447             :   // do the stuffing
     448       20511 :   const unsigned int* srcPtr = &dataVec[0];
     449       20511 :   int bitPos = 0;
     450       20511 :   assert(numBits <= 32); // to avoid coverity warning about large shift a bit later, when doing (*srcPtr++) >> (32 - bitPos)
     451             : 
     452     1354360 :   for (unsigned int i = 0; i < numElements; i++)
     453             :   {
     454     1333850 :     if (32 - bitPos >= numBits)
     455             :     {
     456     1253970 :       *dstPtr |= (*srcPtr++) << bitPos;
     457     1253970 :       bitPos += numBits;
     458     1253970 :       if (bitPos == 32)    // shift >= 32 is undefined
     459             :       {
     460       97956 :         dstPtr++;
     461       97956 :         bitPos = 0;
     462             :       }
     463             :     }
     464             :     else
     465             :     {
     466       79880 :       *dstPtr++ |= (*srcPtr) << bitPos;
     467       79880 :       *dstPtr |= (*srcPtr++) >> (32 - bitPos);
     468       79880 :       bitPos += numBits - 32;
     469             :     }
     470             :   }
     471             : 
     472             :   // copy the bytes to the outgoing byte stream
     473       20511 :   size_t numBytesUsed = numBytes - NumTailBytesNotNeeded(numElements, numBits);
     474             : #ifdef CSA_BUILD
     475             :   assert( numElements );
     476             : #endif
     477       20511 :   memcpy(*ppByte, m_tmpBitStuffVec.data(), numBytesUsed);
     478             : 
     479       20511 :   *ppByte += numBytesUsed;
     480       20511 : }
     481             : 
     482             : // -------------------------------------------------------------------------- ;
     483             : 
     484       32310 : bool BitStuffer2::BitUnStuff(const Byte** ppByte, size_t& nBytesRemaining, vector<unsigned int>& dataVec,
     485             :   unsigned int numElements, int numBits) const
     486             : {
     487       32310 :   if (numElements == 0 || numBits >= 32)
     488           0 :     return false;
     489       32310 :   unsigned long long numUIntsLL = ((unsigned long long)numElements * numBits + 31) / 32;
     490       32310 :   unsigned long long numBytesLL = numUIntsLL * sizeof(unsigned int);
     491       32310 :   size_t numBytes = (size_t)numBytesLL; // could theoretically overflow on 32 bit system
     492       32310 :   if (numBytes != numBytesLL)
     493           0 :     return false;
     494       32310 :   size_t numUInts = (size_t)numUIntsLL;
     495             : 
     496             :   // copy the bytes from the incoming byte stream
     497       32310 :   const size_t numBytesUsed = numBytes - NumTailBytesNotNeeded(numElements, numBits);
     498             : 
     499       32310 :   if (nBytesRemaining < numBytesUsed)
     500           0 :     return false;
     501             : 
     502             :   try
     503             :   {
     504       32310 :     dataVec.resize(numElements);
     505             :   }
     506           0 :   catch( const std::exception& )
     507             :   {
     508           0 :     return false;
     509             :   }
     510             : 
     511             :   try
     512             :   {
     513       32310 :     m_tmpBitStuffVec.resize(numUInts);
     514             :   }
     515           0 :   catch( const std::exception& )
     516             :   {
     517           0 :     return false;
     518             :   }
     519             : 
     520       32310 :   m_tmpBitStuffVec[numUInts - 1] = 0;    // set last uint to 0
     521             : 
     522       32310 :   memcpy(&m_tmpBitStuffVec[0], *ppByte, numBytesUsed);
     523             : 
     524             :   // do the un-stuffing
     525       32310 :   unsigned int* srcPtr = &m_tmpBitStuffVec[0];
     526       32310 :   unsigned int* dstPtr = &dataVec[0];
     527       32310 :   int bitPos = 0;
     528       32310 :   int nb = 32 - numBits;
     529             : 
     530     2089430 :   for (unsigned int i = 0; i < numElements; i++)
     531             :   {
     532     2057120 :     if (nb - bitPos >= 0)
     533             :     {
     534     1948520 :       *dstPtr++ = ((*srcPtr) << (nb - bitPos)) >> nb;
     535     1948520 :       bitPos += numBits;
     536     1948520 :       if (bitPos == 32)    // shift >= 32 is undefined
     537             :       {
     538      159164 :         srcPtr++;
     539      159164 :         bitPos = 0;
     540             :       }
     541             :     }
     542             :     else
     543             :     {
     544      108600 :       *dstPtr = (*srcPtr++) >> bitPos;
     545      108600 :       *dstPtr++ |= ((*srcPtr) << (64 - numBits - bitPos)) >> nb;
     546      108600 :       bitPos -= nb;
     547             :     }
     548             :   }
     549             : 
     550       32310 :   *ppByte += numBytesUsed;
     551       32310 :   nBytesRemaining -= numBytesUsed;
     552       32310 :   return true;
     553             : }
     554             : 
     555             : // -------------------------------------------------------------------------- ;
     556             : 

Generated by: LCOV version 1.14