00001 00005 /* Copyright © 2009 James Legg. 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 */ 00011 00012 #ifndef LIBTRACK_CLASS_LOADER_H 00013 #define LIBTRACK_CLASS_LOADER_H 00014 00015 #include <iostream> 00016 #include <map> 00017 #include <vector> 00018 #include <string> 00019 00020 #include <boost/shared_ptr.hpp> 00021 00022 #include "FormErrors.h" 00023 #include "stream_loader.h" 00024 00025 namespace Track 00026 { 00027 00031 class Savable 00032 { 00037 virtual std::string get_class_identifier() const = 0; 00038 }; 00039 00042 class ClassLoaderBase 00043 { 00044 public: 00046 virtual boost::shared_ptr<Savable> create(std::istream & source) const = 0; 00047 00049 virtual std::string get_identifier() const = 0; 00050 }; 00051 00052 template <class T> 00053 class ClassLoader; 00054 00056 const unsigned int latest_class_record_version = 1; 00058 const unsigned int latest_class_record_vector_version = 1; 00059 00063 void register_all_classes_with_savable_class_list(); 00064 00070 class SaveableClassList 00071 { 00072 private: 00073 SaveableClassList(); 00074 SaveableClassList(const SaveableClassList & source); 00075 bool operator=(const SaveableClassList & source); 00076 public: 00078 static SaveableClassList * get_instance(); 00079 00081 template <class T> 00082 void register_class(ClassLoader<T> * loader) 00083 { 00084 loaders.insert(std::pair<std::string, ClassLoader<T> *>(loader->get_identifier(), loader)); 00085 } 00086 00088 template<class T> 00089 boost::shared_ptr<T> load_object(std::istream & source) 00090 { 00091 register_all_classes_with_savable_class_list(); 00092 unsigned int version; 00093 source >> version; 00094 if (version < latest_class_record_version) 00095 { 00096 throw DepreciatedVersionError(); 00097 } 00098 else if (version > latest_class_record_version) 00099 { 00100 throw NewVersionError(); 00101 } 00102 std::string type; 00103 type = string_from_stream(source); 00104 std::map<std::string, ClassLoaderBase *>::iterator it = loaders.find(type); 00105 if (it == loaders.end()) 00106 { 00107 // couldn't find the object, probably a new one. 00108 assert(false); 00109 throw UnkownObjectError(); 00110 } 00111 boost::shared_ptr<T> ptr = boost::dynamic_pointer_cast<T, Savable>(it->second->create(source)); 00112 if (!ptr) 00113 { 00114 // Not a base class of the requested type. 00115 // Classes changed so this is invalid. 00116 assert(false); 00117 throw WrongTypeError(); 00118 } 00119 return ptr; 00120 } 00121 00127 template <class T> 00128 void write_object(std::ostream & destination, const T & object) 00129 { 00130 destination << latest_class_record_version << " "; 00131 string_to_stream(destination, object.get_class_identifier()); 00132 destination << ' ' << object; 00133 } 00134 00137 template <class T> 00138 void fill_vector(std::istream & source, std::vector<boost::shared_ptr<T> > & vector) 00139 { 00140 unsigned int version; 00141 source >> version; 00142 if (version < latest_class_record_vector_version) 00143 { 00144 throw DepreciatedVersionError(); 00145 } 00146 else if (version > latest_class_record_vector_version) 00147 { 00148 throw NewVersionError(); 00149 } 00150 // how many items were saved? 00151 std::size_t size; 00152 source >> size; 00153 vector.reserve(size); 00154 // load each one. 00155 for (unsigned int index = 0; index < size; index++) 00156 { 00157 boost::shared_ptr<T> ptr(load_object<T>(source)); 00158 vector.push_back(ptr); 00159 } 00160 } 00161 00167 template <class Container> 00168 void write_vector(std::ostream & destination, const Container & vector) 00169 { 00170 destination << latest_class_record_vector_version << ' '; 00171 destination << vector.size(); 00172 for (typename Container::const_iterator it = vector.begin(); 00173 it != vector.end(); 00174 it++) 00175 { 00176 destination << ' '; 00177 write_object(destination, **it); 00178 } 00179 } 00180 private: 00181 std::map<std::string, ClassLoaderBase *> loaders; 00182 }; 00183 00191 template <class T> 00192 class ClassLoader 00193 : public ClassLoaderBase 00194 { 00195 public: 00203 ClassLoader(std::string name) 00204 : m_name(name) 00205 { 00206 SaveableClassList::get_instance()->register_class(this); 00207 } 00208 00214 virtual boost::shared_ptr<Savable> create(std::istream & source) const 00215 { 00216 boost::shared_ptr<Savable> result(new T(source)); 00217 return result; 00218 } 00219 00221 virtual std::string get_identifier() const 00222 { 00223 return m_name; 00224 } 00225 protected: 00227 std::string m_name; 00228 }; 00229 00230 } // namespace Track 00231 00232 #endif // LIBTRACK_CLASS_LOADER_H
Generated at Mon Sep 6 00:41:11 2010 by Doxygen version 1.4.7 for Racer version svn335.