Skip to content

Commit

Permalink
reorganize binary utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
danielaparker committed Dec 29, 2024
1 parent 74f0336 commit 9a81b8e
Show file tree
Hide file tree
Showing 12 changed files with 370 additions and 378 deletions.
227 changes: 0 additions & 227 deletions include/jsoncons/config/binary_config.hpp

This file was deleted.

139 changes: 105 additions & 34 deletions include/jsoncons/config/compiler_support.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,47 +374,118 @@ namespace jsoncons {
#endif
#endif

namespace jsoncons {
// The definitions below follow the definitions in compiler_support_p.h, https://github.com/01org/tinycbor
// MIT license

#ifdef __F16C__
# include <immintrin.h>
#endif

#ifndef __has_builtin
# define __has_builtin(x) 0
#endif

#if defined(__GNUC__)
#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 403) || (__has_builtin(__builtin_bswap64) && __has_builtin(__builtin_bswap32))
# define JSONCONS_BYTE_SWAP_64 __builtin_bswap64
# define JSONCONS_BYTE_SWAP_32 __builtin_bswap32
# ifdef __INTEL_COMPILER
# define JSONCONS_BYTE_SWAP_16 _bswap16
# elif (__GNUC__ * 100 + __GNUC_MINOR__ >= 608) || __has_builtin(__builtin_bswap16)
# define JSONCONS_BYTE_SWAP_16 __builtin_bswap16
# endif
#endif
#elif defined(__sun)
# include <sys/byteorder.h>
#elif defined(_MSC_VER)
// MSVC, which implies sizeof(long) == 4
# define JSONCONS_BYTE_SWAP_64 _byteswap_uint64
# define JSONCONS_BYTE_SWAP_32 _byteswap_ulong
# define JSONCONS_BYTE_SWAP_16 _byteswap_ushort
#endif

namespace jsoncons {
namespace binary {

class assertion_error : public std::runtime_error
static inline bool add_check_overflow(std::size_t v1, std::size_t v2, std::size_t *r)
{
public:
assertion_error(const std::string& s) noexcept
: std::runtime_error(s)
#if ((defined(__GNUC__) && (__GNUC__ >= 5)) && !defined(__INTEL_COMPILER)) || __has_builtin(__builtin_add_overflow)
return __builtin_add_overflow(v1, v2, r);
#else
// unsigned additions are well-defined
*r = v1 + v2;
return v1 > v1 + v2;
#endif
}

#if defined(__apple_build_version__) && ((__clang_major__ < 8) || ((__clang_major__ == 8) && (__clang_minor__ < 1)))
#define APPLE_MISSING_INTRINSICS 1
#endif

inline
uint16_t encode_half(double val)
{
#if defined(__F16C__) && !defined(APPLE_MISSING_INTRINSICS)
return _cvtss_sh((float)val, 3);
#else
uint64_t v;
std::memcpy(&v, &val, sizeof(v));
int64_t sign = static_cast<int64_t>(v >> 63 << 15);
int64_t exp = (v >> 52) & 0x7ff;
int64_t mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
exp -= 1023;
if (exp == 1024) {
/* infinity or NaN */
exp = 16;
mant >>= 1;
} else if (exp >= 16) {
/* overflow, as largest number */
exp = 15;
mant = 1023;
} else if (exp >= -14) {
/* regular normal */
} else if (exp >= -24) {
/* subnormal */
mant |= 1024;
mant >>= -(exp + 14);
exp = -15;
} else {
/* underflow, make zero */
return 0;
}

/* safe cast here as bit operations above guarantee not to overflow */
return static_cast<uint16_t>(sign | ((exp + 15) << 10) | mant);
#endif
}

/* this function was copied & adapted from RFC 7049 Appendix D */
inline
double decode_half(uint16_t half)
{
#if defined(__F16C__) && !defined(APPLE_MISSING_INTRINSICS)
return _cvtsh_ss(half);
#else
int64_t exp = (half >> 10) & 0x1f;
int64_t mant = half & 0x3ff;
double val;
if (exp == 0)
{
val = ldexp(static_cast<double>(mant), -24);
}
const char* what() const noexcept override
else if (exp != 31)
{
return std::runtime_error::what();
val = ldexp(static_cast<double>(mant) + 1024.0, static_cast<int>(exp - 25));
}
else
{
val = mant == 0 ? std::numeric_limits<double>::infinity() : std::nan("");
}
};
return half & 0x8000 ? -val : val;
#endif
}

} // namespace binary
} // namespace jsoncons

#define JSONCONS_STR2(x) #x
#define JSONCONS_STR(x) JSONCONS_STR2(x)

#ifdef _DEBUG
#define JSONCONS_ASSERT(x) if (!(x)) { \
JSONCONS_THROW(jsoncons::assertion_error("assertion '" #x "' failed at " __FILE__ ":" \
JSONCONS_STR(__LINE__))); }
#else
#define JSONCONS_ASSERT(x) if (!(x)) { \
JSONCONS_THROW(jsoncons::assertion_error("assertion '" #x "' failed at <> :" \
JSONCONS_STR( 0 ))); }
#endif // _DEBUG

#if defined(JSONCONS_HAS_2017)
# define JSONCONS_FALLTHROUGH [[fallthrough]]
#elif defined(__clang__)
# define JSONCONS_FALLTHROUGH [[clang::fallthrough]]
#elif defined(__GNUC__) && ((__GNUC__ >= 7))
# define JSONCONS_FALLTHROUGH __attribute__((fallthrough))
#elif defined (__GNUC__)
# define JSONCONS_FALLTHROUGH // FALLTHRU
#else
# define JSONCONS_FALLTHROUGH
#endif


#endif // JSONCONS_CONFIG_COMPILER_SUPPORT_HPP
Loading

0 comments on commit 9a81b8e

Please sign in to comment.