00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef __GLOVE_DEVICES_DEVICEMANAGER_H_
00028 #define __GLOVE_DEVICES_DEVICEMANAGER_H_
00029
00030 #include "../config.hpp"
00031
00032 #include <iostream>
00033 #include <sstream>
00034 #include <string>
00035 #include <vector>
00036 #include <map>
00037 #include <stdexcept>
00038
00039 #include <boost/cast.hpp>
00040 #include <boost/exception.hpp>
00041 #include <boost/config/warning_disable.hpp>
00042 #include <boost/spirit/include/qi.hpp>
00043 #include <boost/spirit/include/phoenix.hpp>
00044 #include <boost/fusion/include/adapt_struct.hpp>
00045 #include <boost/fusion/include/io.hpp>
00046
00047 #include "Device.hpp"
00048
00049 BOOST_FUSION_ADAPT_STRUCT(
00050 glove::devices::device_info,
00051 (int, id)
00052 (std::string, name)
00053 (std::string, type)
00054 (std::string, description)
00055 )
00056
00057 namespace glove {
00058 namespace devices {
00059
00068 template<typename DeviceType>
00069 class API DeviceManager {
00070 protected:
00072 std::map<std::string, DeviceType*> devices;
00073
00074 public:
00078 DeviceManager() {
00079 }
00080
00084 virtual ~DeviceManager() {
00085 typename std::map<std::string, DeviceType*>::iterator itr;
00086 for (itr = devices.begin(); itr != devices.end(); ++itr) {
00087 delete itr->second;
00088 }
00089 }
00090
00098 DeviceType& getDevice(const std::string& key) {
00099 typename std::map<std::string, DeviceType*>::iterator match = devices.find(key);
00100 if (match == devices.end()) {
00101 std::ostringstream oss;
00102 oss << "Illegal device id '" << key << "'";
00103 boost::throw_exception(std::invalid_argument(oss.str()));
00104 }
00105 return *match->second;
00106 }
00107
00117 template<typename T>
00118 T& getDevice(const std::string& key) {
00119 return *boost::polymorphic_cast<T*>(&getDevice(key));
00120 }
00121
00129 DeviceType& operator[](const std::string& key) {
00130 return getDevice(key);
00131 }
00132
00140 DeviceType& getDevice(const int id) {
00141 if (id < 0 && (size_t) id >= devices.size()) {
00142 boost::throw_exception(std::invalid_argument("Illegal device id"));
00143 }
00144 typename std::map<std::string, DeviceType*>::iterator itr = devices.begin();
00145 for (int i = 0; i < id; i++, itr++)
00146 ;
00147 return *itr->second;
00148 }
00149
00158 template<typename T>
00159 T& getDevice(const int id) {
00160 return *boost::polymorphic_cast<T*>(&getDevice(id));
00161 }
00162
00177 template<typename T>
00178 T& getDevice(const int id, const std::string& type) {
00179 Device& d = getDevice(id);
00180 if (d.getTypeIdentifier() != type) {
00181 std::ostringstream oss;
00182 oss << "This is not a '" << type << "' device.";
00183 boost::throw_exception(std::invalid_argument(oss.str()));
00184 }
00185 return *boost::polymorphic_cast<T*>(&getDevice(id));
00186 }
00187
00195 DeviceType& operator[](const int key) {
00196 return getDevice(key);
00197 }
00198
00203 std::size_t numDevices() const {
00204 return devices.size();
00205 }
00206
00219 const std::vector<std::string> getDeviceList() {
00220 std::vector<std::string> v;
00221
00222 int i = 0;
00223 typename std::map<std::string, DeviceType*>::iterator itr;
00224 for (itr = devices.begin(); itr != devices.end(); ++itr, i++) {
00225 std::ostringstream oss;
00226 oss << "[" << i << "] " << itr->first << " (" << itr->second->getTypeIdentifier() << "): "
00227 << itr->second->toString();
00228 v.push_back(oss.str());
00229 }
00230 return v;
00231 }
00232
00240 virtual std::string toString() {
00241 std::ostringstream oss;
00242
00243 size_t i = 0;
00244 const std::vector<std::string> v = getDeviceList();
00245 std::vector<std::string>::const_iterator itr;
00246 for (itr = v.begin(); itr != v.end(); ++itr, i++) {
00247 oss << *itr;
00248
00249
00250 if (i < devices.size() - 1) {
00251 oss << std::endl;
00252 }
00253 }
00254 return oss.str();
00255 }
00256
00265 template<typename Iterator>
00266 struct DeviceGrammar: boost::spirit::qi::grammar<Iterator, device_info()> {
00267 boost::spirit::qi::rule<Iterator, device_info()> start;
00268 boost::spirit::qi::rule<Iterator, std::string()> string_;
00269 boost::spirit::qi::rule<Iterator, std::string()> string_wo_space;
00270 boost::spirit::qi::rule<Iterator, std::string()> string_wo_rbrace;
00271 boost::spirit::qi::rule<Iterator, std::string()> name;
00272 boost::spirit::qi::rule<Iterator, std::string()> type;
00273
00277 DeviceGrammar() :
00278 DeviceGrammar::base_type(start) {
00279
00280 using boost::spirit::eps;
00281 using boost::spirit::lit;
00282 using boost::spirit::int_;
00283 using boost::spirit::char_;
00284 using boost::spirit::lexeme;
00285 using boost::phoenix::push_back;
00286 using boost::phoenix::construct;
00287 namespace arg = boost::spirit::arg_names;
00288
00289 string_ %= lexeme[+char_];
00290 string_wo_space %= lexeme[+(char_ - ' ')];
00291 string_wo_rbrace %= lexeme[+(char_ - ')')];
00292
00293 name = +(string_wo_space[arg::_val += arg::_1] >> (&lit(" (") | lit(" ")[arg::_val += " "]));
00294 type
00295 = +(string_wo_rbrace[arg::_val += arg::_1] >> (&lit("): ") | lit(")")[arg::_val += ")"]));
00296
00297 start %= lit("[") >> int_ >> lit("] ") >> name >> lit(" (") >> type >> lit("): ") >> string_;
00298 }
00299 };
00300
00310 static device_info parseDeviceInfo(std::string str) {
00311 static DeviceGrammar<std::string::const_iterator> deviceGrammar;
00312
00313 device_info result;
00314 std::string::const_iterator begin = str.begin();
00315 std::string::const_iterator end = str.end();
00316
00317 if (!boost::spirit::qi::parse(begin, end, deviceGrammar, result)) {
00318 boost::throw_exception(std::runtime_error("Illegal device info string"));
00319 }
00320 return result;
00321 }
00322 };
00323
00324 }
00325 }
00326
00327 #endif