00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include "bitstream.h"
00025
00026 #include <xapian/types.h>
00027
00028 #include "omassert.h"
00029
00030 #include <cmath>
00031 #include <vector>
00032
00033 using namespace std;
00034
00035 static const unsigned char flstab[256] = {
00036 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
00037 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
00038 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
00039 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
00040 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
00041 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
00042 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
00043 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
00044 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
00045 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
00046 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
00047 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
00048 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
00049 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
00050 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
00051 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
00052 };
00053
00054
00055 inline int my_fls(unsigned mask)
00056 {
00057 int result = 0;
00058 if (mask >= 0x10000u) {
00059 mask >>= 16;
00060 result = 16;
00061 }
00062 if (mask >= 0x100u) {
00063 mask >>= 8;
00064 result += 8;
00065 }
00066 return result + flstab[mask];
00067 }
00068
00069 namespace Xapian {
00070
00071 void
00072 BitWriter::encode(size_t value, size_t outof)
00073 {
00074 Assert(value < outof);
00075 size_t bits = my_fls(outof - 1);
00076 const size_t spare = (1 << bits) - outof;
00077 if (spare) {
00078 const size_t mid_start = (outof - spare) / 2;
00079 if (value >= mid_start + spare) {
00080 value = (value - (mid_start + spare)) | (1 << (bits - 1));
00081 } else if (value >= mid_start) {
00082 --bits;
00083 }
00084 }
00085
00086 if (bits + n_bits > 32) {
00087
00088
00089
00090 Assert(bits <= 32);
00091 acc |= (value << n_bits);
00092 buf += char(acc);
00093 acc >>= 8;
00094 value >>= 8;
00095 bits -= 8;
00096 }
00097 acc |= (value << n_bits);
00098 n_bits += bits;
00099 while (n_bits >= 8) {
00100 buf += char(acc);
00101 acc >>= 8;
00102 n_bits -= 8;
00103 }
00104 }
00105
00106 void
00107 BitWriter::encode_interpolative(const vector<Xapian::termpos> &pos, int j, int k)
00108 {
00109 while (j + 1 < k) {
00110 const size_t mid = (j + k) / 2;
00111
00112
00113
00114 const size_t outof = pos[k] - pos[j] + j - k + 1;
00115 const size_t lowest = pos[j] + mid - j;
00116 encode(pos[mid] - lowest, outof);
00117 encode_interpolative(pos, j, mid);
00118 j = mid;
00119 }
00120 }
00121
00122 Xapian::termpos
00123 BitReader::decode(Xapian::termpos outof)
00124 {
00125 size_t bits = my_fls(outof - 1);
00126 const size_t spare = (1 << bits) - outof;
00127 const size_t mid_start = (outof - spare) / 2;
00128 Xapian::termpos p;
00129 if (spare) {
00130 p = read_bits(bits - 1);
00131 if (p < mid_start) {
00132 if (read_bits(1)) p += mid_start + spare;
00133 }
00134 } else {
00135 p = read_bits(bits);
00136 }
00137 Assert(p < outof);
00138 return p;
00139 }
00140
00141 unsigned int
00142 BitReader::read_bits(int count)
00143 {
00144 unsigned int result;
00145 if (count > 25) {
00146
00147
00148
00149
00150 Assert(count <= 32);
00151 result = read_bits(16);
00152 return result | (read_bits(count - 16) << 16);
00153 }
00154 while (n_bits < count) {
00155 Assert(idx < buf.size());
00156 acc |= static_cast<unsigned char>(buf[idx++]) << n_bits;
00157 n_bits += 8;
00158 }
00159 result = acc & ((1u << count) - 1);
00160 acc >>= count;
00161 n_bits -= count;
00162 return result;
00163 }
00164
00165 void
00166 BitReader::decode_interpolative(vector<Xapian::termpos> & pos, int j, int k)
00167 {
00168 while (j + 1 < k) {
00169 const size_t mid = (j + k) / 2;
00170
00171
00172
00173 const size_t outof = pos[k] - pos[j] + j - k + 1;
00174 pos[mid] = decode(outof) + (pos[j] + mid - j);
00175 decode_interpolative(pos, j, mid);
00176 j = mid;
00177 }
00178 }
00179
00180 }