[retro-gtk] retro-gobject: Refactor serialization functions



commit 7705f99bb1c126da24ae69a762b3ff5d077b797b
Author: Adrien Plazas <kekun plazas laposte net>
Date:   Wed Jan 25 18:11:07 2017 +0100

    retro-gobject: Refactor serialization functions
    
    https://bugzilla.gnome.org/show_bug.cgi?id=777489

 retro-gobject/core-error.vala |    7 +++
 retro-gobject/core.vala       |   51 ++-----------------
 retro-gobject/retro-core.c    |  110 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 121 insertions(+), 47 deletions(-)
---
diff --git a/retro-gobject/core-error.vala b/retro-gobject/core-error.vala
new file mode 100644
index 0000000..46ff478
--- /dev/null
+++ b/retro-gobject/core-error.vala
@@ -0,0 +1,7 @@
+// This file is part of Retro. License: GPLv3
+
+public errordomain Retro.CoreError {
+       COULDNT_SERIALIZE,
+       COULDNT_DESERIALIZE,
+       SERIALIZATION_NOT_SUPPORTED,
+}
diff --git a/retro-gobject/core.vala b/retro-gobject/core.vala
index f882553..224e9c4 100644
--- a/retro-gobject/core.vala
+++ b/retro-gobject/core.vala
@@ -313,55 +313,12 @@ public class Core : Object {
                pop_cb_data ();
        }
 
-       /**
-        * Returns the amount of data the implementation requires to serialize
-        * the internal state.
-        *
-        * Beetween calls to {@link load_game} and
-        * {@link unload_game}, the returned size is never allowed to
-        * be larger than a previous returned value, to ensure that the frontend can
-        * allocate a save state buffer once.
-        *
-        * @return the size needed to serialize the internal state
-        */
-       public size_t serialize_size () {
-               push_cb_data ();
-               var result = module.serialize_size ();
-               pop_cb_data ();
-
-               return result;
-       }
-
-       /**
-        * Serializes the internal state.
-        *
-        * If failed, or size is lower than {@link serialize_size}, it
-        * should return false, true otherwise.
-        *
-        * @param data the buffer where the data will be stored
-        * @return false if the serialization failed, true otherwise
-        */
-       public bool serialize ([CCode (array_length_type = "gsize")] uint8[] data) {
-               push_cb_data ();
-               var result = module.serialize (data);
-               pop_cb_data ();
+       public extern bool supports_serialization ();
 
-               return result;
-       }
+       [CCode (array_length_type = "gsize")]
+       public extern uint8[] serialize_state () throws Error;
 
-       /**
-        * Unserializes the internal state.
-        *
-        * @param data the buffer where the data is stored
-        * @return false if the unserialization failed, true otherwise
-        */
-       public bool unserialize ([CCode (array_length_type = "gsize")] uint8[] data) {
-               push_cb_data ();
-               var result = module.unserialize (data);
-               pop_cb_data ();
-
-               return result;
-       }
+       public extern void deserialize_state ([CCode (array_length_type = "gsize")] uint8[] data) throws 
Error;
 
        /**
         * Load. a game.
diff --git a/retro-gobject/retro-core.c b/retro-gobject/retro-core.c
index 8efb5d3..1bcbf70 100644
--- a/retro-gobject/retro-core.c
+++ b/retro-gobject/retro-core.c
@@ -2,6 +2,116 @@
 
 #include "retro-gobject-internal.h"
 
+gboolean retro_core_supports_serialization (RetroCore *self) {
+       RetroSerializeSize serialize_size = NULL;
+       gsize size;
+
+       g_return_val_if_fail (self != NULL, FALSE);
+
+       retro_core_push_cb_data (self);
+       serialize_size = retro_module_get_serialize_size (self->module);
+       size = serialize_size ();
+       retro_core_pop_cb_data ();
+
+       return size > 0;
+}
+
+guint8 *retro_core_serialize_state (RetroCore *self, gsize *length, GError **error) {
+       RetroSerializeSize serialize_size = NULL;
+       RetroSerialize serialize = NULL;
+       guint8 *data;
+       gsize size;
+       gboolean success;
+
+       g_return_val_if_fail (self != NULL, NULL);
+       g_return_val_if_fail (length != NULL, NULL);
+
+       serialize_size = retro_module_get_serialize_size (self->module);
+
+       retro_core_push_cb_data (self);
+       size = serialize_size ();
+       retro_core_pop_cb_data ();
+
+       if (size <= 0) {
+               g_set_error (error,
+                            RETRO_CORE_ERROR,
+                            RETRO_CORE_ERROR_SERIALIZATION_NOT_SUPPORTED,
+                            "Couldn't serialize the internal state: serialization not supported.");
+
+               return NULL;
+       }
+
+       serialize = retro_module_get_serialize (self->module);
+       data = g_new0 (guint8, size);
+
+       retro_core_push_cb_data (self);
+       success = serialize (data, size);
+       retro_core_pop_cb_data ();
+
+       if (!success) {
+               g_set_error (error,
+                            RETRO_CORE_ERROR,
+                            RETRO_CORE_ERROR_COULDNT_SERIALIZE,
+                            "Couldn't serialize the internal state: serialization failed.");
+               g_free (data);
+
+               return NULL;
+       }
+
+       *length = size;
+
+       return data;
+}
+
+void retro_core_deserialize_state (RetroCore *self, guint8 *data, gsize length, GError **error) {
+       RetroSerializeSize serialize_size = NULL;
+       RetroUnserialize unserialize = NULL;
+       gsize size;
+       gboolean success;
+
+       g_return_val_if_fail (self != NULL, NULL);
+       g_return_val_if_fail (data != NULL, NULL);
+
+       serialize_size = retro_module_get_serialize_size (self->module);
+
+       retro_core_push_cb_data (self);
+       size = serialize_size ();
+       retro_core_pop_cb_data ();
+
+       if (size <= 0) {
+               g_set_error (error,
+                            RETRO_CORE_ERROR,
+                            RETRO_CORE_ERROR_SERIALIZATION_NOT_SUPPORTED,
+                            "Couldn't deserialize the internal state: serialization not supported.");
+
+               return NULL;
+       }
+
+       if (length > size) {
+               g_set_error (error,
+                            RETRO_CORE_ERROR,
+                            RETRO_CORE_ERROR_COULDNT_DESERIALIZE,
+                            "Couldn't deserialize the internal state: expected at most %llu bytes, got 
%llu.", size, length);
+
+               return NULL;
+       }
+
+       unserialize = retro_module_get_unserialize (self->module);
+
+       retro_core_push_cb_data (self);
+       success = unserialize (data, length);
+       retro_core_pop_cb_data ();
+
+       if (!success) {
+               g_set_error (error,
+                            RETRO_CORE_ERROR,
+                            RETRO_CORE_ERROR_COULDNT_DESERIALIZE,
+                            "Couldn't deserialize the internal state: deserialization failed.");
+
+               return NULL;
+       }
+}
+
 guint8 *retro_core_get_memory (RetroCore *self, RetroMemoryType id, gint *length) {
        RetroGetMemoryData get_mem_data;
        RetroGetMemorySize get_mem_size;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]