dbus-gidl.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-gidl.c data structure describing an interface, to be generated from IDL
00003  *             or something
00004  *
00005  * Copyright (C) 2003, 2005  Red Hat, Inc.
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-gidl.h"
00026 
00027 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00028 
00029 struct BaseInfo
00030 {
00031   unsigned int refcount : 28;
00032   unsigned int type     : 4;
00033   char *name;
00034 };
00035 
00036 struct NodeInfo
00037 {
00038   BaseInfo base;
00039   GSList *interfaces;
00040   GSList *nodes;
00041 };
00042 
00043 struct InterfaceInfo
00044 {
00045   BaseInfo base;
00046   GHashTable *annotations;
00047   /* Since we have BaseInfo now these could be one list */
00048   GSList *methods;
00049   GSList *signals;
00050   GSList *properties;
00051 };
00052 
00053 struct MethodInfo
00054 {
00055   BaseInfo base;
00056   GHashTable *annotations;
00057   GSList *args;
00058 };
00059 
00060 struct SignalInfo
00061 {
00062   BaseInfo base;
00063   GSList *args;
00064 };
00065 
00066 struct PropertyInfo
00067 {
00068   BaseInfo base;
00069   char *type;
00070   PropertyAccessFlags access;
00071 };
00072 
00073 struct ArgInfo
00074 {
00075   BaseInfo base;
00076   char *type;
00077   ArgDirection direction;
00078   GHashTable *annotations;
00079 };
00080 
00081 static void
00082 get_hash_key (gpointer key, gpointer value, gpointer data)
00083 {
00084   GSList **list = data;
00085   *list = g_slist_prepend (*list, key);
00086 }
00087 
00088 static GSList *
00089 get_hash_keys (GHashTable *table)
00090 {
00091   GSList *ret = NULL;
00092 
00093   g_hash_table_foreach (table, get_hash_key, &ret);
00094 
00095   return ret;
00096 }
00097 
00098 BaseInfo *
00099 base_info_ref (BaseInfo *info)
00100 {
00101   g_return_val_if_fail (info != NULL, NULL);
00102   g_return_val_if_fail (info->refcount > 0, NULL);
00103   
00104   info->refcount += 1;
00105 
00106   return info;
00107 }
00108 
00109 static void
00110 base_info_free (void *ptr)
00111 {
00112   BaseInfo *info;
00113 
00114   info = ptr;
00115   
00116   g_free (info->name);
00117   g_free (info);
00118 }
00119 
00120 void
00121 base_info_unref (BaseInfo *info)
00122 {
00123   g_return_if_fail (info != NULL);
00124   g_return_if_fail (info->refcount > 0);
00125   
00126   /* This is sort of bizarre, BaseInfo was tacked on later */
00127 
00128   switch (info->type)
00129     {
00130     case INFO_TYPE_NODE:
00131       node_info_unref ((NodeInfo*) info);
00132       break;
00133     case INFO_TYPE_INTERFACE:
00134       interface_info_unref ((InterfaceInfo*) info);
00135       break;
00136     case INFO_TYPE_SIGNAL:
00137       signal_info_unref ((SignalInfo*) info);
00138       break;
00139     case INFO_TYPE_METHOD:
00140       method_info_unref ((MethodInfo*) info);
00141       break;
00142     case INFO_TYPE_PROPERTY:
00143       property_info_unref ((PropertyInfo*) info);
00144       break;
00145     case INFO_TYPE_ARG:
00146       arg_info_unref ((ArgInfo*) info);
00147       break;
00148     }
00149 }
00150 
00151 InfoType
00152 base_info_get_type (BaseInfo      *info)
00153 {
00154   return info->type;
00155 }
00156 
00157 const char*
00158 base_info_get_name (BaseInfo *info)
00159 {
00160   return info->name;
00161 }
00162 
00163 void
00164 base_info_set_name (BaseInfo      *info,
00165                     const char    *name)
00166 {
00167   char *old;
00168 
00169   old = info->name;
00170   info->name = g_strdup (name);
00171   g_free (old);
00172 }
00173 
00174 GType
00175 base_info_get_gtype (void)
00176 {
00177   static GType our_type = 0;
00178   
00179   if (our_type == 0)
00180     our_type = g_boxed_type_register_static ("BaseInfo",
00181                                              (GBoxedCopyFunc) base_info_ref,
00182                                              (GBoxedFreeFunc) base_info_unref);
00183 
00184   return our_type;
00185 }
00186 
00187 static void
00188 free_interface_list (GSList **interfaces_p)
00189 {
00190   GSList *tmp;
00191   tmp = *interfaces_p;
00192   while (tmp != NULL)
00193     {
00194       interface_info_unref (tmp->data);
00195       tmp = tmp->next;
00196     }
00197   g_slist_free (*interfaces_p);
00198   *interfaces_p = NULL;
00199 }
00200 
00201 static void
00202 free_node_list (GSList **nodes_p)
00203 {
00204   GSList *tmp;
00205   tmp = *nodes_p;
00206   while (tmp != NULL)
00207     {
00208       node_info_unref (tmp->data);
00209       tmp = tmp->next;
00210     }
00211   g_slist_free (*nodes_p);
00212   *nodes_p = NULL;
00213 }
00214 
00215 static void
00216 free_method_list (GSList **methods_p)
00217 {
00218   GSList *tmp;
00219   tmp = *methods_p;
00220   while (tmp != NULL)
00221     {
00222       method_info_unref (tmp->data);
00223       tmp = tmp->next;
00224     }
00225   g_slist_free (*methods_p);
00226   *methods_p = NULL;
00227 }
00228 
00229 static void
00230 free_signal_list (GSList **signals_p)
00231 {
00232   GSList *tmp;
00233   tmp = *signals_p;
00234   while (tmp != NULL)
00235     {
00236       signal_info_unref (tmp->data);
00237       tmp = tmp->next;
00238     }
00239   g_slist_free (*signals_p);
00240   *signals_p = NULL;
00241 }
00242 
00243 static void
00244 free_property_list (GSList **props_p)
00245 {
00246   GSList *tmp;
00247   tmp = *props_p;
00248   while (tmp != NULL)
00249     {
00250       property_info_unref (tmp->data);
00251       tmp = tmp->next;
00252     }
00253   g_slist_free (*props_p);
00254   *props_p = NULL;
00255 }
00256 
00257 NodeInfo*
00258 node_info_new (const char *name)
00259 {
00260   NodeInfo *info;
00261 
00262   /* name can be NULL */
00263   
00264   info = g_new0 (NodeInfo, 1);
00265   info->base.refcount = 1;
00266   info->base.name = g_strdup (name);
00267   info->base.type = INFO_TYPE_NODE;
00268   
00269   return info;
00270 }
00271 
00272 NodeInfo *
00273 node_info_ref (NodeInfo *info)
00274 {
00275   info->base.refcount += 1;
00276 
00277   return info;
00278 }
00279 
00280 void
00281 node_info_unref (NodeInfo *info)
00282 {
00283   info->base.refcount -= 1;
00284   if (info->base.refcount == 0)
00285     {
00286       free_interface_list (&info->interfaces);
00287       free_node_list (&info->nodes);
00288       base_info_free (info);
00289     }
00290 }
00291 
00292 const char*
00293 node_info_get_name (NodeInfo *info)
00294 {
00295   return info->base.name;
00296 }
00297 
00298 GSList*
00299 node_info_get_interfaces (NodeInfo *info)
00300 {
00301   return info->interfaces;
00302 }
00303 
00304 void
00305 node_info_add_interface (NodeInfo *info,
00306                          InterfaceInfo    *interface)
00307 {
00308   interface_info_ref (interface);
00309   info->interfaces = g_slist_append (info->interfaces, interface);
00310 }
00311 
00312 GSList*
00313 node_info_get_nodes (NodeInfo *info)
00314 {
00315   return info->nodes;
00316 }
00317 
00318 void
00319 node_info_add_node (NodeInfo *info,
00320                     NodeInfo *node)
00321 {
00322   node_info_ref (node);
00323   info->nodes = g_slist_append (info->nodes, node);
00324 }
00325 
00326 void
00327 node_info_replace_node (NodeInfo            *info,
00328                         NodeInfo            *old_child,
00329                         NodeInfo            *new_child)
00330 {
00331   GSList *link;
00332 
00333   node_info_ref (new_child); /* before unref old_child in case they are the same */
00334   link = g_slist_find (info->nodes, old_child);
00335   g_assert (link != NULL);
00336   node_info_unref (old_child);
00337   link->data = new_child;
00338 }
00339 
00340 InterfaceInfo*
00341 interface_info_new (const char *name)
00342 {
00343   InterfaceInfo *info;
00344 
00345   info = g_new0 (InterfaceInfo, 1);
00346   info->base.refcount = 1;
00347   info->base.name = g_strdup (name);
00348   info->base.type = INFO_TYPE_INTERFACE;
00349   info->annotations = g_hash_table_new_full (g_str_hash, g_str_equal,
00350                                              (GDestroyNotify) g_free,
00351                                              (GDestroyNotify) g_free);
00352   
00353   return info;
00354 }
00355 
00356 InterfaceInfo *
00357 interface_info_ref (InterfaceInfo *info)
00358 {
00359   info->base.refcount += 1;
00360 
00361   return info;
00362 }
00363 
00364 void
00365 interface_info_unref (InterfaceInfo *info)
00366 {
00367   info->base.refcount -= 1;
00368   if (info->base.refcount == 0)
00369     {
00370       g_hash_table_destroy (info->annotations);
00371       free_method_list (&info->methods);
00372       free_signal_list (&info->signals);
00373       free_property_list (&info->properties);
00374       base_info_free (info);
00375     }
00376 }
00377 
00378 const char*
00379 interface_info_get_name (InterfaceInfo *info)
00380 {
00381   return info->base.name;
00382 }
00383 
00384 GSList *
00385 interface_info_get_annotations (InterfaceInfo *info)
00386 {
00387   return get_hash_keys (info->annotations);
00388 }
00389 
00390 const char*
00391 interface_info_get_annotation (InterfaceInfo *info,
00392                                const char    *name)
00393 {
00394   return g_hash_table_lookup (info->annotations, name);
00395 }
00396 
00397 GSList*
00398 interface_info_get_methods (InterfaceInfo *info)
00399 {
00400   return info->methods;
00401 }
00402 
00403 GSList*
00404 interface_info_get_signals (InterfaceInfo *info)
00405 {
00406   return info->signals;
00407 }
00408 
00409 GSList*
00410 interface_info_get_properties (InterfaceInfo *info)
00411 {
00412   return info->properties;
00413 }
00414 
00415 void
00416 interface_info_add_annotation (InterfaceInfo *info,
00417                                const char    *name,
00418                                const char    *value)
00419 {
00420   g_hash_table_insert (info->annotations,
00421                        g_strdup (name),
00422                        g_strdup (value));
00423 }
00424 
00425 void
00426 interface_info_add_method (InterfaceInfo *info,
00427                            MethodInfo    *method)
00428 {
00429   method_info_ref (method);
00430   info->methods = g_slist_append (info->methods, method);
00431 }
00432 
00433 void
00434 interface_info_add_signal (InterfaceInfo *info,
00435                            SignalInfo    *signal)
00436 {
00437   signal_info_ref (signal);
00438   info->signals = g_slist_append (info->signals, signal);
00439 }
00440 
00441 void
00442 interface_info_add_property (InterfaceInfo *info,
00443                              PropertyInfo  *property)
00444 {
00445   property_info_ref (property);
00446   info->properties = g_slist_append (info->properties, property);
00447 }
00448 
00449 static void
00450 free_arg_list (GSList **args_p)
00451 {
00452   GSList *tmp;
00453   tmp = *args_p;
00454   while (tmp != NULL)
00455     {
00456       ArgInfo *ai = tmp->data;
00457       g_assert (ai->base.type == INFO_TYPE_ARG);
00458       arg_info_unref (tmp->data);
00459       tmp = tmp->next;
00460     }
00461   g_slist_free (*args_p);
00462   *args_p = NULL;
00463 }
00464 
00465 MethodInfo*
00466 method_info_new (const char *name)
00467 {
00468   MethodInfo *info;
00469 
00470   info = g_new0 (MethodInfo, 1);
00471   info->base.refcount = 1;
00472   info->base.name = g_strdup (name);
00473   info->base.type = INFO_TYPE_METHOD;
00474   info->annotations = g_hash_table_new_full (g_str_hash, g_str_equal,
00475                                           (GDestroyNotify) g_free,
00476                                           (GDestroyNotify) g_free);
00477   
00478   return info;
00479 }
00480 
00481 MethodInfo *
00482 method_info_ref (MethodInfo *info)
00483 {
00484   info->base.refcount += 1;
00485 
00486   return info;
00487 }
00488 
00489 void
00490 method_info_unref (MethodInfo *info)
00491 {
00492   info->base.refcount -= 1;
00493   if (info->base.refcount == 0)
00494     {
00495       g_hash_table_destroy (info->annotations);
00496       free_arg_list (&info->args);
00497       base_info_free (info);
00498     }
00499 }
00500 
00501 const char*
00502 method_info_get_name (MethodInfo *info)
00503 {
00504   return info->base.name;
00505 }
00506 
00507 GSList *
00508 method_info_get_annotations (MethodInfo *info)
00509 {
00510   return get_hash_keys (info->annotations);
00511 }
00512 
00513 const char*
00514 method_info_get_annotation (MethodInfo *info,
00515                             const char *name)
00516 {
00517   return g_hash_table_lookup (info->annotations, name);
00518 }
00519 
00520 GSList*
00521 method_info_get_args (MethodInfo *info)
00522 {
00523   return info->args;
00524 }
00525 
00526 int
00527 method_info_get_n_args (MethodInfo *info)
00528 {
00529   return g_slist_length (info->args);
00530 }
00531 
00532 static int
00533 args_sort_by_direction (const void *a,
00534                         const void *b)
00535 {
00536   const ArgInfo *arg_a = a;
00537   const ArgInfo *arg_b = b;
00538 
00539   if (arg_a->direction == arg_b->direction)
00540     return 0;
00541   else if (arg_a->direction == ARG_IN)
00542     return -1; /* in is less than out */
00543   else
00544     return 1;
00545 }                  
00546 
00547 void
00548 method_info_add_annotation (MethodInfo  *info,
00549                             const char  *name,
00550                             const char  *value)
00551 {
00552   g_hash_table_insert (info->annotations,
00553                        g_strdup (name),
00554                        g_strdup (value));
00555 }
00556 
00557 void
00558 method_info_add_arg (MethodInfo    *info,
00559                      ArgInfo       *arg)
00560 {
00561   arg_info_ref (arg);
00562   info->args = g_slist_append (info->args, arg);
00563 
00564   /* Keep "in" args sorted before "out" and otherwise maintain
00565    * stable order (g_slist_sort is stable, at least in sufficiently
00566    * new glib)
00567    */
00568   info->args = g_slist_sort (info->args, args_sort_by_direction);
00569 }
00570 
00571 SignalInfo*
00572 signal_info_new (const char *name)
00573 {
00574   SignalInfo *info;
00575 
00576   info = g_new0 (SignalInfo, 1);
00577   info->base.refcount = 1;
00578   info->base.name = g_strdup (name);
00579   info->base.type = INFO_TYPE_SIGNAL;
00580   
00581   return info;
00582 }
00583 
00584 SignalInfo *
00585 signal_info_ref (SignalInfo *info)
00586 {
00587   info->base.refcount += 1;
00588 
00589   return info;
00590 }
00591 
00592 void
00593 signal_info_unref (SignalInfo *info)
00594 {
00595   info->base.refcount -= 1;
00596   if (info->base.refcount == 0)
00597     {
00598       free_arg_list (&info->args);
00599       base_info_free (info);
00600     }
00601 }
00602 
00603 const char*
00604 signal_info_get_name (SignalInfo *info)
00605 {
00606   return info->base.name;
00607 }
00608 
00609 GSList*
00610 signal_info_get_args (SignalInfo *info)
00611 {
00612   return info->args;
00613 }
00614 
00615 int
00616 signal_info_get_n_args (SignalInfo *info)
00617 {
00618   return g_slist_length (info->args);
00619 }
00620 
00621 void
00622 signal_info_add_arg (SignalInfo    *info,
00623                      ArgInfo       *arg)
00624 {
00625   g_assert (arg->direction == ARG_OUT);
00626   
00627   arg_info_ref (arg);
00628   info->args = g_slist_append (info->args, arg);
00629   
00630   /* signal args don't need sorting since only "out" is allowed */
00631 }
00632 
00633 PropertyInfo*
00634 property_info_new (const char          *name,
00635                    const char          *type,
00636                    PropertyAccessFlags  access)
00637 {
00638   PropertyInfo *info;
00639 
00640   info = g_new0 (PropertyInfo, 1);
00641   info->base.refcount = 1;
00642   info->base.name = g_strdup (name);
00643   info->base.type = INFO_TYPE_PROPERTY;
00644 
00645   info->type = g_strdup (type);
00646   info->access = access;
00647   
00648   return info;
00649 }
00650 
00651 PropertyInfo*
00652 property_info_ref (PropertyInfo *info)
00653 {
00654   info->base.refcount += 1;
00655   
00656   return info;
00657 }
00658 
00659 void
00660 property_info_unref (PropertyInfo *info)
00661 {
00662   info->base.refcount -= 1;
00663   if (info->base.refcount == 0)
00664     {
00665       g_free (info->type);
00666       base_info_free (info);
00667     }
00668 }
00669 
00670 const char*
00671 property_info_get_name (PropertyInfo *info)
00672 {
00673   return info->base.name;
00674 }
00675 
00676 const char *
00677 property_info_get_type (PropertyInfo *info)
00678 {
00679   return info->type;
00680 }
00681 
00682 PropertyAccessFlags
00683 property_info_get_access (PropertyInfo *info)
00684 {
00685   return info->access;
00686 }
00687 
00688 ArgInfo*
00689 arg_info_new (const char  *name,
00690               ArgDirection direction,
00691               const char  *type)
00692 {
00693   ArgInfo *info;
00694 
00695   info = g_new0 (ArgInfo, 1);
00696   info->base.refcount = 1;
00697   info->base.type = INFO_TYPE_ARG;
00698   
00699   /* name can be NULL */
00700   info->base.name = g_strdup (name);
00701   info->direction = direction;
00702   info->type = g_strdup (type);
00703   info->annotations = g_hash_table_new_full (g_str_hash, g_str_equal,
00704                                              (GDestroyNotify) g_free,
00705                                              (GDestroyNotify) g_free);
00706 
00707   return info;
00708 }
00709 
00710 ArgInfo *
00711 arg_info_ref (ArgInfo *info)
00712 {
00713   info->base.refcount += 1;
00714 
00715   return info;
00716 }
00717 
00718 void
00719 arg_info_unref (ArgInfo *info)
00720 {
00721   info->base.refcount -= 1;
00722   if (info->base.refcount == 0)
00723     {
00724       g_hash_table_destroy (info->annotations);
00725       g_free (info->type);
00726       base_info_free (info);
00727     }
00728 }
00729 
00730 const char*
00731 arg_info_get_name (ArgInfo *info)
00732 {
00733   return info->base.name;
00734 }
00735 
00736 const char *
00737 arg_info_get_type (ArgInfo *info)
00738 {
00739   return info->type;
00740 }
00741 
00742 ArgDirection
00743 arg_info_get_direction (ArgInfo *info)
00744 {
00745   return info->direction;
00746 }
00747 
00748 GSList*
00749 arg_info_get_annotations (ArgInfo *info)
00750 {
00751   return get_hash_keys (info->annotations);
00752 }
00753 
00754 const char*
00755 arg_info_get_annotation (ArgInfo    *info,
00756                          const char *annotation)
00757 {
00758   return g_hash_table_lookup (info->annotations, annotation);
00759 }
00760 
00761 void
00762 arg_info_add_annotation (ArgInfo             *info,
00763                          const char          *name,
00764                          const char          *value)
00765 {
00766   g_hash_table_insert (info->annotations,
00767                        g_strdup (name),
00768                        g_strdup (value));
00769 }
00770 
00771 
00772 #ifdef DBUS_BUILD_TESTS
00773 
00779 gboolean
00780 _dbus_gidl_test (void)
00781 {
00782 
00783   return TRUE;
00784 }
00785 
00786 #endif /* DBUS_BUILD_TESTS */
00787 
00788 #endif /* DOXYGEN_SHOULD_SKIP_THIS */

Generated on Sat Dec 6 19:56:17 2008 for D-BUSGLibBindings by  doxygen 1.5.1