//+----------------------------------------------------------------------------+ //| Description: Magic Set Editor - Program to make Magic (tm) cards | //| Copyright: (C) 2001 - 2009 Twan van Laarhoven and Sean Hunt | //| License: GNU General Public License 2 or later (see file COPYING) | //+----------------------------------------------------------------------------+ #ifndef HEADER_UTIL_IO_WRITER #define HEADER_UTIL_IO_WRITER // ----------------------------------------------------------------------------- : Includes #include #include template class Defaultable; template class Scriptable; DECLARE_POINTER_TYPE(Game); DECLARE_POINTER_TYPE(StyleSheet); // ----------------------------------------------------------------------------- : Writer typedef wxOutputStream OutputStream; typedef shared_ptr OutputStreamP; /// The Writer can be used for writing (serializing) objects class Writer { public: /// Construct a writer that writes to the given output stream Writer(const OutputStreamP& output, Version file_app_version); /// Tell the reflection code we are not reading inline bool reading() const { return false; } inline bool scripting() const { return false; } inline bool isComplex() const { return true; } inline void addAlias(int, const Char*, const Char*) {} inline void handleIgnore(int, const Char*) {} // --------------------------------------------------- : Handling objects /// Handle an object: write it under the given name template void handle(const Char* name, const T& object) { enterBlock(name); handle(object); exitBlock(); } /// Handle a value template inline void handleNoScript(const Char* name, T& value) { handle(name,value); } /// Write a vector to the output stream template void handle(const Char* name, const vector& vector); /// Write a string to the output stream void handle(const String& str); void handle(const Char* str) { handle(String(str)); } /// Write an object of type T to the output stream template void handle(const T&); /// Write a intrusive_ptr to the output stream template void handle(const intrusive_ptr&); /// Write a map to the output stream template void handle(const map&); /// Write an IndexMap to the output stream template void handle(const IndexMap&); template void handle(const DelayedIndexMaps&); template void handle(const DelayedIndexMapsData&); /// Write an object of type Defaultable to the output stream template void handle(const Defaultable&); /// Write an object of type Scriptable to the output stream template void handle(const Scriptable&); // special behaviour void handle(const GameP&); void handle(const StyleSheetP&); private: // --------------------------------------------------- : Data /// Indentation of the current block int indentation; /// Blocks opened to which nothing has been written vector pending_opened; /// Output stream we are writing to OutputStreamP output; /// Text stream wrapping the output stream wxTextOutputStream stream; // --------------------------------------------------- : Writing to the stream /// Start a new block with the given name void enterBlock(const Char* name); /// Leave the block we are in void exitBlock(); /// Write the pending_opened with the required indentation void writePending(); /// Output some taps to represent the indentation level void writeIndentation(); }; // ----------------------------------------------------------------------------- : Container types template void Writer::handle(const Char* name, const vector& vec) { String vectorKey = singular_form(name); for (typename vector::const_iterator it = vec.begin() ; it != vec.end() ; ++it) { handle(vectorKey, *it); } } template void Writer::handle(const intrusive_ptr& pointer) { if (pointer) handle(*pointer); } template void Writer::handle(const map& m) { for (typename map::const_iterator it = m.begin() ; it != m.end() ; ++it) { handle(it->first.c_str(), it->second); } } template void Writer::handle(const IndexMap& m) { for (typename IndexMap::const_iterator it = m.begin() ; it != m.end() ; ++it) { handle(get_key_name(*it).c_str(), *it); } } // ----------------------------------------------------------------------------- : Reflection /// Implement reflection as used by Writer #define REFLECT_OBJECT_WRITER(Cls) \ template<> void Writer::handle(const Cls& object) { \ const_cast(object).reflect(*this); \ } \ void Cls::reflect(Writer& writer) { \ reflect_impl(writer); \ } // ----------------------------------------------------------------------------- : Reflection for enumerations /// Implement enum reflection as used by Writer #define REFLECT_ENUM_WRITER(Enum) \ template<> void Writer::handle(const Enum& enum_) { \ EnumWriter writer(*this); \ reflect_ ## Enum(const_cast(enum_), writer); \ } /// 'Tag' to be used when reflecting enumerations for Writer class EnumWriter { public: inline EnumWriter(Writer& writer) : writer(writer) {} /// Handle a possible value for the enum, if the name matches the name in the input template inline void handle(const Char* name, Enum value, Enum enum_) { if (enum_ == value) { writer.handle(name); } } private: Writer& writer; ///< The writer to write output to }; // ----------------------------------------------------------------------------- : EOF #endif