[Scummvm-cvs-logs] SF.net SVN: scummvm:[40306] scummvm/trunk/engines/sci/engine

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Mon May 4 17:05:11 CEST 2009


Revision: 40306
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40306&view=rev
Author:   fingolfin
Date:     2009-05-04 15:05:11 +0000 (Mon, 04 May 2009)

Log Message:
-----------
SCI: Unified serializing code for Table subclasses, using template specialization. This whole syncWithSerializer / DefaultSyncer / ArraySyncer code is experimental work in progress ;)

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/savegame.cpp
    scummvm/trunk/engines/sci/engine/vm.h

Modified: scummvm/trunk/engines/sci/engine/savegame.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/savegame.cpp	2009-05-04 15:04:55 UTC (rev 40305)
+++ scummvm/trunk/engines/sci/engine/savegame.cpp	2009-05-04 15:05:11 UTC (rev 40306)
@@ -93,55 +93,64 @@
 }
 
 
+// Experimental hack: Use syncWithSerializer to sync. By default, this assume
+// the object to be synced is a subclass of Serializable and thus tries to invoke
+// the saveLoadWithSerializer() method. But it is possible to specialize this
+// template function to handle stuff that is not implementing that interface.
+template<typename T>
+void syncWithSerializer(Common::Serializer &s, T &obj) {
+	obj.saveLoadWithSerializer(s);
+}
+
+// By default, sync using syncWithSerializer, which in turn can easily be overloaded.
+template <typename T>
+struct DefaultSyncer : Common::BinaryFunction<Common::Serializer, T, void> {
+	void operator()(Common::Serializer &s, T &obj) const {
+		//obj.saveLoadWithSerializer(s);
+		syncWithSerializer(s, obj);
+	}
+};
+
 /**
  * Sync a Common::Array using a Common::Serializer.
  * When saving, this writes the length of the array, then syncs (writes) all entries.
  * When loading, it loads the length of the array, then resizes it accordingly, before
  * syncing all entries.
  *
- * TODO: Right now, this can only sync arrays containing objects which subclass Serializable.
- * To sync arrays containing e.g. ints, we have to tell it how to sync those. There are
- * ways to do that, I just haven't decided yet how to approach it. One way would be to use
- * the same preprocessors tricks as in common/serializer.h. Another is to rely on template
- * specialization (that one could be rather elegant, in fact).
- * 
+ * Note: This shouldn't be in common/array.h nor in common/serializer.h, after
+ * all, not all code using arrays wants to use the serializer, and vice versa.
+ * But we could put this into a separate header file in common/ at some point.
+ * Something like common/serializer-extras.h or so.
  *
- * Note: I didn't add this as a member method to Common::Array (and subclass that from Serializable)
- * on purpose, as not all code using Common::Array wants to do deal with serializers...
- *
  * TODO: Add something like this for lists, queues....
  */
-template<typename T>
-void syncArray(Common::Serializer &s, Common::Array<T> &arr) {
-	uint len = arr.size();
-	s.syncAsUint32LE(len);
+template <typename T, class Syncer = DefaultSyncer<T> >
+struct ArraySyncer : Common::BinaryFunction<Common::Serializer, T, void> {
+	void operator()(Common::Serializer &s, Common::Array<T> &arr) const {
+		uint len = arr.size();
+		s.syncAsUint32LE(len);
+		Syncer sync;
 
-	// Resize the array if loading.
-	if (s.isLoading())
-		arr.resize(len);
+		// Resize the array if loading.
+		if (s.isLoading())
+			arr.resize(len);
 
-	typename Common::Array<T>::iterator i;
-	for (i = arr.begin(); i != arr.end(); ++i) {
-		i->saveLoadWithSerializer(s);
+		typename Common::Array<T>::iterator i;
+		for (i = arr.begin(); i != arr.end(); ++i) {
+			sync(s, *i);
+		}
 	}
-}
+};
 
+// Convenience wrapper
 template<typename T>
-void syncArray(Common::Serializer &s, Common::Array<T> &arr, const Common::Functor2<Common::Serializer &, T &, void> &func) {
-	uint len = arr.size();
-	s.syncAsUint32LE(len);
-
-	// Resize the array if loading.
-	if (s.isLoading())
-		arr.resize(len);
-
-	typename Common::Array<T>::iterator i;
-	for (i = arr.begin(); i != arr.end(); ++i) {
-		func(s, *i);
-	}
+void syncArray(Common::Serializer &s, Common::Array<T> &arr) {
+	ArraySyncer<T> sync;
+	sync(s, arr);
 }
 
 
+
 void MenuItem::saveLoadWithSerializer(Common::Serializer &s) {
 	s.syncAsSint32LE(_type);
 	s.syncString(_keytext);
@@ -211,7 +220,8 @@
 
 
 
-static void sync_Class(Common::Serializer &s, Class &obj) {
+template <>
+void syncWithSerializer(Common::Serializer &s, Class &obj) {
 	s.syncAsSint32LE(obj.script);
 	sync_reg_t(s, obj.reg);
 }
@@ -252,8 +262,7 @@
 	sync_SegManagerPtr(s, seg_manager);
 
 
-	Common::Functor2Fun<Common::Serializer &, Class &, void> tmp(sync_Class);
-	syncArray<Class>(s, _classtable, tmp);
+	syncArray<Class>(s, _classtable);
 
 	sync_sfx_state_t(s, sound);
 }
@@ -281,73 +290,40 @@
 		sync_reg_t(s, obj.variables[i]);
 }
 
-static void sync_Clone(Common::Serializer &s, Clone &obj) {
+template <>
+void syncWithSerializer(Common::Serializer &s, Clone &obj) {
 	sync_Object(s, obj);
 }
 
-static void sync_List(Common::Serializer &s, List &obj) {
+template <>
+void syncWithSerializer(Common::Serializer &s, List &obj) {
 	sync_reg_t(s, obj.first);
 	sync_reg_t(s, obj.last);
 }
 
-static void sync_Node(Common::Serializer &s, Node &obj) {
+template <>
+void syncWithSerializer(Common::Serializer &s, Node &obj) {
 	sync_reg_t(s, obj.pred);
 	sync_reg_t(s, obj.succ);
 	sync_reg_t(s, obj.key);
 	sync_reg_t(s, obj.value);
 }
 
-static void sync_CloneEntry(Common::Serializer &s, CloneTable::Entry &obj) {
-	s.syncAsSint32LE(obj.next_free);
-	sync_Clone(s, obj);
-}
-
-static void sync_CloneTable(Common::Serializer &s, CloneTable &obj) {
+template <typename T>
+static void sync_Table(Common::Serializer &s, T &obj) {
 	s.syncAsSint32LE(obj.entries_nr);
 	s.syncAsSint32LE(obj.first_free);
 	s.syncAsSint32LE(obj.entries_used);
 	s.syncAsSint32LE(obj.max_entry);
 
 	if (!obj.table && obj.entries_nr)
-		obj.table = (CloneTable::Entry *)sci_calloc(obj.entries_nr, sizeof(CloneTable::Entry));
-	for (int i = 0; i < obj.entries_nr; ++i)
-		sync_CloneEntry(s, obj.table[i]);
+		obj.table = (typename T::Entry *)sci_calloc(obj.entries_nr, sizeof(typename T::Entry));
+	for (int i = 0; i < obj.entries_nr; ++i) {
+		s.syncAsSint32LE(obj.table[i].next_free);
+		syncWithSerializer<typename T::value_type>(s, obj.table[i]);
+	}
 }
 
-static void sync_ListEntry(Common::Serializer &s, ListTable::Entry &obj) {
-	s.syncAsSint32LE(obj.next_free);
-	sync_List(s, obj);
-}
-
-static void sync_ListTable(Common::Serializer &s, ListTable &obj) {
-	s.syncAsSint32LE(obj.entries_nr);
-	s.syncAsSint32LE(obj.first_free);
-	s.syncAsSint32LE(obj.entries_used);
-	s.syncAsSint32LE(obj.max_entry);
-
-	if (!obj.table && obj.entries_nr)
-		obj.table = (ListTable::Entry *)sci_calloc(obj.entries_nr, sizeof(ListTable::Entry));
-	for (int i = 0; i < obj.entries_nr; ++i)
-		sync_ListEntry(s, obj.table[i]);
-}
-
-static void sync_NodeEntry(Common::Serializer &s, NodeTable::Entry &obj) {
-	s.syncAsSint32LE(obj.next_free);
-	sync_Node(s, obj);
-}
-
-static void sync_NodeTable(Common::Serializer &s, NodeTable &obj) {
-	s.syncAsSint32LE(obj.entries_nr);
-	s.syncAsSint32LE(obj.first_free);
-	s.syncAsSint32LE(obj.entries_used);
-	s.syncAsSint32LE(obj.max_entry);
-
-	if (!obj.table && obj.entries_nr)
-		obj.table = (NodeTable::Entry *)sci_calloc(obj.entries_nr, sizeof(NodeTable::Entry));
-	for (int i = 0; i < obj.entries_nr; ++i)
-		sync_NodeEntry(s, obj.table[i]);
-}
-
 static void sync_Script(Common::Serializer &s, Script &obj) {
 	s.syncAsSint32LE(obj.nr);
 	s.syncAsUint32LE(obj.buf_size);
@@ -453,7 +429,7 @@
 		sync_Script(s, *(Script *)mobj);
 		break;
 	case MEM_OBJ_CLONES:
-		sync_CloneTable(s, *(CloneTable *)mobj);
+		sync_Table<CloneTable>(s, *(CloneTable *)mobj);
 		break;
 	case MEM_OBJ_LOCALS:
 		sync_LocalVariables(s, *(LocalVariables *)mobj);
@@ -477,10 +453,10 @@
 	case MEM_OBJ_STRING_FRAG:
 		break;
 	case MEM_OBJ_LISTS:
-		sync_ListTable(s, *(ListTable *)mobj);
+		sync_Table<ListTable>(s, *(ListTable *)mobj);
 		break;
 	case MEM_OBJ_NODES:
-		sync_NodeTable(s, *(NodeTable *)mobj);
+		sync_Table<NodeTable>(s, *(NodeTable *)mobj);
 		break;
 	case MEM_OBJ_DYNMEM:
 		sync_DynMem(s, *(DynMem *)mobj);

Modified: scummvm/trunk/engines/sci/engine/vm.h
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.h	2009-05-04 15:04:55 UTC (rev 40305)
+++ scummvm/trunk/engines/sci/engine/vm.h	2009-05-04 15:05:11 UTC (rev 40306)
@@ -394,6 +394,7 @@
 
 template<typename T, int INITIAL, int INCREMENT>
 struct Table : public MemObject {
+	typedef T value_type;
 	struct Entry : public T {
 		int next_free; /* Only used for free entries */
 	};


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list