/src/WasmEdge/include/po/parser.h
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | //===-- wasmedge/po/parser.h - Single Argument parser ---------------------===// |
5 | | // |
6 | | // Part of the WasmEdge Project. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | #pragma once |
10 | | |
11 | | #include "po/error.h" |
12 | | #include <algorithm> |
13 | | #include <cstdint> |
14 | | #include <fmt/format.h> |
15 | | #include <string> |
16 | | #include <utility> |
17 | | |
18 | | namespace WasmEdge { |
19 | | namespace PO { |
20 | | |
21 | 0 | inline void tolower(std::string &String) noexcept { |
22 | 0 | std::transform( |
23 | 0 | String.begin(), String.end(), String.begin(), |
24 | 0 | [](char C) noexcept { return static_cast<char>(std::tolower(C)); }); |
25 | 0 | } |
26 | | |
27 | | template <typename ConvResultT, typename ResultT = ConvResultT> |
28 | | inline cxx20::expected<ResultT, Error> |
29 | | stringToInteger(ConvResultT (&Conv)(const char *, char **, int), |
30 | 126k | std::string Value) noexcept { |
31 | 126k | using namespace std::literals; |
32 | 126k | char *EndPtr; |
33 | 126k | const char *CStr = Value.c_str(); |
34 | 126k | auto SavedErrNo = std::exchange(errno, 0); |
35 | 126k | const auto Result = Conv(CStr, &EndPtr, 10); |
36 | 126k | std::swap(SavedErrNo, errno); |
37 | 126k | if (Value.empty() || *EndPtr != '\0') { |
38 | 137 | return cxx20::unexpected<Error>( |
39 | 137 | std::in_place, ErrCode::InvalidArgument, |
40 | 137 | fmt::format("invalid integer value: {}", Value)); |
41 | 137 | } |
42 | 126k | auto InsideRange = [](auto WiderResult) constexpr noexcept { |
43 | 126k | using WiderResultT = decltype(WiderResult); |
44 | 126k | if constexpr (std::is_same_v<ResultT, WiderResultT>) { |
45 | 69.8k | return true; |
46 | 69.8k | } else { |
47 | 56.7k | return static_cast<WiderResultT>(std::numeric_limits<ResultT>::min()) <= |
48 | 56.7k | WiderResult && |
49 | 56.7k | WiderResult <= |
50 | 56.7k | static_cast<WiderResultT>(std::numeric_limits<ResultT>::max()); |
51 | 56.7k | } |
52 | 126k | }; auto WasmEdge::PO::stringToInteger<long, int>(long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)::{lambda(auto:1)#1}::operator()<long>(long) constLine | Count | Source | 42 | 56.7k | auto InsideRange = [](auto WiderResult) constexpr noexcept { | 43 | 56.7k | using WiderResultT = decltype(WiderResult); | 44 | | if constexpr (std::is_same_v<ResultT, WiderResultT>) { | 45 | | return true; | 46 | 56.7k | } else { | 47 | 56.7k | return static_cast<WiderResultT>(std::numeric_limits<ResultT>::min()) <= | 48 | 56.7k | WiderResult && | 49 | 56.7k | WiderResult <= | 50 | 56.7k | static_cast<WiderResultT>(std::numeric_limits<ResultT>::max()); | 51 | 56.7k | } | 52 | 56.7k | }; |
Unexecuted instantiation: auto WasmEdge::PO::stringToInteger<unsigned long, unsigned int>(unsigned long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)::{lambda(auto:1)#1}::operator()<unsigned long>(unsigned long) constUnexecuted instantiation: auto WasmEdge::PO::stringToInteger<long, signed char>(long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)::{lambda(auto:1)#1}::operator()<long>(long) constUnexecuted instantiation: auto WasmEdge::PO::stringToInteger<unsigned long, unsigned char>(unsigned long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)::{lambda(auto:1)#1}::operator()<unsigned long>(unsigned long) constUnexecuted instantiation: auto WasmEdge::PO::stringToInteger<long, short>(long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)::{lambda(auto:1)#1}::operator()<long>(long) constUnexecuted instantiation: auto WasmEdge::PO::stringToInteger<unsigned long, unsigned short>(unsigned long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)::{lambda(auto:1)#1}::operator()<unsigned long>(unsigned long) constUnexecuted instantiation: auto WasmEdge::PO::stringToInteger<long, long>(long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)::{lambda(auto:1)#1}::operator()<long>(long) constUnexecuted instantiation: auto WasmEdge::PO::stringToInteger<long long, long long>(long long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)::{lambda(auto:1)#1}::operator()<long long>(long long) constauto WasmEdge::PO::stringToInteger<unsigned long, unsigned long>(unsigned long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)::{lambda(auto:1)#1}::operator()<unsigned long>(unsigned long) constLine | Count | Source | 42 | 69.8k | auto InsideRange = [](auto WiderResult) constexpr noexcept { | 43 | 69.8k | using WiderResultT = decltype(WiderResult); | 44 | 69.8k | if constexpr (std::is_same_v<ResultT, WiderResultT>) { | 45 | 69.8k | return true; | 46 | | } else { | 47 | | return static_cast<WiderResultT>(std::numeric_limits<ResultT>::min()) <= | 48 | | WiderResult && | 49 | | WiderResult <= | 50 | | static_cast<WiderResultT>(std::numeric_limits<ResultT>::max()); | 51 | | } | 52 | 69.8k | }; |
Unexecuted instantiation: auto WasmEdge::PO::stringToInteger<unsigned long long, unsigned long long>(unsigned long long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)::{lambda(auto:1)#1}::operator()<unsigned long long>(unsigned long long) const |
53 | 126k | if (SavedErrNo == ERANGE || !InsideRange(Result)) { |
54 | 70 | return cxx20::unexpected<Error>( |
55 | 70 | std::in_place, ErrCode::OutOfRange, |
56 | 70 | fmt::format("integer value out of range: {}", Value)); |
57 | 70 | } |
58 | 126k | return static_cast<ResultT>(Result); |
59 | 126k | } cxx20::expected<int, WasmEdge::PO::Error> WasmEdge::PO::stringToInteger<long, int>(long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Line | Count | Source | 30 | 56.8k | std::string Value) noexcept { | 31 | 56.8k | using namespace std::literals; | 32 | 56.8k | char *EndPtr; | 33 | 56.8k | const char *CStr = Value.c_str(); | 34 | 56.8k | auto SavedErrNo = std::exchange(errno, 0); | 35 | 56.8k | const auto Result = Conv(CStr, &EndPtr, 10); | 36 | 56.8k | std::swap(SavedErrNo, errno); | 37 | 56.8k | if (Value.empty() || *EndPtr != '\0') { | 38 | 116 | return cxx20::unexpected<Error>( | 39 | 116 | std::in_place, ErrCode::InvalidArgument, | 40 | 116 | fmt::format("invalid integer value: {}", Value)); | 41 | 116 | } | 42 | 56.7k | auto InsideRange = [](auto WiderResult) constexpr noexcept { | 43 | 56.7k | using WiderResultT = decltype(WiderResult); | 44 | 56.7k | if constexpr (std::is_same_v<ResultT, WiderResultT>) { | 45 | 56.7k | return true; | 46 | 56.7k | } else { | 47 | 56.7k | return static_cast<WiderResultT>(std::numeric_limits<ResultT>::min()) <= | 48 | 56.7k | WiderResult && | 49 | 56.7k | WiderResult <= | 50 | 56.7k | static_cast<WiderResultT>(std::numeric_limits<ResultT>::max()); | 51 | 56.7k | } | 52 | 56.7k | }; | 53 | 56.7k | if (SavedErrNo == ERANGE || !InsideRange(Result)) { | 54 | 67 | return cxx20::unexpected<Error>( | 55 | 67 | std::in_place, ErrCode::OutOfRange, | 56 | 67 | fmt::format("integer value out of range: {}", Value)); | 57 | 67 | } | 58 | 56.7k | return static_cast<ResultT>(Result); | 59 | 56.7k | } |
Unexecuted instantiation: cxx20::expected<unsigned int, WasmEdge::PO::Error> WasmEdge::PO::stringToInteger<unsigned long, unsigned int>(unsigned long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Unexecuted instantiation: cxx20::expected<signed char, WasmEdge::PO::Error> WasmEdge::PO::stringToInteger<long, signed char>(long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Unexecuted instantiation: cxx20::expected<unsigned char, WasmEdge::PO::Error> WasmEdge::PO::stringToInteger<unsigned long, unsigned char>(unsigned long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Unexecuted instantiation: cxx20::expected<short, WasmEdge::PO::Error> WasmEdge::PO::stringToInteger<long, short>(long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Unexecuted instantiation: cxx20::expected<unsigned short, WasmEdge::PO::Error> WasmEdge::PO::stringToInteger<unsigned long, unsigned short>(unsigned long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Unexecuted instantiation: cxx20::expected<long, WasmEdge::PO::Error> WasmEdge::PO::stringToInteger<long, long>(long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Unexecuted instantiation: cxx20::expected<long long, WasmEdge::PO::Error> WasmEdge::PO::stringToInteger<long long, long long>(long long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) cxx20::expected<unsigned long, WasmEdge::PO::Error> WasmEdge::PO::stringToInteger<unsigned long, unsigned long>(unsigned long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Line | Count | Source | 30 | 69.8k | std::string Value) noexcept { | 31 | 69.8k | using namespace std::literals; | 32 | 69.8k | char *EndPtr; | 33 | 69.8k | const char *CStr = Value.c_str(); | 34 | 69.8k | auto SavedErrNo = std::exchange(errno, 0); | 35 | 69.8k | const auto Result = Conv(CStr, &EndPtr, 10); | 36 | 69.8k | std::swap(SavedErrNo, errno); | 37 | 69.8k | if (Value.empty() || *EndPtr != '\0') { | 38 | 21 | return cxx20::unexpected<Error>( | 39 | 21 | std::in_place, ErrCode::InvalidArgument, | 40 | 21 | fmt::format("invalid integer value: {}", Value)); | 41 | 21 | } | 42 | 69.8k | auto InsideRange = [](auto WiderResult) constexpr noexcept { | 43 | 69.8k | using WiderResultT = decltype(WiderResult); | 44 | 69.8k | if constexpr (std::is_same_v<ResultT, WiderResultT>) { | 45 | 69.8k | return true; | 46 | 69.8k | } else { | 47 | 69.8k | return static_cast<WiderResultT>(std::numeric_limits<ResultT>::min()) <= | 48 | 69.8k | WiderResult && | 49 | 69.8k | WiderResult <= | 50 | 69.8k | static_cast<WiderResultT>(std::numeric_limits<ResultT>::max()); | 51 | 69.8k | } | 52 | 69.8k | }; | 53 | 69.8k | if (SavedErrNo == ERANGE || !InsideRange(Result)) { | 54 | 3 | return cxx20::unexpected<Error>( | 55 | 3 | std::in_place, ErrCode::OutOfRange, | 56 | 3 | fmt::format("integer value out of range: {}", Value)); | 57 | 3 | } | 58 | 69.8k | return static_cast<ResultT>(Result); | 59 | 69.8k | } |
Unexecuted instantiation: cxx20::expected<unsigned long long, WasmEdge::PO::Error> WasmEdge::PO::stringToInteger<unsigned long long, unsigned long long>(unsigned long long (&)(char const*, char**, int), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) |
60 | | |
61 | | template <typename ConvResultT, typename ResultT = ConvResultT> |
62 | | inline cxx20::expected<ResultT, Error> |
63 | | stringToFloating(ConvResultT (&Conv)(const char *, char **), |
64 | 0 | std::string Value) noexcept { |
65 | 0 | using namespace std::literals; |
66 | 0 | char *EndPtr; |
67 | 0 | const char *CStr = Value.c_str(); |
68 | 0 | auto SavedErrNo = std::exchange(errno, 0); |
69 | 0 | const auto Result = Conv(CStr, &EndPtr); |
70 | 0 | std::swap(SavedErrNo, errno); |
71 | 0 | if (Value.empty() || *EndPtr != '\0') { |
72 | 0 | return cxx20::unexpected<Error>( |
73 | 0 | std::in_place, ErrCode::InvalidArgument, |
74 | 0 | fmt::format("invalid floating-point value: {}", Value)); |
75 | 0 | } |
76 | 0 | if (SavedErrNo == ERANGE) { |
77 | 0 | return cxx20::unexpected<Error>( |
78 | 0 | std::in_place, ErrCode::OutOfRange, |
79 | 0 | fmt::format("floating-point value out of range: {}", Value)); |
80 | 0 | } |
81 | 0 | return Result; |
82 | 0 | } Unexecuted instantiation: cxx20::expected<float, WasmEdge::PO::Error> WasmEdge::PO::stringToFloating<float, float>(float (&)(char const*, char**), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Unexecuted instantiation: cxx20::expected<double, WasmEdge::PO::Error> WasmEdge::PO::stringToFloating<double, double>(double (&)(char const*, char**), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Unexecuted instantiation: cxx20::expected<long double, WasmEdge::PO::Error> WasmEdge::PO::stringToFloating<long double, long double>(long double (&)(char const*, char**), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) |
83 | | |
84 | | template <typename T> struct Parser; |
85 | | |
86 | | template <> struct Parser<std::string> { |
87 | 1.18M | static cxx20::expected<std::string, Error> parse(std::string Value) noexcept { |
88 | 1.18M | return Value; |
89 | 1.18M | } |
90 | | }; |
91 | | |
92 | | template <> struct Parser<bool> { |
93 | 0 | static cxx20::expected<bool, Error> parse(std::string Value) noexcept { |
94 | 0 | using namespace std::literals; |
95 | 0 | if (!Value.empty()) { |
96 | 0 | switch (Value[0]) { |
97 | 0 | case 'T': |
98 | 0 | case 't': |
99 | 0 | if (Value.size() == 4) { |
100 | 0 | tolower(Value); |
101 | 0 | if (Value == "true"sv) { |
102 | 0 | return true; |
103 | 0 | } |
104 | 0 | } |
105 | 0 | break; |
106 | 0 | case '1': |
107 | 0 | if (Value.size() == 1) { |
108 | 0 | return true; |
109 | 0 | } |
110 | 0 | break; |
111 | 0 | case 'F': |
112 | 0 | case 'f': |
113 | 0 | if (Value.size() == 5) { |
114 | 0 | tolower(Value); |
115 | 0 | if (Value == "false"sv) { |
116 | 0 | return false; |
117 | 0 | } |
118 | 0 | } |
119 | 0 | break; |
120 | 0 | case '0': |
121 | 0 | if (Value.size() == 1) { |
122 | 0 | return false; |
123 | 0 | } |
124 | 0 | break; |
125 | 0 | default: |
126 | 0 | break; |
127 | 0 | } |
128 | 0 | } |
129 | 0 | return cxx20::unexpected<Error>(std::in_place, ErrCode::InvalidArgument, |
130 | 0 | "invalid boolean string: "s + Value); |
131 | 0 | } |
132 | | }; |
133 | | |
134 | | template <> struct Parser<int> { |
135 | 56.8k | static cxx20::expected<int, Error> parse(std::string Value) noexcept { |
136 | 56.8k | return stringToInteger<long, int>(std::strtol, std::move(Value)); |
137 | 56.8k | } |
138 | | }; |
139 | | |
140 | | template <> struct Parser<unsigned int> { |
141 | | static cxx20::expected<unsigned int, Error> |
142 | 0 | parse(std::string Value) noexcept { |
143 | 0 | return stringToInteger<unsigned long, unsigned int>(std::strtoul, |
144 | 0 | std::move(Value)); |
145 | 0 | } |
146 | | }; |
147 | | |
148 | | template <> struct Parser<signed char> { |
149 | 0 | static cxx20::expected<signed char, Error> parse(std::string Value) noexcept { |
150 | 0 | return stringToInteger<long, signed char>(std::strtol, std::move(Value)); |
151 | 0 | } |
152 | | }; |
153 | | |
154 | | template <> struct Parser<unsigned char> { |
155 | | static cxx20::expected<unsigned char, Error> |
156 | 0 | parse(std::string Value) noexcept { |
157 | 0 | return stringToInteger<unsigned long, unsigned char>(std::strtoul, |
158 | 0 | std::move(Value)); |
159 | 0 | } |
160 | | }; |
161 | | |
162 | | template <> struct Parser<short> { |
163 | 0 | static cxx20::expected<short, Error> parse(std::string Value) noexcept { |
164 | 0 | return stringToInteger<long, short>(std::strtol, std::move(Value)); |
165 | 0 | } |
166 | | }; |
167 | | |
168 | | template <> struct Parser<unsigned short> { |
169 | | static cxx20::expected<unsigned short, Error> |
170 | 0 | parse(std::string Value) noexcept { |
171 | 0 | return stringToInteger<unsigned long, unsigned short>(std::strtoul, |
172 | 0 | std::move(Value)); |
173 | 0 | } |
174 | | }; |
175 | | |
176 | | template <> struct Parser<long> { |
177 | 0 | static cxx20::expected<long, Error> parse(std::string Value) noexcept { |
178 | 0 | return stringToInteger(std::strtol, std::move(Value)); |
179 | 0 | } |
180 | | }; |
181 | | |
182 | | template <> struct Parser<long long> { |
183 | 0 | static cxx20::expected<long long, Error> parse(std::string Value) noexcept { |
184 | 0 | return stringToInteger(std::strtoll, std::move(Value)); |
185 | 0 | } |
186 | | }; |
187 | | |
188 | | template <> struct Parser<unsigned long> { |
189 | | static cxx20::expected<unsigned long, Error> |
190 | 69.8k | parse(std::string Value) noexcept { |
191 | 69.8k | return stringToInteger(std::strtoul, std::move(Value)); |
192 | 69.8k | } |
193 | | }; |
194 | | |
195 | | template <> struct Parser<unsigned long long> { |
196 | | static cxx20::expected<unsigned long long, Error> |
197 | 0 | parse(std::string Value) noexcept { |
198 | 0 | return stringToInteger(std::strtoull, std::move(Value)); |
199 | 0 | } |
200 | | }; |
201 | | |
202 | | template <> struct Parser<float> { |
203 | 0 | static cxx20::expected<float, Error> parse(std::string Value) noexcept { |
204 | 0 | return stringToFloating(std::strtof, std::move(Value)); |
205 | 0 | } |
206 | | }; |
207 | | |
208 | | template <> struct Parser<double> { |
209 | 0 | static cxx20::expected<double, Error> parse(std::string Value) noexcept { |
210 | 0 | return stringToFloating(std::strtod, std::move(Value)); |
211 | 0 | } |
212 | | }; |
213 | | |
214 | | template <> struct Parser<long double> { |
215 | 0 | static cxx20::expected<long double, Error> parse(std::string Value) noexcept { |
216 | 0 | return stringToFloating(std::strtold, std::move(Value)); |
217 | 0 | } |
218 | | }; |
219 | | |
220 | | } // namespace PO |
221 | | } // namespace WasmEdge |