From e8381d5e5e19166001561244f7a9db5742f1090a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 15 Nov 2019 09:49:38 +0200 Subject: Add path_name_view struct --- libbutl/path-io.mxx | 6 +-- libbutl/path.ixx | 90 +++++++++++++++++++++++++++++++++------------ libbutl/path.mxx | 103 +++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 150 insertions(+), 49 deletions(-) diff --git a/libbutl/path-io.mxx b/libbutl/path-io.mxx index a44d26b..54f9569 100644 --- a/libbutl/path-io.mxx +++ b/libbutl/path-io.mxx @@ -46,10 +46,10 @@ LIBBUTL_MODEXPORT namespace butl template inline std::basic_ostream& - operator<< (std::basic_ostream& os, const basic_path_name

& pn) + operator<< (std::basic_ostream& os, const basic_path_name_view

& v) { - assert (!pn.empty ()); + assert (!v.null ()); - return pn.name ? (os << *pn.name) : (os << *pn.path); + return v.name != nullptr && *v.name ? (os << **v.name) : (os << *v.path); } } diff --git a/libbutl/path.ixx b/libbutl/path.ixx index 165f06a..77bc9f7 100644 --- a/libbutl/path.ixx +++ b/libbutl/path.ixx @@ -702,6 +702,72 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. d.tsep_ = 1; // Canonical separator is always first. } + template + inline std::basic_ostream& + to_stream (std::basic_ostream& os, + const basic_path& p, + bool representation) + { + os << p.string (); + + if (representation) + { + C sep (p.separator ()); + +#ifndef _WIN32 + if (sep != 0 && !p.root ()) + os << sep; +#else + if (sep != 0) + os << sep; +#endif + } + + return os; + } + + // basic_path_name + // + template + inline basic_path_name

:: + basic_path_name (basic_path_name&& p) + : basic_path_name (p.path, std::move (p.name)) + { + } + + template + inline basic_path_name

:: + basic_path_name (const basic_path_name& p) + : basic_path_name (p.path, p.name) + { + } + + template + inline basic_path_name

& basic_path_name

:: + operator= (basic_path_name&& p) + { + if (this != &p) + { + this->path = p.path; + name = std::move (p.name); + } + + return *this; + } + + template + inline basic_path_name

& basic_path_name

:: + operator= (const basic_path_name& p) + { + if (this != &p) + { + this->path = p.path; + name = p.name; + } + + return *this; + } + // basic_path_name_value // template @@ -743,28 +809,4 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. return *this; } - - template - inline std::basic_ostream& - to_stream (std::basic_ostream& os, - const basic_path& p, - bool representation) - { - os << p.string (); - - if (representation) - { - C sep (p.separator ()); - -#ifndef _WIN32 - if (sep != 0 && !p.root ()) - os << sep; -#else - if (sep != 0) - os << sep; -#endif - } - - return os; - } } diff --git a/libbutl/path.mxx b/libbutl/path.mxx index 130419c..cc72549 100644 --- a/libbutl/path.mxx +++ b/libbutl/path.mxx @@ -552,6 +552,15 @@ LIBBUTL_MODEXPORT namespace butl using path_name_value = basic_path_name_value; using dir_name_value = basic_path_name_value; + // A "full" view version of the above that also shallow-references the + // optional name. The "partial" view derives from this "full" view. + // + template + struct basic_path_name_view; + + using path_name_view = basic_path_name_view; + using dir_name_view = basic_path_name_view; + // Low-level path data storage. It is also used by the implementation to // pass around initialized/valid paths. // @@ -1343,44 +1352,92 @@ LIBBUTL_MODEXPORT namespace butl return r; } + template + std::basic_ostream& + to_stream (std::basic_ostream&, + const basic_path&, + bool representation); + + // For operator<< (ostream) see the path-io header. + + // path_name + // + template - struct basic_path_name + struct basic_path_name_view { using path_type = P; using string_type = typename path_type::string_type; - const path_type* path; + const path_type* path; + const optional* name; + + explicit + basic_path_name_view (const basic_path_name

& v) + : path (v.path), name (&v.name) {} + + basic_path_name_view (const path_type* p, const optional* n) + : path (p), name (n) {} + + basic_path_name_view () // Create empty/NULL path name. + : path (nullptr), name (nullptr) {} + + + bool + null () const + { + return path == nullptr && (name == nullptr || !*name); + } + + bool + empty () const + { + // assert (!null ()); + return name != nullptr && *name ? (*name)->empty () : path->empty (); + } + }; + + template + struct basic_path_name: basic_path_name_view

+ { + using base = basic_path_name_view

; + + using path_type = typename base::path_type; + using string_type = typename base::string_type; + optional name; + // Note that a NULL name is converted to absent. + // + explicit + basic_path_name (const basic_path_name_view

& v) + : base (v.path, &name), + name (v.name != nullptr ? *v.name : nullopt) {} + explicit basic_path_name (const path_type& p, optional n = nullopt) - : path (&p), name (std::move (n)) {} + : base (&p, &name), name (std::move (n)) {} explicit basic_path_name (path_type&&, optional = nullopt) = delete; explicit basic_path_name (string_type n) - : path (nullptr), name (std::move (n)) {} + : base (nullptr, &name), name (std::move (n)) {} explicit basic_path_name (const path_type* p, optional n = nullopt) - : path (p), name (std::move (n)) {} + : base (p, &name), name (std::move (n)) {} - basic_path_name (): path (nullptr) {} // Create empty/NULL path name. + basic_path_name (): // Create empty/NULL path name. + base (nullptr, &name) {} - bool - empty () const {return path == nullptr && !name;} + basic_path_name (basic_path_name&&); + basic_path_name (const basic_path_name&); + basic_path_name& operator= (basic_path_name&&); + basic_path_name& operator= (const basic_path_name&); }; - template - std::basic_ostream& - to_stream (std::basic_ostream& os, - const basic_path& p, - bool representation); - - // For operator<< (ostream) see the path-io header. - template struct basic_path_name_value: basic_path_name

{ @@ -1391,16 +1448,18 @@ LIBBUTL_MODEXPORT namespace butl path_type path; + // Note that a NULL path/name is converted to empty/absent. + // + explicit + basic_path_name_value (const basic_path_name_view

& v) + : base (&path, v.name != nullptr ? *v.name : nullopt), + path (v.path != nullptr ? *v.path : path_type ()) {} + explicit basic_path_name_value (path_type p, optional n = nullopt) : base (&path, std::move (n)), path (std::move (p)) {} - // Note that a NULL path is converted to empty path. - // - explicit - basic_path_name_value (const basic_path_name

& v) - : base (&path, v.name), - path (v.path != nullptr ? *v.path : path_type ()) {} + basic_path_name_value (): base (&path) {} // Create empty/NULL path name. basic_path_name_value (basic_path_name_value&&); basic_path_name_value (const basic_path_name_value&); -- cgit v1.1