ClassLoader.h

Go to the documentation of this file.
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

Get Racer at SourceForge.net. Fast, secure and Free Open Source software downloads

Generated at Mon Sep 6 00:41:11 2010 by Doxygen version 1.4.7 for Racer version svn335.