summaryrefslogtreecommitdiffstats
path: root/include/raul/Symbol.hpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-11-12 01:11:11 +0100
committerDavid Robillard <d@drobilla.net>2020-11-12 01:47:40 +0100
commitbf9190ef628c1aa04791af1bd7cd4905e9c24658 (patch)
tree56114c93a8ec689cd15497059958dad03a1ee2ce /include/raul/Symbol.hpp
parent496e70e420811c7d744a8bcc44a2ac1b51b676b5 (diff)
downloadraul-bf9190ef628c1aa04791af1bd7cd4905e9c24658.tar.gz
raul-bf9190ef628c1aa04791af1bd7cd4905e9c24658.tar.bz2
raul-bf9190ef628c1aa04791af1bd7cd4905e9c24658.zip
Move includes to a conventional include directory
Diffstat (limited to 'include/raul/Symbol.hpp')
-rw-r--r--include/raul/Symbol.hpp130
1 files changed, 130 insertions, 0 deletions
diff --git a/include/raul/Symbol.hpp b/include/raul/Symbol.hpp
new file mode 100644
index 0000000..70062be
--- /dev/null
+++ b/include/raul/Symbol.hpp
@@ -0,0 +1,130 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2014 David Robillard <http://drobilla.net>
+
+ Raul is free software: you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or any later version.
+
+ Raul is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Raul. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef RAUL_SYMBOL_HPP
+#define RAUL_SYMBOL_HPP
+
+#include "raul/Exception.hpp"
+
+#include <string>
+
+namespace Raul {
+
+/** A restricted string which is a valid C identifier and Path component.
+ *
+ * A Symbol is a very restricted string suitable for use as an identifier.
+ * It is a valid LV2 symbol, URI fragment, filename, OSC path fragment,
+ * and identifier for virtually all programming languages.
+ *
+ * Valid characters are _, a-z, A-Z, 0-9, except the first character which
+ * must not be 0-9.
+ *
+ * @ingroup raul
+ */
+class Symbol : public std::basic_string<char> {
+public:
+ /** Attempt to construct an invalid Symbol. */
+ class BadSymbol : public Exception {
+ public:
+ explicit BadSymbol(const std::string& symbol) : Exception(symbol) {}
+ };
+
+ /** Construct a Symbol from a C++ string.
+ *
+ * This will throw an exception if `symbol` is invalid. To avoid this,
+ * use is_valid() first to check.
+ */
+ explicit Symbol(const std::basic_string<char>& symbol)
+ : std::basic_string<char>(symbol)
+ {
+ if (!is_valid(symbol)) {
+ throw BadSymbol(symbol);
+ }
+ }
+
+ /** Construct a Symbol from a C string.
+ *
+ * This will throw an exception if `symbol` is invalid. To avoid this,
+ * use is_valid() first to check.
+ */
+ explicit Symbol(const char* symbol)
+ : std::basic_string<char>(symbol)
+ {
+ if (!is_valid(symbol)) {
+ throw BadSymbol(symbol);
+ }
+ }
+
+ /** Copy a Symbol.
+ *
+ * Note this is faster than constructing a Symbol from another Symbol's
+ * string since validation is unnecessary.
+ */
+ Symbol(const Symbol& symbol) = default;
+
+ /** Return true iff `c` is a valid Symbol start character. */
+ static inline bool is_valid_start_char(char c) {
+ return (c == '_') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ }
+
+ /** Return true iff `c` is a valid Symbol character. */
+ static inline bool is_valid_char(char c) {
+ return is_valid_start_char(c) || (c >= '0' && c <= '9');
+ }
+
+ /** Return true iff `str` is a valid Symbol. */
+ static inline bool is_valid(const std::basic_string<char>& str) {
+ if (str.empty() || (str[0] >= '0' && str[0] <= '9')) {
+ return false; // Must start with a letter or underscore
+ }
+
+ for (auto c : str) {
+ if (!is_valid_char(c)) {
+ return false; // All characters must be _, a-z, A-Z, 0-9
+ }
+ }
+
+ return true;
+ }
+
+ /** Convert a string to a valid symbol.
+ *
+ * This will make a best effort at turning `str` into a complete, valid
+ * Symbol, and will always return one.
+ */
+ static inline Symbol symbolify(const std::basic_string<char>& in) {
+ if (in.empty()) {
+ return Symbol("_");
+ }
+
+ std::basic_string<char> out(in);
+ for (size_t i = 0; i < in.length(); ++i) {
+ if (!is_valid_char(out[i])) {
+ out[i] = '_';
+ }
+ }
+
+ if (is_valid_start_char(out[0])) {
+ return Symbol(out);
+ } else {
+ return Symbol(std::string("_") + out);
+ }
+ }
+};
+
+} // namespace Raul
+
+#endif // RAUL_SYMBOL_HPP