diff options
author | David Robillard <d@drobilla.net> | 2012-08-14 04:22:07 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2012-08-14 04:22:07 +0000 |
commit | 2a429ca76b97cca197f105b665271360b74f6917 (patch) | |
tree | d25d206910bd4a84050918693816240c26d7d0ae /raul/Symbol.hpp | |
parent | 8bf87dc2367caf9d82dbda0382363cda400971dc (diff) | |
download | raul-2a429ca76b97cca197f105b665271360b74f6917.tar.gz raul-2a429ca76b97cca197f105b665271360b74f6917.tar.bz2 raul-2a429ca76b97cca197f105b665271360b74f6917.zip |
Remove glib dependency.
Make Symbol, URI, and Path simpler derivatives of std::string.
100% test coverage by line for Symbol, URI, Path, AtomicInt, and AtomicPtr.
Add Raul::Exception.
git-svn-id: http://svn.drobilla.net/lad/trunk/raul@4686 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'raul/Symbol.hpp')
-rw-r--r-- | raul/Symbol.hpp | 112 |
1 files changed, 63 insertions, 49 deletions
diff --git a/raul/Symbol.hpp b/raul/Symbol.hpp index dcf1f04..3f14cc2 100644 --- a/raul/Symbol.hpp +++ b/raul/Symbol.hpp @@ -17,45 +17,38 @@ #ifndef RAUL_SYMBOL_HPP #define RAUL_SYMBOL_HPP -#include <cctype> -#include <cstring> -#include <exception> -#include <iostream> #include <string> -#include <glib.h> +#include "raul/Exception.hpp" namespace Raul { -/** A restricted string (C identifier, which is a component of a Path). +/** 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 most programming languages (including C). + * 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 + * @ingroup raul */ -class Symbol { +class Symbol : public std::basic_string<char> { public: - class BadSymbol : public std::exception { + /** Attempt to construct an invalid Symbol. */ + class BadSymbol : public Exception { public: - explicit BadSymbol(const std::string& symbol) : _symbol(symbol) {} - ~BadSymbol() throw() {} - const char* what() const throw() { return _symbol.c_str(); } - private: - const std::string _symbol; + explicit BadSymbol(const std::string& symbol) : Exception(symbol) {} }; - /** Construct a Symbol from an std::string. + /** Construct a Symbol from a C++ string. * - * It is a fatal error to construct a Symbol from an invalid string, - * use is_valid first to check. + * This will throw an exception if @p symbol is invalid. To avoid this, + * use is_valid() first to check. */ - explicit Symbol(const std::basic_string<char>& symbol) throw(BadSymbol) - : _str(g_intern_string(symbol.c_str())) + explicit Symbol(const std::basic_string<char>& symbol) + : std::basic_string<char>(symbol) { if (!is_valid(symbol)) { throw BadSymbol(symbol); @@ -64,50 +57,71 @@ public: /** Construct a Symbol from a C string. * - * It is a fatal error to construct a Symbol from an invalid string, - * use is_valid first to check. + * This will throw an exception if @p symbol is invalid. To avoid this, + * use is_valid() first to check. */ - explicit Symbol(const char* csymbol) throw(BadSymbol) - : _str(g_intern_string(csymbol)) + explicit Symbol(const char* symbol) + : std::basic_string<char>(symbol) { - if (!is_valid(csymbol)) { - throw BadSymbol(csymbol); + if (!is_valid(symbol)) { + throw BadSymbol(symbol); } } - Symbol& operator=(const Symbol& other) { - _str = other._str; - return *this; - } - - inline const char* c_str() const { return _str; } + /** Copy a Symbol. + * + * Note this is faster than constructing a Symbol from another Symbol's + * string since validation is unnecessary. + */ + Symbol(const Symbol& symbol) + : std::basic_string<char>(symbol) + {} - inline bool operator==(const Symbol& other) const { - return _str == other._str; + /** Return true iff @p 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'); } - inline bool operator!=(const Symbol& other) const { - return _str != other._str; + /** Return true iff @p c is a valid Symbol character. */ + static inline bool is_valid_char(char c) { + return is_valid_start_char(c) || (c >= '0' && c <= '9'); } - inline bool operator<(const Symbol& other) const { - return strcmp(_str, other._str) < 0; - } + /** Return true iff @p 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 + } - static bool is_valid(const std::basic_string<char>& symbol); + for (size_t i = 0; i < str.length(); ++i) { + if (!is_valid_char(str[i])) { + return false; // All characters must be _, a-z, A-Z, 0-9 + } + } - static Raul::Symbol symbolify(const std::basic_string<char>& str); + return true; + } + + /** Convert a string to a valid symbol. + * + * This will make a best effort at turning @a 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("_"); + } -private: - const char* _str; + std::basic_string<char> out(in); + for (size_t i = 0; i < in.length(); ++i) { + if (!is_valid_char(out[i])) { + out[i] = '_'; + } + } + return Symbol(out); + } }; } // namespace Raul -static inline std::ostream& -operator<<(std::ostream& os, const Raul::Symbol& symbol) -{ - return (os << symbol.c_str()); -} - #endif // RAUL_SYMBOL_HPP |