back up some files I'm working on that don't do anything yet
[platform/upstream/dbus.git] / dbus / dbus-marshal-recursive.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal-recursive.c  Marshalling routines for recursive types
3  *
4  * Copyright (C) 2004 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-marshal-recursive.h"
25 #include "dbus-internals.h"
26
27 /**
28  * @addtogroup DBusMarshal
29  * @{
30  */
31
32 void
33 _dbus_type_reader_init (DBusTypeReader    *reader,
34                         int                byte_order,
35                         const DBusString  *type_str,
36                         int                type_pos,
37                         const DBusString  *value_str,
38                         int                value_pos)
39 {
40      
41
42 }
43
44 int
45 _dbus_type_reader_get_value_end (DBusTypeReader    *reader)
46 {
47
48
49 }
50
51 int
52 _dbus_type_reader_get_type_end (DBusTypeReader    *reader)
53 {
54
55
56 }
57
58 int
59 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
60 {
61
62
63 }
64
65 int
66 _dbus_type_reader_get_array_type (DBusTypeReader    *reader)
67 {
68
69
70 }
71
72 void
73 _dbus_type_reader_read_basic (DBusTypeReader    *reader,
74                               void              *value)
75 {
76
77
78 }
79
80 dbus_bool_t
81 _dbus_type_reader_read_array (DBusTypeReader    *reader,
82                               int                type,
83                               void             **array,
84                               int               *array_len)
85 {
86
87
88 }
89
90 void
91 _dbus_type_reader_recurse (DBusTypeReader    *reader)
92 {
93
94
95 }
96
97 void
98 _dbus_type_reader_unrecurse (DBusTypeReader    *reader)
99 {
100
101
102 }
103
104 dbus_bool_t
105 _dbus_type_reader_next (DBusTypeReader    *reader)
106 {
107
108
109
110 }
111
112 void
113 _dbus_type_writer_init (DBusTypeWriter *writer,
114                         int             byte_order,
115                         DBusString     *type_str,
116                         int             type_pos,
117                         DBusString     *value_str,
118                         int             value_pos)
119 {
120
121
122 }
123
124 dbus_bool_t
125 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
126                                int             type,
127                                const void     *value)
128 {
129
130
131 }
132
133 dbus_bool_t
134 _dbus_type_writer_write_array (DBusTypeWriter *writer,
135                                int             type,
136                                const void     *array,
137                                int             array_len)
138 {
139
140
141 }
142
143 dbus_bool_t
144 _dbus_type_writer_recurse (DBusTypeWriter *writer,
145                            int             container_type)
146 {
147
148
149 }
150
151 dbus_bool_t
152 _dbus_type_writer_unrecurse (DBusTypeWriter *writer)
153 {
154
155
156 }
157
158 /** @} */ /* end of DBusMarshal group */
159
160 #ifdef DBUS_BUILD_TESTS
161 #include "dbus-test.h"
162 #include <stdio.h>
163 #include <stdlib.h>
164
165 typedef struct
166 {
167   DBusString signature;
168   DBusString body;
169 } DataBlock;
170
171 typedef struct
172 {
173   int saved_sig_len;
174   int saved_body_len;
175 } DataBlockState;
176
177 static dbus_bool_t
178 data_block_init (DataBlock *block)
179 {
180   if (!_dbus_string_init (&block->signature))
181     return FALSE;
182
183   if (!_dbus_string_init (&block->body))
184     {
185       _dbus_string_free (&block->signature);
186       return FALSE;
187     }
188   
189   return TRUE;
190 }
191
192 static void
193 data_block_free (DataBlock *block)
194 {
195   _dbus_string_free (&block->signature);
196   _dbus_string_free (&block->body);
197 }
198
199 static void
200 data_block_save (DataBlock      *block,
201                  DataBlockState *state)
202 {
203   state->saved_sig_len = _dbus_string_get_length (&block->signature);
204   state->saved_body_len = _dbus_string_get_length (&block->body);
205 }
206
207 static void
208 data_block_restore (DataBlock      *block,
209                     DataBlockState *state)
210 {
211   /* These set_length should be shortening things so should always work */
212   
213   if (!_dbus_string_set_length (&block->signature,
214                                 state->saved_sig_len))
215     _dbus_assert_not_reached ("could not restore signature length");
216   
217   if (!_dbus_string_set_length (&block->body,
218                                 state->saved_body_len))
219     _dbus_assert_not_reached ("could not restore body length");
220 }
221
222 static void
223 data_block_init_reader_writer (DataBlock      *block,
224                                int             byte_order,
225                                DBusTypeReader *reader,
226                                DBusTypeWriter *writer)
227 {
228   _dbus_type_reader_init (reader,
229                           byte_order,
230                           &block->signature,
231                           _dbus_string_get_length (&block->signature),
232                           &block->body,
233                           _dbus_string_get_length (&block->body));
234   
235   _dbus_type_writer_init (writer,
236                           byte_order,
237                           &block->signature,
238                           _dbus_string_get_length (&block->signature),
239                           &block->body,
240                           _dbus_string_get_length (&block->body));
241 }
242
243 #define SAMPLE_INT32           12345678
244 #define SAMPLE_INT32_ALTERNATE 53781429
245 static dbus_bool_t
246 write_int32 (DataBlock      *block,
247              DBusTypeWriter *writer)
248 {
249   dbus_int32_t v = SAMPLE_INT32;
250
251   return _dbus_type_writer_write_basic (writer,
252                                         DBUS_TYPE_INT32,
253                                         &v);
254 }
255
256 static void
257 check_expected_type (DBusTypeReader *reader,
258                      int             expected)
259 {
260   int t;
261
262   t = _dbus_type_reader_get_current_type (reader);
263   
264   if (t != expected)
265     {
266       _dbus_warn ("Read type %s while expecting %s\n",
267                   _dbus_type_to_string (t),
268                   _dbus_type_to_string (expected));
269       exit (1);
270     }
271 }
272
273 static dbus_bool_t
274 read_int32 (DataBlock      *block,
275             DBusTypeReader *reader)
276 {
277   dbus_int32_t v;
278
279   check_expected_type (reader, DBUS_TYPE_INT32);
280   
281   _dbus_type_reader_read_basic (reader,
282                                 (dbus_int32_t*) &v);
283
284   _dbus_assert (v == SAMPLE_INT32);
285
286   return TRUE;
287 }
288
289 static dbus_bool_t
290 write_struct_with_int32s (DataBlock      *block,
291                           DBusTypeWriter *writer)
292 {
293   dbus_int32_t v;
294   DataBlockState saved;
295
296   data_block_save (block, &saved);
297   
298   if (!_dbus_type_writer_recurse (writer,
299                                   DBUS_TYPE_STRUCT))
300     return FALSE;
301
302   v = SAMPLE_INT32;
303   if (!_dbus_type_writer_write_basic (writer,
304                                       DBUS_TYPE_INT32,
305                                       &v))
306     {
307       data_block_restore (block, &saved);
308       return FALSE;
309     }
310
311   v = SAMPLE_INT32_ALTERNATE;
312   if (!_dbus_type_writer_write_basic (writer,
313                                       DBUS_TYPE_INT32,
314                                       &v))
315     {
316       data_block_restore (block, &saved);
317       return FALSE;
318     }
319
320   if (!_dbus_type_writer_unrecurse (writer))
321     {
322       data_block_restore (block, &saved);
323       return FALSE;
324     }
325   
326   return TRUE;
327 }
328
329 static dbus_bool_t
330 read_struct_with_int32s (DataBlock      *block,
331                          DBusTypeReader *reader)
332 {
333   dbus_int32_t v;
334
335   check_expected_type (reader, DBUS_TYPE_STRUCT);
336   
337   _dbus_type_reader_recurse (reader);
338
339   check_expected_type (reader, DBUS_TYPE_INT32);
340   
341   _dbus_type_reader_read_basic (reader,
342                                 (dbus_int32_t*) &v);
343
344   _dbus_assert (v == SAMPLE_INT32);
345
346   _dbus_type_reader_next (reader);
347   check_expected_type (reader, DBUS_TYPE_INT32);
348   
349   _dbus_type_reader_read_basic (reader,
350                                 (dbus_int32_t*) &v);
351
352   _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
353
354   _dbus_type_reader_unrecurse (reader);
355   
356   return TRUE;
357 }
358
359 static dbus_bool_t
360 write_struct_of_structs (DataBlock      *block,
361                          DBusTypeWriter *writer)
362 {
363   DataBlockState saved;
364
365   data_block_save (block, &saved);
366   
367   if (!_dbus_type_writer_recurse (writer,
368                                   DBUS_TYPE_STRUCT))
369     return FALSE;
370
371   if (!write_struct_with_int32s (block, writer))
372     {
373       data_block_restore (block, &saved);
374       return FALSE;
375     }
376   if (!write_struct_with_int32s (block, writer))
377     {
378       data_block_restore (block, &saved);
379       return FALSE;
380     }
381   if (!write_struct_with_int32s (block, writer))
382     {
383       data_block_restore (block, &saved);
384       return FALSE;
385     }
386
387   if (!_dbus_type_writer_unrecurse (writer))
388     {
389       data_block_restore (block, &saved);
390       return FALSE;
391     }
392   
393   return TRUE;
394 }
395
396 static dbus_bool_t
397 read_struct_of_structs (DataBlock      *block,
398                         DBusTypeReader *reader)
399 {
400   check_expected_type (reader, DBUS_TYPE_STRUCT);
401   
402   _dbus_type_reader_recurse (reader);
403
404   if (!read_struct_with_int32s (block, reader))
405     return FALSE;
406   _dbus_type_reader_next (reader);
407   if (!read_struct_with_int32s (block, reader))
408     return FALSE;
409   _dbus_type_reader_next (reader);
410   if (!read_struct_with_int32s (block, reader))
411     return FALSE;
412
413   _dbus_type_reader_unrecurse (reader);
414   
415   return TRUE;
416 }
417
418 static dbus_bool_t
419 write_struct_of_structs_of_structs (DataBlock      *block,
420                                     DBusTypeWriter *writer)
421 {
422   DataBlockState saved;
423
424   data_block_save (block, &saved);
425   
426   if (!_dbus_type_writer_recurse (writer,
427                                   DBUS_TYPE_STRUCT))
428     return FALSE;
429
430   if (!write_struct_of_structs (block, writer))
431     {
432       data_block_restore (block, &saved);
433       return FALSE;
434     }
435   if (!write_struct_of_structs (block, writer))
436     {
437       data_block_restore (block, &saved);
438       return FALSE;
439     }
440
441   if (!_dbus_type_writer_unrecurse (writer))
442     {
443       data_block_restore (block, &saved);
444       return FALSE;
445     }
446   
447   return TRUE;
448 }
449
450 static dbus_bool_t
451 read_struct_of_structs_of_structs (DataBlock      *block,
452                                    DBusTypeReader *reader)
453 {
454   check_expected_type (reader, DBUS_TYPE_STRUCT);
455   
456   _dbus_type_reader_recurse (reader);
457
458   if (!read_struct_of_structs (block, reader))
459     return FALSE;
460   _dbus_type_reader_next (reader);
461   if (!read_struct_of_structs (block, reader))
462     return FALSE;
463
464   _dbus_type_reader_unrecurse (reader);
465   
466   return TRUE;
467 }
468
469 typedef enum {
470   ITEM_INVALID = -1,
471   ITEM_INT32 = 0,
472   ITEM_STRUCT_WITH_INT32S,
473   ITEM_STRUCT_OF_STRUCTS,
474   ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
475   ITEM_LAST
476 } WhichItem;
477
478
479 typedef dbus_bool_t (* WriteItemFunc) (DataBlock      *block,
480                                        DBusTypeWriter *writer);
481 typedef dbus_bool_t (* ReadItemFunc)  (DataBlock      *block,
482                                        DBusTypeReader *reader);
483
484 typedef struct
485 {
486   WhichItem which;
487   WriteItemFunc write_item_func;
488   ReadItemFunc read_item_func;
489 } CheckMarshalItem;
490
491 static CheckMarshalItem items[] = {
492   { ITEM_INT32, write_int32, read_int32 },
493   { ITEM_STRUCT_WITH_INT32S, write_struct_with_int32s, read_struct_with_int32s },
494   { ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
495   { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
496     write_struct_of_structs_of_structs,
497     read_struct_of_structs_of_structs }
498 };
499
500 typedef struct
501 {
502   /* Array of items in the above items[]; -1 terminated */
503   int items[20];
504 } TestRun;
505
506 static TestRun runs[] = {
507   { { ITEM_INVALID } },
508
509   /* INT32 */
510   { { ITEM_INT32, ITEM_INVALID } },
511   { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
512   { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
513
514   /* STRUCT_WITH_INT32S */
515   { { ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
516   { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
517   { { ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
518   { { ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
519   { { ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
520
521   /* STRUCT_OF_STRUCTS */
522   { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
523   { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
524   { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
525   { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
526   { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
527   { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
528
529   /* STRUCT_OF_STRUCTS_OF_STRUCTS */
530   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
531   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
532   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
533   { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
534   { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
535   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }
536   
537 };
538
539 static dbus_bool_t
540 perform_one_run (DataBlock *block,
541                  int        byte_order,
542                  TestRun   *run)
543 {
544   DBusTypeReader reader;
545   DBusTypeWriter writer;
546   int i;
547   DataBlockState saved;
548   dbus_bool_t retval;
549
550   retval = FALSE;
551
552   data_block_save (block, &saved);
553   
554   data_block_init_reader_writer (block, 
555                                  byte_order,
556                                  &reader, &writer);
557
558   i = 0;
559   while (run->items[i] != ITEM_INVALID)
560     {
561       CheckMarshalItem *item = &items[run->items[i]];
562       if (!(* item->write_item_func) (block, &writer))
563         goto out;
564       ++i;
565     }
566
567   i = 0;
568   while (run->items[i] != ITEM_INVALID)
569     {
570       CheckMarshalItem *item = &items[run->items[i]];
571       
572       if (!(* item->read_item_func) (block, &reader))
573         goto out;
574
575       _dbus_type_reader_next (&reader);
576       
577       ++i;
578     }
579   
580   retval = TRUE;
581   
582  out:
583   data_block_restore (block, &saved);
584   return retval;
585 }
586
587 static dbus_bool_t
588 perform_all_runs (int byte_order,
589                   int initial_offset)
590 {
591   int i;
592   DataBlock block;
593   dbus_bool_t retval;
594
595   retval = FALSE;
596   
597   if (!data_block_init (&block))
598     return FALSE;
599
600   if (!_dbus_string_lengthen (&block.signature, initial_offset))
601     goto out;
602   
603   if (!_dbus_string_lengthen (&block.body, initial_offset))
604     goto out;
605   
606   i = 0;
607   while (i < _DBUS_N_ELEMENTS (runs))
608     {
609       if (!perform_one_run (&block, byte_order, &runs[i]))
610         goto out;
611       
612       ++i;
613     }
614
615   retval = TRUE;
616   
617  out:
618   data_block_free (&block);
619   
620   return retval;
621 }
622
623 static dbus_bool_t
624 perform_all_items (int byte_order,
625                    int initial_offset)
626 {
627   int i;
628   DataBlock block;
629   dbus_bool_t retval;
630   TestRun run;
631
632   retval = FALSE;
633   
634   if (!data_block_init (&block))
635     return FALSE;
636
637
638   if (!_dbus_string_lengthen (&block.signature, initial_offset))
639     goto out;
640   
641   if (!_dbus_string_lengthen (&block.body, initial_offset))
642     goto out;
643
644   /* Create a run containing all the items */
645   i = 0;
646   while (i < _DBUS_N_ELEMENTS (items))
647     {
648       _dbus_assert (i == items[i].which);
649       
650       run.items[i] = items[i].which;
651       
652       ++i;
653     }
654   
655   run.items[i] = ITEM_INVALID;
656
657   if (!perform_one_run (&block, byte_order, &run))
658     goto out;  
659   
660   retval = TRUE;
661   
662  out:
663   data_block_free (&block);
664   
665   return retval;
666 }
667
668 static dbus_bool_t
669 recursive_marshal_test_iteration (void *data)
670 {
671   int i;
672
673   i = 0;
674   while (i < 18)
675     {
676       if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
677         return FALSE;
678       if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
679         return FALSE;
680       if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
681         return FALSE;
682       if (!perform_all_items (DBUS_BIG_ENDIAN, i))
683         return FALSE;
684       
685       ++i;
686     }
687
688   return TRUE;
689 }
690
691 dbus_bool_t _dbus_marshal_recursive_test (void);
692
693 dbus_bool_t
694 _dbus_marshal_recursive_test (void)
695 {
696   _dbus_test_oom_handling ("recursive marshaling",
697                            recursive_marshal_test_iteration,
698                            NULL);  
699   
700   return TRUE;
701 }
702
703 #if 1
704 int
705 main (int argc, char **argv)
706 {
707   _dbus_marshal_recursive_test ();
708
709   return 0;
710 }
711 #endif /* main() */
712
713 #endif /* DBUS_BUILD_TESTS */