Skip to content

Releases: biojppm/c4core

Release 0.2.2

15 Aug 16:25
Compare
Choose a tag to compare
  • Amalgamate: fix include of <charconv> (see rapidyaml#445).
  • Add C4_MINGW (PR#139)
  • Annotate c4::handle_error() with [[noreturn]] (PR#137).
  • Add bool from_chars(csubstr s, fmt::overflow_checked_<T> *wrapper). There was already a function receiving &wrapper, but *wrapper was missing for use with generic code.
  • Ensure posix_memalign() is never called with bad alignment values (PR#138)
  • Update fast_float to v6.1.1 (PR#136)

Thanks

Release 0.2.1

11 Jun 17:50
Compare
Choose a tag to compare
  • atod(): add missing assertion str.len > 0

Release 0.2.0

24 Apr 18:36
Compare
Choose a tag to compare

Breaking changes

  • #PR101: As part of the substr ctor cleanup, the to_substr(char (&arr)[N]) overload no longer decays to char* inside. This changes calling code by now returning a substr with length equal to N-1 instead of strlen(arr) as before:
    // longer than "foo", ie longer than {'f', 'o', 'o', '\0'}:
    char arr[] = "foo\0\0\0\0\0\0";
    assert(strlen(arr) == 3);
    assert(sizeof(arr) == 9);
    
    // previously:
    assert(to_substr(arr).len == 3);
    // now:
    assert(to_substr(arr).len == 9);
    
    // the breaking change happens only with arrays:
    assert(to_substr((char*)ptr).len == 3); // as before
  • PR#111 - Rename formatting overloads accepting c4::append:
    • catrs(append_t, ...) -> catrs_append(...)
    • catseprs(append_t, ...) -> catseprs_append(...)
    • formatrs(append_t, ...) -> formatrs_append(...)

New features

  • #PR101: For substr and csubstr:
    • add simultaneous ctors from char[] and char*. Using SFINAE to narrow the char* overload prevents it from overriding the char[] overload. Thanks to @huangqinjin for the idea (see #97).
    • remove unneeded constructors of csubstr from non-const chars.
    • to each single-argument ctor, add corresponding functions to_csubstr() and to_substr() to enable clients coercing their types in generic code such as c4::cat() and c4::format().
    • Add interop with std::string_view when the standard is at least C++17 (#PR101):
      • provided in the header c4/std/string_view.hpp
      • similarly to existing interop headers, this is opt-in and requires explicit inclusion
      • implemented:
        • to_csubstr() (since std::string_view is not writeable, cannot provide to_csubstr())
        • to_chars() (since std::string_view is not writeable, cannot provide from_chars())
        • comparison operators
  • substr: split .first_not_of() and .last_not_of() into different overloads, removing the defaulted start parameter:
    • .first_not_of(T, start=0) -> .first_not_of(T) , .first_not_of(T, start)
    • .last_not_of(T, start=npos) -> .first_not_of(T) , .first_not_of(T, npos)
      This may or may not result in a speedup.
  • PR#105: Add macros in c4/language.hpp for compile-time flow of exceptions:
    • C4_EXCEPTIONS: defined when exceptions are enabled
    • C4_IF_EXCEPTIONS(code_with_exc, code_without_exc): select statements for exceptions enabled/disabled
    • C4_IF_EXCEPTIONS_(code_with_exc, code_without_exc): select code tokens for exceptions enabled/disabled
  • PR#105: Add macros in c4/language.hpp for compile-time flow of RTTI:
    • C4_RTTI: defined when rtti is enabled
    • C4_IF_RTTI(code_with_rtti, code_without_rtti): select statements for rtti enabled/disabled
    • C4_IF_RTTI_(code_with_rtti, code_without_rtti): select code tokens for rtti enabled/disabled
  • PR#109: Add partial support for XTENSA processors (missing implementation of c4::aalloc()). See rapidyaml#358.
  • PR#119 Add LoongArch cpu support.
  • Add compiler annotation helper macros: C4_ASSUME, C4_NODISCARD, C4_DEPRECATED, C4_UNREACHABLE_AFTER_ERR

Fixes

  • Fix #126: bad Exception being used with C4_ERROR_THROWS_EXCEPTION.
  • PR#132:
    • Fix typo C_4MSVC_VERSION_2019 in src/compiler.hpp (#124).
    • Add check for definition of __GNUC__ in gcc-4.8.hpp (#125).
  • PR#121 - Fix compile on armv8 due to broken macro definition; see #122 and #94.
  • PR#129 - Support android by enabling aalloc()'s call to memalign(), available for API 16+.
  • PR#115 - Refactor of c4::blob/c4::cblob. Use SFINAE to invalidate some of the constructors.
  • PR#110/PR#107 - Update fast_float.
  • PR#108 - Fix preprocessor concatenation of strings in C4_NOT_IMPLEMENTED_MSG() and C4_NOT_IMPLEMENTED_IF_MSG().
  • PR#106 - Fix include guard in the gcc 4.8 compatibility header, causing it to be missing from the amalgamated header. See also #125: there was no check for __GNUC__ being defined.
  • PR#123 - Ensure the gcc 4.8 compatibility header is installed (fixes #103).
  • PR#105 - Fix existing throw in c4/ext/sg14/inplace_function.h. Ensure tests run with exceptions disabled and RTTI disabled. Add examples of exceptional control flow with setjmp()/std::longjmp().
  • PR#104/PR#112 - Fix pedantic warnings in gcc, clang and MSVC
  • PR#104 - Fix possible compile error when __GNUC__ is not defined
  • Inject explicit #include <charconv> on the amalgamated header. The amalgamation tool was filtering all prior includes, thus causing a compilation error. Addresses rapidyaml#364.
  • PR#117: Windows: fix compilation with MSVC/clang++.
  • Windows: add missing C4CORE_EXPORT to c4::base64_valid(), c4::base64_encode() and c4::base64_decode().
  • rapidyaml#390 - fix csubstr.first_real_span() when the exponent only has one digit (see fae7106)

Thanks

Release 0.1.11

17 Dec 20:28
Compare
Choose a tag to compare

Breaking changes

  • csubstr::operator==(std::nullptr_t) now strictly checks if the pointer is null and no longer looks at the length (rapidyaml#264):
    -bool csubstr::operator== (std::nullptr_t) const noexcept { return str == nullptr || len == 0; }
    -bool csubstr::operator!= (std::nullptr_t) const noexcept { return str != nullptr || len == 0; }
    +bool csubstr::operator== (std::nullptr_t) const noexcept { return str == nullptr; }
    +bool csubstr::operator!= (std::nullptr_t) const noexcept { return str != nullptr; }
  • to_substr(std::string &s) and to_csubstr(std::string const& s) now point at the first element when the string is empty (rapidyaml#264):
    -    return c4::substr(!s.empty() ? &s[0] : nullptr, s.size());
    +    return c4::substr(&s[0], s.size());
    This is OK because an empty std::string is guaranteed to have storage, so calling s[0] is safe.

New features

  • charconv.hpp: added xtoa() floating-point overloads accepting precision and format (PR#88):
    size_t xtoa(substr s,  float v, int precision, RealFormat_e formatting=FTOA_FLEX) noexcept;
    size_t xtoa(substr s, double v, int precision, RealFormat_e formatting=FTOA_FLEX) noexcept;
  • memory_util.hpp: added ipow() overloads for computing powers with integral exponents (PR#88).
  • Add C4_NO_DEBUG_BREAK preprocessor check to disable calls to c4::debug_break() (see rapidyaml#326)
    • The cmake project conditionally enables this macro if the cmake option C4CORE_NO_DEBUG_BREAK is set to ON.

Fixes

  • substr, to_chars(), charconv: ensure memcpy() is not called when the length is zero. Doing this is UB and enabled the optimizer to wreak havoc in the branches of calling code. See comments at rapidyaml#264 for an example and fix. See Raymond Chen's blog for an explanation.
  • atof() and atod() (PR#88):
    • Always use the fastest implementation available: std::from_chars() if available (C++17 or higher standard, with later compilers), fast_float::from_chars() otherwise. On Visual Studio, fast_float::from_chars() is preferred over std::from_chars().
    • If std::from_chars() is not available and C4CORE_NO_FAST_FLOAT is defined, then the fallback is based on sscanf().
    • Ensure hexadecimal floats are accepted. The current fast_float implementation does not accept hexadecimal floats, so an hexfloat scanner was added.
  • Likewise for ftoa() and dtoa(). Prefer the fastest implementation available: std::to_chars()->snprintf().
    • Change the FTOA_* enum values and type to save a function call when converting format. From now on, only the symbols of this enum can be relied on; the values or type will change depending on the selected implementation (std::to_chars() or snprintf()) (PR#91).
  • Fix #84: csubstr::compare(char): refactor to avoid false-positive warning from VS2022.
  • csubstr methods: add noexcept and annotations C4_PURE and C4_ALWAYS_INLINE
  • csubstr: add C4_RESTRICT to incoming string on csubstr::compare()
  • csubstr::first_real_span() (PR#89):
    • Refactor to fix number matching rules. Now fully valid for floating point numbers in decimal (eg 0.123/1.23e+01), hexadecimal (eg 0x123.abc/0x1.23abcp+01), binary (eg 0b101.10/0b1.0110p+01) and octal format (eg 0o701.10/0o7.0110p+01) , with or without exponent or power, in lower or upper case.
    • Also, make the number parsing stateful to fix cases where repeated characters occur, (like e.g. 0.1.0 or 1.23e+e10) which are no longer reported as numbers (see biojppm/rapidyaml#291).
  • csubstr::first_int_span(), csubstr::first_uint_span(): fix edge cases like e.g. 0xzz which were wrongly reported as numbers.
  • Add fully qualified ARM detection macros:
    • __ARM_ARCH_7EM__ (PR#90).
    • __ARM_ARCH_6KZ__ (PR#93).
    • __ARM_ARCH_8A__ (#94).
  • Improve linux and unix platform detection: detect both __linux and __linux__ (PR#92).

Thanks

Release 0.1.10

20 Aug 19:22
Compare
Choose a tag to compare

Changes

Improved the performance of c4/charconv.hpp functions (PR#77):

  • Added digits_dec/hex/oct/bin().
  • Optimized write_dec/hex/oct/bin():
    • these functions now return immediately without entering the loop if the output buffer is smaller than respectively digits_dec/hex/oct/bin(). This enables both:
      • writing every character in its final position without having to revert the string at the end
      • the need to check the buffer size on appending every character.
    • write_dec() now writes two digits at once, thus halving the number of integer divisions.
  • Added write_dec/hex/oct/bin_unchecked(), which receive precomputed digits_dec/hex/oct/bin(), thus speeding up the radix itoa()/utoa() overloads.
  • Added xtoa() radix+digits overloads:
    • size_t xtoa(substr s, T v, T radix)
    • size_t xtoa(substr s, T v, T radix, size_t num_digits)
  • read_dec/hex/oct/bin(): these functions no longer allow an empty input buffer.
  • Use intrinsic functions __builtin_clz() (gcc) / _BitScanReverse() (msvc) in c4::msb() and __builtin_ctz() (gcc) / _BitScanForward() (msvc) in c4::lsb() when they are available. msb() is used by digits_hex()/digits_bin().
  • Refactored the charconv tests to improve consistency and thoroughness.
  • Improved the charconv benchmarks to ensure full consistency across benchmarks.
  • Special thanks and kudos to @fargies for being attentive and pinpointing several issues throughout the PR!
  • Finding the best approach involved writing a R&D benchmark for the several algorithm components. This benchmark is disabled by default, and can be enabled with the flag C4CORE_BM_XTOA_RND.
  • With the changes from this PR, the charconv benchmark results show that on Linux/g++11.2, with integral types:
    • c4::to_chars() can be expected to be roughly...
      • ~40% to 2x faster than std::to_chars()
      • ~10x-30x faster than sprintf()
      • ~50x-100x faster than a naive stringstream::operator<<() followed by stringstream::str()
    • c4::from_chars() can be expected to be roughly...
      • ~10%-30% faster than std::from_chars()
      • ~10x faster than scanf()
      • ~30x-50x faster than a naive stringstream::str() followed by stringstream::operator>>()
  • Here are the results from the run:
    Write throughput Read throughput
    write uint8_t MB/s read uint8_t MB/s
    c4::to_chars<u8> 526.86 c4::from_chars<u8> 163.06
    std::to_chars<u8> 379.03 std::from_chars<u8> 154.85
    std::sprintf<u8> 20.49 std::scanf<u8> 15.75
    std::stringstream<u8> 3.82 std::stringstream<u8> 3.83
    write int8_t MB/s read int8_t MB/s
    c4::to_chars<i8> 599.98 c4::from_chars<i8> 184.20
    std::to_chars<i8> 246.32 std::from_chars<i8> 156.40
    std::sprintf<i8> 19.15 std::scanf<i8> 16.44
    std::stringstream<i8> 3.83 std::stringstream<i8> 3.89
    write uint16_t MB/s read uint16_t MB/s
    c4::to_chars<u16> 486.40 c4::from_chars<u16> 349.48
    std::to_chars<u16> 454.24 std::from_chars<u16> 319.13
    std::sprintf<u16> 38.74 std::scanf<u16> 28.12
    std::stringstream<u16> 7.08 std::stringstream<u16> 6.73
    write int16_t MB/s read int16_t MB/s
    c4::to_chars<i16> 507.44 c4::from_chars<i16> 282.95
    std::to_chars<i16> 297.49 std::from_chars<i16> 186.18
    std::sprintf<i16> 39.03 std::scanf<i16> 28.45
    std::stringstream<i16> 6.98 std::stringstream<i16> 6.49
    write uint32_t MB/s read uint32_t MB/s
    c4::to_chars<u32> 730.12 c4::from_chars<u32> 463.95
    std::to_chars<u32> 514.76 std::from_chars<u32> 329.42
    std::sprintf<u32> 71.19 std::scanf<u32> 44.97
    std::stringstream<u32> 14.05 std::stringstream<u32> 12.57
    write int32_t MB/s read int32_t MB/s
    c4::to_chars<i32> 618.76 c4::from_chars<i32> 345.53
    std::to_chars<i32> 394.72 std::from_chars<i32> 224.46
    std::sprintf<i32> 71.14 std::scanf<i32> 43.49
    std::stringstream<i32> 13.91 std::stringstream<i32> 12.03
    write uint64_t MB/s read uint64_t MB/s
    c4::to_chars<u64> 1118.87 c4::from_chars<u64> 928.49
    std::to_chars<u64> 886.58 std::from_chars<u64> 759.03
    std::sprintf<u64> 140.96 std::scanf<u64> 91.60
    std::stringstream<u64> 28.01 std::stringstream<u64> 25.00
    write int64_t MB/s read int64_t MB/s
    c4::to_chars<i64> 1198.78 c4::from_chars<i64> 713.76
    std::to_chars<i64> 882.17 std::from_chars<i64> 646.18
    std::sprintf<i64> 138.79 std::scanf<i64> 90.07
    std::stringstream<i64> 27.62 std::stringstream<i64> 25.12

If you feel suspicious about these bold claims, you can browse through c4core's CI benchmark results which will hopefully give these more substance.

New features

  • Added bool c4::overflows<T>(csubstr s) for detecting whether a string overflows a given integral type. See PR#78.
    • Also, added c4::fmt::overflow_checked() (and the corresponding from_chars() overload) to enable a check for overflow before parsing from string:
    c4::from_chars(str, &val); // no overflow check
    c4::from_chars(str, c4::fmt::overflow_checked(val)); // enable overflow check
    // as an example, the implementation looks like:
    template<class T>
    bool c4::from_chars(c4::csubstr str, c4::fmt::overflow_checked<T> oc)
    {
        if(overflows<T>(str))
            return false;
        return c4::from_chars(str, oc.val);
    }

Fixes

  • Fix missing endianess macro on windows arm/arm64 compilations PR #76
  • Add missing #define for the include guard of the amalgamated header (see rapidyaml#246).
  • Fix CPU detection with ARMEL PR #86.
  • Fix GCC version detection PR #87.
  • Fix cmake#8: SOVERSION missing from shared libraries.
  • Update fastfloat to 3.5.1.

Thanks

Release 0.1.9

24 Feb 06:34
Compare
Choose a tag to compare

Breaking changes

  • fix #63: remove c4/time.hpp and c4/time.cpp which prevented compilation in bare-metal mode (PR #64).

New features

  • Added decoding of UTF codepoints: c4::decode_code_point() (PR #65).
  • Experimental feature: add formatted-dumping facilities: using semantics like c4::cat(), c4::catsep() and c4::format(), where the subject is not a string buffer but a dump callback accepting strings. This still requires a string buffer for serialization of non-string types, but the buffer's required size is now limited to the max serialized size of non-string arguments, in contrast to the requirement in c4::cat() et al which is the total serialized size of every argument. This enables very efficient and generic printf-like semantics with reuse of a single small buffer, and allows direct-printing to terminal or file (PR #67). This feature is still experimental and a minor amount of changes to the API is possible.
  • Added macro C4_IF_CONSTEXPR resolving to if constexpr (...) if the c++ standard is at least c++17.
  • csubstr: add count(csubstr) overload.
  • Add support for RISC-V architectures (PR #69).
  • Add support for bare-metal compilation (PR #64).
  • gcc >= 4.8 support using polyfills for missing templates and features (PR #74 and PR #68).

Fixes

  • csubstr::operator==(std::nullptr_t) now returns true if either .str==nullptr or .len==0.
  • Fix: bool operator==(const char (&s)[N], csubstr) and operator==(const char (&s)[N], substr). The template declaration for these functions had an extra const which prevented these functions to participate in overload resolution, which in some cases resulted in calls resolving to operator==(std::string const&, csubstr) if that header was visible (PR #64).
  • Fix csubstr::last_not_of(): optional positional parameter was ignored PR #62.
  • atof(), atod(), atox(), substr::is_real(), substr::first_real_span(): accept infinity, inf and nan as valid reals PR #60.
  • Add missing export symbols PR #56, PR #57.
  • c4/substr_fwd.hpp: fix compilation failure in Xcode 12 and earlier, where the forward declaration for std::allocator is inside the inline namespace __1, unlike later versions PR #61, reported in rapidyaml#185.
  • c4/error.hpp: fix compilation failure in debug mode in Xcode 12 and earlier: __clang_major__ does not mean the same as in the common clang, and as a result the warning -Wgnu-inline-cpp-without-extern does not exist there.

Thanks

Release 0.1.8

28 Dec 17:07
Compare
Choose a tag to compare

New features

  • Add amalgamation into a single header file (PR #48):
    • The amalgamated header will be available together with the deliverables from each release.
    • To generate the amalgamated header:
      $ python tools/amalgamate.py c4core_all.hpp
      
    • To use the amalgamated header:
      • Include at will in any header of your project.
      • In one - and only one - of your project source files, #define C4CORE_SINGLE_HDR_DEFINE_NOW and then #include <c4core_all.hpp>. This will enable the function and class definitions in the header file. For example, here's a sample program:
        #include <iostream>
        #define C4CORE_SINGLE_HDR_DEFINE_NOW // do this before the include
        #include <c4core_all.hpp>
        int main()
        {
            for(c4::csubstr s : c4::csubstr("a/b/c/d").split('/'))
                std::cout << s << "\n";
        }
  • Add csubstr::is_unsigned_integer() and csubstr::is_real() (PR #49).
  • CMake: add alias target c4core::c4core, guaranteeing that the same code can be used with add_subdirectory() and find_package(). (see rapidyaml #173)
  • Add support for compilation with emscripten (WebAssembly+javascript) (PR #52).

Fixes

  • Fix edge cases with empty strings in span::first(), span::last() and span::range() (PR #49).
  • Accept octal numbers in substr::first_real_span() and substr::is_real() (PR #49).
  • substr: fix coverage misses in number query methods (PR #49).
  • Use single-header version of fast_float (PR #49).
  • Suppress warnings triggered from fast_float in clang (-Wfortify-source) (PR #49).
  • Add missing inline in src/c4/ext/rng/rng.hpp (PR #49).
  • Fix compilation of src/c4/ext/rng/inplace_function.h in C++11 (PR #49).
  • Change order of headers, notably in windows_push.hpp (PR #47).
  • In c4/charconv.hpp: do not use C4_ASSERT in to_c_fmt(), which is constexpr.
  • Fix #53: cmake install targets were missing call to export() (PR #55).
  • Fix linking of subprojects with libc++: flags should be forwarded through CMAKE_***_FLAGS instead of being set explicitly per-target (PR #54).

Thanks

Release 0.1.7

04 Nov 14:22
Compare
Choose a tag to compare
  • Fix build with C4CORE_NO_FAST_FLOAT (#42).
  • Fix clang warning in AIX/xlclang (#44).

Thanks

--- @mbs-c

Release 0.1.6

27 Sep 21:23
Compare
Choose a tag to compare
  • Fix wrong version names in version 0.1.5 (was saying 0.1.4, should be 0.1.5)

Release 0.1.5

26 Sep 18:44
Compare
Choose a tag to compare
  • Add support for aarch64, s390x, ppc64le CPU architectures
  • Update debugbreak header (added support for the above architectures)