aboutsummaryrefslogtreecommitdiff
path: root/build2/variable.ixx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-01-05 11:55:15 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-01-05 11:55:15 +0200
commit9fb791e9fad6c63fc1dac49f4d05ae63b8a3db9b (patch)
treed60322d4382ca5f97b676c5abe2e39524f35eab4 /build2/variable.ixx
parentf159b1dac68c8714f7ba71ca168e3b695891aad9 (diff)
Rename build directory/namespace to build2
Diffstat (limited to 'build2/variable.ixx')
-rw-r--r--build2/variable.ixx398
1 files changed, 398 insertions, 0 deletions
diff --git a/build2/variable.ixx b/build2/variable.ixx
new file mode 100644
index 0000000..2933deb
--- /dev/null
+++ b/build2/variable.ixx
@@ -0,0 +1,398 @@
+// file : build2/variable.ixx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+namespace build2
+{
+ // value
+ //
+ template <typename T>
+ inline void
+ assign (value& v, const variable& var)
+ {
+ auto t (&value_traits<T>::value_type);
+
+ if (v.type != t)
+ assign (v, t, var);
+ }
+
+ template <typename T>
+ inline typename value_traits<T>::type
+ as (value& v)
+ {
+ return value_traits<T>::as (v);
+ }
+
+ template <typename T>
+ inline typename value_traits<T>::const_type
+ as (const value& v)
+ {
+ return value_traits<T>::as (v);
+ }
+
+ template <typename T>
+ inline bool
+ assign (name& n)
+ {
+ return value_traits<T>::assign (n);
+ }
+
+ template <typename T>
+ inline typename value_traits<T>::type
+ as (name& n)
+ {
+ return value_traits<T>::as (n);
+ }
+
+ template <typename T>
+ inline typename value_traits<T>::const_type
+ as (const name& n)
+ {
+ return value_traits<T>::as (n);
+ }
+
+ template <typename T>
+ inline value& value::
+ operator= (T v)
+ {
+ value_traits<T>::assign (*this, std::move (v));
+ return *this;
+ }
+
+ template <typename T>
+ inline value& value::
+ operator+= (T v)
+ {
+ value_traits<T>::append (*this, std::move (v));
+ return *this;
+ }
+
+ inline void value::
+ assign (names v, const variable& var)
+ {
+ data_ = std::move (v);
+ state_ = (type != nullptr && type->assign != nullptr
+ ? type->assign (data_, var)
+ : !data_.empty ())
+ ? state_type::filled
+ : state_type::empty;
+ }
+
+ // bool value
+ //
+ inline bool_value<name> value_traits<bool>::
+ as (value& v)
+ {
+ assert (v.type == bool_type);
+ return bool_value<name> (v.data_.front ());
+ }
+
+ inline bool_value<const name> value_traits<bool>::
+ as (const value& v)
+ {
+ assert (v.type == bool_type);
+ return bool_value<const name> (v.data_.front ());
+ }
+
+ inline void value_traits<bool>::
+ assign (value& v, bool x)
+ {
+ if (v.null ())
+ {
+ if (v.type == nullptr)
+ v.type = bool_type;
+ v.data_.emplace_back (name ());
+ v.state_ = value::state_type::empty;
+ }
+
+ as (v) = x;
+ v.state_ = value::state_type::filled;
+ }
+
+ inline void value_traits<bool>::
+ append (value& v, bool x)
+ {
+ if (v.null ())
+ assign (v, x);
+ else
+ as (v) += x; // Cannot be empty.
+ }
+
+ // string value
+ //
+ inline std::string& value_traits<std::string>::
+ as (value& v)
+ {
+ assert (v.type == string_type);
+ return v.data_.front ().value;
+ }
+
+ inline const std::string& value_traits<std::string>::
+ as (const value& v)
+ {
+ assert (v.type == string_type);
+ return v.data_.front ().value;
+ }
+
+ inline void value_traits<std::string>::
+ assign (value& v, std::string x)
+ {
+ if (v.null ())
+ {
+ if (v.type == nullptr)
+ v.type = string_type;
+ v.data_.emplace_back (name ());
+ v.state_ = value::state_type::empty;
+ }
+
+ v.state_ = (as (v) = std::move (x)).empty ()
+ ? value::state_type::empty
+ : value::state_type::filled;
+ }
+
+ inline void value_traits<std::string>::
+ append (value& v, std::string x)
+ {
+ if (v.null ())
+ assign (v, std::move (x));
+ else
+ v.state_ = (as (v) += std::move (x)).empty ()
+ ? value::state_type::empty
+ : value::state_type::filled;
+ }
+
+ // dir_path value
+ //
+ inline dir_path& value_traits<dir_path>::
+ as (value& v)
+ {
+ assert (v.type == dir_path_type);
+ return v.data_.front ().dir;
+ }
+
+ inline const dir_path& value_traits<dir_path>::
+ as (const value& v)
+ {
+ assert (v.type == dir_path_type);
+ return v.data_.front ().dir;
+ }
+
+ inline void value_traits<dir_path>::
+ assign (value& v, dir_path x)
+ {
+ if (v.null ())
+ {
+ if (v.type == nullptr)
+ v.type = dir_path_type;
+ v.data_.emplace_back (name ());
+ v.state_ = value::state_type::empty;
+ }
+
+ v.state_ = (as (v) = std::move (x)).empty ()
+ ? value::state_type::empty
+ : value::state_type::filled;
+ }
+
+ inline void value_traits<dir_path>::
+ append (value& v, dir_path x)
+ {
+ if (v.null ())
+ assign (v, std::move (x));
+ else
+ v.state_ = (as (v) /= std::move (x)).empty ()
+ ? value::state_type::empty
+ : value::state_type::filled;
+ }
+
+ // name value
+ //
+ inline name& value_traits<name>::
+ as (value& v)
+ {
+ assert (v.type == name_type);
+ return v.data_.front ();
+ }
+
+ inline const name& value_traits<name>::
+ as (const value& v)
+ {
+ assert (v.type == name_type);
+ return v.data_.front ();
+ }
+
+ inline void value_traits<name>::
+ assign (value& v, name x)
+ {
+ if (v.null ())
+ {
+ if (v.type == nullptr)
+ v.type = name_type;
+ v.data_.emplace_back (name ());
+ v.state_ = value::state_type::empty;
+ }
+
+ v.state_ = (as (v) = std::move (x)).empty ()
+ ? value::state_type::empty
+ : value::state_type::filled;
+ }
+
+ // vector<T> value
+ //
+ template <typename T, typename D>
+ inline vector_value<T, D>& vector_value<T, D>::
+ assign (std::vector<T> v)
+ {
+ d->clear ();
+ d->insert (d->end (),
+ std::make_move_iterator (v.begin ()),
+ std::make_move_iterator (v.end ()));
+ return *this;
+ }
+
+ template <typename T, typename D>
+ template <typename D1>
+ inline vector_value<T, D>& vector_value<T, D>::
+ assign (const vector_value<T, D1>& v)
+ {
+ d->clear ();
+ d->insert (d->end (), v.begin (), v.end ());
+ return *this;
+ }
+
+ template <typename T, typename D>
+ template <typename D1>
+ inline vector_value<T, D>& vector_value<T, D>::
+ append (const vector_value<T, D1>& v)
+ {
+ d->insert (d->end (), v.begin (), v.end ());
+ return *this;
+ }
+
+ template <typename T>
+ inline vector_value<T, names> value_traits<std::vector<T>>::
+ as (value& v)
+ {
+ assert (v.type == &value_traits<std::vector<T>>::value_type);
+ return vector_value<T, names> (v.data_);
+ }
+
+ template <typename T>
+ inline vector_value<T, const names> value_traits<std::vector<T>>::
+ as (const value& v)
+ {
+ assert (v.type == &value_traits<std::vector<T>>::value_type);
+ return vector_value<T, const names> (v.data_);
+ }
+
+ template <typename T>
+ template <typename V>
+ inline void value_traits<std::vector<T>>::
+ assign (value& v, V x)
+ {
+ if (v.null ())
+ {
+ if (v.type == nullptr)
+ v.type = &value_traits<std::vector<T>>::value_type;
+ v.state_ = value::state_type::empty;
+ }
+
+ v.state_ = (as (v).assign (std::move (x))).empty ()
+ ? value::state_type::empty
+ : value::state_type::filled;
+ }
+
+ template <typename T>
+ template <typename V>
+ inline void value_traits<std::vector<T>>::
+ append (value& v, V x)
+ {
+ if (v.null ())
+ assign (v, std::move (x));
+ else
+ v.state_ = (as (v).append (std::move (x))).empty ()
+ ? value::state_type::empty
+ : value::state_type::filled;
+ }
+
+ // map<K, V> value
+ //
+ template <typename K, typename V>
+ inline map_value<K, V, names> value_traits<std::map<K, V>>::
+ as (value& v)
+ {
+ assert ((v.type == &value_traits<std::map<K, V>>::value_type));
+ return map_value<K, V, names> (v.data_);
+ }
+
+ template <typename K, typename V>
+ inline map_value<K, V, const names> value_traits<std::map<K, V>>::
+ as (const value& v)
+ {
+ assert ((v.type == &value_traits<std::map<K, V>>::value_type));
+ return map_value<K, V, const names> (v.data_);
+ }
+
+ template <typename K, typename V>
+ template <typename M>
+ inline void value_traits<std::map<K, V>>::
+ assign (value& v, M x)
+ {
+ if (v.null ())
+ {
+ if (v.type == nullptr)
+ v.type = &value_traits<std::map<K, V>>::value_type;
+ v.state_ = value::state_type::empty;
+ }
+
+ v.state_ = (as (v).assign (std::move (x))).empty ()
+ ? value::state_type::empty
+ : value::state_type::filled;
+ }
+
+ template <typename K, typename V>
+ template <typename M>
+ inline void value_traits<std::map<K, V>>::
+ append (value& v, M x)
+ {
+ if (v.null ())
+ assign (v, std::move (x));
+ else
+ v.state_ = (as (v).append (std::move (x))).empty ()
+ ? value::state_type::empty
+ : value::state_type::filled;
+ }
+
+ // variable_map::iterator_adapter
+ //
+ template <typename I>
+ inline typename I::reference variable_map::iterator_adapter<I>::
+ operator* () const
+ {
+ auto& r (I::operator* ());
+ const variable& var (r.first);
+ auto& val (r.second);
+
+ // First access after being assigned a type?
+ //
+ if (var.type != nullptr && val.type != var.type)
+ build2::assign (const_cast<value&> (val), var.type, var);
+
+ return r;
+ }
+
+ template <typename I>
+ inline typename I::pointer variable_map::iterator_adapter<I>::
+ operator-> () const
+ {
+ auto p (I::operator-> ());
+ const variable& var (p->first);
+ auto& val (p->second);
+
+ // First access after being assigned a type?
+ //
+ if (var.type != nullptr && val.type != var.type)
+ build2::assign (const_cast<value&> (val), var.type, var);
+
+ return p;
+ }
+}