1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
//===-- Format string parser for scanf -------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_PARSER_H
#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_PARSER_H
#include "src/__support/arg_list.h"
#include "src/__support/common.h"
#include "src/stdio/scanf_core/core_structs.h"
#include "src/stdio/scanf_core/scanf_config.h"
#include <stddef.h>
namespace __llvm_libc {
namespace scanf_core {
class Parser {
const char *__restrict str;
size_t cur_pos = 0;
internal::ArgList args_cur;
#ifndef LIBC_COPT_SCANF_DISABLE_INDEX_MODE
// args_start stores the start of the va_args, which is used when a previous
// argument is needed. In that case, we have to read the arguments from the
// beginning since they don't support reading backwards.
internal::ArgList args_start;
size_t args_index = 1;
#endif // LIBC_COPT_SCANF_DISABLE_INDEX_MODE
public:
#ifndef LIBC_COPT_SCANF_DISABLE_INDEX_MODE
LIBC_INLINE Parser(const char *__restrict new_str, internal::ArgList &args)
: str(new_str), args_cur(args), args_start(args) {}
#else
LIBC_INLINE Parser(const char *__restrict new_str, internal::ArgList &args)
: str(new_str), args_cur(args) {}
#endif // LIBC_COPT_SCANF_DISABLE_INDEX_MODE
// get_next_section will parse the format string until it has a fully
// specified format section. This can either be a raw format section with no
// conversion, or a format section with a conversion that has all of its
// variables stored in the format section.
FormatSection get_next_section();
private:
// parse_length_modifier parses the length modifier inside a format string. It
// assumes that str[*local_pos] is inside a format specifier. It returns a
// LengthModifier with the length modifier it found. It will advance local_pos
// after the format specifier if one is found.
LengthModifier parse_length_modifier(size_t *local_pos);
// get_next_arg_value gets the next value from the arg list as type T.
template <class T> LIBC_INLINE T get_next_arg_value() {
return args_cur.next_var<T>();
}
//----------------------------------------------------
// INDEX MODE ONLY FUNCTIONS AFTER HERE:
//----------------------------------------------------
#ifndef LIBC_COPT_SCANF_DISABLE_INDEX_MODE
// parse_index parses the index of a value inside a format string. It
// assumes that str[*local_pos] points to character after a '%' or '*', and
// returns 0 if there is no closing $, or if it finds no number. If it finds a
// number, it will move local_pos past the end of the $, else it will not move
// local_pos.
size_t parse_index(size_t *local_pos);
// get_arg_value gets the value from the arg list at index (starting at 1).
// This may require parsing the format string. An index of 0 is interpreted as
// the next value.
template <class T> LIBC_INLINE T get_arg_value(size_t index) {
if (!(index == 0 || index == args_index))
args_to_index(index);
++args_index;
return get_next_arg_value<T>();
}
// the ArgList can only return the next item in the list. This function is
// used in index mode when the item that needs to be read is not the next one.
// It moves cur_args to the index requested so the the appropriate value may
// be read. This may involve parsing the format string, and is in the worst
// case an O(n^2) operation.
void args_to_index(size_t index);
#endif // LIBC_COPT_SCANF_DISABLE_INDEX_MODE
};
} // namespace scanf_core
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_PARSER_H
|