[2] | 1 | /* $Id: kHlpAssert.h 119 2021-12-19 13:01:47Z bird $ */
|
---|
| 2 | /** @file
|
---|
| 3 | * kHlpAssert - Assertion Macros.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[29] | 7 | * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
|
---|
[2] | 8 | *
|
---|
[29] | 9 | * Permission is hereby granted, free of charge, to any person
|
---|
| 10 | * obtaining a copy of this software and associated documentation
|
---|
| 11 | * files (the "Software"), to deal in the Software without
|
---|
| 12 | * restriction, including without limitation the rights to use,
|
---|
| 13 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
|
---|
| 14 | * copies of the Software, and to permit persons to whom the
|
---|
| 15 | * Software is furnished to do so, subject to the following
|
---|
| 16 | * conditions:
|
---|
[2] | 17 | *
|
---|
[29] | 18 | * The above copyright notice and this permission notice shall be
|
---|
| 19 | * included in all copies or substantial portions of the Software.
|
---|
[2] | 20 | *
|
---|
[29] | 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
---|
| 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
---|
| 23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
---|
| 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
---|
| 25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
---|
| 26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
---|
| 27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
---|
| 28 | * OTHER DEALINGS IN THE SOFTWARE.
|
---|
[2] | 29 | */
|
---|
| 30 |
|
---|
| 31 | #ifndef ___kHlpAssert_h___
|
---|
| 32 | #define ___kHlpAssert_h___
|
---|
| 33 |
|
---|
| 34 | #include <k/kHlpDefs.h>
|
---|
| 35 |
|
---|
| 36 | #ifdef __cplusplus
|
---|
| 37 | extern "C" {
|
---|
| 38 | #endif
|
---|
| 39 |
|
---|
| 40 | /** @defgroup grp_kHlpAssert - Assertion Macros
|
---|
| 41 | * @addtogroup grp_kHlp
|
---|
| 42 | * @{ */
|
---|
| 43 |
|
---|
| 44 | /** @def K_STRICT
|
---|
| 45 | * Assertions are enabled when K_STRICT is \#defined. */
|
---|
| 46 |
|
---|
| 47 | /** @def kHlpAssertBreakpoint
|
---|
| 48 | * Emits a breakpoint instruction or somehow triggers a debugger breakpoint.
|
---|
| 49 | */
|
---|
| 50 | #ifdef _MSC_VER
|
---|
| 51 | # define kHlpAssertBreakpoint() do { __debugbreak(); } while (0)
|
---|
[46] | 52 | #elif defined(__GNUC__) && K_OS == K_OS_SOLARIS && (K_ARCH == K_ARCH_AMD64 || K_ARCH == K_ARCH_X86_32)
|
---|
| 53 | # define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("int $3"); } while (0)
|
---|
| 54 | #elif defined(__GNUC__) && (K_ARCH == K_ARCH_AMD64 || K_ARCH == K_ARCH_X86_32 || K_ARCH == K_ARCH_X86_16)
|
---|
[2] | 55 | # define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("int3"); } while (0)
|
---|
[118] | 56 | #elif defined(__GNUC__) && (K_ARCH == K_ARCH_ARM_64 || K_ARCH == K_ARCH_ARM_32) /* probably not supported by older ARM CPUs */
|
---|
| 57 | # define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("brk #0x1"); } while (0)
|
---|
[119] | 58 | #elif defined(__GNUC__) && (K_ARCH == K_ARCH_SPARC_32)
|
---|
| 59 | # define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("unimp 0"); } while (0) /*??*/
|
---|
| 60 | #elif defined(__GNUC__) && (K_ARCH == K_ARCH_SPARC_64)
|
---|
| 61 | # define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("illtrap 0"); } while (0) /*??*/
|
---|
[2] | 62 | #else
|
---|
| 63 | # error "Port Me"
|
---|
| 64 | #endif
|
---|
| 65 |
|
---|
[70] | 66 | /** @def K_FUNCTION
|
---|
| 67 | * Undecorated function name macro expanded by the compiler.
|
---|
| 68 | */
|
---|
| 69 | #if defined(__GNUC__)
|
---|
| 70 | # define K_FUNCTION __func__
|
---|
| 71 | #else
|
---|
| 72 | # define K_FUNCTION __FUNCTION__
|
---|
| 73 | #endif
|
---|
| 74 |
|
---|
[2] | 75 | #ifdef K_STRICT
|
---|
| 76 |
|
---|
| 77 | # define kHlpAssert(expr) \
|
---|
| 78 | do { \
|
---|
| 79 | if (!(expr)) \
|
---|
| 80 | { \
|
---|
[70] | 81 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[2] | 82 | kHlpAssertBreakpoint(); \
|
---|
[18] | 83 | } \
|
---|
[2] | 84 | } while (0)
|
---|
| 85 |
|
---|
[39] | 86 | # define kHlpAssertStmt(expr, stmt) \
|
---|
[37] | 87 | do { \
|
---|
| 88 | if (!(expr)) \
|
---|
| 89 | { \
|
---|
[70] | 90 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[37] | 91 | kHlpAssertBreakpoint(); \
|
---|
| 92 | stmt; \
|
---|
| 93 | } \
|
---|
| 94 | } while (0)
|
---|
| 95 |
|
---|
[2] | 96 | # define kHlpAssertReturn(expr, rcRet) \
|
---|
| 97 | do { \
|
---|
| 98 | if (!(expr)) \
|
---|
| 99 | { \
|
---|
[70] | 100 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[2] | 101 | kHlpAssertBreakpoint(); \
|
---|
| 102 | return (rcRet); \
|
---|
[18] | 103 | } \
|
---|
[2] | 104 | } while (0)
|
---|
| 105 |
|
---|
[37] | 106 | # define kHlpAssertStmtReturn(expr, stmt, rcRet) \
|
---|
| 107 | do { \
|
---|
| 108 | if (!(expr)) \
|
---|
| 109 | { \
|
---|
[70] | 110 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[37] | 111 | kHlpAssertBreakpoint(); \
|
---|
| 112 | stmt; \
|
---|
| 113 | return (rcRet); \
|
---|
| 114 | } \
|
---|
| 115 | } while (0)
|
---|
| 116 |
|
---|
[2] | 117 | # define kHlpAssertReturnVoid(expr) \
|
---|
| 118 | do { \
|
---|
| 119 | if (!(expr)) \
|
---|
| 120 | { \
|
---|
[70] | 121 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[2] | 122 | kHlpAssertBreakpoint(); \
|
---|
| 123 | return; \
|
---|
[18] | 124 | } \
|
---|
[2] | 125 | } while (0)
|
---|
| 126 |
|
---|
[37] | 127 | # define kHlpAssertStmtReturnVoid(expr, stmt) \
|
---|
| 128 | do { \
|
---|
| 129 | if (!(expr)) \
|
---|
| 130 | { \
|
---|
[70] | 131 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[37] | 132 | kHlpAssertBreakpoint(); \
|
---|
| 133 | stmt; \
|
---|
| 134 | return; \
|
---|
| 135 | } \
|
---|
| 136 | } while (0)
|
---|
| 137 |
|
---|
[2] | 138 | # define kHlpAssertMsg(expr, msg) \
|
---|
| 139 | do { \
|
---|
| 140 | if (!(expr)) \
|
---|
| 141 | { \
|
---|
[70] | 142 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[2] | 143 | kHlpAssertMsg2 msg; \
|
---|
| 144 | kHlpAssertBreakpoint(); \
|
---|
[18] | 145 | } \
|
---|
[2] | 146 | } while (0)
|
---|
| 147 |
|
---|
[37] | 148 | # define kHlpAssertMsgStmt(expr, msg, stmt) \
|
---|
| 149 | do { \
|
---|
| 150 | if (!(expr)) \
|
---|
| 151 | { \
|
---|
[70] | 152 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[37] | 153 | kHlpAssertMsg2 msg; \
|
---|
| 154 | kHlpAssertBreakpoint(); \
|
---|
| 155 | stmt; \
|
---|
| 156 | } \
|
---|
| 157 | } while (0)
|
---|
| 158 |
|
---|
[2] | 159 | # define kHlpAssertMsgReturn(expr, msg, rcRet) \
|
---|
| 160 | do { \
|
---|
| 161 | if (!(expr)) \
|
---|
| 162 | { \
|
---|
[70] | 163 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[2] | 164 | kHlpAssertMsg2 msg; \
|
---|
| 165 | kHlpAssertBreakpoint(); \
|
---|
| 166 | return (rcRet); \
|
---|
[18] | 167 | } \
|
---|
[2] | 168 | } while (0)
|
---|
| 169 |
|
---|
[39] | 170 | # define kHlpAssertMsgStmtReturn(expr, msg, stmt, rcRet) \
|
---|
[37] | 171 | do { \
|
---|
| 172 | if (!(expr)) \
|
---|
| 173 | { \
|
---|
[70] | 174 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[37] | 175 | kHlpAssertMsg2 msg; \
|
---|
| 176 | kHlpAssertBreakpoint(); \
|
---|
| 177 | stmt; \
|
---|
| 178 | return (rcRet); \
|
---|
| 179 | } \
|
---|
| 180 | } while (0)
|
---|
| 181 |
|
---|
[2] | 182 | # define kHlpAssertMsgReturnVoid(expr, msg) \
|
---|
| 183 | do { \
|
---|
| 184 | if (!(expr)) \
|
---|
| 185 | { \
|
---|
[70] | 186 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[2] | 187 | kHlpAssertMsg2 msg; \
|
---|
| 188 | kHlpAssertBreakpoint(); \
|
---|
| 189 | return; \
|
---|
[18] | 190 | } \
|
---|
[2] | 191 | } while (0)
|
---|
| 192 |
|
---|
[39] | 193 | # define kHlpAssertMsgStmtReturnVoid(expr, msg, stmt) \
|
---|
[37] | 194 | do { \
|
---|
| 195 | if (!(expr)) \
|
---|
| 196 | { \
|
---|
[70] | 197 | kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \
|
---|
[37] | 198 | kHlpAssertMsg2 msg; \
|
---|
| 199 | kHlpAssertBreakpoint(); \
|
---|
| 200 | stmt; \
|
---|
| 201 | return; \
|
---|
| 202 | } \
|
---|
| 203 | } while (0)
|
---|
| 204 |
|
---|
[101] | 205 | /* Same as above, only no expression. */
|
---|
| 206 |
|
---|
| 207 | # define kHlpAssertFailed() \
|
---|
| 208 | do { \
|
---|
| 209 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 210 | kHlpAssertBreakpoint(); \
|
---|
| 211 | } while (0)
|
---|
| 212 |
|
---|
| 213 | # define kHlpAssertFailedStmt(stmt) \
|
---|
| 214 | do { \
|
---|
| 215 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 216 | kHlpAssertBreakpoint(); \
|
---|
| 217 | stmt; \
|
---|
| 218 | } while (0)
|
---|
| 219 |
|
---|
| 220 | # define kHlpAssertFailedReturn(rcRet) \
|
---|
| 221 | do { \
|
---|
| 222 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 223 | kHlpAssertBreakpoint(); \
|
---|
| 224 | return (rcRet); \
|
---|
| 225 | } while (0)
|
---|
| 226 |
|
---|
| 227 | # define kHlpAssertFailedStmtReturn(stmt, rcRet) \
|
---|
| 228 | do { \
|
---|
| 229 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 230 | kHlpAssertBreakpoint(); \
|
---|
| 231 | stmt; \
|
---|
| 232 | return (rcRet); \
|
---|
| 233 | } while (0)
|
---|
| 234 |
|
---|
| 235 | # define kHlpAssertFailedReturnVoid() \
|
---|
| 236 | do { \
|
---|
| 237 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 238 | kHlpAssertBreakpoint(); \
|
---|
| 239 | return; \
|
---|
| 240 | } while (0)
|
---|
| 241 |
|
---|
| 242 | # define kHlpAssertFailedStmtReturnVoid(stmt) \
|
---|
| 243 | do { \
|
---|
| 244 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 245 | kHlpAssertBreakpoint(); \
|
---|
| 246 | stmt; \
|
---|
| 247 | return; \
|
---|
| 248 | } while (0)
|
---|
| 249 |
|
---|
| 250 | # define kHlpAssertMsgFailed(msg) \
|
---|
| 251 | do { \
|
---|
| 252 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 253 | kHlpAssertMsg2 msg; \
|
---|
| 254 | kHlpAssertBreakpoint(); \
|
---|
| 255 | } while (0)
|
---|
| 256 |
|
---|
| 257 | # define kHlpAssertMsgFailedStmt(msg, stmt) \
|
---|
| 258 | do { \
|
---|
| 259 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 260 | kHlpAssertMsg2 msg; \
|
---|
| 261 | kHlpAssertBreakpoint(); \
|
---|
| 262 | stmt; \
|
---|
| 263 | } while (0)
|
---|
| 264 |
|
---|
| 265 | # define kHlpAssertMsgFailedReturn(msg, rcRet) \
|
---|
| 266 | do { \
|
---|
| 267 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 268 | kHlpAssertMsg2 msg; \
|
---|
| 269 | kHlpAssertBreakpoint(); \
|
---|
| 270 | return (rcRet); \
|
---|
| 271 | } while (0)
|
---|
| 272 |
|
---|
| 273 | # define kHlpAssertMsgFailedStmtReturn(msg, stmt, rcRet) \
|
---|
| 274 | do { \
|
---|
| 275 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 276 | kHlpAssertMsg2 msg; \
|
---|
| 277 | kHlpAssertBreakpoint(); \
|
---|
| 278 | stmt; \
|
---|
| 279 | return (rcRet); \
|
---|
| 280 | } while (0)
|
---|
| 281 |
|
---|
| 282 | # define kHlpAssertMsgFailedReturnVoid(msg) \
|
---|
| 283 | do { \
|
---|
| 284 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 285 | kHlpAssertMsg2 msg; \
|
---|
| 286 | kHlpAssertBreakpoint(); \
|
---|
| 287 | return; \
|
---|
| 288 | } while (0)
|
---|
| 289 |
|
---|
| 290 | # define kHlpAssertMsgFailedStmtReturnVoid(msg, stmt) \
|
---|
| 291 | do { \
|
---|
| 292 | kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
|
---|
| 293 | kHlpAssertMsg2 msg; \
|
---|
| 294 | kHlpAssertBreakpoint(); \
|
---|
| 295 | stmt; \
|
---|
| 296 | return; \
|
---|
| 297 | } while (0)
|
---|
| 298 |
|
---|
| 299 |
|
---|
[2] | 300 | #else /* !K_STRICT */
|
---|
[101] | 301 |
|
---|
[37] | 302 | # define kHlpAssert(expr) do { } while (0)
|
---|
| 303 | # define kHlpAssertStmt(expr, stmt) do { if (!(expr)) { stmt; } } while (0)
|
---|
| 304 | # define kHlpAssertReturn(expr, rcRet) do { if (!(expr)) return (rcRet); } while (0)
|
---|
| 305 | # define kHlpAssertStmtReturn(expr, stmt, rcRet) do { if (!(expr)) { stmt; return (rcRet); } } while (0)
|
---|
| 306 | # define kHlpAssertReturnVoid(expr) do { if (!(expr)) return; } while (0)
|
---|
| 307 | # define kHlpAssertStmtReturnVoid(expr, stmt) do { if (!(expr)) { stmt; return; } } while (0)
|
---|
| 308 | # define kHlpAssertMsg(expr, msg) do { } while (0)
|
---|
| 309 | # define kHlpAssertMsgStmt(expr, msg, stmt) do { if (!(expr)) { stmt; } } while (0)
|
---|
| 310 | # define kHlpAssertMsgReturn(expr, msg, rcRet) do { if (!(expr)) return (rcRet); } while (0)
|
---|
| 311 | # define kHlpAssertMsgStmtReturn(expr, msg, stmt, rcRet) do { if (!(expr)) { stmt; return (rcRet); } } while (0)
|
---|
| 312 | # define kHlpAssertMsgReturnVoid(expr, msg) do { if (!(expr)) return; } while (0)
|
---|
| 313 | # define kHlpAssertMsgStmtReturnVoid(expr, msg, stmt) do { if (!(expr)) { stmt; return; } } while (0)
|
---|
[101] | 314 | /* Same as above, only no expression: */
|
---|
| 315 | # define kHlpAssertFailed() do { } while (0)
|
---|
| 316 | # define kHlpAssertFailedStmt(stmt) do { stmt; } while (0)
|
---|
| 317 | # define kHlpAssertFailedReturn(rcRet) do { return (rcRet); } while (0)
|
---|
| 318 | # define kHlpAssertFailedStmtReturn(stmt, rcRet) do { stmt; return (rcRet); } while (0)
|
---|
| 319 | # define kHlpAssertFailedReturnVoid() do { return; } while (0)
|
---|
| 320 | # define kHlpAssertFailedStmtReturnVoid(stmt) do { stmt; return; } while (0)
|
---|
| 321 | # define kHlpAssertMsgFailed(msg) do { } while (0)
|
---|
| 322 | # define kHlpAssertMsgFailedStmt(msg, stmt) do { stmt; } while (0)
|
---|
| 323 | # define kHlpAssertMsgFailedReturn(msg, rcRet) do { return (rcRet); } while (0)
|
---|
| 324 | # define kHlpAssertMsgFailedStmtReturn(msg, stmt, rcRet) do { { stmt; return (rcRet); } } while (0)
|
---|
| 325 | # define kHlpAssertMsgFailedReturnVoid(msg) do { return; } while (0)
|
---|
| 326 | # define kHlpAssertMsgFailedStmtReturnVoid(msg, stmt) do { stmt; return; } while (0)
|
---|
| 327 |
|
---|
[2] | 328 | #endif /* !K_STRICT */
|
---|
| 329 |
|
---|
| 330 | #define kHlpAssertPtr(ptr) kHlpAssertMsg(K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
|
---|
| 331 | #define kHlpAssertPtrReturn(ptr, rcRet) kHlpAssertMsgReturn(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
|
---|
[37] | 332 | #define kHlpAssertPtrReturn(ptr, rcRet) kHlpAssertMsgReturn(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
|
---|
[2] | 333 | #define kHlpAssertPtrReturnVoid(ptr) kHlpAssertMsgReturnVoid(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)))
|
---|
| 334 | #define kHlpAssertPtrNull(ptr) kHlpAssertMsg(!(ptr) || K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
|
---|
| 335 | #define kHlpAssertPtrNullReturn(ptr, rcRet) kHlpAssertMsgReturn(!(ptr) || K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet))
|
---|
| 336 | #define kHlpAssertPtrNullReturnVoid(ptr) kHlpAssertMsgReturnVoid(!(ptr) || K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)))
|
---|
| 337 | #define kHlpAssertRC(rc) kHlpAssertMsg((rc) == 0, ("%s = %d\n", #rc, (rc)))
|
---|
| 338 | #define kHlpAssertRCReturn(rc, rcRet) kHlpAssertMsgReturn((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)), (rcRet))
|
---|
| 339 | #define kHlpAssertRCReturnVoid(rc) kHlpAssertMsgReturnVoid((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)))
|
---|
| 340 |
|
---|
[101] | 341 |
|
---|
[2] | 342 | /**
|
---|
| 343 | * Helper function that displays the first part of the assertion message.
|
---|
| 344 | *
|
---|
| 345 | * @param pszExpr The expression.
|
---|
| 346 | * @param pszFile The file name.
|
---|
| 347 | * @param iLine The line number is the file.
|
---|
| 348 | * @param pszFunction The function name.
|
---|
| 349 | * @internal
|
---|
| 350 | */
|
---|
| 351 | KHLP_DECL(void) kHlpAssertMsg1(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction);
|
---|
| 352 |
|
---|
| 353 | /**
|
---|
| 354 | * Helper function that displays custom assert message.
|
---|
| 355 | *
|
---|
| 356 | * @param pszFormat Format string that get passed to vprintf.
|
---|
| 357 | * @param ... Format arguments.
|
---|
| 358 | * @internal
|
---|
| 359 | */
|
---|
| 360 | KHLP_DECL(void) kHlpAssertMsg2(const char *pszFormat, ...);
|
---|
| 361 |
|
---|
| 362 |
|
---|
| 363 | /** @} */
|
---|
| 364 |
|
---|
| 365 | #ifdef __cplusplus
|
---|
| 366 | }
|
---|
| 367 | #endif
|
---|
| 368 |
|
---|
| 369 | #endif
|
---|