21 #ifndef XAPIAN_INCLUDED_PACK_H
22 #define XAPIAN_INCLUDED_PACK_H
25 # error config.h must be included first in each C++ source file
29 #include <string_view>
30 #include <type_traits>
66 s += char(
'0' |
static_cast<char>(value));
79 const char*& ptr = *
p;
82 if (
rare(ptr == end || ((ch = *ptr++ -
'0') &~ 1))) {
86 *result =
static_cast<bool>(ch);
102 static_assert(std::is_unsigned_v<U>,
"Unsigned type required");
105 s += char(value & 0xff);
120 static_assert(std::is_unsigned_v<U>,
"Unsigned type required");
123 const char* ptr = *
p;
128 if (
rare(end - ptr >
int(
sizeof(U)))) {
134 *result = (*result << 8) | U(static_cast<unsigned char>(*--end));
140 #if HAVE_DECL___BUILTIN_CLZ && \
141 HAVE_DECL___BUILTIN_CLZL && \
142 HAVE_DECL___BUILTIN_CLZLL
146 extern int no_clz_builtin_for_this_type(T);
147 return no_clz_builtin_for_this_type(value);
152 do_clz(
unsigned value) {
153 return __builtin_clz(value);
158 do_clz(
unsigned long value) {
159 return __builtin_clzl(value);
164 do_clz(
unsigned long long value) {
165 return __builtin_clzll(value);
206 static_assert(std::is_unsigned_v<U>,
"Unsigned type required");
207 static_assert(
sizeof(U) <= 8,
208 "Template type U too wide for database format");
211 if (value < 0x8000) {
212 s.resize(s.size() + 2);
213 s[s.size() - 2] =
static_cast<unsigned char>(value >> 8);
214 Assert(s[s.size() - 2] !=
'\xff');
215 s[s.size() - 1] =
static_cast<unsigned char>(value);
220 size_t len = ((
sizeof(U) * 8 + 5) - do_clz(value)) / 7;
223 for (
auto x = value >> 22; x; x >>= 7) ++len;
225 unsigned mask = 0xff << (10 - len);
227 s.resize(s.size() + len);
228 for (
size_t i = 1; i != len; ++i) {
229 s[s.size() - i] =
static_cast<unsigned char>(value);
233 s[s.size() - len] =
static_cast<unsigned char>(value | mask);
234 Assert(s[s.size() - len] !=
'\xff');
253 static_assert(std::is_unsigned_v<U>,
"Unsigned type required");
254 static_assert(
sizeof(U) <= 8,
255 "Template type U too wide for database format");
258 const char* ptr = *
p;
261 if (
rare(ptr == end)) {
265 unsigned char len_byte =
static_cast<unsigned char>(*ptr++);
266 if (len_byte < 0x80) {
267 *result = (U(len_byte) << 8) |
static_cast<unsigned char>(*ptr++);
272 if (len_byte == 0xff) {
278 size_t len = do_clz(len_byte ^ 0xffu) + 9 -
sizeof(unsigned) * 8;
281 for (
unsigned char m = 0x40; len_byte & m; m >>= 1) ++len;
283 if (
rare(
size_t(end - ptr) < len)) {
286 unsigned mask = 0xff << (9 - len);
290 if (
rare(len >
int(
sizeof(U))))
return false;
291 if constexpr(
sizeof(U) != 8) {
293 if (
rare(len ==
int(
sizeof(U)) && len_byte != 0))
return false;
301 r = (r << 8) | U(static_cast<unsigned char>(*ptr++));
317 static_assert(std::is_unsigned_v<U>,
"Unsigned type required");
319 while (value >= 128) {
320 s +=
static_cast<char>(
static_cast<unsigned char>(value) | 0x80);
323 s +=
static_cast<char>(value);
335 s +=
static_cast<char>(value);
348 static_assert(std::is_unsigned_v<U>,
"Unsigned type required");
350 const char* ptr = *
p;
352 const char* start = ptr;
356 if (
rare(ptr == end)) {
361 }
while (
static_cast<unsigned char>(*ptr++) >= 128);
365 if (!result)
return true;
373 size_t maxbits = size_t(ptr - start) * 7;
374 if (maxbits <=
sizeof(U) * 8) {
377 unsigned char chunk =
static_cast<unsigned char>(*--ptr) & 0x7f;
378 *result = (*result << 7) | U(chunk);
379 }
while (ptr != start);
383 size_t minbits = maxbits - 6;
384 if (
rare(minbits >
sizeof(U) * 8)) {
389 while (--ptr != start) {
390 unsigned char chunk =
static_cast<unsigned char>(*--ptr) & 0x7f;
391 *result = (*result << 7) | U(chunk);
396 if (
rare(*result < tmp)) {
400 *result |= U(
static_cast<unsigned char>(*ptr) & 0x7f);
414 static_assert(std::is_unsigned_v<U>,
"Unsigned type required");
416 const char* ptr = *
p;
420 if (
rare(ptr == start ||
static_cast<unsigned char>(ptr[-1]) >= 128)) {
427 if (
rare(--ptr == start))
429 }
while (
static_cast<unsigned char>(ptr[-1]) >= 128);
431 const char* end = *
p;
475 const char*& ptr = *
p;
476 if (
rare(len >
size_t(end - ptr))) {
481 result.assign(ptr, len);
500 const char*& ptr = *
p;
501 if (
rare(len >
size_t(end - ptr))) {
506 result.append(ptr, len);
531 std::string::size_type b = 0, e;
532 while ((e = value.find(
'\0', b)) != std::string::npos) {
534 s.append(value, b, e - b);
538 s.append(value, b, std::string::npos);
539 if (!last) s +=
'\0';
556 const char* ptr = *
p;
561 if (
rare(ch ==
'\0')) {
562 if (
usual(ptr == end || *ptr !=
'\xff')) {
578 return std::string(
"\x00\xe0", 2);
590 std::string key(
"\x00\xe0", 2);
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Various assertion macros.
#define AssertRel(A, REL, B)
void unpack_throw_serialisation_error(const char *p)
Throw appropriate SerialisationError.
bool unpack_uint_backwards(const char **p, const char *start, U *result)
Decode an unsigned integer from a string, going backwards.
const unsigned int SORTABLE_UINT_LOG2_MAX_BYTES
How many bits to store the length of a sortable uint in.
std::string pack_honey_postlist_key(std::string_view term)
const unsigned int SORTABLE_UINT_1ST_BYTE_MASK
Calculated value used below.
bool unpack_uint_last(const char **p, const char *end, U *result)
Decode an unsigned integer as the last item in a string.
bool unpack_string_preserving_sort(const char **p, const char *end, std::string &result)
Decode a "sort preserved" std::string from a string.
bool unpack_string(const char **p, const char *end, std::string &result)
Decode a std::string from a string.
const unsigned int SORTABLE_UINT_MAX_BYTES
Calculated value used below.
bool unpack_string_append(const char **p, const char *end, std::string &result)
Decode a std::string from a string and append.
void pack_uint_last(std::string &s, U value)
Append an encoded unsigned integer to a string as the last item.
bool unpack_bool(const char **p, const char *end, bool *result)
Decode a bool from a string.
void pack_bool(std::string &s, bool value)
Append an encoded bool to a string.
bool unpack_uint(const char **p, const char *end, U *result)
Decode an unsigned integer from a string.
void pack_string_preserving_sort(std::string &s, std::string_view value, bool last=false)
Append an encoded std::string to a string, preserving the sort order.
void pack_uint(std::string &s, U value)
Append an encoded unsigned integer to a string.
void pack_string(std::string &s, std::string_view value)
Append an encoded std::string to a string.
bool unpack_uint_preserving_sort(const char **p, const char *end, U *result)
Decode a "sort preserved" unsigned integer from a string.
void pack_string_empty(std::string &s)
Append an empty encoded std::string to a string.
std::string pack_glass_postlist_key(std::string_view term)
void pack_uint_preserving_sort(std::string &s, U value)
Append an encoded unsigned integer to a string, preserving the sort order.