summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS5
-rw-r--r--raul.pc.in1
-rw-r--r--raul/Configuration.hpp10
-rw-r--r--raul/Exception.hpp34
-rw-r--r--raul/Path.hpp219
-rw-r--r--raul/Symbol.hpp112
-rw-r--r--raul/URI.hpp115
-rw-r--r--src/Path.cpp164
-rw-r--r--src/Symbol.cpp67
-rw-r--r--test/path_test.cpp64
-rw-r--r--test/symbol_test.cpp77
-rw-r--r--test/table_test.cpp5
-rw-r--r--test/uri_test.cpp61
-rw-r--r--wscript10
14 files changed, 446 insertions, 498 deletions
diff --git a/NEWS b/NEWS
index 6713d30..b3e5071 100644
--- a/NEWS
+++ b/NEWS
@@ -1,12 +1,13 @@
raul (9999) unstable;
+ * Remove glib dpendency
* Improve RingBuffer
+ * Add ThreadVar, a thread-specific variable class
* Improve test suite
* Remove EventRingBuffer
* Remove SMFReader and SMFWriter
* Remove OSC and RDF library dependent code
- * Remove Thread context stuff and add a thread-specific variable class,
- ThreadVar, which can be used for this and many other things
+ * Remove Thread context stuff in favour of ThreadVar
* Add INSTALL file
* Update license to GPL3+
diff --git a/raul.pc.in b/raul.pc.in
index adb0d70..4f641af 100644
--- a/raul.pc.in
+++ b/raul.pc.in
@@ -6,6 +6,5 @@ includedir=@INCLUDEDIR@
Name: raul
Version: @RAUL_VERSION@
Description: A C++ convenience library for realtime audio applications
-Requires: glib-2.0 gthread-2.0
Libs: -L${libdir} -lraul @RAUL_PC_LIBS@
Cflags: -I${includedir}
diff --git a/raul/Configuration.hpp b/raul/Configuration.hpp
index 554b247..6e45d3c 100644
--- a/raul/Configuration.hpp
+++ b/raul/Configuration.hpp
@@ -22,12 +22,13 @@
#include <stdlib.h>
#include <string.h>
-#include <exception>
#include <list>
#include <map>
#include <ostream>
#include <string>
+#include "raul/Exception.hpp"
+
namespace Raul {
/** Program configuration (command line options and/or configuration file).
@@ -126,11 +127,8 @@ public:
void print_usage(const std::string& program, std::ostream& os);
- struct CommandLineError : public std::exception {
- explicit CommandLineError(const std::string& m) : msg(m) {}
- ~CommandLineError() throw() {}
- const char* what() const throw() { return msg.c_str(); }
- std::string msg;
+ struct CommandLineError : public Exception {
+ explicit CommandLineError(const std::string& m) : Exception(m) {}
};
void parse(int argc, char** argv) throw (CommandLineError);
diff --git a/raul/Exception.hpp b/raul/Exception.hpp
new file mode 100644
index 0000000..4969ab2
--- /dev/null
+++ b/raul/Exception.hpp
@@ -0,0 +1,34 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2012 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/>.
+*/
+
+#include <exception>
+#include <string>
+
+#ifndef RAUL_EXCEPTION_HPP
+#define RAUL_EXCEPTION_HPP
+
+/** An exception (unexpected error). */
+class Exception : public std::exception {
+public:
+ const char* what() const throw() { return _what.c_str(); }
+ ~Exception() throw() {}
+protected:
+ explicit Exception(const std::string& what) : _what(what) {}
+private:
+ const std::string _what;
+};
+
+#endif // RAUL_EXCEPTION_HPP
diff --git a/raul/Path.hpp b/raul/Path.hpp
index 57bed80..05fb029 100644
--- a/raul/Path.hpp
+++ b/raul/Path.hpp
@@ -17,48 +17,38 @@
#ifndef RAUL_PATH_HPP
#define RAUL_PATH_HPP
-#include <cassert>
-#include <cctype>
-#include <cstring>
-#include <exception>
#include <string>
+#include "raul/Exception.hpp"
#include "raul/Symbol.hpp"
namespace Raul {
/** A restricted path of Symbols separated by, and beginning with, "/".
*
- * This enforces that a Path is a valid path, where each fragment is a valid
- * Symbol, separated by exactly one slash (/).
+ * A Path never ends with a "/", except for the root Path "/", which is the
+ * only valid single-character Path.
*
- * A path is divided by slashes (/). The first character MUST be a slash, and
- * the last character MUST NOT be a slash (except in the special case of the
- * root path "/", which is the only valid single-character path).
- *
- * \ingroup raul
+ * @ingroup raul
*/
-class Path {
+class Path : public std::basic_string<char> {
public:
- class BadPath : public std::exception {
+ /** Attempt to construct an invalid Path. */
+ class BadPath : public Exception {
public:
- explicit BadPath(const std::string& path) : _path(path) {}
- ~BadPath() throw() {}
- const char* what() const throw() { return _path.c_str(); }
- private:
- const std::string _path;
+ explicit BadPath(const std::string& path) : Exception(path) {}
};
/** Construct an uninitialzed path, because the STL is annoying. */
- Path() : _str(g_intern_string("/")) {}
+ Path() : std::basic_string<char>("/") {}
- /** Construct a Path from an std::string.
+ /** Construct a Path from a C++ string.
*
- * It is a fatal error to construct a Path from an invalid string,
- * use is_valid first to check.
+ * This will throw an exception if @p path is invalid. To avoid this, use
+ * is_valid() first to check.
*/
- Path(const std::basic_string<char>& path) throw (BadPath)
- : _str(g_intern_string(path.c_str()))
+ explicit Path(const std::basic_string<char>& path)
+ : std::basic_string<char>(path)
{
if (!is_valid(path)) {
throw BadPath(path);
@@ -67,56 +57,81 @@ public:
/** Construct a Path from a C string.
*
- * It is a fatal error to construct a Path from an invalid string,
- * use is_valid first to check.
+ * This will throw an exception if @p path is invalid. To avoid this, use
+ * is_valid() first to check.
*/
- Path(const char* cpath) throw(BadPath)
- : _str(g_intern_string(cpath))
+ explicit Path(const char* path)
+ : std::basic_string<char>(path)
{
- if (!is_valid(cpath)) {
- throw BadPath(cpath);
+ if (!is_valid(path)) {
+ throw BadPath(path);
}
}
- /** Construct a Path from another path.
+ /** Copy a Path.
*
- * This is faster than constructing a path from the other path's string
- * representation, since validity checking is avoided.
+ * Note this is faster than constructing a Path from another Path's string
+ * since validation is unnecessary.
*/
- Path& operator=(const Path& other) {
- _str = other._str;
- return *this;
+ Path(const Path& path)
+ : std::basic_string<char>(path)
+ {}
+
+ /** Return true iff @p c is a valid Path character. */
+ static inline bool is_valid_char(char c) {
+ return c == '/' || Symbol::is_valid_char(c);
}
- static bool is_valid(const std::basic_string<char>& path);
+ /** Return true iff @p str is a valid Path. */
+ static inline bool is_valid(const std::basic_string<char>& str) {
+ if (str.empty() || (str[0] != '/')) {
+ return false; // Must start with '/'
+ }
- /** Convert a string to a valid Path. */
- static Path pathify(const std::basic_string<char>& str);
+ if (str != "/" && *str.rbegin() == '/') {
+ return false; // Must not end with '/' except for the root
+ }
- static void replace_invalid_chars(std::string& str,
- size_t start,
- bool replace_slash = false);
+ for (size_t i = 1; i < str.length(); ++i) {
+ if (!is_valid_char(str[i])) {
+ return false; // All characters must be /, _, a-z, A-Z, 0-9
+ } else if (str[i - 1] == '/') {
+ if (str[i] == '/') {
+ return false; // Must not contain "//"
+ } else if (!Symbol::is_valid_start_char(str[i])) {
+ return false; // Invalid symbol start character (digit)
+ }
+ }
+ }
- bool is_root() const { return !strcmp(_str, "/"); }
+ return true;
+ }
- bool is_child_of(const Path& parent) const;
- bool is_parent_of(const Path& child) const;
+ /** Return true iff this path is the root path ("/"). */
+ inline bool is_root() const { return *this == "/"; }
- Path operator+(const Path& p) const { return child(p); }
+ /** Return true iff this path is a child of @p parent at any depth. */
+ inline bool is_child_of(const Path& parent) const {
+ const std::string parent_base = parent.base();
+ return substr(0, parent_base.length()) == parent_base;
+ }
- /** Return the lowest common ancestor of a and b. */
- static Path lca(const Path& a, const Path& b);
+ /** Return true iff this path is a parent of @p child at any depth. */
+ inline bool is_parent_of(const Path& child) const {
+ return child.is_child_of(*this);
+ }
/** Return the symbol of this path (everything after the last '/').
- * This is e.g. the "method name" for OSC paths, the filename
- * for filesystem paths, etc.
- * The empty string may be returned (if the path is the root path).
+ *
+ * This is what is called the "basename" for file paths, the "method name"
+ * for OSC paths, and so on. Since the root path does not have a symbol,
+ * this does not return a Raul::Symbol but may return the empty string.
*/
inline const char* symbol() const {
if (!is_root()) {
- const char* last_slash = strrchr(c_str(), '/');
- if (last_slash) {
- return last_slash + 1;
+ const size_t last_sep = rfind('/');
+ if (last_sep != std::string::npos) {
+ return c_str() + last_sep + 1;
}
}
return "";
@@ -131,83 +146,65 @@ public:
if (is_root()) {
return *this;
} else {
- const std::string str(this->str());
- const size_t first_slash = str.find('/');
- const size_t last_slash = str.find_last_of('/');
- return (first_slash == last_slash) ? Path("/") : str.substr(0, last_slash);
+ const size_t first_sep = find('/');
+ const size_t last_sep = find_last_of('/');
+ return (first_sep == last_sep) ? Path("/") : Path(substr(0, last_sep));
}
}
- Path child(const Path& p) const {
- return base() + p.str().substr(1);
+ /** Return a child Path of this path. */
+ inline Path child(const Path& p) const {
+ return p.is_root() ? *this : Path(base() + p.substr(1));
}
- /** Return the path's child with the given symbol
- */
+ /** Return a direct child Path of this Path with the given Symbol. */
inline Path child(const Raul::Symbol& symbol) const {
- return base() + symbol.c_str();
+ return Path(base() + symbol.c_str());
}
- /** Return path relative to some base path (chop prefix)
+ /** Return path with a trailing "/".
+ *
+ * The returned string is such that appending a valid Symbol to it is
+ * guaranteed to form a valid path.
*/
- inline Path relative_to_base(const Path& base) const {
- if ((*this) == base) {
- return "/";
+ inline const std::string base() const {
+ if (is_root()) {
+ return *this;
} else {
- assert(length() > base.base().length());
- return str().substr(base.base().length() - 1);
+ return *this + '/';
}
}
- /** Return path with a trailing "/".
- *
- * Returned value is guaranteed to be a valid parent path, i.e. a valid
- * child path can be made using parent.base() + symbol.
- */
- inline const std::string base() const {
- std::string ret = str();
- if (is_root() && ret[ret.length() - 1] == '/')
- return ret;
- else
- return ret + '/';
+ /** Return the lowest common ancestor of a and b. */
+ static inline Path lca(const Path& a, const Path& b) {
+ const size_t len = std::min(a.length(), b.length());
+ size_t last_sep = 0;
+ for (size_t i = 0; i < len; ++i) {
+ if (a[i] == '/' && b[i] == '/') {
+ last_sep = i;
+ }
+ if (a[i] != b[i]) {
+ break;
+ }
+ }
+
+ if (last_sep <= 1) {
+ return Path("/");
+ }
+
+ return Path(a.substr(0, last_sep));
}
- /** Return true if \a child is equal to, or a descendant of \a parent */
- static bool descendant_comparator(const Path& parent, const Path& child) {
+ /** Return true iff @p child is equal to, or a descendant of @p parent. */
+ static inline bool descendant_comparator(const Path& parent,
+ const Path& child) {
return (child == parent ||
(child.length() > parent.length() &&
- (!std::strncmp(parent.c_str(), child.c_str(), parent.length())
- && (parent.is_root() || child.str()[parent.length()] == '/'))) );
- }
-
- inline std::string substr(size_t start, size_t end=std::string::npos) const {
- return str().substr(start, end);
+ (!parent.compare(0, parent.length(), child, 0, parent.length())
+ && (parent.is_root() || child[parent.length()] == '/'))));
}
-
- inline bool operator<(const Path& path) const { return strcmp(_str, path.c_str()) < 0; }
- inline bool operator<=(const Path& path) const { return (*this) == path || (*this) < path; }
- inline bool operator==(const Path& path) const { return _str == path._str; }
- inline bool operator!=(const Path& path) const { return _str != path._str; }
-
- inline char operator[](int i) const { return _str[i]; }
-
- inline size_t length() const { return str().length(); }
- inline size_t find(const std::string& s) const { return str().find(s); }
-
- inline const std::string str() const { return _str; }
- inline const char* c_str() const { return _str; }
-
-private:
- const char* _str;
};
} // namespace Raul
-static inline
-std::ostream&
-operator<<(std::ostream& os, const Raul::Path& path)
-{
- return (os << path.c_str());
-}
-
#endif // RAUL_PATH_HPP
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
diff --git a/raul/URI.hpp b/raul/URI.hpp
index 83454ca..b2ccad7 100644
--- a/raul/URI.hpp
+++ b/raul/URI.hpp
@@ -18,39 +18,30 @@
#define RAUL_URI_HPP
#include <string>
-#include <cstring>
-#include <exception>
-#include <ostream>
-#include <glib.h>
-#include "raul/Path.hpp"
+#include "raul/Exception.hpp"
namespace Raul {
-/** Simple wrapper around standard string with useful URI-specific methods.
+/** A URI (RFC3986) string.
*
- * This "should" be used for proper URIs (RFC3986), but not much support or
- * validation is built-in yet. The URI string MUST have a scheme though.
- * \ingroup raul
+ * @ingroup raul
*/
-class URI {
+class URI : public std::basic_string<char> {
public:
- class BadURI : public std::exception {
+ /** Attempt to construct an invalid URI. */
+ class BadURI : public Exception {
public:
- explicit BadURI(const std::string& uri) : _uri(uri) {}
- ~BadURI() throw() {}
- const char* what() const throw() { return _uri.c_str(); }
- private:
- const std::string _uri;
+ explicit BadURI(const std::string& uri) : Exception(uri) {}
};
- /** Construct a URI from an std::string.
+ /** Construct a URI from a C++ string.
*
- * It is a fatal error to construct a URI from an invalid string,
- * use is_valid first to check.
+ * This will throw an exception if @p uri is invalid. To avoid this, use
+ * is_valid() first to check.
*/
- URI(const std::basic_string<char>& uri="nil:0") throw(BadURI)
- : _str(g_intern_string(uri.c_str()))
+ explicit URI(const std::basic_string<char>& uri)
+ : std::basic_string<char>(uri)
{
if (!is_valid(uri)) {
throw BadURI(uri);
@@ -59,67 +50,63 @@ public:
/** Construct a URI from a C string.
*
- * It is a fatal error to construct a URI from an invalid string,
- * use is_valid first to check.
+ * This will throw an exception if @p uri is invalid. To avoid this, use
+ * is_valid() first to check.
*/
- URI(const char* uri) throw(BadURI)
- : _str(g_intern_string(uri))
+ explicit URI(const char* uri)
+ : std::basic_string<char>(uri)
{
- if (!is_valid(uri))
+ if (!is_valid(uri)) {
throw BadURI(uri);
+ }
}
- /** Construct a URI from a base URI and a Path. */
- URI(const URI& base, const Path& path)
- : _str(g_intern_string((base.str() + path.c_str()).c_str()))
+ /** Copy a URI.
+ *
+ * Note this is faster than constructing a URI from another URI's string
+ * since validation is unnecessary.
+ */
+ URI(const URI& uri)
+ : std::basic_string<char>(uri)
{}
- static bool is_valid(const std::basic_string<char>& uri) {
- return uri.find(":") != std::string::npos;
+ /** Return true iff @p c is a valid URI start character. */
+ static inline bool is_valid_start_char(char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
- /** Return path with everything up to and including the first occurence of str chopped */
- inline const std::string chop_start(const std::string& str) const {
- return substr(find(str) + str.length());
+ /** Return true iff @p c is a valid URI scheme character. */
+ static inline bool is_valid_scheme_char(char c) {
+ // S3.1: scheme ::= ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ return is_valid_start_char(c) || (c >= '0' && c <= '9') ||
+ c == '+' || c == '-' || c == '.';
}
- /** Return the URI with the scheme removed (as a string) */
- std::string chop_scheme() const { return chop_start(":"); }
-
- /** Return the URI scheme (everything before the first ':') */
- inline std::string scheme() const { return substr(0, find(":")); }
+ /** Return true iff @p str is a valid URI.
+ *
+ * Currently this only checks that @p starts with a valid URI scheme.
+ */
+ static inline bool is_valid(const std::basic_string<char>& str) {
+ if (!is_valid_start_char(str[0])) {
+ return false; // Must start with a-z A-Z
+ }
- inline const std::string str() const { return _str; }
- inline const char* c_str() const { return _str; }
+ for (size_t i = 1; i < str.length(); ++i) {
+ if (str[i] == ':') {
+ return true; // Starts with a valid scheme
+ } else if (!is_valid_scheme_char(str[i])) {
+ return false; // Invalid scheme character encountered
+ }
+ }
- inline std::string substr(size_t start, size_t end=std::string::npos) const {
- return str().substr(start, end);
+ return false; // Must start with a scheme followed by ':'
}
- inline bool operator<(const URI& uri) const { return strcmp(_str, uri.c_str()) < 0; }
- inline bool operator<=(const URI& uri) const { return (*this) == uri || (*this) < uri; }
- inline bool operator==(const URI& uri) const { return _str == uri._str; }
- inline bool operator!=(const URI& uri) const { return _str != uri._str; }
-
- inline char operator[](int i) const { return _str[i]; }
-
- inline size_t length() const { return str().length(); }
- inline size_t find(const std::string& s) const { return str().find(s); }
- inline size_t find_last_of(char c) const { return str().find_last_of(c); }
-
-private:
- const char* _str;
+ /** Return the URI scheme (everything before the first ':') */
+ inline std::string scheme() const { return substr(0, find(":")); }
};
} // namespace Raul
-static inline
-std::ostream&
-operator<<(std::ostream& os, const Raul::URI& uri)
-{
- return (os << uri.c_str());
-}
-
-
#endif // RAUL_URI_HPP
diff --git a/src/Path.cpp b/src/Path.cpp
deleted file mode 100644
index e3a529d..0000000
--- a/src/Path.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- This file is part of Raul.
- Copyright 2007-2012 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/>.
-*/
-
-#include <string>
-
-#include "raul/Path.hpp"
-
-using std::string;
-
-namespace Raul {
-
-bool
-Path::is_valid(const std::basic_string<char>& path)
-{
- if (path.empty() || path[0] != '/') {
- return false;
- }
-
- // Root path
- if (path == "/") {
- return true;
- }
-
- // Not root, must not end with a slash
- if (*path.rbegin() == '/')
- return false;
-
- // Double slash not allowed
- if (path.find("//") != string::npos)
- return false;
-
- for (size_t i=0; i < path.length(); ++i)
- // All contained symbols must not start with a digit
- if (i > 0 && path[i-1] == '/' && isdigit(path[i]))
- return false;
- // All characters must be _, a-z, A-Z, 0-9
- else if ( path[i] != '/' && path[i] != '_'
- && (path[i] < 'a' || path[i] > 'z')
- && (path[i] < 'A' || path[i] > 'Z')
- && (path[i] < '0' || path[i] > '9') )
- return false;
-
- return true;
-}
-
-Path
-Path::pathify(const std::basic_string<char>& str)
-{
- if (str.length() == 0)
- return Path("/"); // this might not be wise?
-
- const size_t first_slash = str.find('/');
- string path = (first_slash == string::npos)
- ? string("/").append(str)
- : str.substr(first_slash);
-
- // Must start with a /
- if (path.empty() || path[0] != '/')
- path = string("/").append(path);
-
- // Must not end with a slash unless "/"
- if (path != "/" && path[path.length() - 1] == '/')
- path = path.substr(0, path.length() - 1); // chop trailing slash
-
- replace_invalid_chars(path, 0, false);
- return Path(path);
-}
-
-/** Replace any invalid characters in @a str with a suitable replacement.
- */
-void
-Path::replace_invalid_chars(std::string& str, size_t start, bool replace_slash)
-{
- string prefix = str.substr(0, start);
- str = str.substr(start);
-
- size_t open_bracket = str.find_first_of('(');
- if (open_bracket != string::npos)
- str = str.substr(0, open_bracket);
-
- open_bracket = str.find_first_of('[');
- if (open_bracket != string::npos)
- str = str.substr(0, open_bracket);
-
- if (str[str.length()-1] == ' ')
- str = str.substr(0, str.length()-1);
-
- if (isdigit(str[0]))
- str = string("_").append(str);
-
- for (size_t i=0; i < str.length(); ++i) {
- if (i > 0 && str[i-1] == '/' && isdigit(str[i])) {
- str = str.substr(0, i) + "_" + str.substr(i);
- } else if (str[i] == '\'') {
- str = str.substr(0, i) + str.substr(i+1);
- } else if ( str[i] != '_' && str[i] != '/'
- && (str[i] < 'a' || str[i] > 'z')
- && (str[i] < 'A' || str[i] > 'Z')
- && (str[i] < '0' || str[i] > '9') ) {
- if (i > 0 && str[i-1] == '_') {
- str = str.substr(0, i) + str.substr(i+1);
- --i;
- } else {
- str[i] = '_';
- }
- } else if (replace_slash && str[i] == '/') {
- str[i] = '_';
- }
- }
-
- if (str.length() != 1 && str[str.length()-1] == '_')
- str = str.substr(0, str.length()-1);
-
- str = prefix + str;
-}
-
-bool
-Path::is_child_of(const Path& parent) const
-{
- const string parent_base = parent.base();
- return (str().substr(0, parent_base.length()) == parent_base);
-}
-
-bool
-Path::is_parent_of(const Path& child) const
-{
- return child.is_child_of(*this);
-}
-
-Path
-Path::lca(const Path& a, const Path& b)
-{
- const size_t len = std::min(a.length(), b.length());
-
- size_t last_slash = 0;
- for (size_t i = 0; i < len; ++i) {
- if (a[i] == '/' && b[i] == '/') {
- last_slash = i;
- }
- if (a[i] != b[i]) {
- break;
- }
- }
-
- if (last_slash <= 1) {
- return Path("/");
- }
- return Path(a.str().substr(0, last_slash));
-}
-
-} // namespace Raul
diff --git a/src/Symbol.cpp b/src/Symbol.cpp
deleted file mode 100644
index 4fe049e..0000000
--- a/src/Symbol.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- This file is part of Raul.
- Copyright 2007-2012 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/>.
-*/
-
-#include <string>
-
-#include "raul/Symbol.hpp"
-#include "raul/Path.hpp"
-
-using std::string;
-
-namespace Raul {
-
-bool
-Symbol::is_valid(const std::basic_string<char>& symbol)
-{
- if (symbol.length() == 0)
- return false;
-
- // Slash not allowed
- if (symbol.find("/") != string::npos)
- return false;
-
- // All characters must be _, a-z, A-Z, 0-9
- for (size_t i=0; i < symbol.length(); ++i)
- if (symbol[i] != '_'
- && (symbol[i] < 'a' || symbol[i] > 'z')
- && (symbol[i] < 'A' || symbol[i] > 'Z')
- && (symbol[i] < '0' || symbol[i] > '9') )
- return false;
-
- // First character must not be a number
- if (std::isdigit(symbol[0]))
- return false;
-
- 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.
- */
-Raul::Symbol
-Symbol::symbolify(const std::basic_string<char>& str)
-{
- string symbol = str;
-
- Path::replace_invalid_chars(symbol, 0, true);
-
- return Raul::Symbol(symbol.empty() ? "_" : symbol);
-}
-
-} // namespace Raul
-
diff --git a/test/path_test.cpp b/test/path_test.cpp
index f267595..1bdd99e 100644
--- a/test/path_test.cpp
+++ b/test/path_test.cpp
@@ -14,8 +14,9 @@
along with Raul. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <cstring>
#include <iostream>
-#include <list>
+
#include "raul/log.hpp"
#include "raul/Path.hpp"
@@ -31,23 +32,6 @@ main()
return 1; \
} } while (0)
- list<string> names;
- names.push_back("Dry/Wet Balance");
- names.push_back("foo+1bar(baz)");
- names.push_back("ThisCRAR");
- names.push_back("NAME");
- names.push_back("thing with a bunch of spaces");
- names.push_back("thing-with-a-bunch-of-dashes");
- names.push_back("CamelCaseABC");
- names.push_back("Signal Level [dB]");
- names.push_back("Gain dB");
- names.push_back("Dry/Wet Balance");
- names.push_back("Phaser1 - Similar to CSound's phaser1 by Sean Costello");
-
- for (list<string>::iterator i = names.begin(); i != names.end(); ++i) {
- CHECK(strcmp(Symbol::symbolify(*i).c_str(), ""));
- }
-
CHECK(Path("/foo/bar").parent() == Path("/foo"));
CHECK(Path("/foo").parent() == Path("/"));
CHECK(Path("/").parent() == Path("/"));
@@ -68,13 +52,13 @@ main()
CHECK(Path::is_valid("/"));
CHECK(!Path::is_valid("/foo/3foo/bar"));
- CHECK(Path::descendant_comparator("/", "/foo"));
- CHECK(Path::descendant_comparator("/foo", "/foo/bar"));
- CHECK(Path::descendant_comparator("/foo", "/foo"));
- CHECK(Path::descendant_comparator("/", "/"));
- CHECK(!Path::descendant_comparator("/baz", "/"));
- CHECK(!Path::descendant_comparator("/foo", "/bar"));
- CHECK(!Path::descendant_comparator("/foo/bar", "/foo"));
+ CHECK(Path::descendant_comparator(Path("/"), Path("/foo")));
+ CHECK(Path::descendant_comparator(Path("/foo"), Path("/foo/bar")));
+ CHECK(Path::descendant_comparator(Path("/foo"), Path("/foo")));
+ CHECK(Path::descendant_comparator(Path("/"), Path("/")));
+ CHECK(!Path::descendant_comparator(Path("/baz"), Path("/")));
+ CHECK(!Path::descendant_comparator(Path("/foo"), Path("/bar")));
+ CHECK(!Path::descendant_comparator(Path("/foo/bar"), Path("/foo")));
CHECK(!Symbol::is_valid(""));
CHECK(!Symbol::is_valid("/I/have/slashes"));
@@ -82,5 +66,35 @@ main()
CHECK(!Symbol::is_valid("0illegalleadingdigit"));
CHECK(strcmp(Symbol::symbolify("").c_str(), ""));
+ CHECK(Path("/foo").child(Symbol("bar")) == "/foo/bar");
+ CHECK(Path("/foo").child(Path("/bar/baz")) == "/foo/bar/baz");
+ CHECK(Path("/foo").child(Path("/")) == "/foo");
+
+ CHECK(!strcmp(Path("/foo").symbol(), "foo"));
+ CHECK(!strcmp(Path("/foo/bar").symbol(), "bar"));
+ CHECK(!strcmp(Path("/").symbol(), ""));
+
+ Path original(std::string("/foo/bar"));
+ Path copy(original);
+ CHECK(original == copy);
+
+ bool valid = true;
+ try {
+ Path path("/ends/in/slash/");
+ } catch (const Path::BadPath& e) {
+ std::cerr << "Caught exception: " << e.what() << std::endl;
+ valid = false;
+ }
+ CHECK(!valid);
+
+ valid = true;
+ try {
+ Path path(std::string("/has//double/slash"));
+ } catch (const Path::BadPath& e) {
+ std::cerr << "Caught exception: " << e.what() << std::endl;
+ valid = false;
+ }
+ CHECK(!valid);
+
return 0;
}
diff --git a/test/symbol_test.cpp b/test/symbol_test.cpp
new file mode 100644
index 0000000..9726001
--- /dev/null
+++ b/test/symbol_test.cpp
@@ -0,0 +1,77 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2012 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/>.
+*/
+
+#include <cstring>
+#include <iostream>
+#include <list>
+
+#include "raul/log.hpp"
+#include "raul/Path.hpp"
+
+using namespace std;
+using namespace Raul;
+
+int
+main()
+{
+#define CHECK(cond) \
+ do { if (!(cond)) { \
+ error << "Test failed: " << (cond) << endl; \
+ return 1; \
+ } } while (0)
+
+ list<string> names;
+ names.push_back("Dry/Wet Balance");
+ names.push_back("foo+1bar(baz)");
+ names.push_back("ThisCRAR");
+ names.push_back("NAME");
+ names.push_back("thing with a bunch of spaces");
+ names.push_back("thing-with-a-bunch-of-dashes");
+ names.push_back("CamelCaseABC");
+ names.push_back("Signal Level [dB]");
+ names.push_back("Gain dB");
+ names.push_back("Dry/Wet Balance");
+ names.push_back("Phaser1 - Similar to CSound's phaser1 by Sean Costello");
+ names.push_back("");
+
+ for (list<string>::iterator i = names.begin(); i != names.end(); ++i) {
+ CHECK(!Symbol::symbolify(*i).empty());
+ }
+
+ Symbol original("sym");
+ Symbol copy(original);
+ CHECK(original == copy);
+
+ bool valid = true;
+ try {
+ Symbol symbol("0startswithdigit");
+ } catch (const Symbol::BadSymbol& e) {
+ std::cerr << "Caught exception: " << e.what() << std::endl;
+ valid = false;
+ }
+ CHECK(!valid);
+
+ valid = true;
+ try {
+ Symbol symbol(std::string("invalid/symbol"));
+ } catch (const Symbol::BadSymbol& e) {
+ std::cerr << "Caught exception: " << e.what() << std::endl;
+ valid = false;
+ }
+ CHECK(!valid);
+
+ return 0;
+}
diff --git a/test/table_test.cpp b/test/table_test.cpp
index 70ab5b1..f372d7c 100644
--- a/test/table_test.cpp
+++ b/test/table_test.cpp
@@ -14,12 +14,13 @@
along with Raul. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <string>
+#include <cstring>
#include <iostream>
-#include <utility>
#include <map>
#include <set>
+#include <string>
#include <sys/time.h>
+#include <utility>
#include "raul/log.hpp"
#include "raul/PathTable.hpp"
diff --git a/test/uri_test.cpp b/test/uri_test.cpp
new file mode 100644
index 0000000..d3b9a99
--- /dev/null
+++ b/test/uri_test.cpp
@@ -0,0 +1,61 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2012 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/>.
+*/
+
+#include <iostream>
+
+#include "raul/log.hpp"
+#include "raul/URI.hpp"
+
+using namespace std;
+using namespace Raul;
+
+int
+main()
+{
+#define CHECK(cond) \
+ do { if (!(cond)) { \
+ error << "Test failed: " << (cond) << endl; \
+ assert(0); \
+ return 1; \
+ } } while (0)
+
+ CHECK(URI("http://example.org").scheme() == "http");
+ CHECK(URI("svn+ssh://example.org/").scheme() == "svn+ssh");
+ CHECK(URI("osc.udp://example.org/").scheme() == "osc.udp");
+ CHECK(URI("weird-scheme://example.org/").scheme() == "weird-scheme");
+
+ URI original(std::string("http://example.org"));
+ URI copy(original);
+ CHECK(original == copy);
+
+ bool valid = true;
+ try {
+ URI uri("not/a/uri");
+ } catch (const URI::BadURI& e) {
+ valid = false;
+ }
+ CHECK(!valid);
+
+ valid = true;
+ try {
+ URI uri(std::string("/this/is/a/path"));
+ } catch (const URI::BadURI& e) {
+ valid = false;
+ }
+ CHECK(!valid);
+
+ return 0;
+}
diff --git a/wscript b/wscript
index af99445..d3b4dd7 100644
--- a/wscript
+++ b/wscript
@@ -51,10 +51,6 @@ def configure(conf):
autowaf.configure(conf)
conf.line_just = 40
autowaf.display_header('Raul Configuration')
- autowaf.check_pkg(conf, 'glib-2.0', atleast_version='2.2',
- uselib_store='GLIB', mandatory=True)
- autowaf.check_pkg(conf, 'gthread-2.0', atleast_version='2.14.0',
- uselib_store='GTHREAD', mandatory=True)
if Options.platform == 'darwin':
conf.check(framework_name='CoreServices')
@@ -95,9 +91,11 @@ tests = '''
test/queue_test
test/ringbuffer_test
test/sem_test
+ test/symbol_test
test/table_test
test/thread_test
test/time_test
+ test/uri_test
'''
def build(bld):
@@ -115,8 +113,6 @@ def build(bld):
lib_source = '''
src/Configuration.cpp
src/Maid.cpp
- src/Path.cpp
- src/Symbol.cpp
src/Thread.cpp
src/log.cpp
'''
@@ -144,7 +140,7 @@ def build(bld):
set_defines(obj);
if bld.env.BUILD_TESTS:
- test_libs = []
+ test_libs = ['pthread', 'rt']
test_cxxflags = []
if bld.is_defined('HAVE_GCOV'):
test_libs += ['gcov']