]>
Commit | Line | Data |
---|---|---|
064af421 | 1 | /* |
4e022ec0 | 2 | * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. |
064af421 | 3 | * |
a14bc59f BP |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
064af421 | 7 | * |
a14bc59f BP |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
064af421 BP |
15 | */ |
16 | ||
17 | #ifndef UTIL_H | |
18 | #define UTIL_H 1 | |
19 | ||
a656cb77 | 20 | #include <limits.h> |
064af421 BP |
21 | #include <stdarg.h> |
22 | #include <stdbool.h> | |
23 | #include <stddef.h> | |
24 | #include <stdint.h> | |
25 | #include <stdio.h> | |
ccc09689 | 26 | #include <stdlib.h> |
064af421 BP |
27 | #include <string.h> |
28 | #include "compiler.h" | |
4e022ec0 | 29 | #include "openvswitch/types.h" |
064af421 BP |
30 | |
31 | #ifndef va_copy | |
32 | #ifdef __va_copy | |
33 | #define va_copy __va_copy | |
34 | #else | |
35 | #define va_copy(dst, src) ((dst) = (src)) | |
36 | #endif | |
37 | #endif | |
38 | ||
0b9275b2 BP |
39 | #ifdef __CHECKER__ |
40 | #define BUILD_ASSERT(EXPR) ((void) 0) | |
41 | #define BUILD_ASSERT_DECL(EXPR) extern int (*build_assert(void))[1] | |
42 | #elif !defined(__cplusplus) | |
064af421 BP |
43 | /* Build-time assertion building block. */ |
44 | #define BUILD_ASSERT__(EXPR) \ | |
45 | sizeof(struct { unsigned int build_assert_failed : (EXPR) ? 1 : -1; }) | |
46 | ||
47 | /* Build-time assertion for use in a statement context. */ | |
48 | #define BUILD_ASSERT(EXPR) (void) BUILD_ASSERT__(EXPR) | |
49 | ||
50 | /* Build-time assertion for use in a declaration context. */ | |
51 | #define BUILD_ASSERT_DECL(EXPR) \ | |
52 | extern int (*build_assert(void))[BUILD_ASSERT__(EXPR)] | |
53 | #else /* __cplusplus */ | |
54 | #include <boost/static_assert.hpp> | |
55 | #define BUILD_ASSERT BOOST_STATIC_ASSERT | |
56 | #define BUILD_ASSERT_DECL BOOST_STATIC_ASSERT | |
57 | #endif /* __cplusplus */ | |
58 | ||
320232ec BP |
59 | #ifdef __GNUC__ |
60 | #define BUILD_ASSERT_GCCONLY(EXPR) BUILD_ASSERT(EXPR) | |
61 | #define BUILD_ASSERT_DECL_GCCONLY(EXPR) BUILD_ASSERT_DECL(EXPR) | |
62 | #else | |
63 | #define BUILD_ASSERT_GCCONLY(EXPR) ((void) 0) | |
64 | #define BUILD_ASSERT_DECL_GCCONLY(EXPR) ((void) 0) | |
65 | #endif | |
66 | ||
4749f73d BP |
67 | /* Like the standard assert macro, except: |
68 | * | |
69 | * - Writes the failure message to the log. | |
70 | * | |
71 | * - Not affected by NDEBUG. */ | |
72 | #define ovs_assert(CONDITION) \ | |
73 | if (!OVS_LIKELY(CONDITION)) { \ | |
74 | ovs_assert_failure(SOURCE_LOCATOR, __func__, #CONDITION); \ | |
75 | } | |
76 | void ovs_assert_failure(const char *, const char *, const char *) NO_RETURN; | |
77 | ||
ebc56baa BP |
78 | /* Casts 'pointer' to 'type' and issues a compiler warning if the cast changes |
79 | * anything other than an outermost "const" or "volatile" qualifier. | |
80 | * | |
81 | * The cast to int is present only to suppress an "expression using sizeof | |
82 | * bool" warning from "sparse" (see | |
83 | * http://permalink.gmane.org/gmane.comp.parsers.sparse/2967). */ | |
84 | #define CONST_CAST(TYPE, POINTER) \ | |
85 | ((void) sizeof ((int) ((POINTER) == (TYPE) (POINTER))), \ | |
86 | (TYPE) (POINTER)) | |
87 | ||
064af421 BP |
88 | extern const char *program_name; |
89 | ||
878f1972 FL |
90 | #define __ARRAY_SIZE_NOCHECK(ARRAY) (sizeof(ARRAY) / sizeof((ARRAY)[0])) |
91 | #ifdef __GNUC__ | |
92 | /* return 0 for array types, 1 otherwise */ | |
93 | #define __ARRAY_CHECK(ARRAY) \ | |
94 | !__builtin_types_compatible_p(typeof(ARRAY), typeof(&ARRAY[0])) | |
95 | ||
96 | /* compile-time fail if not array */ | |
97 | #define __ARRAY_FAIL(ARRAY) (sizeof(char[-2*!__ARRAY_CHECK(ARRAY)])) | |
98 | #define __ARRAY_SIZE(ARRAY) \ | |
99 | __builtin_choose_expr(__ARRAY_CHECK(ARRAY), \ | |
100 | __ARRAY_SIZE_NOCHECK(ARRAY), __ARRAY_FAIL(ARRAY)) | |
101 | #else | |
102 | #define __ARRAY_SIZE(ARRAY) __ARRAY_SIZE_NOCHECK(ARRAY) | |
103 | #endif | |
104 | ||
ba25c9d1 | 105 | /* Returns the number of elements in ARRAY. */ |
878f1972 | 106 | #define ARRAY_SIZE(ARRAY) __ARRAY_SIZE(ARRAY) |
ba25c9d1 BP |
107 | |
108 | /* Returns X / Y, rounding up. X must be nonnegative to round correctly. */ | |
bbb18ba7 | 109 | #define DIV_ROUND_UP(X, Y) (((X) + ((Y) - 1)) / (Y)) |
ba25c9d1 BP |
110 | |
111 | /* Returns X rounded up to the nearest multiple of Y. */ | |
bbb18ba7 | 112 | #define ROUND_UP(X, Y) (DIV_ROUND_UP(X, Y) * (Y)) |
ba25c9d1 BP |
113 | |
114 | /* Returns X rounded down to the nearest multiple of Y. */ | |
064af421 | 115 | #define ROUND_DOWN(X, Y) ((X) / (Y) * (Y)) |
ba25c9d1 BP |
116 | |
117 | /* Returns true if X is a power of 2, otherwise false. */ | |
064af421 BP |
118 | #define IS_POW2(X) ((X) && !((X) & ((X) - 1))) |
119 | ||
27527aa0 BP |
120 | static inline bool |
121 | is_pow2(uintmax_t x) | |
122 | { | |
123 | return IS_POW2(x); | |
124 | } | |
125 | ||
e93ab553 BP |
126 | /* Returns X rounded up to a power of 2. X must be a constant expression. */ |
127 | #define ROUND_UP_POW2(X) RUP2__(X) | |
128 | #define RUP2__(X) (RUP2_1(X) + 1) | |
129 | #define RUP2_1(X) (RUP2_2(X) | (RUP2_2(X) >> 16)) | |
130 | #define RUP2_2(X) (RUP2_3(X) | (RUP2_3(X) >> 8)) | |
131 | #define RUP2_3(X) (RUP2_4(X) | (RUP2_4(X) >> 4)) | |
132 | #define RUP2_4(X) (RUP2_5(X) | (RUP2_5(X) >> 2)) | |
133 | #define RUP2_5(X) (RUP2_6(X) | (RUP2_6(X) >> 1)) | |
134 | #define RUP2_6(X) ((X) - 1) | |
135 | ||
136 | /* Returns X rounded down to a power of 2. X must be a constant expression. */ | |
137 | #define ROUND_DOWN_POW2(X) RDP2__(X) | |
138 | #define RDP2__(X) (RDP2_1(X) - (RDP2_1(X) >> 1)) | |
139 | #define RDP2_1(X) (RDP2_2(X) | (RDP2_2(X) >> 16)) | |
140 | #define RDP2_2(X) (RDP2_3(X) | (RDP2_3(X) >> 8)) | |
141 | #define RDP2_3(X) (RDP2_4(X) | (RDP2_4(X) >> 4)) | |
142 | #define RDP2_4(X) (RDP2_5(X) | (RDP2_5(X) >> 2)) | |
143 | #define RDP2_5(X) ( (X) | ( (X) >> 1)) | |
144 | ||
064af421 BP |
145 | #ifndef MIN |
146 | #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) | |
147 | #endif | |
148 | ||
149 | #ifndef MAX | |
150 | #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) | |
151 | #endif | |
152 | ||
153 | #define NOT_REACHED() abort() | |
064af421 | 154 | |
f89ffb0e BP |
155 | /* Expands to a string that looks like "<file>:<line>", e.g. "tmp.c:10". |
156 | * | |
157 | * See http://c-faq.com/ansi/stringize.html for an explanation of STRINGIZE and | |
158 | * STRINGIZE2. */ | |
159 | #define SOURCE_LOCATOR __FILE__ ":" STRINGIZE(__LINE__) | |
160 | #define STRINGIZE(ARG) STRINGIZE2(ARG) | |
161 | #define STRINGIZE2(ARG) #ARG | |
162 | ||
17e42975 BP |
163 | /* Given a pointer-typed lvalue OBJECT, expands to a pointer type that may be |
164 | * assigned to OBJECT. */ | |
165 | #ifdef __GNUC__ | |
166 | #define OVS_TYPEOF(OBJECT) typeof(OBJECT) | |
167 | #else | |
168 | #define OVS_TYPEOF(OBJECT) void * | |
169 | #endif | |
170 | ||
4e6ca956 BP |
171 | /* Given OBJECT of type pointer-to-structure, expands to the offset of MEMBER |
172 | * within an instance of the structure. | |
173 | * | |
174 | * The GCC-specific version avoids the technicality of undefined behavior if | |
175 | * OBJECT is null, invalid, or not yet initialized. This makes some static | |
176 | * checkers (like Coverity) happier. But the non-GCC version does not actually | |
177 | * dereference any pointer, so it would be surprising for it to cause any | |
178 | * problems in practice. | |
179 | */ | |
180 | #ifdef __GNUC__ | |
181 | #define OBJECT_OFFSETOF(OBJECT, MEMBER) offsetof(typeof(*(OBJECT)), MEMBER) | |
182 | #else | |
183 | #define OBJECT_OFFSETOF(OBJECT, MEMBER) \ | |
184 | ((char *) &(OBJECT)->MEMBER - (char *) (OBJECT)) | |
185 | #endif | |
186 | ||
064af421 BP |
187 | /* Given POINTER, the address of the given MEMBER in a STRUCT object, returns |
188 | the STRUCT object. */ | |
189 | #define CONTAINER_OF(POINTER, STRUCT, MEMBER) \ | |
26adc8dd | 190 | ((STRUCT *) (void *) ((char *) (POINTER) - offsetof (STRUCT, MEMBER))) |
064af421 | 191 | |
adf7cfd8 | 192 | /* Given POINTER, the address of the given MEMBER within an object of the type |
17e42975 BP |
193 | * that that OBJECT points to, returns OBJECT as an assignment-compatible |
194 | * pointer type (either the correct pointer type or "void *"). OBJECT must be | |
195 | * an lvalue. | |
adf7cfd8 BP |
196 | * |
197 | * This is the same as CONTAINER_OF except that it infers the structure type | |
198 | * from the type of '*OBJECT'. */ | |
199 | #define OBJECT_CONTAINING(POINTER, OBJECT, MEMBER) \ | |
17e42975 | 200 | ((OVS_TYPEOF(OBJECT)) (void *) \ |
4e6ca956 | 201 | ((char *) (POINTER) - OBJECT_OFFSETOF(OBJECT, MEMBER))) |
adf7cfd8 | 202 | |
772ec52b BP |
203 | /* Given POINTER, the address of the given MEMBER within an object of the type |
204 | * that that OBJECT points to, assigns the address of the outer object to | |
205 | * OBJECT, which must be an lvalue. | |
206 | * | |
33e191a0 | 207 | * Evaluates to (void) 0 as the result is not to be used. */ |
772ec52b | 208 | #define ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER) \ |
33e191a0 | 209 | ((OBJECT) = OBJECT_CONTAINING(POINTER, OBJECT, MEMBER), (void) 0) |
772ec52b | 210 | |
db5a1019 AW |
211 | /* Given ATTR, and TYPE, cast the ATTR to TYPE by first casting ATTR to |
212 | * (void *). This is to suppress the alignment warning issued by clang. */ | |
213 | #define ALIGNED_CAST(TYPE, ATTR) ((TYPE) (void *) (ATTR)) | |
214 | ||
34582733 AS |
215 | /* Use "%"PRIuSIZE to format size_t with printf(). */ |
216 | #ifdef _WIN32 | |
217 | #define PRIdSIZE "Id" | |
218 | #define PRIiSIZE "Ii" | |
219 | #define PRIoSIZE "Io" | |
220 | #define PRIuSIZE "Iu" | |
221 | #define PRIxSIZE "Ix" | |
222 | #define PRIXSIZE "IX" | |
223 | #else | |
224 | #define PRIdSIZE "zd" | |
225 | #define PRIiSIZE "zi" | |
226 | #define PRIoSIZE "zo" | |
227 | #define PRIuSIZE "zu" | |
228 | #define PRIxSIZE "zx" | |
229 | #define PRIXSIZE "zX" | |
230 | #endif | |
231 | ||
064af421 BP |
232 | #ifdef __cplusplus |
233 | extern "C" { | |
234 | #endif | |
235 | ||
e385ef55 EJ |
236 | void set_program_name__(const char *name, const char *version, |
237 | const char *date, const char *time); | |
55d5bb44 | 238 | #define set_program_name(name) \ |
e385ef55 | 239 | set_program_name__(name, VERSION, __DATE__, __TIME__) |
064af421 | 240 | |
bc9fb3a9 | 241 | const char *get_subprogram_name(void); |
d710edc4 | 242 | void set_subprogram_name(const char *format, ...) PRINTF_FORMAT(1, 2); |
bc9fb3a9 | 243 | |
55d5bb44 JP |
244 | const char *get_program_version(void); |
245 | void ovs_print_version(uint8_t min_ofp, uint8_t max_ofp); | |
064af421 BP |
246 | |
247 | void out_of_memory(void) NO_RETURN; | |
248 | void *xmalloc(size_t) MALLOC_LIKE; | |
249 | void *xcalloc(size_t, size_t) MALLOC_LIKE; | |
ec6fde61 | 250 | void *xzalloc(size_t) MALLOC_LIKE; |
064af421 BP |
251 | void *xrealloc(void *, size_t); |
252 | void *xmemdup(const void *, size_t) MALLOC_LIKE; | |
253 | char *xmemdup0(const char *, size_t) MALLOC_LIKE; | |
254 | char *xstrdup(const char *) MALLOC_LIKE; | |
255 | char *xasprintf(const char *format, ...) PRINTF_FORMAT(1, 2) MALLOC_LIKE; | |
256 | char *xvasprintf(const char *format, va_list) PRINTF_FORMAT(1, 0) MALLOC_LIKE; | |
257 | void *x2nrealloc(void *p, size_t *n, size_t s); | |
258 | ||
259 | void ovs_strlcpy(char *dst, const char *src, size_t size); | |
71d7c22f | 260 | void ovs_strzcpy(char *dst, const char *src, size_t size); |
064af421 | 261 | |
c1c8308a BP |
262 | void ovs_abort(int err_no, const char *format, ...) |
263 | PRINTF_FORMAT(2, 3) NO_RETURN; | |
d41d4b71 BP |
264 | void ovs_abort_valist(int err_no, const char *format, va_list) |
265 | PRINTF_FORMAT(2, 0) NO_RETURN; | |
064af421 BP |
266 | void ovs_fatal(int err_no, const char *format, ...) |
267 | PRINTF_FORMAT(2, 3) NO_RETURN; | |
fcaddd4d BP |
268 | void ovs_fatal_valist(int err_no, const char *format, va_list) |
269 | PRINTF_FORMAT(2, 0) NO_RETURN; | |
064af421 | 270 | void ovs_error(int err_no, const char *format, ...) PRINTF_FORMAT(2, 3); |
c1c8308a BP |
271 | void ovs_error_valist(int err_no, const char *format, va_list) |
272 | PRINTF_FORMAT(2, 0); | |
c18ea70d | 273 | const char *ovs_retval_to_string(int); |
5fcbed74 | 274 | const char *ovs_strerror(int); |
064af421 BP |
275 | void ovs_hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii); |
276 | ||
277 | bool str_to_int(const char *, int base, int *); | |
278 | bool str_to_long(const char *, int base, long *); | |
279 | bool str_to_llong(const char *, int base, long long *); | |
280 | bool str_to_uint(const char *, int base, unsigned int *); | |
281 | bool str_to_ulong(const char *, int base, unsigned long *); | |
282 | bool str_to_ullong(const char *, int base, unsigned long long *); | |
283 | ||
ed2232fc BP |
284 | bool ovs_scan(const char *s, const char *template, ...) SCANF_FORMAT(2, 3); |
285 | ||
f38b84ea BP |
286 | bool str_to_double(const char *, double *); |
287 | ||
288 | int hexit_value(int c); | |
bf971267 | 289 | unsigned int hexits_value(const char *s, size_t n, bool *ok); |
f38b84ea | 290 | |
44b4d050 BP |
291 | const char *english_list_delimiter(size_t index, size_t total); |
292 | ||
daf03c53 | 293 | char *get_cwd(void); |
29d4af60 | 294 | char *dir_name(const char *file_name); |
e1aff6f9 | 295 | char *base_name(const char *file_name); |
daf03c53 | 296 | char *abs_file_name(const char *dir, const char *file_name); |
29d4af60 | 297 | |
fee0c963 BP |
298 | char *xreadlink(const char *filename); |
299 | char *follow_symlinks(const char *filename); | |
300 | ||
c69ee87c | 301 | void ignore(bool x OVS_UNUSED); |
fe9d0898 BP |
302 | \f |
303 | /* Bitwise tests. */ | |
0ee140fb | 304 | |
d43d314e BP |
305 | /* Returns the number of trailing 0-bits in 'n'. Undefined if 'n' == 0. */ |
306 | #if __GNUC__ >= 4 | |
0ee140fb | 307 | static inline int |
d43d314e | 308 | raw_ctz(uint64_t n) |
0ee140fb | 309 | { |
d43d314e BP |
310 | /* With GCC 4.7 on 32-bit x86, if a 32-bit integer is passed as 'n', using |
311 | * a plain __builtin_ctzll() here always generates an out-of-line function | |
312 | * call. The test below helps it to emit a single 'bsf' instruction. */ | |
313 | return (__builtin_constant_p(n <= UINT32_MAX) && n <= UINT32_MAX | |
314 | ? __builtin_ctz(n) | |
315 | : __builtin_ctzll(n)); | |
0ee140fb | 316 | } |
8c947903 JR |
317 | |
318 | static inline int | |
319 | raw_clz64(uint64_t n) | |
320 | { | |
321 | return __builtin_clzll(n); | |
322 | } | |
0ee140fb BP |
323 | #else |
324 | /* Defined in util.c. */ | |
d43d314e | 325 | int raw_ctz(uint64_t n); |
8c947903 | 326 | int raw_clz64(uint64_t n); |
0ee140fb BP |
327 | #endif |
328 | ||
329 | /* Returns the number of trailing 0-bits in 'n', or 32 if 'n' is 0. */ | |
330 | static inline int | |
d578065e | 331 | ctz32(uint32_t n) |
0ee140fb BP |
332 | { |
333 | return n ? raw_ctz(n) : 32; | |
334 | } | |
335 | ||
cc4c738e JR |
336 | /* Returns the number of trailing 0-bits in 'n', or 64 if 'n' is 0. */ |
337 | static inline int | |
338 | ctz64(uint64_t n) | |
339 | { | |
d43d314e | 340 | return n ? raw_ctz(n) : 64; |
cc4c738e | 341 | } |
18b9283b | 342 | |
8c947903 JR |
343 | /* Returns the number of leading 0-bits in 'n', or 32 if 'n' is 0. */ |
344 | static inline int | |
345 | clz32(uint32_t n) | |
346 | { | |
347 | return n ? raw_clz64(n) - 32 : 32; | |
348 | } | |
349 | ||
350 | /* Returns the number of leading 0-bits in 'n', or 64 if 'n' is 0. */ | |
351 | static inline int | |
352 | clz64(uint64_t n) | |
353 | { | |
354 | return n ? raw_clz64(n) : 64; | |
355 | } | |
356 | ||
357 | /* Given a word 'n', calculates floor(log_2('n')). This is equivalent | |
358 | * to finding the bit position of the most significant one bit in 'n'. It is | |
359 | * an error to call this function with 'n' == 0. */ | |
360 | static inline int | |
361 | log_2_floor(uint64_t n) | |
362 | { | |
363 | return 63 - raw_clz64(n); | |
364 | } | |
365 | ||
366 | /* Given a word 'n', calculates ceil(log_2('n')). It is an error to | |
367 | * call this function with 'n' == 0. */ | |
368 | static inline int | |
369 | log_2_ceil(uint64_t n) | |
370 | { | |
371 | return log_2_floor(n) + !is_pow2(n); | |
372 | } | |
373 | ||
374 | unsigned int count_1bits(uint64_t); | |
375 | ||
fe9d0898 BP |
376 | /* Returns the rightmost 1-bit in 'x' (e.g. 01011000 => 00001000), or 0 if 'x' |
377 | * is 0. */ | |
378 | static inline uintmax_t | |
379 | rightmost_1bit(uintmax_t x) | |
380 | { | |
381 | return x & -x; | |
382 | } | |
383 | ||
384 | /* Returns 'x' with its rightmost 1-bit changed to a zero (e.g. 01011000 => | |
385 | * 01010000), or 0 if 'x' is 0. */ | |
386 | static inline uintmax_t | |
387 | zero_rightmost_1bit(uintmax_t x) | |
388 | { | |
389 | return x & (x - 1); | |
390 | } | |
35bedb61 BP |
391 | |
392 | /* Returns the index of the rightmost 1-bit in 'x' (e.g. 01011000 => 3), or 32 | |
393 | * if 'x' is 0. | |
394 | * | |
395 | * Unlike the other functions for rightmost 1-bits, this function only works | |
396 | * with 32-bit integers. */ | |
397 | static inline uint32_t | |
398 | rightmost_1bit_idx(uint32_t x) | |
399 | { | |
d578065e | 400 | return ctz32(x); |
35bedb61 BP |
401 | } |
402 | ||
d578065e | 403 | /* Returns the index of the leftmost 1-bit in 'x' (e.g. 01011000 => 6), or 32 |
35bedb61 BP |
404 | * if 'x' is 0. |
405 | * | |
406 | * This function only works with 32-bit integers. */ | |
407 | static inline uint32_t | |
408 | leftmost_1bit_idx(uint32_t x) | |
409 | { | |
410 | return x ? log_2_floor(x) : 32; | |
411 | } | |
fe9d0898 | 412 | \f |
75a75043 BP |
413 | bool is_all_zeros(const uint8_t *, size_t); |
414 | bool is_all_ones(const uint8_t *, size_t); | |
ddc4f8e2 BP |
415 | void bitwise_copy(const void *src, unsigned int src_len, unsigned int src_ofs, |
416 | void *dst, unsigned int dst_len, unsigned int dst_ofs, | |
417 | unsigned int n_bits); | |
6cc7ea5e BP |
418 | void bitwise_zero(void *dst_, unsigned int dst_len, unsigned dst_ofs, |
419 | unsigned int n_bits); | |
c2dd4932 BP |
420 | void bitwise_one(void *dst_, unsigned int dst_len, unsigned dst_ofs, |
421 | unsigned int n_bits); | |
79a010aa BP |
422 | bool bitwise_is_all_zeros(const void *, unsigned int len, unsigned int ofs, |
423 | unsigned int n_bits); | |
ddc4f8e2 BP |
424 | void bitwise_put(uint64_t value, |
425 | void *dst, unsigned int dst_len, unsigned int dst_ofs, | |
426 | unsigned int n_bits); | |
427 | uint64_t bitwise_get(const void *src, unsigned int src_len, | |
428 | unsigned int src_ofs, unsigned int n_bits); | |
75a75043 | 429 | |
064af421 BP |
430 | #ifdef __cplusplus |
431 | } | |
432 | #endif | |
433 | ||
434 | #endif /* util.h */ |