D-Bus  1.6.8
dbus-signature.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-signature.c  Routines for reading recursive type signatures
00003  *
00004  * Copyright (C) 2005 Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 
00026 #include "dbus-signature.h"
00027 #include "dbus-marshal-recursive.h"
00028 #include "dbus-marshal-basic.h"
00029 #include "dbus-internals.h"
00030 #include "dbus-test.h"
00031 
00035 typedef struct
00036 { 
00037   const char *pos;           
00038   unsigned int finished : 1; 
00039   unsigned int in_array : 1; 
00040 } DBusSignatureRealIter;
00041 
00043 #define TYPE_IS_CONTAINER(typecode)             \
00044     ((typecode) == DBUS_TYPE_STRUCT ||          \
00045      (typecode) == DBUS_TYPE_DICT_ENTRY ||      \
00046      (typecode) == DBUS_TYPE_VARIANT ||         \
00047      (typecode) == DBUS_TYPE_ARRAY)
00048 
00049 
00066 void
00067 dbus_signature_iter_init (DBusSignatureIter *iter,
00068                           const char        *signature)
00069 {
00070   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
00071 
00072   real_iter->pos = signature;
00073   real_iter->finished = FALSE;
00074   real_iter->in_array = FALSE;
00075 }
00076 
00091 int
00092 dbus_signature_iter_get_current_type (const DBusSignatureIter *iter)
00093 {
00094   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
00095 
00096   return _dbus_first_type_in_signature_c_str (real_iter->pos, 0);
00097 }
00098 
00111 char *
00112 dbus_signature_iter_get_signature (const DBusSignatureIter *iter)
00113 {
00114   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
00115   DBusString str;
00116   char *ret;
00117   int pos;
00118   
00119   if (!_dbus_string_init (&str))
00120     return NULL;
00121 
00122   pos = 0;
00123   _dbus_type_signature_next (real_iter->pos, &pos);
00124 
00125   if (!_dbus_string_append_len (&str, real_iter->pos, pos))
00126     return NULL;
00127   if (!_dbus_string_steal_data (&str, &ret))
00128     ret = NULL;
00129   _dbus_string_free (&str);
00130 
00131   return ret; 
00132 }
00133 
00145 int
00146 dbus_signature_iter_get_element_type (const DBusSignatureIter *iter)
00147 {
00148   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
00149 
00150   _dbus_return_val_if_fail (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
00151 
00152   return _dbus_first_type_in_signature_c_str (real_iter->pos, 1);
00153 }
00154 
00163 dbus_bool_t
00164 dbus_signature_iter_next (DBusSignatureIter *iter)
00165 {
00166   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
00167 
00168   if (real_iter->finished)
00169     return FALSE;
00170   else
00171     {
00172       int pos;
00173 
00174       if (real_iter->in_array)
00175         {
00176           real_iter->finished = TRUE;
00177           return FALSE;
00178         }
00179 
00180       pos = 0;
00181       _dbus_type_signature_next (real_iter->pos, &pos);
00182       real_iter->pos += pos;
00183 
00184       if (*real_iter->pos == DBUS_STRUCT_END_CHAR
00185           || *real_iter->pos == DBUS_DICT_ENTRY_END_CHAR)
00186         {
00187           real_iter->finished = TRUE;
00188           return FALSE;
00189         }
00190 
00191       return *real_iter->pos != DBUS_TYPE_INVALID;
00192     }
00193 }
00194 
00206 void
00207 dbus_signature_iter_recurse (const DBusSignatureIter *iter,
00208                              DBusSignatureIter       *subiter)
00209 {
00210   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
00211   DBusSignatureRealIter *real_sub_iter = (DBusSignatureRealIter *) subiter;
00212 
00213   _dbus_return_if_fail (dbus_type_is_container (dbus_signature_iter_get_current_type (iter)));
00214 
00215   *real_sub_iter = *real_iter;
00216   real_sub_iter->in_array = FALSE;
00217   real_sub_iter->pos++;
00218 
00219   if (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY)
00220     real_sub_iter->in_array = TRUE;
00221 }
00222 
00232 dbus_bool_t
00233 dbus_signature_validate (const char       *signature,
00234                          DBusError        *error)
00235                          
00236 {
00237   DBusString str;
00238   DBusValidity reason;
00239 
00240   _dbus_string_init_const (&str, signature);
00241   reason = _dbus_validate_signature_with_reason (&str, 0, _dbus_string_get_length (&str));
00242 
00243   if (reason == DBUS_VALID)
00244     return TRUE;
00245   else
00246     {
00247       dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, _dbus_validity_to_error_message (reason));
00248       return FALSE;
00249     }
00250 }
00251 
00263 dbus_bool_t
00264 dbus_signature_validate_single (const char       *signature,
00265                                 DBusError        *error)
00266 {
00267   DBusSignatureIter iter;
00268 
00269   if (!dbus_signature_validate (signature, error))
00270     return FALSE;
00271 
00272   dbus_signature_iter_init (&iter, signature);
00273   if (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID)
00274     goto lose;
00275   if (!dbus_signature_iter_next (&iter))
00276     return TRUE;
00277  lose:
00278   dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, "Exactly one complete type required in signature");
00279   return FALSE;
00280 }
00281 
00293 dbus_bool_t
00294 dbus_type_is_container (int typecode)
00295 {
00296   /* only reasonable (non-line-noise) typecodes are allowed */
00297   _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
00298                             FALSE);
00299   return TYPE_IS_CONTAINER (typecode);
00300 }
00301 
00317 dbus_bool_t
00318 dbus_type_is_basic (int typecode)
00319 {
00320   /* only reasonable (non-line-noise) typecodes are allowed */
00321   _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
00322                             FALSE);
00323 
00324   /* everything that isn't invalid or a container */
00325   return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode));
00326 }
00327 
00348 dbus_bool_t
00349 dbus_type_is_fixed (int typecode)
00350 {
00351   /* only reasonable (non-line-noise) typecodes are allowed */
00352   _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
00353                             FALSE);
00354   
00355   switch (typecode)
00356     {
00357     case DBUS_TYPE_BYTE:
00358     case DBUS_TYPE_BOOLEAN:
00359     case DBUS_TYPE_INT16:
00360     case DBUS_TYPE_UINT16:
00361     case DBUS_TYPE_INT32:
00362     case DBUS_TYPE_UINT32:
00363     case DBUS_TYPE_INT64:
00364     case DBUS_TYPE_UINT64:
00365     case DBUS_TYPE_DOUBLE:
00366     case DBUS_TYPE_UNIX_FD:
00367       return TRUE;
00368     default:
00369       return FALSE;
00370     }
00371 }
00372 
00382 dbus_bool_t
00383 dbus_type_is_valid (int typecode)
00384 {
00385   switch (typecode)
00386     {
00387     case DBUS_TYPE_BYTE:
00388     case DBUS_TYPE_BOOLEAN:
00389     case DBUS_TYPE_INT16:
00390     case DBUS_TYPE_UINT16:
00391     case DBUS_TYPE_INT32:
00392     case DBUS_TYPE_UINT32:
00393     case DBUS_TYPE_INT64:
00394     case DBUS_TYPE_UINT64:
00395     case DBUS_TYPE_DOUBLE:
00396     case DBUS_TYPE_STRING:
00397     case DBUS_TYPE_OBJECT_PATH:
00398     case DBUS_TYPE_SIGNATURE:
00399     case DBUS_TYPE_ARRAY:
00400     case DBUS_TYPE_STRUCT:
00401     case DBUS_TYPE_DICT_ENTRY:
00402     case DBUS_TYPE_VARIANT:
00403     case DBUS_TYPE_UNIX_FD:
00404       return TRUE;
00405 
00406     default:
00407       return FALSE;
00408     }
00409 }
00410  /* end of DBusSignature group */
00412 
00413 #ifdef DBUS_BUILD_TESTS
00414 
00421 dbus_bool_t
00422 _dbus_signature_test (void)
00423 {
00424   DBusSignatureIter iter;
00425   DBusSignatureIter subiter;
00426   DBusSignatureIter subsubiter;
00427   DBusSignatureIter subsubsubiter;
00428   const char *sig;
00429   dbus_bool_t boolres;
00430 
00431   _dbus_assert (sizeof (DBusSignatureIter) >= sizeof (DBusSignatureRealIter));
00432 
00433   sig = "";
00434   _dbus_assert (dbus_signature_validate (sig, NULL));
00435   _dbus_assert (!dbus_signature_validate_single (sig, NULL));
00436   dbus_signature_iter_init (&iter, sig);
00437   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID);
00438 
00439   sig = DBUS_TYPE_STRING_AS_STRING;
00440   _dbus_assert (dbus_signature_validate (sig, NULL));
00441   _dbus_assert (dbus_signature_validate_single (sig, NULL));
00442   dbus_signature_iter_init (&iter, sig);
00443   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
00444 
00445   sig = DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
00446   _dbus_assert (dbus_signature_validate (sig, NULL));
00447   dbus_signature_iter_init (&iter, sig);
00448   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
00449   boolres = dbus_signature_iter_next (&iter);
00450   _dbus_assert (boolres);
00451   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_BYTE);
00452 
00453   sig = DBUS_TYPE_UINT16_AS_STRING
00454     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
00455     DBUS_TYPE_STRING_AS_STRING
00456     DBUS_TYPE_UINT32_AS_STRING
00457     DBUS_TYPE_VARIANT_AS_STRING
00458     DBUS_TYPE_DOUBLE_AS_STRING
00459     DBUS_STRUCT_END_CHAR_AS_STRING;
00460   _dbus_assert (dbus_signature_validate (sig, NULL));
00461   dbus_signature_iter_init (&iter, sig);
00462   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
00463   boolres = dbus_signature_iter_next (&iter);
00464   _dbus_assert (boolres);
00465   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
00466   dbus_signature_iter_recurse (&iter, &subiter);
00467   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRING);
00468   boolres = dbus_signature_iter_next (&subiter);
00469   _dbus_assert (boolres);
00470   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
00471   boolres = dbus_signature_iter_next (&subiter);
00472   _dbus_assert (boolres);
00473   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_VARIANT);
00474   boolres = dbus_signature_iter_next (&subiter);
00475   _dbus_assert (boolres);
00476   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_DOUBLE);
00477 
00478   sig = DBUS_TYPE_UINT16_AS_STRING
00479     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
00480     DBUS_TYPE_UINT32_AS_STRING
00481     DBUS_TYPE_BYTE_AS_STRING
00482     DBUS_TYPE_ARRAY_AS_STRING
00483     DBUS_TYPE_ARRAY_AS_STRING
00484     DBUS_TYPE_DOUBLE_AS_STRING
00485     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
00486     DBUS_TYPE_BYTE_AS_STRING
00487     DBUS_STRUCT_END_CHAR_AS_STRING
00488     DBUS_STRUCT_END_CHAR_AS_STRING;
00489   _dbus_assert (dbus_signature_validate (sig, NULL));
00490   dbus_signature_iter_init (&iter, sig);
00491   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
00492   boolres = dbus_signature_iter_next (&iter);
00493   _dbus_assert (boolres);
00494   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
00495   dbus_signature_iter_recurse (&iter, &subiter);
00496   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
00497   boolres = dbus_signature_iter_next (&subiter);
00498   _dbus_assert (boolres);
00499   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_BYTE);
00500   boolres = dbus_signature_iter_next (&subiter);
00501   _dbus_assert (boolres);
00502   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_ARRAY);
00503   _dbus_assert (dbus_signature_iter_get_element_type (&subiter) == DBUS_TYPE_ARRAY);
00504 
00505   dbus_signature_iter_recurse (&subiter, &subsubiter);
00506   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_ARRAY);
00507   _dbus_assert (dbus_signature_iter_get_element_type (&subsubiter) == DBUS_TYPE_DOUBLE);
00508 
00509   dbus_signature_iter_recurse (&subsubiter, &subsubsubiter);
00510   _dbus_assert (dbus_signature_iter_get_current_type (&subsubsubiter) == DBUS_TYPE_DOUBLE);
00511   boolres = dbus_signature_iter_next (&subiter);
00512   _dbus_assert (boolres);
00513   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRUCT);
00514   dbus_signature_iter_recurse (&subiter, &subsubiter);
00515   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_BYTE);
00516 
00517   sig = DBUS_TYPE_ARRAY_AS_STRING
00518     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
00519     DBUS_TYPE_INT16_AS_STRING
00520     DBUS_TYPE_STRING_AS_STRING
00521     DBUS_DICT_ENTRY_END_CHAR_AS_STRING
00522     DBUS_TYPE_VARIANT_AS_STRING;
00523   _dbus_assert (dbus_signature_validate (sig, NULL));
00524   _dbus_assert (!dbus_signature_validate_single (sig, NULL));
00525   dbus_signature_iter_init (&iter, sig);
00526   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_ARRAY);
00527   _dbus_assert (dbus_signature_iter_get_element_type (&iter) == DBUS_TYPE_DICT_ENTRY);
00528 
00529   dbus_signature_iter_recurse (&iter, &subiter);
00530   dbus_signature_iter_recurse (&subiter, &subsubiter);
00531   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_INT16);
00532   boolres = dbus_signature_iter_next (&subsubiter);
00533   _dbus_assert (boolres);
00534   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_STRING);
00535   boolres = dbus_signature_iter_next (&subsubiter);
00536   _dbus_assert (!boolres);
00537 
00538   boolres = dbus_signature_iter_next (&iter);
00539   _dbus_assert (boolres);
00540   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_VARIANT);
00541   boolres = dbus_signature_iter_next (&iter);
00542   _dbus_assert (!boolres);
00543 
00544   sig = DBUS_TYPE_DICT_ENTRY_AS_STRING;
00545   _dbus_assert (!dbus_signature_validate (sig, NULL));
00546 
00547   sig = DBUS_TYPE_ARRAY_AS_STRING;
00548   _dbus_assert (!dbus_signature_validate (sig, NULL));
00549 
00550   sig = DBUS_TYPE_UINT32_AS_STRING
00551     DBUS_TYPE_ARRAY_AS_STRING;
00552   _dbus_assert (!dbus_signature_validate (sig, NULL));
00553 
00554   sig = DBUS_TYPE_ARRAY_AS_STRING
00555     DBUS_TYPE_DICT_ENTRY_AS_STRING;
00556   _dbus_assert (!dbus_signature_validate (sig, NULL));
00557 
00558   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING;
00559   _dbus_assert (!dbus_signature_validate (sig, NULL));
00560 
00561   sig = DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
00562   _dbus_assert (!dbus_signature_validate (sig, NULL));
00563 
00564   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
00565     DBUS_TYPE_INT32_AS_STRING;
00566   _dbus_assert (!dbus_signature_validate (sig, NULL));
00567 
00568   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
00569     DBUS_TYPE_INT32_AS_STRING
00570     DBUS_TYPE_STRING_AS_STRING;
00571   _dbus_assert (!dbus_signature_validate (sig, NULL));
00572 
00573   sig = DBUS_STRUCT_END_CHAR_AS_STRING
00574     DBUS_STRUCT_BEGIN_CHAR_AS_STRING;
00575   _dbus_assert (!dbus_signature_validate (sig, NULL));
00576 
00577   sig = DBUS_STRUCT_BEGIN_CHAR_AS_STRING
00578     DBUS_TYPE_BOOLEAN_AS_STRING;
00579   _dbus_assert (!dbus_signature_validate (sig, NULL));
00580   return TRUE;
00581 #if 0
00582  oom:
00583   _dbus_assert_not_reached ("out of memory");
00584   return FALSE;
00585 #endif
00586 }
00587 
00588 #endif
00589