ifw-daq  3.0.0-pre2
IFW Data Acquisition modules
internalParseUtils.hpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup daq_libjson
4  * @copyright
5  * (c) Copyright ESO 2022
6  * All Rights Reserved
7  * ESO (eso.org) is an Intergovernmental Organisation, and therefore special legal conditions apply.
8  */
9 #ifndef DAQ_INTERNAL_PARSE_UTILS_HPP
10 #define DAQ_INTERNAL_PARSE_UTILS_HPP
11 #include <string>
12 
13 #include <fmt/format.h>
14 #include <nlohmann/json.hpp>
15 
16 #include <daq/fits/json.hpp>
17 
18 using Json = nlohmann::json;
19 using JsonPointer = nlohmann::json_pointer<Json>;
20 
21 namespace daq {
22 
23 template <class E, class... Args>
24 E MakeParseException(JsonPointer const& ptr, Args&&... args) {
25  return E((fmt::format("({}) {}", ptr.to_string(), fmt::format(std::forward<Args>(args)...)))
26  .c_str());
27 }
28 
29 template <class E, char const*>
30 E MakeParseException(JsonPointer const& ptr, char const* str) {
31  return E(fmt::format("({}) {}", ptr.to_string(), str).c_str());
32 }
33 
34 template <class E>
36  return E(fmt::format("({}) {}", ptr.to_string(), "mandatory value missing").c_str());
37 }
38 
39 template <class E>
41  char const* expected_type,
42  char const* actual_type) {
43  return E(fmt::format("({}) {}",
44  ptr.to_string(),
45  fmt::format("must be a {}, but is {}", expected_type, actual_type))
46  .c_str());
47 }
48 
49 template <class E>
51  char const* known_variants,
52  char const* actual_variant) {
53  return E(
54  fmt::format("({}) {}",
55  ptr.to_string(),
56  fmt::format("must be one of {}, but is '{}'", known_variants, actual_variant))
57  .c_str());
58 }
59 
60 template <class E>
61 std::pair<Json const&, JsonPointer>
62 GetMember(Json const& json, char const* name, JsonPointer const& breadcrumb) {
63  auto bc = breadcrumb / name;
64  if (!json.contains(name)) {
65  throw MakeValueMissingException<E>(breadcrumb);
66  }
67  return {json[name], bc};
68 }
69 
70 template <class E, class BinaryFunction>
71 std::pair<Json const&, JsonPointer> GetMember(Json const& json,
72  char const* name,
73  JsonPointer const& breadcrumb,
74  BinaryFunction const& f) {
75  auto res = GetMember<E>(json, name, breadcrumb);
76  f(res.first, res.second);
77  return res;
78 }
79 
80 template <class E, class T>
81 struct JsonObject {
82  static T
83  Get(Json const& json, char const* name, JsonPointer const& breadcrumb, bool allow_empty = true);
84 };
85 
86 template <class E>
87 struct JsonObject<E, std::string> {
88  static std::string Get(Json const& json,
89  char const* name,
90  JsonPointer const& breadcrumb,
91  bool allow_empty = true) {
92  if (!json.contains(name)) {
93  throw MakeValueMissingException<E>(breadcrumb / name);
94  }
95  auto const& value_json = json[name];
96  if (!value_json.is_string()) {
97  throw MakeWrongTypeException<E>(breadcrumb / name, "string", value_json.type_name());
98  }
99  auto value = value_json.get<std::string>();
100  if (value.empty() && !allow_empty) {
101  throw MakeParseException<E>(breadcrumb / name, "empty string is invalid");
102  }
103  return value;
104  }
105 };
106 
107 template <class E>
108 struct JsonObject<E, double> {
109  static double Get(Json const& json,
110  char const* name,
111  JsonPointer const& breadcrumb) {
112  if (!json.contains(name)) {
113  throw MakeValueMissingException<E>(breadcrumb / name);
114  }
115  auto const& value_json = json[name];
116  if (!value_json.is_number()) {
117  throw MakeWrongTypeException<E>(
118  breadcrumb / name, "int or float", value_json.type_name());
119  }
120  auto value = value_json.get<double>();
121  return value;
122  }
123 };
124 
125 template <class E>
126 void AssertIsObject(Json const& json, JsonPointer const& breadcrumb) {
127  if (!json.is_object()) {
128  throw MakeWrongTypeException<E>(breadcrumb, "object", json.type_name());
129  }
130 }
131 
132 template <class E>
133 void AssertIsArray(Json const& json, JsonPointer const& breadcrumb) {
134  if (!json.is_array()) {
135  throw MakeWrongTypeException<E>(breadcrumb, "array", json.type_name());
136  }
137 }
138 
139 template <class E>
140 std::vector<std::string> ParseArrayOfString(Json const& json, JsonPointer const& breadcrumb) {
141  AssertIsArray<E>(json, breadcrumb);
142  std::vector<std::string> result;
143  auto index = 0u;
144  for (auto const& value_json : json) {
145  if (!value_json.is_string()) {
146  throw MakeWrongTypeException<E>(breadcrumb / index, "string", value_json.type_name());
147  }
148  auto value = value_json.get<std::string>();
149  if (value.empty()) {
150  throw MakeParseException<E>(breadcrumb / index, "empty string is invalid");
151  }
152  result.emplace_back(std::move(value));
153  index++;
154  }
155  return result;
156 }
157 } // namespace daq
158 #endif // DAQ_INTERNAL_PARSE_UTILS_HPP
Contains data structure for FITS keywords.
nlohmann::json_pointer< Json > JsonPointer
Definition: json.cpp:19
nlohmann::json Json
Definition: json.cpp:18
E MakeValueMissingException(JsonPointer const &ptr)
std::pair< Json const &, JsonPointer > GetMember(Json const &json, char const *name, JsonPointer const &breadcrumb)
std::vector< std::string > ParseArrayOfString(Json const &json, JsonPointer const &breadcrumb)
void AssertIsObject(Json const &json, JsonPointer const &breadcrumb)
E MakeUnknownVariantException(JsonPointer const &ptr, char const *known_variants, char const *actual_variant)
E MakeWrongTypeException(JsonPointer const &ptr, char const *expected_type, char const *actual_type)
E MakeParseException(JsonPointer const &ptr, Args &&... args)
void AssertIsArray(Json const &json, JsonPointer const &breadcrumb)
static double Get(Json const &json, char const *name, JsonPointer const &breadcrumb)
static std::string Get(Json const &json, char const *name, JsonPointer const &breadcrumb, bool allow_empty=true)
static T Get(Json const &json, char const *name, JsonPointer const &breadcrumb, bool allow_empty=true)