aboutsummaryrefslogtreecommitdiff
path: root/libbutl
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-07-25 20:11:47 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-07-25 20:22:33 +0300
commit84f6ebab62a9f2553ae454d67861b0b142470d0b (patch)
tree63d41dc772ebcaf6f1821de3b155cadd90d309dc /libbutl
parent35e9273090109e5fb87fe65e3f1631ff6fc5fb3a (diff)
Move bpkg::package_name class to butl::project_name
Diffstat (limited to 'libbutl')
-rw-r--r--libbutl/project-name.cxx115
-rw-r--r--libbutl/project-name.mxx223
2 files changed, 338 insertions, 0 deletions
diff --git a/libbutl/project-name.cxx b/libbutl/project-name.cxx
new file mode 100644
index 0000000..5f94ea0
--- /dev/null
+++ b/libbutl/project-name.cxx
@@ -0,0 +1,115 @@
+// file : libbutl/project-name.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef __cpp_modules
+#include <libbutl/project-name.mxx>
+#endif
+
+#ifndef __cpp_lib_modules
+#include <string>
+#include <vector>
+#include <utility> // move()
+#include <iterator> // back_inserter
+#include <algorithm> // find(), transform()
+#include <stdexcept> // invalid_argument
+#endif
+
+// Other includes.
+
+#ifdef __cpp_modules
+module butl.project_name;
+
+// Only imports additional to interface.
+#ifdef __clang__
+#ifdef __cpp_lib_modules
+import std.core;
+import std.io;
+#endif
+import butl.utility;
+#endif
+
+import butl.path; // path::traits
+import butl.utility; // alpha(), alnum()
+#else
+#include <libbutl/path.mxx>
+#include <libbutl/utility.mxx>
+#endif
+
+using namespace std;
+
+namespace butl
+{
+ // project_name
+ //
+ static const vector<string> illegal_prj_names ({
+ "build",
+ "con", "prn", "aux", "nul",
+ "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9",
+ "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9"});
+
+ static const string legal_prj_chars ("_+-.");
+
+ project_name::
+ project_name (std::string&& nm)
+ {
+ if (nm.size () < 2)
+ throw invalid_argument ("length is less than two characters");
+
+ if (find (illegal_prj_names.begin (), illegal_prj_names.end (), nm) !=
+ illegal_prj_names.end ())
+ throw invalid_argument ("illegal name");
+
+ if (!alpha (nm.front ()))
+ throw invalid_argument ("illegal first character (must be alphabetic)");
+
+ // Here we rely on the fact that the name length >= 2.
+ //
+ for (auto i (nm.cbegin () + 1), e (nm.cend () - 1); i != e; ++i)
+ {
+ char c (*i);
+
+ if (!(alnum(c) || legal_prj_chars.find (c) != string::npos))
+ throw invalid_argument ("illegal character");
+ }
+
+ if (!alnum (nm.back ()) && nm.back () != '+')
+ throw invalid_argument (
+ "illegal last character (must be alphabetic, digit, or plus)");
+
+ value_ = move (nm);
+ }
+
+ string project_name::
+ base () const
+ {
+ using std::string;
+
+ size_t p (path::traits::find_extension (value_));
+ return string (value_, 0, p);
+ }
+
+ string project_name::
+ extension () const
+ {
+ using std::string;
+
+ size_t p (path::traits::find_extension (value_));
+ return p != string::npos ? string (value_, p + 1) : string ();
+ }
+
+ string project_name::
+ variable () const
+ {
+ using std::string;
+
+ auto sanitize = [] (char c)
+ {
+ return (c == '-' || c == '+' || c == '.') ? '_' : c;
+ };
+
+ string r;
+ transform (value_.begin (), value_.end (), back_inserter (r), sanitize);
+ return r;
+ }
+}
diff --git a/libbutl/project-name.mxx b/libbutl/project-name.mxx
new file mode 100644
index 0000000..bb92340
--- /dev/null
+++ b/libbutl/project-name.mxx
@@ -0,0 +1,223 @@
+// file : libbutl/project-name.mxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef __cpp_modules
+#pragma once
+#endif
+
+// C includes.
+
+#ifndef __cpp_lib_modules
+#include <string>
+#include <utility> // move()
+#include <ostream>
+#endif
+
+// Other includes.
+
+#ifdef __cpp_modules
+export module butl.project_name;
+#ifdef __cpp_lib_modules
+import std.core;
+import std.io;
+#endif
+import butl.utility; // casecmp()
+#else
+#include <libbutl/utility.mxx>
+#endif
+
+#include <libbutl/export.hxx>
+
+LIBBUTL_MODEXPORT namespace butl
+{
+ class LIBBUTL_SYMEXPORT project_name
+ {
+ public:
+ // Create project name from string verifying that it complied with the
+ // specification and throwing std::invalid_argument if that's not the
+ // case. Note that in this case the passed value is guaranteed to be
+ // unchanged.
+ //
+ explicit
+ project_name (const std::string& s): project_name (std::string (s)) {}
+
+ explicit
+ project_name (std::string&&);
+
+ // Create a special empty project name.
+ //
+ project_name () = default;
+
+ // Create an arbitrary string that can be used in contexts that expect
+ // a project name. For example, a project name pattern for use in ODB query
+ // expressions.
+ //
+ enum raw_string_type {raw_string};
+ project_name (std::string s, raw_string_type): value_ (std::move (s)) {}
+
+ bool
+ empty () const noexcept {return value_.empty ();}
+
+ const std::string&
+ string () const& noexcept {return value_;}
+
+ // Moves the underlying project name string out of the project name object.
+ // The object becomes empty. Usage: std::move (name).string ().
+ //
+ std::string
+ string () && {std::string r; r.swap (this->value_); return r;}
+
+ // Project name base and extension (without the dot). If there is no
+ // extension, then the base name is the same as the full name and the
+ // returned extension is empty.
+ //
+ std::string
+ base () const;
+
+ std::string
+ extension () const;
+
+ // Project name sanitized to a canonical variable name. Specifically,
+ // '.', '-', and '+' are replaced with '_'.
+ //
+ std::string
+ variable () const;
+
+ // Compare ignoring case. Note that a string is not checked to be a valid
+ // project name.
+ //
+ int compare (const project_name& n) const {return compare (n.value_);}
+ int compare (const std::string& n) const {return compare (n.c_str ());}
+ int compare (const char* n) const {return butl::casecmp (value_, n);}
+
+ private:
+ std::string value_;
+ };
+
+ inline bool
+ operator< (const project_name& x, const project_name& y)
+ {
+ return x.compare (y) < 0;
+ }
+
+ inline bool
+ operator> (const project_name& x, const project_name& y)
+ {
+ return x.compare (y) > 0;
+ }
+
+ inline bool
+ operator== (const project_name& x, const project_name& y)
+ {
+ return x.compare (y) == 0;
+ }
+
+ inline bool
+ operator<= (const project_name& x, const project_name& y)
+ {
+ return x.compare (y) <= 0;
+ }
+
+ inline bool
+ operator>= (const project_name& x, const project_name& y)
+ {
+ return x.compare (y) >= 0;
+ }
+
+ inline bool
+ operator!= (const project_name& x, const project_name& y)
+ {
+ return x.compare (y) != 0;
+ }
+
+ template <typename T>
+ inline auto
+ operator< (const project_name& x, const T& y)
+ {
+ return x.compare (y) < 0;
+ }
+
+ template <typename T>
+ inline auto
+ operator> (const project_name& x, const T& y)
+ {
+ return x.compare (y) > 0;
+ }
+
+ template <typename T>
+ inline auto
+ operator== (const project_name& x, const T& y)
+ {
+ return x.compare (y) == 0;
+ }
+
+ template <typename T>
+ inline auto
+ operator<= (const project_name& x, const T& y)
+ {
+ return x.compare (y) <= 0;
+ }
+
+ template <typename T>
+ inline auto
+ operator>= (const project_name& x, const T& y)
+ {
+ return x.compare (y) >= 0;
+ }
+
+ template <typename T>
+ inline auto
+ operator!= (const project_name& x, const T& y)
+ {
+ return x.compare (y) != 0;
+ }
+
+ template <typename T>
+ inline auto
+ operator< (const T& x, const project_name& y)
+ {
+ return y > x;
+ }
+
+ template <typename T>
+ inline auto
+ operator> (const T& x, const project_name& y)
+ {
+ return y < x;
+ }
+
+ template <typename T>
+ inline auto
+ operator== (const T& x, const project_name& y)
+ {
+ return y == x;
+ }
+
+ template <typename T>
+ inline auto
+ operator<= (const T& x, const project_name& y)
+ {
+ return y >= x;
+ }
+
+ template <typename T>
+ inline auto
+ operator>= (const T& x, const project_name& y)
+ {
+ return y <= x;
+ }
+
+ template <typename T>
+ inline auto
+ operator!= (const T& x, const project_name& y)
+ {
+ return y != x;
+ }
+
+ inline std::ostream&
+ operator<< (std::ostream& os, const project_name& v)
+ {
+ return os << v.string ();
+ }
+}