| 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 | |