@@ -58,24 +58,74 @@ enum class PortDirection
58
58
59
59
using StringView = std::string_view;
60
60
61
+ bool StartWith (StringView str, StringView prefix);
62
+
61
63
// vector of key/value pairs
62
64
using KeyValueVector = std::vector<std::pair<std::string, std::string>>;
63
65
66
+ /* * Usage: given a function/method like this:
67
+ *
68
+ * Expected<double> getAnswer();
69
+ *
70
+ * User code can check result and error message like this:
71
+ *
72
+ * auto res = getAnswer();
73
+ * if( res )
74
+ * {
75
+ * std::cout << "answer was: " << res.value() << std::endl;
76
+ * }
77
+ * else{
78
+ * std::cerr << "failed to get the answer: " << res.error() << std::endl;
79
+ * }
80
+ *
81
+ * */
82
+ template <typename T>
83
+ using Expected = nonstd::expected<T, std::string>;
84
+
64
85
struct AnyTypeAllowed
65
86
{
66
87
};
67
88
89
+ /* *
90
+ * @brief convertFromJSON will parse a json string and use JsonExporter
91
+ * to convert its content to a given type. It will work only if
92
+ * the type was previously registered. May throw if it fails.
93
+ *
94
+ * @param json_text a valid JSON string
95
+ * @param type you must specify the typeid()
96
+ * @return the object, wrapped in Any.
97
+ */
98
+ [[nodiscard]] Any convertFromJSON (StringView json_text, std::type_index type);
99
+
100
+ // / Same as the non template version, but with automatic casting
101
+ template <typename T>
102
+ [[nodiscard]] inline T convertFromJSON (StringView str)
103
+ {
104
+ return convertFromJSON (str, typeid (T)).cast <T>();
105
+ }
106
+
68
107
/* *
69
108
* convertFromString is used to convert a string into a custom type.
70
109
*
71
110
* This function is invoked under the hood by TreeNode::getInput(), but only when the
72
111
* input port contains a string.
73
112
*
74
- * If you have a custom type, you need to implement the corresponding template specialization.
113
+ * If you have a custom type, you need to implement the corresponding
114
+ * template specialization.
115
+ *
116
+ * If the string starts with the prefix "json:", it will
117
+ * fall back to convertFromJSON()
75
118
*/
76
119
template <typename T>
77
- [[nodiscard]] inline T convertFromString (StringView /* str*/ )
120
+ [[nodiscard]] inline T convertFromString (StringView str)
78
121
{
122
+ // if string starts with "json:{", try to parse it as json
123
+ if (StartWith (str, " json:" ))
124
+ {
125
+ str.remove_prefix (5 );
126
+ return convertFromJSON<T>(str);
127
+ }
128
+
79
129
auto type_name = BT::demangle (typeid (T));
80
130
81
131
std::cerr << " You (maybe indirectly) called BT::convertFromString() for type ["
@@ -171,6 +221,14 @@ constexpr bool IsConvertibleToString()
171
221
std::is_convertible_v<T, std::string_view>;
172
222
}
173
223
224
+ Expected<std::string> toJsonString (const Any& value);
225
+
226
+ /* *
227
+ * @brief toStr is the reverse operation of convertFromString.
228
+ *
229
+ * If T is a custom type and there is no template specialization,
230
+ * it will try to fall back to toJsonString()
231
+ */
174
232
template <typename T>
175
233
[[nodiscard]] std::string toStr (const T& value)
176
234
{
@@ -180,6 +238,11 @@ template <typename T>
180
238
}
181
239
else if constexpr (!std::is_arithmetic_v<T>)
182
240
{
241
+ if (auto str = toJsonString (Any (value)))
242
+ {
243
+ return *str;
244
+ }
245
+
183
246
throw LogicError (StrCat (" Function BT::toStr<T>() not specialized for type [" ,
184
247
BT::demangle (typeid (T)), " ]" ));
185
248
}
@@ -225,25 +288,6 @@ using enable_if = typename std::enable_if<Predicate::value>::type*;
225
288
template <typename Predicate>
226
289
using enable_if_not = typename std::enable_if<!Predicate::value>::type*;
227
290
228
- /* * Usage: given a function/method like this:
229
- *
230
- * Expected<double> getAnswer();
231
- *
232
- * User code can check result and error message like this:
233
- *
234
- * auto res = getAnswer();
235
- * if( res )
236
- * {
237
- * std::cout << "answer was: " << res.value() << std::endl;
238
- * }
239
- * else{
240
- * std::cerr << "failed to get the answer: " << res.error() << std::endl;
241
- * }
242
- *
243
- * */
244
- template <typename T>
245
- using Expected = nonstd::expected<T, std::string>;
246
-
247
291
#ifdef USE_BTCPP3_OLD_NAMES
248
292
// note: we also use the name Optional instead of expected because it is more intuitive
249
293
// for users that are not up to date with "modern" C++
0 commit comments