Line data Source code
1 : /**
2 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_DATA_SPDATA_H_
25 : #define STAPPLER_DATA_SPDATA_H_
26 :
27 : #include "SPDataDecode.h"
28 : #include "SPDataEncode.h"
29 :
30 : namespace STAPPLER_VERSIONIZED stappler::data {
31 :
32 : // command line options parsing
33 : //
34 : // arguments, prefixed with '-' resolved as char switches
35 : // 'switchCallback' used to process this chars
36 : // 'char c' - current char,
37 : // 'const char *str' - string in which this char was found, str[0] = c;
38 : // return value - number of processed chars (usually - 1)
39 : // For string '-name' switchCallback will be called 4 times with each char in string,
40 : // but you can process whole string in first call, then return 4 from callback
41 : //
42 : // arguments, prefixed with '--' resolved as string options
43 : // 'stringCallback' used to process this strings
44 : // 'const String &str' - current parsed string
45 : // 'int argc' - number of strings in argv
46 : // 'const char * argv[]' - remaining strings to parse
47 : // return value - number of parsed strings (usually 1)
48 :
49 : template <typename Interface, typename Output = ValueTemplate<Interface>>
50 25 : bool parseCommandLineOptions(Output &output, int argc, const char * argv[],
51 : const Callback<void(Output &, StringView)> &argCallback,
52 : const Callback<int (Output &, char c, const char *str)> &switchCallback,
53 : const Callback<int (Output &, const StringView &str, int argc, const char * argv[])> &stringCallback) {
54 25 : if (argc == 0) {
55 0 : return false;
56 : }
57 :
58 25 : int i = argc;
59 50 : while (i > 0) {
60 25 : const char *value = argv[argc - i];
61 25 : char quoted = 0;
62 25 : if (value[0] == '\'' || value[0] == '"') {
63 0 : quoted = value[0];
64 0 : value ++;
65 : }
66 25 : if (value[0] == '-') {
67 0 : if (value[1] == '-') {
68 0 : if (stringCallback) {
69 0 : i -= (stringCallback(output, &value[2], i - 1, &argv[argc - i + 1]) - 1);
70 : } else {
71 0 : i -= 1;
72 : }
73 : } else {
74 0 : if (switchCallback) {
75 0 : const char *str = &value[1];
76 0 : while (str[0] != 0) {
77 0 : str += switchCallback(output, str[0], &str[1]);
78 : }
79 : }
80 : }
81 : } else {
82 25 : if (quoted > 0) {
83 0 : size_t len = strlen(value);
84 0 : if (len > 0 && value[len - 1] == quoted) {
85 0 : -- len;
86 : }
87 0 : argCallback(output, StringView(value, len));
88 : } else {
89 25 : if (i == argc) {
90 : // first arg
91 : #ifdef MODULE_COMMON_FILESYSTEM
92 : argCallback(output, filesystem::native::nativeToPosix<Interface>(value));
93 : #else
94 25 : argCallback(output, value);
95 : #endif
96 : } else {
97 0 : argCallback(output, value);
98 : }
99 : }
100 : }
101 25 : i --;
102 : }
103 :
104 25 : return true;
105 : }
106 :
107 : template <typename Interface, typename Output = ValueTemplate<Interface>>
108 : bool parseCommandLineOptions(Output &output, int argc, const char16_t * wargv[],
109 : const Callback<void(Output &, StringView)> &argCallback,
110 : const Callback<int (Output &, char c, const char *str)> &switchCallback,
111 : const Callback<int (Output &, const StringView &str, int argc, const char * argv[])> &stringCallback) {
112 : typename Interface::template VectorType<typename Interface::StringType> vec; vec.reserve(argc);
113 : typename Interface::template VectorType<const char *> argv; argv.reserve(argc);
114 : for (int i = 0; i < argc; ++ i) {
115 : vec.push_back(string::toUtf8<Interface>(wargv[i]));
116 : argv.push_back(vec.back().c_str());
117 : }
118 :
119 : return parseCommandLineOptions<Interface, Output>(output, argc, argv.data(), argCallback, switchCallback, stringCallback);
120 : }
121 :
122 : template <typename Interface, typename Output = ValueTemplate<Interface>>
123 25 : auto parseCommandLineOptions(int argc, const char * argv[],
124 : const Callback<int (Output &ret, char c, const char *str)> &switchCallback,
125 : const Callback<int (Output &ret, const StringView &str, int argc, const char * argv[])> &stringCallback)
126 : -> Pair<Output, typename Interface::template VectorType<typename Interface::StringType>> {
127 25 : Pair<Output, typename Interface::template VectorType<typename Interface::StringType>> ret;
128 25 : parseCommandLineOptions<Interface, Output>(ret.first, argc, argv,
129 50 : [&] (Output &, StringView str) {
130 25 : ret.second.emplace_back(str.str<Interface>());
131 : },
132 : switchCallback, stringCallback);
133 25 : return ret;
134 0 : }
135 :
136 : template <typename Interface, typename Output = ValueTemplate<Interface>>
137 : auto parseCommandLineOptions(int argc, const char16_t * wargv[],
138 : const Callback<int (Output &ret, char c, const char *str)> &switchCallback,
139 : const Callback<int (Output &ret, const StringView &str, int argc, const char * argv[])> &stringCallback)
140 : -> Pair<Output, typename Interface::template VectorType<typename Interface::StringType>> {
141 : typename Interface::template VectorType<typename Interface::StringType> vec; vec.reserve(argc);
142 : typename Interface::template VectorType<const char *> argv; argv.reserve(argc);
143 : for (int i = 0; i < argc; ++ i) {
144 : vec.push_back(string::toUtf8<Interface>(wargv[i]));
145 : argv.push_back(vec.back().c_str());
146 : }
147 :
148 : return parseCommandLineOptions<Interface, Output>(argc, argv.data(), switchCallback, stringCallback);
149 : }
150 :
151 : constexpr StringView MIME_URLENCODED("application/x-www-form-urlencoded");
152 : constexpr StringView MIME_SERENITY("application/x-serenity-urlencoded");
153 : constexpr StringView MIME_JSON("application/json");
154 : constexpr StringView MIME_CBOR("application/cbor");
155 :
156 : // decode x-www-urlencoded into data
157 : template <typename Interface>
158 : auto readUrlencoded(StringView, size_t maxVarSize = maxOf<size_t>()) -> data::ValueTemplate<Interface>;
159 :
160 : }
161 :
162 : #endif // STAPPLER_DATA_SPDATA_H_
|