xapian-core  2.0.0
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 #if HAVE_DECL__BYTESWAP_USHORT || HAVE_DECL__BYTESWAP_ULONG
40 # include <stdlib.h>
41 #endif
42 
43 inline uint16_t do_bswap(uint16_t value) {
44 # if HAVE_DECL___BUILTIN_BSWAP16
45  return __builtin_bswap16(value);
46 # elif HAVE_DECL__BYTESWAP_USHORT
47  return _byteswap_ushort(value);
48 # else
49  return (value << 8) | (value >> 8);
50 # endif
51 }
52 
53 inline uint32_t do_bswap(uint32_t value) {
54 # if HAVE_DECL___BUILTIN_BSWAP32
55  return __builtin_bswap32(value);
56 # elif HAVE_DECL__BYTESWAP_ULONG
57  return _byteswap_ulong(value);
58 # else
59  return (value << 24) |
60  ((value & 0xff00) << 8) |
61  ((value >> 8) & 0xff00) |
62  (value >> 24);
63 # endif
64 }
65 
66 inline uint64_t do_bswap(uint64_t value) {
67 # if HAVE_DECL___BUILTIN_BSWAP64
68  return __builtin_bswap64(value);
69 # elif HAVE_DECL__BYTESWAP_UINT64
70  return _byteswap_uint64(value);
71 # else
72  return (value << 56) |
73  ((value & 0xff00) << 40) |
74  ((value & 0xff0000) << 24) |
75  ((value & 0xff000000) << 8) |
76  ((value >> 8) & 0xff000000) |
77  ((value >> 24) & 0xff0000) |
78  ((value >> 40) & 0xff00) |
79  (value >> 56);
80 # endif
81 }
82 
83 template<typename UINT>
84 inline UINT
85 do_aligned_read(const unsigned char * ptr)
86 {
87  UINT value = *alignment_cast<const UINT*>(ptr);
88 #ifndef WORDS_BIGENDIAN
89  value = do_bswap(value);
90 #endif
91  return value;
92 }
93 
94 template<typename T, typename UINT>
95 inline void
96 do_aligned_write(unsigned char * ptr, T value)
97 {
98  if (std::is_signed_v<T>) {
99  AssertRel(value, >=, 0);
100  }
101  if constexpr(sizeof(T) > sizeof(UINT)) {
102  AssertEq(value, T(UINT(value)));
103  }
104  UINT v = UINT(value);
105 #ifndef WORDS_BIGENDIAN
106  v = do_bswap(v);
107 #endif
108  *alignment_cast<UINT*>(ptr) = v;
109 }
110 
111 template<typename UINT>
112 inline UINT
113 do_unaligned_read(const unsigned char * ptr)
114 {
115  UINT value;
116  memcpy(&value, ptr, sizeof(UINT));
117 #ifndef WORDS_BIGENDIAN
118  value = do_bswap(value);
119 #endif
120  return value;
121 }
122 
123 template<typename T, typename UINT>
124 inline void
125 do_unaligned_write(unsigned char * ptr, T value)
126 {
127  if (std::is_signed_v<T>) {
128  AssertRel(value, >=, 0);
129  }
130  if constexpr(sizeof(T) > sizeof(UINT)) {
131  AssertEq(value, T(UINT(value)));
132  }
133  UINT v = UINT(value);
134 #ifndef WORDS_BIGENDIAN
135  v = do_bswap(v);
136 #endif
137  memcpy(ptr, &v, sizeof(UINT));
138 }
139 
140 inline uint32_t
141 aligned_read4(const unsigned char *ptr)
142 {
143  return do_aligned_read<uint32_t>(ptr);
144 }
145 
146 inline uint32_t
147 unaligned_read4(const unsigned char *ptr)
148 {
149  return do_unaligned_read<uint32_t>(ptr);
150 }
151 
152 inline uint16_t
153 aligned_read2(const unsigned char *ptr)
154 {
155  return do_aligned_read<uint16_t>(ptr);
156 }
157 
158 inline uint16_t
159 unaligned_read2(const unsigned char *ptr)
160 {
161  return do_unaligned_read<uint16_t>(ptr);
162 }
163 
164 template<typename T>
165 inline void
166 aligned_write4(unsigned char *ptr, T value)
167 {
168  do_aligned_write<T, uint32_t>(ptr, value);
169 }
170 
171 template<typename T>
172 inline void
173 unaligned_write4(unsigned char *ptr, T value)
174 {
175  do_unaligned_write<T, uint32_t>(ptr, value);
176 }
177 
178 template<typename T>
179 inline void
180 aligned_write2(unsigned char *ptr, T value)
181 {
182  do_aligned_write<T, uint16_t>(ptr, value);
183 }
184 
185 template<typename T>
186 inline void
187 unaligned_write2(unsigned char *ptr, T value)
188 {
189  do_unaligned_write<T, uint16_t>(ptr, value);
190 }
191 
192 #endif // XAPIAN_INCLUDED_WORDACCESS_H
Cast a pointer we know is suitably aligned.
Various assertion macros.
#define AssertEq(A, B)
Definition: omassert.h:124
#define AssertRel(A, REL, B)
Definition: omassert.h:123
void aligned_write2(unsigned char *ptr, T value)
Definition: wordaccess.h:180
void aligned_write4(unsigned char *ptr, T value)
Definition: wordaccess.h:166
uint32_t unaligned_read4(const unsigned char *ptr)
Definition: wordaccess.h:147
UINT do_unaligned_read(const unsigned char *ptr)
Definition: wordaccess.h:113
void unaligned_write2(unsigned char *ptr, T value)
Definition: wordaccess.h:187
UINT do_aligned_read(const unsigned char *ptr)
Definition: wordaccess.h:85
uint16_t unaligned_read2(const unsigned char *ptr)
Definition: wordaccess.h:159
void do_aligned_write(unsigned char *ptr, T value)
Definition: wordaccess.h:96
void do_unaligned_write(unsigned char *ptr, T value)
Definition: wordaccess.h:125
uint16_t aligned_read2(const unsigned char *ptr)
Definition: wordaccess.h:153
void unaligned_write4(unsigned char *ptr, T value)
Definition: wordaccess.h:173
uint32_t aligned_read4(const unsigned char *ptr)
Definition: wordaccess.h:141
uint16_t do_bswap(uint16_t value)
Definition: wordaccess.h:43