00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef OM_HGUARD_FLINT_UTILS_H
00024 #define OM_HGUARD_FLINT_UTILS_H
00025
00026 #include "omassert.h"
00027
00028 #include <xapian/types.h>
00029
00030 #include <string>
00031
00032 using namespace std;
00033
00034 typedef unsigned char om_byte;
00035 typedef unsigned int om_uint32;
00036 typedef int om_int32;
00037
00062 template<class T>
00063 bool
00064 F_unpack_uint(const char ** src,
00065 const char * src_end,
00066 T * resultptr)
00067 {
00068
00069 STATIC_ASSERT_UNSIGNED_TYPE(T);
00070
00071
00072 STATIC_ASSERT(sizeof(om_byte) == 1);
00073
00074 unsigned int shift = 0;
00075 T result = 0;
00076
00077 while (true) {
00078 if ((*src) == src_end) {
00079 *src = 0;
00080 return false;
00081 }
00082
00083 om_byte part = static_cast<om_byte>(**src);
00084 (*src)++;
00085
00086
00087 if (((shift > (sizeof(T) - 1) * 8 + 1) &&
00088 ((part & 0x7f) << (shift % 8)) >= 0x100) ||
00089 (shift >= sizeof(T) * 8)) {
00090
00091 while (true) {
00092 if ((part & 0x80) == 0) return false;
00093 if ((*src) == src_end) {
00094 *src = 0;
00095 return false;
00096 }
00097 part = static_cast<om_byte>(**src);
00098 (*src)++;
00099 }
00100 }
00101
00102 result += T(part & 0x7f) << shift;
00103 shift += 7;
00104
00105 if ((part & 0x80) == 0) {
00106 if (resultptr) *resultptr = result;
00107 return true;
00108 }
00109 }
00110 }
00111
00112
00119 template<class T>
00120 string
00121 F_pack_uint(T value)
00122 {
00123
00124 STATIC_ASSERT_UNSIGNED_TYPE(T);
00125
00126 if (value == 0) return string(1, '\0');
00127 string result;
00128
00129 while (value != 0) {
00130 om_byte part = static_cast<om_byte>(value & 0x7f);
00131 value = value >> 7;
00132 if (value) part |= 0x80;
00133 result.append(1u, char(part));
00134 }
00135
00136 return result;
00137 }
00138
00147 template<>
00148 inline string
00149 F_pack_uint<bool>(bool value)
00150 {
00151 return string(1, static_cast<char>(value));
00152 }
00153
00171 template<class T>
00172 bool
00173 F_unpack_uint_last(const char ** src, const char * src_end, T * resultptr)
00174 {
00175
00176 STATIC_ASSERT_UNSIGNED_TYPE(T);
00177
00178 STATIC_ASSERT(sizeof(om_byte) == 1);
00179
00180 if (src_end - *src > int(sizeof(T))) {
00181
00182 *src = src_end;
00183 return false;
00184 }
00185
00186 T result = 0;
00187 int shift = 0;
00188 while (*src != src_end) {
00189 result |= static_cast<T>(static_cast<om_byte>(**src)) << shift;
00190 ++(*src);
00191 shift += 8;
00192 }
00193 *resultptr = result;
00194 return true;
00195 }
00196
00206 template<class T>
00207 string
00208 F_pack_uint_last(T value)
00209 {
00210
00211 STATIC_ASSERT_UNSIGNED_TYPE(T);
00212
00213 string result;
00214 while (value) {
00215 result += char(value);
00216 value >>= 8;
00217 }
00218 return result;
00219 }
00220
00231 template<class T>
00232 string
00233 F_pack_uint_preserving_sort(T value)
00234 {
00235
00236 STATIC_ASSERT_UNSIGNED_TYPE(T);
00237
00238 string result;
00239 while (value != 0) {
00240 om_byte part = static_cast<om_byte>(value & 0xff);
00241 value = value >> 8;
00242 result.insert(string::size_type(0), 1u, char(part));
00243 }
00244 result.insert(string::size_type(0), 1u, char(result.size()));
00245 return result;
00246 }
00247
00267 template<class T>
00268 bool
00269 F_unpack_uint_preserving_sort(const char ** src,
00270 const char * src_end,
00271 T * resultptr)
00272 {
00273 if (*src == src_end) {
00274 *src = 0;
00275 return false;
00276 }
00277
00278 unsigned int length = static_cast<om_byte>(**src);
00279 (*src)++;
00280
00281 if (length > sizeof(T)) {
00282 *src += length;
00283 if (*src > src_end) {
00284 *src = 0;
00285 }
00286 return false;
00287 }
00288
00289
00290 T result = 0;
00291 while (length > 0) {
00292 result = result << 8;
00293 result += static_cast<om_byte>(**src);
00294 (*src)++;
00295 length--;
00296 }
00297 *resultptr = result;
00298
00299 return true;
00300 }
00301
00302 inline bool
00303 F_unpack_string(const char ** src,
00304 const char * src_end,
00305 string & result)
00306 {
00307 string::size_type length;
00308 if (!F_unpack_uint(src, src_end, &length)) {
00309 return false;
00310 }
00311
00312 if (src_end - *src < 0 ||
00313 string::size_type(src_end - *src) < length) {
00314 src = 0;
00315 return false;
00316 }
00317
00318 result.assign(*src, length);
00319 *src += length;
00320 return true;
00321 }
00322
00323 inline string
00324 F_pack_string(const string & value)
00325 {
00326 return F_pack_uint(value.size()) + value;
00327 }
00328
00334 inline string
00335 F_pack_string_preserving_sort(string value)
00336 {
00337 string::size_type i = 0, j;
00338 while ((j = value.find('\0', i)) != string::npos) {
00339 value.replace(j, 1, "\0\xff", 2);
00340 i = j + 2;
00341 }
00342 value += '\0';
00343 return value + '\0';
00344 }
00345
00346 inline bool
00347 F_unpack_string_preserving_sort(const char ** src,
00348 const char * src_end,
00349 string & result)
00350 {
00351 result.resize(0);
00352 while (*src < src_end) {
00353 const char *begin = *src;
00354 while (**src) {
00355 ++(*src);
00356 if (*src == src_end) return false;
00357 }
00358 result += string(begin, *src - begin);
00359 ++(*src);
00360 if (*src == src_end) return false;
00361 if (**src != '\xff') {
00362 ++(*src);
00363 return true;
00364 }
00365 result += '\0';
00366 ++(*src);
00367 }
00368 return false;
00369 }
00370
00371 inline bool
00372 F_unpack_bool(const char ** src,
00373 const char * src_end,
00374 bool * resultptr)
00375 {
00376 if (*src == src_end) {
00377 *src = 0;
00378 return false;
00379 }
00380 switch (*((*src)++)) {
00381 case '0':
00382 if (resultptr) *resultptr = false;
00383 return true;
00384 case '1':
00385 if (resultptr) *resultptr = true;
00386 return true;
00387 }
00388 *src = 0;
00389 return false;
00390 }
00391
00392 inline string
00393 F_pack_bool(bool value)
00394 {
00395 return value ? "1" : "0";
00396 }
00397
00401 inline string
00402 flint_docid_to_key(Xapian::docid did)
00403 {
00404 return F_pack_uint_preserving_sort(did);
00405 }
00406
00407 #endif