summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-10-22 03:46:46 +0000
committerDavid Robillard <d@drobilla.net>2007-10-22 03:46:46 +0000
commit282ad28ebe5217bec8039e6417bc518680f910e2 (patch)
tree90e8573758ebb197d3faa7ecc8391f5d446471e5
parent58ceeae7457f03b60fdc5a491b36abb2aa6d9e8a (diff)
downloadraul-282ad28ebe5217bec8039e6417bc518680f910e2.tar.gz
raul-282ad28ebe5217bec8039e6417bc518680f910e2.tar.bz2
raul-282ad28ebe5217bec8039e6417bc518680f910e2.zip
Stricter limitations for path symbols/names (C symbols, equivalent to lv2:symbol, subset of OSC addresses and URIs).
git-svn-id: http://svn.drobilla.net/lad/raul@897 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/Path.cpp79
-rw-r--r--tests/path_test.cpp19
2 files changed, 75 insertions, 23 deletions
diff --git a/src/Path.cpp b/src/Path.cpp
index 96dad69..284cf16 100644
--- a/src/Path.cpp
+++ b/src/Path.cpp
@@ -27,11 +27,11 @@ Path::is_valid(const std::basic_string<char>& path)
return false;
// Must start with a /
- if (path.at(0) != '/')
+ if (path[0] != '/')
return false;
// Must not end with a slash unless "/"
- if (path.length() > 1 && path.at(path.length()-1) == '/')
+ if (path.length() > 1 && path[path.length()-1] == '/')
return false;
assert(path.find_last_of("/") != string::npos);
@@ -40,11 +40,17 @@ Path::is_valid(const std::basic_string<char>& path)
if (path.find("//") != string::npos)
return false;
- // All characters must be printable ASCII
+ // All characters must be _, a-z, A-Z, 0-9
for (size_t i=0; i < path.length(); ++i)
- if (path.at(i) < 32 || path.at(i) > 126)
+ 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;
+ // FIXME: first character can't be number?
+
+#if 0
// Disallowed characters
if ( path.find(" ") != string::npos
|| path.find("#") != string::npos
@@ -56,6 +62,7 @@ Path::is_valid(const std::basic_string<char>& path)
|| path.find("{") != string::npos
|| path.find("}") != string::npos)
return false;
+#endif
return true;
}
@@ -102,7 +109,7 @@ Path::nameify(const std::basic_string<char>& str)
string name = str;
if (name.length() == 0)
- return "."; // this might not be wise
+ return "_"; // this might not be wise
replace_invalid_chars(name, true);
@@ -113,14 +120,11 @@ Path::nameify(const std::basic_string<char>& str)
/** Replace any invalid characters in @a str with a suitable replacement.
- *
- * Makes a pretty name - underscores are a valid character, but this chops
- * both spaces and underscores, uppercasing the next letter, to create
- * uniform CamelCase names that look nice
*/
void
Path::replace_invalid_chars(string& str, bool replace_slash)
{
+#if 0
for (size_t i=0; i < str.length(); ++i) {
if (str[i] == ' ' || str[i] == '_') {
str[i+1] = std::toupper(str[i+1]); // capitalize next char
@@ -139,22 +143,55 @@ Path::replace_invalid_chars(string& str, bool replace_slash)
str[i] = '.';
}
}
+#endif
- // Chop brackets
- // No, ruins uniqueness (LADSPA plugins)
- /*while (true) {
+ size_t open_bracket = str.find_first_of('(');
+ if (open_bracket != string::npos)
+ str = str.substr(0, open_bracket-1);
+
+ open_bracket = str.find_first_of('[');
+ if (open_bracket != string::npos)
+ str = str.substr(0, open_bracket-1);
+
+ // dB = special case, need to avoid CamelCase killing below
+ while (true) {
+ size_t decibels = str.find("dB");
+ if (decibels != string::npos)
+ str[decibels+1] = 'b';
+ else
+ break;
+ }
- const string::size_type open = str.find("(");
- const string::size_type close = str.find(")");
- if (open != string::npos) {
- if (close != string::npos)
- str.erase(open, (close - open) + 1);
- } else {
- break;
+ // Kill CamelCase in favour of god_fearing_symbol_names
+ for (size_t i=1; i < str.length(); ++i) {
+ if (str[i] >= 'A' && str[i] <= 'Z' && str[i-1] >= 'a' && str[i-1] <= 'z') {
+ //str[i] = std::tolower(str[i]);
+ str = str.substr(0, i) + '_' + str.substr(i);
}
-
- }*/
+ }
+
+ for (size_t i=0; i < str.length(); ++i) {
+ if (str[i] == '\'') {
+ str = str.substr(0, i) + str.substr(i+1);
+ } else if (str[i] >= 'A' && str[i] <= 'Z') {
+ str[i] = std::tolower(str[i]);
+ } else if ( str[i] != '_' && str[i] != '/'
+ && (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[str.length()-1] == '_')
+ str = str.substr(0, str.length()-1);
}
diff --git a/tests/path_test.cpp b/tests/path_test.cpp
index c5c4415..8f33dee 100644
--- a/tests/path_test.cpp
+++ b/tests/path_test.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <list>
#include <raul/Path.hpp>
using namespace std;
@@ -7,14 +8,28 @@ using namespace Raul;
int
main()
{
+ list<string> names;
+ 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");
+
+ cerr << "Nameification:" << endl;
+ for (list<string>::iterator i = names.begin(); i != names.end(); ++i)
+ cerr << *i << " -> " << Path::nameify(*i) << endl;
+
cerr << "1's are good..." << endl << endl;
cerr << (Path("/").is_parent_of(Path("/foo"))) << endl;
cerr << (Path("/foo").is_parent_of(Path("/foo/bar"))) << endl;
cerr << !(Path("/foo").is_parent_of(Path("/foo2"))) << endl;
- cerr << Path::nameify("Signal Level [dB]") << endl;
-
cerr << endl << endl << "Descendants..." << endl;
cerr << "/ /foo " << Path::descendant_comparator("/", "/foo") << endl;
cerr << "/foo /foo/bar " << Path::descendant_comparator("/foo", "/foo/bar") << endl;