aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-04-09 07:48:02 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-04-09 07:48:02 +0200
commit7a7b8ba432977282a90567c77822a72645d2a5c8 (patch)
tree6abac0b3fad817c4149bc34d80b9c0e6e4a31168
parent6906097a822517af4dc711825132d5f026329c62 (diff)
Add abs_dir_path type, auto-complete if initialized from names
-rw-r--r--build2/parser.cxx21
-rw-r--r--build2/types18
-rw-r--r--build2/variable17
-rw-r--r--build2/variable.cxx28
-rw-r--r--build2/variable.ixx41
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>::