750e5c134363cd479319c30476b1d8c8b7056abb
[platform/upstream/dbus.git] / dbus / dbus-signature.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-signature.c  Routines for reading recursive type signatures
3  *
4  * Copyright (C) 2005 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-signature.h"
25 #include "dbus-marshal-recursive.h"
26 #include "dbus-marshal-basic.h"
27 #include "dbus-internals.h"
28 #include "dbus-test.h"
29
30 /**
31  * Implementation details of #DBusSignatureIter, all fields are private
32  */
33 typedef struct
34
35   const char *pos;           /**< current position in the signature string */
36   unsigned int finished : 1; /**< true if we are at the end iter */
37   unsigned int in_array : 1; /**< true if we are a subiterator pointing to an array's element type */
38 } DBusSignatureRealIter;
39
40 /**
41  * @defgroup DBusSignature Type signature parsing
42  * @ingroup  DBus
43  * @brief Parsing D-Bus type signatures
44  * @{
45  */
46
47 /**
48  * Initializes a #DBusSignatureIter for reading a type signature.  This
49  * function is not safe to use on invalid signatures; be sure to
50  * validate potentially invalid signatures with dbus_signature_validate
51  * before using this function.
52  *
53  * @param iter pointer to an iterator to initialize
54  * @param signature the type signature
55  */
56 void
57 dbus_signature_iter_init (DBusSignatureIter *iter,
58                           const char        *signature)
59 {
60   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
61
62   real_iter->pos = signature;
63   real_iter->finished = FALSE;
64   real_iter->in_array = FALSE;
65 }
66
67 /**
68  * Returns the current type pointed to by the iterator.
69  * If the iterator is pointing at a type code such as 's', then
70  * it will be returned directly.
71  *
72  * However, when the parser encounters a container type start
73  * character such as '(' for a structure, the corresponding type for
74  * the container will be returned, e.g.  DBUS_TYPE_STRUCT, not '('.
75  * In this case, you should initialize a sub-iterator with
76  * dbus_signature_iter_recurse to parse the container type.
77  *
78  * @param iter pointer to an iterator 
79  * @returns current type (e.g. DBUS_TYPE_STRING, DBUS_TYPE_ARRAY)
80  */
81 int
82 dbus_signature_iter_get_current_type (const DBusSignatureIter *iter)
83 {
84   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
85
86   return _dbus_first_type_in_signature_c_str (real_iter->pos, 0);
87 }
88
89 /**
90  * Returns the full type signature represented by the current
91  * iterator as a C string.
92  *
93  * @param iter pointer to an iterator 
94  * @returns current signature; or NULL on OOM.  Should be freed with #dbus_free
95  */
96 char *
97 dbus_signature_iter_get_signature (const DBusSignatureIter *iter)
98 {
99   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
100   DBusString str;
101   char *ret;
102   int pos;
103   
104   if (!_dbus_string_init (&str))
105     return NULL;
106
107   pos = 0;
108   _dbus_type_signature_next (real_iter->pos, &pos);
109
110   if (!_dbus_string_append_len (&str, real_iter->pos, pos))
111     return NULL;
112   if (!_dbus_string_steal_data (&str, &ret))
113     ret = NULL;
114   _dbus_string_free (&str);
115
116   return ret; 
117 }
118
119 /**
120  * Convenience function for returning the element type of an array;
121  * This function allows you to avoid initializing a sub-iterator and
122  * getting its current type.
123  *
124  * It is an error to invoke this function if the current type of the
125  * iterator is not DBUS_TYPE_ARRAY.
126  *
127  * @param iter pointer to an iterator 
128  * @returns current array element type
129  */
130 int
131 dbus_signature_iter_get_element_type (const DBusSignatureIter *iter)
132 {
133   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
134
135   _dbus_return_val_if_fail (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
136
137   return _dbus_first_type_in_signature_c_str (real_iter->pos, 1);
138 }
139
140 /**
141  * Skip to the next value on this "level". e.g. the next field in a
142  * struct, the next value in an array. Returns FALSE at the end of the
143  * current container.
144  *
145  * @param iter the iterator
146  * @returns FALSE if nothing more to read at or below this level
147  */
148 dbus_bool_t
149 dbus_signature_iter_next (DBusSignatureIter *iter)
150 {
151   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
152
153   if (real_iter->finished)
154     return FALSE;
155   else
156     {
157       int pos;
158
159       if (real_iter->in_array)
160         {
161           real_iter->finished = TRUE;
162           return FALSE;
163         }
164
165       pos = 0;
166       _dbus_type_signature_next (real_iter->pos, &pos);
167       real_iter->pos += pos;
168
169       if (*real_iter->pos == DBUS_STRUCT_END_CHAR
170           || *real_iter->pos == DBUS_DICT_ENTRY_END_CHAR)
171         {
172           real_iter->finished = TRUE;
173           return FALSE;
174         }
175
176       return *real_iter->pos != DBUS_TYPE_INVALID;
177     }
178 }
179
180 /**
181  * Initialize a new iterator pointing to the first type current
182  * container. It's an error to call this if the current type is a
183  * non-container (i.e. if dbus_type_is_container returns FALSE).
184  *
185  * @param iter the current interator
186  * @param subiter an iterator to initialize pointing to the first child
187  */
188 void
189 dbus_signature_iter_recurse (const DBusSignatureIter *iter,
190                              DBusSignatureIter       *subiter)
191 {
192   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
193   DBusSignatureRealIter *real_sub_iter = (DBusSignatureRealIter *) subiter;
194
195   _dbus_return_if_fail (dbus_type_is_container (dbus_signature_iter_get_current_type (iter)));
196
197   *real_sub_iter = *real_iter;
198   real_sub_iter->in_array = FALSE;
199   real_sub_iter->pos++;
200
201   if (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY)
202     real_sub_iter->in_array = TRUE;
203 }
204
205 /**
206  * Check a type signature for validity.
207  *
208  * @param signature a potentially invalid type signature
209  * @param error error return
210  * @returns TRUE iif signature is valid
211  */
212 dbus_bool_t
213 dbus_signature_validate (const char       *signature,
214                          DBusError        *error)
215                          
216 {
217   DBusString str;
218
219   _dbus_string_init_const (&str, signature);
220   if (_dbus_validate_signature (&str, 0, _dbus_string_get_length (&str)))
221     return TRUE;
222   dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, "Corrupt type signature");
223   return FALSE;
224 }
225
226 /**
227  * Check that a type signature is both valid and contains exactly
228  * one complete type.
229  *
230  * @param signature a potentially invalid type signature
231  * @param error error return
232  * @returns TRUE iif signature is valid and has exactly one complete type
233  */
234 dbus_bool_t
235 dbus_signature_validate_single (const char       *signature,
236                                 DBusError        *error)
237 {
238   DBusSignatureIter iter;
239
240   if (!dbus_signature_validate (signature, error))
241     return FALSE;
242
243   dbus_signature_iter_init (&iter, signature);
244   if (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID)
245     goto lose;
246   if (!dbus_signature_iter_next (&iter))
247     return TRUE;
248  lose:
249   dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, "Exactly one complete type required in signature");
250   return FALSE;
251 }
252
253 /** macro that checks whether a typecode is a container type */
254 #define TYPE_IS_CONTAINER(typecode)             \
255     ((typecode) == DBUS_TYPE_STRUCT ||          \
256      (typecode) == DBUS_TYPE_DICT_ENTRY ||      \
257      (typecode) == DBUS_TYPE_VARIANT ||         \
258      (typecode) == DBUS_TYPE_ARRAY)
259
260 /**
261  * A "container type" can contain basic types, or nested
262  * container types. #DBUS_TYPE_INVALID is not a container type.
263  * This function will crash if passed a typecode that isn't
264  * in dbus-protocol.h
265  *
266  * @returns #TRUE if type is a container
267  */
268 dbus_bool_t
269 dbus_type_is_container (int typecode)
270 {
271   /* only reasonable (non-line-noise) typecodes are allowed */
272   _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
273                             FALSE);
274   return TYPE_IS_CONTAINER (typecode);
275 }
276
277 /**
278  * A "basic type" is a somewhat arbitrary concept, but the intent
279  * is to include those types that are fully-specified by a single
280  * typecode, with no additional type information or nested
281  * values. So all numbers and strings are basic types and
282  * structs, arrays, and variants are not basic types.
283  * #DBUS_TYPE_INVALID is not a basic type.
284  *
285  * This function will crash if passed a typecode that isn't
286  * in dbus-protocol.h
287  *
288  * @returns #TRUE if type is basic
289  */
290 dbus_bool_t
291 dbus_type_is_basic (int typecode)
292 {
293   /* only reasonable (non-line-noise) typecodes are allowed */
294   _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
295                             FALSE);
296
297   /* everything that isn't invalid or a container */
298   return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode));
299 }
300
301 /**
302  * Tells you whether values of this type can change length if you set
303  * them to some other value. For this purpose, you assume that the
304  * first byte of the old and new value would be in the same location,
305  * so alignment padding is not a factor.
306  *
307  * This function is useful to determine whether #dbus_message_iter_get_fixed_array
308  * may be used.
309  *
310  * @returns #FALSE if the type can occupy different lengths
311  */
312 dbus_bool_t
313 dbus_type_is_fixed (int typecode)
314 {
315   switch (typecode)
316     {
317     case DBUS_TYPE_BYTE:
318     case DBUS_TYPE_BOOLEAN:
319     case DBUS_TYPE_INT16:
320     case DBUS_TYPE_UINT16:
321     case DBUS_TYPE_INT32:
322     case DBUS_TYPE_UINT32:
323     case DBUS_TYPE_INT64:
324     case DBUS_TYPE_UINT64:
325     case DBUS_TYPE_DOUBLE:
326       return TRUE;
327     default:
328       return FALSE;
329     }
330 }
331
332 #ifdef DBUS_BUILD_TESTS
333
334 /**
335  * @ingroup DBusSignatureInternals
336  * Unit test for DBusSignature.
337  *
338  * @returns #TRUE on success.
339  */
340 dbus_bool_t
341 _dbus_signature_test (void)
342 {
343   DBusSignatureIter iter;
344   DBusSignatureIter subiter;
345   DBusSignatureIter subsubiter;
346   DBusSignatureIter subsubsubiter;
347   const char *sig;
348   dbus_bool_t boolres;
349
350   _dbus_assert (sizeof (DBusSignatureIter) >= sizeof (DBusSignatureRealIter));
351
352   sig = "";
353   _dbus_assert (dbus_signature_validate (sig, NULL));
354   _dbus_assert (!dbus_signature_validate_single (sig, NULL));
355   dbus_signature_iter_init (&iter, sig);
356   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID);
357
358   sig = DBUS_TYPE_STRING_AS_STRING;
359   _dbus_assert (dbus_signature_validate (sig, NULL));
360   _dbus_assert (dbus_signature_validate_single (sig, NULL));
361   dbus_signature_iter_init (&iter, sig);
362   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
363
364   sig = DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
365   _dbus_assert (dbus_signature_validate (sig, NULL));
366   dbus_signature_iter_init (&iter, sig);
367   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
368   boolres = dbus_signature_iter_next (&iter);
369   _dbus_assert (boolres);
370   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_BYTE);
371
372   sig = DBUS_TYPE_UINT16_AS_STRING
373     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
374     DBUS_TYPE_STRING_AS_STRING
375     DBUS_TYPE_UINT32_AS_STRING
376     DBUS_TYPE_VARIANT_AS_STRING
377     DBUS_TYPE_DOUBLE_AS_STRING
378     DBUS_STRUCT_END_CHAR_AS_STRING;
379   _dbus_assert (dbus_signature_validate (sig, NULL));
380   dbus_signature_iter_init (&iter, sig);
381   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
382   boolres = dbus_signature_iter_next (&iter);
383   _dbus_assert (boolres);
384   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
385   dbus_signature_iter_recurse (&iter, &subiter);
386   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRING);
387   boolres = dbus_signature_iter_next (&subiter);
388   _dbus_assert (boolres);
389   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
390   boolres = dbus_signature_iter_next (&subiter);
391   _dbus_assert (boolres);
392   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_VARIANT);
393   boolres = dbus_signature_iter_next (&subiter);
394   _dbus_assert (boolres);
395   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_DOUBLE);
396
397   sig = DBUS_TYPE_UINT16_AS_STRING
398     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
399     DBUS_TYPE_UINT32_AS_STRING
400     DBUS_TYPE_BYTE_AS_STRING
401     DBUS_TYPE_ARRAY_AS_STRING
402     DBUS_TYPE_ARRAY_AS_STRING
403     DBUS_TYPE_DOUBLE_AS_STRING
404     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
405     DBUS_TYPE_BYTE_AS_STRING
406     DBUS_STRUCT_END_CHAR_AS_STRING
407     DBUS_STRUCT_END_CHAR_AS_STRING;
408   _dbus_assert (dbus_signature_validate (sig, NULL));
409   dbus_signature_iter_init (&iter, sig);
410   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
411   boolres = dbus_signature_iter_next (&iter);
412   _dbus_assert (boolres);
413   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
414   dbus_signature_iter_recurse (&iter, &subiter);
415   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
416   boolres = dbus_signature_iter_next (&subiter);
417   _dbus_assert (boolres);
418   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_BYTE);
419   boolres = dbus_signature_iter_next (&subiter);
420   _dbus_assert (boolres);
421   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_ARRAY);
422   _dbus_assert (dbus_signature_iter_get_element_type (&subiter) == DBUS_TYPE_ARRAY);
423
424   dbus_signature_iter_recurse (&subiter, &subsubiter);
425   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_ARRAY);
426   _dbus_assert (dbus_signature_iter_get_element_type (&subsubiter) == DBUS_TYPE_DOUBLE);
427
428   dbus_signature_iter_recurse (&subsubiter, &subsubsubiter);
429   _dbus_assert (dbus_signature_iter_get_current_type (&subsubsubiter) == DBUS_TYPE_DOUBLE);
430   boolres = dbus_signature_iter_next (&subiter);
431   _dbus_assert (boolres);
432   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRUCT);
433   dbus_signature_iter_recurse (&subiter, &subsubiter);
434   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_BYTE);
435
436   sig = DBUS_TYPE_ARRAY_AS_STRING
437     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
438     DBUS_TYPE_INT16_AS_STRING
439     DBUS_TYPE_STRING_AS_STRING
440     DBUS_DICT_ENTRY_END_CHAR_AS_STRING
441     DBUS_TYPE_VARIANT_AS_STRING;
442   _dbus_assert (dbus_signature_validate (sig, NULL));
443   _dbus_assert (!dbus_signature_validate_single (sig, NULL));
444   dbus_signature_iter_init (&iter, sig);
445   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_ARRAY);
446   _dbus_assert (dbus_signature_iter_get_element_type (&iter) == DBUS_TYPE_DICT_ENTRY);
447
448   dbus_signature_iter_recurse (&iter, &subiter);
449   dbus_signature_iter_recurse (&subiter, &subsubiter);
450   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_INT16);
451   boolres = dbus_signature_iter_next (&subsubiter);
452   _dbus_assert (boolres);
453   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_STRING);
454   boolres = dbus_signature_iter_next (&subsubiter);
455   _dbus_assert (!boolres);
456
457   boolres = dbus_signature_iter_next (&iter);
458   _dbus_assert (boolres);
459   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_VARIANT);
460   boolres = dbus_signature_iter_next (&iter);
461   _dbus_assert (!boolres);
462
463   sig = DBUS_TYPE_DICT_ENTRY_AS_STRING;
464   _dbus_assert (!dbus_signature_validate (sig, NULL));
465
466   sig = DBUS_TYPE_ARRAY_AS_STRING;
467   _dbus_assert (!dbus_signature_validate (sig, NULL));
468
469   sig = DBUS_TYPE_UINT32_AS_STRING
470     DBUS_TYPE_ARRAY_AS_STRING;
471   _dbus_assert (!dbus_signature_validate (sig, NULL));
472
473   sig = DBUS_TYPE_ARRAY_AS_STRING
474     DBUS_TYPE_DICT_ENTRY_AS_STRING;
475   _dbus_assert (!dbus_signature_validate (sig, NULL));
476
477   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING;
478   _dbus_assert (!dbus_signature_validate (sig, NULL));
479
480   sig = DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
481   _dbus_assert (!dbus_signature_validate (sig, NULL));
482
483   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
484     DBUS_TYPE_INT32_AS_STRING;
485   _dbus_assert (!dbus_signature_validate (sig, NULL));
486
487   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
488     DBUS_TYPE_INT32_AS_STRING
489     DBUS_TYPE_STRING_AS_STRING;
490   _dbus_assert (!dbus_signature_validate (sig, NULL));
491
492   sig = DBUS_STRUCT_END_CHAR_AS_STRING
493     DBUS_STRUCT_BEGIN_CHAR_AS_STRING;
494   _dbus_assert (!dbus_signature_validate (sig, NULL));
495
496   sig = DBUS_STRUCT_BEGIN_CHAR_AS_STRING
497     DBUS_TYPE_BOOLEAN_AS_STRING;
498   _dbus_assert (!dbus_signature_validate (sig, NULL));
499   return TRUE;
500 #if 0
501  oom:
502   _dbus_assert_not_reached ("out of memory");
503   return FALSE;
504 #endif
505 }
506
507 #endif
508
509 /** @} */ /* end of DBusSignature group */
510