Remembering last offset and position at the message level
authorAdrian Szyndela <adrian.s@samsung.com>
Mon, 25 Jan 2016 08:38:10 +0000 (09:38 +0100)
committerAdrian Szyndela <adrian.s@samsung.com>
Fri, 19 Feb 2016 10:54:00 +0000 (11:54 +0100)
In GVariant, offsets in structs are stored for every end
of variable-sized elements except the last one.
We never know if an element we just added is the last one.
Therefore, the offset may be added when next element is added.
However, some users use multiple iterators. This change fixes
it at the root level - last offset value and position is kept
in the message.

Change-Id: I954657424d9da075edb10e5630b27df5bca8f917

dbus/dbus-marshal-gvariant.c
dbus/dbus-marshal-recursive.c
dbus/dbus-marshal-recursive.h
dbus/dbus-message-private.h
dbus/dbus-message.c
dbus/dbus-message.h

index f454e6b..d319108 100644 (file)
@@ -1167,38 +1167,37 @@ _dbus_writer_gvariant_add_offset_with_variability (DBusTypeWriter *writer,
 {
   writer->is_fixed = writer->is_fixed && fixed;
 
-  if (writer->body_container ||
-      DBUS_TYPE_STRUCT == writer->container_type ||
-      DBUS_TYPE_DICT_ENTRY == writer->container_type)
+  if (writer->body_container)
+  {
+    if (*writer->u.root.last_offset != 0)
+    {
+      check_offsets_in_body_for_adding (writer);
+
+      write_offset (writer->value_str,
+                    *writer->u.root.last_offset,
+                    writer->offsets_size,
+                    writer->value_pos);
+    }
+    if (!fixed)
+      *writer->u.root.last_offset = writer->value_pos - writer->value_start;
+    else
+      *writer->u.root.last_offset = 0;
+  }
+  else if (DBUS_TYPE_STRUCT == writer->container_type ||
+           DBUS_TYPE_DICT_ENTRY == writer->container_type)
   {
     if (writer->u.struct_or_dict.last_offset != 0)
     {
-      if (writer->body_container)
-      {
-        check_offsets_in_body_for_adding (writer);
+      check_offsets_for_adding (writer);
 
-        write_offset (writer->value_str,
+      prepend_offset (writer->offsets,
                       writer->u.struct_or_dict.last_offset,
-                      writer->offsets_size,
-                      writer->value_pos);
-      }
-      else
-      {
-        check_offsets_for_adding (writer);
-
-        prepend_offset (writer->offsets,
-                        writer->u.struct_or_dict.last_offset,
-                        writer->offsets_size);
-      }
+                      writer->offsets_size);
     }
     if (!fixed)
-    {
       writer->u.struct_or_dict.last_offset = writer->value_pos - writer->value_start;
-    }
     else
-    {
       writer->u.struct_or_dict.last_offset = 0;
-    }
   }
   else if (DBUS_TYPE_ARRAY == writer->container_type)
   {
@@ -1268,6 +1267,13 @@ fix_struct_alignment (DBusTypeWriter *writer, int type)
   return fix_struct_alignment_value (writer, get_alignment (type));
 }
 
+static void
+update_root_last_pos (DBusTypeWriter *writer)
+{
+  if (writer->body_container)
+    *writer->u.root.last_pos = writer->value_pos;
+}
+
 dbus_bool_t
 _dbus_type_writer_gvariant_write_basic_no_typecode (DBusTypeWriter *writer,
                                                     int             type,
@@ -1285,6 +1291,8 @@ _dbus_type_writer_gvariant_write_basic_no_typecode (DBusTypeWriter *writer,
                                                          writer->byte_order,
                                                          &writer->value_pos);
 
+  update_root_last_pos (writer);
+
   result = result && _dbus_writer_gvariant_add_offset (writer, type);
   return result;
 }
@@ -1377,6 +1385,8 @@ _dbus_writer_unrecurse_gvariant_write (DBusTypeWriter *writer,
       _dbus_assert_not_reached("Invalid container type");
   }
 
+  update_root_last_pos (writer);
+
   /* well, we don't know where in the type string beginning of current container is */
   result = result && _dbus_writer_gvariant_add_offset_with_variability (writer, sub->is_fixed);
 
index ee3fa98..e51e0c8 100644 (file)
@@ -1700,12 +1700,26 @@ _dbus_type_writer_init_types_delayed (DBusTypeWriter *writer,
                           NULL, 0, value_str, value_pos);
 }
 
+/**
+ * Initialize a write iterator, with the signature to be provided
+ * later. Supports GVariant
+ *
+ * @param writer the writer to init
+ * @param byte_order the byte order to marshal into
+ * @param value_str the string to write values into
+ * @param value_pos where to insert values
+ * @param gvariant TRUE if append values with GVariant marshalling
+ * @param last_offset pointer to root level offset of last variable-size value
+ * @param last_pos pointer to root level position of offsets
+ */
 void
-_dbus_type_writer_gvariant_init_types_delayed (DBusTypeWriter *writer,
-                                      int             byte_order,
-                                      DBusString     *value_str,
-                                      int             value_pos,
-                                      dbus_bool_t     gvariant)
+_dbus_type_writer_gvariant_init_types_delayed (DBusTypeWriter  *writer,
+                                               int              byte_order,
+                                               DBusString      *value_str,
+                                               int              value_pos,
+                                               dbus_bool_t      gvariant,
+                                               size_t          *last_offset,
+                                               size_t          *last_pos)
 {
   _dbus_type_writer_init (writer, byte_order,
                           NULL, 0, value_str, value_pos);
@@ -1713,9 +1727,16 @@ _dbus_type_writer_gvariant_init_types_delayed (DBusTypeWriter *writer,
   writer->body_container = TRUE;
   writer->is_fixed = TRUE;
   writer->alignment = 8;
-  writer->u.struct_or_dict.last_offset = 0;
+  writer->u.root.last_offset = last_offset;
+  writer->u.root.last_pos = last_pos;
   writer->offsets_size = 1;
   writer->offsets = NULL;
+
+  if (gvariant)
+    {
+      writer->value_pos = *last_pos;
+      writer->value_start = 0;
+    }
 }
 
 /**
@@ -2006,7 +2027,8 @@ writer_recurse_struct_or_dict_entry (DBusTypeWriter   *writer,
                                           sub->value_pos,
                                           _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
                                           '\0'))
-          _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
+            _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
+
           sub->value_pos =  _DBUS_ALIGN_VALUE (sub->value_pos, 8);
         }
     }
index aa9e513..623bf3f 100644 (file)
@@ -102,6 +102,10 @@ struct DBusTypeWriter
     struct {
       size_t last_offset; /**< for GVariant marshalling: position of end of last field */
     } struct_or_dict;
+    struct {
+      size_t *last_offset; /**< for GVariant: pointer to root-level last offset */
+      size_t *last_pos;    /**< for GVariant: pointer to root-level last writing position */
+    } root;
   } u; /**< class-specific data */
 };
 
@@ -181,7 +185,9 @@ void        _dbus_type_writer_gvariant_init_types_delayed   (DBusTypeWriter
                                                              int                    byte_order,
                                                              DBusString            *value_str,
                                                              int                    value_pos,
-                                                             dbus_bool_t            gvariant);
+                                                             dbus_bool_t            gvariant,
+                                                             size_t                *last_offset,
+                                                             size_t                *last_pos);
 void        _dbus_type_writer_add_types            (DBusTypeWriter        *writer,
                                                     DBusString            *type_str,
                                                     int                    type_pos);
index 75076c4..4d59ff2 100644 (file)
@@ -134,6 +134,8 @@ struct DBusMessage
 #endif
   DBusString *signature; /**< A placeholder for signature of received GVariant messages */
   DBusString *unique_sender; /**< A placeholder for sender name of received GVariant messages */
+  size_t gvariant_body_last_offset; /**< Offset of end of last variable-sized element of body. */
+  size_t gvariant_body_last_pos; /**< Offset of last writing position. */
 };
 
 DBUS_PRIVATE_EXPORT
index 7b494e4..07cd3b8 100644 (file)
@@ -1383,6 +1383,8 @@ dbus_message_new_empty_header (dbus_bool_t gvariant)
 
   message->signature = NULL;
   message->unique_sender = NULL;
+  message->gvariant_body_last_offset = 0;
+  message->gvariant_body_last_pos = 0;
 
   return message;
 }
@@ -2586,7 +2588,9 @@ dbus_message_iter_init_append (DBusMessage     *message,
                               _dbus_header_get_byte_order (&message->header),
                               &message->body,
                               _dbus_string_get_length (&message->body),
-                              _dbus_message_is_gvariant (message));
+                              _dbus_message_is_gvariant (message),
+                              &message->gvariant_body_last_offset,
+                              &message->gvariant_body_last_pos);
 }
 
 /**
index ef9226b..d6499a3 100644 (file)
@@ -113,6 +113,10 @@ struct DBusMessageIter
         struct {
           size_t dummy13;        /**< Don't use this */
         };
+        struct {
+          size_t *dummy14;       /**< Don't use this */
+          size_t *dummy15;       /**< Don't use this */
+        };
       } u;
     } s2;
   } u;