D-Bus 1.4.0
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 
00291 dbus_bool_t
00292 dbus_type_is_container (int typecode)
00293 {
00294   /* only reasonable (non-line-noise) typecodes are allowed */
00295   _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
00296                             FALSE);
00297   return TYPE_IS_CONTAINER (typecode);
00298 }
00299 
00313 dbus_bool_t
00314 dbus_type_is_basic (int typecode)
00315 {
00316   /* only reasonable (non-line-noise) typecodes are allowed */
00317   _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
00318                             FALSE);
00319 
00320   /* everything that isn't invalid or a container */
00321   return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode));
00322 }
00323 
00342 dbus_bool_t
00343 dbus_type_is_fixed (int typecode)
00344 {
00345   /* only reasonable (non-line-noise) typecodes are allowed */
00346   _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
00347                             FALSE);
00348   
00349   switch (typecode)
00350     {
00351     case DBUS_TYPE_BYTE:
00352     case DBUS_TYPE_BOOLEAN:
00353     case DBUS_TYPE_INT16:
00354     case DBUS_TYPE_UINT16:
00355     case DBUS_TYPE_INT32:
00356     case DBUS_TYPE_UINT32:
00357     case DBUS_TYPE_INT64:
00358     case DBUS_TYPE_UINT64:
00359     case DBUS_TYPE_DOUBLE:
00360     case DBUS_TYPE_UNIX_FD:
00361       return TRUE;
00362     default:
00363       return FALSE;
00364     }
00365 }
00366  /* end of DBusSignature group */
00368 
00369 #ifdef DBUS_BUILD_TESTS
00370 
00377 dbus_bool_t
00378 _dbus_signature_test (void)
00379 {
00380   DBusSignatureIter iter;
00381   DBusSignatureIter subiter;
00382   DBusSignatureIter subsubiter;
00383   DBusSignatureIter subsubsubiter;
00384   const char *sig;
00385   dbus_bool_t boolres;
00386 
00387   _dbus_assert (sizeof (DBusSignatureIter) >= sizeof (DBusSignatureRealIter));
00388 
00389   sig = "";
00390   _dbus_assert (dbus_signature_validate (sig, NULL));
00391   _dbus_assert (!dbus_signature_validate_single (sig, NULL));
00392   dbus_signature_iter_init (&iter, sig);
00393   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID);
00394 
00395   sig = DBUS_TYPE_STRING_AS_STRING;
00396   _dbus_assert (dbus_signature_validate (sig, NULL));
00397   _dbus_assert (dbus_signature_validate_single (sig, NULL));
00398   dbus_signature_iter_init (&iter, sig);
00399   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
00400 
00401   sig = DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
00402   _dbus_assert (dbus_signature_validate (sig, NULL));
00403   dbus_signature_iter_init (&iter, sig);
00404   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
00405   boolres = dbus_signature_iter_next (&iter);
00406   _dbus_assert (boolres);
00407   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_BYTE);
00408 
00409   sig = DBUS_TYPE_UINT16_AS_STRING
00410     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
00411     DBUS_TYPE_STRING_AS_STRING
00412     DBUS_TYPE_UINT32_AS_STRING
00413     DBUS_TYPE_VARIANT_AS_STRING
00414     DBUS_TYPE_DOUBLE_AS_STRING
00415     DBUS_STRUCT_END_CHAR_AS_STRING;
00416   _dbus_assert (dbus_signature_validate (sig, NULL));
00417   dbus_signature_iter_init (&iter, sig);
00418   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
00419   boolres = dbus_signature_iter_next (&iter);
00420   _dbus_assert (boolres);
00421   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
00422   dbus_signature_iter_recurse (&iter, &subiter);
00423   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRING);
00424   boolres = dbus_signature_iter_next (&subiter);
00425   _dbus_assert (boolres);
00426   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
00427   boolres = dbus_signature_iter_next (&subiter);
00428   _dbus_assert (boolres);
00429   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_VARIANT);
00430   boolres = dbus_signature_iter_next (&subiter);
00431   _dbus_assert (boolres);
00432   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_DOUBLE);
00433 
00434   sig = DBUS_TYPE_UINT16_AS_STRING
00435     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
00436     DBUS_TYPE_UINT32_AS_STRING
00437     DBUS_TYPE_BYTE_AS_STRING
00438     DBUS_TYPE_ARRAY_AS_STRING
00439     DBUS_TYPE_ARRAY_AS_STRING
00440     DBUS_TYPE_DOUBLE_AS_STRING
00441     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
00442     DBUS_TYPE_BYTE_AS_STRING
00443     DBUS_STRUCT_END_CHAR_AS_STRING
00444     DBUS_STRUCT_END_CHAR_AS_STRING;
00445   _dbus_assert (dbus_signature_validate (sig, NULL));
00446   dbus_signature_iter_init (&iter, sig);
00447   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
00448   boolres = dbus_signature_iter_next (&iter);
00449   _dbus_assert (boolres);
00450   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
00451   dbus_signature_iter_recurse (&iter, &subiter);
00452   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
00453   boolres = dbus_signature_iter_next (&subiter);
00454   _dbus_assert (boolres);
00455   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_BYTE);
00456   boolres = dbus_signature_iter_next (&subiter);
00457   _dbus_assert (boolres);
00458   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_ARRAY);
00459   _dbus_assert (dbus_signature_iter_get_element_type (&subiter) == DBUS_TYPE_ARRAY);
00460 
00461   dbus_signature_iter_recurse (&subiter, &subsubiter);
00462   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_ARRAY);
00463   _dbus_assert (dbus_signature_iter_get_element_type (&subsubiter) == DBUS_TYPE_DOUBLE);
00464 
00465   dbus_signature_iter_recurse (&subsubiter, &subsubsubiter);
00466   _dbus_assert (dbus_signature_iter_get_current_type (&subsubsubiter) == DBUS_TYPE_DOUBLE);
00467   boolres = dbus_signature_iter_next (&subiter);
00468   _dbus_assert (boolres);
00469   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRUCT);
00470   dbus_signature_iter_recurse (&subiter, &subsubiter);
00471   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_BYTE);
00472 
00473   sig = DBUS_TYPE_ARRAY_AS_STRING
00474     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
00475     DBUS_TYPE_INT16_AS_STRING
00476     DBUS_TYPE_STRING_AS_STRING
00477     DBUS_DICT_ENTRY_END_CHAR_AS_STRING
00478     DBUS_TYPE_VARIANT_AS_STRING;
00479   _dbus_assert (dbus_signature_validate (sig, NULL));
00480   _dbus_assert (!dbus_signature_validate_single (sig, NULL));
00481   dbus_signature_iter_init (&iter, sig);
00482   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_ARRAY);
00483   _dbus_assert (dbus_signature_iter_get_element_type (&iter) == DBUS_TYPE_DICT_ENTRY);
00484 
00485   dbus_signature_iter_recurse (&iter, &subiter);
00486   dbus_signature_iter_recurse (&subiter, &subsubiter);
00487   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_INT16);
00488   boolres = dbus_signature_iter_next (&subsubiter);
00489   _dbus_assert (boolres);
00490   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_STRING);
00491   boolres = dbus_signature_iter_next (&subsubiter);
00492   _dbus_assert (!boolres);
00493 
00494   boolres = dbus_signature_iter_next (&iter);
00495   _dbus_assert (boolres);
00496   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_VARIANT);
00497   boolres = dbus_signature_iter_next (&iter);
00498   _dbus_assert (!boolres);
00499 
00500   sig = DBUS_TYPE_DICT_ENTRY_AS_STRING;
00501   _dbus_assert (!dbus_signature_validate (sig, NULL));
00502 
00503   sig = DBUS_TYPE_ARRAY_AS_STRING;
00504   _dbus_assert (!dbus_signature_validate (sig, NULL));
00505 
00506   sig = DBUS_TYPE_UINT32_AS_STRING
00507     DBUS_TYPE_ARRAY_AS_STRING;
00508   _dbus_assert (!dbus_signature_validate (sig, NULL));
00509 
00510   sig = DBUS_TYPE_ARRAY_AS_STRING
00511     DBUS_TYPE_DICT_ENTRY_AS_STRING;
00512   _dbus_assert (!dbus_signature_validate (sig, NULL));
00513 
00514   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING;
00515   _dbus_assert (!dbus_signature_validate (sig, NULL));
00516 
00517   sig = DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
00518   _dbus_assert (!dbus_signature_validate (sig, NULL));
00519 
00520   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
00521     DBUS_TYPE_INT32_AS_STRING;
00522   _dbus_assert (!dbus_signature_validate (sig, NULL));
00523 
00524   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
00525     DBUS_TYPE_INT32_AS_STRING
00526     DBUS_TYPE_STRING_AS_STRING;
00527   _dbus_assert (!dbus_signature_validate (sig, NULL));
00528 
00529   sig = DBUS_STRUCT_END_CHAR_AS_STRING
00530     DBUS_STRUCT_BEGIN_CHAR_AS_STRING;
00531   _dbus_assert (!dbus_signature_validate (sig, NULL));
00532 
00533   sig = DBUS_STRUCT_BEGIN_CHAR_AS_STRING
00534     DBUS_TYPE_BOOLEAN_AS_STRING;
00535   _dbus_assert (!dbus_signature_validate (sig, NULL));
00536   return TRUE;
00537 #if 0
00538  oom:
00539   _dbus_assert_not_reached ("out of memory");
00540   return FALSE;
00541 #endif
00542 }
00543 
00544 #endif
00545