aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-08-12 13:54:21 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-08-12 13:54:21 +0200
commitd72e5f95e70976f9b8bc29a7ace3c354e815ca49 (patch)
tree4ac1f39941be5c6cd57287e15a049ec4d62eb126
parent446c6548a1b61a18a27e24320a53a66a3ef7008a (diff)
Add int64 and int64s variable types
-rw-r--r--doc/manual.cli3
-rw-r--r--libbuild2/parser.cxx2
-rw-r--r--libbuild2/types.hxx2
-rw-r--r--libbuild2/variable.cxx49
-rw-r--r--libbuild2/variable.hxx36
-rw-r--r--libbuild2/variable.ixx28
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>::