aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/variable.ixx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-02-20 15:40:02 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-02-20 16:08:14 +0200
commit0efae7db7b5870246f1e294a5fedaa69e9c90331 (patch)
treefd53e7b4b416a63c8e082dead3ef1d6496fa872a /libbuild2/variable.ixx
parent6ff1cf35f78a24d52603d84eac9349b3d4670c6c (diff)
Add json_map and json_set buildfile value types
These expose the std::map<json_value,json_value> and std::set<json_value> types to buildfiles. New functions: $size(<json-set>) $size(<json-map>) $keys(<json-map>) Note that the $keys() function returns the list of map key as a json array. For example: m = [json_map] 2@([json] a@1 b@2) 1@([json] 1 2) s = [json_set] ([json] x@1 y@2) ([json] a@1 b@2) print ($m[2][b]) # 2 print ($s[([json] y@2 x@1)]) # true
Diffstat (limited to 'libbuild2/variable.ixx')
-rw-r--r--libbuild2/variable.ixx42
1 files changed, 41 insertions, 1 deletions
diff --git a/libbuild2/variable.ixx b/libbuild2/variable.ixx
index a448cd8..ca84a33 100644
--- a/libbuild2/variable.ixx
+++ b/libbuild2/variable.ixx
@@ -362,13 +362,53 @@ namespace build2
// This one will be SFINAE'd out unless T is a container.
//
+ // If T is both (e.g., json_value), then make this version preferable.
+ //
template <typename T>
inline auto
- convert (names&& ns) -> decltype (value_traits<T>::convert (move (ns)))
+ convert_impl (names&& ns, int)
+ -> decltype (value_traits<T>::convert (move (ns)))
{
return value_traits<T>::convert (move (ns));
}
+ // This one will be SFINAE'd out unless T is a simple value.
+ //
+ // If T is both (e.g., json_value), then make this version less preferable.
+ //
+ template <typename T>
+ auto // NOTE: not inline!
+ convert_impl (names&& ns, ...) ->
+ decltype (value_traits<T>::convert (move (ns[0]), nullptr))
+ {
+ size_t n (ns.size ());
+
+ if (n == 0)
+ {
+ if (value_traits<T>::empty_value)
+ return T ();
+ }
+ else if (n == 1)
+ {
+ return convert<T> (move (ns[0]));
+ }
+ else if (n == 2 && ns[0].pair != '\0')
+ {
+ return convert<T> (move (ns[0]), move (ns[1]));
+ }
+
+ throw invalid_argument (
+ string ("invalid ") + value_traits<T>::type_name +
+ (n == 0 ? " value: empty" : " value: multiple names"));
+ }
+
+ template <typename T>
+ inline T
+ convert (names&& ns)
+ {
+ return convert_impl<T> (move (ns), 0);
+ }
+
// bool value
//
inline void value_traits<bool>::