scanf for modern C++
APACHE-2.0 License
Bot releases are visible (Hide)
d
(decimal) instead of i
(detect base from prefix).// v3
auto result = scn::scan<int>("077", "{}");
// result->value() == 77
result = scn::scan<int>("078", "{}");
// result->value() == 78
// v2
auto result = scn::scan<int>("077", "{}");
// result->value() == 63
result = scn::scan<int>("078", "{}");
// result->value() == 7
// result->range() == "8"
// (Because of the '0' prefix, an octal number is expected,
// and '8' is not a valid octal digit, so reading is stopped)
<ranges>
-implementation is removed.<ranges>
, even if available.scn::ranges::enable_borrowed_range
for your own range types,std::ranges::enable_borrowed_range
.std::basic_string_view
are already borrowed out of the box.// std::span is a borrowed_range,
// but scnlib doesn't know about it
auto result = scn::scan<...>(std::span{...}, ...);
// decltype(result->range()) is scn::ranges::dangling
namespace scn::ranges {
template <typename T, size_t E>
inline constexpr bool enable_borrowed_range<std::span<T, E>> = true;
}
auto result = scn::scan<...>(std::span{...}, ...);
// decltype(result->range()) is a scn::ranges::subrange<const T*>
scn::span
is removedscan_arg_store
and borrowed_subrange_with_sentinel
are removed from the public interfacescan_arg_store
is changed to be non-copyable and non-movable, for correctness reasonsmake_scan_result
is changed to take a tuple
instead of the now unmovable scan_arg_store
.// v3
auto args = make_scan_args<scan_context, Args...>();
auto result = vscan(source, format, args);
return make_scan_result(std::move(result), std::move(args.args()));
// v2
auto args = make_scan_args<scan_context, Args...>();
auto result = vscan(source, format, args);
return make_scan_result(std::move(result), std::move(args));
std::format
), instead of the maximum (sort of like in scanf
)// v3
auto result = std::scan<int>("123", "{:2}");
// result->value() == 123
// result->range() == ""
// v2
auto result = std::scan<int>("123", "{:2}");
// result->value() == 12
// result->range() == "3"
std::format
)// Scan up to 2 width units
auto result = scn::scan<int>("123", "{:.2}");
// result->value() == 12
// result->range() == "3"
// Read an integer, aligned to the right ('>'), with asterisks ('*')
auto result = std::scan<int>("***42", "{:*>}");
// result->value() == 42
// result->range() == ""
// Read an integer, aligned to the left ('<'), with whitespace (default),
// with a maximum total width of 3
auto result = std::scan<int>("42 ", "{:<.3}");
// result->value() == 42
// result->range() == " "
simdutf
is removed. The library now has no external dependencies to compiled librariesFull Changelog: https://github.com/eliaskosunen/scnlib/compare/v2.0.3...v3.0.0
Published by eliaskosunen 5 months ago
Fixes:
i
, not d
:0x...
is hexadecimal, 0...
or 0o...
is octal, 0b...
is binary, and everything else is decimal.scn::scan
.GNUInstallDirs
in CMake (#111, thanks @WangWeiLin-MV)SCN_COMPILER
to fix usage with a recent Clang using modules (#109, thanks @Delta-dev-99 (Armando Martin))<utility>
for std::unreachable
Full Changelog: https://github.com/eliaskosunen/scnlib/compare/v2.0.2...v2.0.3
Published by eliaskosunen 8 months ago
Minor fixes:
{:[^
as a format string.scan_buffer.cpp
on some MSVC versions.test/
folderFull Changelog: https://github.com/eliaskosunen/scnlib/compare/v2.0.1...v2.0.2
Published by eliaskosunen 8 months ago
Minor bugfixes
std::regex_constants::multiline
(#98, thanks @jiayuehua (Jia Yue Hua))float_reader
on Android SDK < v28 (#99, thanks @jiayuehua (Jia Yue Hua))Full Changelog: https://github.com/eliaskosunen/scnlib/compare/v2.0.0...v2.0.1
Published by eliaskosunen 9 months ago
Major overhaul, both internally and in terms of the library interface. The library is rewritten in its entirety. See the documentation at https://scnlib.dev/, namely the Migration guide for more details.
The changes below are relative to v1. See CHANGELOG.md for changes relative to v2.0.0-beta.
Major changes include:
scan_
prefix.scn::scan
returns the scanned values by value. Output parameters are no longer used.scn::scan
now accepts all forward_range
s (v1: bidirectional_range
+ default- and move constructible).scn::scan
returns a view (subrange
) into its input, and never takes ownership.ignore
, getline
, and file
have been removed.Full Changelog: https://github.com/eliaskosunen/scnlib/compare/v2.0.0-beta...v2.0.0
Published by eliaskosunen 12 months ago
Expected to be the last release in the v1-branch.
Development efforts are now fully directed towards v2.
SCN_DISABLE_TYPE_*
(#70, thanks @cjvaughter (CJ Vaughter))
std::from_chars
and std::strtod
when scanning floatsSCN_DISABLE_LOCALE
(#71, thanks @cjvaughter (CJ Vaughter))+
signs in floats (reported in #77)scn::wrap(std::string_view&&)
being ambiguous on gcc (reported in #83)scn::basic_string_view<CharT>::substr
(reported in #86)small_vector
, detail::utf16::validate_next
, and detail::get_buffer
.COMPONENT
to CMake install targets (#80, thanks @pawelwod)SCN_MSVC
from _MSC_FULL_VER
(#62, thanks @matbech (Mathias Berchtold))C4146
warning in integer_scanner
(#64, thanks @matbech (Mathias Berchtold))if constexpr
and std::unreachable
if available (#61, #78, thanks @matbech (Mathias Berchtold))Published by eliaskosunen 12 months ago
Major overhaul, both internally and in terms of the library interface. The library is rewritten in its entirety. See the documentation (note the new URL: https://v2.scnlib.dev), namely the Migration guide for more details.
This is a beta pre-release. There may still be some bugs. Changes before v2.0.0 proper are possible, but aren't probably going to be major.
Major changes include:
scan_
prefix.scn::scan
returns the scanned values by value. Output parameters are no longer used.scn::scan
now accepts all forward_range
s (v1: bidirectional_range
+ default- and move constructible).scn::scan
returns a view (subrange
) into its input, and never takes ownership.ignore
, getline
, and file
have been removed.Published by eliaskosunen over 2 years ago
SCN_VERSION
to report the correct version number: 1.1.0 -> 1.1.2 (#57)Published by eliaskosunen over 2 years ago
file.sync()
(#56)
file.sync()
needs to be accompanied by a call to reset_begin_iterator()
to the result objectint i;
auto ret = scn::scan(scn::cstdin(), "{}", i);
scn::cstdin().sync();
ret.range().reset_begin_iterator();
// Not necessary with input and prompt
ret = scn::input("{}", i);
Published by eliaskosunen over 2 years ago
(un)signed char
, (u)int8_t
),char
, wchar_t
) as integersint8_t i1, i2;
char c1, c2;
auto ret = scn::scan("1 2 3 4", "{} {:c} {} {:i}", i1, i2, i3, i4);
// ret == true
// i1 == 1
// i2 == '2'
// c1 == '3'
// c2 == 4
small_vector
on 32-bit architecturesFull Changelog: https://github.com/eliaskosunen/scnlib/compare/v1.0...v1.1
Published by eliaskosunen over 2 years ago
First stable release!
The library is now deemed production-ready, and backwards-compatibility will be maintained until the next major release comes out, in accordance to semantic versioning. 1.x-versions will be getting security updates after that, until further notice.
If you're migrating from v1.0-rc1, no major changes have been made, only bugfixes.
If you're migrating from v0.4, see the migration guide v0.4 -> v1.0.
If you're new here, see the documentation and the repository.
The feature highlights below are the same compared to those of v1.0-rc1
Now, by default, scnlib uses https://github.com/fastfloat/fast_float for parsing floating-point values, falling back on std::from_chars
and std::strtod
only if necessary.
This provides even more performance than before: using scn::scan
is now 2x to 8x faster than using std::stringstream
, when parsing floats.
Many things have changed (see the migration guide above), and the same format strings may now do different things.
// alignment
int i{};
auto result = scn::scan("***1***", "{:*^}", i);
// i == 1
// result.empty() == true
// localization
double d{};
result = scn::scan_localized(std::locale{"fi_FI.UTF-8"}, "3,14", "{:L}", d);
// d == 3.14
// result.empty() == true
// width
std::string str1;
result = scn::scan("abcde", "{:3}", str1);
// str1 == "abc"
// result.range() == "de"
// string set
std::string str2;
result = scn::scan("123abc", "{:[0-9]}", str2);
// str2 == "123"
// result.range() == "abc"
// Parse Unicode code points
scn::code_point cp{};
auto result = scn::scan("äa", "{}", cp);
// cp == 0xe4
// result.range() == "a"
// Parse Unicode strings
std::string s1, s2;
// s1: read until whitespace
// s2: read until non-letter character, according to locale
result = scn::scan_localized(std::locale{"fi_FI.UTF-8"}, "äa1 äa1", "{} {:L[:alpha:]}", s1, s2);
// s1 == "äa1"
// s2 == "äa"
// result.range() == "1"
See CHANGELOG.md and the documentation for more details
Full Changelog (from v1.0-rc1): https://github.com/eliaskosunen/scnlib/compare/v1.0-rc1...v1.0
Published by eliaskosunen over 2 years ago
Getting closer to 1.0!
Now, by default, scnlib uses https://github.com/fastfloat/fast_float for parsing floating-point values, falling back on std::from_chars
and std::strtod
only if necessary.
This provides even more performance than before.
Many things have changed (see the migration guide below), and the same format strings may now do different things.
// alignment
int i{};
auto result = scn::scan("***1***", "{:*^}", i);
// i == 1
// result.empty() == true
// localization
double d{};
result = scn::scan_localized(std::locale{"fi_FI.UTF-8"}, "3,14", "{:L}", d);
// d == 3.14
// result.empty() == true
// width
std::string str1;
result = scn::scan("abcde", "{:3}", str1);
// str1 == "abc"
// result.range() == "de"
// string set
std::string str2;
result = scn::scan("123abc", "{:[0-9]}", str2);
// str2 == "123"
// result.range() == "abc"
// Parse Unicode code points
scn::code_point cp{};
auto result = scn::scan("äa", "{}", cp);
// cp == 0xe4
// result.range() == "a"
// Parse Unicode strings
std::string s1, s2;
// s1: read until whitespace
// s2: read until non-letter character, according to locale
result = scn::scan_localized(std::locale{"fi_FI.UTF-8"}, "äa äa", "{} {:L[:alpha:]}", s1, s2);
// s1 == s2 == "äa"
// result.empty() == true
See CHANGELOG.md and the documentation, namely the migration guide for more details
Full Changelog: https://github.com/eliaskosunen/scnlib/compare/v0.4...v1.0-rc1
Published by eliaskosunen almost 4 years ago
Planned to be the last 0.x release before 1.0-rc1.
std::string
and std::vector<char>
.range()
can be used to scan the range again,.reconstruct()
reconstructs the range, if possible.file_view
and caching rangesdefault_tag
, replace with scan_default
function templatescanf
syntax, including scn::scanf
and scn::basic_scanf_parse_context
.scn::detail::ranges
): scn::custom_ranges
scn::std_ranges
aliased to std::ranges
scn::ranges
, control behavior with SCN_USE_STD_RANGES
scan_list_until
"C"
SONAME
(#32, thanks @xvitaly (Vitaly Zaitsev))Published by eliaskosunen over 4 years ago
Largely a bugfix release
scan
fail, the whole function failsread
-field removed from result
scan_list
std::string_view
and MSVC debug iterators (#11, #14, #18, #20)std::string
s (#16)git
command in README (#13)Thanks to @nanoric and @SuperWig for bug reports!
std::char_traits
std::string
sPublished by eliaskosunen almost 5 years ago
There are so many changes, that writing a complete changelog isn't really possible.
The most substantial change is the removal of streams, which have been replaced with C++20-like ranges.
There are also some pretty sweet performance improvements; see benchmarks in README for more details.
See the documentation for more details, a tutorial, and an API reference.
Published by eliaskosunen over 5 years ago
SCN_RANGES
CMake optionscn::temp
helper function-Wpadded
warnings on clang-Wfloat-equal
and -Wconversion
warnings on gccC4146
error on UWP MSVCPublished by eliaskosunen over 5 years ago
Quick bugfix release
scn::cstdin()
or scn::wcstdin()
,small_vector
setting data pointer to nullptr
small_vector
.scn::ranges::get_value
.Published by eliaskosunen over 5 years ago
First release!