Signed-off-by: Philip Withnall <phi...@tecnocode.co.uk>
---
 src/connection.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/src/connection.c b/src/connection.c
index 141875e..531255a 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -444,6 +444,8 @@ arg_count_for_signature(const char *signature)
        return count;
 }
 
+/* See wl_connection_demarshal() for an explanation of the marshalling
+ * format. */
 struct wl_closure *
 wl_closure_vmarshal(struct wl_object *sender,
                    uint32_t opcode, va_list ap,
@@ -641,6 +643,41 @@ err_null:
        return NULL;
 }
 
+/**
+ * Consume a packet off the wire from the connection, `size` bytes long, and
+ * demarshal it to a wl_closure. Return NULL on failure. Use the provided
+ * wl_message to give metadata about the packet, such as its signature.
+ *
+ * The returned wl_closure has the following structure:
+ *
+ *   +--------------------------------------+
+ *   | preamble (count, message, types, cif |
+ *   +--------------------------------------+
+ *   | args[20]                             |
+ *   +--------------------------------------+
+ *   | start (pointer to buffer)            |
+ *   +--------------------------------------+
+ *   | link, proxy                          |
+ *   +--------------------------------------+
+ *   | buffer (first 2 uint32s)             | <- start
+ *   | buffer (size bytes long)             | <- p
+ *   | ...                                  |
+ *   | extra area (extra_space bytes long)  | <-- end, extra
+ *   | ...                                  |
+ *   +--------------------------------------+
+ *
+ * After setting up the closure, demarshalling proceeds through each argument,
+ * i, in the message's signature, setting closure->args[i] as appropriate. For
+ * small data types (e.g. inline integers), a value is pulled from `buffer`
+ * (skipping the first 2 uint32s) and `p` is incremented.
+ *
+ * Handling of strings, objects and arrays is more complex. They are
+ * demarshalled from the buffer in the obvious manner (e.g. strings as
+ * length + character data + nul terminator), then copied into the extra area
+ * in the closure, and a pointer to this extra space stored in 
closure->args[i].
+ * This is necessary so that a single pointer refers to all the data for each
+ * argument.
+ */
 struct wl_closure *
 wl_connection_demarshal(struct wl_connection *connection,
                        uint32_t size,
@@ -703,6 +740,14 @@ wl_connection_demarshal(struct wl_connection *connection,
                        closure->args[i] = p++;
                        break;
                case 's':
+                       /* Strings are stored as a uint32 length in the buffer,
+                        * followed immediately by the nul-terminated characters
+                        * of the string, then some padding to reach the next
+                        * 4-byte alignment in the buffer.
+                        *
+                        * Zero-length strings are always outputted as NULL,
+                        * and non-zero-length strings must always be
+                        * nul-terminated. */
                        closure->types[i] = &ffi_type_pointer;
                        length = *p++;
 
@@ -735,6 +780,13 @@ wl_connection_demarshal(struct wl_connection *connection,
                        p = next;
                        break;
                case 'o':
+                       /* Objects are stored as a uint32 pointer in the
+                        * buffer. Space for a pointer to this pointer (i.e. a
+                        * uint32_t**) is allocated in the extra space, and
+                        * the object pointer stored there.
+                        *
+                        * If the object pointer is 0 when dereferenced, the
+                        * object is NULL. */
                        closure->types[i] = &ffi_type_pointer;
                        id = (uint32_t **) extra;
                        extra += sizeof *id;
@@ -752,6 +804,8 @@ wl_connection_demarshal(struct wl_connection *connection,
                        p++;
                        break;
                case 'n':
+                       /* New objects are stored as normal objects, as
+                        * above. */
                        closure->types[i] = &ffi_type_pointer;
                        id = (uint32_t **) extra;
                        extra += sizeof *id;
@@ -777,6 +831,14 @@ wl_connection_demarshal(struct wl_connection *connection,
                        p++;
                        break;
                case 'a':
+                       /* Arrays are stored as a length in the buffer, followed
+                        * by `length` bytes of the array data, then by some
+                        * padding to reach the next 4-byte alignment in the
+                        * buffer.
+                        *
+                        * The array argument is returned as a pointer in the
+                        * extra area, pointing to the array data which
+                        * immediately follows it in the extra area. */
                        closure->types[i] = &ffi_type_pointer;
                        length = *p++;
 
-- 
1.7.11.7

Attachment: signature.asc
Description: This is a digitally signed message part

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to