diff options
-rw-r--r-- | build2/parser.cxx | 21 | ||||
-rw-r--r-- | build2/types | 18 | ||||
-rw-r--r-- | build2/variable | 17 | ||||
-rw-r--r-- | build2/variable.cxx | 28 | ||||
-rw-r--r-- | build2/variable.ixx | 41 |
5 files changed, 114 insertions, 11 deletions
diff --git a/build2/parser.cxx b/build2/parser.cxx index 3d21cac..6926ce3 100644 --- a/build2/parser.cxx +++ b/build2/parser.cxx @@ -1335,16 +1335,17 @@ namespace build2 map_type (const string& n) { return - n == "bool" ? &value_traits<bool>::value_type : - n == "uint64" ? &value_traits<uint64_t>::value_type : - n == "string" ? &value_traits<string>::value_type : - n == "path" ? &value_traits<path>::value_type : - n == "dir_path" ? &value_traits<dir_path>::value_type : - n == "name" ? &value_traits<name>::value_type : - n == "strings" ? &value_traits<strings>::value_type : - n == "paths" ? &value_traits<paths>::value_type : - n == "dir_paths" ? &value_traits<dir_paths>::value_type : - n == "names" ? &value_traits<names>::value_type : + n == "bool" ? &value_traits<bool>::value_type : + n == "uint64" ? &value_traits<uint64_t>::value_type : + n == "string" ? &value_traits<string>::value_type : + n == "path" ? &value_traits<path>::value_type : + n == "dir_path" ? &value_traits<dir_path>::value_type : + n == "abs_dir_path" ? &value_traits<abs_dir_path>::value_type : + n == "name" ? &value_traits<name>::value_type : + n == "strings" ? &value_traits<strings>::value_type : + n == "paths" ? &value_traits<paths>::value_type : + n == "dir_paths" ? &value_traits<dir_paths>::value_type : + n == "names" ? &value_traits<names>::value_type : nullptr; } diff --git a/build2/types b/build2/types index 166f47a..d3930ba 100644 --- a/build2/types +++ b/build2/types @@ -8,7 +8,7 @@ #include <vector> #include <string> #include <memory> // unique_ptr, shared_ptr -#include <utility> // pair +#include <utility> // pair, move() #include <cstddef> // size_t, nullptr_t #include <cstdint> // uint{8,16,32,64}_t #include <istream> @@ -77,6 +77,22 @@ namespace build2 using butl::basic_path; using butl::invalid_path; + // Absolute directory path. Note that for now we don't do any checking that + // the path is in fact absolute. + // + // The idea is to have a different type that we automatically complete when + // a (variable) value of this type gets initialized from untyped names. See + // value_type<abs_dir_path> for details. + // + struct abs_dir_path: dir_path + { + using dir_path::dir_path; + + explicit + abs_dir_path (dir_path d): dir_path (std::move (d).string (), false) {} + abs_dir_path () = default; + }; + using paths = std::vector<path>; using dir_paths = std::vector<dir_path>; diff --git a/build2/variable b/build2/variable index a3c1ea6..5a33037 100644 --- a/build2/variable +++ b/build2/variable @@ -479,6 +479,23 @@ namespace build2 static const build2::value_type value_type; }; + // abs_dir_path + // + template <> + struct value_traits<abs_dir_path> + { + static_assert (sizeof (abs_dir_path) <= value::size_, + "insufficient space"); + + static abs_dir_path convert (name&&, name*); + static bool assign (value&, abs_dir_path&&); + static bool append (value&, abs_dir_path&&); // operator/ + static name reverse (const abs_dir_path& x) {return name (x);} + static int compare (const abs_dir_path&, const abs_dir_path&); + + static const build2::value_type value_type; + }; + // name // template <> diff --git a/build2/variable.cxx b/build2/variable.cxx index da7446d..61f5975 100644 --- a/build2/variable.cxx +++ b/build2/variable.cxx @@ -526,6 +526,34 @@ namespace build2 &simple_compare<dir_path> }; + // abs_dir_path value + // + abs_dir_path value_traits<abs_dir_path>:: + convert (name&& n, name* r) + { + dir_path d (value_traits<dir_path>::convert (move (n), r)); + + if (d.relative ()) + d.complete (); + + return abs_dir_path (move (d)); + } + + const value_type value_traits<abs_dir_path>::value_type + { + "abs_dir_path", + sizeof (abs_dir_path), + &default_dtor<abs_dir_path>, + &default_copy_ctor<abs_dir_path>, + &default_copy_assign<abs_dir_path>, + &simple_assign<abs_dir_path, true>, // Allow empty paths. + &simple_append<abs_dir_path, true>, + nullptr, // No prepend. + &simple_reverse<abs_dir_path>, + nullptr, // No cast (cast data_ directly). + &simple_compare<abs_dir_path> + }; + // name value // name value_traits<name>:: diff --git a/build2/variable.ixx b/build2/variable.ixx index 821d224..e52a150 100644 --- a/build2/variable.ixx +++ b/build2/variable.ixx @@ -411,6 +411,47 @@ namespace build2 return l.compare (r); } + // abs_dir_path value + // + inline bool value_traits<abs_dir_path>:: + assign (value& v, abs_dir_path&& x) + { + abs_dir_path* p; + + if (v.null ()) + p = new (&v.data_) abs_dir_path (move (x)); + else + p = &(v.as<abs_dir_path> () = move (x)); + + return !p->empty (); + } + + inline bool value_traits<abs_dir_path>:: + append (value& v, abs_dir_path&& x) + { + abs_dir_path* p; + + if (v.null ()) + p = new (&v.data_) abs_dir_path (move (x)); + else + { + p = &v.as<abs_dir_path> (); + + if (p->empty ()) + p->swap (x); + else + *p /= x; + } + + return !p->empty (); + } + + inline int value_traits<abs_dir_path>:: + compare (const abs_dir_path& l, const abs_dir_path& r) + { + return l.compare (static_cast<const dir_path&> (r)); + } + // name value // inline bool value_traits<name>:: |