Apache Mesos
parse.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_FLAGS_PARSE_HPP__
14 #define __STOUT_FLAGS_PARSE_HPP__
15 
16 #include <sstream> // For istringstream.
17 #include <string>
18 
19 #include <stout/bytes.hpp>
20 #include <stout/duration.hpp>
21 #include <stout/error.hpp>
22 #include <stout/ip.hpp>
23 #include <stout/json.hpp>
24 #include <stout/path.hpp>
25 #include <stout/strings.hpp>
26 #include <stout/try.hpp>
27 
28 #include <stout/flags/flag.hpp>
29 
30 #include <stout/os/read.hpp>
31 
32 namespace flags {
33 
34 template <typename T>
35 Try<T> parse(const std::string& value)
36 {
37  T t;
38  std::istringstream in(value);
39  in >> t;
40 
41  if (in && in.eof()) {
42  return t;
43  }
44 
45  return Error("Failed to convert into required type");
46 }
47 
48 
49 template <>
50 inline Try<std::string> parse(const std::string& value)
51 {
52  return value;
53 }
54 
55 
56 template <>
57 inline Try<bool> parse(const std::string& value)
58 {
59  if (value == "true" || value == "1") {
60  return true;
61  } else if (value == "false" || value == "0") {
62  return false;
63  }
64  return Error("Expecting a boolean (e.g., true or false)");
65 }
66 
67 
68 template <>
69 inline Try<Duration> parse(const std::string& value)
70 {
71  return Duration::parse(value);
72 }
73 
74 
75 template <>
76 inline Try<Bytes> parse(const std::string& value)
77 {
78  return Bytes::parse(value);
79 }
80 
81 
82 template <>
83 inline Try<net::IP> parse(const std::string& value)
84 {
85  return net::IP::parse(value);
86 }
87 
88 
89 template <>
90 inline Try<net::IPv4> parse(const std::string& value)
91 {
92  return net::IPv4::parse(value);
93 }
94 
95 
96 template <>
97 inline Try<net::IPv6> parse(const std::string& value)
98 {
99  return net::IPv6::parse(value);
100 }
101 
102 
103 template <>
104 inline Try<JSON::Object> parse(const std::string& value)
105 {
106 #ifndef __WINDOWS__
107  // A value that already starts with 'file://' will properly be
108  // loaded from the file and put into 'value' but if it starts with
109  // '/' we need to explicitly handle it for backwards compatibility
110  // reasons (because we used to handle it before we introduced the
111  // 'fetch' mechanism for flags that first fetches the data from URIs
112  // such as 'file://').
113  //
114  // NOTE: Because this code is deprecated, it is not supported on Windows.
115  if (strings::startsWith(value, "/")) {
116  LOG(WARNING) << "Specifying an absolute filename to read a command line "
117  "option out of without using 'file:// is deprecated and "
118  "will be removed in a future release. Simply adding "
119  "'file://' to the beginning of the path should eliminate "
120  "this warning.";
121 
122  Try<std::string> read = os::read(value);
123  if (read.isError()) {
124  return Error("Error reading file '" + value + "': " + read.error());
125  }
126  return JSON::parse<JSON::Object>(read.get());
127  }
128 #endif // __WINDOWS__
129  return JSON::parse<JSON::Object>(value);
130 }
131 
132 
133 template <>
134 inline Try<JSON::Array> parse(const std::string& value)
135 {
136 #ifndef __WINDOWS__
137  // A value that already starts with 'file://' will properly be
138  // loaded from the file and put into 'value' but if it starts with
139  // '/' we need to explicitly handle it for backwards compatibility
140  // reasons (because we used to handle it before we introduced the
141  // 'fetch' mechanism for flags that first fetches the data from URIs
142  // such as 'file://').
143  //
144  // NOTE: Because this code is deprecated, it is not supported on Windows.
145  if (strings::startsWith(value, "/")) {
146  LOG(WARNING) << "Specifying an absolute filename to read a command line "
147  "option out of without using 'file:// is deprecated and "
148  "will be removed in a future release. Simply adding "
149  "'file://' to the beginning of the path should eliminate "
150  "this warning.";
151 
152  Try<std::string> read = os::read(value);
153  if (read.isError()) {
154  return Error("Error reading file '" + value + "': " + read.error());
155  }
156  return JSON::parse<JSON::Array>(read.get());
157  }
158 #endif // __WINDOWS__
159  return JSON::parse<JSON::Array>(value);
160 }
161 
162 
163 template <>
164 inline Try<Path> parse(const std::string& value)
165 {
166  return Path(value);
167 }
168 
169 
170 template <>
171 inline Try<SecurePathOrValue> parse(const std::string& value)
172 {
173  SecurePathOrValue result;
174  result.value = value;
175 
176  if (strings::startsWith(value, "file://")) {
177  const std::string path = value.substr(7);
178 
180 
181  if (read.isError()) {
182  return Error("Error reading file '" + path + "': " + read.error());
183  }
184 
185  result.value = read.get();
186  result.path = Path(path);
187  }
188 
189  return result;
190 }
191 
192 
193 #ifdef __WINDOWS__
194 template <>
195 inline Try<int_fd> parse(const std::string& value)
196 {
197  // Looks like "WindowsFD::Type::HANDLE=0000000000000000".
198  std::vector<std::string> fd = strings::split(value, "=");
199  if (fd.size() != 2) {
200  return Error("Expected to split string into exactly two parts.");
201  }
202 
203  if (strings::endsWith(fd[0], "HANDLE")) {
204  Try<HANDLE> t = parse<HANDLE>(fd[1]);
205  if (t.isError()) {
206  return Error(t.error());
207  }
208  return int_fd(t.get());
209  } else if (strings::endsWith(fd[0], "SOCKET")) {
210  Try<SOCKET> t = parse<SOCKET>(fd[1]);
211  if (t.isError()) {
212  return Error(t.error());
213  }
214  return int_fd(t.get());
215  }
216 
217  return Error("`int_fd` was neither a `HANDLE` nor a `SOCKET`");
218 }
219 #endif // __WINDOWS__
220 
221 
222 // TODO(klueska): Generalize this parser to take any comma separated
223 // list and convert it to its appropriate type (i.e., not just for
224 // unsigned ints). Issues could arise when the generic type is a
225 // string that contains commas though, so generalizing this is not as
226 // straightforward as it looks at first glance.
227 template <>
228 inline Try<std::vector<unsigned int>> parse(const std::string& value)
229 {
230  std::vector<unsigned int> result;
231 
232  foreach (const std::string& token, strings::tokenize(value, ",")) {
233  Try<unsigned int> number = numify<unsigned int>(token);
234 
235  if (number.isError()) {
236  return Error("Failed to numify '" + token + "': " + number.error());
237  }
238 
239  result.push_back(number.get());
240  }
241 
242  return result;
243 }
244 
245 
246 // NOTE: Strings in the set cannot contain commas, since that
247 // is the delimiter and we provide no way to escape it.
248 //
249 // TODO(klueska): Generalize this parser to take any comma separated
250 // list and convert it to its appropriate type (i.e., not just for
251 // strings).
252 template <>
253 inline Try<std::set<std::string>> parse(const std::string& value)
254 {
255  std::set<std::string> result;
256 
257  foreach (const std::string& token, strings::tokenize(value, ",")) {
258  if (result.count(token) > 0) {
259  return Error("Duplicate token '" + token + "'");
260  }
261 
262  result.insert(token);
263  }
264 
265  return result;
266 }
267 
268 } // namespace flags {
269 
270 #endif // __STOUT_FLAGS_PARSE_HPP__
bool endsWith(const std::string &s, const std::string &suffix)
Definition: strings.hpp:402
Definition: path.hpp:29
Definition: errorbase.hpp:36
T & get()&
Definition: try.hpp:80
Definition: check.hpp:33
std::string value
Definition: flag.hpp:109
static Try< IPv6 > parse(const std::string &value)
Definition: ip.hpp:391
static Try< Bytes > parse(const std::string &s)
Definition: bytes.hpp:39
static Try< IP > parse(const std::string &value, int family=AF_UNSPEC)
Definition: ip.hpp:417
Option< Path > path
Definition: flag.hpp:108
std::vector< std::string > tokenize(const std::string &s, const std::string &delims, const Option< size_t > &maxTokens=None())
Definition: strings.hpp:139
Represents a POSIX or Windows file system path and offers common path manipulations.
Definition: path.hpp:212
Try< mesos::ACLs > parse(const std::string &value)
Returns the OCI v1 descriptor, image index, image manifest and image configuration from the given str...
Definition: parse.hpp:36
static Try error(const E &e)
Definition: try.hpp:43
static Try< Duration > parse(const std::string &s)
Definition: duration.hpp:363
Result< std::string > read(int_fd fd, size_t size)
Definition: read.hpp:55
bool isError() const
Definition: try.hpp:78
Result< Credentials > read(const Path &path)
Definition: credentials.hpp:35
Definition: flag.hpp:106
std::vector< std::string > split(const std::string &s, const std::string &delims, const Option< size_t > &maxTokens=None())
Definition: strings.hpp:184
int int_fd
Definition: int_fd.hpp:35
bool startsWith(const std::string &s, const std::string &prefix)
Definition: strings.hpp:381
static Try< IPv4 > parse(const std::string &value)
Definition: ip.hpp:347
Definition: parse.hpp:33