summaryrefslogtreecommitdiffstats
path: root/raul/Symbol.hpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-08-14 04:22:07 +0000
committerDavid Robillard <d@drobilla.net>2012-08-14 04:22:07 +0000
commit2a429ca76b97cca197f105b665271360b74f6917 (patch)
treed25d206910bd4a84050918693816240c26d7d0ae /raul/Symbol.hpp
parent8bf87dc2367caf9d82dbda0382363cda400971dc (diff)
downloadraul-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.hpp112
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