API Documentation¶
Scanning functions¶
Main part of the public API.
Generally, the functions in this group take a range, a format string, and a list of arguments. The arguments are parsed from the range based on the information given in the format string.
If the function takes a format string and a range, they must share
character types. Also, the format string must be convertible to
basic_string_view<CharT>
, where CharT
is that aforementioned
character type.
-
template<typename
Range
, typenameFormat
, typename ...Args
>
autoscn
::
scan
(Range &&r, const Format &f, Args&... a) -> detail::scan_result_for_range<Range>¶ The most fundamental part of the scanning API.
Reads from the range in
r
according to the format stringf
.int i; scn::scan("123", "{}", i); // i == 123
-
template<typename
Range
, typename ...Args
>
autoscn
::
scan_default
(Range &&r, Args&... a) -> detail::scan_result_for_range<Range>¶ Equivalent to scan, but with a format string with the appropriate amount of space-separated
"{}"
s for the number of arguments.Because this function doesn’t have to parse the format string, performance is improved.
Adapted from the example for scan
int i; scn::scan_default("123", i); // i == 123
- See
-
template<typename
Locale
, typenameRange
, typenameFormat
, typename ...Args
>
autoscn
::
scan_localized
(const Locale &loc, Range &&r, const Format &f, Args&... a) -> detail::scan_result_for_range<Range>¶ Read from the range in
r
using the locale inloc
.loc
must be astd::locale
. The parameter is a template to avoid inclusion of<locale>
.Use of this function is discouraged, due to the overhead involved with locales. Note, that the other functions are completely locale-agnostic, and aren’t affected by changes to the global C locale.
double d; scn::scan_localized(std::locale{"fi_FI"}, "3,14", "{}", d); // d == 3.14
- See
-
template<typename
T
, typenameRange
>
autoscn
::
scan_value
(Range &&r) -> detail::generic_scan_result_for_range<expected<T>, Range>¶ Scans a single value with the default options, returning it instead of using an output parameter.
The parsed value is in
ret.value()
, ifret == true
. The return type of this function is otherwise similar to other scanning functions.auto ret = scn::scan_value<int>("42"); if (ret) { // ret.value() == 42 }
-
template<typename
Format
, typename ...Args
, typenameCharT
= ranges::range_value_t<Format>>
autoscn
::
input
(const Format &f, Args&... a) -> detail::scan_result_for_range<basic_file<CharT>&>¶ Otherwise equivalent to scan, expect reads from
stdin
.Character type is determined by the format string. Syncs with
<cstdio>
.
-
template<typename
CharT
, typenameFormat
, typename ...Args
>
autoscn
::
prompt
(const CharT *p, const Format &f, Args&... a) -> decltype(input(f, a...))¶ Equivalent to input, except writes what’s in
p
tostdout
.int i{}; scn::prompt("What's your favorite number? ", "{}", i); // Equivalent to: // std::fputs("What's your favorite number? ", stdout); // scn::input("{}", i);
-
template<typename
Range
, typenameString
, typenameCharT
>
autoscn
::
getline
(Range &&r, String &str, CharT until) -> detail::scan_result_for_range<Range>¶ Read the range in
r
intostr
untiluntil
is found.until
will be skipped in parsing: it will not be pushed intostr
, and the returned range will go past it.r
andstr
must share character types, which must beCharT
.If
str
is convertible to abasic_string_view
:And if
r
is acontiguous_range
:str
is set to point insider
with the appropriate length
if not, returns an error
Otherwise, clears
str
by callingstr.clear()
, and then reads the range intostr
as if by repeatedly callingstr.push_back
.str.reserve
is also required to be present.auto source = "hello\nworld" std::string line; auto result = scn::getline(source, line, '\n'); // line == "hello" // result.range() == "world" // Using the other overload result = scn::getline(result.range(), line); // line == "world" // result.empty() == true
-
template<typename
Range
, typenameString
, typenameCharT
= typename detail::extract_char_type<ranges::iterator_t<detail::range_wrapper_for_t<Range>>>::type>
autoscn
::
getline
(Range &&r, String &str) -> detail::scan_result_for_range<Range>¶ Equivalent to getline with the last parameter set to
'\n'
with the appropriate character type.In other words, reads
r
intostr
until'\n'
is found.The character type is determined by
r
.
-
template<typename
Range
, typenameCharT
>
autoscn
::
ignore_until
(Range &&r, CharT until) -> detail::scan_result_for_range<Range>¶ Advances the beginning of
r
untiluntil
is found.The character type of
r
must beCharT
.
-
template<typename
Range
, typenameCharT
>
autoscn
::
ignore_until_n
(Range &&r, ranges::range_difference_t<Range> n, CharT until) -> detail::scan_result_for_range<Range>¶ Advances the beginning of
r
untiluntil
is found, or the beginning has been advancedn
times.The character type of
r
must beCharT
.
-
template<typename
Range
, typenameContainer
, typenameCharT
= typename detail::extract_char_type<ranges::iterator_t<Range>>::type>
autoscn
::
scan_list
(Range &&r, Container &c, CharT separator = detail::zero_value<CharT>::value) -> detail::scan_result_for_range<Range>¶ Reads values repeatedly from
r
and writes them intoc
.The values read are of type
Container::value_type
, and they are written intoc
usingc.push_back
.The values must be separated by separator character
separator
, followed by whitespace. Ifseparator == 0
, no separator character is expected.The range is read, until:
c.max_size()
is reached, orrange
EOF
was reached, orunexpected separator character was found between values.
In all these cases, an error will not be returned, and the beginning of the returned range will point to the first character after the scanned list.
To scan into
span
, use span_list_wrapper. make_span_list_wrapperstd::vector<int> vec{}; auto result = scn::scan_list("123 456", vec); // vec == [123, 456] // result.empty() == true result = scn::scan_list("123, 456", vec, ','); // vec == [123, 456] // result.empty() == true
-
template<typename
Range
, typenameContainer
, typenameCharT
= typename detail::extract_char_type<ranges::iterator_t<Range>>::type>
autoscn
::
scan_list_until
(Range &&r, Container &c, CharT until, CharT separator = detail::zero_value<CharT>::value) -> detail::scan_result_for_range<Range>¶ Otherwise equivalent to scan_list, except with an additional case of stopping scanning: if
until
is found where a separator was expected.std::vector<int> vec{}; auto result = scn::scan_list_until("123 456\n789", vec, '\n'); // vec == [123, 456] // result.range() == "789"
- See
Source range¶
Various kinds of ranges can be passed to scanning functions.
Fundamentally, a range is something that has a beginning and an end.
Examples of ranges are a string literal, a C-style array, and a std::vector
.
All of these can be passed to std::begin
and std::end
, which then return an iterator to the range.
This notion of ranges was standardized in C++20 with the Ranges TS.
This library provides barebone support of this functionality.
Source range requirements¶
- Ranges passed to scanning functions must be:
bidirectional
default and move constructible
Using C++20 concepts:
template <typename Range>
concept scannable_range =
std::ranges::bidirectional_range<Range> &&
std::default_constructible<Range> &&
std::move_constructible<Range>;
A bidirectional range is a range, the iterator type of which is
bidirectional: http://eel.is/c++draft/iterator.concepts#iterator.concept.bidir.
Bidirectionality means, that the iterator can be moved both
forwards: ++it
and backwards --it
.
Note, that both random-access and contiguous ranges are refinements of bidirectional ranges, and can be passed to the library. In fact, the library implements various optimizations for contiguous ranges.
Recommended range requirements¶
In addition, to limit unnecessary copies and possible dynamic memory allocations,
the ranges should be passed as an lvalue, and/or be a view
: http://eel.is/c++draft/range.view.
A view
is a range
that is cheap to copy: think string_view
or span
.
Passing a non-view as an rvalue will work, but it may cause worse performance, especially with larger source ranges.
// okay: view
scn::scan(std::string_view{...}, ...);
// okay: lvalue
std::string source = ...
scn::scan(source, ...);
// worse performance: non-view + rvalue
scn::scan(std::string{...}, ...);
In order for the .reconstruct()
member function to compile in the result object,
the range must be a pair-reconstructible-range
as defined by https://wg21.link/p1664r1,
i.e. be constructible from an iterator and a sentinel.
If the source range is contiguous, and/or its value_type
is its character type,
various fast-path optimizations are enabled inside the library implementation.
Also, a string_view
can only be scanned from such a range.
Character type¶
The range has an associated character type.
This character type can be either char
or wchar_t
.
The character type is determined by the result of operator*
of the range
iterator. If dereferencing the iterator returns
char
orwchar_t
: the character type ischar
orwchar_t
, respectively
expected<char>
orexpected<wchar_t>
: the character type ischar
orwchar_t
, respectively
Note on string literals¶
Please note, that only string literals are ranges (const char(&)[N]
), not pointers to a constant character (const char*
).
This is because:
It’s impossible to differentiate if a
const char*
is a null-terminated string, a pointer to a singlechar
, or a pointer to an array ofchar
. For safety reasons,const char*
is thus not an allowed source range type.It’s how ranges in the standard are defined: a
const char*
cannot be passed tostd::ranges::begin
orstd::ranges::end
(it doesn’t have a clear beginning or an end, for the reason explained above), so it’s not even a range to begin with.
Therefore, this code is allowed, as it uses a string literal (const char(&)[N]
) as the source range type:
int i;
scn::scan_default("123", i);
But this code isn’t, as the source range type used is not a range, but a pointer to constant character (const char*
):
const char* source = "123";
int i;
scn::scan_default(source, i); // compiler error
This issue can be avoided by using a string_view
:
const char* source = "123";
int i;
scn::scan_default(scn::string_view{source}, i);
// std::string_view would also work
Return type¶
The return type of the scanning functions is based on the type of the given range. It contains an object of that range type, representing what was left over of the range after scanning. The type is designed in such a way as to minimize copying and dynamic memory allocations. The type also contains an error value.
-
struct
scn
::
wrapped_error
¶ Base class for the result type returned by most scanning functions (except for scan_value).
scan_result_base inherits either from this class or expected.
-
template<typename
WrappedRange
, typenameBase
>
classscn::detail
::
scan_result_base
: public scn::detail::scan_result_base_wrapper<Base>¶ Type returned by scanning functions.
Contains an error (inherits from it: for error, that’s wrapped_error; with scan_value, inherits from expected), and the leftover range after scanning.
The leftover range may reference the range given to the scanning function. Please take the necessary measures to make sure that the original range outlives the leftover range. Alternatively, if possible for your specific range type, call the reconstruct() member function to get a new, independent range.
Subclassed by scn::detail::intermediary_scan_result< WrappedRange, Base >
Public Functions
-
iterator
begin
() const noexcept¶ Beginning of the leftover range.
-
sentinel
end
() const noexcept(noexcept(declval
<wrapped_range_type>().end()))¶ End of the leftover range.
-
bool
empty
() const noexcept(noexcept(declval
<wrapped_range_type>().end()))¶ Whether the leftover range is empty.
-
ranges::subrange<iterator, sentinel>
subrange
() const¶ A subrange pointing to the leftover range.
-
wrapped_range_type &
range
() &¶ Leftover range.
If the leftover range is used to scan a new value, this member function should be used.
-
const wrapped_range_type &
range
() const &¶ Leftover range.
If the leftover range is used to scan a new value, this member function should be used.
-
wrapped_range_type
range
() &&¶ Leftover range.
If the leftover range is used to scan a new value, this member function should be used.
-
template<typename
R
= wrapped_range_type, typename = typename std::enable_if<R::is_contiguous>::type>
basic_string_view<char_type>string_view
() const¶ These member functions enable more conventient use of the leftover range for non-scnlib use cases.
The range must be contiguous.
The lifetime semantics are as one would expect: string_view and scan reference the leftover range, string allocates a new string, independent of the leftover range.
-
template<typename
R
= wrapped_range_type, typename = typename std::enable_if<R::is_contiguous>::type>
span<char_type>span
() const¶ These member functions enable more conventient use of the leftover range for non-scnlib use cases.
The range must be contiguous.
The lifetime semantics are as one would expect: string_view and scan reference the leftover range, string allocates a new string, independent of the leftover range.
-
template<typename
R
= wrapped_range_type, typename = typename std::enable_if<R::is_contiguous>::type>
std::basic_string<char_type>string
() const¶ These member functions enable more conventient use of the leftover range for non-scnlib use cases.
The range must be contiguous.
The lifetime semantics are as one would expect: string_view and scan reference the leftover range, string allocates a new string, independent of the leftover range.
-
template<typename
R
= typename WrappedRange::range_type>
Rreconstruct
() const¶ Reconstructs a range of the original type, independent of the leftover range, beginning from begin and ending in end.
Compiles only if range is reconstructible.
-
iterator
Note, that the values scanned are only touched iff the scanning succeeded, i.e. operator bool()
returns true
.
This means, that reading from a default-constructed value of a built-in type on error will cause UB:
int i;
auto ret = scn::scan("foo", "{}", i);
// ret == false
// i is still default-constructed -- reading from it is UB
Error types¶
-
class
scn
::
error
¶ Error class.
Used as a return value for functions without a success value.
Public Types
-
enum
code
¶ Error code.
Values:
-
enumerator
good
¶ No error.
-
enumerator
end_of_range
¶ EOF.
-
enumerator
invalid_format_string
¶ Format string was invalid.
-
enumerator
invalid_scanned_value
¶ Scanned value was invalid for given type.
e.g. a period ‘.’ when scanning for an int
-
enumerator
invalid_operation
¶ Stream does not support the performed operation.
-
enumerator
value_out_of_range
¶ Scanned value was out of range for the desired type.
(e.g.
>2^32
for anuint32_t
)
-
enumerator
invalid_argument
¶ Invalid argument given to operation.
-
enumerator
exceptions_required
¶ This operation is only possible with exceptions enabled.
-
enumerator
source_error
¶ The source range emitted an error.
-
enumerator
unrecoverable_source_error
¶ The source range emitted an error that cannot be recovered from.
The stream is now unusable.
-
enumerator
unrecoverable_internal_error
¶
-
enumerator
max_error
¶
-
enumerator
Public Functions
-
constexpr
operator bool
() const noexcept¶ Evaluated to true if there was no error.
-
constexpr enum code
code
() const noexcept Get error code.
-
constexpr bool
is_recoverable
() const noexcept¶ Returns
true
if, after this error, the state of the given input range is consistent, and thus, the range can be used for new scanning operations.
-
struct
success_tag_t
¶
-
enum
Convenience scan types¶
These types can be passed to scanning functions (scn::scan
and alike) as arguments, providing useful functionality.
-
template<typename
T
>
structtemporary
¶ Allows reading an rvalue.
Stores an rvalue and returns an lvalue reference to it via
operator()
. Create one with temp.
-
template<typename
T
, typename std::enable_if<!std::is_lvalue_reference<T>::value>::type* = nullptr>
temporary<T>scn
::
temp
(T &&val)¶ Factory function for temporary.
Canonical use case is with span:
std::vector<char> buffer(32, '\0'); auto result = scn::scan("123", "{}", scn::temp(scn::make_span(buffer))); // buffer == "123"
-
template<typename
T
>
discard_type<T> &scn
::
discard
()¶ Scans an instance of
T
, but doesn’t store it anywhere.Uses
scn::temp
internally, so the user doesn’t have to bother.int i{}; // 123 is discarded, 456 is read into `i` auto result = scn::scan("123 456", "{} {}", scn::discard<T>(), i); // result == true // i == 456
-
template<typename
T
>
structspan_list_wrapper
¶ Adapts a
span
into a type that can be read into using scan_list.This way, potentially unnecessary dynamic memory allocations can be avoided. To use as a parameter to scan_list, use make_span_list_wrapper.
std::vector<int> buffer(8, 0); scn::span<int> s = scn::make_span(buffer); auto wrapper = scn::span_list_wrapper<int>(s); scn::scan_list("123 456", wrapper); // s[0] == buffer[0] == 123 // s[1] == buffer[1] == 456
-
template<typename
T
>
autoscn
::
make_span_list_wrapper
(T &s) -> temporary<detail::span_list_wrapper_for<T>>¶ Adapts a contiguous buffer into a type containing a
span
that can be read into using scan_list.Example adapted from span_list_wrapper:
std::vector<int> buffer(8, 0); scn::scan_list("123 456", scn::make_span_list_wrapper(buffer)); // s[0] == buffer[0] == 123 // s[1] == buffer[1] == 456
- See
- See
Format string¶
Every value to be scanned from the source range is marked with a pair of
curly braces "{}"
in the format string. Inside these braces, additional
options can be specified. The syntax is not dissimilar from the one found in
fmtlib.
The information inside the braces consist of two parts: the index and the
scanning options, separated by a colon ':'
.
The index part can either be empty, or be an integer. If the index is specified for one of the arguments, it must be set for all of them. The index tells the library which argument the braces correspond to.
int i;
std::string str;
scn::scan(range, "{1} {0}", i, str);
// Reads from the range in the order of:
// string, whitespace, integer
// That's because the first format string braces have index '1', pointing to
// the second passed argument (indices start from 0), which is a string
After the index comes a colon and the scanning options. The colon only has to be there if any scanning options are specified.
For span
s, there are no supported scanning options.
Integral types¶
There are localization specifiers:
n
: Use thousands separator from the given locale
l
: Accept characters specified as digits by the given locale. Impliesn
(default): Use
,
as thousands separator and[0-9]
as digits
And base specifiers:
d
: Decimal (base-10)
x
: Hexadecimal (base-16)
o
: Octal (base-8)
b..
Custom base;b
followed by one or two digits (e.g.b2
for binary). Base must be between 2 and 36, inclusive(default): Detect base.
0x
/0X
prefix for hexadecimal,0
prefix for octal, decimal by default
i
: Detect base. Argument must be signed
u
: Detect base. Argument must be unsigned
And other options:
'
: Accept thousands separator characters, as specified by the given locale (only withcustom
-scanning method)(default): Thousands separator characters aren’t accepted
These specifiers can be given in any order, with up to one from each category.
Floating-point types¶
First, there’s a localization specifier:
n
: Use decimal and thousands separator from the given locale(default): Use
.
as decimal point and,
as thousands separator
After that, an optional a
, A
, e
, E
, f
, F
, g
or G
can be
given, which has no effect.
bool
¶
First, there are a number of specifiers that can be given, in any order:
a
: Accept onlytrue
orfalse
n
: Accept only0
or1
l
: Impliesa
. Expect boolean text values as specified as such by the given locale(default): Accept
0
,1
,true
, andfalse
, equivalent toan
After that, an optional b
can be given, which has no effect.
Strings (std::string
, string_view
)¶
Only supported option is s
, which has no effect
Characters (char
, wchar_t
)¶
Only supported option is c
, which has no effect
Whitespace¶
Any amount of whitespace in the format string tells the library to skip until the next non-whitespace character is found from the range. Not finding any whitespace from the range is not an error.
Literal characters¶
To scan literal characters and immediately discard them, just write the
characters in the format string. scanf
-like []
-wildcard is not supported.
To read literal {
or }
, write {{
or }}
, respectively.
std::string bar;
scn::scan("foobar", "foo{}", bar);
// bar == "bar"
Semantics of scanning a value¶
In the beginning, with every scn::scan
(or similar) call, the library
wraps the given range in a scn::detail::range_wrapper
.
This wrapper provides an uniform interface and lifetime semantics over all possible ranges.
The arguments to scan are wrapped in a scn::arg_store
.
The appropriate context and parse context types are then constructed based on these values,
the format string, and the requested locale.
These are passed to scn::vscan
, which then calls scn::visit
.
There, the library calls begin()
on the range, getting an iterator. This iterator is
advanced until a non-whitespace character is found.
After that, the format string is scanned character-by-character, until an
unescaped '{'
is found, after which the part after the '{'
is parsed,
until a ':'
or '}'
is found. If the parser finds an argument id,
the argument with that id is fetched from the argument list, otherwise the
next argument is used.
The parse()
member function of the appropriate scn::scanner
specialization is called, which parses the parsing options-part of the format
string argument, setting the member variables of the scn::scanner
specialization to their appropriate values.
After that, the scan()
member function is called. It reads the range,
starting from the aforementioned iterator, into a buffer until the next
whitespace character is found (except for char
/wchar_t
: just a single
character is read; and for span
: span.size()
characters are read). That
buffer is then parsed with the appropriate algorithm (plain copy for
string
s, the method determined by the options
object for ints and
floats).
If some of the characters in the buffer were not used, these characters are
put back to the range, meaning that operator--
is called on the iterator.
Because how the range is read until a whitespace character, and how the
unused part of the buffer is simply put back to the range, some interesting
situations may arise. Please note, that the following behavior is consistent
with both scanf
and <iostream>
.
char c;
std::string str;
// No whitespace character after first {}, no range whitespace is skipped
scn::scan("abc", "{}{}", c, str);
// c == 'a'
// str == "bc"
// Not finding whitespace to skip from the range when whitespace is found in
// the format string isn't an error
scn::scan("abc", "{} {}", c, str);
// c == 'a'
// str == "bc"
// Because there are no non-whitespace characters between 'a' and the next
// whitespace character ' ', ``str`` is empty
scn::scan("a bc", "{}{}", c, str);
// c == 'a'
// str == ""
// Nothing surprising
scn::scan("a bc", "{} {}", c, str);
// c == 'a'
// str == "bc"
Using scn::scan_default
is equivalent to using "{}"
in the format string
as many times as there are arguments, separated by whitespace.
scn::scan_default(range, a, b);
// Equivalent to:
// scn::scan(range, "{} {}", a, b);
Files¶
-
template<typename
CharT
>
classscn
::
basic_file
¶ Range mapping to a C FILE*.
Not copyable or reconstructible.
Subclassed by scn::basic_owning_file< CharT >
Public Functions
-
basic_file
(FILE *f)¶ Construct from a FILE*.
Must be a valid handle that can be read from.
-
FILE *
handle
() const¶ Get the FILE* for this range.
Only use this handle for reading sync() has been called and no reading operations have taken place after that.
- See
-
FILE *
set_handle
(FILE *f)¶ Reset the file handle.
Calls sync(), if necessary, before resetting.
- Return
The old handle
-
bool
valid
() const¶ Whether the file has been opened.
-
void
sync
()¶ Synchronizes this file with the underlying FILE*.
Invalidates all non-end iterators. File must be open.
Necessary for mixing-and-matching scnlib and <cstdio>:
scn::scan(file, ...); file.sync(); std::fscanf(file.handle(), ...);
Necessary for synchronizing result objects:
auto result = scn::scan(file, ...); // only result.range() can now be used for scanning result = scn::scan(result.range(), ...); // .sync() allows the original file to also be used file.sync(); result = scn::scan(file, ...);
-
class
iterator
¶
-
-
template<typename
CharT
>
classscn
::
basic_owning_file
: public scn::basic_file<CharT>¶ A child class for basic_file, handling fopen, fclose, and lifetimes with RAII.
Public Functions
-
basic_owning_file
() = default¶ Open an empty file.
-
basic_owning_file
(const char *f, const char *mode)¶ Open a file, with fopen arguments.
-
basic_owning_file
(FILE *f)¶ Steal ownership of a FILE*.
-
bool
open
(const char *f, const char *mode)¶ fopen
-
bool
open
(FILE *f)¶ Steal ownership.
-
void
close
()¶ Close file.
-
SCN_NODISCARD bool is_open () const
Is the file open.
-
-
template<typename
CharT
>
classscn
::
basic_mapped_file
: public scn::detail::byte_mapped_file¶ Memory-mapped file range.
Manages the lifetime of the mapping itself.
-
using
scn
::
file
= basic_file<char>¶
-
using
scn
::
wfile
= basic_file<wchar_t>¶
-
using
scn
::
owning_file
= basic_owning_file<char>¶
-
using
scn
::
owning_wfile
= basic_owning_file<wchar_t>¶
-
using
scn
::
mapped_file
= basic_mapped_file<char>¶
-
using
scn
::
mapped_wfile
= basic_mapped_file<wchar_t>¶
-
template<typename
CharT
>
basic_file<CharT> &scn
::
stdin_range
()¶ Get a reference to the global stdin range.
Lower level parsing and scanning operations¶
-
template<typename
Context
, typenameParseCtx
>
errorscn
::
vscan
(Context &ctx, ParseCtx &pctx, basic_args<typename Context::char_type> args)¶ In the spirit of {fmt}/
std::format
andvformat
,vscan
behaves similarly to scan, except instead of taking a variadic argument pack, it takes an object of typebasic_args
, which type-erases the arguments to scan.This, in effect, will decrease generated code size and compile times dramatically.
parse_integer
and parse_float
will provide super-fast parsing from a string, at the expense of some safety and usability guarantees.
Using these functions can easily lead to unexpected behavior or UB if not used correctly and proper precautions are not taken.
-
template<typename
T
, typenameCharT
>
expected<const CharT*>scn
::
parse_integer
(basic_string_view<CharT> str, T &val, int base = 10)¶ Parses an integer into
val
in basebase
fromstr
.Returns a pointer past the last character read, or an error.
- Parameters
str
: source, can’t be empty, cannot have:preceding whitespace
preceding
"0x"
or"0"
(base is determined by thebase
parameter)'+'
sign ('-'
is fine)
val
: parsed integer, must be default-constructedbase
: between [2,36]
-
template<typename
T
, typenameCharT
>
expected<const CharT*>scn
::
parse_float
(basic_string_view<CharT> str, T &val)¶ Parses float into
val
fromstr
.Returns a pointer past the last character read, or an error.
- Parameters
str
: source, can’t be emptyval
: parsed float, must be default-constructed
The following functions abstract away the source range in easier to understand parsing operations.
-
template<typename
WrappedRange
, typename std::enable_if<WrappedRange::is_contiguous>::type* = nullptr>
expected<span<const typename detail::extract_char_type<typename WrappedRange::iterator>::type>>scn
::
read_zero_copy
(WrappedRange &r, ranges::range_difference_t<WrappedRange> n)¶ Reads up to
n
characters fromr
, and returns aspan
into the range.If
r.begin() == r.end()
, returns EOF. If the range does not satisfycontiguous_range
, returns an emptyspan
.Let
count
bemin(r.size(), n)
. Returns a span pointing tor.data()
with the lengthcount
. Advances the range bycount
characters.
-
template<typename
WrappedRange
, typename std::enable_if<WrappedRange::is_contiguous>::type* = nullptr>
expected<span<const typename detail::extract_char_type<typename WrappedRange::iterator>::type>>scn
::
read_all_zero_copy
(WrappedRange &r)¶ Reads every character from
r
, and returns aspan
into the range.If
r.begin() == r.end()
, returns EOF. If the range does not satisfycontiguous_range
, returns an emptyspan
.
-
template<typename
WrappedRange
, typenameOutputIterator
, typename std::enable_if<WrappedRange::is_contiguous>::type* = nullptr>
errorscn
::
read_into
(WrappedRange &r, OutputIterator &it, ranges::range_difference_t<WrappedRange> n)¶ Reads
n
characters fromr
intoit
.If
r.begin() == r.end()
in the beginning or before advancingn
characters, returns EOF. Ifr
can’t be advanced byn
characters, the range is advanced by an indeterminate amout. If successful, the range is advanced byn
characters.
-
template<typename
WrappedRange
, typenamePredicate
, typename std::enable_if<WrappedRange::is_contiguous>::type* = nullptr>
expected<span<const typename detail::extract_char_type<typename WrappedRange::iterator>::type>>scn
::
read_until_space_zero_copy
(WrappedRange &r, Predicate is_space, bool keep_final_space)¶ Reads characters from
r
until a space is found (as determined byis_space
), and returns aspan
into the range.If
r.begin() == r.end()
, returns EOF. If the range does not satisfycontiguous_range
, returns an emptyspan
.- Parameters
is_space
: Predicate taking a character and returning abool
.true
means, that the given character is a space.keep_final_space
: Whether the final found space character is included in the returned span, and is advanced past.
-
template<typename
WrappedRange
, typenameOutputIterator
, typenamePredicate
, typename std::enable_if<WrappedRange::is_contiguous>::type* = nullptr>
errorscn
::
read_until_space
(WrappedRange &r, OutputIterator &out, Predicate is_space, bool keep_final_space)¶ Reads characters from
r
until a space is found (as determined byis_space
) and writes them intoout
.If
r.begin() == r.end()
, returns EOF.- Parameters
is_space
: Predicate taking a character and returning abool
.true
means, that the given character is a space.keep_final_space
: Whether the final found space character is written intoout
and is advanced past.
-
template<typename
WrappedRange
, typenameOutputIterator
, typenameSentinel
, typenamePredicate
, typename std::enable_if<WrappedRange::is_direct>::type* = nullptr>
errorscn
::
read_until_space_ranged
(WrappedRange &r, OutputIterator &out, Sentinel end, Predicate is_space, bool keep_final_space)¶ Reads characters from
r
until a space is found (as determined byis_space
), orout
reachesend
, and writes them intoout
.If
r.begin() == r.end()
, returns EOF.- Parameters
is_space
: Predicate taking a character and returning abool
.true
means, that the given character is a space.keep_final_space
: Whether the final found space character is written intoout
and is advanced past.
-
template<typename
WrappedRange
, typename std::enable_if<WrappedRange::is_contiguous>::type* = nullptr>
errorscn
::
putback_n
(WrappedRange &r, ranges::range_difference_t<WrappedRange> n)¶ Puts back
n
characters intor
as if by repeatedly callingr.advance(-1)
.
-
template<typename
Context
, typename std::enable_if<!Context::range_type::is_contiguous>::type* = nullptr>
errorscn
::
skip_range_whitespace
(Context &ctx) noexcept¶ Reads from the range in
ctx
as if by repeatedly callingread_char()
, until a non-space character is found (as determined byctx.locale()
), or EOF is reached.That non-space character is then put back into the range.
Utility types¶
-
template<typename
CharT
>
classbasic_string_view
¶ A view over a (sub)string.
Used even when std::string_view is available to avoid compatibility issues.
-
using
scn
::
string_view
= basic_string_view<char>¶
-
using
scn
::
wstring_view
= basic_string_view<wchar_t>¶
-
template<typename
T
>
classspan
¶ A view over a contiguous range.
Stripped-down version of
std::span
.
-
template<typename
T
>
classoptional
¶ A very lackluster optional implementation.
Useful when scanning non-default-constructible types, especially with <tuple_return.h>:
// implement scn::scanner for optional<mytype> optional<mytype> val; scn::scan(source, "{}", val); // with tuple_return: auto [result, val] = scn::scan_tuple<optional<mytype>>(source, "{}");