ofdbus/dbus-glib/dbus/dbus-gsignature.c
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 /* -*- mode: C; c-file-style: "gnu" -*- */
       
     2 /* dbus-gsignature.c Mapping from dbus type signatures to GType
       
     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 "config.h"
       
    25 #include "dbus-gtest.h"
       
    26 #include "dbus-gsignature.h"
       
    27 #include "dbus-gvalue-utils.h"
       
    28 #include <string.h>
       
    29 #include <glib.h>
       
    30 
       
    31 #define MAP_BASIC(d_t, g_t)                     \
       
    32     case DBUS_TYPE_##d_t:                       \
       
    33       return G_TYPE_##g_t;
       
    34 static GType
       
    35 typecode_to_gtype (int type)
       
    36 {
       
    37   switch (type)
       
    38     {
       
    39       MAP_BASIC (BOOLEAN, BOOLEAN);
       
    40       MAP_BASIC (BYTE,    UCHAR);
       
    41       MAP_BASIC (INT16,   INT);
       
    42       MAP_BASIC (INT32,   INT);
       
    43       MAP_BASIC (UINT16,  UINT);
       
    44       MAP_BASIC (UINT32,  UINT);
       
    45       MAP_BASIC (INT64,   INT64);
       
    46       MAP_BASIC (UINT64,  UINT64);
       
    47       MAP_BASIC (DOUBLE,  DOUBLE);
       
    48       MAP_BASIC (STRING,  STRING);
       
    49     default:
       
    50       return G_TYPE_INVALID;
       
    51     }
       
    52 }
       
    53 #undef MAP_BASIC
       
    54 
       
    55 static gboolean
       
    56 dbus_typecode_maps_to_basic (int typecode)
       
    57 {
       
    58   return typecode_to_gtype (typecode) != G_TYPE_INVALID;
       
    59 }
       
    60 
       
    61 GType
       
    62 _dbus_gtype_from_basic_typecode (int typecode)
       
    63 {
       
    64   g_assert (dbus_type_is_basic (typecode));
       
    65   g_assert (dbus_typecode_maps_to_basic (typecode));
       
    66   return typecode_to_gtype (typecode);
       
    67 }
       
    68 
       
    69 static GType
       
    70 signature_iter_to_g_type_dict (const DBusSignatureIter *subiter, gboolean is_client)
       
    71 {
       
    72   DBusSignatureIter iter;
       
    73   GType key_gtype;
       
    74   GType value_gtype;
       
    75 
       
    76   g_assert (dbus_signature_iter_get_current_type (subiter) == DBUS_TYPE_DICT_ENTRY);
       
    77 
       
    78   dbus_signature_iter_recurse (subiter, &iter);
       
    79 
       
    80   key_gtype = _dbus_gtype_from_signature_iter (&iter, is_client); 
       
    81   if (key_gtype == G_TYPE_INVALID)
       
    82     return G_TYPE_INVALID;
       
    83 
       
    84   dbus_signature_iter_next (&iter);
       
    85   value_gtype = _dbus_gtype_from_signature_iter (&iter, is_client);
       
    86   if (value_gtype == G_TYPE_INVALID)
       
    87     return G_TYPE_INVALID;
       
    88 
       
    89   if (!_dbus_gtype_is_valid_hash_key (key_gtype)
       
    90       || !_dbus_gtype_is_valid_hash_value (value_gtype))
       
    91     /* Later we need to return DBUS_TYPE_G_VALUE */
       
    92     return G_TYPE_INVALID; 
       
    93 
       
    94   return dbus_g_type_get_map ("GHashTable", key_gtype, value_gtype);
       
    95 }
       
    96 
       
    97 static GType
       
    98 signature_iter_to_g_type_array (DBusSignatureIter *iter, gboolean is_client)
       
    99 {
       
   100   GType elt_gtype;
       
   101 
       
   102   elt_gtype = _dbus_gtype_from_signature_iter (iter, is_client);
       
   103   if (elt_gtype == G_TYPE_INVALID)
       
   104     return G_TYPE_INVALID;
       
   105 
       
   106   if (elt_gtype == G_TYPE_OBJECT)
       
   107     return DBUS_TYPE_G_OBJECT_ARRAY;
       
   108   if (elt_gtype == G_TYPE_STRING)
       
   109     return G_TYPE_STRV;
       
   110   if (_dbus_g_type_is_fixed (elt_gtype))
       
   111     return dbus_g_type_get_collection ("GArray", elt_gtype);
       
   112   else if (g_type_is_a (elt_gtype, G_TYPE_OBJECT)
       
   113 	   || g_type_is_a (elt_gtype, G_TYPE_BOXED))
       
   114     return dbus_g_type_get_collection ("GPtrArray", elt_gtype);
       
   115 
       
   116   /* Later we need to return DBUS_TYPE_G_VALUE */
       
   117   return G_TYPE_INVALID; 
       
   118 }
       
   119 
       
   120 static GType
       
   121 signature_iter_to_g_type_struct (DBusSignatureIter *iter, gboolean is_client)
       
   122 {
       
   123   GArray *types;
       
   124   GType ret;
       
   125   types = g_array_new (FALSE, FALSE, sizeof (GType));
       
   126   do
       
   127     {
       
   128       GType curtype;
       
   129       curtype = _dbus_gtype_from_signature_iter (iter, is_client);
       
   130       g_array_append_val (types, curtype);
       
   131     }
       
   132   while (dbus_signature_iter_next (iter));
       
   133 
       
   134   ret = dbus_g_type_get_structv ("GValueArray", types->len, (GType*) types->data);
       
   135   g_array_free (types, TRUE);
       
   136   return ret;
       
   137 }
       
   138 
       
   139 GType
       
   140 _dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client)
       
   141 {
       
   142   int current_type;
       
   143 
       
   144   current_type = dbus_signature_iter_get_current_type (iter);
       
   145   /* TODO: handle type 0? */
       
   146   if (dbus_typecode_maps_to_basic (current_type))
       
   147     return _dbus_gtype_from_basic_typecode (current_type);
       
   148   else if (current_type == DBUS_TYPE_OBJECT_PATH)
       
   149     return DBUS_TYPE_G_OBJECT_PATH;
       
   150   else
       
   151     {
       
   152       DBusSignatureIter subiter;
       
   153 
       
   154       g_assert (dbus_type_is_container (current_type));
       
   155 
       
   156       if (current_type == DBUS_TYPE_VARIANT)
       
   157 	return G_TYPE_VALUE;
       
   158       
       
   159       dbus_signature_iter_recurse (iter, &subiter);
       
   160 
       
   161       if (current_type == DBUS_TYPE_ARRAY)
       
   162 	{
       
   163 	  int elt_type = dbus_signature_iter_get_current_type (&subiter);
       
   164 	  if (elt_type == DBUS_TYPE_DICT_ENTRY)
       
   165 	    return signature_iter_to_g_type_dict (&subiter, is_client);
       
   166 	  else 
       
   167 	    return signature_iter_to_g_type_array (&subiter, is_client);
       
   168 	}
       
   169       else if (current_type == DBUS_TYPE_STRUCT)
       
   170         {
       
   171           return signature_iter_to_g_type_struct (&subiter, is_client);
       
   172         }
       
   173       else
       
   174 	{
       
   175 	  g_assert_not_reached ();
       
   176 	  return G_TYPE_INVALID;
       
   177 	}
       
   178     }
       
   179 }
       
   180 
       
   181 GType
       
   182 _dbus_gtype_from_signature (const char *signature, gboolean is_client)
       
   183 {
       
   184   DBusSignatureIter iter;
       
   185 
       
   186   dbus_signature_iter_init (&iter, signature);
       
   187 
       
   188   return _dbus_gtype_from_signature_iter (&iter, is_client);
       
   189 }
       
   190 
       
   191 GArray *
       
   192 _dbus_gtypes_from_arg_signature (const char *argsig, gboolean is_client)
       
   193 {
       
   194   GArray *ret;
       
   195   int current_type;
       
   196   DBusSignatureIter sigiter;
       
   197 
       
   198   ret = g_array_new (FALSE, FALSE, sizeof (GType));
       
   199 
       
   200   dbus_signature_iter_init (&sigiter, argsig);
       
   201   while ((current_type = dbus_signature_iter_get_current_type (&sigiter)) != DBUS_TYPE_INVALID)
       
   202     {
       
   203       GType curtype;
       
   204 
       
   205       curtype = _dbus_gtype_from_signature_iter (&sigiter, is_client);
       
   206       g_array_append_val (ret, curtype);
       
   207       dbus_signature_iter_next (&sigiter);
       
   208     }
       
   209   return ret;
       
   210 }