LCOV - code coverage report
Current view: top level - common - bitstream.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core r Lines: 62 69 89.9 %
Date: 2011-08-21 Functions: 6 6 100.0 %
Branches: 26 28 92.9 %

           Branch data     Line data    Source code
       1                 :            : /** @file bitstream.cc
       2                 :            :  * @brief Classes to encode/decode a bitstream.
       3                 :            :  */
       4                 :            : /* Copyright (C) 2004,2005,2006,2008 Olly Betts
       5                 :            :  *
       6                 :            :  * This program is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU General Public License as
       8                 :            :  * published by the Free Software Foundation; either version 2 of the
       9                 :            :  * License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This program is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :            :  * GNU General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU General Public License
      17                 :            :  * along with this program; if not, write to the Free Software
      18                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      19                 :            :  * USA
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <config.h>
      23                 :            : 
      24                 :            : #include "bitstream.h"
      25                 :            : 
      26                 :            : #include <xapian/types.h>
      27                 :            : 
      28                 :            : #include "omassert.h"
      29                 :            : 
      30                 :            : #include <cmath>
      31                 :            : #include <vector>
      32                 :            : 
      33                 :            : using namespace std;
      34                 :            : 
      35                 :            : static const unsigned char flstab[256] = {
      36                 :            :     0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
      37                 :            :     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
      38                 :            :     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
      39                 :            :     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
      40                 :            :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      41                 :            :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      42                 :            :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      43                 :            :     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
      44                 :            :     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
      45                 :            :     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
      46                 :            :     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
      47                 :            :     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
      48                 :            :     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
      49                 :            :     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
      50                 :            :     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
      51                 :            :     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
      52                 :            : };
      53                 :            : 
      54                 :            : // Highly optimised fls() implementation.
      55                 :     293811 : inline int my_fls(unsigned mask)
      56                 :            : {
      57                 :     293811 :     int result = 0;
      58         [ +  + ]:     293811 :     if (mask >= 0x10000u) {
      59                 :       1512 :         mask >>= 16;
      60                 :       1512 :         result = 16;
      61                 :            :     }
      62         [ +  + ]:     293811 :     if (mask >= 0x100u) {
      63                 :      41706 :         mask >>= 8;
      64                 :      41706 :         result += 8;
      65                 :            :     }
      66                 :     293811 :     return result + flstab[mask];
      67                 :            : }
      68                 :            : 
      69                 :            : namespace Xapian {
      70                 :            : 
      71                 :            : void
      72                 :     232005 : BitWriter::encode(size_t value, size_t outof)
      73                 :            : {
      74                 :            :     Assert(value < outof);
      75                 :     232005 :     size_t bits = my_fls(outof - 1);
      76                 :     232005 :     const size_t spare = (1 << bits) - outof;
      77         [ +  + ]:     232005 :     if (spare) {
      78                 :     225015 :         const size_t mid_start = (outof - spare) / 2;
      79         [ +  + ]:     225015 :         if (value >= mid_start + spare) {
      80                 :      23271 :             value = (value - (mid_start + spare)) | (1 << (bits - 1));
      81         [ +  + ]:     201744 :         } else if (value >= mid_start) {
      82                 :     107535 :             --bits;
      83                 :            :         }
      84                 :            :     }
      85                 :            : 
      86         [ -  + ]:     232005 :     if (bits + n_bits > 32) {
      87                 :            :         // We need to write more bits than there's empty room for in
      88                 :            :         // the accumulator.  So we arrange to shift out 8 bits, then
      89                 :            :         // adjust things so we're adding 8 fewer bits.
      90                 :            :         Assert(bits <= 32);
      91                 :          0 :         acc |= (value << n_bits);
      92                 :          0 :         buf += char(acc);
      93                 :          0 :         acc >>= 8;
      94                 :          0 :         value >>= 8;
      95                 :          0 :         bits -= 8;
      96                 :            :     }
      97                 :     232005 :     acc |= (value << n_bits);
      98                 :     232005 :     n_bits += bits;
      99         [ +  + ]:     389745 :     while (n_bits >= 8) {
     100                 :     157740 :         buf += char(acc);
     101                 :     157740 :         acc >>= 8;
     102                 :     157740 :         n_bits -= 8;
     103                 :            :     }
     104                 :     232005 : }
     105                 :            : 
     106                 :            : void
     107                 :     175686 : BitWriter::encode_interpolative(const vector<Xapian::termpos> &pos, int j, int k)
     108                 :            : {
     109         [ +  + ]:     295053 :     while (j + 1 < k) {
     110                 :     119367 :         const size_t mid = (j + k) / 2;
     111                 :            :         // Encode one out of (pos[k] - pos[j] + 1) values
     112                 :            :         // (less some at either end because we must be able to fit
     113                 :            :         // all the intervening pos in)
     114                 :     119367 :         const size_t outof = pos[k] - pos[j] + j - k + 1;
     115                 :     119367 :         const size_t lowest = pos[j] + mid - j;
     116                 :     119367 :         encode(pos[mid] - lowest, outof);
     117                 :     119367 :         encode_interpolative(pos, j, mid);
     118                 :     119367 :         j = mid;
     119                 :            :     }
     120                 :     175686 : }
     121                 :            : 
     122                 :            : Xapian::termpos
     123                 :      61806 : BitReader::decode(Xapian::termpos outof)
     124                 :            : {
     125                 :      61806 :     size_t bits = my_fls(outof - 1);
     126                 :      61806 :     const size_t spare = (1 << bits) - outof;
     127                 :      61806 :     const size_t mid_start = (outof - spare) / 2;
     128                 :            :     Xapian::termpos p;
     129         [ +  + ]:      61806 :     if (spare) {
     130                 :      60453 :         p = read_bits(bits - 1);
     131         [ +  + ]:      60453 :         if (p < mid_start) {
     132         [ +  + ]:       7341 :             if (read_bits(1)) p += mid_start + spare;
     133                 :            :         }
     134                 :            :     } else {
     135                 :       1353 :         p = read_bits(bits);
     136                 :            :     }
     137                 :            :     Assert(p < outof);
     138                 :      61806 :     return p;
     139                 :            : }
     140                 :            : 
     141                 :            : unsigned int
     142                 :      69147 : BitReader::read_bits(int count)
     143                 :            : {
     144                 :            :     unsigned int result;
     145         [ -  + ]:      69147 :     if (count > 25) {
     146                 :            :         // If we need more than 25 bits, read in two goes to ensure that we
     147                 :            :         // don't overflow acc.  This is a little more conservative than it
     148                 :            :         // needs to be, but such large values will inevitably be rare (because
     149                 :            :         // you can't fit very many of them into 2^32!)
     150                 :            :         Assert(count <= 32);
     151                 :          0 :         result = read_bits(16);
     152                 :          0 :         return result | (read_bits(count - 16) << 16);
     153                 :            :     }
     154         [ +  + ]:     117213 :     while (n_bits < count) {
     155                 :            :         Assert(idx < buf.size());
     156                 :      48066 :         acc |= static_cast<unsigned char>(buf[idx++]) << n_bits;
     157                 :      48066 :         n_bits += 8;
     158                 :            :     }
     159                 :      69147 :     result = acc & ((1u << count) - 1);
     160                 :      69147 :     acc >>= count;
     161                 :      69147 :     n_bits -= count;
     162                 :      69147 :     return result;
     163                 :            : }
     164                 :            : 
     165                 :            : void
     166                 :      58203 : BitReader::decode_interpolative(vector<Xapian::termpos> & pos, int j, int k)
     167                 :            : {
     168         [ +  + ]:     113721 :     while (j + 1 < k) {
     169                 :      55518 :         const size_t mid = (j + k) / 2;
     170                 :            :         // Decode one out of (pos[k] - pos[j] + 1) values
     171                 :            :         // (less some at either end because we must be able to fit
     172                 :            :         // all the intervening pos in)
     173                 :      55518 :         const size_t outof = pos[k] - pos[j] + j - k + 1;
     174                 :      55518 :         pos[mid] = decode(outof) + (pos[j] + mid - j);
     175                 :      55518 :         decode_interpolative(pos, j, mid);
     176                 :      55518 :         j = mid;
     177                 :            :     }
     178                 :      58203 : }
     179                 :            : 
     180                 :            : }

Generated by: LCOV version 1.8