1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/json
8 //
9 
10 #ifndef BOOST_JSON_DETAIL_CONFIG_HPP
11 #define BOOST_JSON_DETAIL_CONFIG_HPP
12 
13 #ifndef BOOST_JSON_STANDALONE
14 # include <boost/config.hpp>
15 # include <boost/assert.hpp>
16 # include <boost/throw_exception.hpp>
17 #else
18 # include <cassert>
19 #endif
20 #include <cstdint>
21 #include <type_traits>
22 #include <utility>
23 
24 // detect 32/64 bit
25 #if UINTPTR_MAX == UINT64_MAX
26 # define BOOST_JSON_ARCH 64
27 #elif UINTPTR_MAX == UINT32_MAX
28 # define BOOST_JSON_ARCH 32
29 #else
30 # error Unknown or unsupported architecture, please open an issue
31 #endif
32 
33 // VFALCO Copied from Boost.Config
34 //        This is a derivative work.
35 #ifndef BOOST_JSON_NODISCARD
36 # ifdef __has_cpp_attribute
37 // clang-6 accepts [[nodiscard]] with -std=c++14, but warns about it -pedantic
38 #  if __has_cpp_attribute(nodiscard) && !(defined(__clang__) && (__cplusplus < 201703L))
39 #   define BOOST_JSON_NODISCARD [[nodiscard]]
40 #  else
41 #   define BOOST_JSON_NODISCARD
42 #  endif
43 # else
44 #  define BOOST_JSON_NODISCARD
45 # endif
46 #endif
47 
48 #ifndef BOOST_JSON_REQUIRE_CONST_INIT
49 # define BOOST_JSON_REQUIRE_CONST_INIT
50 # if __cpp_constinit >= 201907L
51 #  undef BOOST_JSON_REQUIRE_CONST_INIT
52 #  define BOOST_JSON_REQUIRE_CONST_INIT constinit
53 # elif defined(__clang__) && defined(__has_cpp_attribute)
54 #  if __has_cpp_attribute(clang::require_constant_initialization)
55 #   undef BOOST_JSON_REQUIRE_CONST_INIT
56 #   define BOOST_JSON_REQUIRE_CONST_INIT [[clang::require_constant_initialization]]
57 #  endif
58 # endif
59 #endif
60 
61 #ifndef BOOST_JSON_NO_DESTROY
62 # if defined(__clang__) && defined(__has_cpp_attribute)
63 #  if __has_cpp_attribute(clang::no_destroy)
64 #   define BOOST_JSON_NO_DESTROY [[clang::no_destroy]]
65 #  endif
66 # endif
67 #endif
68 
69 // BOOST_NORETURN ---------------------------------------------//
70 // Macro to use before a function declaration/definition to designate
71 // the function as not returning normally (i.e. with a return statement
72 // or by leaving the function scope, if the function return type is void).
73 #if !defined(BOOST_NORETURN)
74 #  if defined(_MSC_VER)
75 #    define BOOST_NORETURN __declspec(noreturn)
76 #  elif defined(__GNUC__)
77 #    define BOOST_NORETURN __attribute__ ((__noreturn__))
78 #  elif defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130)
79 #    if __has_attribute(noreturn)
80 #      define BOOST_NORETURN [[noreturn]]
81 #    endif
82 #  elif defined(__has_cpp_attribute)
83 #    if __has_cpp_attribute(noreturn)
84 #      define BOOST_NORETURN [[noreturn]]
85 #    endif
86 #  endif
87 #endif
88 
89 #ifndef BOOST_ASSERT
90 #define BOOST_ASSERT assert
91 #endif
92 
93 #ifndef BOOST_STATIC_ASSERT
94 #define BOOST_STATIC_ASSERT( ... ) static_assert(__VA_ARGS__, #__VA_ARGS__)
95 #endif
96 
97 #ifndef BOOST_FALLTHROUGH
98 #define BOOST_FALLTHROUGH [[fallthrough]]
99 #endif
100 
101 #ifndef BOOST_FORCEINLINE
102 # ifdef _MSC_VER
103 #  define BOOST_FORCEINLINE __forceinline
104 # elif defined(__GNUC__) || defined(__clang__)
105 #  define BOOST_FORCEINLINE inline __attribute__((always_inline))
106 # else
107 #  define BOOST_FORCEINLINE inline
108 # endif
109 #endif
110 
111 #ifndef BOOST_NOINLINE
112 # ifdef _MSC_VER
113 #  define BOOST_NOINLINE __declspec(noinline)
114 # elif defined(__GNUC__) || defined(__clang__)
115 #  define BOOST_NOINLINE __attribute__((noinline))
116 # else
117 #  define BOOST_NOINLINE
118 # endif
119 #endif
120 
121 #ifndef BOOST_THROW_EXCEPTION
122 # ifndef BOOST_NO_EXCEPTIONS
123 #  define BOOST_THROW_EXCEPTION(x) throw(x)
124 # else
125 #  define BOOST_THROW_EXCEPTION(x) do{}while(0)
126 # endif
127 #endif
128 
129 #if ! defined(BOOST_JSON_NO_SSE2) && \
130     ! defined(BOOST_JSON_USE_SSE2)
131 # if (defined(_M_IX86) && _M_IX86_FP == 2) || \
132       defined(_M_X64) || defined(__SSE2__)
133 #  define BOOST_JSON_USE_SSE2
134 # endif
135 #endif
136 
137 #ifndef BOOST_SYMBOL_VISIBLE
138 #define BOOST_SYMBOL_VISIBLE
139 #endif
140 
141 #ifdef BOOST_JSON_STANDALONE
142 # define BOOST_JSON_NS_BEGIN \
143     namespace boost { \
144     namespace json { \
145     inline namespace standalone {
146 # define BOOST_JSON_NS_END } } }
147 #elif ! defined(BOOST_JSON_DOCS)
148 # define BOOST_JSON_NS_BEGIN \
149     namespace boost { \
150     namespace json {
151 # define BOOST_JSON_NS_END } }
152 #endif
153 
154 #ifndef BOOST_JSON_STANDALONE
155 # if defined(BOOST_JSON_DOCS)
156 #  define BOOST_JSON_DECL
157 # else
158 #  if (defined(BOOST_JSON_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_JSON_STATIC_LINK)
159 #   if defined(BOOST_JSON_SOURCE)
160 #    define BOOST_JSON_DECL        BOOST_SYMBOL_EXPORT
161 #    define BOOST_JSON_CLASS_DECL  BOOST_SYMBOL_EXPORT
162 #    define BOOST_JSON_BUILD_DLL
163 #   else
164 #    define BOOST_JSON_DECL        BOOST_SYMBOL_IMPORT
165 #    define BOOST_JSON_CLASS_DECL  BOOST_SYMBOL_IMPORT
166 #   endif
167 #  endif // shared lib
168 #  ifndef  BOOST_JSON_DECL
169 #   define BOOST_JSON_DECL
170 #  endif
171 #  if !defined(BOOST_JSON_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_JSON_NO_LIB)
172 #   define BOOST_LIB_NAME boost_json
173 #   if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_JSON_DYN_LINK)
174 #    define BOOST_DYN_LINK
175 #   endif
176 #   include <boost/config/auto_link.hpp>
177 #  endif
178 # endif
179 #else
180 // For standalone, shared library builds, users must manually
181 // define the macros BOOST_JSON_DECL and BOOST_JSON_CLASS_DECL
182 #endif
183 
184 #ifndef BOOST_JSON_DECL
185 #define BOOST_JSON_DECL
186 #endif
187 #ifndef BOOST_JSON_CLASS_DECL
188 #define BOOST_JSON_CLASS_DECL
189 #endif
190 
191 #ifndef BOOST_JSON_LIKELY
192 # if defined(__GNUC__) || defined(__clang__)
193 #  define BOOST_JSON_LIKELY(x) __builtin_expect(!!(x), 1)
194 # else
195 #  define BOOST_JSON_LIKELY(x) x
196 # endif
197 #endif
198 
199 #ifndef BOOST_JSON_UNLIKELY
200 # if defined(__GNUC__) || defined(__clang__)
201 #  define BOOST_JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
202 # else
203 #  define BOOST_JSON_UNLIKELY(x) x
204 # endif
205 #endif
206 
207 #ifndef BOOST_JSON_UNREACHABLE
208 # define BOOST_JSON_UNREACHABLE() static_cast<void>(0)
209 # ifdef _MSC_VER
210 #  undef BOOST_JSON_UNREACHABLE
211 #  define BOOST_JSON_UNREACHABLE() __assume(0)
212 # elif defined(__has_builtin)
213 #  if __has_builtin(__builtin_unreachable)
214 #   undef BOOST_JSON_UNREACHABLE
215 #   define BOOST_JSON_UNREACHABLE() __builtin_unreachable()
216 #  endif
217 # endif
218 #endif
219 
220 #ifndef BOOST_JSON_ASSUME
221 # define BOOST_JSON_ASSUME(x) (!!(x) ? void() : BOOST_JSON_UNREACHABLE())
222 # ifdef _MSC_VER
223 #  undef BOOST_JSON_ASSUME
224 #  define BOOST_JSON_ASSUME(x) __assume(!!(x))
225 # elif defined(__has_builtin)
226 #  if __has_builtin(__builtin_assume)
227 #   undef BOOST_JSON_ASSUME
228 #   define BOOST_JSON_ASSUME(x) __builtin_assume(!!(x))
229 #  endif
230 # endif
231 #endif
232 
233 // older versions of msvc and clang don't always
234 // constant initialize when they are supposed to
235 #ifndef BOOST_JSON_WEAK_CONSTINIT
236 # if defined(_MSC_VER) && ! defined(__clang__) && _MSC_VER < 1920
237 #  define BOOST_JSON_WEAK_CONSTINIT
238 # elif defined(__clang__) && __clang_major__ < 4
239 #  define BOOST_JSON_WEAK_CONSTINIT
240 # endif
241 #endif
242 
243 // These macros are private, for tests, do not change
244 // them or else previously built libraries won't match.
245 #ifndef  BOOST_JSON_MAX_STRING_SIZE
246 # define BOOST_JSON_NO_MAX_STRING_SIZE
247 # define BOOST_JSON_MAX_STRING_SIZE  0x7ffffffe
248 #endif
249 #ifndef  BOOST_JSON_MAX_STRUCTURED_SIZE
250 # define BOOST_JSON_NO_MAX_STRUCTURED_SIZE
251 # define BOOST_JSON_MAX_STRUCTURED_SIZE  0x7ffffffe
252 #endif
253 #ifndef  BOOST_JSON_STACK_BUFFER_SIZE
254 # define BOOST_JSON_NO_STACK_BUFFER_SIZE
255 # if defined(__i386__) || defined(__x86_64__) || \
256      defined(_M_IX86)  || defined(_M_X64)
257 #  define BOOST_JSON_STACK_BUFFER_SIZE 4096
258 # else
259 // If we are not on Intel, then assume we are on
260 // embedded and use a smaller stack size. If this
261 // is not suitable, the user can define the macro
262 // themselves when building the library or including
263 // src.hpp.
264 #  define BOOST_JSON_STACK_BUFFER_SIZE 256
265 # endif
266 #endif
267 
268 BOOST_JSON_NS_BEGIN
269 namespace detail {
270 
271 template<class...>
272 struct make_void
273 {
274     using type =void;
275 };
276 
277 template<class... Ts>
278 using void_t = typename
279     make_void<Ts...>::type;
280 
281 template<class T>
282 using remove_cvref = typename
283     std::remove_cv<typename
284         std::remove_reference<T>::type>::type;
285 
286 template<class T, class U>
287 T exchange(T& t, U u) noexcept
288 {
289     T v = std::move(t);
290     t = std::move(u);
291     return v;
292 }
293 
294 /*  This is a derivative work, original copyright:
295 
296     Copyright Eric Niebler 2013-present
297 
298     Use, modification and distribution is subject to the
299     Boost Software License, Version 1.0. (See accompanying
300     file LICENSE_1_0.txt or copy at
301     http://www.boost.org/LICENSE_1_0.txt)
302 
303     Project home: https://github.com/ericniebler/range-v3
304 */
305 template<typename T>
306 struct static_const
307 {
308     static constexpr T value {};
309 };
310 template<typename T>
311 constexpr T static_const<T>::value;
312 
313 #define BOOST_JSON_INLINE_VARIABLE(name, type) \
314     namespace { constexpr auto& name = \
315         ::boost::json::detail::static_const<type>::value; \
316     } struct _unused_ ## name ## _semicolon_bait_
317 
318 } // detail
319 BOOST_JSON_NS_END
320 
321 #endif
322