// file : build2/name -*- C++ -*- // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file // Note: include instead of this file directly. // #ifndef BUILD2_NAME #define BUILD2_NAME // We cannot include since it includes . // #include // move() namespace build2 { using std::move; // A name is what we operate on by default. Depending on the context, it can // be interpreted as a target or prerequisite name. A name without a type // and directory can be used to represent any text. A name with directory // and empty value represents a directory. A name may also be qualified with // a project. If the project name is empty, then it means the name is in a // project other than our own (e.g., it is installed). // // If pair is not '\0', then this name and the next in the list form a // pair. Can be used as a bool flag. // // The original flag indicates whether this is the original name (e.g., came // from the buildfile) or if it is the result of reversing a typed value. // Original names have stricter representation requirements since we don't // know what they actually mean (e.g., is s/foo/bar/ really a directory or // a sed script). // struct name { const string* proj = nullptr; // Points to project_name_pool. dir_path dir; string type; string value; char pair = '\0'; bool original = true; name () = default; name (string v, bool o): value (move (v)), original (o) {} name (dir_path d, bool o): dir (move (d)), original (o) {} name (string t, string v): type (move (t)), value (move (v)) {} name (dir_path d, string t, string v) : dir (move (d)), type (move (t)), value (move (v)) {} // The first argument should be from project_name_pool. // name (const string* p, dir_path d, string t, string v) : proj (p), dir (move (d)), type (move (t)), value (move (v)) {} bool qualified () const {return proj != nullptr;} bool unqualified () const {return proj == nullptr;} bool typed () const {return !type.empty ();} bool untyped () const {return type.empty ();} bool empty () const {return dir.empty () && value.empty ();} // Note that strictly speaking the following tests should be orthogonal // to qualification. However, the vast majority of cases where we expect // a simple or directory name, we also expect it to be unqualified. // // Note also that empty name is simple but not a directory. // bool simple (bool ignore_qual = false) const { return (ignore_qual || unqualified ()) && untyped () && dir.empty (); } bool directory (bool ignore_qual = false) const { return (ignore_qual || unqualified ()) && untyped () && !dir.empty () && value.empty (); } int compare (const name&) const; }; inline bool operator== (const name& x, const name& y) {return x.compare (y) == 0;} inline bool operator!= (const name& x, const name& y) {return !(x == y);} inline bool operator< (const name& x, const name& y) {return x.compare (y) < 0;} // Serialize the name to the stream. If requested, the name components // containing special characters are quoted. The special characters are: // // {}[]$() \t\n#\"'% // // If the pair argument is not '\0', then it is added to the above special // characters set. If the quote character is present in the component then // it is double quoted rather than single quoted. In this case the following // characters are escaped: // // \$(" // ostream& to_stream (ostream&, const name&, bool quote, char pair); inline ostream& operator<< (ostream& os, const name& n) { return to_stream (os, n, false, '\0');} // Vector of names. // using names = vector; using names_view = vector_view; // The same semantics as to_stream(name). // ostream& to_stream (ostream&, const names_view&, bool quote, char pair); inline ostream& operator<< (ostream& os, const names_view& ns) { return to_stream (os, ns, false, '\0');} inline ostream& operator<< (ostream& os, const names& ns) {return os << names_view (ns);} } #include #endif // BUILD2_NAME