xapian-core  1.4.27
wordaccess.h
Go to the documentation of this file.
1 
4 /* Copyright (C) 2016,2018,2019 Olly Betts
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #ifndef XAPIAN_INCLUDED_WORDACCESS_H
26 #define XAPIAN_INCLUDED_WORDACCESS_H
27 
28 #ifndef PACKAGE
29 # error config.h must be included first in each C++ source file
30 #endif
31 
32 #include <cstdint>
33 #include <type_traits>
34 #include <cstring>
35 
36 #include "alignment_cast.h"
37 #include "omassert.h"
38 
39 #ifndef WORDS_BIGENDIAN
40 
41 #if HAVE_DECL__BYTESWAP_USHORT || HAVE_DECL__BYTESWAP_ULONG
42 # include <stdlib.h>
43 #endif
44 
45 inline uint16_t do_bswap(uint16_t value) {
46 # if HAVE_DECL___BUILTIN_BSWAP16
47  return __builtin_bswap16(value);
48 # elif HAVE_DECL__BYTESWAP_USHORT
49  return _byteswap_ushort(value);
50 # else
51  return (value << 8) | (value >> 8);
52 # endif
53 }
54 
55 inline uint32_t do_bswap(uint32_t value) {
56 # if HAVE_DECL___BUILTIN_BSWAP32
57  return __builtin_bswap32(value);
58 # elif HAVE_DECL__BYTESWAP_ULONG
59  return _byteswap_ulong(value);
60 # else
61  return (value << 24) |
62  ((value & 0xff00) << 8) |
63  ((value >> 8) & 0xff00) |
64  (value >> 24);
65 # endif
66 }
67 
68 inline uint64_t do_bswap(uint64_t value) {
69 # if HAVE_DECL___BUILTIN_BSWAP64
70  return __builtin_bswap64(value);
71 # elif HAVE_DECL__BYTESWAP_UINT64
72  return _byteswap_uint64(value);
73 # else
74  return (value << 56) |
75  ((value & 0xff00) << 40) |
76  ((value & 0xff0000) << 24) |
77  ((value & 0xff000000) << 8) |
78  ((value >> 8) & 0xff000000) |
79  ((value >> 24) & 0xff0000) |
80  ((value >> 40) & 0xff00) |
81  (value >> 56);
82 # endif
83 }
84 
85 #endif
86 
87 template<typename UINT>
88 inline UINT
89 do_aligned_read(const unsigned char * ptr)
90 {
91  UINT value = *alignment_cast<const UINT*>(ptr);
92 #ifndef WORDS_BIGENDIAN
93  value = do_bswap(value);
94 #endif
95  return value;
96 }
97 
98 template<typename T, typename UINT>
99 inline void
100 do_aligned_write(unsigned char * ptr, T value)
101 {
102  if (std::is_signed<T>::value) {
103  AssertRel(value, >=, 0);
104  }
105  if (sizeof(T) > sizeof(UINT)) {
106  AssertEq(value, T(UINT(value)));
107  }
108  UINT v = UINT(value);
109 #ifndef WORDS_BIGENDIAN
110  v = do_bswap(v);
111 #endif
112  *alignment_cast<UINT*>(ptr) = v;
113 }
114 
115 template<typename UINT>
116 inline UINT
117 do_unaligned_read(const unsigned char * ptr)
118 {
119  UINT value;
120  memcpy(&value, ptr, sizeof(UINT));
121 #ifndef WORDS_BIGENDIAN
122  value = do_bswap(value);
123 #endif
124  return value;
125 }
126 
127 template<typename T, typename UINT>
128 inline void
129 do_unaligned_write(unsigned char * ptr, T value)
130 {
131  if (std::is_signed<T>::value) {
132  AssertRel(value, >=, 0);
133  }
134  if (sizeof(T) > sizeof(UINT)) {
135  AssertEq(value, T(UINT(value)));
136  }
137  UINT v = UINT(value);
138 #ifndef WORDS_BIGENDIAN
139  v = do_bswap(v);
140 #endif
141  memcpy(ptr, &v, sizeof(UINT));
142 }
143 
144 inline uint32_t
145 aligned_read4(const unsigned char *ptr)
146 {
147  return do_aligned_read<uint32_t>(ptr);
148 }
149 
150 inline uint32_t
151 unaligned_read4(const unsigned char *ptr)
152 {
153  return do_unaligned_read<uint32_t>(ptr);
154 }
155 
156 inline uint16_t
157 aligned_read2(const unsigned char *ptr)
158 {
159  return do_aligned_read<uint16_t>(ptr);
160 }
161 
162 inline uint16_t
163 unaligned_read2(const unsigned char *ptr)
164 {
165  return do_unaligned_read<uint16_t>(ptr);
166 }
167 
168 template<typename T>
169 inline void
170 aligned_write4(unsigned char *ptr, T value)
171 {
172  do_aligned_write<T, uint32_t>(ptr, value);
173 }
174 
175 template<typename T>
176 inline void
177 unaligned_write4(unsigned char *ptr, T value)
178 {
179  do_unaligned_write<T, uint32_t>(ptr, value);
180 }
181 
182 template<typename T>
183 inline void
184 aligned_write2(unsigned char *ptr, T value)
185 {
186  do_aligned_write<T, uint16_t>(ptr, value);
187 }
188 
189 template<typename T>
190 inline void
191 unaligned_write2(unsigned char *ptr, T value)
192 {
193  do_unaligned_write<T, uint16_t>(ptr, value);
194 }
195 
196 #endif // XAPIAN_INCLUDED_WORDACCESS_H
#define AssertEq(A, B)
Definition: omassert.h:124
#define AssertRel(A, REL, B)
Definition: omassert.h:123
void unaligned_write4(unsigned char *ptr, T value)
Definition: wordaccess.h:177
uint16_t unaligned_read2(const unsigned char *ptr)
Definition: wordaccess.h:163
Cast a pointer we know is suitably aligned.
std::enable_if< std::is_const< typename std::remove_pointer< U >::type >::value, T >::type alignment_cast(U ptr)
Cast a pointer we know is suitably aligned.
void aligned_write4(unsigned char *ptr, T value)
Definition: wordaccess.h:170
UINT do_unaligned_read(const unsigned char *ptr)
Definition: wordaccess.h:117
void do_aligned_write(unsigned char *ptr, T value)
Definition: wordaccess.h:100
UINT do_aligned_read(const unsigned char *ptr)
Definition: wordaccess.h:89
uint32_t aligned_read4(const unsigned char *ptr)
Definition: wordaccess.h:145
void aligned_write2(unsigned char *ptr, T value)
Definition: wordaccess.h:184
uint16_t aligned_read2(const unsigned char *ptr)
Definition: wordaccess.h:157
void unaligned_write2(unsigned char *ptr, T value)
Definition: wordaccess.h:191
void do_unaligned_write(unsigned char *ptr, T value)
Definition: wordaccess.h:129
uint16_t do_bswap(uint16_t value)
Definition: wordaccess.h:45
Various assertion macros.
uint32_t unaligned_read4(const unsigned char *ptr)
Definition: wordaccess.h:151