[honey] Fix portability to systems without pread()
[xapian.git] / xapian-core / net / length.cc
blobf03066ecf931e5f808b13b88e1ee355a44fabc99
1 /** @file length.cc
2 * @brief length encoded as a string
3 */
4 /* Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2015 Olly Betts
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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.
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 USA
21 #include <config.h>
23 #include "length.h"
25 #ifndef XAPIAN_UNITTEST
27 #include "xapian/error.h"
29 [[noreturn]]
30 static void
31 throw_network_error(const char * msg)
33 throw Xapian::NetworkError(msg);
36 #else
38 class Xapian_NetworkError {
39 const char * msg;
41 public:
42 explicit Xapian_NetworkError(const char * msg_) : msg(msg_) { }
44 const char * get_description() const { return msg; }
47 [[noreturn]]
48 static void
49 throw_network_error(const char * msg)
51 throw Xapian_NetworkError(msg);
54 #endif
56 template<typename T>
57 inline void
58 decode_length_(const char ** p, const char *end, T & out)
60 if (*p == end) {
61 throw_network_error("Bad encoded length: no data");
64 T len = static_cast<unsigned char>(*(*p)++);
65 if (len == 0xff) {
66 len = 0;
67 unsigned char ch;
68 unsigned shift = 0;
69 do {
70 if (*p == end || shift > (sizeof(T) * 8 / 7 * 7))
71 throw_network_error("Bad encoded length: insufficient data");
72 ch = *(*p)++;
73 len |= T(ch & 0x7f) << shift;
74 shift += 7;
75 } while ((ch & 0x80) == 0);
76 len += 255;
78 out = len;
81 template<typename T>
82 inline void
83 decode_length_and_check_(const char ** p, const char *end, T & out)
85 decode_length(p, end, out);
86 if (out > T(end - *p)) {
87 throw_network_error("Bad encoded length: length greater than data");
91 void
92 decode_length(const char ** p, const char *end, unsigned & out)
94 decode_length_(p, end, out);
97 void
98 decode_length(const char ** p, const char *end, unsigned long & out)
100 decode_length_(p, end, out);
103 void
104 decode_length(const char ** p, const char *end, unsigned long long & out)
106 decode_length_(p, end, out);
109 void
110 decode_length_and_check(const char ** p, const char *end, unsigned & out)
112 decode_length_and_check_(p, end, out);
115 void
116 decode_length_and_check(const char ** p, const char *end, unsigned long & out)
118 decode_length_and_check_(p, end, out);
121 void
122 decode_length_and_check(const char ** p, const char *end,
123 unsigned long long & out)
125 decode_length_and_check_(p, end, out);