proxygen
DynamicParser-inl.h
Go to the documentation of this file.
1 /*
2  * Copyright 2016-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /*
17  * Copyright (c) 2015, Facebook, Inc.
18  * All rights reserved.
19  *
20  * This source code is licensed under the BSD-style license found in the
21  * LICENSE file in the root directory of this source tree. An additional grant
22  * of patent rights can be found in the PATENTS file in the same directory.
23  *
24  */
25 #pragma once
26 
27 #include <boost/function_types/is_member_pointer.hpp>
28 #include <boost/function_types/parameter_types.hpp>
29 #include <boost/mpl/equal.hpp>
30 #include <boost/mpl/pop_front.hpp>
31 #include <boost/mpl/transform.hpp>
32 #include <boost/mpl/vector.hpp>
33 
34 #include <folly/Conv.h>
35 
36 namespace folly {
37 
38 // Auto-conversion of key/value based on callback signature, documented in
39 // DynamicParser.h.
40 namespace detail {
42  public:
43  enum class Kind { Function, MemberFunction };
44  template <typename Fn>
45  constexpr static Kind getKind() {
46  return test<Fn>(nullptr);
47  }
48 
49  private:
50  template <typename Fn>
51  using IsMemFn =
52  typename boost::function_types::template is_member_pointer<decltype(
53  &Fn::operator())>;
54  template <typename Fn>
55  constexpr static typename std::enable_if<IsMemFn<Fn>::value, Kind>::type test(
56  IsMemFn<Fn>*) {
58  }
59  template <typename>
60  constexpr static Kind test(...) {
62  }
63 };
64 
65 template <IdentifyCallable::Kind, typename Fn>
67 template <typename Fn>
69  using type = typename boost::mpl::template pop_front<
70  typename boost::function_types::template parameter_types<decltype(
71  &Fn::operator())>::type>::type;
72 };
73 template <typename Fn>
75  using type = typename boost::function_types::template parameter_types<Fn>;
76 };
77 
78 template <typename Fn>
79 using ArgumentTypes =
81 
82 // At present, works for lambdas or plain old functions, but can be
83 // extended. The comparison deliberately strips cv-qualifieers and
84 // reference, leaving that choice up to the caller.
85 template <typename Fn, typename... Args>
87  : boost::mpl::template equal<
88  typename boost::mpl::template transform<
89  typename boost::mpl::template transform<
90  ArgumentTypes<Fn>,
91  typename std::template remove_reference<boost::mpl::_1>>::
92  type,
93  typename std::template remove_cv<boost::mpl::_1>>::type,
94  boost::mpl::vector<Args...>>::type {};
95 template <typename... Args>
96 using EnableForArgTypes =
97  typename std::enable_if<HasArgumentTypes<Args...>::value, void>::type;
98 
99 // No arguments
100 template <typename Fn>
103  f();
104 }
105 
106 // 1 argument -- pass only the value
107 //
108 // folly::dynamic (no conversion)
109 template <typename Fn>
112  fn(v);
113 }
114 // int64_t
115 template <typename Fn>
118  fn(v.asInt());
119 }
120 // bool
121 template <typename Fn>
124  fn(v.asBool());
125 }
126 // double
127 template <typename Fn>
130  fn(v.asDouble());
131 }
132 // std::string
133 template <typename Fn>
136  fn(v.asString());
137 }
138 
139 //
140 // 2 arguments -- pass both the key and the value.
141 //
142 
143 // Pass the key as folly::dynamic, without conversion
144 //
145 // folly::dynamic, folly::dynamic (no conversion of value, either)
146 template <typename Fn>
149  fn(k, v);
150 }
151 // folly::dynamic, int64_t
152 template <typename Fn>
155  fn(k, v.asInt());
156 }
157 // folly::dynamic, bool
158 template <typename Fn>
161  fn(k, v.asBool());
162 }
163 // folly::dynamic, double
164 template <typename Fn>
167  fn(k, v.asDouble());
168 }
169 // folly::dynamic, std::string
170 template <typename Fn>
173  fn(k, v.asString());
174 }
175 
176 // Convert the key to std::string.
177 //
178 // std::string, folly::dynamic (no conversion of value)
179 template <typename Fn>
182  fn(k.asString(), v);
183 }
184 // std::string, int64_t
185 template <typename Fn>
188  fn(k.asString(), v.asInt());
189 }
190 // std::string, bool
191 template <typename Fn>
194  fn(k.asString(), v.asBool());
195 }
196 // std::string, double
197 template <typename Fn>
200  fn(k.asString(), v.asDouble());
201 }
202 // std::string, std::string
203 template <typename Fn>
206  fn(k.asString(), v.asString());
207 }
208 
209 // Convert the key to int64_t (good for arrays).
210 //
211 // int64_t, folly::dynamic (no conversion of value)
212 template <typename Fn>
215  fn(k.asInt(), v);
216 }
217 // int64_t, int64_t
218 template <typename Fn>
221  fn(k.asInt(), v.asInt());
222 }
223 // int64_t, bool
224 template <typename Fn>
227  fn(k.asInt(), v.asBool());
228 }
229 // int64_t, double
230 template <typename Fn>
233  fn(k.asInt(), v.asDouble());
234 }
235 // int64_t, std::string
236 template <typename Fn>
239  fn(k.asInt(), v.asString());
240 }
241 } // namespace detail
242 
243 template <typename Fn>
244 void DynamicParser::optional(const folly::dynamic& key, Fn fn) {
245  wrapError(&key, [&]() {
246  if (auto vp = value().get_ptr(key)) {
247  parse(key, *vp, fn);
248  }
249  });
250 }
251 
252 //
253 // Implementation of DynamicParser template & inline methods.
254 //
255 
256 template <typename Fn>
257 void DynamicParser::required(const folly::dynamic& key, Fn fn) {
258  wrapError(&key, [&]() {
259  auto vp = value().get_ptr(key);
260  if (!vp) {
261  throw std::runtime_error(folly::to<std::string>(
262  "Couldn't find key ",
264  " in dynamic object"));
265  }
266  parse(key, *vp, fn);
267  });
268 }
269 
270 template <typename Fn>
272  wrapError(nullptr, [&]() {
273  for (const auto& kv : value().items()) { // .items() can throw
274  parse(kv.first, kv.second, fn);
275  }
276  });
277 }
278 
279 template <typename Fn>
281  wrapError(nullptr, [&]() {
282  size_t i = 0;
283  for (const auto& v : value()) { // Iteration can throw
284  parse(i, v, fn); // i => dynamic cannot throw
285  ++i;
286  }
287  });
288 }
289 
290 template <typename Fn>
291 void DynamicParser::wrapError(const folly::dynamic* lookup_k, Fn fn) {
292  try {
293  fn();
294  } catch (DynamicParserLogicError&) {
295  // When the parser is misused, we throw all the way up to the user,
296  // instead of reporting it as if the input is invalid.
297  throw;
298  } catch (DynamicParserParseError&) {
299  // We are just bubbling up a parse error for OnError::THROW.
300  throw;
301  } catch (const std::exception& ex) {
302  reportError(lookup_k, ex);
303  }
304 }
305 
306 template <typename Fn>
308  const folly::dynamic& k,
309  const folly::dynamic& v,
310  Fn fn) {
311  auto guard = stack_.push(k, v); // User code can nest parser calls.
312  wrapError(nullptr, [&]() { detail::invokeForKeyValue(fn, k, v); });
313 }
314 
316  if (!key_) {
317  throw DynamicParserLogicError("Only call key() inside parsing callbacks.");
318  }
319  return *key_;
320 }
321 
323  if (!value_) {
325  "Parsing nullptr, or parsing after releaseErrors()");
326  }
327  return *value_;
328 }
329 
330 } // namespace folly
size_t parse(const char *buf, size_t len)
Definition: test.c:1591
const Map::mapped_type * get_ptr(const Map &map, const Key &key)
Definition: MapUtil.h:169
EnableForArgTypes< Fn > invokeForKeyValue(Fn f, const folly::dynamic &, const folly::dynamic &)
auto f
auto v
typename boost::function_types::template is_member_pointer< decltype(&Fn::operator())> IsMemFn
static constexpr Kind test(...)
typename boost::mpl::template pop_front< typename boost::function_types::template parameter_types< decltype(&Fn::operator())>::type >::type type
void required(const folly::dynamic &key, Fn)
PskType type
double asDouble() const
Definition: dynamic-inl.h:521
const folly::dynamic & key() const
bool asBool() const
Definition: dynamic-inl.h:527
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
void wrapError(const folly::dynamic *lookup_key, Fn)
void optional(const folly::dynamic &key, Fn)
typename std::enable_if< HasArgumentTypes< Args... >::value, void >::type EnableForArgTypes
std::string asString() const
Definition: dynamic-inl.h:518
std::string toPseudoJson(const folly::dynamic &d)
typename ArgumentTypesByKind< IdentifyCallable::getKind< Fn >(), Fn >::type ArgumentTypes
GuardImpl guard(ErrorHandler &&handler)
Definition: Base.h:840
int64_t asInt() const
Definition: dynamic-inl.h:524
std::unique_ptr< AltStackBuffer > stack_
static const char *const value
Definition: Conv.cpp:50
static constexpr Kind getKind()
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
typename boost::function_types::template parameter_types< Fn > type
static constexpr std::enable_if< IsMemFn< Fn >::value, Kind >::type test(IsMemFn< Fn > *)
const folly::dynamic & value() const
KeyT k
void parse(const folly::dynamic &key, const folly::dynamic &value, Fn fn)