Releases: biojppm/c4core
Releases · biojppm/c4core
Release 0.2.2
- 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
atod()
: add missing assertion str.len > 0
Release 0.2.0
Breaking changes
- #PR101: As part of the
substr
ctor cleanup, theto_substr(char (&arr)[N])
overload no longer decays tochar*
inside. This changes calling code by now returning asubstr
with length equal toN-1
instead ofstrlen(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
andcsubstr
:- add simultaneous ctors from
char[]
andchar*
. Using SFINAE to narrow thechar*
overload prevents it from overriding thechar[]
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()
andto_substr()
to enable clients coercing their types in generic code such asc4::cat()
andc4::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()
(sincestd::string_view
is not writeable, cannot provideto_csubstr()
)to_chars()
(sincestd::string_view
is not writeable, cannot providefrom_chars()
)- comparison operators
- provided in the header
- add simultaneous ctors from
substr
: split.first_not_of()
and.last_not_of()
into different overloads, removing the defaultedstart
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 enabledC4_IF_EXCEPTIONS(code_with_exc, code_without_exc)
: select statements for exceptions enabled/disabledC4_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 enabledC4_IF_RTTI(code_with_rtti, code_without_rtti)
: select statements for rtti enabled/disabledC4_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 withC4_ERROR_THROWS_EXCEPTION
. - PR#132:
- PR#121 - Fix compile on armv8 due to broken macro definition; see #122 and #94.
- PR#129 - Support android by enabling
aalloc()
's call tomemalign()
, 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()
andC4_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 withsetjmp()/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
toc4::base64_valid()
,c4::base64_encode()
andc4::base64_decode()
. - rapidyaml#390 - fix
csubstr.first_real_span()
when the exponent only has one digit (see fae7106)
Thanks
Release 0.1.11
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)
andto_csubstr(std::string const& s)
now point at the first element when the string is empty (rapidyaml#264):This is OK because an empty- return c4::substr(!s.empty() ? &s[0] : nullptr, s.size()); + return c4::substr(&s[0], s.size());
std::string
is guaranteed to have storage, so callings[0]
is safe.
New features
charconv.hpp
: addedxtoa()
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
: addedipow()
overloads for computing powers with integral exponents (PR#88).- Add
C4_NO_DEBUG_BREAK
preprocessor check to disable calls toc4::debug_break()
(see rapidyaml#326)- The cmake project conditionally enables this macro if the cmake option
C4CORE_NO_DEBUG_BREAK
is set toON
.
- The cmake project conditionally enables this macro if the cmake option
Fixes
substr
,to_chars()
, charconv: ensurememcpy()
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()
andatod()
(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 overstd::from_chars()
. - If
std::from_chars()
is not available andC4CORE_NO_FAST_FLOAT
is defined, then the fallback is based onsscanf()
. - Ensure hexadecimal floats are accepted. The current fast_float implementation does not accept hexadecimal floats, so an hexfloat scanner was added.
- Always use the fastest implementation available:
- Likewise for
ftoa()
anddtoa()
. 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()
orsnprintf()
) (PR#91).
- Change the
- Fix #84:
csubstr::compare(char)
: refactor to avoid false-positive warning from VS2022. csubstr
methods: addnoexcept
and annotationsC4_PURE
andC4_ALWAYS_INLINE
csubstr
: addC4_RESTRICT
to incoming string oncsubstr::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 (eg0x123.abc/0x1.23abcp+01
), binary (eg0b101.10/0b1.0110p+01
) and octal format (eg0o701.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
or1.23e+e10
) which are no longer reported as numbers (see biojppm/rapidyaml#291).
- Refactor to fix number matching rules. Now fully valid for floating point numbers in decimal (eg
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:
- Improve linux and unix platform detection: detect both
__linux
and__linux__
(PR#92).
Thanks
Release 0.1.10
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.
- these functions now return immediately without entering the loop if the output buffer is smaller than respectively
- Added
write_dec/hex/oct/bin_unchecked()
, which receive precomputeddigits_dec/hex/oct/bin()
, thus speeding up the radixitoa()/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) inc4::msb()
and__builtin_ctz()
(gcc) /_BitScanForward()
(msvc) inc4::lsb()
when they are available.msb()
is used bydigits_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 bystringstream::str()
- ~40% to 2x faster than
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 bystringstream::operator>>()
- ~10%-30% faster than
- 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 correspondingfrom_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); }
- Also, added
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
Breaking changes
- fix #63: remove
c4/time.hpp
andc4/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()
andc4::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 inc4::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 toif constexpr (...)
if the c++ standard is at least c++17. csubstr
: addcount(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)
andoperator==(const char (&s)[N], substr)
. The template declaration for these functions had an extraconst
which prevented these functions to participate in overload resolution, which in some cases resulted in calls resolving tooperator==(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()
: acceptinfinity
,inf
andnan
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 forstd::allocator
is inside theinline 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
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()
andcsubstr::is_real()
(PR #49). - CMake: add alias target c4core::c4core, guaranteeing that the same code can be used with
add_subdirectory()
andfind_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()
andspan::range()
(PR #49). - Accept octal numbers in
substr::first_real_span()
andsubstr::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 into_c_fmt()
, which isconstexpr
. - 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
Release 0.1.6
- Fix wrong version names in version 0.1.5 (was saying 0.1.4, should be 0.1.5)
Release 0.1.5
- Add support for aarch64, s390x, ppc64le CPU architectures
- Update debugbreak header (added support for the above architectures)