#ifndef ICL_DATA_STORE_H #define ICL_DATA_STORE_H #include #include namespace icl{ /// Extension of the associative container MultiTypeMap \ingroup UNCOMMON /** Adds an index operator[string] for direct access to contained values */ class DataStore : public MultiTypeMap{ public: /// Internal Exception type thrown if operator[] is given an unknown index string struct KeyNotFoundException : public ICLException{ KeyNotFoundException(const std::string &key):ICLException("Key not found: " + key){} }; /// Internal Exception type thrown if Data::operator= is called for incompatible values struct UnassignableTypesException : public ICLException{ UnassignableTypesException(const std::string &tSrc, const std::string &tDst): ICLException("Unable to assign "+ tDst+ " = "+ tSrc){} }; /// Arbitrary Data encapsulation type class Data{ /// internally reference DataStore entry DataArray *data; /// Constructor (private->only the parent DataStore is allowed to contruct Data's) inline Data(DataArray *data):data(data){} /// This is the mighty and magic conversion function static void assign(void *src, const std::string &srcType, void *dst, const std::string &dstType) throw (UnassignableTypesException); public: /// Internally used Data- Structure struct Event{ Event(const std::string &msg="", void *data=0):message(msg),data(data){} std::string message; void *data; }; friend class DataStore; /// Trys to assign an instance of T to this Data-Element /** This will only work, if the data types are assignable */ template inline void operator=(const T &t) throw (UnassignableTypesException){ assign(const_cast(reinterpret_cast(&t)), get_type_name(),data->data,data->type); } /// Trys to convert a Data element into a (by template parameter) given type /** this will only work, if the data element is convertable to the desired type. Otherwise an exception is thrown*/ template inline T as() const throw (UnassignableTypesException){ T t; assign(data->data,data->type,&t,get_type_name()); return t; } /// returns the internal type ID (obtained by C++'s RTTI) const std::string &getTypeID() const { return data->type; } /// this is necessary for some gui components /** Currently supported for Data-types ImageHandle, DrawHandle and FPSHandle */ void update() throw (UnassignableTypesException){ *this = Event("update"); } void install(void *data){ *this = Event("install",data); } }; /// Allows to assign new values to a entry with given key (*NEW*) /** The returned Data-Element is a shallow Reference of a DataStore entry of internal type DataArray. Each entry is typed by C++'s RTTI, so, the function can determine if the assigned value is compatible to actual type of the data element. Internally a magic assignment system is used to determine whether two types can be assigned, and what to do if. Basically one can say, type assignments line T = T are of course allowed as well as type assignments A = B, if A and B are C++ built-in numerical type (int, float, etc.) Additionally a lot of GUIHandle types (contained by a GUI's DataStore) can be assigned (and updated, see void DataStore::Data::update()) with this mechanism A detailed description of all allowed assigmnet must ba added here: TODO... Here are some examples ... \code DataStore x; x.allocValue("hello",int(5)); x.allocValue("world",float(5)); x.allocValue("!",std::string("yes yes!")); x["hello"] = "44"; // string to int x["world"] = 4; // int to float x["!"] = 44; // int to string x["hello"] = 44; // int to int x.allocValue("image",ImgHandle(...)); x["image"] = icl::create("parrot"); // ImgQ to ImageHandle x.allocValue("sl",SliderHandle(...)); x["sl"] = 7; // sets slider value to 7 std::cout << "slider val is:" << x["sl"].as() << std::endl; x["sl"] = Range32s(3,9); // sets slider's Range ... \endcode */ Data operator[](const std::string &key) throw (KeyNotFoundException); }; } #endif