Forráskód Böngészése

tools: Refactor Database

Daniele Bartolini 9 éve
szülő
commit
4471107ca1
1 módosított fájl, 403 hozzáadás és 185 törlés
  1. 403 185
      tools/core/database.vala

+ 403 - 185
tools/core/database.vala

@@ -7,134 +7,381 @@ using Gee;
 
 namespace Crown
 {
-	public class Stack
+	public class Database
 	{
-		private ArrayList<Value?> _data;
+		private enum ActionType
+		{
+			CREATE,
+			DESTROY,
+			SET_PROPERTY,
+			ADD_TO_SET,
+			REMOVE_FROM_SET,
+			RESTORE_POINT
+		}
 
-		public Stack()
+		private enum ValueType
 		{
-			_data = new ArrayList<Value?>();
+			NULL,
+			BOOL,
+			DOUBLE,
+			STRING,
+			GUID,
+			VECTOR3,
+			QUATERNION
 		}
 
-		public void push(Value? value)
+		private struct CreateAction
 		{
-			_data.add(value);
+			public Guid id;
 		}
 
-		public Value? pop()
+		private struct DestroyAction
 		{
-			return _data.remove_at(_data.size - 1);
+			public Guid id;
 		}
 
-		public Value? peek()
+		private struct SetPropertyAction
 		{
-			return _data.last();
+			public Guid id;
+			public string key;
+			public Value? val;
 		}
 
-		public int size()
+		private struct AddToSetAction
 		{
-			return _data.size;
+			public Guid id;
+			public string key;
+			public Guid item_id;
 		}
 
-		public void clear()
+		private struct RemoveFromSetAction
 		{
-			_data.clear();
+			public Guid id;
+			public string key;
+			public Guid item_id;
 		}
-	}
 
-	public class Database
-	{
-		private abstract class ChangeAction
+		private struct RestorePoint
 		{
+			public int id;
+			public uint32 size;
+			public Guid[] data;
 		}
 
-		private class CreateAction : ChangeAction
+		private class Stack
 		{
-			public Guid _id;
+			private uint8[] _data;
+			private uint32 _read;
 
-			public CreateAction(Guid id)
+			public Stack()
 			{
-				_id = id;
+				_data = new uint8[1024*1024];
+				_read = 0;
 			}
-		}
 
-		private class DestroyAction : ChangeAction
-		{
-			public Guid _id;
+			public void clear()
+			{
+				_read = 0;
+			}
 
-			public DestroyAction(Guid id)
+			public uint32 size()
 			{
-				_id = id;
+				return _read;
 			}
-		}
 
-		private class SetPropertyAction : ChangeAction
-		{
-			public Guid _id;
-			public string _key;
-			public Value? _value;
+			public void write_data(void* data, ulong len)
+			{
+				uint8* buf = (uint8*)data;
+				for (ulong i = 0; i < len; ++i, ++_read)
+					_data[_read] = buf[i];
+			}
 
-			public SetPropertyAction(Guid id, string key, Value? value)
+			public void write_bool(bool a)
 			{
-				_id = id;
-				_key = key;
-				_value = value;
+				write_data(&a, sizeof(bool));
 			}
-		}
 
-		private class AddToSetAction : ChangeAction
-		{
-			public Guid _id;
-			public string _key;
-			public Guid _item_id;
+			public void write_int(int a)
+			{
+				write_data(&a, sizeof(int));
+			}
 
-			public AddToSetAction(Guid id, string key, Guid item_id)
+			public void write_uint32(uint32 a)
 			{
-				_id = id;
-				_key = key;
-				_item_id = item_id;
+				write_data(&a, sizeof(uint32));
 			}
-		}
 
-		private class RemoveFromSetAction : ChangeAction
-		{
-			public Guid _id;
-			public string _key;
-			public Guid _item_id;
+			public void write_double(double a)
+			{
+				write_data(&a, sizeof(double));
+			}
 
-			public RemoveFromSetAction(Guid id, string key, Guid item_id)
+			public void write_string(string str)
 			{
-				_id = id;
-				_key = key;
-				_item_id = item_id;
+				uint32 len = str.length;
+				write_data(&str.data[0], len);
+				write_data(&len, sizeof(uint32));
+			}
+
+			public void write_guid(Guid a)
+			{
+				write_data(&a, sizeof(Guid));
 			}
-		}
 
-		public delegate void ActionCallback(bool undo, int id, Value? data);
+			public void write_vector3(Vector3 a)
+			{
+				write_data(&a, sizeof(Vector3));
+			}
 
-		private class RestorePoint : ChangeAction
-		{
-			public ActionCallback _undo_redo;
-			public int _id;
-			public Value? _data;
+			public void write_quaternion(Quaternion a)
+			{
+				write_data(&a, sizeof(Quaternion));
+			}
+
+			public void write_action_type(ActionType t)
+			{
+				write_uint32((uint32)t);
+			}
+
+			public void write_value_type(ValueType t)
+			{
+				write_uint32((uint32)t);
+			}
+
+			public ActionType read_action_type()
+			{
+				_read -= (uint32)sizeof(uint32);
+				uint32 a = *(uint32*)(&_data[_read]);
+				return (ActionType)a;
+			}
+
+			public bool read_bool()
+			{
+				_read -= (uint32)sizeof(bool);
+				bool a = *(bool*)(&_data[_read]);
+				return a;
+			}
+
+			public int read_int()
+			{
+				_read -= (uint32)sizeof(int);
+				int a = *(int*)(&_data[_read]);
+				return a;
+			}
+
+			public uint32 read_uint32()
+			{
+				_read -= (uint32)sizeof(uint32);
+				uint32 a = *(uint32*)(&_data[_read]);
+				return a;
+			}
+
+			public double read_double()
+			{
+				_read -= (uint32)sizeof(double);
+				double a = *(double*)(&_data[_read]);
+				return a;
+			}
+
+			public Guid read_guid()
+			{
+				_read -= (uint32)sizeof(Guid);
+				Guid a = *(Guid*)(&_data[_read]);
+				return a;
+			}
+
+			public Vector3 read_vector3()
+			{
+				_read -= (uint32)sizeof(Vector3);
+				Vector3 a = *(Vector3*)(&_data[_read]);
+				return a;
+			}
 
-			public RestorePoint(ActionCallback undo_redo, int id, Value? data)
+			public Quaternion read_quaternion()
 			{
-				_undo_redo = undo_redo;
-				_id = id;
-				_data = data;
+				_read -= (uint32)sizeof(Quaternion);
+				Quaternion a = *(Quaternion*)(&_data[_read]);
+				return a;
 			}
 
-			public void Redo()
+			public string read_string()
 			{
-				if (_undo_redo != null)
-					_undo_redo(false, _id, _data);
+				_read -= (uint32)sizeof(uint32);
+				uint32 len = *(uint32*)(&_data[_read]);
+				_read -= len;
+				uint8[] str = new uint8[len + 1];
+				for (uint32 i = 0; i < len; ++i)
+					str[i] = *(uint8*)(&_data[_read + i]);
+				str[len] = '\0';
+				return (string)str;
 			}
 
-			public void Undo()
+			public ValueType read_value_type()
 			{
-				if (_undo_redo != null)
-					_undo_redo(true, _id, _data);
+				_read -= (uint32)sizeof(uint32);
+				uint32 a = *(uint32*)(&_data[_read]);
+				return (ValueType)a;
+			}
+
+			public void write_create_action(Guid id)
+			{
+				write_guid(id);
+				write_action_type(ActionType.CREATE);
+			}
+
+			public void write_destroy_action(Guid id)
+			{
+				write_guid(id);
+				write_action_type(ActionType.DESTROY);
+			}
+
+			public void write_set_property_action(Guid id, string key, Value? val)
+			{
+				if (val == null)
+				{
+					// Push nothing
+					write_value_type(ValueType.NULL);
+				}
+				else if (val.holds(typeof(bool)))
+				{
+					write_bool((bool)val);
+					write_value_type(ValueType.BOOL);
+				}
+				else if (val.holds(typeof(double)))
+				{
+					write_double((double)val);
+					write_value_type(ValueType.DOUBLE);
+				}
+				else if (val.holds(typeof(string)))
+				{
+					write_string((string)val);
+					write_value_type(ValueType.STRING);
+				}
+				else if (val.holds(typeof(Guid)))
+				{
+					write_guid((Guid)val);
+					write_value_type(ValueType.GUID);
+				}
+				else if (val.holds(typeof(Vector3)))
+				{
+					write_vector3((Vector3)val);
+					write_value_type(ValueType.VECTOR3);
+				}
+				else if (val.holds(typeof(Quaternion)))
+				{
+					write_quaternion((Quaternion)val);
+					write_value_type(ValueType.QUATERNION);
+				}
+
+				write_string(key);
+				write_guid(id);
+				write_action_type(ActionType.SET_PROPERTY);
+			}
+
+			public void write_add_to_set_action(Guid id, string key, Guid item_id)
+			{
+				write_guid(item_id);
+				write_string(key);
+				write_guid(id);
+				write_action_type(ActionType.ADD_TO_SET);
+			}
+
+			public void write_remove_from_set_action(Guid id, string key, Guid item_id)
+			{
+				write_guid(item_id);
+				write_string(key);
+				write_guid(id);
+				write_action_type(ActionType.REMOVE_FROM_SET);
+			}
+
+			public void write_restore_point(int id, uint32 size, Guid[] data)
+			{
+				uint32 num_guids = data.length;
+				for (uint32 i = 0; i < num_guids; ++i)
+					write_guid(data[i]);
+				write_uint32(num_guids);
+				write_uint32(size);
+				write_int(id);
+				write_action_type(ActionType.RESTORE_POINT);
+			}
+
+			public uint32 peek_type()
+			{
+				return *(uint32*)(&_data[_read - (uint32)sizeof(uint32)]);
+			}
+
+			public CreateAction read_create_action()
+			{
+				ActionType t = read_action_type();
+				assert(t == ActionType.CREATE);
+				return { read_guid() };
+			}
+
+			public DestroyAction read_destroy_action()
+			{
+				ActionType t = read_action_type();
+				assert(t == ActionType.DESTROY);
+				return { read_guid() };
+			}
+
+			public SetPropertyAction read_set_property_action()
+			{
+				ActionType t = read_action_type();
+				assert(t == ActionType.SET_PROPERTY);
+
+				Guid id = read_guid();
+				string key = read_string();
+				ValueType type = read_value_type();
+
+				Value? val = null;
+
+				if (type == ValueType.NULL)
+				{
+					// Pop nothing
+				}
+				else if (type == ValueType.BOOL)
+					val = read_bool();
+				else if (type == ValueType.DOUBLE)
+					val = read_double();
+				else if (type == ValueType.STRING)
+					val = read_string();
+				else if (type == ValueType.GUID)
+					val = read_guid();
+				else if (type == ValueType.VECTOR3)
+					val = read_vector3();
+				else if (type == ValueType.QUATERNION)
+					val = read_quaternion();
+				else
+					assert(false);
+
+				return { id, key, val };
+			}
+
+			public AddToSetAction read_add_to_set_action()
+			{
+				ActionType t = read_action_type();
+				assert(t == ActionType.ADD_TO_SET);
+				return { read_guid(), read_string(), read_guid() };
+			}
+
+			public RemoveFromSetAction read_remove_from_set_action()
+			{
+				ActionType t = read_action_type();
+				assert(t == ActionType.REMOVE_FROM_SET);
+				return { read_guid(), read_string(), read_guid() };
+			}
+
+			public RestorePoint read_restore_point()
+			{
+				ActionType t = read_action_type();
+				assert(t == ActionType.RESTORE_POINT);
+				int id = read_int();
+				uint32 size = read_uint32();
+				uint32 num_guids = read_uint32();
+				Guid[] ids = new Guid[num_guids];
+				for (uint32 i = 0; i < num_guids; ++i)
+					ids[i] = read_guid();
+				return { id, size, ids };
 			}
 		}
 
@@ -142,16 +389,21 @@ namespace Crown
 		private HashMap<string, Value?> _data;
 		private Stack _undo;
 		private Stack _redo;
+		private Stack _undo_points;
+		private Stack _redo_points;
 		private bool _changed;
 
 		// Signals
 		public signal void key_changed(Guid id, string key);
+		public signal void undo_redo(bool undo, int id, Guid[] data);
 
 		public Database()
 		{
 			_data = new HashMap<string, Value?>();
 			_undo = new Stack();
 			_redo = new Stack();
+			_undo_points = new Stack();
+			_redo_points = new Stack();
 
 			reset();
 		}
@@ -164,6 +416,8 @@ namespace Crown
 			_data.clear();
 			_undo.clear();
 			_redo.clear();
+			_undo_points.clear();
+			_redo_points.clear();
 
 			_changed = false;
 
@@ -543,7 +797,7 @@ namespace Crown
 			assert(id != GUID_ZERO);
 			assert(!has_object(id));
 
-			_undo.push(new DestroyAction(id));
+			_undo.write_destroy_action(id);
 			_redo.clear();
 
 			create_internal(id);
@@ -577,7 +831,7 @@ namespace Crown
 				}
 			}
 
-			_undo.push(new CreateAction(id));
+			_undo.write_create_action(id);
 			_redo.clear();
 
 			destroy_internal(id);
@@ -590,7 +844,7 @@ namespace Crown
 			assert(is_valid_value(value));
 
 			HashMap<string, Value?> ob = get_data(id);
-			_undo.push(new SetPropertyAction(id, key, ob.has_key(key) ? ob[key] : null));
+			_undo.write_set_property_action(id, key, ob.has_key(key) ? ob[key] : null);
 			_redo.clear();
 
 			set_property_internal(id, key, value);
@@ -603,7 +857,7 @@ namespace Crown
 			assert(item_id != GUID_ZERO);
 			assert(has_object(item_id));
 
-			_undo.push(new RemoveFromSetAction(id, key, item_id));
+			_undo.write_remove_from_set_action(id, key, item_id);
 			_redo.clear();
 
 			add_to_set_internal(id, key, item_id);
@@ -615,7 +869,7 @@ namespace Crown
 			assert(is_valid_key(key));
 			assert(item_id != GUID_ZERO);
 
-			_undo.push(new AddToSetAction(id, key, item_id));
+			_undo.write_add_to_set_action(id, key, item_id);
 			_redo.clear();
 
 			remove_from_set_internal(id, key, item_id);
@@ -663,12 +917,12 @@ namespace Crown
 			return data.keys.to_array();
 		}
 
-		public void add_restore_point(ActionCallback? undo_redo = null, int id = -1, Value? data = null)
+		public void add_restore_point(int id, Guid[] data)
 		{
 #if CROWN_DEBUG
 			stdout.printf("add_restore_point %d\n", id);
 #endif // CROWN_DEBUG
-			_undo.push(new RestorePoint(undo_redo, id, data));
+			_undo_points.write_restore_point(id, _undo.size(), data);
 		}
 
 		/// <summary>
@@ -743,137 +997,101 @@ namespace Crown
 			}
 		}
 
-		public void undo_single_action()
+		public void undo()
 		{
-			RestorePoint begin_action = null;
+			if (_undo_points.size() == 0)
+				return;
 
-			while (true)
-			{
-				if (_undo.size() == 0)
-				{
-					if (begin_action != null)
-					{
-						_redo.push(begin_action);
-						begin_action.Undo();
-					}
-					return;
-				}
+			RestorePoint rp = _undo_points.read_restore_point();
+			_redo_points.write_restore_point(rp.id, _redo.size(), rp.data);
+			undo_until(rp.size);
+			undo_redo(true, rp.id, rp.data);
+		}
 
-				Value? action = _undo.peek();
-				if (action.holds(typeof(RestorePoint)))
-				{
-					if (begin_action == null)
-					{
-						begin_action = (RestorePoint)action;
-						_undo.pop();
-						continue;
-					}
-					else
-					{
-						_redo.push(begin_action);
-						begin_action.Undo();
-						return;
-					}
-				}
-				else if (action.holds(typeof(CreateAction)))
+		public void redo()
+		{
+			if (_redo_points.size() == 0)
+				return;
+
+			RestorePoint rp = _redo_points.read_restore_point();
+			_undo_points.write_restore_point(rp.id, _undo.size(), rp.data);
+			redo_until(rp.size);
+			undo_redo(false, rp.id, rp.data);
+		}
+
+		private void undo_until(uint32 size)
+		{
+			while (_undo.size() != size)
+			{
+				uint32 type = _undo.peek_type();
+				if (type == ActionType.CREATE)
 				{
-					CreateAction a = (action as CreateAction);
-					_redo.push(new DestroyAction(a._id));
-					create_internal(a._id);
+					CreateAction a = _undo.read_create_action();
+					_redo.write_destroy_action(a.id);
+					create_internal(a.id);
 				}
-				else if (action.holds(typeof(DestroyAction)))
+				else if (type == ActionType.DESTROY)
 				{
-					DestroyAction a = (action as DestroyAction);
-					_redo.push(new CreateAction(a._id));
-					destroy_internal(a._id);
+					DestroyAction a = _undo.read_destroy_action();
+					_redo.write_create_action(a.id);
+					destroy_internal(a.id);
 				}
-				else if (action.holds(typeof(SetPropertyAction)))
+				else if (type == ActionType.SET_PROPERTY)
 				{
-					SetPropertyAction a = (action as SetPropertyAction);
-					_redo.push(new SetPropertyAction(a._id, a._key, get_data(a._id).has_key(a._key) ? get_data(a._id)[a._key] : null));
-					set_property_internal(a._id, a._key, a._value);
+					SetPropertyAction a = _undo.read_set_property_action();
+					_redo.write_set_property_action(a.id, a.key, get_data(a.id).has_key(a.key) ? get_data(a.id)[a.key] : null);
+					set_property_internal(a.id, a.key, a.val);
 				}
-				else if (action.holds(typeof(AddToSetAction)))
+				else if (type == ActionType.ADD_TO_SET)
 				{
-					AddToSetAction a = (action as AddToSetAction);
-					_redo.push(new RemoveFromSetAction(a._id, a._key, a._item_id));
-					add_to_set_internal(a._id, a._key, a._item_id);
+					AddToSetAction a = _undo.read_add_to_set_action();
+					_redo.write_remove_from_set_action(a.id, a.key, a.item_id);
+					add_to_set_internal(a.id, a.key, a.item_id);
 				}
-				else if (action.holds(typeof(RemoveFromSetAction)))
+				else if (type == ActionType.REMOVE_FROM_SET)
 				{
-					RemoveFromSetAction a = (action as RemoveFromSetAction);
-					_redo.push(new AddToSetAction(a._id, a._key, a._item_id));
-					remove_from_set_internal(a._id, a._key, a._item_id);
+					RemoveFromSetAction a = _undo.read_remove_from_set_action();
+					_redo.write_add_to_set_action(a.id, a.key, a.item_id);
+					remove_from_set_internal(a.id, a.key, a.item_id);
 				}
-
-				_undo.pop();
 			}
 		}
 
-		public void redo_single_action()
+		private void redo_until(uint32 size)
 		{
-			RestorePoint begin_action = null;
-
-			while (true)
+			while (_redo.size() != size)
 			{
-				if (_redo.size() == 0)
+				uint32 type = _redo.peek_type();
+				if (type == ActionType.CREATE)
 				{
-					if (begin_action != null)
-					{
-						_undo.push(begin_action);
-						begin_action.Redo();
-					}
-					return;
+					CreateAction a = _redo.read_create_action();
+					_undo.write_destroy_action(a.id);
+					create_internal(a.id);
 				}
-
-				Value? action = _redo.peek();
-				if (action.holds(typeof(RestorePoint)))
+				else if (type == ActionType.DESTROY)
 				{
-					if (begin_action == null)
-					{
-						begin_action = (RestorePoint)action;
-						_redo.pop();
-						continue;
-					}
-					else
-					{
-						_undo.push(begin_action);
-						begin_action.Redo();
-						return;
-					}
+					DestroyAction a = _redo.read_destroy_action();
+					_undo.write_create_action(a.id);
+					destroy_internal(a.id);
 				}
-				else if (action.holds(typeof(CreateAction)))
+				else if (type == ActionType.SET_PROPERTY)
 				{
-					CreateAction a = (action as CreateAction);
-					_undo.push(new DestroyAction(a._id));
-					create_internal(a._id);
+					SetPropertyAction a = _redo.read_set_property_action();
+					_undo.write_set_property_action(a.id, a.key, get_data(a.id).has_key(a.key) ? get_data(a.id)[a.key] : null);
+					set_property_internal(a.id, a.key, a.val);
 				}
-				else if (action.holds(typeof(DestroyAction)))
+				else if (type == ActionType.ADD_TO_SET)
 				{
-					DestroyAction a = (action as DestroyAction);
-					_undo.push(new CreateAction(a._id));
-					destroy_internal(a._id);
+					AddToSetAction a = _redo.read_add_to_set_action();
+					_undo.write_remove_from_set_action(a.id, a.key, a.item_id);
+					add_to_set_internal(a.id, a.key, a.item_id);
 				}
-				else if (action.holds(typeof(SetPropertyAction)))
+				else if (type == ActionType.REMOVE_FROM_SET)
 				{
-					SetPropertyAction a = (action as SetPropertyAction);
-					_undo.push(new SetPropertyAction(a._id, a._key, get_data(a._id).has_key(a._key) ? get_data(a._id)[a._key] : null));
-					set_property_internal(a._id, a._key, a._value);
+					RemoveFromSetAction a = _redo.read_remove_from_set_action();
+					_undo.write_add_to_set_action(a.id, a.key, a.item_id);
+					remove_from_set_internal(a.id, a.key, a.item_id);
 				}
-				else if (action.holds(typeof(AddToSetAction)))
-				{
-					AddToSetAction a = (action as AddToSetAction);
-					_undo.push(new RemoveFromSetAction(a._id, a._key, a._item_id));
-					add_to_set_internal(a._id, a._key, a._item_id);
-				}
-				else if (action.holds(typeof(RemoveFromSetAction)))
-				{
-					RemoveFromSetAction a = (action as RemoveFromSetAction);
-					_undo.push(new AddToSetAction(a._id, a._key, a._item_id));
-					remove_from_set_internal(a._id, a._key, a._item_id);
-				}
-
-				_redo.pop();
 			}
 		}
 	}