1 | #ifndef AWS_COMMON_MACROS_H |
2 | #define AWS_COMMON_MACROS_H |
3 | /* |
4 | * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
5 | * |
6 | * Licensed under the Apache License, Version 2.0 (the "License"). |
7 | * You may not use this file except in compliance with the License. |
8 | * A copy of the License is located at |
9 | * |
10 | * http://aws.amazon.com/apache2.0 |
11 | * |
12 | * or in the "license" file accompanying this file. This file is distributed |
13 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
14 | * express or implied. See the License for the specific language governing |
15 | * permissions and limitations under the License. |
16 | */ |
17 | |
18 | #ifdef __cplusplus |
19 | # define AWS_EXTERN_C_BEGIN extern "C" { |
20 | # define AWS_EXTERN_C_END } |
21 | #else |
22 | # define AWS_EXTERN_C_BEGIN |
23 | # define AWS_EXTERN_C_END |
24 | #endif /* __cplusplus */ |
25 | |
26 | #define AWS_CONCAT(A, B) A##B |
27 | #define AWS_STATIC_ASSERT0(cond, msg) typedef char AWS_CONCAT(static_assertion_, msg)[(!!(cond)) * 2 - 1] |
28 | #define AWS_STATIC_ASSERT1(cond, line) AWS_STATIC_ASSERT0(cond, AWS_CONCAT(at_line_, line)) |
29 | #define AWS_STATIC_ASSERT(cond) AWS_STATIC_ASSERT1(cond, __LINE__) |
30 | |
31 | /* https://stackoverflow.com/questions/9183993/msvc-variadic-macro-expansion */ |
32 | #define GLUE(x, y) x y |
33 | |
34 | #define RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, count, ...) count |
35 | #define EXPAND_ARGS(args) RETURN_ARG_COUNT args |
36 | #define COUNT_ARGS_MAX5(...) EXPAND_ARGS((__VA_ARGS__, 5, 4, 3, 2, 1, 0)) |
37 | |
38 | #define OVERLOAD_MACRO2(name, count) name##count |
39 | #define OVERLOAD_MACRO1(name, count) OVERLOAD_MACRO2(name, count) |
40 | #define OVERLOAD_MACRO(name, count) OVERLOAD_MACRO1(name, count) |
41 | |
42 | #define CALL_OVERLOAD(name, ...) GLUE(OVERLOAD_MACRO(name, COUNT_ARGS_MAX5(__VA_ARGS__)), (__VA_ARGS__)) |
43 | |
44 | #define CALL_OVERLOAD_TEST1(x) x |
45 | #define CALL_OVERLOAD_TEST2(x, y) y |
46 | #define CALL_OVERLOAD_TEST3(x, y, z) z |
47 | #define CALL_OVERLOAD_TEST(...) CALL_OVERLOAD(CALL_OVERLOAD_TEST, __VA_ARGS__) |
48 | AWS_STATIC_ASSERT(CALL_OVERLOAD_TEST(1) == 1); |
49 | AWS_STATIC_ASSERT(CALL_OVERLOAD_TEST(1, 2) == 2); |
50 | AWS_STATIC_ASSERT(CALL_OVERLOAD_TEST(1, 2, 3) == 3); |
51 | |
52 | #define AWS_CACHE_LINE 64 |
53 | /** |
54 | * Format macro for strings of a specified length. |
55 | * Allows non null-terminated strings to be used with the printf family of functions. |
56 | * Ex: printf("scheme is " PRInSTR, 4, "http://example.org"); // ouputs: "scheme is http" |
57 | */ |
58 | #define PRInSTR "%.*s" |
59 | |
60 | #if defined(_MSC_VER) |
61 | # include <malloc.h> |
62 | # define AWS_ALIGNED_TYPEDEF(from, to, alignment) typedef __declspec(align(alignment)) from to |
63 | # define AWS_LIKELY(x) x |
64 | # define AWS_UNLIKELY(x) x |
65 | # define AWS_FORCE_INLINE __forceinline |
66 | # define AWS_VARIABLE_LENGTH_ARRAY(type, name, length) type *name = _alloca(sizeof(type) * (length)) |
67 | # define AWS_DECLSPEC_NORETURN __declspec(noreturn) |
68 | # define AWS_ATTRIBUTE_NORETURN |
69 | #else |
70 | # if defined(__GNUC__) || defined(__clang__) |
71 | # define AWS_ALIGNED_TYPEDEF(from, to, alignment) typedef from to __attribute__((aligned(alignment))) |
72 | # define AWS_TYPE_OF(a) __typeof__(a) |
73 | # define AWS_LIKELY(x) __builtin_expect(!!(x), 1) |
74 | # define AWS_UNLIKELY(x) __builtin_expect(!!(x), 0) |
75 | # define AWS_FORCE_INLINE __attribute__((always_inline)) |
76 | # define AWS_DECLSPEC_NORETURN |
77 | # define AWS_ATTRIBUTE_NORETURN __attribute__((noreturn)) |
78 | # if defined(__cplusplus) |
79 | # define AWS_VARIABLE_LENGTH_ARRAY(type, name, length) type *name = alloca(sizeof(type) * (length)) |
80 | # else |
81 | # define AWS_VARIABLE_LENGTH_ARRAY(type, name, length) type name[length]; |
82 | # endif /* defined(__cplusplus) */ |
83 | # endif /* defined(__GNUC__) || defined(__clang__) */ |
84 | #endif /* defined(_MSC_VER) */ |
85 | |
86 | /* If this is C++, restrict isn't supported. If this is not at least C99 on gcc and clang, it isn't supported. |
87 | * If visual C++ building in C mode, the restrict definition is __restrict. |
88 | * This just figures all of that out based on who's including this header file. */ |
89 | #if defined(__cplusplus) |
90 | # define AWS_RESTRICT |
91 | #else |
92 | # if defined(_MSC_VER) |
93 | # define AWS_RESTRICT __restrict |
94 | # else |
95 | # if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L |
96 | # define AWS_RESTRICT restrict |
97 | # else |
98 | # define AWS_RESTRICT |
99 | # endif /* defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */ |
100 | # endif /* defined(_MSC_VER) */ |
101 | #endif /* defined(__cplusplus) */ |
102 | |
103 | #if defined(_MSC_VER) |
104 | # define AWS_THREAD_LOCAL __declspec(thread) |
105 | #else |
106 | # define AWS_THREAD_LOCAL __thread |
107 | #endif |
108 | |
109 | #define AWS_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) |
110 | /** |
111 | * from a pointer and a type of the struct containing the node |
112 | * this will get you back to the pointer of the object. member is the name of |
113 | * the instance of struct aws_linked_list_node in your struct. |
114 | */ |
115 | #define AWS_CONTAINER_OF(ptr, type, member) ((type *)((uint8_t *)(ptr)-offsetof(type, member))) |
116 | |
117 | #endif /* AWS_COMMON_MACROS_H */ |
118 | |