sparrow
2.0.0
C++20 idiomatic APIs for the Apache Arrow Columnar Format
Loading...
Searching...
No Matches
contracts.hpp
Go to the documentation of this file.
1
// Copyright 2024 Man Group Operations Limited
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
// NOTE: This is based upon v0.3.0 of NoContracts library
16
// https://github.com/Klaim/nocontracts/tree/0ffc183f7527213e3f0a57b8dae9befa7c0ca02c
17
// Modifications: renamed macros
18
19
#pragma once
20
#include <csignal>
21
#include <cstdio>
22
23
#if !defined(SPARROW_CONTRACTS_THROW_ON_FAILURE)
24
# define SPARROW_CONTRACTS_THROW_ON_FAILURE 0
25
#endif
26
27
// Include sparrow exception if throwing is enabled
28
#if SPARROW_CONTRACTS_THROW_ON_FAILURE == 1
29
# include <string>
30
31
# include "
sparrow_exception.hpp
"
32
33
#endif
34
35
37
// Possible bits used to compose the behavior:
38
39
// if not specified by the user but available, use std::print
40
#if not defined(SPARROW_CONTRACTS_USE_STD_PRINT) and not defined(SPARROW_CONTRACTS_USE_STD_FORMAT)
41
# if __cplusplus >= 202002L
42
# include <version>
43
# ifdef __cpp_lib_print
44
# define SPARROW_CONTRACTS_USE_STD_PRINT 1
45
# endif
46
# endif
47
#else
48
// The option is defined, but is it supported? If not we fail.
49
# if defined(SPARROW_CONTRACTS_USE_STD_PRINT) and not defined(__cpp_lib_print)
50
# error "std::print usage is requested but not available"
51
# endif
52
#endif
53
54
// if not specified by the user but available and std::print is not already forced, use std::format
55
#if not defined(SPARROW_CONTRACTS_USE_STD_FORMAT) and not defined(SPARROW_CONTRACTS_USE_STD_PRINT)
56
# if __cplusplus >= 202002L
57
# include <version>
58
# ifdef __cpp_lib_format
59
# define SPARROW_CONTRACTS_USE_STD_FORMAT 1
60
# endif
61
# endif
62
// The option is defined, but is it supported? If not we fail.
63
# if defined(SPARROW_CONTRACTS_USE_STD_FORMAT) and not defined(__cpp_lib_format)
64
# error "std::format usage is requested but not available"
65
# endif
66
#endif
67
68
// user specified to use neither std::format nor std::print, but C's formatting
69
#if defined(SPARROW_CONTRACTS_USE_CFORMAT) && SPARROW_CONTRACTS_USE_CFORMAT == 1
70
# ifdef SPARROW_CONTRACTS_USE_STD_FORMAT
71
# undef SPARROW_CONTRACTS_USE_STD_FORMAT
72
# endif
73
# ifdef SPARROW_CONTRACTS_USE_STD_PRINT
74
# undef SPARROW_CONTRACTS_USE_STD_PRINT
75
# endif
76
#endif
77
78
// clang-format off
79
#if defined(__GNUC__)
80
# define SPARROW_CONTRACTS_IGNORE_WARNINGS \
81
_Pragma("GCC diagnostic push") \
82
_Pragma("GCC diagnostic ignored \"-Wall\"") \
83
_Pragma("GCC diagnostic ignored \"-Wformat-security\"")
84
# define SPARROW_CONTRACTS_RESTORE_WARNINGS \
85
_Pragma("GCC diagnostic pop")
86
#elif defined(__clang__)
87
# define SPARROW_CONTRACTS_IGNORE_WARNINGS \
88
_Pragma("clang diagnostic push") \
89
_Pragma("clang diagnostic ignored \"-Weverything\"")
90
# define SPARROW_CONTRACTS_RESTORE_WARNINGS \
91
_Pragma("clang diagnostic pop")
92
#elif defined(_MSC_VER)
93
# define SPARROW_CONTRACTS_IGNORE_WARNINGS \
94
_Pragma("warning(push)") \
95
_Pragma("warning(disable : 4774)")
// 'var' has different type in 'file1' and 'file2': 'type1' and 'type2'
96
# define SPARROW_CONTRACTS_RESTORE_WARNINGS \
97
_Pragma("warning(pop)")
98
#else
99
# define SPARROW_CONTRACTS_IGNORE_WARNINGS
100
# define SPARROW_CONTRACTS_RESTORE_WARNINGS
101
#endif
102
// clang-format on
103
104
#ifndef SPARROW_CONTRACTS_LOG_FAILURE
105
# if defined(SPARROW_CONTRACTS_USE_STD_PRINT) && SPARROW_CONTRACTS_USE_STD_PRINT == 1
106
# include <cstdio>
107
# include <print>
108
// clang-format off
109
# define SPARROW_CONTRACTS_LOG_FAILURE(expr__, message__) \
110
::std::print(stderr, "Assertion Failed ({}:{}): {} - ({} is wrong)\n", __FILE__, __LINE__, message__, #expr__)
111
// clang-format on
112
# elif defined(SPARROW_CONTRACTS_USE_STD_FORMAT) && SPARROW_CONTRACTS_USE_STD_FORMAT == 1
113
# include <cstdio>
114
# include <format>
115
// clang-format off
116
# define SPARROW_CONTRACTS_LOG_FAILURE( expr__, message__ ) \
117
{ \
118
auto msg = ::std::format("Assertion Failed ({}:{}): {} - ({} is wrong)\n", __FILE__, __LINE__, message__, #expr__); \
119
::fprintf(stderr, "%s", msg.c_str()); \
120
}
121
// clang-format on
122
# else
123
# include <cstdio>
124
# include <cstdlib>
125
// clang-format off
126
# define SPARROW_CONTRACTS_LOG_FAILURE(expr__, message__) \
127
::fprintf(stderr, "Assertion Failed (%s:%i): %s - (%s is wrong)\n", __FILE__, __LINE__, message__, #expr__);
128
// clang-format on
129
# endif
130
#endif
131
132
#ifndef SPARROW_CONTRACTS_ABORT
133
# if SPARROW_CONTRACTS_THROW_ON_FAILURE == 1
134
# if defined(SPARROW_CONTRACTS_USE_STD_FORMAT) && SPARROW_CONTRACTS_USE_STD_FORMAT == 1
135
# define SPARROW_CONTRACTS_ABORT(expr__, message__) \
136
throw ::sparrow::contract_assertion_error( \
137
::std::format("Assertion Failed ({}:{}): {} - ({} is wrong)", __FILE__, __LINE__, message__, #expr__) \
138
)
139
# else
140
# define SPARROW_CONTRACTS_ABORT(expr__, message__) \
141
throw ::sparrow::contract_assertion_error( \
142
::std::string("Assertion Failed (") + __FILE__ + ":" + ::std::to_string(__LINE__) \
143
+ "): " + message__ + " - (" + #expr__ + " is wrong)" \
144
)
145
# endif
146
# else
147
# define SPARROW_CONTRACTS_ABORT(expr__, message__) std::abort()
148
# endif
149
#endif
150
151
// User specifies to just continue instead of abort on failure.
152
#if defined(SPARROW_CONTRACTS_CONTINUE_ON_FAILURE) and SPARROW_CONTRACTS_CONTINUE_ON_FAILURE == 1
153
# undef SPARROW_CONTRACTS_ABORT
154
# if SPARROW_CONTRACTS_THROW_ON_FAILURE == 1
155
# define SPARROW_CONTRACTS_ABORT(expr__, message__)
156
# else
157
# define SPARROW_CONTRACTS_ABORT
158
# endif
159
#endif
160
161
#ifndef SPARROW_CONTRACTS_DEBUGBREAK
162
# ifdef _WIN32
163
# define SPARROW_CONTRACTS_DEBUGBREAK() __debugbreak();
164
# else
165
# define SPARROW_CONTRACTS_DEBUGBREAK() std::raise(SIGTRAP);
166
# endif
167
#endif
168
170
// Default behavior:
171
172
#define SPARROW_CONTRACTS_DEFAULT_CHECKS_ENABLED 1
173
#define SPARROW_CONTRACTS_DEFAULT_ABORT_ON_FAILURE 1
174
175
#define SPARROW_CONTRACTS_DEFAULT_ON_FAILURE(expr__, message__) \
176
SPARROW_CONTRACTS_LOG_FAILURE(expr__, message__); \
177
SPARROW_CONTRACTS_DEBUGBREAK(); \
178
SPARROW_CONTRACTS_ABORT(expr__, message__);
179
181
// Apply Configuration:
182
183
// If not override, use the default behavior.
184
#ifndef SPARROW_CONTRACTS_CHECKS_ENABLED
185
# define SPARROW_CONTRACTS_CHECKS_ENABLED SPARROW_CONTRACTS_DEFAULT_CHECKS_ENABLED
186
#endif
187
188
#if SPARROW_CONTRACTS_CHECKS_ENABLED == 1
// Behavior when contracts are enabled.
189
190
# ifndef SPARROW_CONTRACTS_ON_FAILURE
191
# define SPARROW_CONTRACTS_ON_FAILURE(expr__, message__) \
192
SPARROW_CONTRACTS_DEFAULT_ON_FAILURE(expr__, message__)
193
# endif
194
195
# ifndef SPARROW_ASSERT
196
# define SPARROW_ASSERT(expr__, message__) \
197
if (!(expr__)) \
198
{ \
199
SPARROW_CONTRACTS_ON_FAILURE(expr__, message__); \
200
}
201
# endif
202
203
# define SPARROW_ASSERT_TRUE(expr__) SPARROW_ASSERT(expr__, #expr__)
204
# define SPARROW_ASSERT_FALSE(expr__) SPARROW_ASSERT(!(expr__), "!(" #expr__ ")")
205
206
#else
// Do nothing otherwise.
207
# define SPARROW_CONTRACTS_ON_FAILURE(expr__)
208
# define SPARROW_ASSERT(expr__, message__)
209
# define SPARROW_ASSERT_TRUE(expr__)
210
# define SPARROW_ASSERT_FALSE(expr__)
211
#endif
sparrow_exception.hpp
sparrow
utils
contracts.hpp
Generated by
1.13.2