diff options
-rw-r--r-- | doc/manual.cli | 3 | ||||
-rw-r--r-- | libbuild2/parser.cxx | 2 | ||||
-rw-r--r-- | libbuild2/types.hxx | 2 | ||||
-rw-r--r-- | libbuild2/variable.cxx | 49 | ||||
-rw-r--r-- | libbuild2/variable.hxx | 36 | ||||
-rw-r--r-- | libbuild2/variable.ixx | 28 |
6 files changed, 118 insertions, 2 deletions
diff --git a/doc/manual.cli b/doc/manual.cli index 03dc180..d3ee659 100644 --- a/doc/manual.cli +++ b/doc/manual.cli @@ -5497,6 +5497,9 @@ The following variable/value types can currently be used in \c{buildfiles}: \ bool +int64 +int64s + uint64 uint64s diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index cda4c69..8ae13a8 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -3797,6 +3797,7 @@ namespace build2 return n == "bool" ? ptr (value_traits<bool>::value_type) : + n == "int64" ? ptr (value_traits<int64_t>::value_type) : n == "uint64" ? ptr (value_traits<uint64_t>::value_type) : n == "string" ? ptr (value_traits<string>::value_type) : n == "path" ? ptr (value_traits<path>::value_type) : @@ -3807,6 +3808,7 @@ namespace build2 n == "target_triplet" ? ptr (value_traits<target_triplet>::value_type) : n == "project_name" ? ptr (value_traits<project_name>::value_type) : + n == "int64s" ? ptr (value_traits<int64s>::value_type) : n == "uint64s" ? ptr (value_traits<uint64s>::value_type) : n == "strings" ? ptr (value_traits<strings>::value_type) : n == "paths" ? ptr (value_traits<paths>::value_type) : diff --git a/libbuild2/types.hxx b/libbuild2/types.hxx index 65e0918..dcf1a30 100644 --- a/libbuild2/types.hxx +++ b/libbuild2/types.hxx @@ -65,9 +65,11 @@ namespace build2 using std::uint8_t; using std::uint16_t; using std::uint32_t; + using std::int64_t; using std::uint64_t; using std::uintptr_t; + using int64s = std::vector<int64_t>; using uint64s = std::vector<uint64_t>; using std::size_t; diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx index 79d0018..a4c3ef3 100644 --- a/libbuild2/variable.cxx +++ b/libbuild2/variable.cxx @@ -480,6 +480,54 @@ namespace build2 nullptr // Never empty. }; + // int64_t value + // + int64_t value_traits<int64_t>:: + convert (const name& n, const name* r) + { + if (r == nullptr && n.simple ()) + { + try + { + // May throw invalid_argument or out_of_range. + // + size_t i; + int64_t r (stoll (n.value, &i)); + + if (i == n.value.size ()) + return r; + + // Fall through. + } + catch (const std::exception&) + { + // Fall through. + } + } + + throw_invalid_argument (n, r, "int64"); + } + + const char* const value_traits<int64_t>::type_name = "int64"; + + const value_type value_traits<int64_t>::value_type + { + type_name, + sizeof (int64_t), + nullptr, // No base. + nullptr, // No element. + nullptr, // No dtor (POD). + nullptr, // No copy_ctor (POD). + nullptr, // No copy_assign (POD). + &simple_assign<int64_t>, + &simple_append<int64_t>, + &simple_append<int64_t>, // Prepend same as append. + &simple_reverse<int64_t>, + nullptr, // No cast (cast data_ directly). + nullptr, // No compare (compare as POD). + nullptr // Never empty. + }; + // uint64_t value // uint64_t value_traits<uint64_t>:: @@ -1759,6 +1807,7 @@ namespace build2 template struct LIBBUILD2_DEFEXPORT value_traits<vector<name>>; template struct LIBBUILD2_DEFEXPORT value_traits<paths>; template struct LIBBUILD2_DEFEXPORT value_traits<dir_paths>; + template struct LIBBUILD2_DEFEXPORT value_traits<int64s>; template struct LIBBUILD2_DEFEXPORT value_traits<uint64s>; template struct LIBBUILD2_DEFEXPORT diff --git a/libbuild2/variable.hxx b/libbuild2/variable.hxx index 99eb3aa..6c78c95 100644 --- a/libbuild2/variable.hxx +++ b/libbuild2/variable.hxx @@ -710,6 +710,30 @@ namespace build2 static const build2::value_type value_type; }; + // int64_t + // + template <> + struct LIBBUILD2_SYMEXPORT value_traits<int64_t> + { + static_assert (sizeof (int64_t) <= value::size_, "insufficient space"); + + // Note: in some places we rely on the convert() function not changing + // the passed names thus we make them const. + // + static int64_t convert (const name&, const name*); + static void assign (value&, int64_t); + static void append (value&, int64_t); // ADD. + static name reverse (int64_t x) {return name (to_string (x));} + static int compare (int64_t, int64_t); + static bool empty (bool) {return false;} + + static const bool empty_value = false; + static const char* const type_name; + static const build2::value_type value_type; + }; + + // uint64_t + // template <> struct LIBBUILD2_SYMEXPORT value_traits<uint64_t> { @@ -730,13 +754,20 @@ namespace build2 static const build2::value_type value_type; }; - // Treat unsigned integral types as uint64. Note that bool is handled - // differently at an earlier stage. + // Treat signed/unsigned integral types as int64/uint64. Note that bool is + // handled differently at an earlier stage. // template <typename T> struct value_traits_specialization<T, typename std::enable_if< std::is_integral<T>::value && + std::is_signed<T>::value>::type>: + value_traits<int64_t> {}; + + template <typename T> + struct value_traits_specialization<T, + typename std::enable_if< + std::is_integral<T>::value && std::is_unsigned<T>::value>::type>: value_traits<uint64_t> {}; @@ -1055,6 +1086,7 @@ namespace build2 extern template struct LIBBUILD2_DECEXPORT value_traits<vector<name>>; extern template struct LIBBUILD2_DECEXPORT value_traits<paths>; extern template struct LIBBUILD2_DECEXPORT value_traits<dir_paths>; + extern template struct LIBBUILD2_DECEXPORT value_traits<int64s>; extern template struct LIBBUILD2_DECEXPORT value_traits<uint64s>; extern template struct LIBBUILD2_DECEXPORT diff --git a/libbuild2/variable.ixx b/libbuild2/variable.ixx index 84bf20c..a11ee12 100644 --- a/libbuild2/variable.ixx +++ b/libbuild2/variable.ixx @@ -368,6 +368,34 @@ namespace build2 return l < r ? -1 : (l > r ? 1 : 0); } + // int64_t value + // + inline void value_traits<int64_t>:: + assign (value& v, int64_t x) + { + if (v) + v.as<int64_t> () = x; + else + new (&v.data_) int64_t (x); + } + + inline void value_traits<int64_t>:: + append (value& v, int64_t x) + { + // ADD. + // + if (v) + v.as<int64_t> () += x; + else + new (&v.data_) int64_t (x); + } + + inline int value_traits<int64_t>:: + compare (int64_t l, int64_t r) + { + return l < r ? -1 : (l > r ? 1 : 0); + } + // uint64_t value // inline void value_traits<uint64_t>:: |