nostrdb: pull latest, adding flatcc and lmdb
This commit is contained in:
14
nostrdb/flatcc/portable/LICENSE
Normal file
14
nostrdb/flatcc/portable/LICENSE
Normal file
@@ -0,0 +1,14 @@
|
||||
Copyright (c) 2016 Mikkel F. Jørgensen, dvide.com
|
||||
Some files also Copyright author of MathGeoLib (https://github.com/juj)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License. http://www.apache.org/licenses/LICENSE-2.0
|
||||
57
nostrdb/flatcc/portable/README.md
Normal file
57
nostrdb/flatcc/portable/README.md
Normal file
@@ -0,0 +1,57 @@
|
||||
A small library for adding C11 compatibility to older C compilers, but
|
||||
only a small highly useful subset such as static assertions, inline
|
||||
functions and alignment.
|
||||
|
||||
C++ is not a primary target, but the library has been updated to be more
|
||||
C++ friendly based on user feedback.
|
||||
|
||||
Many compilers already have the required functionality but with slightly
|
||||
different names and arguments.
|
||||
|
||||
In addition, compatibility with the Linux `<endian.h>` system file is
|
||||
provided, and "punaligned.h" is provided for unaligned memory reads
|
||||
which in part depends on endian support.
|
||||
|
||||
The library also provides fast integer printing and floating point
|
||||
printing and parsing optionally using the grisu3 algorithm, but can fall
|
||||
back to strtod and related. The `pgrisu3` folder is header only and
|
||||
excludes test cases found in the main grisu3 project the files were
|
||||
extracted from. Base64 conversion is also provided.
|
||||
|
||||
Integer conversion is not just an optimization. It is more difficult
|
||||
than it would appear to portably parse an integer of known size such as
|
||||
`uint64_t` up to at most n bytes which is needed for safe parsing. At
|
||||
the same time, the sometimes significant performance gains warrants
|
||||
custom implementations that might as well be done once and for all.
|
||||
|
||||
Files can be included individually, or portable.h may be included to get
|
||||
all functionality. If the compiler is C11 compliant, portable.h will not
|
||||
include anything, except: it will provide a patch for static assertions
|
||||
which clang does not fully support in all versions even with C11 flagged.
|
||||
|
||||
The grisu3 header files are the runtime files for the Grisu3 floating
|
||||
point conversion to/from text C port. Test coverage is provided separately.
|
||||
This library can be used indirectly via pparsefp.h and pprintfp.h.
|
||||
|
||||
The `pstatic_assert.h` file is often needed on C11 systems because the
|
||||
compiler and standard library may support `_Static_assert` without
|
||||
`static_assert`. For compilers without `_Static_assert`, a unique
|
||||
identifier is needed for each assertion. This is done non-standard with
|
||||
the `__COUNTER__` macro, but has a fallback to `pstatic_assert_scope.h`
|
||||
for systems witout the `__COUNTER__` macro. Because of this fallback,
|
||||
`pstatic_assert.h` needs to be included in every file using
|
||||
`static_assert` in order to increment a scope counter, otherwise there
|
||||
is a risk of assert identifier conflicts when `static_assert` happen on
|
||||
the same line in different files.
|
||||
|
||||
The `paligned_alloc.h` file implements the non-standard `aligned_free`
|
||||
to match the C11 standard `aligned_alloc` call. `aligned_free` is
|
||||
normally equivalent to `free`, but not on systems where `aligned_free`
|
||||
cannot be implemented using a system provived `free` call. Use of
|
||||
`aligned_free` is thus optional on some systems, but using it increases
|
||||
general portablity at the cost of pure C11 compatibility.
|
||||
|
||||
IMPORTANT NOTE: this library has been used on various platforms and
|
||||
updated with user feedback but it is impossibly to systematically test
|
||||
all platforms so please test for specific uses cases and report
|
||||
any issues upstream.
|
||||
329
nostrdb/flatcc/portable/grisu3_math.h
Normal file
329
nostrdb/flatcc/portable/grisu3_math.h
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Mikkel F. Jørgensen, dvide.com
|
||||
* Copyright author of MathGeoLib (https://github.com/juj)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License. http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
/* 2016-02-02: Updated by mikkelfj
|
||||
*
|
||||
* Extracted from MatGeoLib grisu3.c, Apache 2.0 license, and extended.
|
||||
*
|
||||
* This file is usually include via grisu3_print.h or grisu3_parse.h.
|
||||
*
|
||||
* The original MatGeoLib dtoa_grisu3 implementation is largely
|
||||
* unchanged except for the uint64 to double cast. The remaining changes
|
||||
* are file structure, name changes, and new additions for parsing:
|
||||
*
|
||||
* - Split into header files only:
|
||||
* grisu3_math.h, grisu3_print.h, (added grisu3_parse.h)
|
||||
*
|
||||
* - names prefixed with grisu3_, grisu3_diy_fp_, GRISU3_.
|
||||
* - added static to all functions.
|
||||
* - disabled clang unused function warnings.
|
||||
* - guarded <stdint.h> to allow for alternative impl.
|
||||
* - added extra numeric constants needed for parsing.
|
||||
* - added dec_pow, cast_double_from_diy_fp.
|
||||
* - changed some function names for consistency.
|
||||
* - moved printing specific grisu3 functions to grisu3_print.h.
|
||||
* - changed double to uint64 cast to avoid aliasing.
|
||||
* - added new grisu3_parse.h for parsing doubles.
|
||||
* - grisu3_print_double (dtoa_grisu3) format .1 as 0.1 needed for valid JSON output
|
||||
* and grisu3_parse_double wouldn't consume it.
|
||||
* - grsu3_print_double changed formatting to prefer 0.012 over 1.2e-2.
|
||||
*
|
||||
* These changes make it possible to include the files as headers only
|
||||
* in other software libraries without risking name conflicts, and to
|
||||
* extend the implementation with a port of Googles Double Conversion
|
||||
* strtod functionality for parsing doubles.
|
||||
*
|
||||
* Extracted from: rev. 915501a / Dec 22, 2015
|
||||
* <https://github.com/juj/MathGeoLib/blob/master/src/Math/grisu3.c>
|
||||
* MathGeoLib License: http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
*/
|
||||
|
||||
#ifndef GRISU3_MATH_H
|
||||
#define GRISU3_MATH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Guarded to allow inclusion of pstdint.h first, if stdint.h is not supported. */
|
||||
#ifndef UINT8_MAX
|
||||
#include <stdint.h> /* uint64_t etc. */
|
||||
#endif
|
||||
|
||||
#ifdef GRISU3_NO_ASSERT
|
||||
#undef GRISU3_ASSERT
|
||||
#define GRISU3_ASSERT(x) ((void)0)
|
||||
#endif
|
||||
|
||||
#ifndef GRISU3_ASSERT
|
||||
#include <assert.h> /* assert */
|
||||
#define GRISU3_ASSERT(x) assert(x)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer */
|
||||
#endif
|
||||
|
||||
#define GRISU3_D64_SIGN 0x8000000000000000ULL
|
||||
#define GRISU3_D64_EXP_MASK 0x7FF0000000000000ULL
|
||||
#define GRISU3_D64_FRACT_MASK 0x000FFFFFFFFFFFFFULL
|
||||
#define GRISU3_D64_IMPLICIT_ONE 0x0010000000000000ULL
|
||||
#define GRISU3_D64_EXP_POS 52
|
||||
#define GRISU3_D64_EXP_BIAS 1075
|
||||
#define GRISU3_D64_DENORM_EXP (-GRISU3_D64_EXP_BIAS + 1)
|
||||
#define GRISU3_DIY_FP_FRACT_SIZE 64
|
||||
#define GRISU3_D_1_LOG2_10 0.30102999566398114 /* 1 / lg(10) */
|
||||
#define GRISU3_MIN_TARGET_EXP -60
|
||||
#define GRISU3_MASK32 0xFFFFFFFFULL
|
||||
#define GRISU3_MIN_CACHED_EXP -348
|
||||
#define GRISU3_MAX_CACHED_EXP 340
|
||||
#define GRISU3_CACHED_EXP_STEP 8
|
||||
#define GRISU3_D64_MAX_DEC_EXP 309
|
||||
#define GRISU3_D64_MIN_DEC_EXP -324
|
||||
#define GRISU3_D64_INF GRISU3_D64_EXP_MASK
|
||||
|
||||
#define GRISU3_MIN(x,y) ((x) <= (y) ? (x) : (y))
|
||||
#define GRISU3_MAX(x,y) ((x) >= (y) ? (x) : (y))
|
||||
|
||||
|
||||
typedef struct grisu3_diy_fp
|
||||
{
|
||||
uint64_t f;
|
||||
int e;
|
||||
} grisu3_diy_fp_t;
|
||||
|
||||
typedef struct grisu3_diy_fp_power
|
||||
{
|
||||
uint64_t fract;
|
||||
int16_t b_exp, d_exp;
|
||||
} grisu3_diy_fp_power_t;
|
||||
|
||||
typedef union {
|
||||
uint64_t u64;
|
||||
double d64;
|
||||
} grisu3_cast_double_t;
|
||||
|
||||
static uint64_t grisu3_cast_uint64_from_double(double d)
|
||||
{
|
||||
grisu3_cast_double_t cd;
|
||||
cd.d64 = d;
|
||||
return cd.u64;
|
||||
}
|
||||
|
||||
static double grisu3_cast_double_from_uint64(uint64_t u)
|
||||
{
|
||||
grisu3_cast_double_t cd;
|
||||
cd.u64 = u;
|
||||
return cd.d64;
|
||||
}
|
||||
|
||||
#define grisu3_double_infinity grisu3_cast_double_from_uint64(GRISU3_D64_INF)
|
||||
#define grisu3_double_nan grisu3_cast_double_from_uint64(GRISU3_D64_INF + 1)
|
||||
|
||||
static const grisu3_diy_fp_power_t grisu3_diy_fp_pow_cache[] =
|
||||
{
|
||||
{ 0xfa8fd5a0081c0288ULL, -1220, -348 },
|
||||
{ 0xbaaee17fa23ebf76ULL, -1193, -340 },
|
||||
{ 0x8b16fb203055ac76ULL, -1166, -332 },
|
||||
{ 0xcf42894a5dce35eaULL, -1140, -324 },
|
||||
{ 0x9a6bb0aa55653b2dULL, -1113, -316 },
|
||||
{ 0xe61acf033d1a45dfULL, -1087, -308 },
|
||||
{ 0xab70fe17c79ac6caULL, -1060, -300 },
|
||||
{ 0xff77b1fcbebcdc4fULL, -1034, -292 },
|
||||
{ 0xbe5691ef416bd60cULL, -1007, -284 },
|
||||
{ 0x8dd01fad907ffc3cULL, -980, -276 },
|
||||
{ 0xd3515c2831559a83ULL, -954, -268 },
|
||||
{ 0x9d71ac8fada6c9b5ULL, -927, -260 },
|
||||
{ 0xea9c227723ee8bcbULL, -901, -252 },
|
||||
{ 0xaecc49914078536dULL, -874, -244 },
|
||||
{ 0x823c12795db6ce57ULL, -847, -236 },
|
||||
{ 0xc21094364dfb5637ULL, -821, -228 },
|
||||
{ 0x9096ea6f3848984fULL, -794, -220 },
|
||||
{ 0xd77485cb25823ac7ULL, -768, -212 },
|
||||
{ 0xa086cfcd97bf97f4ULL, -741, -204 },
|
||||
{ 0xef340a98172aace5ULL, -715, -196 },
|
||||
{ 0xb23867fb2a35b28eULL, -688, -188 },
|
||||
{ 0x84c8d4dfd2c63f3bULL, -661, -180 },
|
||||
{ 0xc5dd44271ad3cdbaULL, -635, -172 },
|
||||
{ 0x936b9fcebb25c996ULL, -608, -164 },
|
||||
{ 0xdbac6c247d62a584ULL, -582, -156 },
|
||||
{ 0xa3ab66580d5fdaf6ULL, -555, -148 },
|
||||
{ 0xf3e2f893dec3f126ULL, -529, -140 },
|
||||
{ 0xb5b5ada8aaff80b8ULL, -502, -132 },
|
||||
{ 0x87625f056c7c4a8bULL, -475, -124 },
|
||||
{ 0xc9bcff6034c13053ULL, -449, -116 },
|
||||
{ 0x964e858c91ba2655ULL, -422, -108 },
|
||||
{ 0xdff9772470297ebdULL, -396, -100 },
|
||||
{ 0xa6dfbd9fb8e5b88fULL, -369, -92 },
|
||||
{ 0xf8a95fcf88747d94ULL, -343, -84 },
|
||||
{ 0xb94470938fa89bcfULL, -316, -76 },
|
||||
{ 0x8a08f0f8bf0f156bULL, -289, -68 },
|
||||
{ 0xcdb02555653131b6ULL, -263, -60 },
|
||||
{ 0x993fe2c6d07b7facULL, -236, -52 },
|
||||
{ 0xe45c10c42a2b3b06ULL, -210, -44 },
|
||||
{ 0xaa242499697392d3ULL, -183, -36 },
|
||||
{ 0xfd87b5f28300ca0eULL, -157, -28 },
|
||||
{ 0xbce5086492111aebULL, -130, -20 },
|
||||
{ 0x8cbccc096f5088ccULL, -103, -12 },
|
||||
{ 0xd1b71758e219652cULL, -77, -4 },
|
||||
{ 0x9c40000000000000ULL, -50, 4 },
|
||||
{ 0xe8d4a51000000000ULL, -24, 12 },
|
||||
{ 0xad78ebc5ac620000ULL, 3, 20 },
|
||||
{ 0x813f3978f8940984ULL, 30, 28 },
|
||||
{ 0xc097ce7bc90715b3ULL, 56, 36 },
|
||||
{ 0x8f7e32ce7bea5c70ULL, 83, 44 },
|
||||
{ 0xd5d238a4abe98068ULL, 109, 52 },
|
||||
{ 0x9f4f2726179a2245ULL, 136, 60 },
|
||||
{ 0xed63a231d4c4fb27ULL, 162, 68 },
|
||||
{ 0xb0de65388cc8ada8ULL, 189, 76 },
|
||||
{ 0x83c7088e1aab65dbULL, 216, 84 },
|
||||
{ 0xc45d1df942711d9aULL, 242, 92 },
|
||||
{ 0x924d692ca61be758ULL, 269, 100 },
|
||||
{ 0xda01ee641a708deaULL, 295, 108 },
|
||||
{ 0xa26da3999aef774aULL, 322, 116 },
|
||||
{ 0xf209787bb47d6b85ULL, 348, 124 },
|
||||
{ 0xb454e4a179dd1877ULL, 375, 132 },
|
||||
{ 0x865b86925b9bc5c2ULL, 402, 140 },
|
||||
{ 0xc83553c5c8965d3dULL, 428, 148 },
|
||||
{ 0x952ab45cfa97a0b3ULL, 455, 156 },
|
||||
{ 0xde469fbd99a05fe3ULL, 481, 164 },
|
||||
{ 0xa59bc234db398c25ULL, 508, 172 },
|
||||
{ 0xf6c69a72a3989f5cULL, 534, 180 },
|
||||
{ 0xb7dcbf5354e9beceULL, 561, 188 },
|
||||
{ 0x88fcf317f22241e2ULL, 588, 196 },
|
||||
{ 0xcc20ce9bd35c78a5ULL, 614, 204 },
|
||||
{ 0x98165af37b2153dfULL, 641, 212 },
|
||||
{ 0xe2a0b5dc971f303aULL, 667, 220 },
|
||||
{ 0xa8d9d1535ce3b396ULL, 694, 228 },
|
||||
{ 0xfb9b7cd9a4a7443cULL, 720, 236 },
|
||||
{ 0xbb764c4ca7a44410ULL, 747, 244 },
|
||||
{ 0x8bab8eefb6409c1aULL, 774, 252 },
|
||||
{ 0xd01fef10a657842cULL, 800, 260 },
|
||||
{ 0x9b10a4e5e9913129ULL, 827, 268 },
|
||||
{ 0xe7109bfba19c0c9dULL, 853, 276 },
|
||||
{ 0xac2820d9623bf429ULL, 880, 284 },
|
||||
{ 0x80444b5e7aa7cf85ULL, 907, 292 },
|
||||
{ 0xbf21e44003acdd2dULL, 933, 300 },
|
||||
{ 0x8e679c2f5e44ff8fULL, 960, 308 },
|
||||
{ 0xd433179d9c8cb841ULL, 986, 316 },
|
||||
{ 0x9e19db92b4e31ba9ULL, 1013, 324 },
|
||||
{ 0xeb96bf6ebadf77d9ULL, 1039, 332 },
|
||||
{ 0xaf87023b9bf0ee6bULL, 1066, 340 }
|
||||
};
|
||||
|
||||
/* Avoid dependence on lib math to get (int)ceil(v) */
|
||||
static int grisu3_iceil(double v)
|
||||
{
|
||||
int k = (int)v;
|
||||
if (v < 0) return k;
|
||||
return v - k == 0 ? k : k + 1;
|
||||
}
|
||||
|
||||
static int grisu3_diy_fp_cached_pow(int exp, grisu3_diy_fp_t *p)
|
||||
{
|
||||
int k = grisu3_iceil((exp+GRISU3_DIY_FP_FRACT_SIZE-1) * GRISU3_D_1_LOG2_10);
|
||||
int i = (k-GRISU3_MIN_CACHED_EXP-1) / GRISU3_CACHED_EXP_STEP + 1;
|
||||
p->f = grisu3_diy_fp_pow_cache[i].fract;
|
||||
p->e = grisu3_diy_fp_pow_cache[i].b_exp;
|
||||
return grisu3_diy_fp_pow_cache[i].d_exp;
|
||||
}
|
||||
|
||||
static grisu3_diy_fp_t grisu3_diy_fp_minus(grisu3_diy_fp_t x, grisu3_diy_fp_t y)
|
||||
{
|
||||
grisu3_diy_fp_t d; d.f = x.f - y.f; d.e = x.e;
|
||||
GRISU3_ASSERT(x.e == y.e && x.f >= y.f);
|
||||
return d;
|
||||
}
|
||||
|
||||
static grisu3_diy_fp_t grisu3_diy_fp_multiply(grisu3_diy_fp_t x, grisu3_diy_fp_t y)
|
||||
{
|
||||
uint64_t a, b, c, d, ac, bc, ad, bd, tmp;
|
||||
grisu3_diy_fp_t r;
|
||||
a = x.f >> 32; b = x.f & GRISU3_MASK32;
|
||||
c = y.f >> 32; d = y.f & GRISU3_MASK32;
|
||||
ac = a*c; bc = b*c;
|
||||
ad = a*d; bd = b*d;
|
||||
tmp = (bd >> 32) + (ad & GRISU3_MASK32) + (bc & GRISU3_MASK32);
|
||||
tmp += 1U << 31; /* round */
|
||||
r.f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
|
||||
r.e = x.e + y.e + 64;
|
||||
return r;
|
||||
}
|
||||
|
||||
static grisu3_diy_fp_t grisu3_diy_fp_normalize(grisu3_diy_fp_t n)
|
||||
{
|
||||
GRISU3_ASSERT(n.f != 0);
|
||||
while(!(n.f & 0xFFC0000000000000ULL)) { n.f <<= 10; n.e -= 10; }
|
||||
while(!(n.f & GRISU3_D64_SIGN)) { n.f <<= 1; --n.e; }
|
||||
return n;
|
||||
}
|
||||
|
||||
static grisu3_diy_fp_t grisu3_cast_diy_fp_from_double(double d)
|
||||
{
|
||||
grisu3_diy_fp_t fp;
|
||||
uint64_t u64 = grisu3_cast_uint64_from_double(d);
|
||||
if (!(u64 & GRISU3_D64_EXP_MASK)) { fp.f = u64 & GRISU3_D64_FRACT_MASK; fp.e = 1 - GRISU3_D64_EXP_BIAS; }
|
||||
else { fp.f = (u64 & GRISU3_D64_FRACT_MASK) + GRISU3_D64_IMPLICIT_ONE; fp.e = (int)((u64 & GRISU3_D64_EXP_MASK) >> GRISU3_D64_EXP_POS) - GRISU3_D64_EXP_BIAS; }
|
||||
return fp;
|
||||
}
|
||||
|
||||
static double grisu3_cast_double_from_diy_fp(grisu3_diy_fp_t n)
|
||||
{
|
||||
const uint64_t hidden_bit = GRISU3_D64_IMPLICIT_ONE;
|
||||
const uint64_t frac_mask = GRISU3_D64_FRACT_MASK;
|
||||
const int denorm_exp = GRISU3_D64_DENORM_EXP;
|
||||
const int exp_bias = GRISU3_D64_EXP_BIAS;
|
||||
const int exp_pos = GRISU3_D64_EXP_POS;
|
||||
|
||||
grisu3_diy_fp_t v = n;
|
||||
uint64_t e_biased;
|
||||
|
||||
while (v.f > hidden_bit + frac_mask) {
|
||||
v.f >>= 1;
|
||||
++v.e;
|
||||
}
|
||||
if (v.e < denorm_exp) {
|
||||
return 0.0;
|
||||
}
|
||||
while (v.e > denorm_exp && (v.f & hidden_bit) == 0) {
|
||||
v.f <<= 1;
|
||||
--v.e;
|
||||
}
|
||||
if (v.e == denorm_exp && (v.f & hidden_bit) == 0) {
|
||||
e_biased = 0;
|
||||
} else {
|
||||
e_biased = (uint64_t)(v.e + exp_bias);
|
||||
}
|
||||
return grisu3_cast_double_from_uint64((v.f & frac_mask) | (e_biased << exp_pos));
|
||||
}
|
||||
|
||||
/* pow10_cache[i] = 10^(i-1) */
|
||||
static const unsigned int grisu3_pow10_cache[] = { 0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
|
||||
|
||||
static int grisu3_largest_pow10(uint32_t n, int n_bits, uint32_t *power)
|
||||
{
|
||||
int guess = ((n_bits + 1) * 1233 >> 12) + 1/*skip first entry*/;
|
||||
if (n < grisu3_pow10_cache[guess]) --guess; /* We don't have any guarantees that 2^n_bits <= n. */
|
||||
*power = grisu3_pow10_cache[guess];
|
||||
return guess;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GRISU3_MATH_H */
|
||||
582
nostrdb/flatcc/portable/grisu3_parse.h
Normal file
582
nostrdb/flatcc/portable/grisu3_parse.h
Normal file
@@ -0,0 +1,582 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Mikkel F. Jørgensen, dvide.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License. http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Port of parts of Google Double Conversion strtod functionality
|
||||
* but with fallback to strtod instead of a bignum implementation.
|
||||
*
|
||||
* Based on grisu3 math from MathGeoLib.
|
||||
*
|
||||
* See also grisu3_math.h comments.
|
||||
*/
|
||||
|
||||
#ifndef GRISU3_PARSE_H
|
||||
#define GRISU3_PARSE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "grisu3_math.h"
|
||||
|
||||
|
||||
/*
|
||||
* The maximum number characters a valid number may contain. The parse
|
||||
* fails if the input length is longer but the character after max len
|
||||
* was part of the number.
|
||||
*
|
||||
* The length should not be set too high because it protects against
|
||||
* overflow in the exponent part derived from the input length.
|
||||
*/
|
||||
#define GRISU3_NUM_MAX_LEN 1000
|
||||
|
||||
/*
|
||||
* The lightweight "portable" C library recognizes grisu3 support if
|
||||
* included first.
|
||||
*/
|
||||
#define grisu3_parse_double_is_defined 1
|
||||
|
||||
/*
|
||||
* Disable to compare performance and to test diy_fp algorithm in
|
||||
* broader range.
|
||||
*/
|
||||
#define GRISU3_PARSE_FAST_CASE
|
||||
|
||||
/* May result in a one off error, otherwise when uncertain, fall back to strtod. */
|
||||
//#define GRISU3_PARSE_ALLOW_ERROR
|
||||
|
||||
|
||||
/*
|
||||
* The dec output exponent jumps in 8, so the result is offset at most
|
||||
* by 7 when the input is within range.
|
||||
*/
|
||||
static int grisu3_diy_fp_cached_dec_pow(int d_exp, grisu3_diy_fp_t *p)
|
||||
{
|
||||
const int cached_offset = -GRISU3_MIN_CACHED_EXP;
|
||||
const int d_exp_dist = GRISU3_CACHED_EXP_STEP;
|
||||
int i, a_exp;
|
||||
|
||||
GRISU3_ASSERT(GRISU3_MIN_CACHED_EXP <= d_exp);
|
||||
GRISU3_ASSERT(d_exp < GRISU3_MAX_CACHED_EXP + d_exp_dist);
|
||||
|
||||
i = (d_exp + cached_offset) / d_exp_dist;
|
||||
a_exp = grisu3_diy_fp_pow_cache[i].d_exp;
|
||||
p->f = grisu3_diy_fp_pow_cache[i].fract;
|
||||
p->e = grisu3_diy_fp_pow_cache[i].b_exp;
|
||||
|
||||
GRISU3_ASSERT(a_exp <= d_exp);
|
||||
GRISU3_ASSERT(d_exp < a_exp + d_exp_dist);
|
||||
|
||||
return a_exp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ported from google double conversion strtod using
|
||||
* MathGeoLibs diy_fp functions for grisu3 in C.
|
||||
*
|
||||
* ulp_half_error is set if needed to trunacted non-zero trialing
|
||||
* characters.
|
||||
*
|
||||
* The actual value we need to encode is:
|
||||
*
|
||||
* (sign ? -1 : 1) * fraction * 2 ^ (exponent - fraction_exp)
|
||||
* where exponent is the base 10 exponent assuming the decimal point is
|
||||
* after the first digit. fraction_exp is the base 10 magnitude of the
|
||||
* fraction or number of significant digits - 1.
|
||||
*
|
||||
* If the exponent is between 0 and 22 and the fraction is encoded in
|
||||
* the lower 53 bits (the largest bit is implicit in a double, but not
|
||||
* in this fraction), then the value can be trivially converted to
|
||||
* double without loss of precision. If the fraction was in fact
|
||||
* multiplied by trailing zeroes that we didn't convert to exponent,
|
||||
* we there are larger values the 53 bits that can also be encoded
|
||||
* trivially - but then it is better to handle this during parsing
|
||||
* if it is worthwhile. We do not optimize for this here, because it
|
||||
* can be done in a simple check before calling, and because it might
|
||||
* not be worthwile to do at all since it cery likely will fail for
|
||||
* numbers printed to be convertible back to double without loss.
|
||||
*
|
||||
* Returns 0 if conversion was not exact. In that case the vale is
|
||||
* either one smaller than the correct one, or the correct one.
|
||||
*
|
||||
* Exponents must be range protected before calling otherwise cached
|
||||
* powers will blow up.
|
||||
*
|
||||
* Google Double Conversion seems to prefer the following notion:
|
||||
*
|
||||
* x >= 10^309 => +Inf
|
||||
* x <= 10^-324 => 0,
|
||||
*
|
||||
* max double: HUGE_VAL = 1.7976931348623157 * 10^308
|
||||
* min double: 4.9406564584124654 * 10^-324
|
||||
*
|
||||
* Values just below or above min/max representable number
|
||||
* may round towards large/small non-Inf/non-neg values.
|
||||
*
|
||||
* but `strtod` seems to return +/-HUGE_VAL on overflow?
|
||||
*/
|
||||
static int grisu3_diy_fp_encode_double(uint64_t fraction, int exponent, int fraction_exp, int ulp_half_error, double *result)
|
||||
{
|
||||
/*
|
||||
* Error is measures in fractions of integers, so we scale up to get
|
||||
* some resolution to represent error expressions.
|
||||
*/
|
||||
const int log2_error_one = 3;
|
||||
const int error_one = 1 << log2_error_one;
|
||||
const int denorm_exp = GRISU3_D64_DENORM_EXP;
|
||||
const uint64_t hidden_bit = GRISU3_D64_IMPLICIT_ONE;
|
||||
const int diy_size = GRISU3_DIY_FP_FRACT_SIZE;
|
||||
const int max_digits = 19;
|
||||
|
||||
int error = ulp_half_error ? error_one / 2 : 0;
|
||||
int d_exp = (exponent - fraction_exp);
|
||||
int a_exp;
|
||||
int o_exp;
|
||||
grisu3_diy_fp_t v = { fraction, 0 };
|
||||
grisu3_diy_fp_t cp;
|
||||
grisu3_diy_fp_t rounded;
|
||||
int mag;
|
||||
int prec;
|
||||
int prec_bits;
|
||||
int half_way;
|
||||
|
||||
/* When fractions in a double aren't stored with implicit msb fraction bit. */
|
||||
|
||||
/* Shift fraction to msb. */
|
||||
v = grisu3_diy_fp_normalize(v);
|
||||
/* The half point error moves up while the exponent moves down. */
|
||||
error <<= -v.e;
|
||||
|
||||
a_exp = grisu3_diy_fp_cached_dec_pow(d_exp, &cp);
|
||||
|
||||
/* Interpolate between cached powers at distance 8. */
|
||||
if (a_exp != d_exp) {
|
||||
int adj_exp = d_exp - a_exp - 1;
|
||||
static grisu3_diy_fp_t cp_10_lut[] = {
|
||||
{ 0xa000000000000000ULL, -60 },
|
||||
{ 0xc800000000000000ULL, -57 },
|
||||
{ 0xfa00000000000000ULL, -54 },
|
||||
{ 0x9c40000000000000ULL, -50 },
|
||||
{ 0xc350000000000000ULL, -47 },
|
||||
{ 0xf424000000000000ULL, -44 },
|
||||
{ 0x9896800000000000ULL, -40 },
|
||||
};
|
||||
GRISU3_ASSERT(adj_exp >= 0 && adj_exp < 7);
|
||||
v = grisu3_diy_fp_multiply(v, cp_10_lut[adj_exp]);
|
||||
|
||||
/* 20 decimal digits won't always fit in 64 bit.
|
||||
* (`fraction_exp` is one less than significant decimal
|
||||
* digits in fraction, e.g. 1 * 10e0).
|
||||
* If we cannot fit, introduce 1/2 ulp error
|
||||
* (says double conversion reference impl.) */
|
||||
if (1 + fraction_exp + adj_exp > max_digits) {
|
||||
error += error_one / 2;
|
||||
}
|
||||
}
|
||||
|
||||
v = grisu3_diy_fp_multiply(v, cp);
|
||||
/*
|
||||
* Google double conversion claims that:
|
||||
*
|
||||
* The error introduced by a multiplication of a*b equals
|
||||
* error_a + error_b + error_a*error_b/2^64 + 0.5
|
||||
* Substituting a with 'input' and b with 'cached_power' we have
|
||||
* error_b = 0.5 (all cached powers have an error of less than 0.5 ulp),
|
||||
* error_ab = 0 or 1 / error_oner > error_a*error_b/ 2^64
|
||||
*
|
||||
* which in our encoding becomes:
|
||||
* error_a = error_one/2
|
||||
* error_ab = 1 / error_one (rounds up to 1 if error != 0, or 0 * otherwise)
|
||||
* fixed_error = error_one/2
|
||||
*
|
||||
* error += error_a + fixed_error + (error ? 1 : 0)
|
||||
*
|
||||
* (this isn't entirely clear, but that is as close as we get).
|
||||
*/
|
||||
error += error_one + (error ? 1 : 0);
|
||||
|
||||
o_exp = v.e;
|
||||
v = grisu3_diy_fp_normalize(v);
|
||||
/* Again, if we shift the significant bits, the error moves along. */
|
||||
error <<= o_exp - v.e;
|
||||
|
||||
/*
|
||||
* The value `v` is bounded by 2^mag which is 64 + v.e. because we
|
||||
* just normalized it by shifting towards msb.
|
||||
*/
|
||||
mag = diy_size + v.e;
|
||||
|
||||
/* The effective magnitude of the IEEE double representation. */
|
||||
mag = mag >= diy_size + denorm_exp ? diy_size : mag <= denorm_exp ? 0 : mag - denorm_exp;
|
||||
prec = diy_size - mag;
|
||||
if (prec + log2_error_one >= diy_size) {
|
||||
int e_scale = prec + log2_error_one - diy_size - 1;
|
||||
v.f >>= e_scale;
|
||||
v.e += e_scale;
|
||||
error = (error >> e_scale) + 1 + error_one;
|
||||
prec -= e_scale;
|
||||
}
|
||||
rounded.f = v.f >> prec;
|
||||
rounded.e = v.e + prec;
|
||||
prec_bits = (int)(v.f & ((uint64_t)1 << (prec - 1))) * error_one;
|
||||
half_way = (int)((uint64_t)1 << (prec - 1)) * error_one;
|
||||
if (prec >= half_way + error) {
|
||||
rounded.f++;
|
||||
/* Prevent overflow. */
|
||||
if (rounded.f & (hidden_bit << 1)) {
|
||||
rounded.f >>= 1;
|
||||
rounded.e += 1;
|
||||
}
|
||||
}
|
||||
*result = grisu3_cast_double_from_diy_fp(rounded);
|
||||
return half_way - error >= prec_bits || prec_bits >= half_way + error;
|
||||
}
|
||||
|
||||
/*
|
||||
* `end` is unchanged if number is handled natively, or it is the result
|
||||
* of strtod parsing in case of fallback.
|
||||
*/
|
||||
static const char *grisu3_encode_double(const char *buf, const char *end, int sign, uint64_t fraction, int exponent, int fraction_exp, int ulp_half_error, double *result)
|
||||
{
|
||||
const int max_d_exp = GRISU3_D64_MAX_DEC_EXP;
|
||||
const int min_d_exp = GRISU3_D64_MIN_DEC_EXP;
|
||||
|
||||
char *v_end;
|
||||
|
||||
/* Both for user experience, and to protect internal power table lookups. */
|
||||
if (fraction == 0 || exponent < min_d_exp) {
|
||||
*result = 0.0;
|
||||
goto done;
|
||||
}
|
||||
if (exponent - 1 > max_d_exp) {
|
||||
*result = grisu3_double_infinity;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* `exponent` is the normalized value, fraction_exp is the size of
|
||||
* the representation in the `fraction value`, or one less than
|
||||
* number of significant digits.
|
||||
*
|
||||
* If the final value can be kept in 53 bits and we can avoid
|
||||
* division, then we can convert to double quite fast.
|
||||
*
|
||||
* ulf_half_error only happens when fraction is maxed out, so
|
||||
* fraction_exp > 22 by definition.
|
||||
*
|
||||
* fraction_exp >= 0 always.
|
||||
*
|
||||
* http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
|
||||
*/
|
||||
|
||||
|
||||
#ifdef GRISU3_PARSE_FAST_CASE
|
||||
if (fraction < (1ULL << 53) && exponent >= 0 && exponent <= 22) {
|
||||
double v = (double)fraction;
|
||||
/* Multiplying by 1e-k instead of dividing by 1ek results in rounding error. */
|
||||
switch (exponent - fraction_exp) {
|
||||
case -22: v /= 1e22; break;
|
||||
case -21: v /= 1e21; break;
|
||||
case -20: v /= 1e20; break;
|
||||
case -19: v /= 1e19; break;
|
||||
case -18: v /= 1e18; break;
|
||||
case -17: v /= 1e17; break;
|
||||
case -16: v /= 1e16; break;
|
||||
case -15: v /= 1e15; break;
|
||||
case -14: v /= 1e14; break;
|
||||
case -13: v /= 1e13; break;
|
||||
case -12: v /= 1e12; break;
|
||||
case -11: v /= 1e11; break;
|
||||
case -10: v /= 1e10; break;
|
||||
case -9: v /= 1e9; break;
|
||||
case -8: v /= 1e8; break;
|
||||
case -7: v /= 1e7; break;
|
||||
case -6: v /= 1e6; break;
|
||||
case -5: v /= 1e5; break;
|
||||
case -4: v /= 1e4; break;
|
||||
case -3: v /= 1e3; break;
|
||||
case -2: v /= 1e2; break;
|
||||
case -1: v /= 1e1; break;
|
||||
case 0: break;
|
||||
case 1: v *= 1e1; break;
|
||||
case 2: v *= 1e2; break;
|
||||
case 3: v *= 1e3; break;
|
||||
case 4: v *= 1e4; break;
|
||||
case 5: v *= 1e5; break;
|
||||
case 6: v *= 1e6; break;
|
||||
case 7: v *= 1e7; break;
|
||||
case 8: v *= 1e8; break;
|
||||
case 9: v *= 1e9; break;
|
||||
case 10: v *= 1e10; break;
|
||||
case 11: v *= 1e11; break;
|
||||
case 12: v *= 1e12; break;
|
||||
case 13: v *= 1e13; break;
|
||||
case 14: v *= 1e14; break;
|
||||
case 15: v *= 1e15; break;
|
||||
case 16: v *= 1e16; break;
|
||||
case 17: v *= 1e17; break;
|
||||
case 18: v *= 1e18; break;
|
||||
case 19: v *= 1e19; break;
|
||||
case 20: v *= 1e20; break;
|
||||
case 21: v *= 1e21; break;
|
||||
case 22: v *= 1e22; break;
|
||||
}
|
||||
*result = v;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (grisu3_diy_fp_encode_double(fraction, exponent, fraction_exp, ulp_half_error, result)) {
|
||||
goto done;
|
||||
}
|
||||
#ifdef GRISU3_PARSE_ALLOW_ERROR
|
||||
goto done;
|
||||
#endif
|
||||
*result = strtod(buf, &v_end);
|
||||
if (v_end < end) {
|
||||
return v_end;
|
||||
}
|
||||
return end;
|
||||
done:
|
||||
if (sign) {
|
||||
*result = -*result;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns buf if number wasn't matched, or null if number starts ok
|
||||
* but contains invalid content.
|
||||
*/
|
||||
static const char *grisu3_parse_hex_fp(const char *buf, const char *end, int sign, double *result)
|
||||
{
|
||||
(void)buf;
|
||||
(void)end;
|
||||
(void)sign;
|
||||
*result = 0.0;
|
||||
/* Not currently supported. */
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns end pointer on success, or null, or buf if start is not a number.
|
||||
* Sets result to 0.0 on error.
|
||||
* Reads up to len + 1 bytes from buffer where len + 1 must not be a
|
||||
* valid part of a number, but all of buf, buf + len need not be a
|
||||
* number. Leading whitespace is NOT valid.
|
||||
* Very small numbers are truncated to +/-0.0 and numerically very large
|
||||
* numbers are returns as +/-infinity.
|
||||
*
|
||||
* A value must not end or begin with '.' (like JSON), but can have
|
||||
* leading zeroes (unlike JSON). A single leading zero followed by
|
||||
* an encoding symbol may or may not be interpreted as a non-decimal
|
||||
* encoding prefix, e.g. 0x, but a leading zero followed by a digit is
|
||||
* NOT interpreted as octal.
|
||||
* A single leading negative sign may appear before digits, but positive
|
||||
* sign is not allowed and space after the sign is not allowed.
|
||||
* At most the first 1000 characters of the input is considered.
|
||||
*/
|
||||
static const char *grisu3_parse_double(const char *buf, size_t len, double *result)
|
||||
{
|
||||
const char *mark, *k, *end;
|
||||
int sign = 0, esign = 0;
|
||||
uint64_t fraction = 0;
|
||||
int exponent = 0;
|
||||
int ee = 0;
|
||||
int fraction_exp = 0;
|
||||
int ulp_half_error = 0;
|
||||
|
||||
*result = 0.0;
|
||||
|
||||
end = buf + len + 1;
|
||||
|
||||
/* Failsafe for exponent overflow. */
|
||||
if (len > GRISU3_NUM_MAX_LEN) {
|
||||
end = buf + GRISU3_NUM_MAX_LEN + 1;
|
||||
}
|
||||
|
||||
if (buf == end) {
|
||||
return buf;
|
||||
}
|
||||
mark = buf;
|
||||
if (*buf == '-') {
|
||||
++buf;
|
||||
sign = 1;
|
||||
if (buf == end) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (*buf == '0') {
|
||||
++buf;
|
||||
/* | 0x20 is lower case ASCII. */
|
||||
if (buf != end && (*buf | 0x20) == 'x') {
|
||||
k = grisu3_parse_hex_fp(buf, end, sign, result);
|
||||
if (k == buf) {
|
||||
return mark;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
/* Not worthwhile, except for getting the scale of integer part. */
|
||||
while (buf != end && *buf == '0') {
|
||||
++buf;
|
||||
}
|
||||
} else {
|
||||
if (*buf < '1' || *buf > '9') {
|
||||
/*
|
||||
* If we didn't see a sign, just don't recognize it as
|
||||
* number, otherwise make it an error.
|
||||
*/
|
||||
return sign ? 0 : mark;
|
||||
}
|
||||
fraction = (uint64_t)(*buf++ - '0');
|
||||
}
|
||||
k = buf;
|
||||
/*
|
||||
* We do not catch trailing zeroes when there is no decimal point.
|
||||
* This misses an opportunity for moving the exponent down into the
|
||||
* fast case. But it is unlikely to be worthwhile as it complicates
|
||||
* parsing.
|
||||
*/
|
||||
while (buf != end && *buf >= '0' && *buf <= '9') {
|
||||
if (fraction >= UINT64_MAX / 10) {
|
||||
fraction += *buf >= '5';
|
||||
ulp_half_error = 1;
|
||||
break;
|
||||
}
|
||||
fraction = fraction * 10 + (uint64_t)(*buf++ - '0');
|
||||
}
|
||||
fraction_exp = (int)(buf - k);
|
||||
/* Skip surplus digits. Trailing zero does not introduce error. */
|
||||
while (buf != end && *buf == '0') {
|
||||
++exponent;
|
||||
++buf;
|
||||
}
|
||||
if (buf != end && *buf >= '1' && *buf <= '9') {
|
||||
ulp_half_error = 1;
|
||||
++exponent;
|
||||
++buf;
|
||||
while (buf != end && *buf >= '0' && *buf <= '9') {
|
||||
++exponent;
|
||||
++buf;
|
||||
}
|
||||
}
|
||||
if (buf != end && *buf == '.') {
|
||||
++buf;
|
||||
k = buf;
|
||||
if (*buf < '0' || *buf > '9') {
|
||||
/* We don't accept numbers without leading or trailing digit. */
|
||||
return 0;
|
||||
}
|
||||
while (buf != end && *buf >= '0' && *buf <= '9') {
|
||||
if (fraction >= UINT64_MAX / 10) {
|
||||
if (!ulp_half_error) {
|
||||
fraction += *buf >= '5';
|
||||
ulp_half_error = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
fraction = fraction * 10 + (uint64_t)(*buf++ - '0');
|
||||
--exponent;
|
||||
}
|
||||
fraction_exp += (int)(buf - k);
|
||||
while (buf != end && *buf == '0') {
|
||||
++exponent;
|
||||
++buf;
|
||||
}
|
||||
if (buf != end && *buf >= '1' && *buf <= '9') {
|
||||
ulp_half_error = 1;
|
||||
++buf;
|
||||
while (buf != end && *buf >= '0' && *buf <= '9') {
|
||||
++buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Normalized exponent e.g: 1.23434e3 with fraction = 123434,
|
||||
* fraction_exp = 5, exponent = 3.
|
||||
* So value = fraction * 10^(exponent - fraction_exp)
|
||||
*/
|
||||
exponent += fraction_exp;
|
||||
if (buf != end && (*buf | 0x20) == 'e') {
|
||||
if (end - buf < 2) {
|
||||
return 0;
|
||||
}
|
||||
++buf;
|
||||
if (*buf == '+') {
|
||||
++buf;
|
||||
if (buf == end) {
|
||||
return 0;
|
||||
}
|
||||
} else if (*buf == '-') {
|
||||
esign = 1;
|
||||
++buf;
|
||||
if (buf == end) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (*buf < '0' || *buf > '9') {
|
||||
return 0;
|
||||
}
|
||||
ee = *buf++ - '0';
|
||||
while (buf != end && *buf >= '0' && *buf <= '9') {
|
||||
/*
|
||||
* This test impacts performance and we do not need an
|
||||
* exact value just one large enough to dominate the fraction_exp.
|
||||
* Subsequent handling maps large absolute ee to 0 or infinity.
|
||||
*/
|
||||
if (ee <= 0x7fff) {
|
||||
ee = ee * 10 + *buf - '0';
|
||||
}
|
||||
++buf;
|
||||
}
|
||||
}
|
||||
exponent = exponent + (esign ? -ee : ee);
|
||||
|
||||
/*
|
||||
* Exponent is now a base 10 normalized exponent so the absolute value
|
||||
* is less the 10^(exponent + 1) for positive exponents. For
|
||||
* denormalized doubles (using 11 bit exponent 0 with a fraction
|
||||
* shiftet down, extra small numbers can be achieved.
|
||||
*
|
||||
* https://en.wikipedia.org/wiki/Double-precision_floating-point_format
|
||||
*
|
||||
* 10^-324 holds the smallest normalized exponent (but not value) and
|
||||
* 10^308 holds the largest exponent. Internally our lookup table is
|
||||
* only safe to use within a range slightly larger than this.
|
||||
* Externally, a slightly larger/smaller value represents NaNs which
|
||||
* are technically also possible to store as a number.
|
||||
*
|
||||
*/
|
||||
|
||||
/* This also protects strod fallback parsing. */
|
||||
if (buf == end) {
|
||||
return 0;
|
||||
}
|
||||
return grisu3_encode_double(mark, buf, sign, fraction, exponent, fraction_exp, ulp_half_error, result);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GRISU3_PARSE_H */
|
||||
265
nostrdb/flatcc/portable/grisu3_print.h
Normal file
265
nostrdb/flatcc/portable/grisu3_print.h
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Mikkel F. Jørgensen, dvide.com
|
||||
* Copyright author of MathGeoLib (https://github.com/juj)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License. http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extracted from MathGeoLib.
|
||||
*
|
||||
* mikkelfj:
|
||||
* - Fixed final output when printing single digit negative exponent to
|
||||
* have leading zero (important for JSON).
|
||||
* - Changed formatting to prefer 0.012 over 1.2-e-2.
|
||||
*
|
||||
* Large portions of the original grisu3.c file has been moved to
|
||||
* grisu3_math.h, the rest is placed here.
|
||||
*
|
||||
* See also comments in grisu3_math.h.
|
||||
*
|
||||
* MatGeoLib grisu3.c comment:
|
||||
*
|
||||
* This file is part of an implementation of the "grisu3" double to string
|
||||
* conversion algorithm described in the research paper
|
||||
*
|
||||
* "Printing Floating-Point Numbers Quickly And Accurately with Integers"
|
||||
* by Florian Loitsch, available at
|
||||
* http://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf
|
||||
*/
|
||||
|
||||
#ifndef GRISU3_PRINT_H
|
||||
#define GRISU3_PRINT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* sprintf, only needed for fallback printing */
|
||||
#include <assert.h> /* assert */
|
||||
|
||||
#include "grisu3_math.h"
|
||||
|
||||
/*
|
||||
* The lightweight "portable" C library recognizes grisu3 support if
|
||||
* included first.
|
||||
*/
|
||||
#define grisu3_print_double_is_defined 1
|
||||
|
||||
/*
|
||||
* Not sure we have an exact definition, but we get up to 23
|
||||
* emperically. There is some math ensuring it does not go awol though,
|
||||
* like 18 digits + exponent or so.
|
||||
* This max should be safe size buffer for printing, including zero term.
|
||||
*/
|
||||
#define GRISU3_PRINT_MAX 30
|
||||
|
||||
static int grisu3_round_weed(char *buffer, int len, uint64_t wp_W, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t ulp)
|
||||
{
|
||||
uint64_t wp_Wup = wp_W - ulp;
|
||||
uint64_t wp_Wdown = wp_W + ulp;
|
||||
while(rest < wp_Wup && delta - rest >= ten_kappa
|
||||
&& (rest + ten_kappa < wp_Wup || wp_Wup - rest >= rest + ten_kappa - wp_Wup))
|
||||
{
|
||||
--buffer[len-1];
|
||||
rest += ten_kappa;
|
||||
}
|
||||
if (rest < wp_Wdown && delta - rest >= ten_kappa
|
||||
&& (rest + ten_kappa < wp_Wdown || wp_Wdown - rest > rest + ten_kappa - wp_Wdown))
|
||||
return 0;
|
||||
|
||||
return 2*ulp <= rest && rest <= delta - 4*ulp;
|
||||
}
|
||||
|
||||
static int grisu3_digit_gen(grisu3_diy_fp_t low, grisu3_diy_fp_t w, grisu3_diy_fp_t high, char *buffer, int *length, int *kappa)
|
||||
{
|
||||
uint64_t unit = 1;
|
||||
grisu3_diy_fp_t too_low = { low.f - unit, low.e };
|
||||
grisu3_diy_fp_t too_high = { high.f + unit, high.e };
|
||||
grisu3_diy_fp_t unsafe_interval = grisu3_diy_fp_minus(too_high, too_low);
|
||||
grisu3_diy_fp_t one = { 1ULL << -w.e, w.e };
|
||||
uint32_t p1 = (uint32_t)(too_high.f >> -one.e);
|
||||
uint64_t p2 = too_high.f & (one.f - 1);
|
||||
uint32_t div;
|
||||
*kappa = grisu3_largest_pow10(p1, GRISU3_DIY_FP_FRACT_SIZE + one.e, &div);
|
||||
*length = 0;
|
||||
|
||||
while(*kappa > 0)
|
||||
{
|
||||
uint64_t rest;
|
||||
char digit = (char)(p1 / div);
|
||||
buffer[*length] = '0' + digit;
|
||||
++*length;
|
||||
p1 %= div;
|
||||
--*kappa;
|
||||
rest = ((uint64_t)p1 << -one.e) + p2;
|
||||
if (rest < unsafe_interval.f) return grisu3_round_weed(buffer, *length, grisu3_diy_fp_minus(too_high, w).f, unsafe_interval.f, rest, (uint64_t)div << -one.e, unit);
|
||||
div /= 10;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
char digit;
|
||||
p2 *= 10;
|
||||
unit *= 10;
|
||||
unsafe_interval.f *= 10;
|
||||
/* Integer division by one. */
|
||||
digit = (char)(p2 >> -one.e);
|
||||
buffer[*length] = '0' + digit;
|
||||
++*length;
|
||||
p2 &= one.f - 1; /* Modulo by one. */
|
||||
--*kappa;
|
||||
if (p2 < unsafe_interval.f) return grisu3_round_weed(buffer, *length, grisu3_diy_fp_minus(too_high, w).f * unit, unsafe_interval.f, p2, one.f, unit);
|
||||
}
|
||||
}
|
||||
|
||||
static int grisu3(double v, char *buffer, int *length, int *d_exp)
|
||||
{
|
||||
int mk, kappa, success;
|
||||
grisu3_diy_fp_t dfp = grisu3_cast_diy_fp_from_double(v);
|
||||
grisu3_diy_fp_t w = grisu3_diy_fp_normalize(dfp);
|
||||
|
||||
/* normalize boundaries */
|
||||
grisu3_diy_fp_t t = { (dfp.f << 1) + 1, dfp.e - 1 };
|
||||
grisu3_diy_fp_t b_plus = grisu3_diy_fp_normalize(t);
|
||||
grisu3_diy_fp_t b_minus;
|
||||
grisu3_diy_fp_t c_mk; /* Cached power of ten: 10^-k */
|
||||
uint64_t u64 = grisu3_cast_uint64_from_double(v);
|
||||
assert(v > 0 && v <= 1.7976931348623157e308); /* Grisu only handles strictly positive finite numbers. */
|
||||
if (!(u64 & GRISU3_D64_FRACT_MASK) && (u64 & GRISU3_D64_EXP_MASK) != 0) { b_minus.f = (dfp.f << 2) - 1; b_minus.e = dfp.e - 2;} /* lower boundary is closer? */
|
||||
else { b_minus.f = (dfp.f << 1) - 1; b_minus.e = dfp.e - 1; }
|
||||
b_minus.f = b_minus.f << (b_minus.e - b_plus.e);
|
||||
b_minus.e = b_plus.e;
|
||||
|
||||
mk = grisu3_diy_fp_cached_pow(GRISU3_MIN_TARGET_EXP - GRISU3_DIY_FP_FRACT_SIZE - w.e, &c_mk);
|
||||
|
||||
w = grisu3_diy_fp_multiply(w, c_mk);
|
||||
b_minus = grisu3_diy_fp_multiply(b_minus, c_mk);
|
||||
b_plus = grisu3_diy_fp_multiply(b_plus, c_mk);
|
||||
|
||||
success = grisu3_digit_gen(b_minus, w, b_plus, buffer, length, &kappa);
|
||||
*d_exp = kappa - mk;
|
||||
return success;
|
||||
}
|
||||
|
||||
static int grisu3_i_to_str(int val, char *str)
|
||||
{
|
||||
int len, i;
|
||||
char *s;
|
||||
char *begin = str;
|
||||
if (val < 0) { *str++ = '-'; val = -val; }
|
||||
s = str;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int ni = val / 10;
|
||||
int digit = val - ni*10;
|
||||
*s++ = (char)('0' + digit);
|
||||
if (ni == 0)
|
||||
break;
|
||||
val = ni;
|
||||
}
|
||||
*s = '\0';
|
||||
len = (int)(s - str);
|
||||
for(i = 0; i < len/2; ++i)
|
||||
{
|
||||
char ch = str[i];
|
||||
str[i] = str[len-1-i];
|
||||
str[len-1-i] = ch;
|
||||
}
|
||||
|
||||
return (int)(s - begin);
|
||||
}
|
||||
|
||||
static int grisu3_print_nan(uint64_t v, char *dst)
|
||||
{
|
||||
static char hexdigits[16] = "0123456789ABCDEF";
|
||||
int i = 0;
|
||||
|
||||
dst[0] = 'N';
|
||||
dst[1] = 'a';
|
||||
dst[2] = 'N';
|
||||
dst[3] = '(';
|
||||
dst[20] = ')';
|
||||
dst[21] = '\0';
|
||||
dst += 4;
|
||||
for (i = 15; i >= 0; --i) {
|
||||
dst[i] = hexdigits[v & 0x0F];
|
||||
v >>= 4;
|
||||
}
|
||||
return 21;
|
||||
}
|
||||
|
||||
static int grisu3_print_double(double v, char *dst)
|
||||
{
|
||||
int d_exp, len, success, decimals, i;
|
||||
uint64_t u64 = grisu3_cast_uint64_from_double(v);
|
||||
char *s2 = dst;
|
||||
assert(dst);
|
||||
|
||||
/* Prehandle NaNs */
|
||||
if ((u64 << 1) > 0xFFE0000000000000ULL) return grisu3_print_nan(u64, dst);
|
||||
/* Prehandle negative values. */
|
||||
if ((u64 & GRISU3_D64_SIGN) != 0) { *s2++ = '-'; v = -v; u64 ^= GRISU3_D64_SIGN; }
|
||||
/* Prehandle zero. */
|
||||
if (!u64) { *s2++ = '0'; *s2 = '\0'; return (int)(s2 - dst); }
|
||||
/* Prehandle infinity. */
|
||||
if (u64 == GRISU3_D64_EXP_MASK) { *s2++ = 'i'; *s2++ = 'n'; *s2++ = 'f'; *s2 = '\0'; return (int)(s2 - dst); }
|
||||
|
||||
success = grisu3(v, s2, &len, &d_exp);
|
||||
/* If grisu3 was not able to convert the number to a string, then use old sprintf (suboptimal). */
|
||||
if (!success) return sprintf(s2, "%.17g", v) + (int)(s2 - dst);
|
||||
|
||||
/* We now have an integer string of form "151324135" and a base-10 exponent for that number. */
|
||||
/* Next, decide the best presentation for that string by whether to use a decimal point, or the scientific exponent notation 'e'. */
|
||||
/* We don't pick the absolute shortest representation, but pick a balance between readability and shortness, e.g. */
|
||||
/* 1.545056189557677e-308 could be represented in a shorter form */
|
||||
/* 1545056189557677e-323 but that would be somewhat unreadable. */
|
||||
decimals = GRISU3_MIN(-d_exp, GRISU3_MAX(1, len-1));
|
||||
|
||||
/* mikkelfj:
|
||||
* fix zero prefix .1 => 0.1, important for JSON export.
|
||||
* prefer unscientific notation at same length:
|
||||
* -1.2345e-4 over -1.00012345,
|
||||
* -1.0012345 over -1.2345e-3
|
||||
*/
|
||||
if (d_exp < 0 && (len + d_exp) > -3 && len <= -d_exp)
|
||||
{
|
||||
/* mikkelfj: fix zero prefix .1 => 0.1, and short exponents 1.3e-2 => 0.013. */
|
||||
memmove(s2 + 2 - d_exp - len, s2, (size_t)len);
|
||||
s2[0] = '0';
|
||||
s2[1] = '.';
|
||||
for (i = 2; i < 2-d_exp-len; ++i) s2[i] = '0';
|
||||
len += i;
|
||||
}
|
||||
else if (d_exp < 0 && len > 1) /* Add decimal point? */
|
||||
{
|
||||
for(i = 0; i < decimals; ++i) s2[len-i] = s2[len-i-1];
|
||||
s2[len++ - decimals] = '.';
|
||||
d_exp += decimals;
|
||||
/* Need scientific notation as well? */
|
||||
if (d_exp != 0) { s2[len++] = 'e'; len += grisu3_i_to_str(d_exp, s2+len); }
|
||||
}
|
||||
/* Add scientific notation? */
|
||||
else if (d_exp < 0 || d_exp > 2) { s2[len++] = 'e'; len += grisu3_i_to_str(d_exp, s2+len); }
|
||||
/* Add zeroes instead of scientific notation? */
|
||||
else if (d_exp > 0) { while(d_exp-- > 0) s2[len++] = '0'; }
|
||||
s2[len] = '\0'; /* grisu3 doesn't null terminate, so ensure termination. */
|
||||
return (int)(s2+len-dst);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GRISU3_PRINT_H */
|
||||
4
nostrdb/flatcc/portable/include/README
Normal file
4
nostrdb/flatcc/portable/include/README
Normal file
@@ -0,0 +1,4 @@
|
||||
This directory holds subdirectories it can be added to the include path
|
||||
such that standard and OS specific header includes like <stdint.h>,
|
||||
<bool.h> and <endian.h> can succeed without explicitly including
|
||||
special headers explicitly.
|
||||
1
nostrdb/flatcc/portable/include/linux/endian.h
Normal file
1
nostrdb/flatcc/portable/include/linux/endian.h
Normal file
@@ -0,0 +1 @@
|
||||
#include "portable/pendian.h"
|
||||
1
nostrdb/flatcc/portable/include/std/inttypes.h
Normal file
1
nostrdb/flatcc/portable/include/std/inttypes.h
Normal file
@@ -0,0 +1 @@
|
||||
#include "portable/inttypes.h"
|
||||
1
nostrdb/flatcc/portable/include/std/stdalign.h
Normal file
1
nostrdb/flatcc/portable/include/std/stdalign.h
Normal file
@@ -0,0 +1 @@
|
||||
#include "portable/pstdalign.h"
|
||||
1
nostrdb/flatcc/portable/include/std/stdbool.h
Normal file
1
nostrdb/flatcc/portable/include/std/stdbool.h
Normal file
@@ -0,0 +1 @@
|
||||
#include "portable/pstdbool.h"
|
||||
1
nostrdb/flatcc/portable/include/std/stdint.h
Normal file
1
nostrdb/flatcc/portable/include/std/stdint.h
Normal file
@@ -0,0 +1 @@
|
||||
#include "portable/pstdint.h"
|
||||
210
nostrdb/flatcc/portable/paligned_alloc.h
Normal file
210
nostrdb/flatcc/portable/paligned_alloc.h
Normal file
@@ -0,0 +1,210 @@
|
||||
#ifndef PALIGNED_ALLOC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NOTE: MSVC in general has no aligned alloc function that is
|
||||
* compatible with free and it is not trivial to implement a version
|
||||
* which is. Therefore, to remain portable, end user code needs to
|
||||
* use `aligned_free` which is not part of C11 but defined in this header.
|
||||
*
|
||||
* glibc only provides aligned_alloc when _ISOC11_SOURCE is defined, but
|
||||
* MingW does not support aligned_alloc despite of this, it uses the
|
||||
* the _aligned_malloc as MSVC.
|
||||
*
|
||||
* The same issue is present on some Unix systems not providing
|
||||
* posix_memalign.
|
||||
*
|
||||
* Note that clang and gcc with -std=c11 or -std=c99 will not define
|
||||
* _POSIX_C_SOURCE and thus posix_memalign cannot be detected but
|
||||
* aligned_alloc is not necessarily available either. We assume
|
||||
* that clang always has posix_memalign although it is not strictly
|
||||
* correct. For gcc, use -std=gnu99 or -std=gnu11 or don't use -std in
|
||||
* order to enable posix_memalign, or live with the fallback until using
|
||||
* a system where glibc has a version that supports aligned_alloc.
|
||||
*
|
||||
* For C11 compliant compilers and compilers with posix_memalign,
|
||||
* it is valid to use free instead of aligned_free with the above
|
||||
* caveats.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Define this to see which version is used so the fallback is not
|
||||
* enganged unnecessarily:
|
||||
*
|
||||
* #define PORTABLE_DEBUG_ALIGNED_ALLOC
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#define PORTABLE_DEBUG_ALIGNED_ALLOC
|
||||
#endif
|
||||
|
||||
#if !defined(PORTABLE_C11_ALIGNED_ALLOC)
|
||||
|
||||
/*
|
||||
* PORTABLE_C11_ALIGNED_ALLOC = 1
|
||||
* indicates that the system has builtin aligned_alloc
|
||||
* If it doesn't, the section after detection provides an implemention.
|
||||
*/
|
||||
#if defined (__MINGW32__)
|
||||
/* MingW does not provide aligned_alloc despite defining _ISOC11_SOURCE */
|
||||
#define PORTABLE_C11_ALIGNED_ALLOC 0
|
||||
#elif defined (_ISOC11_SOURCE)
|
||||
/* glibc aligned_alloc detection, but MingW is not truthful */
|
||||
#define PORTABLE_C11_ALIGNED_ALLOC 1
|
||||
#elif defined (__GLIBC__)
|
||||
/* aligned_alloc is not available in glibc just because __STDC_VERSION__ >= 201112L. */
|
||||
#define PORTABLE_C11_ALIGNED_ALLOC 0
|
||||
#elif defined (__clang__)
|
||||
#define PORTABLE_C11_ALIGNED_ALLOC 0
|
||||
#elif defined(__IBMC__)
|
||||
#define PORTABLE_C11_ALIGNED_ALLOC 0
|
||||
#elif (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
|
||||
#define PORTABLE_C11_ALIGNED_ALLOC 1
|
||||
#else
|
||||
#define PORTABLE_C11_ALIGNED_ALLOC 0
|
||||
#endif
|
||||
|
||||
#endif /* PORTABLE_C11_ALIGNED_ALLOC */
|
||||
|
||||
/* https://linux.die.net/man/3/posix_memalign */
|
||||
#if !defined(PORTABLE_POSIX_MEMALIGN) && defined(_GNU_SOURCE)
|
||||
#define PORTABLE_POSIX_MEMALIGN 1
|
||||
#endif
|
||||
|
||||
/* https://forum.kde.org/viewtopic.php?p=66274 */
|
||||
#if !defined(PORTABLE_POSIX_MEMALIGN) && defined(_XOPEN_SOURCE)
|
||||
#if _XOPEN_SOURCE >= 600
|
||||
#define PORTABLE_POSIX_MEMALIGN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(PORTABLE_POSIX_MEMALIGN) && defined(_POSIX_C_SOURCE)
|
||||
#if _POSIX_C_SOURCE >= 200112L
|
||||
#define PORTABLE_POSIX_MEMALIGN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(PORTABLE_POSIX_MEMALIGN) && defined(__clang__)
|
||||
#define PORTABLE_POSIX_MEMALIGN 1
|
||||
#endif
|
||||
|
||||
#if !defined(PORTABLE_POSIX_MEMALIGN)
|
||||
#define PORTABLE_POSIX_MEMALIGN 0
|
||||
#endif
|
||||
|
||||
/* https://forum.kde.org/viewtopic.php?p=66274 */
|
||||
#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
|
||||
/* C11 or newer */
|
||||
#include <stdalign.h>
|
||||
#endif
|
||||
|
||||
/* C11 or newer */
|
||||
#if !defined(aligned_alloc) && !defined(__aligned_alloc_is_defined)
|
||||
|
||||
#if PORTABLE_C11_ALIGNED_ALLOC
|
||||
#ifdef PORTABLE_DEBUG_ALIGNED_ALLOC
|
||||
#error "DEBUG: C11_ALIGNED_ALLOC configured"
|
||||
#endif
|
||||
#elif defined(_MSC_VER) || defined(__MINGW32__)
|
||||
|
||||
#ifdef PORTABLE_DEBUG_ALIGNED_ALLOC
|
||||
#error "DEBUG: Windows _aligned_malloc configured"
|
||||
#endif
|
||||
|
||||
/* Aligned _aligned_malloc is not compatible with free. */
|
||||
#define aligned_alloc(alignment, size) _aligned_malloc(size, alignment)
|
||||
#define aligned_free(p) _aligned_free(p)
|
||||
#define __aligned_alloc_is_defined 1
|
||||
#define __aligned_free_is_defined 1
|
||||
|
||||
#elif PORTABLE_POSIX_MEMALIGN
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if !defined(__GNUCC__)
|
||||
extern int posix_memalign (void **, size_t, size_t);
|
||||
#elif __GNUCC__ < 5
|
||||
extern int posix_memalign (void **, size_t, size_t);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline void *__portable_aligned_alloc(size_t alignment, size_t size)
|
||||
{
|
||||
int err;
|
||||
void *p = 0;
|
||||
|
||||
if (alignment < sizeof(void *)) {
|
||||
alignment = sizeof(void *);
|
||||
}
|
||||
err = posix_memalign(&p, alignment, size);
|
||||
if (err && p) {
|
||||
free(p);
|
||||
p = 0;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
#ifdef PORTABLE_DEBUG_ALIGNED_ALLOC
|
||||
#error "DEBUG: POSIX_MEMALIGN configured"
|
||||
#endif
|
||||
|
||||
#define aligned_alloc(alignment, size) __portable_aligned_alloc(alignment, size)
|
||||
#define aligned_free(p) free(p)
|
||||
#define __aligned_alloc_is_defined 1
|
||||
#define __aligned_free_is_defined 1
|
||||
|
||||
#else
|
||||
|
||||
static inline void *__portable_aligned_alloc(size_t alignment, size_t size)
|
||||
{
|
||||
char *raw;
|
||||
void *buf;
|
||||
size_t total_size = (size + alignment - 1 + sizeof(void *));
|
||||
|
||||
if (alignment < sizeof(void *)) {
|
||||
alignment = sizeof(void *);
|
||||
}
|
||||
raw = (char *)(size_t)malloc(total_size);
|
||||
buf = raw + alignment - 1 + sizeof(void *);
|
||||
buf = (void *)(((size_t)buf) & ~(alignment - 1));
|
||||
((void **)buf)[-1] = raw;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline void __portable_aligned_free(void *p)
|
||||
{
|
||||
char *raw;
|
||||
|
||||
if (p) {
|
||||
raw = (char*)((void **)p)[-1];
|
||||
free(raw);
|
||||
}
|
||||
}
|
||||
|
||||
#define aligned_alloc(alignment, size) __portable_aligned_alloc(alignment, size)
|
||||
#define aligned_free(p) __portable_aligned_free(p)
|
||||
#define __aligned_alloc_is_defined 1
|
||||
#define __aligned_free_is_defined 1
|
||||
|
||||
#ifdef PORTABLE_DEBUG_ALIGNED_ALLOC
|
||||
#error "DEBUG: aligned_alloc malloc fallback configured"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* aligned_alloc */
|
||||
|
||||
#if !defined(aligned_free) && !defined(__aligned_free_is_defined)
|
||||
#define aligned_free(p) free(p)
|
||||
#define __aligned_free_is_defined 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PALIGNED_ALLOC_H */
|
||||
84
nostrdb/flatcc/portable/pattributes.h
Normal file
84
nostrdb/flatcc/portable/pattributes.h
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
/*
|
||||
* C23 introduces an attribute syntax `[[<attribute>]]`. Prior to that
|
||||
* other non-standard syntaxes such as `__attribute__((<attribute>))`
|
||||
* and `__declspec(<attribute>)` have been supported by some compiler
|
||||
* versions.
|
||||
*
|
||||
* See also:
|
||||
* https://en.cppreference.com/w/c/language/attributes
|
||||
*
|
||||
* There is no portable way to use C23 attributes in older C standards
|
||||
* so in order to use these portably, some macro name needs to be
|
||||
* defined for each attribute that either maps to the older supported
|
||||
* syntax, or ignores the attribute as appropriate.
|
||||
*
|
||||
* The Linux kernel defines certain attributes as macros, such as
|
||||
* `fallthrough`. When adding attributes it seems reasonable to follow
|
||||
* the Linux conventions in lack of any official standard. However, it
|
||||
* is not the intention that this file should mirror the Linux
|
||||
* attributes 1 to 1.
|
||||
*
|
||||
* See also:
|
||||
* https://github.com/torvalds/linux/blob/master/include/linux/compiler_attributes.h
|
||||
*
|
||||
* There is a risk that exposed attribute names may lead to name
|
||||
* conflicts. A conflicting name can be undefined and if necessary used
|
||||
* using `pattribute(<attribute>)`. All attributes can be hidden by
|
||||
* defining `PORTABLE_EXPOSE_ATTRIBUTES=0` in which case
|
||||
* `pattribute(<attribute>)` can still be used and then if a specific
|
||||
* attribute name still needs to be exposed, it can be defined manually
|
||||
* like `#define fallthrough pattribute(fallthrough)`.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PATTRIBUTES_H
|
||||
#define PATTRIBUTES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef PORTABLE_EXPOSE_ATTRIBUTES
|
||||
#define PORTABLE_EXPOSE_ATTRIBUTES 1
|
||||
#endif
|
||||
|
||||
#ifdef __has_c_attribute
|
||||
# define PORTABLE_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
|
||||
#else
|
||||
# define PORTABLE_HAS_C_ATTRIBUTE(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef __has_attribute
|
||||
# define PORTABLE_HAS_ATTRIBUTE(x) __has_attribute(x)
|
||||
#else
|
||||
# define PORTABLE_HAS_ATTRIBUTE(x) 0
|
||||
#endif
|
||||
|
||||
|
||||
/* https://en.cppreference.com/w/c/language/attributes/fallthrough */
|
||||
#if PORTABLE_HAS_C_ATTRIBUTE(__fallthrough__)
|
||||
# define pattribute_fallthrough [[__fallthrough__]]
|
||||
#elif PORTABLE_HAS_ATTRIBUTE(__fallthrough__)
|
||||
# define pattribute_fallthrough __attribute__((__fallthrough__))
|
||||
#else
|
||||
# define pattribute_fallthrough ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
#define pattribute(x) pattribute_##x
|
||||
|
||||
#if PORTABLE_EXPOSE_ATTRIBUTES
|
||||
|
||||
#ifndef fallthrough
|
||||
# define fallthrough pattribute(fallthrough)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PATTRIBUTES_H */
|
||||
448
nostrdb/flatcc/portable/pbase64.h
Normal file
448
nostrdb/flatcc/portable/pbase64.h
Normal file
@@ -0,0 +1,448 @@
|
||||
#ifndef PBASE64_H
|
||||
#define PBASE64_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Guarded to allow inclusion of pstdint.h first, if stdint.h is not supported. */
|
||||
#ifndef UINT8_MAX
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define BASE64_EOK 0
|
||||
/* 0 or mure full blocks decoded, remaining content may be parsed with fresh buffer. */
|
||||
#define BASE64_EMORE 1
|
||||
/* The `src_len` argument is required when encoding. */
|
||||
#define BASE64_EARGS 2
|
||||
/* Unsupported mode, or modifier not supported by mode when encoding. */
|
||||
#define BASE64_EMODE 3
|
||||
/* Decoding ends at invalid tail length - either by source length or by non-alphabet symbol. */
|
||||
#define BASE64_ETAIL 4
|
||||
/* Decoding ends at valid tail length but last byte has non-zero bits where it shouldn't have. */
|
||||
#define BASE64_EDIRTY 5
|
||||
|
||||
static inline const char *base64_strerror(int err);
|
||||
|
||||
/* All codecs are URL safe. Only Crockford allow for non-canocical decoding. */
|
||||
enum {
|
||||
/* Most common base64 codec, but not url friendly. */
|
||||
base64_mode_rfc4648 = 0,
|
||||
|
||||
/* URL safe version, '+' -> '-', '/' -> '_'. */
|
||||
base64_mode_url = 1,
|
||||
|
||||
/*
|
||||
* Skip ' ', '\r', and '\n' - we do not allow tab because common
|
||||
* uses of base64 such as PEM do not allow tab.
|
||||
*/
|
||||
base64_dec_modifier_skipspace = 32,
|
||||
|
||||
/* Padding is excluded by default. Not allowed for zbase64. */
|
||||
base64_enc_modifier_padding = 128,
|
||||
|
||||
/* For internal use or to decide codec of mode. */
|
||||
base64_modifier_mask = 32 + 64 + 128,
|
||||
};
|
||||
|
||||
/* Encoded size with or without padding. */
|
||||
static inline size_t base64_encoded_size(size_t len, int mode);
|
||||
|
||||
/*
|
||||
* Decoded size assuming no padding.
|
||||
* If `len` does include padding, the actual size may be less
|
||||
* when decoding, but never more.
|
||||
*/
|
||||
static inline size_t base64_decoded_size(size_t len);
|
||||
|
||||
/*
|
||||
* `dst` must hold ceil(len * 4 / 3) bytes.
|
||||
* `src_len` points to length of source and is updated with length of
|
||||
* parse on both success and failure. If `dst_len` is not null
|
||||
* it is used to store resulting output lengt withh length of decoded
|
||||
* output on both success and failure.
|
||||
* If `hyphen` is non-zero a hyphen is encoded every `hyphen` output bytes.
|
||||
* `mode` selects encoding alphabet defaulting to Crockfords base64.
|
||||
* Returns 0 on success.
|
||||
*
|
||||
* A terminal space can be added with `dst[dst_len++] = ' '` after the
|
||||
* encode call. All non-alphabet can be used as terminators except the
|
||||
* padding character '='. The following characters will work as
|
||||
* terminator for all modes: { '\0', '\n', ' ', '\t' }. A terminator is
|
||||
* optional when the source length is given to the decoder. Note that
|
||||
* crockford also reserves a few extra characters for checksum but the
|
||||
* checksum must be separate from the main buffer and is not supported
|
||||
* by this library.
|
||||
*/
|
||||
static inline int base64_encode(uint8_t *dst, const uint8_t *src, size_t *dst_len, size_t *src_len, int mode);
|
||||
|
||||
/*
|
||||
* Decodes according to mode while ignoring encoding modifiers.
|
||||
* `src_len` and `dst_len` are optional pointers. If `src_len` is set it
|
||||
* must contain the length of the input, otherwise the input must be
|
||||
* terminated with a non-alphabet character or valid padding (a single
|
||||
* padding character is accepted) - if the src_len output is needed but
|
||||
* not the input due to guaranteed termination, then set it to
|
||||
* (size_t)-1. `dst_len` must contain length of output buffer if present
|
||||
* and parse will fail with BASE64_EMORE after decoding a block multiple
|
||||
* if dst_len is exhausted - the parse can thus be resumed after
|
||||
* draining destination. `src_len` and `dst_len` are updated with parsed
|
||||
* and decoded length, when present, on both success and failure.
|
||||
* Returns 0 on success. Invalid characters are not considered errors -
|
||||
* they simply terminate the parse, however, if the termination is not
|
||||
* at a block multiple or a valid partial block length then BASE64_ETAIL
|
||||
* without output holding the last full block, if any. BASE64_ETAIL is also
|
||||
* returned if the a valid length holds non-zero unused tail bits.
|
||||
*/
|
||||
static inline int base64_decode(uint8_t *dst, const uint8_t *src, size_t *dst_len, size_t *src_len, int mode);
|
||||
|
||||
static inline const char *base64_strerror(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case BASE64_EOK: return "ok";
|
||||
case BASE64_EARGS: return "invalid argument";
|
||||
case BASE64_EMODE: return "invalid mode";
|
||||
case BASE64_EMORE: return "destination full";
|
||||
case BASE64_ETAIL: return "invalid tail length";
|
||||
case BASE64_EDIRTY: return "invalid tail content";
|
||||
default: return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
static inline size_t base64_encoded_size(size_t len, int mode)
|
||||
{
|
||||
size_t k = len % 3;
|
||||
size_t n = (len * 4 / 3 + 3) & ~(size_t)3;
|
||||
int pad = mode & base64_enc_modifier_padding;
|
||||
|
||||
if (!pad) {
|
||||
switch (k) {
|
||||
case 2:
|
||||
n -= 1;
|
||||
break;
|
||||
case 1:
|
||||
n -= 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline size_t base64_decoded_size(size_t len)
|
||||
{
|
||||
size_t k = len % 4;
|
||||
size_t n = len / 4 * 3;
|
||||
|
||||
switch (k) {
|
||||
case 3:
|
||||
return n + 2;
|
||||
case 2:
|
||||
return n + 1;
|
||||
case 1: /* Not valid without padding. */
|
||||
case 0:
|
||||
default:
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int base64_encode(uint8_t *dst, const uint8_t *src, size_t *dst_len, size_t *src_len, int mode)
|
||||
{
|
||||
const uint8_t *rfc4648_alphabet = (const uint8_t *)
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
const uint8_t *url_alphabet = (const uint8_t *)
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
|
||||
const uint8_t *T;
|
||||
uint8_t *dst_base = dst;
|
||||
int pad = mode & base64_enc_modifier_padding;
|
||||
size_t len = 0;
|
||||
int ret = BASE64_EMODE;
|
||||
|
||||
if (!src_len) {
|
||||
ret = BASE64_EARGS;
|
||||
goto done;
|
||||
}
|
||||
len = *src_len;
|
||||
mode = mode & ~base64_modifier_mask;
|
||||
switch (mode) {
|
||||
case base64_mode_rfc4648:
|
||||
T = rfc4648_alphabet;
|
||||
break;
|
||||
case base64_mode_url:
|
||||
T = url_alphabet;
|
||||
break;
|
||||
default:
|
||||
/* Invalid mode. */
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = BASE64_EOK;
|
||||
|
||||
/* Encodes 4 destination bytes from 3 source bytes. */
|
||||
while (len >= 3) {
|
||||
dst[0] = T[((src[0] >> 2))];
|
||||
dst[1] = T[((src[0] << 4) & 0x30) | (src[1] >> 4)];
|
||||
dst[2] = T[((src[1] << 2) & 0x3c) | (src[2] >> 6)];
|
||||
dst[3] = T[((src[2] & 0x3f))];
|
||||
len -= 3;
|
||||
dst += 4;
|
||||
src += 3;
|
||||
}
|
||||
/* Encodes 8 destination bytes from 1 to 4 source bytes, if any. */
|
||||
switch(len) {
|
||||
case 2:
|
||||
dst[0] = T[((src[0] >> 2))];
|
||||
dst[1] = T[((src[0] << 4) & 0x30) | (src[1] >> 4)];
|
||||
dst[2] = T[((src[1] << 2) & 0x3c)];
|
||||
dst += 3;
|
||||
if (pad) {
|
||||
*dst++ = '=';
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
dst[0] = T[((src[0] >> 2))];
|
||||
dst[1] = T[((src[0] << 4) & 0x30)];
|
||||
dst += 2;
|
||||
if (pad) {
|
||||
*dst++ = '=';
|
||||
*dst++ = '=';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pad = 0;
|
||||
break;
|
||||
}
|
||||
len = 0;
|
||||
done:
|
||||
if (dst_len) {
|
||||
*dst_len = (size_t)(dst - dst_base);
|
||||
}
|
||||
if (src_len) {
|
||||
*src_len -= len;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int base64_decode(uint8_t *dst, const uint8_t *src, size_t *dst_len, size_t *src_len, int mode)
|
||||
{
|
||||
static const uint8_t cinvalid = 64;
|
||||
static const uint8_t cignore = 65;
|
||||
static const uint8_t cpadding = 66;
|
||||
|
||||
/*
|
||||
* 0..63: 6-bit encoded value.
|
||||
* 64: flags non-alphabet symbols.
|
||||
* 65: codes for ignored symbols.
|
||||
* 66: codes for pad symbol '='.
|
||||
* All codecs consider padding an optional terminator and if present
|
||||
* consumes as many pad bytes as possible up to block termination,
|
||||
* but does not fail if a block is not full.
|
||||
*
|
||||
* We do not currently have any ignored characters but we might
|
||||
* add spaces as per MIME spec, but assuming spaces only happen
|
||||
* at block boundaries this is probalby better handled by repeated
|
||||
* parsing.
|
||||
*/
|
||||
static const uint8_t base64rfc4648_decode[256] = {
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 66, 64, 64,
|
||||
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
|
||||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
||||
};
|
||||
|
||||
static const uint8_t base64url_decode[256] = {
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 66, 64, 64,
|
||||
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 63,
|
||||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
||||
};
|
||||
|
||||
static const uint8_t base64rfc4648_decode_skipspace[256] = {
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 64, 64, 65, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
65, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 66, 64, 64,
|
||||
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
|
||||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
||||
};
|
||||
|
||||
static const uint8_t base64url_decode_skipspace[256] = {
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 64, 64, 65, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
65, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 66, 64, 64,
|
||||
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 63,
|
||||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
||||
};
|
||||
|
||||
int ret = BASE64_EOK;
|
||||
size_t i, k;
|
||||
uint8_t hold[4];
|
||||
uint8_t *dst_base = dst;
|
||||
size_t limit = (size_t)-1;
|
||||
size_t len = (size_t)-1, mark;
|
||||
const uint8_t *T = base64rfc4648_decode;
|
||||
int skipspace = mode & base64_dec_modifier_skipspace;
|
||||
|
||||
if (src_len) {
|
||||
len = *src_len;
|
||||
}
|
||||
mark = len;
|
||||
mode = mode & ~base64_modifier_mask;
|
||||
switch (mode) {
|
||||
case base64_mode_rfc4648:
|
||||
T = skipspace ? base64rfc4648_decode_skipspace : base64rfc4648_decode;
|
||||
break;
|
||||
case base64_mode_url:
|
||||
T = skipspace ? base64url_decode_skipspace : base64url_decode;
|
||||
break;
|
||||
default:
|
||||
ret = BASE64_EMODE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (dst_len && *dst_len > 0) {
|
||||
limit = *dst_len;
|
||||
}
|
||||
while(limit > 0) {
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (len == i) {
|
||||
k = i;
|
||||
len -= i;
|
||||
goto tail;
|
||||
}
|
||||
if ((hold[i] = T[src[i]]) >= cinvalid) {
|
||||
if (hold[i] == cignore) {
|
||||
++src;
|
||||
--len;
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
k = i;
|
||||
/* Strip padding and ignore hyphen in padding, if present. */
|
||||
if (hold[i] == cpadding) {
|
||||
++i;
|
||||
while (i < len && i < 8) {
|
||||
if (T[src[i]] != cpadding && T[src[i]] != cignore) {
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
len -= i;
|
||||
goto tail;
|
||||
}
|
||||
}
|
||||
if (limit < 3) {
|
||||
goto more;
|
||||
}
|
||||
dst[0] = (uint8_t)((hold[0] << 2) | (hold[1] >> 4));
|
||||
dst[1] = (uint8_t)((hold[1] << 4) | (hold[2] >> 2));
|
||||
dst[2] = (uint8_t)((hold[2] << 6) | (hold[3]));
|
||||
dst += 3;
|
||||
src += 4;
|
||||
limit -= 3;
|
||||
len -= 4;
|
||||
mark = len;
|
||||
}
|
||||
done:
|
||||
if (dst_len) {
|
||||
*dst_len = (size_t)(dst - dst_base);
|
||||
}
|
||||
if (src_len) {
|
||||
*src_len -= mark;
|
||||
}
|
||||
return ret;
|
||||
|
||||
tail:
|
||||
switch (k) {
|
||||
case 0:
|
||||
break;
|
||||
case 2:
|
||||
if ((hold[1] << 4) & 0xff) {
|
||||
goto dirty;
|
||||
}
|
||||
if (limit < 1) {
|
||||
goto more;
|
||||
}
|
||||
dst[0] = (uint8_t)((hold[0] << 2) | (hold[1] >> 4));
|
||||
dst += 1;
|
||||
break;
|
||||
case 3:
|
||||
if ((hold[2] << 6) & 0xff) {
|
||||
goto dirty;
|
||||
}
|
||||
if (limit < 2) {
|
||||
goto more;
|
||||
}
|
||||
dst[0] = (uint8_t)((hold[0] << 2) | (hold[1] >> 4));
|
||||
dst[1] = (uint8_t)((hold[1] << 4) | (hold[2] >> 2));
|
||||
dst += 2;
|
||||
break;
|
||||
default:
|
||||
ret = BASE64_ETAIL;
|
||||
goto done;
|
||||
}
|
||||
mark = len;
|
||||
goto done;
|
||||
dirty:
|
||||
ret = BASE64_EDIRTY;
|
||||
goto done;
|
||||
more:
|
||||
ret = BASE64_EMORE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PBASE64_H */
|
||||
48
nostrdb/flatcc/portable/pcrt.h
Normal file
48
nostrdb/flatcc/portable/pcrt.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef PCRT_H
|
||||
#define PCRT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Assertions and pointer violations in debug mode may trigger a dialog
|
||||
* on Windows. When running headless this is not helpful, but
|
||||
* unfortunately it cannot be disabled with a compiler option so code
|
||||
* must be injected into the runtime early in the main function.
|
||||
* A call to the provided `init_headless_crt()` macro does this in
|
||||
* a portable manner.
|
||||
*
|
||||
* See also:
|
||||
* https://stackoverflow.com/questions/13943665/how-can-i-disable-the-debug-assertion-dialog-on-windows
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <crtdbg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int _portable_msvc_headless_report_hook(int reportType, char *message, int *returnValue)
|
||||
{
|
||||
fprintf(stderr, "CRT[%d]: %s\n", reportType, message);
|
||||
*returnValue = 1;
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define init_headless_crt() _CrtSetReportHook(_portable_msvc_headless_report_hook)
|
||||
|
||||
#else
|
||||
|
||||
#define init_headless_crt() ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PCRT_H */
|
||||
85
nostrdb/flatcc/portable/pdiagnostic.h
Normal file
85
nostrdb/flatcc/portable/pdiagnostic.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* There is intentionally no include guard in this file. */
|
||||
|
||||
|
||||
/*
|
||||
* Usage: optionally disable any of these before including.
|
||||
*
|
||||
* #define PDIAGNOSTIC_IGNORE_UNUSED_FUNCTION
|
||||
* #define PDIAGNOSTIC_IGNORE_UNUSED_VARIABLE
|
||||
* #define PDIAGNOSTIC_IGNORE_UNUSED_PARAMETER
|
||||
* #define PDIAGNOSTIC_IGNORE_UNUSED // all of the above
|
||||
*
|
||||
* #include "pdiagnostic.h"
|
||||
*
|
||||
* Alternatively use #include "pdiagnostic_push/pop.h"
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4668) /* preprocessor name not defined */
|
||||
#endif
|
||||
|
||||
#if !defined(PDIAGNOSTIC_AWARE_MSVC) && defined(_MSC_VER)
|
||||
#define PDIAGNOSTIC_AWARE_MSVC 1
|
||||
#elif !defined(PDIAGNOSTIC_AWARE_MSVC)
|
||||
#define PDIAGNOSTIC_AWARE_MSVC 0
|
||||
#endif
|
||||
|
||||
#if !defined(PDIAGNOSTIC_AWARE_CLANG) && defined(__clang__)
|
||||
#define PDIAGNOSTIC_AWARE_CLANG 1
|
||||
#elif !defined(PDIAGNOSTIC_AWARE_CLANG)
|
||||
#define PDIAGNOSTIC_AWARE_CLANG 0
|
||||
#endif
|
||||
|
||||
#if !defined(PDIAGNOSTIC_AWARE_GCC) && defined(__GNUC__) && !defined(__clang__)
|
||||
/* Can disable some warnings even if push is not available (gcc-4.2 vs gcc-4.7) */
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
|
||||
#define PDIAGNOSTIC_AWARE_GCC 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(PDIAGNOSTIC_AWARE_GCC)
|
||||
#define PDIAGNOSTIC_AWARE_GCC 0
|
||||
#endif
|
||||
|
||||
#if defined(PDIAGNOSTIC_IGNORE_UNUSED_FUNCTION) || defined(PDIAGNOSTIC_IGNORE_UNUSED)
|
||||
#if PDIAGNOSTIC_AWARE_CLANG
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
#elif PDIAGNOSTIC_AWARE_GCC
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
#endif
|
||||
#undef PDIAGNOSTIC_IGNORE_UNUSED_FUNCTION
|
||||
|
||||
#if defined(PDIAGNOSTIC_IGNORE_UNUSED_VARIABLE) || defined(PDIAGNOSTIC_IGNORE_UNUSED)
|
||||
#if PDIAGNOSTIC_AWARE_MSVC
|
||||
#pragma warning(disable: 4101) /* unused local variable */
|
||||
#elif PDIAGNOSTIC_AWARE_CLANG
|
||||
#pragma clang diagnostic ignored "-Wunused-variable"
|
||||
#elif PDIAGNOSTIC_AWARE_GCC
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#endif
|
||||
#endif
|
||||
#undef PDIAGNOSTIC_IGNORE_UNUSED_VARIABLE
|
||||
|
||||
#if defined(PDIAGNOSTIC_IGNORE_UNUSED_PARAMETER) || defined(PDIAGNOSTIC_IGNORE_UNUSED)
|
||||
#if PDIAGNOSTIC_AWARE_CLANG
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
#elif PDIAGNOSTIC_AWARE_GCC
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
#endif
|
||||
#undef PDIAGNOSTIC_IGNORE_UNUSED_PARAMETER
|
||||
|
||||
#undef PDIAGNOSTIC_IGNORE_UNUSED
|
||||
|
||||
#if defined (__cplusplus) && __cplusplus < 201103L
|
||||
#if PDIAGNOSTIC_AWARE_CLANG
|
||||
/* Needed for < C++11 clang C++ static_assert */
|
||||
#pragma clang diagnostic ignored "-Wc11-extensions"
|
||||
/* Needed for empty macro arguments. */
|
||||
#pragma clang diagnostic ignored "-Wc99-extensions"
|
||||
/* Needed for trailing commas. */
|
||||
#pragma clang diagnostic ignored "-Wc++11-extensions"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
20
nostrdb/flatcc/portable/pdiagnostic_pop.h
Normal file
20
nostrdb/flatcc/portable/pdiagnostic_pop.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#if defined(PDIAGNOSTIC_PUSHED_MSVC)
|
||||
#if PDIAGNOSTIC_PUSHED_MSVC
|
||||
#pragma warning( pop )
|
||||
#endif // PDIAGNOSTIC_PUSHED_MSVC
|
||||
#undef PDIAGNOSTIC_PUSHED_MSVC
|
||||
#endif // defined(PDIAGNOSTIC_PUSHED_MSVC)
|
||||
|
||||
#if defined(PDIAGNOSTIC_PUSHED_CLANG)
|
||||
#if PDIAGNOSTIC_PUSHED_CLANG
|
||||
#pragma clang diagnostic pop
|
||||
#endif // PDIAGNOSTIC_PUSHED_CLANG
|
||||
#undef PDIAGNOSTIC_PUSHED_CLANG
|
||||
#endif // defined(PDIAGNOSTIC_PUSHED_CLANG)
|
||||
|
||||
#if defined(PDIAGNOSTIC_PUSHED_GCC)
|
||||
#if PDIAGNOSTIC_PUSHED_GCC
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // PDIAGNOSTIC_PUSHED_GCC
|
||||
#undef PDIAGNOSTIC_PUSHED_GCC
|
||||
#endif // defined(PDIAGNOSTIC_PUSHED_GCC)
|
||||
51
nostrdb/flatcc/portable/pdiagnostic_push.h
Normal file
51
nostrdb/flatcc/portable/pdiagnostic_push.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* See also comment in "pdiagnostic.h"
|
||||
*
|
||||
* e.g.
|
||||
* #define PDIAGNOSTIC_IGNORE_USED_FUNCTION
|
||||
* #define PDIAGNOSTIC_IGNORE_USED_VARIABLE
|
||||
* #include "pdiagnostic_push"
|
||||
* ...
|
||||
* #include "pdiagnostic_pop.h"
|
||||
* <eof>
|
||||
*
|
||||
* or if push pop isn't desired:
|
||||
* #define PDIAGNOSTIC_IGNORE_USED_FUNCTION
|
||||
* #define PDIAGNOSTIC_IGNORE_USED_VARIABLE
|
||||
* #include "pdiagnostic.h"
|
||||
* ...
|
||||
* <eof>
|
||||
*
|
||||
*
|
||||
* Some if these warnings cannot be ignored
|
||||
* at the #pragma level, but might in the future.
|
||||
* Use compiler switches like -Wno-unused-function
|
||||
* to work around this.
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( push )
|
||||
#define PDIAGNOSTIC_PUSHED_MSVC 1
|
||||
#else
|
||||
#define PDIAGNOSTIC_PUSHED_MSVC 0
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#define PDIAGNOSTIC_PUSHED_CLANG 1
|
||||
#else
|
||||
#define PDIAGNOSTIC_PUSHED_CLANG 0
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
||||
#pragma GCC diagnostic push
|
||||
#define PDIAGNOSTIC_PUSHED_GCC 1
|
||||
#else
|
||||
#define PDIAGNOSTIC_PUSHED_GCC 0
|
||||
#endif // GNUC >= 4.6
|
||||
#else
|
||||
#define PDIAGNOSTIC_PUSHED_GCC 0
|
||||
#endif // defined(__GNUC__) && !defined(__clang__)
|
||||
|
||||
#include "pdiagnostic.h"
|
||||
206
nostrdb/flatcc/portable/pendian.h
Normal file
206
nostrdb/flatcc/portable/pendian.h
Normal file
@@ -0,0 +1,206 @@
|
||||
#ifndef PENDIAN_H
|
||||
#define PENDIAN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Defines platform optimized (as per linux <endian.h>
|
||||
*
|
||||
* le16toh, le32to, le64toh, be16toh, be32toh, be64toh
|
||||
* htole16, htole32, htole64, htobe16, htobe32, htobe64
|
||||
*
|
||||
* Falls back to auto-detect endian conversion which is also fast
|
||||
* if fast byteswap operation was detected.
|
||||
*
|
||||
* Also defines platform optimized:
|
||||
*
|
||||
* bswap16, bswap32, bswap64,
|
||||
*
|
||||
* with fall-back to shift-or implementation.
|
||||
*
|
||||
* For convenience also defines:
|
||||
*
|
||||
* le8to, be8toh, htole8, htobe8
|
||||
* bswap8
|
||||
*
|
||||
* The convience functions makes is simpler to define conversion macros
|
||||
* based on type size.
|
||||
*
|
||||
* NOTE: this implementation expects arguments with no side-effects and
|
||||
* with appropriately sized unsigned arguments. These are expected to be
|
||||
* used with typesafe wrappers.
|
||||
*/
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
#include "pstdint.h"
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <endian.h>
|
||||
#elif defined(__OpenBSD__) || defined(__FreeBSD__)
|
||||
#include <sys/endian.h>
|
||||
#endif
|
||||
|
||||
#include "pendian_detect.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if _MSC_VER >= 1300
|
||||
#include <stdlib.h>
|
||||
#define bswap16 _byteswap_ushort
|
||||
#define bswap32 _byteswap_ulong
|
||||
#define bswap64 _byteswap_uint64
|
||||
#endif
|
||||
#elif defined(__clang__)
|
||||
#if __has_builtin(__builtin_bswap16)
|
||||
#ifndef bswap16
|
||||
#define bswap16 __builtin_bswap16
|
||||
#endif
|
||||
#endif
|
||||
#if __has_builtin(__builtin_bswap32)
|
||||
#ifndef bswap32
|
||||
#define bswap32 __builtin_bswap32
|
||||
#endif
|
||||
#endif
|
||||
#if __has_builtin(__builtin_bswap64)
|
||||
#ifndef bswap64
|
||||
#define bswap64 __builtin_bswap64
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(__OpenBSD__) || defined(__FreeBSD__)
|
||||
#ifndef bswap16
|
||||
#define bswap16 swap16
|
||||
#endif
|
||||
#ifndef bswap32
|
||||
#define bswap32 swap32
|
||||
#endif
|
||||
#ifndef bswap64
|
||||
#define bswap64 swap64
|
||||
#endif
|
||||
#elif defined(__GNUC__) /* Supported since at least GCC 4.4 */
|
||||
#ifndef bswap32
|
||||
#define bswap32 __builtin_bswap32
|
||||
#endif
|
||||
#ifndef bswap64
|
||||
#define bswap64 __builtin_bswap64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef bswap16
|
||||
#define bswap16(v) \
|
||||
(((uint16_t)(v) << 8) | ((uint16_t)(v) >> 8))
|
||||
#endif
|
||||
|
||||
#ifndef bswap32
|
||||
#define bswap32(v) \
|
||||
((((uint32_t)(v) << 24)) \
|
||||
| (((uint32_t)(v) << 8) & UINT32_C(0x00FF0000)) \
|
||||
| (((uint32_t)(v) >> 8) & UINT32_C(0x0000FF00)) \
|
||||
| (((uint32_t)(v) >> 24)))
|
||||
#endif
|
||||
|
||||
#ifndef bswap64
|
||||
#define bswap64(v) \
|
||||
((((uint64_t)(v) << 56)) \
|
||||
| (((uint64_t)(v) << 40) & UINT64_C(0x00FF000000000000)) \
|
||||
| (((uint64_t)(v) << 24) & UINT64_C(0x0000FF0000000000)) \
|
||||
| (((uint64_t)(v) << 8) & UINT64_C(0x000000FF00000000)) \
|
||||
| (((uint64_t)(v) >> 8) & UINT64_C(0x00000000FF000000)) \
|
||||
| (((uint64_t)(v) >> 24) & UINT64_C(0x0000000000FF0000)) \
|
||||
| (((uint64_t)(v) >> 40) & UINT64_C(0x000000000000FF00)) \
|
||||
| (((uint64_t)(v) >> 56)))
|
||||
#endif
|
||||
|
||||
#ifndef bswap8
|
||||
#define bswap8(v) ((uint8_t)(v))
|
||||
#endif
|
||||
|
||||
#if !defined(le16toh) && defined(letoh16)
|
||||
#define le16toh letoh16
|
||||
#define le32toh letoh32
|
||||
#define le64toh letoh64
|
||||
#endif
|
||||
|
||||
#if !defined(be16toh) && defined(betoh16)
|
||||
#define be16toh betoh16
|
||||
#define be32toh betoh32
|
||||
#define be64toh betoh64
|
||||
#endif
|
||||
|
||||
/* Assume it goes for all. */
|
||||
#if !defined(le16toh)
|
||||
|
||||
#if defined(__LITTLE_ENDIAN__)
|
||||
|
||||
#define le16toh(v) (v)
|
||||
#define le32toh(v) (v)
|
||||
#define le64toh(v) (v)
|
||||
|
||||
#define htole16(v) (v)
|
||||
#define htole32(v) (v)
|
||||
#define htole64(v) (v)
|
||||
|
||||
#define be16toh(v) bswap16(v)
|
||||
#define be32toh(v) bswap32(v)
|
||||
#define be64toh(v) bswap64(v)
|
||||
|
||||
#define htobe16(v) bswap16(v)
|
||||
#define htobe32(v) bswap32(v)
|
||||
#define htobe64(v) bswap64(v)
|
||||
|
||||
#elif defined(__BIG_ENDIAN__)
|
||||
|
||||
#define le16toh(v) bswap16(v)
|
||||
#define le32toh(v) bswap32(v)
|
||||
#define le64toh(v) bswap64(v)
|
||||
|
||||
#define htole16(v) bswap16(v)
|
||||
#define htole32(v) bswap32(v)
|
||||
#define htole64(v) bswap64(v)
|
||||
|
||||
#define be16toh(v) (v)
|
||||
#define be32toh(v) (v)
|
||||
#define be64toh(v) (v)
|
||||
|
||||
#define htobe16(v) (v)
|
||||
#define htobe32(v) (v)
|
||||
#define htobe64(v) (v)
|
||||
|
||||
#else
|
||||
|
||||
static const int __pendian_test = 1;
|
||||
|
||||
#define le16toh(v) (*(char *)&__pendian_test ? (v) : bswap16(v))
|
||||
#define le32toh(v) (*(char *)&__pendian_test ? (v) : bswap32(v))
|
||||
#define le64toh(v) (*(char *)&__pendian_test ? (v) : bswap64(v))
|
||||
|
||||
#define htole16(v) (*(char *)&__pendian_test ? (v) : bswap16(v))
|
||||
#define htole32(v) (*(char *)&__pendian_test ? (v) : bswap32(v))
|
||||
#define htole64(v) (*(char *)&__pendian_test ? (v) : bswap64(v))
|
||||
|
||||
#define be16toh(v) (*(char *)&__pendian_test ? bswap16(v) : (v))
|
||||
#define be32toh(v) (*(char *)&__pendian_test ? bswap32(v) : (v))
|
||||
#define be64toh(v) (*(char *)&__pendian_test ? bswap64(v) : (v))
|
||||
|
||||
#define htobe16(v) (*(char *)&__pendian_test ? bswap16(v) : (v))
|
||||
#define htobe32(v) (*(char *)&__pendian_test ? bswap32(v) : (v))
|
||||
#define htobe64(v) (*(char *)&__pendian_test ? bswap64(v) : (v))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* le16toh */
|
||||
|
||||
/* Helpers not part of Linux <endian.h> */
|
||||
#if !defined(le8toh)
|
||||
#define le8toh(n) (n)
|
||||
#define htole8(n) (n)
|
||||
#define be8toh(n) (n)
|
||||
#define htobe8(n) (n)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PENDIAN_H */
|
||||
118
nostrdb/flatcc/portable/pendian_detect.h
Normal file
118
nostrdb/flatcc/portable/pendian_detect.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Uses various known flags to decide endianness and defines:
|
||||
*
|
||||
* __LITTLE_ENDIAN__ or __BIG_ENDIAN__ if not already defined
|
||||
*
|
||||
* and also defines
|
||||
*
|
||||
* __BYTE_ORDER__ to either __ORDER_LITTLE_ENDIAN__ or
|
||||
* __ORDER_BIG_ENDIAN__ if not already defined
|
||||
*
|
||||
* If none of these could be set, __UNKNOWN_ENDIAN__ is defined,
|
||||
* which is not a known flag. If __BYTE_ORDER__ is defined but
|
||||
* not big or little endian, __UNKNOWN_ENDIAN__ is also defined.
|
||||
*
|
||||
* Note: Some systems define __BYTE_ORDER without __ at the end
|
||||
* - this will be mapped to to __BYTE_ORDER__.
|
||||
*/
|
||||
|
||||
#ifndef PENDIAN_DETECT
|
||||
#define PENDIAN_DETECT
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef __ORDER_LITTLE_ENDIAN__
|
||||
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||
#endif
|
||||
|
||||
#ifndef __ORDER_BIG_ENDIAN__
|
||||
#define __ORDER_BIG_ENDIAN__ 4321
|
||||
#endif
|
||||
|
||||
#ifdef __BYTE_ORDER__
|
||||
|
||||
#if defined(__LITTLE_ENDIAN__) && __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
|
||||
#error __LITTLE_ENDIAN__ inconsistent with __BYTE_ORDER__
|
||||
#endif
|
||||
|
||||
#if defined(__BIG_ENDIAN__) && __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
|
||||
#error __BIG_ENDIAN__ inconsistent with __BYTE_ORDER__
|
||||
#endif
|
||||
|
||||
#else /* __BYTE_ORDER__ */
|
||||
|
||||
|
||||
#if \
|
||||
defined(__LITTLE_ENDIAN__) || \
|
||||
(defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \
|
||||
defined(__ARMEL__) || defined(__THUMBEL__) || \
|
||||
defined(__AARCH64EL__) || \
|
||||
(defined(_MSC_VER) && defined(_M_ARM)) || \
|
||||
defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \
|
||||
defined(_M_X64) || defined(_M_IX86) || defined(_M_I86) || \
|
||||
defined(__i386__) || defined(__alpha__) || \
|
||||
defined(__ia64) || defined(__ia64__) || \
|
||||
defined(_M_IA64) || defined(_M_ALPHA) || \
|
||||
defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || \
|
||||
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
|
||||
defined(__bfin__)
|
||||
|
||||
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
|
||||
#endif
|
||||
|
||||
#if \
|
||||
defined (__BIG_ENDIAN__) || \
|
||||
(defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \
|
||||
defined(__ARMEB__) || defined(THUMBEB__) || defined (__AARCH64EB__) || \
|
||||
defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \
|
||||
defined(__sparc) || defined(__sparc__) || \
|
||||
defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || \
|
||||
defined(__hpux) || defined(__hppa) || defined(__s390__)
|
||||
|
||||
#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __BYTE_ORDER__ */
|
||||
|
||||
#ifdef __BYTE_ORDER__
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
|
||||
#ifndef __LITTLE_ENDIAN__
|
||||
#define __LITTLE_ENDIAN__ 1
|
||||
#endif
|
||||
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
#define __BIG_ENDIAN__ 1
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Custom extension - we only define __BYTE_ORDER__ if known big or little.
|
||||
* User code that understands __BYTE_ORDER__ may also assume unkown if
|
||||
* it is not defined by now - this will allow other endian formats than
|
||||
* big or little when supported by compiler.
|
||||
*/
|
||||
#ifndef __UNKNOWN_ENDIAN__
|
||||
#define __UNKNOWN_ENDIAN__ 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* __BYTE_ORDER__ */
|
||||
|
||||
#if defined(__LITTLE_ENDIAN__) && defined(__BIG_ENDIAN__)
|
||||
#error conflicting definitions of __LITTLE_ENDIAN__ and __BIG_ENDIAN__
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PENDIAN_DETECT */
|
||||
19
nostrdb/flatcc/portable/pinline.h
Normal file
19
nostrdb/flatcc/portable/pinline.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef PINLINE_H
|
||||
#define PINLINE_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
|
||||
/* C99 or newer */
|
||||
#elif _MSC_VER >= 1500 /* MSVC 9 or newer */
|
||||
#undef inline
|
||||
#define inline __inline
|
||||
#elif __GNUC__ >= 3 /* GCC 3 or newer */
|
||||
#define inline __inline
|
||||
#else /* Unknown or ancient */
|
||||
#define inline
|
||||
#endif
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PINLINE_H */
|
||||
52
nostrdb/flatcc/portable/pinttypes.h
Normal file
52
nostrdb/flatcc/portable/pinttypes.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef PINTTYPES_H
|
||||
#define PINTTYPES_H
|
||||
|
||||
#ifndef PRId16
|
||||
|
||||
#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
|
||||
/* C99 or newer */
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
|
||||
/*
|
||||
* This is not a complete implementation of <inttypes.h>, just the most
|
||||
* useful printf modifiers.
|
||||
*/
|
||||
|
||||
#include "pstdint.h"
|
||||
|
||||
#ifndef PRINTF_INT64_MODIFIER
|
||||
#error "please define PRINTF_INT64_MODIFIER"
|
||||
#endif
|
||||
|
||||
#ifndef PRId64
|
||||
#define PRId64 PRINTF_INT64_MODIFIER "d"
|
||||
#define PRIu64 PRINTF_INT64_MODIFIER "u"
|
||||
#define PRIx64 PRINTF_INT64_MODIFIER "x"
|
||||
#endif
|
||||
|
||||
#ifndef PRINTF_INT32_MODIFIER
|
||||
#define PRINTF_INT32_MODIFIER "l"
|
||||
#endif
|
||||
|
||||
#ifndef PRId32
|
||||
#define PRId32 PRINTF_INT32_MODIFIER "d"
|
||||
#define PRIu32 PRINTF_INT32_MODIFIER "u"
|
||||
#define PRIx32 PRINTF_INT32_MODIFIER "x"
|
||||
#endif
|
||||
|
||||
#ifndef PRINTF_INT16_MODIFIER
|
||||
#define PRINTF_INT16_MODIFIER "h"
|
||||
#endif
|
||||
|
||||
#ifndef PRId16
|
||||
#define PRId16 PRINTF_INT16_MODIFIER "d"
|
||||
#define PRIu16 PRINTF_INT16_MODIFIER "u"
|
||||
#define PRIx16 PRINTF_INT16_MODIFIER "x"
|
||||
#endif
|
||||
|
||||
# endif /* __STDC__ */
|
||||
|
||||
#endif /* PRId16 */
|
||||
|
||||
#endif /* PINTTYPES */
|
||||
2
nostrdb/flatcc/portable/portable.h
Normal file
2
nostrdb/flatcc/portable/portable.h
Normal file
@@ -0,0 +1,2 @@
|
||||
/* portable.h is widely used, so we redirect to a less conflicting name. */
|
||||
#include "portable_basic.h"
|
||||
25
nostrdb/flatcc/portable/portable_basic.h
Normal file
25
nostrdb/flatcc/portable/portable_basic.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef PORTABLE_BASIC_H
|
||||
#define PORTABLE_BASIC_H
|
||||
|
||||
/*
|
||||
* Basic features need to make compilers support the most common moden C
|
||||
* features, and endian / unligned read support as well.
|
||||
*
|
||||
* It is not assumed that this file is always included.
|
||||
* Other include files are independent or include what they need.
|
||||
*/
|
||||
|
||||
#include "pversion.h"
|
||||
#include "pwarnings.h"
|
||||
|
||||
/* Featutures that ought to be supported by C11, but some aren't. */
|
||||
#include "pinttypes.h"
|
||||
#include "pstdalign.h"
|
||||
#include "pinline.h"
|
||||
#include "pstatic_assert.h"
|
||||
|
||||
/* These are not supported by C11 and are general platform abstractions. */
|
||||
#include "pendian.h"
|
||||
#include "punaligned.h"
|
||||
|
||||
#endif /* PORTABLE_BASIC_H */
|
||||
140
nostrdb/flatcc/portable/pparsefp.h
Normal file
140
nostrdb/flatcc/portable/pparsefp.h
Normal file
@@ -0,0 +1,140 @@
|
||||
#ifndef PPARSEFP_H
|
||||
#define PPARSEFP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Parses a float or double number and returns the length parsed if
|
||||
* successful. The length argument is of limited value due to dependency
|
||||
* on `strtod` - buf[len] must be accessible and must not be part of
|
||||
* a valid number, including hex float numbers..
|
||||
*
|
||||
* Unlike strtod, whitespace is not parsed.
|
||||
*
|
||||
* May return:
|
||||
* - null on error,
|
||||
* - buffer start if first character does not start a number,
|
||||
* - or end of parse on success.
|
||||
*
|
||||
*/
|
||||
|
||||
#define PDIAGNOSTIC_IGNORE_UNUSED_FUNCTION
|
||||
#include "pdiagnostic_push.h"
|
||||
|
||||
/*
|
||||
* isinf is needed in order to stay compatible with strtod's
|
||||
* over/underflow handling but isinf has some portability issues.
|
||||
*
|
||||
* Use the parse_double/float_is_range_error instead of isinf directly.
|
||||
* This ensures optimizations can be added when not using strtod.
|
||||
*
|
||||
* On gcc, clang and msvc we can use isinf or equivalent directly.
|
||||
* Other compilers such as xlc may require linking with -lm which may not
|
||||
* be convienent so a default isinf is provided. If isinf is available
|
||||
* and there is a noticable performance issue, define
|
||||
* `PORTABLE_USE_ISINF`.
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) || defined(PORTABLE_USE_ISINF)
|
||||
#include <math.h>
|
||||
#if defined(_MSC_VER) && !defined(isinf)
|
||||
#include <float.h>
|
||||
#define isnan _isnan
|
||||
#define isinf(x) (!_finite(x))
|
||||
#endif
|
||||
/*
|
||||
* clang-5 through clang-8 but not clang-9 issues incorrect precision
|
||||
* loss warning with -Wconversion flag when cast is absent.
|
||||
*/
|
||||
#if defined(__clang__)
|
||||
#if __clang_major__ >= 5 && __clang_major__ <= 8
|
||||
#define parse_double_isinf(x) isinf((float)x)
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(parse_double_isinf)
|
||||
#define parse_double_isinf isinf
|
||||
#endif
|
||||
#define parse_float_isinf isinf
|
||||
|
||||
#else
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Avoid linking with libmath but depends on float/double being IEEE754 */
|
||||
static inline int parse_double_isinf(double x)
|
||||
{
|
||||
union { uint64_t u64; double f64; } v;
|
||||
v.f64 = x;
|
||||
return (v.u64 & 0x7fffffff00000000ULL) == 0x7ff0000000000000ULL;
|
||||
}
|
||||
|
||||
static inline int parse_float_isinf(float x)
|
||||
{
|
||||
union { uint32_t u32; float f32; } v;
|
||||
v.f32 = x;
|
||||
return (v.u32 & 0x7fffffff) == 0x7f800000;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returns 0 when in range, 1 on overflow, and -1 on underflow. */
|
||||
static inline int parse_double_is_range_error(double x)
|
||||
{
|
||||
return parse_double_isinf(x) ? (x < 0.0 ? -1 : 1) : 0;
|
||||
}
|
||||
|
||||
static inline int parse_float_is_range_error(float x)
|
||||
{
|
||||
return parse_float_isinf(x) ? (x < 0.0f ? -1 : 1) : 0;
|
||||
}
|
||||
|
||||
#ifndef PORTABLE_USE_GRISU3
|
||||
#define PORTABLE_USE_GRISU3 1
|
||||
#endif
|
||||
|
||||
#if PORTABLE_USE_GRISU3
|
||||
#include "grisu3_parse.h"
|
||||
#endif
|
||||
|
||||
#ifdef grisu3_parse_double_is_defined
|
||||
static inline const char *parse_double(const char *buf, size_t len, double *result)
|
||||
{
|
||||
return grisu3_parse_double(buf, len, result);
|
||||
}
|
||||
#else
|
||||
#include <stdio.h>
|
||||
static inline const char *parse_double(const char *buf, size_t len, double *result)
|
||||
{
|
||||
char *end;
|
||||
|
||||
(void)len;
|
||||
*result = strtod(buf, &end);
|
||||
return end;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline const char *parse_float(const char *buf, size_t len, float *result)
|
||||
{
|
||||
const char *end;
|
||||
double v;
|
||||
union { uint32_t u32; float f32; } inf;
|
||||
inf.u32 = 0x7f800000;
|
||||
|
||||
end = parse_double(buf, len, &v);
|
||||
*result = (float)v;
|
||||
if (parse_float_isinf(*result)) {
|
||||
*result = v < 0 ? -inf.f32 : inf.f32;
|
||||
return buf;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
#include "pdiagnostic_pop.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PPARSEFP_H */
|
||||
374
nostrdb/flatcc/portable/pparseint.h
Normal file
374
nostrdb/flatcc/portable/pparseint.h
Normal file
@@ -0,0 +1,374 @@
|
||||
#ifndef PPARSEINT_H
|
||||
#define PPARSEINT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Type specific integer parsers:
|
||||
*
|
||||
* const char *
|
||||
* parse_<type-name>(const char *buf, size_t len, <type> *value, int *status);
|
||||
*
|
||||
* parse_uint64, parse_int64
|
||||
* parse_uint32, parse_int32
|
||||
* parse_uint16, parse_int16
|
||||
* parse_uint8, parse_int8
|
||||
* parse_ushort, parse_short
|
||||
* parse_uint, parse_int
|
||||
* parse_ulong, parse_long
|
||||
*
|
||||
* Leading space must be stripped in advance. Status argument can be
|
||||
* null.
|
||||
*
|
||||
* Returns pointer to end of match and a non-negative status code
|
||||
* on succcess (0 for unsigned, 1 for signed):
|
||||
*
|
||||
* PARSE_INTEGER_UNSIGNED
|
||||
* PARSE_INTEGER_SIGNED
|
||||
*
|
||||
* Returns null with a negative status code and unmodified value on
|
||||
* invalid integer formats:
|
||||
*
|
||||
* PARSE_INTEGER_OVERFLOW
|
||||
* PARSE_INTEGER_UNDERFLOW
|
||||
* PARSE_INTEGER_INVALID
|
||||
*
|
||||
* Returns input buffer with negative status code and unmodified value
|
||||
* if first character does not start an integer (not a sign or a digit).
|
||||
*
|
||||
* PARSE_INTEGER_UNMATCHED
|
||||
* PARSE_INTEGER_END
|
||||
*
|
||||
* The signed parsers only works with two's complement architectures.
|
||||
*
|
||||
* Note: the corresponding parse_float and parse_double parsers do not
|
||||
* have a status argument because +/-Inf and NaN are conventionally used
|
||||
* for this.
|
||||
*/
|
||||
|
||||
#include "limits.h"
|
||||
#ifndef UINT8_MAX
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define PARSE_INTEGER_UNSIGNED 0
|
||||
#define PARSE_INTEGER_SIGNED 1
|
||||
#define PARSE_INTEGER_OVERFLOW -1
|
||||
#define PARSE_INTEGER_UNDERFLOW -2
|
||||
#define PARSE_INTEGER_INVALID -3
|
||||
#define PARSE_INTEGER_UNMATCHED -4
|
||||
#define PARSE_INTEGER_END -5
|
||||
|
||||
/*
|
||||
* Generic integer parser that holds 64-bit unsigned values and stores
|
||||
* sign separately. Leading space is not valid.
|
||||
*
|
||||
* Note: this function differs from the type specific parsers like
|
||||
* parse_int64 by not negating the value when there is a sign. It
|
||||
* differs from parse_uint64 by being able to return a negative
|
||||
* UINT64_MAX successfully.
|
||||
*
|
||||
* This parser is used by all type specific integer parsers.
|
||||
*
|
||||
* Status argument can be null.
|
||||
*/
|
||||
static const char *parse_integer(const char *buf, size_t len, uint64_t *value, int *status)
|
||||
{
|
||||
uint64_t x0, x = 0;
|
||||
const char *k, *end = buf + len;
|
||||
int sign, status_;
|
||||
|
||||
if (!status) {
|
||||
status = &status_;
|
||||
}
|
||||
if (buf == end) {
|
||||
*status = PARSE_INTEGER_END;
|
||||
return buf;
|
||||
}
|
||||
k = buf;
|
||||
sign = *buf == '-';
|
||||
buf += sign;
|
||||
while (buf != end && *buf >= '0' && *buf <= '9') {
|
||||
x0 = x;
|
||||
x = x * 10 + (uint64_t)(*buf - '0');
|
||||
if (x0 > x) {
|
||||
*status = sign ? PARSE_INTEGER_UNDERFLOW : PARSE_INTEGER_OVERFLOW;
|
||||
return 0;
|
||||
}
|
||||
++buf;
|
||||
}
|
||||
if (buf == k) {
|
||||
/* No number was matched, but it isn't an invalid number either. */
|
||||
*status = PARSE_INTEGER_UNMATCHED;
|
||||
return buf;
|
||||
}
|
||||
if (buf == k + sign) {
|
||||
*status = PARSE_INTEGER_INVALID;
|
||||
return 0;
|
||||
}
|
||||
if (buf != end)
|
||||
switch (*buf) {
|
||||
case 'e': case 'E': case '.': case 'p': case 'P':
|
||||
*status = PARSE_INTEGER_INVALID;
|
||||
return 0;
|
||||
}
|
||||
*value = x;
|
||||
*status = sign;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse hex values like 0xff, -0xff, 0XdeAdBeaf42, cannot be trailed by '.', 'p', or 'P'.
|
||||
* Overflows if string is more than 16 valid hex digits. Otherwise similar to parse_integer.
|
||||
*/
|
||||
static const char *parse_hex_integer(const char *buf, size_t len, uint64_t *value, int *status)
|
||||
{
|
||||
uint64_t x = 0;
|
||||
const char *k, *k2, *end = buf + len;
|
||||
int sign, status_;
|
||||
unsigned char c;
|
||||
|
||||
if (!status) {
|
||||
status = &status_;
|
||||
}
|
||||
if (buf == end) {
|
||||
*status = PARSE_INTEGER_END;
|
||||
return buf;
|
||||
}
|
||||
sign = *buf == '-';
|
||||
buf += sign;
|
||||
if (end - buf < 2 || buf[0] != '0' || (buf[1] | 0x20) != 'x') {
|
||||
*status = PARSE_INTEGER_UNMATCHED;
|
||||
return buf - sign;
|
||||
}
|
||||
buf += 2;
|
||||
k = buf;
|
||||
k2 = end;
|
||||
if (end - buf > 16) {
|
||||
k2 = buf + 16;
|
||||
}
|
||||
while (buf != k2) {
|
||||
c = (unsigned char)*buf;
|
||||
if (c >= '0' && c <= '9') {
|
||||
x = x * 16 + c - '0';
|
||||
} else {
|
||||
/* Lower case. */
|
||||
c |= 0x20;
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
x = x * 16 + c - 'a' + 10;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
++buf;
|
||||
}
|
||||
if (buf == k) {
|
||||
if (sign) {
|
||||
*status = PARSE_INTEGER_INVALID;
|
||||
return 0;
|
||||
} else {
|
||||
/* No number was matched, but it isn't an invalid number either. */
|
||||
*status = PARSE_INTEGER_UNMATCHED;
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
if (buf == end) {
|
||||
goto done;
|
||||
}
|
||||
c = (unsigned char)*buf;
|
||||
if (buf == k2) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
*status = sign ? PARSE_INTEGER_UNDERFLOW : PARSE_INTEGER_OVERFLOW;
|
||||
return 0;
|
||||
}
|
||||
c |= 0x20;
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
*status = sign ? PARSE_INTEGER_UNDERFLOW : PARSE_INTEGER_OVERFLOW;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
switch (c) {
|
||||
case '.': case 'p': case 'P':
|
||||
*status = PARSE_INTEGER_INVALID;
|
||||
return 0;
|
||||
}
|
||||
done:
|
||||
*value = x;
|
||||
*status = sign;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
#define __portable_define_parse_unsigned(NAME, TYPE, LIMIT) \
|
||||
static inline const char *parse_ ## NAME \
|
||||
(const char *buf, size_t len, TYPE *value, int *status) \
|
||||
{ \
|
||||
int status_ = 0; \
|
||||
uint64_t x; \
|
||||
\
|
||||
if (!status) { \
|
||||
status = &status_; \
|
||||
} \
|
||||
buf = parse_integer(buf, len, &x, status); \
|
||||
switch (*status) { \
|
||||
case PARSE_INTEGER_UNSIGNED: \
|
||||
if (x <= LIMIT) { \
|
||||
*value = (TYPE)x; \
|
||||
return buf; \
|
||||
} \
|
||||
*status = PARSE_INTEGER_OVERFLOW; \
|
||||
return 0; \
|
||||
case PARSE_INTEGER_SIGNED: \
|
||||
*status = PARSE_INTEGER_UNDERFLOW; \
|
||||
return 0; \
|
||||
default: \
|
||||
return buf; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define __portable_define_parse_hex_unsigned(NAME, TYPE, LIMIT) \
|
||||
static inline const char *parse_hex_ ## NAME \
|
||||
(const char *buf, size_t len, TYPE *value, int *status) \
|
||||
{ \
|
||||
int status_ = 0; \
|
||||
uint64_t x; \
|
||||
\
|
||||
if (!status) { \
|
||||
status = &status_; \
|
||||
} \
|
||||
buf = parse_hex_integer(buf, len, &x, status); \
|
||||
switch (*status) { \
|
||||
case PARSE_INTEGER_UNSIGNED: \
|
||||
if (x <= LIMIT) { \
|
||||
*value = (TYPE)x; \
|
||||
return buf; \
|
||||
} \
|
||||
*status = PARSE_INTEGER_OVERFLOW; \
|
||||
return 0; \
|
||||
case PARSE_INTEGER_SIGNED: \
|
||||
*status = PARSE_INTEGER_UNDERFLOW; \
|
||||
return 0; \
|
||||
default: \
|
||||
return buf; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* This assumes two's complement. */
|
||||
#define __portable_define_parse_signed(NAME, TYPE, LIMIT) \
|
||||
static inline const char *parse_ ## NAME \
|
||||
(const char *buf, size_t len, TYPE *value, int *status) \
|
||||
{ \
|
||||
int status_ = 0; \
|
||||
uint64_t x; \
|
||||
\
|
||||
if (!status) { \
|
||||
status = &status_; \
|
||||
} \
|
||||
buf = parse_integer(buf, len, &x, status); \
|
||||
switch (*status) { \
|
||||
case PARSE_INTEGER_UNSIGNED: \
|
||||
if (x <= LIMIT) { \
|
||||
*value = (TYPE)x; \
|
||||
return buf; \
|
||||
} \
|
||||
*status = PARSE_INTEGER_OVERFLOW; \
|
||||
return 0; \
|
||||
case PARSE_INTEGER_SIGNED: \
|
||||
if (x <= (uint64_t)(LIMIT) + 1) { \
|
||||
*value = (TYPE)-(int64_t)x; \
|
||||
return buf; \
|
||||
} \
|
||||
*status = PARSE_INTEGER_UNDERFLOW; \
|
||||
return 0; \
|
||||
default: \
|
||||
return buf; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* This assumes two's complement. */
|
||||
#define __portable_define_parse_hex_signed(NAME, TYPE, LIMIT) \
|
||||
static inline const char *parse_hex_ ## NAME \
|
||||
(const char *buf, size_t len, TYPE *value, int *status) \
|
||||
{ \
|
||||
int status_ = 0; \
|
||||
uint64_t x; \
|
||||
\
|
||||
if (!status) { \
|
||||
status = &status_; \
|
||||
} \
|
||||
buf = parse_hex_integer(buf, len, &x, status); \
|
||||
switch (*status) { \
|
||||
case PARSE_INTEGER_UNSIGNED: \
|
||||
if (x <= LIMIT) { \
|
||||
*value = (TYPE)x; \
|
||||
return buf; \
|
||||
} \
|
||||
*status = PARSE_INTEGER_OVERFLOW; \
|
||||
return 0; \
|
||||
case PARSE_INTEGER_SIGNED: \
|
||||
if (x <= (uint64_t)(LIMIT) + 1) { \
|
||||
*value = (TYPE)-(int64_t)x; \
|
||||
return buf; \
|
||||
} \
|
||||
*status = PARSE_INTEGER_UNDERFLOW; \
|
||||
return 0; \
|
||||
default: \
|
||||
return buf; \
|
||||
} \
|
||||
}
|
||||
|
||||
static inline const char *parse_uint64(const char *buf, size_t len, uint64_t *value, int *status)
|
||||
{
|
||||
buf = parse_integer(buf, len, value, status);
|
||||
if (*status == PARSE_INTEGER_SIGNED) {
|
||||
*status = PARSE_INTEGER_UNDERFLOW;
|
||||
return 0;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline const char *parse_hex_uint64(const char *buf, size_t len, uint64_t *value, int *status)
|
||||
{
|
||||
buf = parse_hex_integer(buf, len, value, status);
|
||||
if (*status == PARSE_INTEGER_SIGNED) {
|
||||
*status = PARSE_INTEGER_UNDERFLOW;
|
||||
return 0;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
__portable_define_parse_signed(int64, int64_t, INT64_MAX)
|
||||
__portable_define_parse_signed(int32, int32_t, INT32_MAX)
|
||||
__portable_define_parse_unsigned(uint16, uint16_t, UINT16_MAX)
|
||||
__portable_define_parse_signed(int16, int16_t, INT16_MAX)
|
||||
__portable_define_parse_unsigned(uint8, uint8_t, UINT8_MAX)
|
||||
__portable_define_parse_signed(int8, int8_t, INT8_MAX)
|
||||
|
||||
__portable_define_parse_hex_signed(int64, int64_t, INT64_MAX)
|
||||
__portable_define_parse_hex_signed(int32, int32_t, INT32_MAX)
|
||||
__portable_define_parse_hex_unsigned(uint16, uint16_t, UINT16_MAX)
|
||||
__portable_define_parse_hex_signed(int16, int16_t, INT16_MAX)
|
||||
__portable_define_parse_hex_unsigned(uint8, uint8_t, UINT8_MAX)
|
||||
__portable_define_parse_hex_signed(int8, int8_t, INT8_MAX)
|
||||
|
||||
__portable_define_parse_unsigned(ushort, unsigned short, USHRT_MAX)
|
||||
__portable_define_parse_signed(short, short, SHRT_MAX)
|
||||
__portable_define_parse_unsigned(uint, unsigned int, UINT_MAX)
|
||||
__portable_define_parse_signed(int, int, INT_MAX)
|
||||
__portable_define_parse_unsigned(ulong, unsigned long, ULONG_MAX)
|
||||
__portable_define_parse_signed(long, unsigned long, LONG_MAX)
|
||||
|
||||
__portable_define_parse_hex_unsigned(ushort, unsigned short, USHRT_MAX)
|
||||
__portable_define_parse_hex_signed(short, short, SHRT_MAX)
|
||||
__portable_define_parse_hex_unsigned(uint, unsigned int, UINT_MAX)
|
||||
__portable_define_parse_hex_signed(int, int, INT_MAX)
|
||||
__portable_define_parse_hex_unsigned(ulong, unsigned long, ULONG_MAX)
|
||||
__portable_define_parse_hex_signed(long, unsigned long, LONG_MAX)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PPARSEINT_H */
|
||||
39
nostrdb/flatcc/portable/pprintfp.h
Normal file
39
nostrdb/flatcc/portable/pprintfp.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef PPRINTFP_H
|
||||
#define PPRINTFP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PDIAGNOSTIC_IGNORE_UNUSED_FUNCTION
|
||||
#include "pdiagnostic_push.h"
|
||||
|
||||
#ifndef PORTABLE_USE_GRISU3
|
||||
#define PORTABLE_USE_GRISU3 1
|
||||
#endif
|
||||
|
||||
|
||||
#if PORTABLE_USE_GRISU3
|
||||
#include "grisu3_print.h"
|
||||
#endif
|
||||
|
||||
#ifdef grisu3_print_double_is_defined
|
||||
/* Currently there is not special support for floats. */
|
||||
#define print_float(n, p) grisu3_print_double((float)(n), (p))
|
||||
#define print_double(n, p) grisu3_print_double((double)(n), (p))
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define print_float(n, p) sprintf(p, "%.9g", (float)(n))
|
||||
#define print_double(n, p) sprintf(p, "%.17g", (double)(n))
|
||||
#endif
|
||||
|
||||
#define print_hex_float(n, p) sprintf(p, "%a", (float)(n))
|
||||
#define print_hex_double(n, p) sprintf(p, "%a", (double)(n))
|
||||
|
||||
#include "pdiagnostic_pop.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PPRINTFP_H */
|
||||
628
nostrdb/flatcc/portable/pprintint.h
Normal file
628
nostrdb/flatcc/portable/pprintint.h
Normal file
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Mikkel F. Jørgensen, dvide.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
* Fast printing of (u)int8/16/32/64_t, (u)int, (u)long.
|
||||
*
|
||||
* Functions take for the
|
||||
*
|
||||
* int print_<type>(type value, char *buf);
|
||||
*
|
||||
* and returns number of characters printed, excluding trailing '\0'
|
||||
* which is also printed. Prints at most 21 characters including zero-
|
||||
* termination.
|
||||
*
|
||||
* The function `print_bool` is a bit different - it simply prints "true\0" for
|
||||
* non-zero integers, and "false\0" otherwise.
|
||||
*
|
||||
* The general algorithm is in-place formatting using binary search log10
|
||||
* followed by duff device loop unrolling div / 100 stages.
|
||||
*
|
||||
* The simpler post copy algorithm also provided for fmt_(u)int uses a
|
||||
* temp buffer and loops over div/100 and post copy to target buffer.
|
||||
*
|
||||
*
|
||||
* Benchmarks on core-i7, 2.2GHz, 64-bit clang/OS-X -O2:
|
||||
*
|
||||
* print_int64: avg 15ns for values between INT64_MIN + (10^7/2 .. 10^7/2)
|
||||
* print_int64: avg 11ns for values between 10^9 + (0..10,000,000).
|
||||
* print_int32: avg 7ns for values cast from INT64_MIN + (10^7/2 .. 10^7/2)
|
||||
* print_int32: avg 7ns for values between 10^9 + (0..10,000,000).
|
||||
* print_int64: avg 13ns for values between 10^16 + (0..10,000,000).
|
||||
* print_int64: avg 5ns for values between 0 and 10,000,000.
|
||||
* print_int32: avg 5ns for values between 0 and 10,000,000.
|
||||
* print_int16: avg 10ns for values cast from 0 and 10,000,000.
|
||||
* print_int8: avg 4ns for values cast from 0 and 10,000,000.
|
||||
*
|
||||
* Post copy algorithm:
|
||||
* print_int: avg 12ns for values between INT64_MIN + (10^7/2 .. 10^7/2)
|
||||
* print_int: avg 14ns for values between 10^9 + (0..10,000,000).
|
||||
* print_long: avg 29ns for values between INT64_MIN + (10^7/2 .. 10^7/2)
|
||||
*
|
||||
* The post copy algorithm is nearly half as fast as the in-place
|
||||
* algorithm, but can also be faster occasionally - possibly because the
|
||||
* optimizer being able to skip the copy step.
|
||||
*/
|
||||
|
||||
#ifndef PPRINTINT_H
|
||||
#define PPRINTINT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "pattributes.h" /* fallthrough */
|
||||
|
||||
#define PDIAGNOSTIC_IGNORE_UNUSED_FUNCTION
|
||||
#include "pdiagnostic_push.h"
|
||||
|
||||
static int print_bool(int n, char *p);
|
||||
|
||||
static int print_uint8(uint8_t n, char *p);
|
||||
static int print_uint16(uint16_t n, char *p);
|
||||
static int print_uint32(uint32_t n, char *p);
|
||||
static int print_uint64(uint64_t n, char *p);
|
||||
static int print_int8(int8_t n, char *p);
|
||||
static int print_int16(int16_t n, char *p);
|
||||
static int print_int32(int32_t n, char *p);
|
||||
static int print_int64(int64_t n, char *p);
|
||||
|
||||
/*
|
||||
* Uses slightly slower, but more compact alogrithm
|
||||
* that is not hardcoded to implementation size.
|
||||
* Other types may be defined using macros below.
|
||||
*/
|
||||
static int print_ulong(unsigned long n, char *p);
|
||||
static int print_uint(unsigned int n, char *p);
|
||||
static int print_int(int n, char *p);
|
||||
static int print_long(long n, char *p);
|
||||
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
|
||||
#define __print_unaligned_copy_16(p, q) (*(uint16_t*)(p) = *(uint16_t*)(q))
|
||||
#else
|
||||
#define __print_unaligned_copy_16(p, q) \
|
||||
((((uint8_t*)(p))[0] = ((uint8_t*)(q))[0]), \
|
||||
(((uint8_t*)(p))[1] = ((uint8_t*)(q))[1]))
|
||||
#endif
|
||||
|
||||
static const char __print_digit_pairs[] =
|
||||
"0001020304050607080910111213141516171819"
|
||||
"2021222324252627282930313233343536373839"
|
||||
"4041424344454647484950515253545556575859"
|
||||
"6061626364656667686970717273747576777879"
|
||||
"8081828384858687888990919293949596979899";
|
||||
|
||||
#define __print_stage() \
|
||||
p -= 2; \
|
||||
dp = __print_digit_pairs + (n % 100) * 2; \
|
||||
n /= 100; \
|
||||
__print_unaligned_copy_16(p, dp);
|
||||
|
||||
#define __print_long_stage() \
|
||||
__print_stage() \
|
||||
__print_stage()
|
||||
|
||||
#define __print_short_stage() \
|
||||
*--p = (n % 10) + '0'; \
|
||||
n /= 10;
|
||||
|
||||
static int print_bool(int n, char *buf)
|
||||
{
|
||||
if (n) {
|
||||
memcpy(buf, "true\0", 5);
|
||||
return 4;
|
||||
} else {
|
||||
memcpy(buf, "false\0", 6);
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
static int print_uint8(uint8_t n, char *p)
|
||||
{
|
||||
const char *dp;
|
||||
|
||||
if (n >= 100) {
|
||||
p += 3;
|
||||
*p = '\0';
|
||||
__print_stage();
|
||||
p[-1] = (char)n + '0';
|
||||
return 3;
|
||||
}
|
||||
if (n >= 10) {
|
||||
p += 2;
|
||||
*p = '\0';
|
||||
__print_stage();
|
||||
return 2;
|
||||
}
|
||||
p[1] = '\0';
|
||||
p[0] = (char)n + '0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int print_uint16(uint16_t n, char *p)
|
||||
{
|
||||
int k = 0;
|
||||
const char *dp;
|
||||
|
||||
if (n >= 1000) {
|
||||
if(n >= 10000) {
|
||||
k = 5;
|
||||
} else {
|
||||
k = 4;
|
||||
}
|
||||
} else {
|
||||
if(n >= 100) {
|
||||
k = 3;
|
||||
} else if(n >= 10) {
|
||||
k = 2;
|
||||
} else {
|
||||
k = 1;
|
||||
}
|
||||
}
|
||||
p += k;
|
||||
*p = '\0';
|
||||
if (k & 1) {
|
||||
switch (k) {
|
||||
case 5:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 3:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 1:
|
||||
p[-1] = (char)n + '0';
|
||||
}
|
||||
} else {
|
||||
switch (k) {
|
||||
case 4:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 2:
|
||||
__print_stage();
|
||||
}
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
static int print_uint32(uint32_t n, char *p)
|
||||
{
|
||||
int k = 0;
|
||||
const char *dp;
|
||||
|
||||
if(n >= 10000UL) {
|
||||
if(n >= 10000000UL) {
|
||||
if(n >= 1000000000UL) {
|
||||
k = 10;
|
||||
} else if(n >= 100000000UL) {
|
||||
k = 9;
|
||||
} else {
|
||||
k = 8;
|
||||
}
|
||||
} else {
|
||||
if(n >= 1000000UL) {
|
||||
k = 7;
|
||||
} else if(n >= 100000UL) {
|
||||
k = 6;
|
||||
} else {
|
||||
k = 5;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(n >= 100UL) {
|
||||
if(n >= 1000UL) {
|
||||
k = 4;
|
||||
} else {
|
||||
k = 3;
|
||||
}
|
||||
} else {
|
||||
if(n >= 10UL) {
|
||||
k = 2;
|
||||
} else {
|
||||
k = 1UL;
|
||||
}
|
||||
}
|
||||
}
|
||||
p += k;
|
||||
*p = '\0';
|
||||
if (k & 1) {
|
||||
switch (k) {
|
||||
case 9:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 7:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 5:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 3:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 1:
|
||||
p[-1] = (char)n + '0';
|
||||
}
|
||||
} else {
|
||||
switch (k) {
|
||||
case 10:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 8:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 6:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 4:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 2:
|
||||
__print_stage();
|
||||
}
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
static int print_uint64(uint64_t n, char *p)
|
||||
{
|
||||
int k = 0;
|
||||
const char *dp;
|
||||
const uint64_t x = 1000000000ULL;
|
||||
|
||||
if (n < x) {
|
||||
return print_uint32((uint32_t)n, p);
|
||||
}
|
||||
if(n >= 10000ULL * x) {
|
||||
if(n >= 10000000ULL * x) {
|
||||
if(n >= 1000000000ULL * x) {
|
||||
if (n >= 10000000000ULL * x) {
|
||||
k = 11 + 9;
|
||||
} else {
|
||||
k = 10 + 9;
|
||||
}
|
||||
} else if(n >= 100000000ULL * x) {
|
||||
k = 9 + 9;
|
||||
} else {
|
||||
k = 8 + 9;
|
||||
}
|
||||
} else {
|
||||
if(n >= 1000000ULL * x) {
|
||||
k = 7 + 9;
|
||||
} else if(n >= 100000ULL * x) {
|
||||
k = 6 + 9;
|
||||
} else {
|
||||
k = 5 + 9;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(n >= 100ULL * x) {
|
||||
if(n >= 1000ULL * x) {
|
||||
k = 4 + 9;
|
||||
} else {
|
||||
k = 3 + 9;
|
||||
}
|
||||
} else {
|
||||
if(n >= 10ULL * x) {
|
||||
k = 2 + 9;
|
||||
} else {
|
||||
k = 1 + 9;
|
||||
}
|
||||
}
|
||||
}
|
||||
p += k;
|
||||
*p = '\0';
|
||||
if (k & 1) {
|
||||
switch (k) {
|
||||
case 19:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 17:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 15:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 13:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 11:
|
||||
__print_stage()
|
||||
__print_short_stage();
|
||||
}
|
||||
} else {
|
||||
switch (k) {
|
||||
case 20:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 18:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 16:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 14:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 12:
|
||||
__print_stage();
|
||||
pattribute(fallthrough);
|
||||
case 10:
|
||||
__print_stage();
|
||||
}
|
||||
}
|
||||
__print_long_stage()
|
||||
__print_long_stage()
|
||||
return k;
|
||||
}
|
||||
|
||||
static int print_int8(int8_t n, char *p)
|
||||
{
|
||||
int sign;
|
||||
|
||||
if ((sign = n < 0)) {
|
||||
*p++ = '-';
|
||||
n = -n;
|
||||
}
|
||||
return print_uint8((uint8_t)n, p) + sign;
|
||||
}
|
||||
|
||||
static int print_int16(int16_t n, char *p)
|
||||
{
|
||||
int sign;
|
||||
|
||||
if ((sign = n < 0)) {
|
||||
*p++ = '-';
|
||||
n = -n;
|
||||
}
|
||||
return print_uint16((uint16_t)n, p) + sign;
|
||||
}
|
||||
|
||||
static int print_int32(int32_t n, char *p)
|
||||
{
|
||||
int sign;
|
||||
|
||||
if ((sign = n < 0)) {
|
||||
*p++ = '-';
|
||||
n = -n;
|
||||
}
|
||||
return print_uint32((uint32_t)n, p) + sign;
|
||||
}
|
||||
|
||||
static int print_int64(int64_t n, char *p)
|
||||
{
|
||||
int sign;
|
||||
|
||||
if ((sign = n < 0)) {
|
||||
*p++ = '-';
|
||||
n = -n;
|
||||
}
|
||||
return print_uint64((uint64_t)n, p) + sign;
|
||||
}
|
||||
|
||||
#define __define_print_int_simple(NAME, UNAME, T, UT) \
|
||||
static int UNAME(UT n, char *buf) \
|
||||
{ \
|
||||
char tmp[20]; \
|
||||
char* p = tmp + 20; \
|
||||
char* q = p; \
|
||||
unsigned int k, m; \
|
||||
\
|
||||
while (n >= 100) { \
|
||||
p -= 2; \
|
||||
m = (unsigned int)(n % 100) * 2; \
|
||||
n /= 100; \
|
||||
__print_unaligned_copy_16(p, __print_digit_pairs + m); \
|
||||
} \
|
||||
p -= 2; \
|
||||
m = (unsigned int)n * 2; \
|
||||
__print_unaligned_copy_16(p, __print_digit_pairs + m); \
|
||||
if (n < 10) { \
|
||||
++p; \
|
||||
} \
|
||||
k = (unsigned int)(q - p); \
|
||||
while (p != q) { \
|
||||
*buf++ = *p++; \
|
||||
} \
|
||||
*buf = '\0'; \
|
||||
return (int)k; \
|
||||
} \
|
||||
\
|
||||
static int NAME(T n, char *buf) \
|
||||
{ \
|
||||
int sign = n < 0; \
|
||||
\
|
||||
if (sign) { \
|
||||
*buf++ = '-'; \
|
||||
n = -n; \
|
||||
} \
|
||||
return UNAME((UT)n, buf) + sign; \
|
||||
}
|
||||
|
||||
__define_print_int_simple(print_int, print_uint, int, unsigned int)
|
||||
__define_print_int_simple(print_long, print_ulong, long, unsigned long)
|
||||
|
||||
#ifdef PPRINTINT_BENCH
|
||||
int main() {
|
||||
int64_t count = 10000000; /* 10^7 */
|
||||
#if 0
|
||||
int64_t base = 0;
|
||||
int64_t base = 10000000000000000; /* 10^16 */
|
||||
int64_t base = 1000000000; /* 10^9 */
|
||||
#endif
|
||||
int64_t base = INT64_MIN - count/2;
|
||||
char buf[100];
|
||||
int i, k = 0, n = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
k = print_int64(i + base, buf);
|
||||
n += buf[0] + buf[k - 1];
|
||||
}
|
||||
return n;
|
||||
}
|
||||
/* Call with time on executable, multiply time in seconds by 100 to get time unit in ns/number. */
|
||||
#endif /* PPRINTINT_BENCH */
|
||||
|
||||
#ifdef PPRINTINT_TEST
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
char buf[21];
|
||||
int failed = 0;
|
||||
int k;
|
||||
|
||||
k = print_uint64(UINT64_MAX, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("18446744073709551615", buf)) {
|
||||
printf("UINT64_MAX didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_int64(INT64_MAX, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("9223372036854775807", buf)) {
|
||||
printf("INT64_MAX didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_int64(INT64_MIN, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("-9223372036854775808", buf)) {
|
||||
printf("INT64_MIN didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_uint32(UINT32_MAX, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("4294967295", buf)) {
|
||||
printf("UINT32_MAX didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_int32(INT32_MAX, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("2147483647", buf)) {
|
||||
printf("INT32_MAX didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_int32(INT32_MIN, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("-2147483648", buf)) {
|
||||
printf("INT32_MIN didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_uint16(UINT16_MAX, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("65535", buf)) {
|
||||
printf("UINT16_MAX didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_int16(INT16_MAX, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("32767", buf)) {
|
||||
printf("INT16_MAX didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_int16(INT16_MIN, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("-32768", buf)) {
|
||||
printf("INT16_MIN didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_uint8(UINT8_MAX, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("255", buf)) {
|
||||
printf("INT8_MAX didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_int8(INT8_MAX, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("127", buf)) {
|
||||
printf("INT8_MAX didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_int8(INT8_MIN, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("-128", buf)) {
|
||||
printf("INT8_MIN didn't print correctly, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_int(INT32_MAX, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("2147483647", buf)) {
|
||||
printf("INT32_MAX didn't print correctly with k = print_int, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_int(INT32_MIN, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("-2147483648", buf)) {
|
||||
printf("INT32_MIN didn't print correctly k = print_int, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_long(INT32_MAX, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("2147483647", buf)) {
|
||||
printf("INT32_MAX didn't print correctly with fmt_long, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_long(INT32_MIN, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("-2147483648", buf)) {
|
||||
printf("INT32_MIN didn't print correctly fmt_long, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_bool(1, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("true", buf) {
|
||||
printf("1 didn't print 'true' as expected, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_bool(-1, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("true", buf) {
|
||||
printf("-1 didn't print 'true' as expected, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
k = print_bool(, buf);
|
||||
if (strlen(buf) != k) printf("length error\n");
|
||||
if (strcmp("false", buf) {
|
||||
printf("0 didn't print 'false' as expected, got:\n'%s'\n", buf);
|
||||
++failed;
|
||||
}
|
||||
if (failed) {
|
||||
printf("FAILED\n");
|
||||
return -1;
|
||||
}
|
||||
printf("SUCCESS\n");
|
||||
return 0;
|
||||
}
|
||||
#endif /* PPRINTINT_TEST */
|
||||
|
||||
#include "pdiagnostic_pop.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PPRINTINT_H */
|
||||
67
nostrdb/flatcc/portable/pstatic_assert.h
Normal file
67
nostrdb/flatcc/portable/pstatic_assert.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef PSTATIC_ASSERT_H
|
||||
#define PSTATIC_ASSERT_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* Handle clang */
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(static_assert)
|
||||
#ifndef __static_assert_is_defined
|
||||
#define __static_assert_is_defined 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Handle static_assert as a keyword in C++ and compiler specifics. */
|
||||
#if !defined(__static_assert_is_defined)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#define __static_assert_is_defined 1
|
||||
#elif __has_feature(cxx_static_assert)
|
||||
#define __static_assert_is_defined 1
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
|
||||
#define __static_assert_is_defined 1
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
|
||||
#define __static_assert_is_defined 1
|
||||
#elif __has_feature(c_static_assert)
|
||||
#define static_assert(pred, msg) _Static_assert(pred, msg)
|
||||
#define __static_assert_is_defined 1
|
||||
#elif defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
||||
/* In case the clib headers are not compliant. */
|
||||
#define static_assert(pred, msg) _Static_assert(pred, msg)
|
||||
#define __static_assert_is_defined 1
|
||||
#endif
|
||||
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __static_assert_is_defined */
|
||||
|
||||
|
||||
#if !defined(__static_assert_is_defined)
|
||||
|
||||
#define __PSTATIC_ASSERT_CONCAT_(a, b) static_assert_scope_##a##_line_##b
|
||||
#define __PSTATIC_ASSERT_CONCAT(a, b) __PSTATIC_ASSERT_CONCAT_(a, b)
|
||||
#ifdef __COUNTER__
|
||||
#define static_assert(e, msg) enum { __PSTATIC_ASSERT_CONCAT(__COUNTER__, __LINE__) = 1/(!!(e)) }
|
||||
#else
|
||||
#include "pstatic_assert_scope.h"
|
||||
#define static_assert(e, msg) enum { __PSTATIC_ASSERT_CONCAT(__PSTATIC_ASSERT_COUNTER, __LINE__) = 1/(int)(!!(e)) }
|
||||
#endif
|
||||
|
||||
#define __static_assert_is_defined 1
|
||||
|
||||
#endif /* __static_assert_is_defined */
|
||||
|
||||
#endif /* PSTATIC_ASSERT_H */
|
||||
|
||||
/* Update scope counter outside of include guard. */
|
||||
#ifdef __PSTATIC_ASSERT_COUNTER
|
||||
#include "pstatic_assert_scope.h"
|
||||
#endif
|
||||
280
nostrdb/flatcc/portable/pstatic_assert_scope.h
Normal file
280
nostrdb/flatcc/portable/pstatic_assert_scope.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* january, 2017, ported to portable library by mikkelfj.
|
||||
* Based on dbgtools static assert counter, but with renamed macros.
|
||||
*/
|
||||
|
||||
/*
|
||||
dbgtools - platform independent wrapping of "nice to have" debug functions.
|
||||
|
||||
version 0.1, october, 2013
|
||||
|
||||
https://github.com/wc-duck/dbgtools
|
||||
|
||||
Copyright (C) 2013- Fredrik Kihlander
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Fredrik Kihlander
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-generated header implementing a counter that increases by each include of the file.
|
||||
*
|
||||
* This header will define the macro __PSTATIC_ASSERT_COUNTER to be increased for each inclusion of the file.
|
||||
*
|
||||
* It has been generated with 3 amount of digits resulting in the counter wrapping around after
|
||||
* 10000 inclusions.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* #include "this_header.h"
|
||||
* int a = __PSTATIC_ASSERT_COUNTER; // 0
|
||||
* #include "this_header.h"
|
||||
* int b = __PSTATIC_ASSERT_COUNTER; // 1
|
||||
* #include "this_header.h"
|
||||
* int c = __PSTATIC_ASSERT_COUNTER; // 2
|
||||
* #include "this_header.h"
|
||||
* int d = __PSTATIC_ASSERT_COUNTER; // 3
|
||||
*/
|
||||
|
||||
#ifndef __PSTATIC_ASSERT_COUNTER
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 0
|
||||
# define __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_0
|
||||
#endif /* __PSTATIC_ASSERT_COUNTER */
|
||||
|
||||
#if !defined( __PSTATIC_ASSERT_COUNTER_D0_0 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D0_0
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 0
|
||||
#elif !defined( __PSTATIC_ASSERT_COUNTER_D0_1 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D0_1
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 1
|
||||
#elif !defined( __PSTATIC_ASSERT_COUNTER_D0_2 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D0_2
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 2
|
||||
#elif !defined( __PSTATIC_ASSERT_COUNTER_D0_3 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D0_3
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 3
|
||||
#elif !defined( __PSTATIC_ASSERT_COUNTER_D0_4 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D0_4
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 4
|
||||
#elif !defined( __PSTATIC_ASSERT_COUNTER_D0_5 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D0_5
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 5
|
||||
#elif !defined( __PSTATIC_ASSERT_COUNTER_D0_6 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D0_6
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 6
|
||||
#elif !defined( __PSTATIC_ASSERT_COUNTER_D0_7 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D0_7
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 7
|
||||
#elif !defined( __PSTATIC_ASSERT_COUNTER_D0_8 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D0_8
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 8
|
||||
#elif !defined( __PSTATIC_ASSERT_COUNTER_D0_9 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D0_9
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 9
|
||||
#else
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D0_1
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D0_2
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D0_3
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D0_4
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D0_5
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D0_6
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D0_7
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D0_8
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D0_9
|
||||
# undef __PSTATIC_ASSERT_COUNTER_0
|
||||
# define __PSTATIC_ASSERT_COUNTER_0 0
|
||||
# if !defined( __PSTATIC_ASSERT_COUNTER_D1_0 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_0
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 0
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D1_1 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_1
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 1
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D1_2 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_2
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 2
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D1_3 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_3
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 3
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D1_4 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_4
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 4
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D1_5 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_5
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 5
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D1_6 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_6
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 6
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D1_7 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_7
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 7
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D1_8 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_8
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 8
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D1_9 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D1_9
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 9
|
||||
# else
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D1_1
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D1_2
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D1_3
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D1_4
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D1_5
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D1_6
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D1_7
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D1_8
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D1_9
|
||||
# undef __PSTATIC_ASSERT_COUNTER_1
|
||||
# define __PSTATIC_ASSERT_COUNTER_1 0
|
||||
# if !defined( __PSTATIC_ASSERT_COUNTER_D2_0 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_0
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 0
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D2_1 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_1
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 1
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D2_2 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_2
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 2
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D2_3 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_3
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 3
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D2_4 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_4
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 4
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D2_5 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_5
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 5
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D2_6 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_6
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 6
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D2_7 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_7
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 7
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D2_8 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_8
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 8
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D2_9 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D2_9
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 9
|
||||
# else
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D2_1
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D2_2
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D2_3
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D2_4
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D2_5
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D2_6
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D2_7
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D2_8
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D2_9
|
||||
# undef __PSTATIC_ASSERT_COUNTER_2
|
||||
# define __PSTATIC_ASSERT_COUNTER_2 0
|
||||
# if !defined( __PSTATIC_ASSERT_COUNTER_D3_0 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_0
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 0
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D3_1 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_1
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 1
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D3_2 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_2
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 2
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D3_3 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_3
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 3
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D3_4 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_4
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 4
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D3_5 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_5
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 5
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D3_6 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_6
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 6
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D3_7 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_7
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 7
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D3_8 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_8
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 8
|
||||
# elif !defined( __PSTATIC_ASSERT_COUNTER_D3_9 )
|
||||
# define __PSTATIC_ASSERT_COUNTER_D3_9
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 9
|
||||
# else
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D3_1
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D3_2
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D3_3
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D3_4
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D3_5
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D3_6
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D3_7
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D3_8
|
||||
# undef __PSTATIC_ASSERT_COUNTER_D3_9
|
||||
# undef __PSTATIC_ASSERT_COUNTER_3
|
||||
# define __PSTATIC_ASSERT_COUNTER_3 0
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define __PSTATIC_ASSERT_COUNTER_JOIN_DIGITS_MACRO_(digit0,digit1,digit2,digit3) digit0##digit1##digit2##digit3
|
||||
#define __PSTATIC_ASSERT_COUNTER_JOIN_DIGITS_MACRO(digit0,digit1,digit2,digit3) __PSTATIC_ASSERT_COUNTER_JOIN_DIGITS_MACRO_(digit0,digit1,digit2,digit3)
|
||||
#undef __PSTATIC_ASSERT_COUNTER
|
||||
#define __PSTATIC_ASSERT_COUNTER __PSTATIC_ASSERT_COUNTER_JOIN_DIGITS_MACRO(__PSTATIC_ASSERT_COUNTER_3,__PSTATIC_ASSERT_COUNTER_2,__PSTATIC_ASSERT_COUNTER_1,__PSTATIC_ASSERT_COUNTER_0)
|
||||
162
nostrdb/flatcc/portable/pstdalign.h
Normal file
162
nostrdb/flatcc/portable/pstdalign.h
Normal file
@@ -0,0 +1,162 @@
|
||||
#ifndef PSTDALIGN_H
|
||||
#define PSTDALIGN_H
|
||||
|
||||
/*
|
||||
* NOTE: aligned_alloc is defined via paligned_alloc.h
|
||||
* and requires aligned_free to be fully portable although
|
||||
* free also works on C11 and platforms with posix_memalign.
|
||||
*
|
||||
* NOTE: C++11 defines alignas as a keyword but then also defines
|
||||
* __alignas_is_defined.
|
||||
*
|
||||
* C++14 does not define __alignas_is_defined, at least sometimes.
|
||||
*
|
||||
* GCC 8.3 reverts on this and makes C++11 behave the same as C++14
|
||||
* preventing a simple __cplusplus version check from working.
|
||||
*
|
||||
* Clang C++ without std=c++11 or std=c++14 does define alignas
|
||||
* but does so incorrectly wrt. C11 and C++11 semantics because
|
||||
* `alignas(4) float x;` is not recognized.
|
||||
* To fix such issues, either move to a std version, or
|
||||
* include a working stdalign.h for the given compiler before
|
||||
* this file.
|
||||
*
|
||||
* newlib defines _Alignas and _Alignof in sys/cdefs but rely on
|
||||
* gcc version for <stdaligh.h> which can lead to conflicts if
|
||||
* stdalign is not included.
|
||||
*
|
||||
* newlibs need for <stdalign.h> conflicts with broken C++ stdalign
|
||||
* but this can be fixed be using std=C++11 or newer.
|
||||
*
|
||||
* MSVC does not support <stdalign.h> at least up to MSVC 2015,
|
||||
* but does appear to support alignas and alignof keywords in
|
||||
* recent standard C++.
|
||||
*
|
||||
* TCC only supports alignas with a numeric argument like
|
||||
* `alignas(4)`, but not `alignas(float)`.
|
||||
*
|
||||
* If stdalign.h is supported but heuristics in this file are
|
||||
* insufficient to detect this, try including <stdaligh.h> manually
|
||||
* or define HAVE_STDALIGN_H.
|
||||
*/
|
||||
|
||||
/* https://github.com/dvidelabs/flatcc/issues/130 */
|
||||
#ifndef __alignas_is_defined
|
||||
#if defined(__cplusplus)
|
||||
#if __cplusplus == 201103 && !defined(__clang__) && ((__GNUC__ > 8) || (__GNUC__ == 8 && __GNUC_MINOR__ >= 3))
|
||||
#define __alignas_is_defined 1
|
||||
#define __alignof_is_defined 1
|
||||
#include <stdalign.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Allow for alternative solution to be included first. */
|
||||
#ifndef __alignas_is_defined
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(PORTABLE_PATCH_CPLUSPLUS_STDALIGN)
|
||||
#include <stdalign.h>
|
||||
#undef alignas
|
||||
#define alignas(t) __attribute__((__aligned__(t)))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(PORTABLE_HAS_INCLUDE_STDALIGN)
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<stdalign.h>)
|
||||
#define PORTABLE_HAS_INCLUDE_STDALIGN 1
|
||||
#else
|
||||
#define PORTABLE_HAS_INCLUDE_STDALIGN 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* https://lists.gnu.org/archive/html/bug-gnulib/2015-08/msg00003.html */
|
||||
#if defined(__cplusplus)
|
||||
#if !defined(_MSC_VER)
|
||||
#include <stdalign.h>
|
||||
#endif
|
||||
#if __cplusplus > 201103
|
||||
#define __alignas_is_defined 1
|
||||
#define __alignof_is_defined 1
|
||||
#endif
|
||||
#elif PORTABLE_HAS_INCLUDE_STDALIGN
|
||||
#include <stdalign.h>
|
||||
#elif !defined(__clang__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
|
||||
#include <stdalign.h>
|
||||
#elif defined(HAVE_STDALIGN_H)
|
||||
#include <stdaligh.h>
|
||||
#endif
|
||||
|
||||
#endif /* __alignas_is_defined */
|
||||
|
||||
#ifndef __alignas_is_defined
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (!defined(__clang__) && defined(__GNUC__) && \
|
||||
((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)))
|
||||
#undef PORTABLE_C11_STDALIGN_MISSING
|
||||
#define PORTABLE_C11_STDALIGN_MISSING
|
||||
#endif
|
||||
|
||||
#if defined(__IBMC__)
|
||||
#undef PORTABLE_C11_STDALIGN_MISSING
|
||||
#define PORTABLE_C11_STDALIGN_MISSING
|
||||
#endif
|
||||
|
||||
#if ((defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) && \
|
||||
!defined(PORTABLE_C11_STDALIGN_MISSING))
|
||||
/* C11 or newer */
|
||||
#include <stdalign.h>
|
||||
#else
|
||||
#if defined(__GNUC__) || defined(__IBM_ALIGNOF__) || defined(__clang__)
|
||||
|
||||
#ifndef _Alignas
|
||||
#define _Alignas(t) __attribute__((__aligned__(t)))
|
||||
#endif
|
||||
|
||||
#ifndef _Alignof
|
||||
#define _Alignof(t) __alignof__(t)
|
||||
#endif
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
#define _Alignas(t) __declspec (align(t))
|
||||
#define _Alignof(t) __alignof(t)
|
||||
|
||||
#elif defined(__TINYC__)
|
||||
|
||||
/* Supports `_Alignas(integer-expression)`, but not `_Alignas(type)`. */
|
||||
#define _Alignas(t) __attribute__(aligned(t))
|
||||
#define _Alignof(t) __alignof__(t)
|
||||
|
||||
#else
|
||||
#error please update pstdalign.h with support for current compiler and library
|
||||
#endif
|
||||
|
||||
#endif /* __STDC__ */
|
||||
|
||||
#ifndef alignas
|
||||
#define alignas _Alignas
|
||||
#endif
|
||||
|
||||
#ifndef alignof
|
||||
#define alignof _Alignof
|
||||
#endif
|
||||
|
||||
#define __alignas_is_defined 1
|
||||
#define __alignof_is_defined 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __alignas__is_defined */
|
||||
|
||||
#include "paligned_alloc.h"
|
||||
|
||||
#endif /* PSTDALIGN_H */
|
||||
37
nostrdb/flatcc/portable/pstdbool.h
Normal file
37
nostrdb/flatcc/portable/pstdbool.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef PSTDBOOL_H
|
||||
#define PSTDBOOL_H
|
||||
|
||||
#if !defined(__cplusplus) && !__bool_true_false_are_defined && !defined(bool) && !defined(__STDBOOL_H)
|
||||
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#elif (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
|
||||
/* C99 or newer */
|
||||
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
#define bool bool
|
||||
#define true true
|
||||
#define false false
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#else
|
||||
|
||||
typedef unsigned char _Portable_bool;
|
||||
#define bool _Portable_bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PSTDBOOL_H */
|
||||
898
nostrdb/flatcc/portable/pstdint.h
Normal file
898
nostrdb/flatcc/portable/pstdint.h
Normal file
@@ -0,0 +1,898 @@
|
||||
/* A portable stdint.h
|
||||
****************************************************************************
|
||||
* BSD License:
|
||||
****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2005-2016 Paul Hsieh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* Version 0.1.15.2
|
||||
*
|
||||
* The ANSI C standard committee, for the C99 standard, specified the
|
||||
* inclusion of a new standard include file called stdint.h. This is
|
||||
* a very useful and long desired include file which contains several
|
||||
* very precise definitions for integer scalar types that is
|
||||
* critically important for making portable several classes of
|
||||
* applications including cryptography, hashing, variable length
|
||||
* integer libraries and so on. But for most developers its likely
|
||||
* useful just for programming sanity.
|
||||
*
|
||||
* The problem is that some compiler vendors chose to ignore the C99
|
||||
* standard and some older compilers have no opportunity to be updated.
|
||||
* Because of this situation, simply including stdint.h in your code
|
||||
* makes it unportable.
|
||||
*
|
||||
* So that's what this file is all about. Its an attempt to build a
|
||||
* single universal include file that works on as many platforms as
|
||||
* possible to deliver what stdint.h is supposed to. Even compilers
|
||||
* that already come with stdint.h can use this file instead without
|
||||
* any loss of functionality. A few things that should be noted about
|
||||
* this file:
|
||||
*
|
||||
* 1) It is not guaranteed to be portable and/or present an identical
|
||||
* interface on all platforms. The extreme variability of the
|
||||
* ANSI C standard makes this an impossibility right from the
|
||||
* very get go. Its really only meant to be useful for the vast
|
||||
* majority of platforms that possess the capability of
|
||||
* implementing usefully and precisely defined, standard sized
|
||||
* integer scalars. Systems which are not intrinsically 2s
|
||||
* complement may produce invalid constants.
|
||||
*
|
||||
* 2) There is an unavoidable use of non-reserved symbols.
|
||||
*
|
||||
* 3) Other standard include files are invoked.
|
||||
*
|
||||
* 4) This file may come in conflict with future platforms that do
|
||||
* include stdint.h. The hope is that one or the other can be
|
||||
* used with no real difference.
|
||||
*
|
||||
* 5) In the current verison, if your platform can't represent
|
||||
* int32_t, int16_t and int8_t, it just dumps out with a compiler
|
||||
* error.
|
||||
*
|
||||
* 6) 64 bit integers may or may not be defined. Test for their
|
||||
* presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
|
||||
* Note that this is different from the C99 specification which
|
||||
* requires the existence of 64 bit support in the compiler. If
|
||||
* this is not defined for your platform, yet it is capable of
|
||||
* dealing with 64 bits then it is because this file has not yet
|
||||
* been extended to cover all of your system's capabilities.
|
||||
*
|
||||
* 7) (u)intptr_t may or may not be defined. Test for its presence
|
||||
* with the test: #ifdef PTRDIFF_MAX. If this is not defined
|
||||
* for your platform, then it is because this file has not yet
|
||||
* been extended to cover all of your system's capabilities, not
|
||||
* because its optional.
|
||||
*
|
||||
* 8) The following might not been defined even if your platform is
|
||||
* capable of defining it:
|
||||
*
|
||||
* WCHAR_MIN
|
||||
* WCHAR_MAX
|
||||
* (u)int64_t
|
||||
* PTRDIFF_MIN
|
||||
* PTRDIFF_MAX
|
||||
* (u)intptr_t
|
||||
*
|
||||
* 9) The following have not been defined:
|
||||
*
|
||||
* WINT_MIN
|
||||
* WINT_MAX
|
||||
*
|
||||
* 10) The criteria for defining (u)int_least(*)_t isn't clear,
|
||||
* except for systems which don't have a type that precisely
|
||||
* defined 8, 16, or 32 bit types (which this include file does
|
||||
* not support anyways). Default definitions have been given.
|
||||
*
|
||||
* 11) The criteria for defining (u)int_fast(*)_t isn't something I
|
||||
* would trust to any particular compiler vendor or the ANSI C
|
||||
* committee. It is well known that "compatible systems" are
|
||||
* commonly created that have very different performance
|
||||
* characteristics from the systems they are compatible with,
|
||||
* especially those whose vendors make both the compiler and the
|
||||
* system. Default definitions have been given, but its strongly
|
||||
* recommended that users never use these definitions for any
|
||||
* reason (they do *NOT* deliver any serious guarantee of
|
||||
* improved performance -- not in this file, nor any vendor's
|
||||
* stdint.h).
|
||||
*
|
||||
* 12) The following macros:
|
||||
*
|
||||
* PRINTF_INTMAX_MODIFIER
|
||||
* PRINTF_INT64_MODIFIER
|
||||
* PRINTF_INT32_MODIFIER
|
||||
* PRINTF_INT16_MODIFIER
|
||||
* PRINTF_LEAST64_MODIFIER
|
||||
* PRINTF_LEAST32_MODIFIER
|
||||
* PRINTF_LEAST16_MODIFIER
|
||||
* PRINTF_INTPTR_MODIFIER
|
||||
*
|
||||
* are strings which have been defined as the modifiers required
|
||||
* for the "d", "u" and "x" printf formats to correctly output
|
||||
* (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
|
||||
* (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
|
||||
* PRINTF_INTPTR_MODIFIER is not defined for some systems which
|
||||
* provide their own stdint.h. PRINTF_INT64_MODIFIER is not
|
||||
* defined if INT64_MAX is not defined. These are an extension
|
||||
* beyond what C99 specifies must be in stdint.h.
|
||||
*
|
||||
* In addition, the following macros are defined:
|
||||
*
|
||||
* PRINTF_INTMAX_HEX_WIDTH
|
||||
* PRINTF_INT64_HEX_WIDTH
|
||||
* PRINTF_INT32_HEX_WIDTH
|
||||
* PRINTF_INT16_HEX_WIDTH
|
||||
* PRINTF_INT8_HEX_WIDTH
|
||||
* PRINTF_INTMAX_DEC_WIDTH
|
||||
* PRINTF_INT64_DEC_WIDTH
|
||||
* PRINTF_INT32_DEC_WIDTH
|
||||
* PRINTF_INT16_DEC_WIDTH
|
||||
* PRINTF_UINT8_DEC_WIDTH
|
||||
* PRINTF_UINTMAX_DEC_WIDTH
|
||||
* PRINTF_UINT64_DEC_WIDTH
|
||||
* PRINTF_UINT32_DEC_WIDTH
|
||||
* PRINTF_UINT16_DEC_WIDTH
|
||||
* PRINTF_UINT8_DEC_WIDTH
|
||||
*
|
||||
* Which specifies the maximum number of characters required to
|
||||
* print the number of that type in either hexadecimal or decimal.
|
||||
* These are an extension beyond what C99 specifies must be in
|
||||
* stdint.h.
|
||||
*
|
||||
* Compilers tested (all with 0 warnings at their highest respective
|
||||
* settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
|
||||
* bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
|
||||
* .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
|
||||
*
|
||||
* This file should be considered a work in progress. Suggestions for
|
||||
* improvements, especially those which increase coverage are strongly
|
||||
* encouraged.
|
||||
*
|
||||
* Acknowledgements
|
||||
*
|
||||
* The following people have made significant contributions to the
|
||||
* development and testing of this file:
|
||||
*
|
||||
* Chris Howie
|
||||
* John Steele Scott
|
||||
* Dave Thorup
|
||||
* John Dill
|
||||
* Florian Wobbe
|
||||
* Christopher Sean Morrison
|
||||
* Mikkel Fahnoe Jorgensen
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
|
||||
/*
|
||||
* For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
|
||||
* do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
|
||||
*/
|
||||
|
||||
#if ((defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (__GNUC__ > 3 || defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED)
|
||||
#include <stdint.h>
|
||||
#define _PSTDINT_H_INCLUDED
|
||||
# if defined(__GNUC__) && (defined(__x86_64__) || defined(__ppc64__)) && !(defined(__APPLE__) && defined(__MACH__))
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "l"
|
||||
# endif
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
# else
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# if (UINT_MAX == UINT32_MAX)
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# else
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_MODIFIER
|
||||
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
|
||||
# endif
|
||||
# ifndef PRINTF_INT64_HEX_WIDTH
|
||||
# define PRINTF_INT64_HEX_WIDTH "16"
|
||||
# endif
|
||||
# ifndef PRINTF_UINT64_HEX_WIDTH
|
||||
# define PRINTF_UINT64_HEX_WIDTH "16"
|
||||
# endif
|
||||
# ifndef PRINTF_INT32_HEX_WIDTH
|
||||
# define PRINTF_INT32_HEX_WIDTH "8"
|
||||
# endif
|
||||
# ifndef PRINTF_UINT32_HEX_WIDTH
|
||||
# define PRINTF_UINT32_HEX_WIDTH "8"
|
||||
# endif
|
||||
# ifndef PRINTF_INT16_HEX_WIDTH
|
||||
# define PRINTF_INT16_HEX_WIDTH "4"
|
||||
# endif
|
||||
# ifndef PRINTF_UINT16_HEX_WIDTH
|
||||
# define PRINTF_UINT16_HEX_WIDTH "4"
|
||||
# endif
|
||||
# ifndef PRINTF_INT8_HEX_WIDTH
|
||||
# define PRINTF_INT8_HEX_WIDTH "2"
|
||||
# endif
|
||||
# ifndef PRINTF_UINT8_HEX_WIDTH
|
||||
# define PRINTF_UINT8_HEX_WIDTH "2"
|
||||
# endif
|
||||
# ifndef PRINTF_INT64_DEC_WIDTH
|
||||
# define PRINTF_INT64_DEC_WIDTH "19"
|
||||
# endif
|
||||
# ifndef PRINTF_UINT64_DEC_WIDTH
|
||||
# define PRINTF_UINT64_DEC_WIDTH "20"
|
||||
# endif
|
||||
# ifndef PRINTF_INT32_DEC_WIDTH
|
||||
# define PRINTF_INT32_DEC_WIDTH "10"
|
||||
# endif
|
||||
# ifndef PRINTF_UINT32_DEC_WIDTH
|
||||
# define PRINTF_UINT32_DEC_WIDTH "10"
|
||||
# endif
|
||||
# ifndef PRINTF_INT16_DEC_WIDTH
|
||||
# define PRINTF_INT16_DEC_WIDTH "5"
|
||||
# endif
|
||||
# ifndef PRINTF_UINT16_DEC_WIDTH
|
||||
# define PRINTF_UINT16_DEC_WIDTH "5"
|
||||
# endif
|
||||
# ifndef PRINTF_INT8_DEC_WIDTH
|
||||
# define PRINTF_INT8_DEC_WIDTH "3"
|
||||
# endif
|
||||
# ifndef PRINTF_UINT8_DEC_WIDTH
|
||||
# define PRINTF_UINT8_DEC_WIDTH "3"
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_HEX_WIDTH
|
||||
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_UINTMAX_HEX_WIDTH
|
||||
# define PRINTF_UINTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_DEC_WIDTH
|
||||
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_UINTMAX_DEC_WIDTH
|
||||
# define PRINTF_UINTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Something really weird is going on with Open Watcom. Just pull some of
|
||||
* these duplicated definitions from Open Watcom's stdint.h file for now.
|
||||
*/
|
||||
|
||||
# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
|
||||
# if !defined (INT64_C)
|
||||
# define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
|
||||
# endif
|
||||
# if !defined (UINT64_C)
|
||||
# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
|
||||
# endif
|
||||
# if !defined (INT32_C)
|
||||
# define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
|
||||
# endif
|
||||
# if !defined (UINT32_C)
|
||||
# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
|
||||
# endif
|
||||
# if !defined (INT16_C)
|
||||
# define INT16_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT16_C)
|
||||
# define UINT16_C(x) (x)
|
||||
# endif
|
||||
# if !defined (INT8_C)
|
||||
# define INT8_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT8_C)
|
||||
# define UINT8_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT64_MAX)
|
||||
# define UINT64_MAX 18446744073709551615ULL
|
||||
# endif
|
||||
# if !defined (INT64_MAX)
|
||||
# define INT64_MAX 9223372036854775807LL
|
||||
# endif
|
||||
# if !defined (UINT32_MAX)
|
||||
# define UINT32_MAX 4294967295UL
|
||||
# endif
|
||||
# if !defined (INT32_MAX)
|
||||
# define INT32_MAX 2147483647L
|
||||
# endif
|
||||
# if !defined (INTMAX_MAX)
|
||||
# define INTMAX_MAX INT64_MAX
|
||||
# endif
|
||||
# if !defined (INTMAX_MIN)
|
||||
# define INTMAX_MIN INT64_MIN
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _PSTDINT_H_INCLUDED
|
||||
#define _PSTDINT_H_INCLUDED
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX (~(size_t)0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Deduce the type assignments from limits.h under the assumption that
|
||||
* integer sizes in bits are powers of 2, and follow the ANSI
|
||||
* definitions.
|
||||
*/
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
# define UINT8_MAX 0xff
|
||||
#endif
|
||||
#if !defined(uint8_t) && !defined(_UINT8_T)
|
||||
# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned char uint8_t;
|
||||
# define UINT8_C(v) ((uint8_t) v)
|
||||
# else
|
||||
# error "Platform not supported"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef INT8_MAX
|
||||
# define INT8_MAX 0x7f
|
||||
#endif
|
||||
#ifndef INT8_MIN
|
||||
# define INT8_MIN INT8_C(0x80)
|
||||
#endif
|
||||
#if !defined(int8_t) && !defined(_INT8_T)
|
||||
# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed char int8_t;
|
||||
# define INT8_C(v) ((int8_t) v)
|
||||
# else
|
||||
# error "Platform not supported"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef UINT16_MAX
|
||||
# define UINT16_MAX 0xffff
|
||||
#endif
|
||||
#if !defined(uint16_t) && !defined(_UINT16_T)
|
||||
#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned int uint16_t;
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER ""
|
||||
# endif
|
||||
# define UINT16_C(v) ((uint16_t) (v))
|
||||
#elif (USHRT_MAX == UINT16_MAX)
|
||||
typedef unsigned short uint16_t;
|
||||
# define UINT16_C(v) ((uint16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MAX
|
||||
# define INT16_MAX 0x7fff
|
||||
#endif
|
||||
#ifndef INT16_MIN
|
||||
# define INT16_MIN INT16_C(0x8000)
|
||||
#endif
|
||||
#if !defined(int16_t) && !defined(_INT16_T)
|
||||
#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed int int16_t;
|
||||
# define INT16_C(v) ((int16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER ""
|
||||
# endif
|
||||
#elif (SHRT_MAX == INT16_MAX)
|
||||
typedef signed short int16_t;
|
||||
# define INT16_C(v) ((int16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
# define UINT32_MAX (0xffffffffUL)
|
||||
#endif
|
||||
#if !defined(uint32_t) && !defined(_UINT32_T)
|
||||
#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned long uint32_t;
|
||||
# define UINT32_C(v) v ## UL
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
#elif (UINT_MAX == UINT32_MAX)
|
||||
typedef unsigned int uint32_t;
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
# define UINT32_C(v) v ## U
|
||||
#elif (USHRT_MAX == UINT32_MAX)
|
||||
typedef unsigned short uint32_t;
|
||||
# define UINT32_C(v) ((unsigned short) (v))
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MAX
|
||||
# define INT32_MAX (0x7fffffffL)
|
||||
#endif
|
||||
#ifndef INT32_MIN
|
||||
# define INT32_MIN INT32_C(0x80000000)
|
||||
#endif
|
||||
#if !defined(int32_t) && !defined(_INT32_T)
|
||||
#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed long int32_t;
|
||||
# define INT32_C(v) v ## L
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
#elif (INT_MAX == INT32_MAX)
|
||||
typedef signed int int32_t;
|
||||
# define INT32_C(v) v
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
#elif (SHRT_MAX == INT32_MAX)
|
||||
typedef signed short int32_t;
|
||||
# define INT32_C(v) ((short) (v))
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The macro stdint_int64_defined is temporarily used to record
|
||||
* whether or not 64 integer support is available. It must be
|
||||
* defined for any 64 integer extensions for new platforms that are
|
||||
* added.
|
||||
*/
|
||||
|
||||
#undef stdint_int64_defined
|
||||
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
|
||||
# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S)
|
||||
# define stdint_int64_defined
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (stdint_int64_defined)
|
||||
# if defined(__GNUC__)
|
||||
# define stdint_int64_defined
|
||||
__extension__ typedef long long int64_t;
|
||||
__extension__ typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
|
||||
# define stdint_int64_defined
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
|
||||
# define stdint_int64_defined
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# define UINT64_C(v) v ## UI64
|
||||
# define INT64_C(v) v ## I64
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "I64"
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (LONG_LONG_MAX) && defined (INT64_C)
|
||||
# define LONG_LONG_MAX INT64_C (9223372036854775807)
|
||||
#endif
|
||||
#ifndef ULONG_LONG_MAX
|
||||
# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
|
||||
#endif
|
||||
|
||||
#if !defined (INT64_MAX) && defined (INT64_C)
|
||||
# define INT64_MAX INT64_C (9223372036854775807)
|
||||
#endif
|
||||
#if !defined (INT64_MIN) && defined (INT64_C)
|
||||
# define INT64_MIN INT64_C (-9223372036854775808)
|
||||
#endif
|
||||
#if !defined (UINT64_MAX) && defined (INT64_C)
|
||||
# define UINT64_MAX UINT64_C (18446744073709551615)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Width of hexadecimal for number field.
|
||||
*/
|
||||
|
||||
#ifndef PRINTF_INT64_HEX_WIDTH
|
||||
# define PRINTF_INT64_HEX_WIDTH "16"
|
||||
#endif
|
||||
#ifndef PRINTF_INT32_HEX_WIDTH
|
||||
# define PRINTF_INT32_HEX_WIDTH "8"
|
||||
#endif
|
||||
#ifndef PRINTF_INT16_HEX_WIDTH
|
||||
# define PRINTF_INT16_HEX_WIDTH "4"
|
||||
#endif
|
||||
#ifndef PRINTF_INT8_HEX_WIDTH
|
||||
# define PRINTF_INT8_HEX_WIDTH "2"
|
||||
#endif
|
||||
#ifndef PRINTF_INT64_DEC_WIDTH
|
||||
# define PRINTF_INT64_DEC_WIDTH "19"
|
||||
#endif
|
||||
#ifndef PRINTF_INT32_DEC_WIDTH
|
||||
# define PRINTF_INT32_DEC_WIDTH "10"
|
||||
#endif
|
||||
#ifndef PRINTF_INT16_DEC_WIDTH
|
||||
# define PRINTF_INT16_DEC_WIDTH "5"
|
||||
#endif
|
||||
#ifndef PRINTF_INT8_DEC_WIDTH
|
||||
# define PRINTF_INT8_DEC_WIDTH "3"
|
||||
#endif
|
||||
#ifndef PRINTF_UINT64_DEC_WIDTH
|
||||
# define PRINTF_UINT64_DEC_WIDTH "20"
|
||||
#endif
|
||||
#ifndef PRINTF_UINT32_DEC_WIDTH
|
||||
# define PRINTF_UINT32_DEC_WIDTH "10"
|
||||
#endif
|
||||
#ifndef PRINTF_UINT16_DEC_WIDTH
|
||||
# define PRINTF_UINT16_DEC_WIDTH "5"
|
||||
#endif
|
||||
#ifndef PRINTF_UINT8_DEC_WIDTH
|
||||
# define PRINTF_UINT8_DEC_WIDTH "3"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ok, lets not worry about 128 bit integers for now. Moore's law says
|
||||
* we don't need to worry about that until about 2040 at which point
|
||||
* we'll have bigger things to worry about.
|
||||
*/
|
||||
|
||||
#ifdef stdint_int64_defined
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
# define INTMAX_MAX INT64_MAX
|
||||
# define INTMAX_MIN INT64_MIN
|
||||
# define UINTMAX_MAX UINT64_MAX
|
||||
# define UINTMAX_C(v) UINT64_C(v)
|
||||
# define INTMAX_C(v) INT64_C(v)
|
||||
# ifndef PRINTF_INTMAX_MODIFIER
|
||||
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_HEX_WIDTH
|
||||
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_DEC_WIDTH
|
||||
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
|
||||
# endif
|
||||
#else
|
||||
typedef int32_t intmax_t;
|
||||
typedef uint32_t uintmax_t;
|
||||
# define INTMAX_MAX INT32_MAX
|
||||
# define UINTMAX_MAX UINT32_MAX
|
||||
# define UINTMAX_C(v) UINT32_C(v)
|
||||
# define INTMAX_C(v) INT32_C(v)
|
||||
# ifndef PRINTF_INTMAX_MODIFIER
|
||||
# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_HEX_WIDTH
|
||||
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_DEC_WIDTH
|
||||
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Because this file currently only supports platforms which have
|
||||
* precise powers of 2 as bit sizes for the default integers, the
|
||||
* least definitions are all trivial. Its possible that a future
|
||||
* version of this file could have different definitions.
|
||||
*/
|
||||
|
||||
#ifndef stdint_least_defined
|
||||
typedef int8_t int_least8_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
|
||||
# define UINT_LEAST8_MAX UINT8_MAX
|
||||
# define INT_LEAST8_MAX INT8_MAX
|
||||
# define UINT_LEAST16_MAX UINT16_MAX
|
||||
# define INT_LEAST16_MAX INT16_MAX
|
||||
# define UINT_LEAST32_MAX UINT32_MAX
|
||||
# define INT_LEAST32_MAX INT32_MAX
|
||||
# define INT_LEAST8_MIN INT8_MIN
|
||||
# define INT_LEAST16_MIN INT16_MIN
|
||||
# define INT_LEAST32_MIN INT32_MIN
|
||||
# ifdef stdint_int64_defined
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
|
||||
# define UINT_LEAST64_MAX UINT64_MAX
|
||||
# define INT_LEAST64_MAX INT64_MAX
|
||||
# define INT_LEAST64_MIN INT64_MIN
|
||||
# endif
|
||||
#endif
|
||||
#undef stdint_least_defined
|
||||
|
||||
/*
|
||||
* The ANSI C committee pretending to know or specify anything about
|
||||
* performance is the epitome of misguided arrogance. The mandate of
|
||||
* this file is to *ONLY* ever support that absolute minimum
|
||||
* definition of the fast integer types, for compatibility purposes.
|
||||
* No extensions, and no attempt to suggest what may or may not be a
|
||||
* faster integer type will ever be made in this file. Developers are
|
||||
* warned to stay away from these types when using this or any other
|
||||
* stdint.h.
|
||||
*/
|
||||
|
||||
typedef int_least8_t int_fast8_t;
|
||||
typedef uint_least8_t uint_fast8_t;
|
||||
typedef int_least16_t int_fast16_t;
|
||||
typedef uint_least16_t uint_fast16_t;
|
||||
typedef int_least32_t int_fast32_t;
|
||||
typedef uint_least32_t uint_fast32_t;
|
||||
#define UINT_FAST8_MAX UINT_LEAST8_MAX
|
||||
#define INT_FAST8_MAX INT_LEAST8_MAX
|
||||
#define UINT_FAST16_MAX UINT_LEAST16_MAX
|
||||
#define INT_FAST16_MAX INT_LEAST16_MAX
|
||||
#define UINT_FAST32_MAX UINT_LEAST32_MAX
|
||||
#define INT_FAST32_MAX INT_LEAST32_MAX
|
||||
#define INT_FAST8_MIN INT_LEAST8_MIN
|
||||
#define INT_FAST16_MIN INT_LEAST16_MIN
|
||||
#define INT_FAST32_MIN INT_LEAST32_MIN
|
||||
#ifdef stdint_int64_defined
|
||||
typedef int_least64_t int_fast64_t;
|
||||
typedef uint_least64_t uint_fast64_t;
|
||||
# define UINT_FAST64_MAX UINT_LEAST64_MAX
|
||||
# define INT_FAST64_MAX INT_LEAST64_MAX
|
||||
# define INT_FAST64_MIN INT_LEAST64_MIN
|
||||
#endif
|
||||
|
||||
#undef stdint_int64_defined
|
||||
|
||||
/*
|
||||
* Whatever piecemeal, per compiler thing we can do about the wchar_t
|
||||
* type limits.
|
||||
*/
|
||||
|
||||
#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
|
||||
# include <wchar.h>
|
||||
# ifndef WCHAR_MIN
|
||||
# define WCHAR_MIN 0
|
||||
# endif
|
||||
# ifndef WCHAR_MAX
|
||||
# define WCHAR_MAX ((wchar_t)-1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whatever piecemeal, per compiler/platform thing we can do about the
|
||||
* (u)intptr_t types and limits.
|
||||
*/
|
||||
|
||||
#if (defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)) || defined (_UINTPTR_T)
|
||||
# define STDINT_H_UINTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
#ifndef STDINT_H_UINTPTR_T_DEFINED
|
||||
# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) || defined (__ppc64__)
|
||||
# define stdint_intptr_bits 64
|
||||
# elif defined (__WATCOMC__) || defined (__TURBOC__)
|
||||
# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
|
||||
# define stdint_intptr_bits 16
|
||||
# else
|
||||
# define stdint_intptr_bits 32
|
||||
# endif
|
||||
# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) || defined (__ppc64__)
|
||||
# define stdint_intptr_bits 32
|
||||
# elif defined (__INTEL_COMPILER)
|
||||
/* TODO -- what did Intel do about x86-64? */
|
||||
# else
|
||||
/* #error "This platform might not be supported yet" */
|
||||
# endif
|
||||
|
||||
# ifdef stdint_intptr_bits
|
||||
# define stdint_intptr_glue3_i(a,b,c) a##b##c
|
||||
# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
|
||||
# ifndef PRINTF_INTPTR_MODIFIER
|
||||
# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
|
||||
# endif
|
||||
# ifndef PTRDIFF_MAX
|
||||
# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
|
||||
# endif
|
||||
# ifndef PTRDIFF_MIN
|
||||
# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
|
||||
# endif
|
||||
# ifndef UINTPTR_MAX
|
||||
# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
|
||||
# endif
|
||||
# ifndef INTPTR_MAX
|
||||
# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
|
||||
# endif
|
||||
# ifndef INTPTR_MIN
|
||||
# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
|
||||
# endif
|
||||
# ifndef INTPTR_C
|
||||
# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
|
||||
# endif
|
||||
# ifndef UINTPTR_C
|
||||
# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
|
||||
# endif
|
||||
typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
|
||||
typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
|
||||
# else
|
||||
/* TODO -- This following is likely wrong for some platforms, and does
|
||||
nothing for the definition of uintptr_t. */
|
||||
typedef ptrdiff_t intptr_t;
|
||||
# endif
|
||||
# define STDINT_H_UINTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Assumes sig_atomic_t is signed and we have a 2s complement machine.
|
||||
*/
|
||||
|
||||
#ifndef SIG_ATOMIC_MAX
|
||||
# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
|
||||
|
||||
/*
|
||||
* Please compile with the maximum warning settings to make sure macros are
|
||||
* not defined more than once.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define glue3_aux(x,y,z) x ## y ## z
|
||||
#define glue3(x,y,z) glue3_aux(x,y,z)
|
||||
|
||||
#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,) = glue3(UINT,bits,_C) (0);
|
||||
#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,) = glue3(INT,bits,_C) (0);
|
||||
|
||||
#define DECL(us,bits) glue3(DECL,us,) (bits)
|
||||
|
||||
#define TESTUMAX(bits) glue3(u,bits,) = ~glue3(u,bits,); if (glue3(UINT,bits,_MAX) != glue3(u,bits,)) printf ("Something wrong with UINT%d_MAX\n", bits)
|
||||
|
||||
#define REPORTERROR(msg) { err_n++; if (err_first <= 0) err_first = __LINE__; printf msg; }
|
||||
|
||||
int main () {
|
||||
int err_n = 0;
|
||||
int err_first = 0;
|
||||
DECL(I,8)
|
||||
DECL(U,8)
|
||||
DECL(I,16)
|
||||
DECL(U,16)
|
||||
DECL(I,32)
|
||||
DECL(U,32)
|
||||
#ifdef INT64_MAX
|
||||
DECL(I,64)
|
||||
DECL(U,64)
|
||||
#endif
|
||||
intmax_t imax = INTMAX_C(0);
|
||||
uintmax_t umax = UINTMAX_C(0);
|
||||
char str0[256], str1[256];
|
||||
|
||||
sprintf (str0, "%" PRINTF_INT32_MODIFIER "d", INT32_C(2147483647));
|
||||
if (0 != strcmp (str0, "2147483647")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0));
|
||||
if (atoi(PRINTF_INT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_INT32_DEC_WIDTH : %s\n", PRINTF_INT32_DEC_WIDTH));
|
||||
sprintf (str0, "%" PRINTF_INT32_MODIFIER "u", UINT32_C(4294967295));
|
||||
if (0 != strcmp (str0, "4294967295")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0));
|
||||
if (atoi(PRINTF_UINT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_UINT32_DEC_WIDTH : %s\n", PRINTF_UINT32_DEC_WIDTH));
|
||||
#ifdef INT64_MAX
|
||||
sprintf (str1, "%" PRINTF_INT64_MODIFIER "d", INT64_C(9223372036854775807));
|
||||
if (0 != strcmp (str1, "9223372036854775807")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1));
|
||||
if (atoi(PRINTF_INT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_INT64_DEC_WIDTH : %s, %d\n", PRINTF_INT64_DEC_WIDTH, (int) strlen(str1)));
|
||||
sprintf (str1, "%" PRINTF_INT64_MODIFIER "u", UINT64_C(18446744073709550591));
|
||||
if (0 != strcmp (str1, "18446744073709550591")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1));
|
||||
if (atoi(PRINTF_UINT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_UINT64_DEC_WIDTH : %s, %d\n", PRINTF_UINT64_DEC_WIDTH, (int) strlen(str1)));
|
||||
#endif
|
||||
|
||||
sprintf (str0, "%d %x\n", 0, ~0);
|
||||
|
||||
sprintf (str1, "%d %x\n", i8, ~0);
|
||||
if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i8 : %s\n", str1));
|
||||
sprintf (str1, "%u %x\n", u8, ~0);
|
||||
if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u8 : %s\n", str1));
|
||||
sprintf (str1, "%d %x\n", i16, ~0);
|
||||
if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i16 : %s\n", str1));
|
||||
sprintf (str1, "%u %x\n", u16, ~0);
|
||||
if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u16 : %s\n", str1));
|
||||
sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
|
||||
if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i32 : %s\n", str1));
|
||||
sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
|
||||
if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u32 : %s\n", str1));
|
||||
#ifdef INT64_MAX
|
||||
sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
|
||||
if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i64 : %s\n", str1));
|
||||
#endif
|
||||
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
|
||||
if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with imax : %s\n", str1));
|
||||
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
|
||||
if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with umax : %s\n", str1));
|
||||
|
||||
TESTUMAX(8);
|
||||
TESTUMAX(16);
|
||||
TESTUMAX(32);
|
||||
#ifdef INT64_MAX
|
||||
TESTUMAX(64);
|
||||
#endif
|
||||
|
||||
#define STR(v) #v
|
||||
#define Q(v) printf ("sizeof " STR(v) " = %u\n", (unsigned) sizeof (v));
|
||||
if (err_n) {
|
||||
printf ("pstdint.h is not correct. Please use sizes below to correct it:\n");
|
||||
}
|
||||
|
||||
Q(int)
|
||||
Q(unsigned)
|
||||
Q(long int)
|
||||
Q(short int)
|
||||
Q(int8_t)
|
||||
Q(int16_t)
|
||||
Q(int32_t)
|
||||
#ifdef INT64_MAX
|
||||
Q(int64_t)
|
||||
#endif
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
190
nostrdb/flatcc/portable/punaligned.h
Normal file
190
nostrdb/flatcc/portable/punaligned.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Mikkel Fahnøe Jørgensen, dvide.com
|
||||
*
|
||||
* (MIT License)
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
* - The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
* - The Software is provided "as is", without warranty of any kind, express or
|
||||
* implied, including but not limited to the warranties of merchantability,
|
||||
* fitness for a particular purpose and noninfringement. In no event shall the
|
||||
* authors or copyright holders be liable for any claim, damages or other
|
||||
* liability, whether in an action of contract, tort or otherwise, arising from,
|
||||
* out of or in connection with the Software or the use or other dealings in the
|
||||
* Software.
|
||||
*/
|
||||
|
||||
#ifndef PUNLIGNED_H
|
||||
#define PUNLIGNED_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef PORTABLE_UNALIGNED_ACCESS
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
|
||||
#define PORTABLE_UNALIGNED_ACCESS 1
|
||||
#else
|
||||
#define PORTABLE_UNALIGNED_ACCESS 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* `unaligned_read_16` might not be defined if endianness was not determined. */
|
||||
#if !defined(unaligned_read_le16toh)
|
||||
|
||||
#include "pendian.h"
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if PORTABLE_UNALIGNED_ACCESS
|
||||
|
||||
#define unaligned_read_16(p) (*(uint16_t*)(p))
|
||||
#define unaligned_read_32(p) (*(uint32_t*)(p))
|
||||
#define unaligned_read_64(p) (*(uint64_t*)(p))
|
||||
|
||||
#define unaligned_read_le16toh(p) le16toh(*(uint16_t*)(p))
|
||||
#define unaligned_read_le32toh(p) le32toh(*(uint32_t*)(p))
|
||||
#define unaligned_read_le64toh(p) le64toh(*(uint64_t*)(p))
|
||||
|
||||
#define unaligned_read_be16toh(p) be16toh(*(uint16_t*)(p))
|
||||
#define unaligned_read_be32toh(p) be32toh(*(uint32_t*)(p))
|
||||
#define unaligned_read_be64toh(p) be64toh(*(uint64_t*)(p))
|
||||
|
||||
#define unaligned_write_16(p, v) (*(uint16_t*)(p) = (uint16_t)(v))
|
||||
#define unaligned_write_32(p, v) (*(uint32_t*)(p) = (uint32_t)(v))
|
||||
#define unaligned_write_64(p, v) (*(uint64_t*)(p) = (uint64_t)(v))
|
||||
|
||||
#define unaligned_write_htole16(p, v) (*(uint16_t*)(p) = htole16(v))
|
||||
#define unaligned_write_htole32(p, v) (*(uint32_t*)(p) = htole32(v))
|
||||
#define unaligned_write_htole64(p, v) (*(uint64_t*)(p) = htole64(v))
|
||||
|
||||
#define unaligned_write_htobe16(p, v) (*(uint16_t*)(p) = htobe16(v))
|
||||
#define unaligned_write_htobe32(p, v) (*(uint32_t*)(p) = htobe32(v))
|
||||
#define unaligned_write_htobe64(p, v) (*(uint64_t*)(p) = htobe64(v))
|
||||
|
||||
#else
|
||||
|
||||
#define unaligned_read_le16toh(p) ( \
|
||||
(((uint16_t)(((uint8_t *)(p))[0])) << 0) | \
|
||||
(((uint16_t)(((uint8_t *)(p))[1])) << 8))
|
||||
|
||||
#define unaligned_read_le32toh(p) ( \
|
||||
(((uint32_t)(((uint8_t *)(p))[0])) << 0) | \
|
||||
(((uint32_t)(((uint8_t *)(p))[1])) << 8) | \
|
||||
(((uint32_t)(((uint8_t *)(p))[2])) << 16) | \
|
||||
(((uint32_t)(((uint8_t *)(p))[3])) << 24))
|
||||
|
||||
#define unaligned_read_le64toh(p) ( \
|
||||
(((uint64_t)(((uint8_t *)(p))[0])) << 0) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[1])) << 8) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[2])) << 16) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[3])) << 24) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[4])) << 32) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[5])) << 40) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[6])) << 48) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[7])) << 56))
|
||||
|
||||
#define unaligned_read_be16toh(p) ( \
|
||||
(((uint16_t)(((uint8_t *)(p))[0])) << 8) | \
|
||||
(((uint16_t)(((uint8_t *)(p))[1])) << 0))
|
||||
|
||||
#define unaligned_read_be32toh(p) ( \
|
||||
(((uint32_t)(((uint8_t *)(p))[0])) << 24) | \
|
||||
(((uint32_t)(((uint8_t *)(p))[1])) << 16) | \
|
||||
(((uint32_t)(((uint8_t *)(p))[2])) << 8) | \
|
||||
(((uint32_t)(((uint8_t *)(p))[3])) << 0))
|
||||
|
||||
#define unaligned_read_be64toh(p) ( \
|
||||
(((uint64_t)(((uint8_t *)(p))[0])) << 56) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[1])) << 48) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[2])) << 40) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[3])) << 32) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[4])) << 24) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[5])) << 16) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[6])) << 8) | \
|
||||
(((uint64_t)(((uint8_t *)(p))[7])) << 0))
|
||||
|
||||
#define unaligned_write_htole16(p, v) do { \
|
||||
((uint8_t *)(p))[0] = (uint8_t)(((uint16_t)(v)) >> 0); \
|
||||
((uint8_t *)(p))[1] = (uint8_t)(((uint16_t)(v)) >> 8); \
|
||||
} while (0)
|
||||
|
||||
#define unaligned_write_htole32(p, v) do { \
|
||||
((uint8_t *)(p))[0] = (uint8_t)(((uint32_t)(v)) >> 0); \
|
||||
((uint8_t *)(p))[1] = (uint8_t)(((uint32_t)(v)) >> 8); \
|
||||
((uint8_t *)(p))[2] = (uint8_t)(((uint32_t)(v)) >> 16); \
|
||||
((uint8_t *)(p))[3] = (uint8_t)(((uint32_t)(v)) >> 24); \
|
||||
} while (0)
|
||||
|
||||
#define unaligned_write_htole64(p) do { \
|
||||
((uint8_t *)(p))[0] = (uint8_t)(((uint64_t)(v)) >> 0); \
|
||||
((uint8_t *)(p))[1] = (uint8_t)(((uint64_t)(v)) >> 8); \
|
||||
((uint8_t *)(p))[2] = (uint8_t)(((uint64_t)(v)) >> 16); \
|
||||
((uint8_t *)(p))[3] = (uint8_t)(((uint64_t)(v)) >> 24); \
|
||||
((uint8_t *)(p))[4] = (uint8_t)(((uint64_t)(v)) >> 32); \
|
||||
((uint8_t *)(p))[5] = (uint8_t)(((uint64_t)(v)) >> 40); \
|
||||
((uint8_t *)(p))[6] = (uint8_t)(((uint64_t)(v)) >> 48); \
|
||||
((uint8_t *)(p))[7] = (uint8_t)(((uint64_t)(v)) >> 56); \
|
||||
} while (0)
|
||||
|
||||
#define unaligned_write_htobe16(p, v) do { \
|
||||
((uint8_t *)(p))[0] = (uint8_t)(((uint16_t)(v)) >> 8); \
|
||||
((uint8_t *)(p))[1] = (uint8_t)(((uint16_t)(v)) >> 0); \
|
||||
} while (0)
|
||||
|
||||
#define unaligned_write_htobe32(p, v) do { \
|
||||
((uint8_t *)(p))[0] = (uint8_t)(((uint32_t)(v)) >> 24); \
|
||||
((uint8_t *)(p))[1] = (uint8_t)(((uint32_t)(v)) >> 16); \
|
||||
((uint8_t *)(p))[2] = (uint8_t)(((uint32_t)(v)) >> 8); \
|
||||
((uint8_t *)(p))[3] = (uint8_t)(((uint32_t)(v)) >> 0); \
|
||||
} while (0)
|
||||
|
||||
#define unaligned_write_htobe64(p) do { \
|
||||
((uint8_t *)(p))[0] = (uint8_t)(((uint64_t)(v)) >> 56); \
|
||||
((uint8_t *)(p))[1] = (uint8_t)(((uint64_t)(v)) >> 48); \
|
||||
((uint8_t *)(p))[2] = (uint8_t)(((uint64_t)(v)) >> 40); \
|
||||
((uint8_t *)(p))[3] = (uint8_t)(((uint64_t)(v)) >> 32); \
|
||||
((uint8_t *)(p))[4] = (uint8_t)(((uint64_t)(v)) >> 24); \
|
||||
((uint8_t *)(p))[5] = (uint8_t)(((uint64_t)(v)) >> 16); \
|
||||
((uint8_t *)(p))[6] = (uint8_t)(((uint64_t)(v)) >> 8); \
|
||||
((uint8_t *)(p))[7] = (uint8_t)(((uint64_t)(v)) >> 0); \
|
||||
} while (0)
|
||||
|
||||
#if __LITTLE_ENDIAN__
|
||||
#define unaligned_read_16(p) unaligned_read_le16toh(p)
|
||||
#define unaligned_read_32(p) unaligned_read_le32toh(p)
|
||||
#define unaligned_read_64(p) unaligned_read_le64toh(p)
|
||||
|
||||
#define unaligned_write_16(p) unaligned_write_htole16(p)
|
||||
#define unaligned_write_32(p) unaligned_write_htole32(p)
|
||||
#define unaligned_write_64(p) unaligned_write_htole64(p)
|
||||
#endif
|
||||
|
||||
#if __BIG_ENDIAN__
|
||||
#define unaligned_read_16(p) unaligned_read_be16toh(p)
|
||||
#define unaligned_read_32(p) unaligned_read_be32toh(p)
|
||||
#define unaligned_read_64(p) unaligned_read_be64toh(p)
|
||||
|
||||
#define unaligned_write_16(p) unaligned_write_htobe16(p)
|
||||
#define unaligned_write_32(p) unaligned_write_htobe32(p)
|
||||
#define unaligned_write_64(p) unaligned_write_htobe64(p)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PUNALIGNED_H */
|
||||
6
nostrdb/flatcc/portable/pversion.h
Normal file
6
nostrdb/flatcc/portable/pversion.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#define PORTABLE_VERSION_TEXT "0.2.6-pre"
|
||||
#define PORTABLE_VERSION_MAJOR 0
|
||||
#define PORTABLE_VERSION_MINOR 2
|
||||
#define PORTABLE_VERSION_PATCH 6
|
||||
/* 1 or 0 */
|
||||
#define PORTABLE_VERSION_RELEASED 0
|
||||
52
nostrdb/flatcc/portable/pwarnings.h
Normal file
52
nostrdb/flatcc/portable/pwarnings.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef PWARNINGS_H
|
||||
#define PWARNINGS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* See also pdiagnostics.h headers for per file control of common
|
||||
* warnings.
|
||||
*
|
||||
* This file is intended for global disabling of warnings that shouldn't
|
||||
* be present in C11 or perhaps C99, or a generally just noise where
|
||||
* recent clang / gcc compile cleanly with high warning levels.
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* Needed when flagging code in or out and more. */
|
||||
#pragma warning(disable: 4127) /* conditional expression is constant */
|
||||
/* happens also in MS's own headers. */
|
||||
#pragma warning(disable: 4668) /* preprocessor name not defined */
|
||||
/* MSVC does not respect double parenthesis for intent */
|
||||
#pragma warning(disable: 4706) /* assignment within conditional expression */
|
||||
/* `inline` only advisory anyway. */
|
||||
#pragma warning(disable: 4710) /* function not inlined */
|
||||
/* Well, we don't intend to add the padding manually. */
|
||||
#pragma warning(disable: 4820) /* x bytes padding added in struct */
|
||||
|
||||
/*
|
||||
* Don't warn that fopen etc. are unsafe
|
||||
*
|
||||
* Define a compiler flag like `-D_CRT_SECURE_NO_WARNINGS` in the build.
|
||||
* For some reason it doesn't work when defined here.
|
||||
*
|
||||
* #define _CRT_SECURE_NO_WARNINGS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Anonymous union in struct is valid in C11 and has been supported in
|
||||
* GCC and Clang for a while, but it is not C99. MSVC also handles it,
|
||||
* but warns. Truly portable code should perhaps not use this feature,
|
||||
* but this is not the place to complain about it.
|
||||
*/
|
||||
#pragma warning(disable: 4201) /* nonstandard extension used: nameless struct/union */
|
||||
|
||||
#endif /* _MSV_VER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PWARNINGS_H */
|
||||
Reference in New Issue
Block a user