00001 // Serializer - base class for storing Serializables 00002 // Copyright (C) 2000-2003 bozo & sgbeal @users.sourceforge.net 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 #ifndef _FUN_SERIALIZER_H 00019 #define _FUN_SERIALIZER_H 00020 00021 #include <fun/fun.h> 00022 #include <fun/Serializable.h> 00023 #include <qlist.h> 00024 00025 class QString; 00026 class QColor; 00027 class QPoint; 00028 class QSize; 00029 00030 namespace fun { 00031 00032 // Remove when you can... 00033 #define SERIALIZER_API_COMPAT 1 00034 00035 /** 00036 * Serializer is an abstract base class for objects which can store 00037 * Serializable objects to files or streams. Depending on the subclass' 00038 * implementation, the data may be stored natively, or it may be converted to 00039 * strings, or stuck in a database, etc. 00040 * 00041 * Think of a Serializer as taking key/value pairs of data, where the values 00042 * may be Serializable objects, which implies a tree structure. Duplicate 00043 * keys are allowed, but note that the only way to get at the values for 00044 * duplicate keys in a Deserializer is to use one of the forms of get() which 00045 * takes a reference to a list of Serializables or QStrings. 00046 * 00047 * As Serializer is abstract, subclasses must provide implementations for 00048 * the following methods: 00049 * - put(const QString &key, const QString &val) 00050 * - put(const QString &key, const Serializable &val) 00051 * - setSerializableClass(const char *name) 00052 * Also, setComment() does nothing in the base class. 00053 */ 00054 class Serializer 00055 { 00056 public: 00057 /** 00058 * Creates an empty Serializer node. 00059 */ 00060 Serializer() { } 00061 virtual ~Serializer() { } 00062 00063 /** 00064 * Adds a new element containing the given string value. 00065 * This is one of the methods which subclasses must implement. 00066 */ 00067 virtual void put(const QString &key, const QString &val) = 0; 00068 00069 /** 00070 * Adds a new element containing the given string value. 00071 * (this one is because put(key, "bleh") was calling the bool version!) 00072 */ 00073 void put(const QString &key, const char *val) { put(key, QString(val)); } 00074 00075 /** 00076 * This is just like the string version of put(), except that it 00077 * converts the given int value to a string. 00078 */ 00079 virtual void put(const QString &key, int val); 00080 00081 /** 00082 * This is just like the string version of put(), except that it 00083 * converts the given unsigned int value to a string. 00084 */ 00085 virtual void put(const QString &key, unsigned val); 00086 00087 /** 00088 * This is just like the string version of put(), except that it 00089 * converts the given bool value to a string. 00090 */ 00091 virtual void put(const QString &key, bool val); 00092 00093 /** 00094 * This is just like the string version of put(), except that it 00095 * converts the given float value to a string. 00096 */ 00097 virtual void put(const QString &key, float val); 00098 00099 /** 00100 * This is just like the string version of put(), except that it 00101 * converts the given double value to a string. 00102 */ 00103 virtual void put(const QString &key, double val); 00104 00105 /** 00106 * This is just like the string version of put(), except that it 00107 * converts the given QColor value to a string in the format #rrggbb. 00108 */ 00109 virtual void put(const QString &key, const QColor &val); 00110 00111 /** 00112 * Adds a new element containing the given Serializable value. 00113 * Passing a NULL Serializable here has the same effect as not 00114 * calling it at all. 00115 * 00116 * This is one of the methods which subclasses must implement. 00117 */ 00118 virtual void put(const QString &key, const Serializable *val) = 0; 00119 00120 /** 00121 * Calls put() for each element in the list. 00122 */ 00123 virtual void put(const QString &key, const QPtrList<Serializable> &list); 00124 00125 /** 00126 * Calls put() for each element in the list. To serialize an entire 00127 * std::vector<Serializable *>, call put(key, vec.begin(), vec.end()). 00128 */ 00129 template <class InputIterator> 00130 void put(const QString &key, InputIterator begin, InputIterator end) { while (begin != end) put(key, *begin++); } 00131 00132 /** 00133 * Calls put() for each Serializable element in the list. This is 00134 * because even if Foo is a subclass of Serializable, QPtrList<Foo> 00135 * can't be (or isn't being) treated as a QPtrList<Serializable>. 00136 */ 00137 template <class SC> 00138 void put(const QString &key, const QPtrList<SC> &list); 00139 00140 /** 00141 * Calls put() for each Serializable element in the array of pointers. 00142 * NULL elements in the list will be ignored... nuts, that means you 00143 * can't rely on it to deserialize the same way. OK, how about the 00144 * behavior is undefined in that case, ha ha. 00145 */ 00146 template <class SC> 00147 void put(const QString &key, const SC * const *list, unsigned len); 00148 00149 /** 00150 * Calls put() for each element in the list. Note that in the result 00151 * there may be no way to tell "null" and "empty" strings apart. 00152 */ 00153 virtual void put(const QString &key, const QStringList &list); 00154 00155 /** 00156 * Calls put() for each element in the list. Note that in the result 00157 * there may be no way to tell "null" and "empty" strings apart. 00158 */ 00159 virtual void put(const QString &key, const QString *list, unsigned len); 00160 00161 /** 00162 * This is just like the string version of put(), except that it 00163 * converts the given QPoint value to a string in the format "x,y". 00164 */ 00165 virtual void put(const QString &key, const QPoint &val); 00166 00167 /** 00168 * This is just like the string version of put(), except that it 00169 * converts the given QSize value to a string in the format "x,y". 00170 */ 00171 virtual void put(const QString &key, const QSize &val); 00172 00173 /** 00174 * This sets the name of the Serializable subclass name, so that the same 00175 * class can be instantiated during deserialization. Every Serializable's 00176 * serialize() method should call this with its own class name after 00177 * calling its superclass' serialize(). 00178 * 00179 * This is one of the methods which subclasses must implement. 00180 */ 00181 virtual void setSerializableClass(const char *name) = 0; 00182 00183 /** 00184 * Sets an optional comment which will be associated with a child 00185 * element. Note that if you have multiple elements with the same 00186 * key, you're probably only going to have one comment. 00187 * 00188 * The default base class behavior is to do nothing. 00189 */ 00190 virtual void setComment(const QString &key, const QString &comment); 00191 00192 #if SERIALIZER_API_COMPAT 00193 void putString(const QString &key, const QString &val) { put(key, val); } 00194 void putInt(const QString &key, int val) { put(key, val); } 00195 void putUInt(const QString &key, unsigned val) { put(key, val); } 00196 void putBool(const QString &key, bool val) { put(key, val); } 00197 void putFloat(const QString &key, float val) { put(key, val); } 00198 void putDouble(const QString &key, double val) { put(key, val); } 00199 void putColor(const QString &key, const QColor &val) { put(key, val); } 00200 void putSerializable(const QString &key, const Serializable &val) { put(key, &val); } 00201 void putSerializables(const QString &key, const QPtrList<Serializable> &list) { put(key, list); } 00202 void putStrings(const QString &key, const QStringList &list) { put(key, list); } 00203 void putPoint( const QString &key, const QPoint &val ) { put(key, val); } 00204 void putSize( const QString &key, const QSize &val ) { put(key, val); } 00205 #endif 00206 }; 00207 00208 template <class SC> 00209 void 00210 Serializer::put(const QString &key, const QPtrList<SC> &list) 00211 { 00212 for(QPtrListIterator<SC> it(list); it.current(); ++it) 00213 { 00214 Serializable *sp = dynamic_cast<Serializable *>(it.current()); 00215 if (sp) put(key, sp); 00216 else 00217 { 00218 NOT_DONE("need to warn that non-Serializable object is being ignored?"); 00219 } 00220 } 00221 } 00222 00223 template <class SC> 00224 void 00225 Serializer::put(const QString &key, const SC * const *list, unsigned len) 00226 { 00227 for(unsigned i = 0; i < len; ++i) 00228 { 00229 if (list[i] == NULL) continue; 00230 const Serializable *sp = dynamic_cast<const Serializable *>(list[i]); 00231 if (sp) put(key, sp); 00232 else 00233 { 00234 NOT_DONE("need to warn that non-Serializable object is being ignored?"); 00235 } 00236 } 00237 } 00238 00239 } // namespace fun 00240 00241 #endif // _FUN_SERIALIZER_H