summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/reference.doxygen.in3
-rw-r--r--raul/Configuration.hpp104
-rw-r--r--src/Configuration.cpp166
-rw-r--r--src/Maid.cpp5
-rw-r--r--src/Path.cpp2
-rw-r--r--src/SMFReader.cpp4
-rw-r--r--src/SMFWriter.cpp4
-rw-r--r--src/Thread.cpp4
-rw-r--r--wscript1
9 files changed, 282 insertions, 11 deletions
diff --git a/doc/reference.doxygen.in b/doc/reference.doxygen.in
index d52d57f..ecc4fa9 100644
--- a/doc/reference.doxygen.in
+++ b/doc/reference.doxygen.in
@@ -569,7 +569,8 @@ WARN_LOGFILE =
# with spaces.
INPUT = @RAUL_SRCDIR@/doc/mainpage.dox \
- @RAUL_SRCDIR@/raul
+ @RAUL_SRCDIR@/raul \
+ @RAUL_SRCDIR@/src
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
diff --git a/raul/Configuration.hpp b/raul/Configuration.hpp
new file mode 100644
index 0000000..5c9ec4b
--- /dev/null
+++ b/raul/Configuration.hpp
@@ -0,0 +1,104 @@
+/* This file is part of Raul.
+ * Copyright (C) 2009 Dave 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 2 of the License, or (at your option) 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 details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_CONFIGURATION_HPP
+#define RAUL_CONFIGURATION_HPP
+
+#include <map>
+#include <string>
+#include <list>
+#include <ostream>
+#include <exception>
+#include "raul/Atom.hpp"
+
+namespace Raul {
+
+/** Program configuration (command line options and/or configuration file).
+ *
+ * \ingroup raul
+ */
+class Configuration {
+public:
+ Configuration(const std::string& shortdesc, const std::string& desc)
+ : _shortdesc(shortdesc)
+ , _desc(desc)
+ , _max_name_length(0)
+ {}
+
+ Configuration& add(
+ const std::string& name,
+ char letter,
+ const std::string& desc,
+ const Atom::Type type,
+ const Atom& value);
+
+ void print_usage(const std::string& program, std::ostream& os);
+
+ struct CommandLineError : public std::exception {
+ CommandLineError(const std::string& m) : msg(m) {}
+ ~CommandLineError() throw() {}
+ const char* what() const throw() { return msg.c_str(); }
+ std::string msg;
+ };
+
+ void parse(int argc, char** argv) throw (CommandLineError);
+
+ void print(std::ostream& os, const std::string mime_type="text/plain") const;
+
+ const Raul::Atom& option(const std::string& long_name);
+
+private:
+ struct Option {
+ public:
+ Option(const std::string& n, char l, const std::string& d,
+ const Atom::Type type, const Raul::Atom& def)
+ : name(n), letter(l), desc(d), type(type), default_value(def), value(def)
+ {}
+
+ std::string name;
+ char letter;
+ std::string desc;
+ Atom::Type type;
+ Raul::Atom default_value;
+ Raul::Atom value;
+ };
+
+ struct OptionNameOrder {
+ inline bool operator()(const Option& a, const Option& b) {
+ return a.name < b.name;
+ }
+ };
+
+ typedef std::map<std::string, Option> Options;
+ typedef std::map<char, std::string> ShortNames;
+ typedef std::list<std::string> Files;
+
+ int set_value_from_string(Configuration::Option& option, const std::string& value)
+ throw (Configuration::CommandLineError);
+
+ const std::string _shortdesc;
+ const std::string _desc;
+ Options _options;
+ ShortNames _short_names;
+ Files _files;
+ size_t _max_name_length;
+};
+
+} // namespace Raul
+
+#endif // RAUL_CONFIGURATION_HPP
+
diff --git a/src/Configuration.cpp b/src/Configuration.cpp
new file mode 100644
index 0000000..1ea70a3
--- /dev/null
+++ b/src/Configuration.cpp
@@ -0,0 +1,166 @@
+/* This file is part of Raul.
+ * Copyright (C) 2009 Dave 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 2 of the License, or (at your option) 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 details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "raul/Configuration.hpp"
+
+using namespace std;
+
+namespace Raul {
+
+
+/** Add a configuration option.
+ *
+ * @param name Long name (without leading "--")
+ * @param letter Short name (without leading "-")
+ * @param desc Description
+ * @param type Type (Atom::BOOL for flags)
+ * @param value Default value
+ */
+Configuration&
+Configuration::add(
+ const std::string& name,
+ char letter,
+ const std::string& desc,
+ const Atom::Type type,
+ const Atom& value)
+{
+ _max_name_length = std::max(_max_name_length, name.length());
+ _options.insert(make_pair(name, Option(name, letter, desc, type, value)));
+ if (letter != '\0')
+ _short_names.insert(make_pair(letter, name));
+ assert(value.type() == type || value.type() == Atom::NIL);
+ return *this;
+}
+
+
+void
+Configuration::print_usage(const std::string& program, std::ostream& os)
+{
+ os << "Usage: " << program << " [OPTIONS]" << endl;
+ os << _shortdesc << endl << endl;
+ os << _desc << endl << endl;
+ os << "Options:" << endl;
+ for (Options::iterator o = _options.begin(); o != _options.end(); ++o) {
+ Option& option = o->second;
+ os << " ";
+ if (option.letter != '\0')
+ os << "-" << option.letter << ", ";
+ else
+ os << " ";
+ os.width(_max_name_length + 4);
+ os << std::left << (string("--") + o->first);
+ os << option.desc << endl;
+ }
+}
+
+
+int
+Configuration::set_value_from_string(Configuration::Option& option, const std::string& value)
+ throw (Configuration::CommandLineError)
+{
+ int intval = 0;
+ char* endptr = NULL;
+ switch (option.type) {
+ case Atom::INT:
+ intval = (int)strtol(value.c_str(), &endptr, 10);
+ if (endptr && *endptr == '\0') {
+ option.value = intval;
+ } else {
+ throw CommandLineError("option `" + option.name
+ + "' has non-integer value `" + value + "'");
+ }
+ break;
+ case Atom::STRING:
+ option.value = Atom(Atom::STRING, value);
+ break;
+ default:
+ throw CommandLineError(string("bad option type `--") + option.name + "'");
+ }
+ return EXIT_SUCCESS;
+}
+
+
+/** Parse command line arguments. */
+void
+Configuration::parse(int argc, char** argv) throw (Configuration::CommandLineError)
+{
+ for (int i = 1; i < argc; ++i) {
+ if (argv[i][0] != '-' || !strcmp(argv[i], "-")) {
+ _files.push_back(argv[i]);
+ } else if (argv[i][1] == '-') {
+ const string name = string(argv[i]).substr(2);
+ Options::iterator o = _options.find(name);
+ if (o == _options.end()) {
+ throw CommandLineError(string("unrecognized option `--") + name + "'");
+ }
+ if (o->second.type == Atom::BOOL) {
+ o->second.value = true;
+ } else {
+ if (++i >= argc)
+ throw CommandLineError("missing value for `--" + name + "'");
+ set_value_from_string(o->second, argv[i]);
+ }
+ } else {
+ const size_t len = strlen(argv[i]);
+ for (size_t j = 1; j < len; ++j) {
+ char letter = argv[i][j];
+ ShortNames::iterator n = _short_names.find(letter);
+ if (n == _short_names.end())
+ throw CommandLineError(string("unrecognized option `-") + letter + "'");
+ Options::iterator o = _options.find(n->second);
+ if (j < len - 1) {
+ if (o->second.type != Atom::BOOL)
+ throw CommandLineError(string("missing value for `-") + letter + "'");
+ o->second.value = true;
+ } else {
+ if (o->second.type == Atom::BOOL) {
+ o->second.value = true;
+ } else {
+ if (++i >= argc)
+ throw CommandLineError(string("missing value for `-") + letter + "'");
+ set_value_from_string(o->second, argv[i]);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void
+Configuration::print(std::ostream& os, const std::string mime_type) const
+{
+ for (Options::const_iterator o = _options.begin(); o != _options.end(); ++o) {
+ const Option& option = o->second;
+ os << o->first << " = " << option.value << endl;
+ }
+}
+
+
+const Raul::Atom&
+Configuration::option(const std::string& long_name)
+{
+ static const Raul::Atom nil;
+ Options::iterator o = _options.find(long_name);
+ if (o == _options.end())
+ return nil;
+ else
+ return o->second.value;
+}
+
+} // namespace Raul
+
diff --git a/src/Maid.cpp b/src/Maid.cpp
index 43a817e..ab0e463 100644
--- a/src/Maid.cpp
+++ b/src/Maid.cpp
@@ -33,10 +33,9 @@ Maid::~Maid()
cleanup();
}
-/** Manage a SharedPtr.
- * NOT realtime safe.
+/** Manage a SharedPtr. NOT realtime safe.
*
- * @ptr is guaranteed to be deleted in the context that calls cleanup()
+ * @a ptr is guaranteed to be deleted in the context that calls cleanup()
*/
void
Maid::manage(SharedPtr<Raul::Deletable> ptr)
diff --git a/src/Path.cpp b/src/Path.cpp
index 6e14076..512d91b 100644
--- a/src/Path.cpp
+++ b/src/Path.cpp
@@ -119,7 +119,7 @@ Path::nameify(const std::basic_string<char>& str)
/** Replace any invalid characters in @a str with a suitable replacement.
*/
void
-Path::replace_invalid_chars(string& str, size_t start, bool replace_slash)
+Path::replace_invalid_chars(std::string& str, size_t start, bool replace_slash)
{
string prefix = str.substr(0, start);
str = str.substr(start);
diff --git a/src/SMFReader.cpp b/src/SMFReader.cpp
index 60775f5..e7866a2 100644
--- a/src/SMFReader.cpp
+++ b/src/SMFReader.cpp
@@ -71,7 +71,7 @@ midi_event_size(unsigned char status)
}
-SMFReader::SMFReader(const string filename)
+SMFReader::SMFReader(const std::string filename)
: _fd(NULL)
, _ppqn(0)
, _track(0)
@@ -90,7 +90,7 @@ SMFReader::~SMFReader()
bool
-SMFReader::open(const string& filename) throw (logic_error, UnsupportedTime)
+SMFReader::open(const std::string& filename) throw (logic_error, UnsupportedTime)
{
if (_fd)
throw logic_error("Attempt to start new read while write in progress.");
diff --git a/src/SMFWriter.cpp b/src/SMFWriter.cpp
index 939e859..bca7c78 100644
--- a/src/SMFWriter.cpp
+++ b/src/SMFWriter.cpp
@@ -62,8 +62,8 @@ SMFWriter::~SMFWriter()
* to write_event will have this value subtracted before writing).
*/
bool
-SMFWriter::start(const string& filename,
- Raul::TimeStamp start_time) throw (logic_error)
+SMFWriter::start(const std::string& filename,
+ Raul::TimeStamp start_time) throw (logic_error)
{
if (_fd)
throw logic_error("Attempt to start new write while write in progress.");
diff --git a/src/Thread.cpp b/src/Thread.cpp
index f5ba09f..0449515 100644
--- a/src/Thread.cpp
+++ b/src/Thread.cpp
@@ -28,7 +28,7 @@ pthread_once_t Thread::_thread_key_once = PTHREAD_ONCE_INIT;
pthread_key_t Thread::_thread_key;
-Thread::Thread(const string& name)
+Thread::Thread(const std::string& name)
: _exit_flag(false)
, _context(0)
, _name(name)
@@ -41,7 +41,7 @@ Thread::Thread(const string& name)
/** Must be called from thread */
-Thread::Thread(pthread_t thread, const string& name)
+Thread::Thread(pthread_t thread, const std::string& name)
: _exit_flag(false)
, _context(0)
, _name(name)
diff --git a/wscript b/wscript
index a386485..ed3f4e7 100644
--- a/wscript
+++ b/wscript
@@ -59,6 +59,7 @@ def build(bld):
# Library
obj = bld.new_task_gen('cxx', 'shlib')
obj.source = '''
+ src/Configuration.cpp
src/Maid.cpp
src/Path.cpp
src/SMFReader.cpp