7880c5a7af497834103f2b9a43511de3fc8084b9
[platform/upstream/glib.git] / glib / gvariant-serialiser.c
1 /*
2  * Copyright © 2007, 2008 Ryan Lortie
3  * Copyright © 2010 Codethink Limited
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Ryan Lortie <desrt@desrt.ca>
19  */
20
21 /* Prologue {{{1 */
22 #include "config.h"
23
24 #include "gvariant-serialiser.h"
25
26 #include <glib/gtestutils.h>
27 #include <glib/gstrfuncs.h>
28 #include <glib/gtypes.h>
29
30 #include <string.h>
31
32
33 /* GVariantSerialiser
34  *
35  * After this prologue section, this file has roughly 2 parts.
36  *
37  * The first part is split up into sections according to various
38  * container types.  Maybe, Array, Tuple, Variant.  The Maybe and Array
39  * sections are subdivided for element types being fixed or
40  * variable-sized types.
41  *
42  * Each section documents the format of that particular type of
43  * container and implements 5 functions for dealing with it:
44  *
45  *  n_children:
46  *    - determines (according to serialised data) how many child values
47  *      are inside a particular container value.
48  *
49  *  get_child:
50  *    - gets the type of and the serialised data corresponding to a
51  *      given child value within the container value.
52  *
53  *  needed_size:
54  *    - determines how much space would be required to serialise a
55  *      container of this type, containing the given children so that
56  *      buffers can be preallocated before serialising.
57  *
58  *  serialise:
59  *    - write the serialised data for a container of this type,
60  *      containing the given children, to a buffer.
61  *
62  *  is_normal:
63  *    - check the given data to ensure that it is in normal form.  For a
64  *      given set of child values, there is exactly one normal form for
65  *      the serialised data of a container.  Other forms are possible
66  *      while maintaining the same children (for example, by inserting
67  *      something other than zero bytes as padding) but only one form is
68  *      the normal form.
69  *
70  * The second part contains the main entry point for each of the above 5
71  * functions and logic to dispatch it to the handler for the appropriate
72  * container type code.
73  *
74  * The second part also contains a routine to byteswap serialised
75  * values.  This code makes use of the n_children() and get_child()
76  * functions above to do its work so no extra support is needed on a
77  * per-container-type basis.
78  *
79  * There is also additional code for checking for normal form.  All
80  * numeric types are always in normal form since the full range of
81  * values is permitted (eg: 0 to 255 is a valid byte).  Special checks
82  * need to be performed for booleans (only 0 or 1 allowed), strings
83  * (properly nul-terminated) and object paths and signature strings
84  * (meeting the D-Bus specification requirements).
85  */
86
87 /* < private >
88  * GVariantSerialised:
89  * @type_info: the #GVariantTypeInfo of this value
90  * @data: (allow-none): the serialised data of this value, or %NULL
91  * @size: the size of this value
92  *
93  * A structure representing a GVariant in serialised form.  This
94  * structure is used with #GVariantSerialisedFiller functions and as the
95  * primary interface to the serialiser.  See #GVariantSerialisedFiller
96  * for a description of its use there.
97  *
98  * When used with the serialiser API functions, the following invariants
99  * apply to all #GVariantTypeSerialised structures passed to and
100  * returned from the serialiser.
101  *
102  * @type_info must be non-%NULL.
103  *
104  * @data must be properly aligned for the type described by @type_info.
105  *
106  * If @type_info describes a fixed-sized type then @size must always be
107  * equal to the fixed size of that type.
108  *
109  * For fixed-sized types (and only fixed-sized types), @data may be
110  * %NULL even if @size is non-zero.  This happens when a framing error
111  * occurs while attempting to extract a fixed-sized value out of a
112  * variable-sized container.  There is no data to return for the
113  * fixed-sized type, yet @size must be non-zero.  The effect of this
114  * combination should be as if @data were a pointer to an
115  * appropriately-sized zero-filled region.
116  */
117
118 /* < private >
119  * g_variant_serialised_check:
120  * @serialised: a #GVariantSerialised struct
121  *
122  * Checks @serialised for validity according to the invariants described
123  * above.
124  */
125 static void
126 g_variant_serialised_check (GVariantSerialised serialised)
127 {
128   gsize fixed_size;
129   guint alignment;
130
131   g_assert (serialised.type_info != NULL);
132   g_variant_type_info_query (serialised.type_info, &alignment, &fixed_size);
133
134   if (fixed_size)
135     g_assert_cmpint (serialised.size, ==, fixed_size);
136   else
137     g_assert (serialised.size == 0 || serialised.data != NULL);
138
139   /* Depending on the native alignment requirements of the machine, the
140    * compiler will insert either 3 or 7 padding bytes after the char.
141    * This will result in the sizeof() the struct being 12 or 16.
142    * Subtract 9 to get 3 or 7 which is a nice bitmask to apply to get
143    * the alignment bits that we "care about" being zero: in the
144    * 4-aligned case, we care about 2 bits, and in the 8-aligned case, we
145    * care about 3 bits.
146    */
147   alignment &= sizeof (struct {
148                          char a;
149                          union {
150                            guint64 x;
151                            void *y;
152                            gdouble z;
153                          } b;
154                        }
155                       ) - 9;
156
157   /* Some OSes (FreeBSD is a known example) have a malloc() that returns
158    * unaligned memory if you request small sizes.  'malloc (1);', for
159    * example, has been seen to return pointers aligned to 6 mod 16.
160    *
161    * Check if this is a small allocation and return without enforcing
162    * the alignment assertion if this is the case.
163    */
164   if (serialised.size <= alignment)
165     return;
166
167   g_assert_cmpint (alignment & (gsize) serialised.data, ==, 0);
168 }
169
170 /* < private >
171  * GVariantSerialisedFiller:
172  * @serialised: a #GVariantSerialised instance to fill
173  * @data: data from the children array
174  *
175  * This function is called back from g_variant_serialiser_needed_size()
176  * and g_variant_serialiser_serialise().  It fills in missing details
177  * from a partially-complete #GVariantSerialised.
178  *
179  * The @data parameter passed back to the function is one of the items
180  * that was passed to the serialiser in the @children array.  It
181  * represents a single child item of the container that is being
182  * serialised.  The information filled in to @serialised is the
183  * information for this child.
184  *
185  * If the @type_info field of @serialised is %NULL then the callback
186  * function must set it to the type information corresponding to the
187  * type of the child.  No reference should be added.  If it is non-%NULL
188  * then the callback should assert that it is equal to the actual type
189  * of the child.
190  *
191  * If the @size field is zero then the callback must fill it in with the
192  * required amount of space to store the serialised form of the child.
193  * If it is non-zero then the callback should assert that it is equal to
194  * the needed size of the child.
195  *
196  * If @data is non-%NULL then it points to a space that is properly
197  * aligned for and large enough to store the serialised data of the
198  * child.  The callback must store the serialised form of the child at
199  * @data.
200  *
201  * If the child value is another container then the callback will likely
202  * recurse back into the serialiser by calling
203  * g_variant_serialiser_needed_size() to determine @size and
204  * g_variant_serialiser_serialise() to write to @data.
205  */
206
207 /* PART 1: Container types {{{1
208  *
209  * This section contains the serialiser implementation functions for
210  * each container type.
211  */
212
213 /* Maybe {{{2
214  *
215  * Maybe types are handled depending on if the element type of the maybe
216  * type is a fixed-sized or variable-sized type.  Although all maybe
217  * types themselves are variable-sized types, herein, a maybe value with
218  * a fixed-sized element type is called a "fixed-sized maybe" for
219  * convenience and a maybe value with a variable-sized element type is
220  * called a "variable-sized maybe".
221  */
222
223 /* Fixed-sized Maybe {{{3
224  *
225  * The size of a maybe value with a fixed-sized element type is either 0
226  * or equal to the fixed size of its element type.  The case where the
227  * size of the maybe value is zero corresponds to the "Nothing" case and
228  * the case where the size of the maybe value is equal to the fixed size
229  * of the element type corresponds to the "Just" case; in that case, the
230  * serialised data of the child value forms the entire serialised data
231  * of the maybe value.
232  *
233  * In the event that a fixed-sized maybe value is presented with a size
234  * that is not equal to the fixed size of the element type then the
235  * value must be taken to be "Nothing".
236  */
237
238 static gsize
239 gvs_fixed_sized_maybe_n_children (GVariantSerialised value)
240 {
241   gsize element_fixed_size;
242
243   g_variant_type_info_query_element (value.type_info, NULL,
244                                      &element_fixed_size);
245
246   return (element_fixed_size == value.size) ? 1 : 0;
247 }
248
249 static GVariantSerialised
250 gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
251                                  gsize              index_)
252 {
253   /* the child has the same bounds as the
254    * container, so just update the type.
255    */
256   value.type_info = g_variant_type_info_element (value.type_info);
257   g_variant_type_info_ref (value.type_info);
258
259   return value;
260 }
261
262 static gboolean
263 gvs_fixed_sized_maybe_unpack_all (GVariantTypeInfo *type_info,
264                                   const guchar     *end,
265                                   gsize             end_size,
266                                   gsize             total_size,
267                                   GArray           *results)
268 {
269   if (total_size)
270     {
271       GVariantUnpacked unpacked;
272
273       unpacked.type_info = g_variant_type_info_element (type_info);
274       g_variant_type_info_ref (unpacked.type_info);
275       unpacked.skip = 0;
276       unpacked.size = total_size;
277
278       g_array_append_val (results, unpacked);
279     }
280
281   return TRUE;
282 }
283
284 static gsize
285 gvs_fixed_sized_maybe_needed_size (GVariantTypeInfo         *type_info,
286                                    GVariantSerialisedFiller  gvs_filler,
287                                    const gpointer           *children,
288                                    gsize                     n_children)
289 {
290   if (n_children)
291     {
292       gsize element_fixed_size;
293
294       g_variant_type_info_query_element (type_info, NULL,
295                                          &element_fixed_size);
296
297       return element_fixed_size;
298     }
299   else
300     return 0;
301 }
302
303 static void
304 gvs_fixed_sized_maybe_serialise (GVariantSerialised        value,
305                                  GVariantSerialisedFiller  gvs_filler,
306                                  const gpointer           *children,
307                                  gsize                     n_children)
308 {
309   if (n_children)
310     {
311       GVariantSerialised child = { NULL, value.data, value.size };
312
313       gvs_filler (&child, children[0]);
314     }
315 }
316
317 static gsize
318 gvs_fixed_sized_maybe_write_to_vectors (GVariantVectors  *vectors,
319                                         GVariantTypeInfo *type_info,
320                                         gsize             size,
321                                         const gpointer   *children,
322                                         gsize             n_children)
323 {
324   if (!n_children)
325     return 0;
326
327   return g_variant_callback_write_to_vectors (vectors, children[0], NULL);
328 }
329
330 static gboolean
331 gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
332 {
333   if (value.size > 0)
334     {
335       gsize element_fixed_size;
336
337       g_variant_type_info_query_element (value.type_info,
338                                          NULL, &element_fixed_size);
339
340       if (value.size != element_fixed_size)
341         return FALSE;
342
343       /* proper element size: "Just".  recurse to the child. */
344       value.type_info = g_variant_type_info_element (value.type_info);
345
346       return g_variant_serialised_is_normal (value);
347     }
348
349   /* size of 0: "Nothing" */
350   return TRUE;
351 }
352
353 /* Variable-sized Maybe
354  *
355  * The size of a maybe value with a variable-sized element type is
356  * either 0 or strictly greater than 0.  The case where the size of the
357  * maybe value is zero corresponds to the "Nothing" case and the case
358  * where the size of the maybe value is greater than zero corresponds to
359  * the "Just" case; in that case, the serialised data of the child value
360  * forms the first part of the serialised data of the maybe value and is
361  * followed by a single zero byte.  This zero byte is always appended,
362  * regardless of any zero bytes that may already be at the end of the
363  * serialised ata of the child value.
364  */
365
366 static gsize
367 gvs_variable_sized_maybe_n_children (GVariantSerialised value)
368 {
369   return (value.size > 0) ? 1 : 0;
370 }
371
372 static GVariantSerialised
373 gvs_variable_sized_maybe_get_child (GVariantSerialised value,
374                                     gsize              index_)
375 {
376   /* remove the padding byte and update the type. */
377   value.type_info = g_variant_type_info_element (value.type_info);
378   g_variant_type_info_ref (value.type_info);
379   value.size--;
380
381   /* if it's zero-sized then it may as well be NULL */
382   if (value.size == 0)
383     value.data = NULL;
384
385   return value;
386 }
387
388 static gboolean
389 gvs_variable_sized_maybe_unpack_all (GVariantTypeInfo *type_info,
390                                      const guchar     *end,
391                                      gsize             end_size,
392                                      gsize             total_size,
393                                      GArray           *results)
394 {
395   if (total_size)
396     {
397       GVariantUnpacked unpacked;
398
399       unpacked.type_info = g_variant_type_info_element (type_info);
400       g_variant_type_info_ref (unpacked.type_info);
401       unpacked.skip = 0;
402       unpacked.size = total_size - 1;
403
404       g_array_append_val (results, unpacked);
405     }
406
407   return TRUE;
408 }
409
410 static gsize
411 gvs_variable_sized_maybe_needed_size (GVariantTypeInfo         *type_info,
412                                       GVariantSerialisedFiller  gvs_filler,
413                                       const gpointer           *children,
414                                       gsize                     n_children)
415 {
416   if (n_children)
417     {
418       GVariantSerialised child = { 0, };
419
420       gvs_filler (&child, children[0]);
421
422       return child.size + 1;
423     }
424   else
425     return 0;
426 }
427
428 static void
429 gvs_variable_sized_maybe_serialise (GVariantSerialised        value,
430                                     GVariantSerialisedFiller  gvs_filler,
431                                     const gpointer           *children,
432                                     gsize                     n_children)
433 {
434   if (n_children)
435     {
436       GVariantSerialised child = { NULL, value.data, value.size - 1 };
437
438       /* write the data for the child.  */
439       gvs_filler (&child, children[0]);
440       value.data[child.size] = '\0';
441     }
442 }
443
444 static void
445 gvs_variable_sized_maybe_write_to_vectors (GVariantVectors  *vectors,
446                                            GVariantTypeInfo *type_info,
447                                            gsize             size,
448                                            const gpointer   *children,
449                                            gsize             n_children)
450 {
451   if (n_children)
452     {
453       g_variant_callback_write_to_vectors (vectors, children[0], NULL);
454       g_variant_vectors_append_copy (vectors, "", 1);
455     }
456 }
457
458 static gboolean
459 gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
460 {
461   if (value.size == 0)
462     return TRUE;
463
464   if (value.data[value.size - 1] != '\0')
465     return FALSE;
466
467   value.type_info = g_variant_type_info_element (value.type_info);
468   value.size--;
469
470   return g_variant_serialised_is_normal (value);
471 }
472
473 /* Arrays {{{2
474  *
475  * Just as with maybe types, array types are handled depending on if the
476  * element type of the array type is a fixed-sized or variable-sized
477  * type.  Similar to maybe types, for convenience, an array value with a
478  * fixed-sized element type is called a "fixed-sized array" and an array
479  * value with a variable-sized element type is called a "variable sized
480  * array".
481  */
482
483 /* Fixed-sized Array {{{3
484  *
485  * For fixed sized arrays, the serialised data is simply a concatenation
486  * of the serialised data of each element, in order.  Since fixed-sized
487  * values always have a fixed size that is a multiple of their alignment
488  * requirement no extra padding is required.
489  *
490  * In the event that a fixed-sized array is presented with a size that
491  * is not an integer multiple of the element size then the value of the
492  * array must be taken as being empty.
493  */
494
495 static gsize
496 gvs_fixed_sized_array_n_children (GVariantSerialised value)
497 {
498   gsize element_fixed_size;
499
500   g_variant_type_info_query_element (value.type_info, NULL,
501                                      &element_fixed_size);
502
503   if (value.size % element_fixed_size == 0)
504     return value.size / element_fixed_size;
505
506   return 0;
507 }
508
509 static GVariantSerialised
510 gvs_fixed_sized_array_get_child (GVariantSerialised value,
511                                  gsize              index_)
512 {
513   GVariantSerialised child = { 0, };
514
515   child.type_info = g_variant_type_info_element (value.type_info);
516   g_variant_type_info_query (child.type_info, NULL, &child.size);
517   child.data = value.data + (child.size * index_);
518   g_variant_type_info_ref (child.type_info);
519
520   return child;
521 }
522
523 static gboolean
524 gvs_fixed_sized_array_unpack_all (GVariantTypeInfo *type_info,
525                                   const guchar     *end,
526                                   gsize             end_size,
527                                   gsize             total_size,
528                                   GArray           *results)
529 {
530   GVariantTypeInfo *element;
531   gsize element_fixed_size;
532   gsize i, n;
533
534   element = g_variant_type_info_element (type_info);
535   g_variant_type_info_query (element, NULL, &element_fixed_size);
536
537   if (total_size % element_fixed_size)
538     return FALSE;
539
540   n = total_size / element_fixed_size;
541
542   for (i = 0; i < n; i++)
543     {
544       GVariantUnpacked unpacked;
545
546       unpacked.type_info = g_variant_type_info_ref (element);
547       unpacked.skip = 0;
548       unpacked.size = element_fixed_size;
549
550       g_array_append_val (results, unpacked);
551     }
552
553   return TRUE;
554 }
555
556 static gsize
557 gvs_fixed_sized_array_needed_size (GVariantTypeInfo         *type_info,
558                                    GVariantSerialisedFiller  gvs_filler,
559                                    const gpointer           *children,
560                                    gsize                     n_children)
561 {
562   gsize element_fixed_size;
563
564   g_variant_type_info_query_element (type_info, NULL, &element_fixed_size);
565
566   return element_fixed_size * n_children;
567 }
568
569 static void
570 gvs_fixed_sized_array_serialise (GVariantSerialised        value,
571                                  GVariantSerialisedFiller  gvs_filler,
572                                  const gpointer           *children,
573                                  gsize                     n_children)
574 {
575   GVariantSerialised child = { 0, };
576   gsize i;
577
578   child.type_info = g_variant_type_info_element (value.type_info);
579   g_variant_type_info_query (child.type_info, NULL, &child.size);
580   child.data = value.data;
581
582   for (i = 0; i < n_children; i++)
583     {
584       gvs_filler (&child, children[i]);
585       child.data += child.size;
586     }
587 }
588
589 static void
590 gvs_fixed_sized_array_write_to_vectors (GVariantVectors  *vectors,
591                                         GVariantTypeInfo *type_info,
592                                         gsize             size,
593                                         const gpointer   *children,
594                                         gsize             n_children)
595 {
596   gsize i;
597
598   for (i = 0; i < n_children; i++)
599     g_variant_callback_write_to_vectors (vectors, children[i], NULL);
600 }
601
602 static gboolean
603 gvs_fixed_sized_array_is_normal (GVariantSerialised value)
604 {
605   GVariantSerialised child = { 0, };
606
607   child.type_info = g_variant_type_info_element (value.type_info);
608   g_variant_type_info_query (child.type_info, NULL, &child.size);
609
610   if (value.size % child.size != 0)
611     return FALSE;
612
613   for (child.data = value.data;
614        child.data < value.data + value.size;
615        child.data += child.size)
616     {
617       if (!g_variant_serialised_is_normal (child))
618         return FALSE;
619     }
620
621   return TRUE;
622 }
623
624 /* Variable-sized Array {{{3
625  *
626  * Variable sized arrays, containing variable-sized elements, must be
627  * able to determine the boundaries between the elements.  The items
628  * cannot simply be concatenated.  Additionally, we are faced with the
629  * fact that non-fixed-sized values do not necessarily have a size that
630  * is a multiple of their alignment requirement, so we may need to
631  * insert zero-filled padding.
632  *
633  * While it is possible to find the start of an item by starting from
634  * the end of the item before it and padding for alignment, it is not
635  * generally possible to do the reverse operation.  For this reason, we
636  * record the end point of each element in the array.
637  *
638  * GVariant works in terms of "offsets".  An offset is a pointer to a
639  * boundary between two bytes.  In 4 bytes of serialised data, there
640  * would be 5 possible offsets: one at the start ('0'), one between each
641  * pair of adjacent bytes ('1', '2', '3') and one at the end ('4').
642  *
643  * The numeric value of an offset is an unsigned integer given relative
644  * to the start of the serialised data of the array.  Offsets are always
645  * stored in little endian byte order and are always only as big as they
646  * need to be.  For example, in 255 bytes of serialised data, there are
647  * 256 offsets.  All possibilities can be stored in an 8 bit unsigned
648  * integer.  In 256 bytes of serialised data, however, there are 257
649  * possible offsets so 16 bit integers must be used.  The size of an
650  * offset is always a power of 2.
651  *
652  * The offsets are stored at the end of the serialised data of the
653  * array.  They are simply concatenated on without any particular
654  * alignment.  The size of the offsets is included in the size of the
655  * serialised data for purposes of determining the size of the offsets.
656  * This presents a possibly ambiguity; in certain cases, a particular
657  * value of array could have two different serialised forms.
658  *
659  * Imagine an array containing a single string of 253 bytes in length
660  * (so, 254 bytes including the nul terminator).  Now the offset must be
661  * written.  If an 8 bit offset is written, it will bring the size of
662  * the array's serialised data to 255 -- which means that the use of an
663  * 8 bit offset was valid.  If a 16 bit offset is used then the total
664  * size of the array will be 256 -- which means that the use of a 16 bit
665  * offset was valid.  Although both of these will be accepted by the
666  * deserialiser, only the smaller of the two is considered to be in
667  * normal form and that is the one that the serialiser must produce.
668  */
669
670 /* bytes may be NULL if (size == 0). */
671 static inline gsize
672 gvs_read_unaligned_le (const guchar *bytes,
673                        guint         size)
674 {
675   union
676   {
677     guchar bytes[GLIB_SIZEOF_SIZE_T];
678     gsize integer;
679   } tmpvalue;
680
681   tmpvalue.integer = 0;
682   if (bytes != NULL)
683     memcpy (&tmpvalue.bytes, bytes, size);
684
685   return GSIZE_FROM_LE (tmpvalue.integer);
686 }
687
688 static inline void
689 gvs_write_unaligned_le (guchar *bytes,
690                         gsize   value,
691                         guint   size)
692 {
693   union
694   {
695     guchar bytes[GLIB_SIZEOF_SIZE_T];
696     gsize integer;
697   } tmpvalue;
698
699   tmpvalue.integer = GSIZE_TO_LE (value);
700   memcpy (bytes, &tmpvalue.bytes, size);
701 }
702
703 static guint
704 gvs_get_offset_size (gsize size)
705 {
706   if (size > G_MAXUINT32)
707     return 8;
708
709   else if (size > G_MAXUINT16)
710     return 4;
711
712   else if (size > G_MAXUINT8)
713     return 2;
714
715   else if (size > 0)
716     return 1;
717
718   return 0;
719 }
720
721 static gsize
722 gvs_calculate_total_size (gsize body_size,
723                           gsize offsets)
724 {
725   if (body_size + 1 * offsets <= G_MAXUINT8)
726     return body_size + 1 * offsets;
727
728   if (body_size + 2 * offsets <= G_MAXUINT16)
729     return body_size + 2 * offsets;
730
731   if (body_size + 4 * offsets <= G_MAXUINT32)
732     return body_size + 4 * offsets;
733
734   return body_size + 8 * offsets;
735 }
736
737 static gsize
738 gvs_variable_sized_array_n_children (GVariantSerialised value)
739 {
740   gsize offsets_array_size;
741   gsize offset_size;
742   gsize last_end;
743
744   if (value.size == 0)
745     return 0;
746
747   offset_size = gvs_get_offset_size (value.size);
748
749   last_end = gvs_read_unaligned_le (value.data + value.size -
750                                     offset_size, offset_size);
751
752   if (last_end > value.size)
753     return 0;
754
755   offsets_array_size = value.size - last_end;
756
757   if (offsets_array_size % offset_size)
758     return 0;
759
760   return offsets_array_size / offset_size;
761 }
762
763 static GVariantSerialised
764 gvs_variable_sized_array_get_child (GVariantSerialised value,
765                                     gsize              index_)
766 {
767   GVariantSerialised child = { 0, };
768   gsize offset_size;
769   gsize last_end;
770   gsize start;
771   gsize end;
772
773   child.type_info = g_variant_type_info_element (value.type_info);
774   g_variant_type_info_ref (child.type_info);
775
776   offset_size = gvs_get_offset_size (value.size);
777
778   last_end = gvs_read_unaligned_le (value.data + value.size -
779                                     offset_size, offset_size);
780
781   if (index_ > 0)
782     {
783       guint alignment;
784
785       start = gvs_read_unaligned_le (value.data + last_end +
786                                      (offset_size * (index_ - 1)),
787                                      offset_size);
788
789       g_variant_type_info_query (child.type_info, &alignment, NULL);
790       start += (-start) & alignment;
791     }
792   else
793     start = 0;
794
795   end = gvs_read_unaligned_le (value.data + last_end +
796                                (offset_size * index_),
797                                offset_size);
798
799   if (start < end && end <= value.size)
800     {
801       child.data = value.data + start;
802       child.size = end - start;
803     }
804
805   return child;
806 }
807
808 static gboolean
809 gvs_variable_sized_array_unpack_all (GVariantTypeInfo *type_info,
810                                      const guchar     *end,
811                                      gsize             end_size,
812                                      gsize             total_size,
813                                      GArray           *results)
814 {
815   GVariantTypeInfo *element;
816   guint element_alignment;
817   const guchar *offsets;
818   gsize offset_size;
819   gsize offsets_array_size;
820   gsize prev_end;
821   gsize last_end;
822   gsize i, n;
823
824   if (total_size == 0)
825     return TRUE;
826
827   element = g_variant_type_info_element (type_info);
828   g_variant_type_info_query (element, &element_alignment, NULL);
829
830   offset_size = gvs_get_offset_size (total_size);
831
832   if (offset_size > end_size)
833     return FALSE;
834
835   last_end = gvs_read_unaligned_le (end - offset_size, offset_size);
836
837   if (last_end > total_size)
838     return 0;
839
840   offsets_array_size = total_size - last_end;
841
842   if (offsets_array_size > end_size)
843     return FALSE;
844
845   offsets = end - offsets_array_size;
846
847   if (offsets_array_size % offset_size)
848     return FALSE;
849
850   n = offsets_array_size / offset_size;
851
852   if (n == 0)
853     return FALSE;
854
855   prev_end = 0;
856
857   for (i = 0; i < n; i++)
858     {
859       GVariantUnpacked unpacked;
860       gsize start;
861       gsize end;
862
863       start = prev_end + ((-prev_end) & element_alignment);
864       end = gvs_read_unaligned_le (offsets, offset_size);
865       offsets += offset_size;
866
867       if (start < prev_end || end < start) { g_assert_not_reached ();
868         return FALSE; /* XXX free the array and type infos */ }
869
870       unpacked.type_info = g_variant_type_info_ref (element);
871       unpacked.skip = start - prev_end;
872       unpacked.size = end - start;
873
874       g_array_append_val (results, unpacked);
875     }
876
877   return TRUE;
878 }
879
880 static gsize
881 gvs_variable_sized_array_needed_size (GVariantTypeInfo         *type_info,
882                                       GVariantSerialisedFiller  gvs_filler,
883                                       const gpointer           *children,
884                                       gsize                     n_children)
885 {
886   guint alignment;
887   gsize offset;
888   gsize i;
889
890   g_variant_type_info_query (type_info, &alignment, NULL);
891   offset = 0;
892
893   for (i = 0; i < n_children; i++)
894     {
895       GVariantSerialised child = { 0, };
896
897       offset += (-offset) & alignment;
898       gvs_filler (&child, children[i]);
899       offset += child.size;
900     }
901
902   return gvs_calculate_total_size (offset, n_children);
903 }
904
905 static void
906 gvs_variable_sized_array_serialise (GVariantSerialised        value,
907                                     GVariantSerialisedFiller  gvs_filler,
908                                     const gpointer           *children,
909                                     gsize                     n_children)
910 {
911   guchar *offset_ptr;
912   gsize offset_size;
913   guint alignment;
914   gsize offset;
915   gsize i;
916
917   g_variant_type_info_query (value.type_info, &alignment, NULL);
918   offset_size = gvs_get_offset_size (value.size);
919   offset = 0;
920
921   offset_ptr = value.data + value.size - offset_size * n_children;
922
923   for (i = 0; i < n_children; i++)
924     {
925       GVariantSerialised child = { 0, };
926
927       while (offset & alignment)
928         value.data[offset++] = '\0';
929
930       child.data = value.data + offset;
931       gvs_filler (&child, children[i]);
932       offset += child.size;
933
934       gvs_write_unaligned_le (offset_ptr, offset, offset_size);
935       offset_ptr += offset_size;
936     }
937 }
938
939 static void
940 gvs_variable_sized_array_write_to_vectors (GVariantVectors  *vectors,
941                                            GVariantTypeInfo *type_info,
942                                            gsize             size,
943                                            const gpointer   *children,
944                                            gsize             n_children)
945 {
946   guint offset_key;
947   guint alignment;
948   gsize offset;
949   gsize i;
950
951   if (n_children == 0)
952     return;
953
954   offset_key = g_variant_vectors_reserve_offsets (vectors, n_children, gvs_get_offset_size (size));
955   g_variant_type_info_query (type_info, &alignment, NULL);
956   offset = 0;
957
958   for (i = 0; i < n_children; i++)
959     {
960       if ((-offset) & alignment)
961         offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
962
963       offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
964
965       g_variant_vectors_write_to_offsets (vectors, i, offset, offset_key);
966     }
967
968   g_variant_vectors_commit_offsets (vectors, offset_key);
969 }
970
971 static gboolean
972 gvs_variable_sized_array_is_normal (GVariantSerialised value)
973 {
974   GVariantSerialised child = { 0, };
975   gsize offsets_array_size;
976   guchar *offsets_array;
977   guint offset_size;
978   guint alignment;
979   gsize last_end;
980   gsize length;
981   gsize offset;
982   gsize i;
983
984   if (value.size == 0)
985     return TRUE;
986
987   offset_size = gvs_get_offset_size (value.size);
988   last_end = gvs_read_unaligned_le (value.data + value.size -
989                                     offset_size, offset_size);
990
991   if (last_end > value.size)
992     return FALSE;
993
994   offsets_array_size = value.size - last_end;
995
996   if (offsets_array_size % offset_size)
997     return FALSE;
998
999   offsets_array = value.data + value.size - offsets_array_size;
1000   length = offsets_array_size / offset_size;
1001
1002   if (length == 0)
1003     return FALSE;
1004
1005   child.type_info = g_variant_type_info_element (value.type_info);
1006   g_variant_type_info_query (child.type_info, &alignment, NULL);
1007   offset = 0;
1008
1009   for (i = 0; i < length; i++)
1010     {
1011       gsize this_end;
1012
1013       this_end = gvs_read_unaligned_le (offsets_array + offset_size * i,
1014                                         offset_size);
1015
1016       if (this_end < offset || this_end > last_end)
1017         return FALSE;
1018
1019       while (offset & alignment)
1020         {
1021           if (!(offset < this_end && value.data[offset] == '\0'))
1022             return FALSE;
1023           offset++;
1024         }
1025
1026       child.data = value.data + offset;
1027       child.size = this_end - offset;
1028
1029       if (child.size == 0)
1030         child.data = NULL;
1031
1032       if (!g_variant_serialised_is_normal (child))
1033         return FALSE;
1034
1035       offset = this_end;
1036     }
1037
1038   g_assert (offset == last_end);
1039
1040   return TRUE;
1041 }
1042
1043 /* Tuples {{{2
1044  *
1045  * Since tuples can contain a mix of variable- and fixed-sized items,
1046  * they are, in terms of serialisation, a hybrid of variable-sized and
1047  * fixed-sized arrays.
1048  *
1049  * Offsets are only stored for variable-sized items.  Also, since the
1050  * number of items in a tuple is known from its type, we are able to
1051  * know exactly how many offsets to expect in the serialised data (and
1052  * therefore how much space is taken up by the offset array).  This
1053  * means that we know where the end of the serialised data for the last
1054  * item is -- we can just subtract the size of the offset array from the
1055  * total size of the tuple.  For this reason, the last item in the tuple
1056  * doesn't need an offset stored.
1057  *
1058  * Tuple offsets are stored in reverse.  This design choice allows
1059  * iterator-based deserialisers to be more efficient.
1060  *
1061  * Most of the "heavy lifting" here is handled by the GVariantTypeInfo
1062  * for the tuple.  See the notes in gvarianttypeinfo.h.
1063  */
1064
1065 static gsize
1066 gvs_tuple_n_children (GVariantSerialised value)
1067 {
1068   return g_variant_type_info_n_members (value.type_info);
1069 }
1070
1071 static GVariantSerialised
1072 gvs_tuple_get_child (GVariantSerialised value,
1073                      gsize              index_)
1074 {
1075   const GVariantMemberInfo *member_info;
1076   GVariantSerialised child = { 0, };
1077   gsize offset_size;
1078   gsize start, end;
1079
1080   member_info = g_variant_type_info_member_info (value.type_info, index_);
1081   child.type_info = g_variant_type_info_ref (member_info->type_info);
1082   offset_size = gvs_get_offset_size (value.size);
1083
1084   /* tuples are the only (potentially) fixed-sized containers, so the
1085    * only ones that have to deal with the possibility of having %NULL
1086    * data with a non-zero %size if errors occurred elsewhere.
1087    */
1088   if G_UNLIKELY (value.data == NULL && value.size != 0)
1089     {
1090       g_variant_type_info_query (child.type_info, NULL, &child.size);
1091
1092       /* this can only happen in fixed-sized tuples,
1093        * so the child must also be fixed sized.
1094        */
1095       g_assert (child.size != 0);
1096       child.data = NULL;
1097
1098       return child;
1099     }
1100
1101   if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
1102     {
1103       if (offset_size * (member_info->i + 2) > value.size)
1104         return child;
1105     }
1106   else
1107     {
1108       if (offset_size * (member_info->i + 1) > value.size)
1109         {
1110           /* if the child is fixed size, return its size.
1111            * if child is not fixed-sized, return size = 0.
1112            */
1113           g_variant_type_info_query (child.type_info, NULL, &child.size);
1114
1115           return child;
1116         }
1117     }
1118
1119   if (member_info->i + 1)
1120     start = gvs_read_unaligned_le (value.data + value.size -
1121                                    offset_size * (member_info->i + 1),
1122                                    offset_size);
1123   else
1124     start = 0;
1125
1126   start += member_info->a;
1127   start &= member_info->b;
1128   start |= member_info->c;
1129
1130   if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
1131     end = value.size - offset_size * (member_info->i + 1);
1132
1133   else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
1134     {
1135       gsize fixed_size;
1136
1137       g_variant_type_info_query (child.type_info, NULL, &fixed_size);
1138       end = start + fixed_size;
1139       child.size = fixed_size;
1140     }
1141
1142   else /* G_VARIANT_MEMBER_ENDING_OFFSET */
1143     end = gvs_read_unaligned_le (value.data + value.size -
1144                                  offset_size * (member_info->i + 2),
1145                                  offset_size);
1146
1147   if (start < end && end <= value.size)
1148     {
1149       child.data = value.data + start;
1150       child.size = end - start;
1151     }
1152
1153   return child;
1154 }
1155
1156 static gboolean
1157 gvs_tuple_unpack_all (GVariantTypeInfo *type_info,
1158                       const guchar     *end,
1159                       gsize             end_size,
1160                       gsize             total_size,
1161                       GArray           *results)
1162 {
1163   g_assert_not_reached (); /* FIXME */
1164   return FALSE;
1165 }
1166
1167 static gsize
1168 gvs_tuple_needed_size (GVariantTypeInfo         *type_info,
1169                        GVariantSerialisedFiller  gvs_filler,
1170                        const gpointer           *children,
1171                        gsize                     n_children)
1172 {
1173   const GVariantMemberInfo *member_info = NULL;
1174   gsize fixed_size;
1175   gsize offset;
1176   gsize i;
1177
1178   g_variant_type_info_query (type_info, NULL, &fixed_size);
1179
1180   if (fixed_size)
1181     return fixed_size;
1182
1183   offset = 0;
1184
1185   for (i = 0; i < n_children; i++)
1186     {
1187       guint alignment;
1188
1189       member_info = g_variant_type_info_member_info (type_info, i);
1190       g_variant_type_info_query (member_info->type_info,
1191                                  &alignment, &fixed_size);
1192       offset += (-offset) & alignment;
1193
1194       if (fixed_size)
1195         offset += fixed_size;
1196       else
1197         {
1198           GVariantSerialised child = { 0, };
1199
1200           gvs_filler (&child, children[i]);
1201           offset += child.size;
1202         }
1203     }
1204
1205   return gvs_calculate_total_size (offset, member_info->i + 1);
1206 }
1207
1208 static void
1209 gvs_tuple_serialise (GVariantSerialised        value,
1210                      GVariantSerialisedFiller  gvs_filler,
1211                      const gpointer           *children,
1212                      gsize                     n_children)
1213 {
1214   gsize offset_size;
1215   gsize offset;
1216   gsize i;
1217
1218   offset_size = gvs_get_offset_size (value.size);
1219   offset = 0;
1220
1221   for (i = 0; i < n_children; i++)
1222     {
1223       const GVariantMemberInfo *member_info;
1224       GVariantSerialised child = { 0, };
1225       guint alignment;
1226
1227       member_info = g_variant_type_info_member_info (value.type_info, i);
1228       g_variant_type_info_query (member_info->type_info, &alignment, NULL);
1229
1230       while (offset & alignment)
1231         value.data[offset++] = '\0';
1232
1233       child.data = value.data + offset;
1234       gvs_filler (&child, children[i]);
1235       offset += child.size;
1236
1237       if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
1238         {
1239           value.size -= offset_size;
1240           gvs_write_unaligned_le (value.data + value.size,
1241                                   offset, offset_size);
1242         }
1243     }
1244
1245   while (offset < value.size)
1246     value.data[offset++] = '\0';
1247 }
1248
1249
1250 static void
1251 gvs_tuple_write_to_vectors (GVariantVectors  *vectors,
1252                             GVariantTypeInfo *type_info,
1253                             gsize             size,
1254                             const gpointer   *children,
1255                             gsize             n_children)
1256 {
1257   const GVariantMemberInfo *member_info = NULL;
1258   gsize fixed_size;
1259   gsize offset;
1260   gsize i;
1261
1262   if (n_children == 0)
1263     {
1264       g_variant_vectors_append_copy (vectors, "", 1);
1265       return;
1266     }
1267
1268   g_variant_type_info_query (type_info, NULL, &fixed_size);
1269   offset = 0;
1270
1271   if (!fixed_size)
1272     {
1273       gsize n_offsets;
1274
1275       member_info = g_variant_type_info_member_info (type_info, n_children - 1);
1276       n_offsets = member_info->i + 1;
1277
1278       if (n_offsets)
1279         {
1280           gsize offset_key = 0;
1281
1282           offset_key = g_variant_vectors_reserve_offsets (vectors, n_offsets, gvs_get_offset_size (size));
1283
1284           for (i = 0; i < n_children; i++)
1285             {
1286               guint alignment;
1287
1288               member_info = g_variant_type_info_member_info (type_info, i);
1289               g_variant_type_info_query (member_info->type_info, &alignment, NULL);
1290
1291               if ((-offset) & alignment)
1292                 offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
1293
1294               offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
1295
1296               if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
1297                 g_variant_vectors_write_to_offsets (vectors, --n_offsets, offset, offset_key);
1298             }
1299
1300           g_variant_vectors_commit_offsets (vectors, offset_key);
1301         }
1302       else
1303         {
1304           for (i = 0; i < n_children; i++)
1305             {
1306               guint alignment;
1307
1308               member_info = g_variant_type_info_member_info (type_info, i);
1309               g_variant_type_info_query (member_info->type_info, &alignment, NULL);
1310
1311               if ((-offset) & alignment)
1312                 offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
1313
1314               offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
1315             }
1316         }
1317     }
1318   else
1319     {
1320       for (i = 0; i < n_children; i++)
1321         {
1322           guint alignment;
1323
1324           member_info = g_variant_type_info_member_info (type_info, i);
1325           g_variant_type_info_query (member_info->type_info, &alignment, NULL);
1326
1327           if ((-offset) & alignment)
1328             offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
1329
1330           offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
1331         }
1332
1333       g_assert (fixed_size - offset < 8);
1334       g_variant_vectors_append_pad (vectors, fixed_size - offset);
1335     }
1336 }
1337
1338 static gboolean
1339 gvs_tuple_is_normal (GVariantSerialised value)
1340 {
1341   guint offset_size;
1342   gsize offset_ptr;
1343   gsize length;
1344   gsize offset;
1345   gsize i;
1346
1347   /* as per the comment in gvs_tuple_get_child() */
1348   if G_UNLIKELY (value.data == NULL && value.size != 0)
1349     return FALSE;
1350
1351   offset_size = gvs_get_offset_size (value.size);
1352   length = g_variant_type_info_n_members (value.type_info);
1353   offset_ptr = value.size;
1354   offset = 0;
1355
1356   for (i = 0; i < length; i++)
1357     {
1358       const GVariantMemberInfo *member_info;
1359       GVariantSerialised child;
1360       gsize fixed_size;
1361       guint alignment;
1362       gsize end;
1363
1364       member_info = g_variant_type_info_member_info (value.type_info, i);
1365       child.type_info = member_info->type_info;
1366
1367       g_variant_type_info_query (child.type_info, &alignment, &fixed_size);
1368
1369       while (offset & alignment)
1370         {
1371           if (offset > value.size || value.data[offset] != '\0')
1372             return FALSE;
1373           offset++;
1374         }
1375
1376       child.data = value.data + offset;
1377
1378       switch (member_info->ending_type)
1379         {
1380         case G_VARIANT_MEMBER_ENDING_FIXED:
1381           end = offset + fixed_size;
1382           break;
1383
1384         case G_VARIANT_MEMBER_ENDING_LAST:
1385           end = offset_ptr;
1386           break;
1387
1388         case G_VARIANT_MEMBER_ENDING_OFFSET:
1389           offset_ptr -= offset_size;
1390
1391           if (offset_ptr < offset)
1392             return FALSE;
1393
1394           end = gvs_read_unaligned_le (value.data + offset_ptr, offset_size);
1395           break;
1396
1397         default:
1398           g_assert_not_reached ();
1399         }
1400
1401       if (end < offset || end > offset_ptr)
1402         return FALSE;
1403
1404       child.size = end - offset;
1405
1406       if (child.size == 0)
1407         child.data = NULL;
1408
1409       if (!g_variant_serialised_is_normal (child))
1410         return FALSE;
1411
1412       offset = end;
1413     }
1414
1415   {
1416     gsize fixed_size;
1417     guint alignment;
1418
1419     g_variant_type_info_query (value.type_info, &alignment, &fixed_size);
1420
1421     if (fixed_size)
1422       {
1423         g_assert (fixed_size == value.size);
1424         g_assert (offset_ptr == value.size);
1425
1426         if (i == 0)
1427           {
1428             if (value.data[offset++] != '\0')
1429               return FALSE;
1430           }
1431         else
1432           {
1433             while (offset & alignment)
1434               if (value.data[offset++] != '\0')
1435                 return FALSE;
1436           }
1437
1438         g_assert (offset == value.size);
1439       }
1440   }
1441
1442   return offset_ptr == offset;
1443 }
1444
1445 /* Variants {{{2
1446  *
1447  * Variants are stored by storing the serialised data of the child,
1448  * followed by a '\0' character, followed by the type string of the
1449  * child.
1450  *
1451  * In the case that a value is presented that contains no '\0'
1452  * character, or doesn't have a single well-formed definite type string
1453  * following that character, the variant must be taken as containing the
1454  * unit tuple: ().
1455  */
1456
1457 static inline gsize
1458 gvs_variant_n_children (GVariantSerialised value)
1459 {
1460   return 1;
1461 }
1462
1463 static inline GVariantSerialised
1464 gvs_variant_get_child (GVariantSerialised value,
1465                        gsize              index_)
1466 {
1467   GVariantSerialised child = { 0, };
1468
1469   /* NOTE: not O(1) and impossible for it to be... */
1470   if (value.size)
1471     {
1472       /* find '\0' character */
1473       for (child.size = value.size - 1; child.size; child.size--)
1474         if (value.data[child.size] == '\0')
1475           break;
1476
1477       /* ensure we didn't just hit the start of the string */
1478       if (value.data[child.size] == '\0')
1479         {
1480           const gchar *type_string = (gchar *) &value.data[child.size + 1];
1481           const gchar *limit = (gchar *) &value.data[value.size];
1482           const gchar *end;
1483
1484           if (g_variant_type_string_scan (type_string, limit, &end) &&
1485               end == limit)
1486             {
1487               const GVariantType *type = (GVariantType *) type_string;
1488
1489               if (g_variant_type_is_definite (type))
1490                 {
1491                   gsize fixed_size;
1492
1493                   child.type_info = g_variant_type_info_get (type);
1494
1495                   if (child.size != 0)
1496                     /* only set to non-%NULL if size > 0 */
1497                     child.data = value.data;
1498
1499                   g_variant_type_info_query (child.type_info,
1500                                              NULL, &fixed_size);
1501
1502                   if (!fixed_size || fixed_size == child.size)
1503                     return child;
1504
1505                   g_variant_type_info_unref (child.type_info);
1506                 }
1507             }
1508         }
1509     }
1510
1511   child.type_info = g_variant_type_info_get (G_VARIANT_TYPE_UNIT);
1512   child.data = NULL;
1513   child.size = 1;
1514
1515   return child;
1516 }
1517
1518 static gboolean
1519 gvs_variant_unpack_all (GVariantTypeInfo *type_info,
1520                         const guchar     *end,
1521                         gsize             end_size,
1522                         gsize             total_size,
1523                         GArray           *results)
1524 {
1525   g_assert_not_reached (); /* FIXME */
1526   return FALSE;
1527 }
1528
1529 static inline gsize
1530 gvs_variant_needed_size (GVariantTypeInfo         *type_info,
1531                          GVariantSerialisedFiller  gvs_filler,
1532                          const gpointer           *children,
1533                          gsize                     n_children)
1534 {
1535   GVariantSerialised child = { 0, };
1536   const gchar *type_string;
1537
1538   gvs_filler (&child, children[0]);
1539   type_string = g_variant_type_info_get_type_string (child.type_info);
1540
1541   return child.size + 1 + strlen (type_string);
1542 }
1543
1544 static inline void
1545 gvs_variant_serialise (GVariantSerialised        value,
1546                        GVariantSerialisedFiller  gvs_filler,
1547                        const gpointer           *children,
1548                        gsize                     n_children)
1549 {
1550   GVariantSerialised child = { 0, };
1551   const gchar *type_string;
1552
1553   child.data = value.data;
1554
1555   gvs_filler (&child, children[0]);
1556   type_string = g_variant_type_info_get_type_string (child.type_info);
1557   value.data[child.size] = '\0';
1558   memcpy (value.data + child.size + 1, type_string, strlen (type_string));
1559 }
1560
1561 static void
1562 gvs_variant_write_to_vectors (GVariantVectors  *vectors,
1563                               GVariantTypeInfo *type_info,
1564                               gsize             size,
1565                               const gpointer   *children,
1566                               gsize             n_children)
1567 {
1568   GVariantTypeInfo *child_type_info;
1569   const gchar *type_string;
1570
1571   g_variant_callback_write_to_vectors (vectors, children[0], &child_type_info);
1572   type_string = g_variant_type_info_get_type_string (child_type_info);
1573
1574   g_variant_vectors_append_copy (vectors, "", 1);
1575   g_variant_vectors_append_copy (vectors, type_string, strlen (type_string));
1576 }
1577
1578 static inline gboolean
1579 gvs_variant_is_normal (GVariantSerialised value)
1580 {
1581   GVariantSerialised child;
1582   gboolean normal;
1583
1584   child = gvs_variant_get_child (value, 0);
1585
1586   normal = (child.data != NULL || child.size == 0) &&
1587            g_variant_serialised_is_normal (child);
1588
1589   g_variant_type_info_unref (child.type_info);
1590
1591   return normal;
1592 }
1593
1594
1595
1596 /* PART 2: Serialiser API {{{1
1597  *
1598  * This is the implementation of the API of the serialiser as advertised
1599  * in gvariant-serialiser.h.
1600  */
1601
1602 /* Dispatch Utilities {{{2
1603  *
1604  * These macros allow a given function (for example,
1605  * g_variant_serialiser_serialise) to be dispatched to the appropriate
1606  * type-specific function above (fixed/variable-sized maybe,
1607  * fixed/variable-sized array, tuple or variant).
1608  */
1609 #define DISPATCH_FIXED(type_info, before, after) \
1610   {                                                     \
1611     gsize fixed_size;                                   \
1612                                                         \
1613     g_variant_type_info_query_element (type_info, NULL, \
1614                                        &fixed_size);    \
1615                                                         \
1616     if (fixed_size)                                     \
1617       {                                                 \
1618         before ## fixed_sized ## after                  \
1619       }                                                 \
1620     else                                                \
1621       {                                                 \
1622         before ## variable_sized ## after               \
1623       }                                                 \
1624   }
1625
1626 #define DISPATCH_CASES(type_info, before, after) \
1627   switch (g_variant_type_info_get_type_char (type_info))        \
1628     {                                                           \
1629       case G_VARIANT_TYPE_INFO_CHAR_MAYBE:                      \
1630         DISPATCH_FIXED (type_info, before, _maybe ## after)     \
1631                                                                 \
1632       case G_VARIANT_TYPE_INFO_CHAR_ARRAY:                      \
1633         DISPATCH_FIXED (type_info, before, _array ## after)     \
1634                                                                 \
1635       case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:                 \
1636       case G_VARIANT_TYPE_INFO_CHAR_TUPLE:                      \
1637         {                                                       \
1638           before ## tuple ## after                              \
1639         }                                                       \
1640                                                                 \
1641       case G_VARIANT_TYPE_INFO_CHAR_VARIANT:                    \
1642         {                                                       \
1643           before ## variant ## after                            \
1644         }                                                       \
1645     }
1646
1647 /* Serialiser entry points {{{2
1648  *
1649  * These are the functions that are called in order for the serialiser
1650  * to do its thing.
1651  */
1652
1653 /* < private >
1654  * g_variant_serialised_n_children:
1655  * @serialised: a #GVariantSerialised
1656  *
1657  * For serialised data that represents a container value (maybes,
1658  * tuples, arrays, variants), determine how many child items are inside
1659  * that container.
1660  *
1661  * Returns: the number of children
1662  */
1663 gsize
1664 g_variant_serialised_n_children (GVariantSerialised serialised)
1665 {
1666   g_variant_serialised_check (serialised);
1667
1668   DISPATCH_CASES (serialised.type_info,
1669
1670                   return gvs_/**/,/**/_n_children (serialised);
1671
1672                  )
1673   g_assert_not_reached ();
1674 }
1675
1676 /* < private >
1677  * g_variant_serialised_get_child:
1678  * @serialised: a #GVariantSerialised
1679  * @index_: the index of the child to fetch
1680  *
1681  * Extracts a child from a serialised data representing a container
1682  * value.
1683  *
1684  * It is an error to call this function with an index out of bounds.
1685  *
1686  * If the result .data == %NULL and .size > 0 then there has been an
1687  * error extracting the requested fixed-sized value.  This number of
1688  * zero bytes needs to be allocated instead.
1689  *
1690  * In the case that .data == %NULL and .size == 0 then a zero-sized
1691  * item of a variable-sized type is being returned.
1692  *
1693  * .data is never non-%NULL if size is 0.
1694  *
1695  * Returns: a #GVariantSerialised for the child
1696  */
1697 GVariantSerialised
1698 g_variant_serialised_get_child (GVariantSerialised serialised,
1699                                 gsize              index_)
1700 {
1701   GVariantSerialised child;
1702
1703   g_variant_serialised_check (serialised);
1704
1705   if G_LIKELY (index_ < g_variant_serialised_n_children (serialised))
1706     {
1707       DISPATCH_CASES (serialised.type_info,
1708
1709                       child = gvs_/**/,/**/_get_child (serialised, index_);
1710                       g_assert (child.size || child.data == NULL);
1711                       g_variant_serialised_check (child);
1712                       return child;
1713
1714                      )
1715       g_assert_not_reached ();
1716     }
1717
1718   g_error ("Attempt to access item %"G_GSIZE_FORMAT
1719            " in a container with only %"G_GSIZE_FORMAT" items",
1720            index_, g_variant_serialised_n_children (serialised));
1721 }
1722
1723 /* < private >
1724  * g_variant_serialiser_serialise:
1725  * @serialised: a #GVariantSerialised, properly set up
1726  * @gvs_filler: the filler function
1727  * @children: an array of child items
1728  * @n_children: the size of @children
1729  *
1730  * Writes data in serialised form.
1731  *
1732  * The type_info field of @serialised must be filled in to type info for
1733  * the type that we are serialising.
1734  *
1735  * The size field of @serialised must be filled in with the value
1736  * returned by a previous call to g_variant_serialiser_needed_size().
1737  *
1738  * The data field of @serialised must be a pointer to a properly-aligned
1739  * memory region large enough to serialise into (ie: at least as big as
1740  * the size field).
1741  *
1742  * This function is only resonsible for serialising the top-level
1743  * container.  @gvs_filler is called on each child of the container in
1744  * order for all of the data of that child to be filled in.
1745  */
1746 void
1747 g_variant_serialiser_serialise (GVariantSerialised        serialised,
1748                                 GVariantSerialisedFiller  gvs_filler,
1749                                 const gpointer           *children,
1750                                 gsize                     n_children)
1751 {
1752   g_variant_serialised_check (serialised);
1753
1754   DISPATCH_CASES (serialised.type_info,
1755
1756                   gvs_/**/,/**/_serialise (serialised, gvs_filler,
1757                                            children, n_children);
1758                   return;
1759
1760                  )
1761   g_assert_not_reached ();
1762 }
1763
1764 /* < private >
1765  * g_variant_serialiser_needed_size:
1766  * @type_info: the type to serialise for
1767  * @gvs_filler: the filler function
1768  * @children: an array of child items
1769  * @n_children: the size of @children
1770  *
1771  * Determines how much memory would be needed to serialise this value.
1772  *
1773  * This function is only resonsible for performing calculations for the
1774  * top-level container.  @gvs_filler is called on each child of the
1775  * container in order to determine its size.
1776  */
1777 gsize
1778 g_variant_serialiser_needed_size (GVariantTypeInfo         *type_info,
1779                                   GVariantSerialisedFiller  gvs_filler,
1780                                   const gpointer           *children,
1781                                   gsize                     n_children)
1782 {
1783   DISPATCH_CASES (type_info,
1784
1785                   return gvs_/**/,/**/_needed_size (type_info, gvs_filler,
1786                                                     children, n_children);
1787                  )
1788   g_assert_not_reached ();
1789 }
1790
1791 gboolean
1792 g_variant_serialiser_unpack_all (GVariantTypeInfo *type_info,
1793                                  const guchar     *end,
1794                                  gsize             end_size,
1795                                  gsize             total_size,
1796                                  GArray           *results)
1797 {
1798   DISPATCH_CASES (type_info,
1799                   return gvs_/**/,/**/_unpack_all (type_info, end, end_size, total_size, results);
1800                  )
1801
1802   /* We are here because type_info is not a container type */
1803   return FALSE;
1804 }
1805
1806 void
1807 g_variant_serialiser_write_to_vectors (GVariantVectors  *vectors,
1808                                        GVariantTypeInfo *type_info,
1809                                        gsize             size,
1810                                        const gpointer   *children,
1811                                        gsize             n_children)
1812 {
1813   DISPATCH_CASES (type_info,
1814                   gvs_/**/,/**/_write_to_vectors (vectors, type_info, size, children, n_children);
1815                   return;
1816                  )
1817   g_assert_not_reached ();
1818 }
1819
1820 /* Byteswapping {{{2 */
1821
1822 /* < private >
1823  * g_variant_serialised_byteswap:
1824  * @value: a #GVariantSerialised
1825  *
1826  * Byte-swap serialised data.  The result of this function is only
1827  * well-defined if the data is in normal form.
1828  */
1829 void
1830 g_variant_serialised_byteswap (GVariantSerialised serialised)
1831 {
1832   gsize fixed_size;
1833   guint alignment;
1834
1835   g_variant_serialised_check (serialised);
1836
1837   if (!serialised.data)
1838     return;
1839
1840   /* the types we potentially need to byteswap are
1841    * exactly those with alignment requirements.
1842    */
1843   g_variant_type_info_query (serialised.type_info, &alignment, &fixed_size);
1844   if (!alignment)
1845     return;
1846
1847   /* if fixed size and alignment are equal then we are down
1848    * to the base integer type and we should swap it.  the
1849    * only exception to this is if we have a tuple with a
1850    * single item, and then swapping it will be OK anyway.
1851    */
1852   if (alignment + 1 == fixed_size)
1853     {
1854       switch (fixed_size)
1855       {
1856         case 2:
1857           {
1858             guint16 *ptr = (guint16 *) serialised.data;
1859
1860             g_assert_cmpint (serialised.size, ==, 2);
1861             *ptr = GUINT16_SWAP_LE_BE (*ptr);
1862           }
1863           return;
1864
1865         case 4:
1866           {
1867             guint32 *ptr = (guint32 *) serialised.data;
1868
1869             g_assert_cmpint (serialised.size, ==, 4);
1870             *ptr = GUINT32_SWAP_LE_BE (*ptr);
1871           }
1872           return;
1873
1874         case 8:
1875           {
1876             guint64 *ptr = (guint64 *) serialised.data;
1877
1878             g_assert_cmpint (serialised.size, ==, 8);
1879             *ptr = GUINT64_SWAP_LE_BE (*ptr);
1880           }
1881           return;
1882
1883         default:
1884           g_assert_not_reached ();
1885       }
1886     }
1887
1888   /* else, we have a container that potentially contains
1889    * some children that need to be byteswapped.
1890    */
1891   else
1892     {
1893       gsize children, i;
1894
1895       children = g_variant_serialised_n_children (serialised);
1896       for (i = 0; i < children; i++)
1897         {
1898           GVariantSerialised child;
1899
1900           child = g_variant_serialised_get_child (serialised, i);
1901           g_variant_serialised_byteswap (child);
1902           g_variant_type_info_unref (child.type_info);
1903         }
1904     }
1905 }
1906
1907 /* Normal form checking {{{2 */
1908
1909 /* < private >
1910  * g_variant_serialised_is_normal:
1911  * @serialised: a #GVariantSerialised
1912  *
1913  * Determines, recursively if @serialised is in normal form.  There is
1914  * precisely one normal form of serialised data for each possible value.
1915  *
1916  * It is possible that multiple byte sequences form the serialised data
1917  * for a given value if, for example, the padding bytes are filled in
1918  * with something other than zeros, but only one form is the normal
1919  * form.
1920  */
1921 gboolean
1922 g_variant_serialised_is_normal (GVariantSerialised serialised)
1923 {
1924   DISPATCH_CASES (serialised.type_info,
1925
1926                   return gvs_/**/,/**/_is_normal (serialised);
1927
1928                  )
1929
1930   if (serialised.data == NULL)
1931     return FALSE;
1932
1933   /* some hard-coded terminal cases */
1934   switch (g_variant_type_info_get_type_char (serialised.type_info))
1935     {
1936     case 'b': /* boolean */
1937       return serialised.data[0] < 2;
1938
1939     case 's': /* string */
1940       return g_variant_serialiser_is_string (serialised.data,
1941                                              serialised.size);
1942
1943     case 'o':
1944       return g_variant_serialiser_is_object_path (serialised.data,
1945                                                   serialised.size);
1946
1947     case 'g':
1948       return g_variant_serialiser_is_signature (serialised.data,
1949                                                 serialised.size);
1950
1951     default:
1952       /* all of the other types are fixed-sized numerical types for
1953        * which all possible values are valid (including various NaN
1954        * representations for floating point values).
1955        */
1956       return TRUE;
1957     }
1958 }
1959
1960 /* Validity-checking functions {{{2
1961  *
1962  * Checks if strings, object paths and signature strings are valid.
1963  */
1964
1965 /* < private >
1966  * g_variant_serialiser_is_string:
1967  * @data: a possible string
1968  * @size: the size of @data
1969  *
1970  * Ensures that @data is a valid string with a nul terminator at the end
1971  * and no nul bytes embedded.
1972  */
1973 gboolean
1974 g_variant_serialiser_is_string (gconstpointer data,
1975                                 gsize         size)
1976 {
1977   const gchar *expected_end;
1978   const gchar *end;
1979
1980   if (size == 0)
1981     return FALSE;
1982
1983   expected_end = ((gchar *) data) + size - 1;
1984
1985   if (*expected_end != '\0')
1986     return FALSE;
1987
1988   g_utf8_validate (data, size, &end);
1989
1990   return end == expected_end;
1991 }
1992
1993 /* < private >
1994  * g_variant_serialiser_is_object_path:
1995  * @data: a possible D-Bus object path
1996  * @size: the size of @data
1997  *
1998  * Performs the checks for being a valid string.
1999  *
2000  * Also, ensures that @data is a valid DBus object path, as per the D-Bus
2001  * specification.
2002  */
2003 gboolean
2004 g_variant_serialiser_is_object_path (gconstpointer data,
2005                                      gsize         size)
2006 {
2007   const gchar *string = data;
2008   gsize i;
2009
2010   if (!g_variant_serialiser_is_string (data, size))
2011     return FALSE;
2012
2013   /* The path must begin with an ASCII '/' (integer 47) character */
2014   if (string[0] != '/')
2015     return FALSE;
2016
2017   for (i = 1; string[i]; i++)
2018     /* Each element must only contain the ASCII characters
2019      * "[A-Z][a-z][0-9]_"
2020      */
2021     if (g_ascii_isalnum (string[i]) || string[i] == '_')
2022       ;
2023
2024     /* must consist of elements separated by slash characters. */
2025     else if (string[i] == '/')
2026       {
2027         /* No element may be the empty string. */
2028         /* Multiple '/' characters cannot occur in sequence. */
2029         if (string[i - 1] == '/')
2030           return FALSE;
2031       }
2032
2033     else
2034       return FALSE;
2035
2036   /* A trailing '/' character is not allowed unless the path is the
2037    * root path (a single '/' character).
2038    */
2039   if (i > 1 && string[i - 1] == '/')
2040     return FALSE;
2041
2042   return TRUE;
2043 }
2044
2045 /* < private >
2046  * g_variant_serialiser_is_signature:
2047  * @data: a possible D-Bus signature
2048  * @size: the size of @data
2049  *
2050  * Performs the checks for being a valid string.
2051  *
2052  * Also, ensures that @data is a valid D-Bus type signature, as per the
2053  * D-Bus specification.
2054  */
2055 gboolean
2056 g_variant_serialiser_is_signature (gconstpointer data,
2057                                    gsize         size)
2058 {
2059   const gchar *string = data;
2060   gsize first_invalid;
2061
2062   if (!g_variant_serialiser_is_string (data, size))
2063     return FALSE;
2064
2065   /* make sure no non-definite characters appear */
2066   first_invalid = strspn (string, "ybnqiuxthdvasog(){}");
2067   if (string[first_invalid])
2068     return FALSE;
2069
2070   /* make sure each type string is well-formed */
2071   while (*string)
2072     if (!g_variant_type_string_scan (string, NULL, &string))
2073       return FALSE;
2074
2075   return TRUE;
2076 }
2077
2078 /* Epilogue {{{1 */
2079 /* vim:set foldmethod=marker: */