ofdbus/dbus-glib/dbus/dbus-gidl.c
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 /* -*- mode: C; c-file-style: "gnu" -*- */
       
     2 /* dbus-gidl.c data structure describing an interface, to be generated from IDL
       
     3  *             or something
       
     4  *
       
     5  * Copyright (C) 2003, 2005  Red Hat, Inc.
       
     6  * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
       
     7  * Licensed under the Academic Free License version 2.1
       
     8  *
       
     9  * This program is free software; you can redistribute it and/or modify
       
    10  * it under the terms of the GNU General Public License as published by
       
    11  * the Free Software Foundation; either version 2 of the License, or
       
    12  * (at your option) any later version.
       
    13  *
       
    14  * This program is distributed in the hope that it will be useful,
       
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    17  * GNU General Public License for more details.
       
    18  *
       
    19  * You should have received a copy of the GNU General Public License
       
    20  * along with this program; if not, write to the Free Software
       
    21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    22  *
       
    23  */
       
    24 
       
    25 #include "dbus-gidl.h"
       
    26 
       
    27 #ifndef DOXYGEN_SHOULD_SKIP_THIS
       
    28 
       
    29 struct BaseInfo
       
    30 {
       
    31   unsigned int refcount : 28;
       
    32   unsigned int type     : 4;
       
    33   char *name;
       
    34 };
       
    35 
       
    36 struct NodeInfo
       
    37 {
       
    38   BaseInfo base;
       
    39   GSList *interfaces;
       
    40   GSList *nodes;
       
    41 };
       
    42 
       
    43 struct InterfaceInfo
       
    44 {
       
    45   BaseInfo base;
       
    46   GHashTable *annotations;
       
    47   /* Since we have BaseInfo now these could be one list */
       
    48   GSList *methods;
       
    49   GSList *signals;
       
    50   GSList *properties;
       
    51 };
       
    52 
       
    53 struct MethodInfo
       
    54 {
       
    55   BaseInfo base;
       
    56   GHashTable *annotations;
       
    57   GSList *args;
       
    58 };
       
    59 
       
    60 struct SignalInfo
       
    61 {
       
    62   BaseInfo base;
       
    63   GSList *args;
       
    64 };
       
    65 
       
    66 struct PropertyInfo
       
    67 {
       
    68   BaseInfo base;
       
    69   char *type;
       
    70   PropertyAccessFlags access;
       
    71 };
       
    72 
       
    73 struct ArgInfo
       
    74 {
       
    75   BaseInfo base;
       
    76   char *type;
       
    77   ArgDirection direction;
       
    78   GHashTable *annotations;
       
    79 };
       
    80 
       
    81 static void
       
    82 get_hash_key (gpointer key, gpointer value, gpointer data)
       
    83 {
       
    84   GSList **list = data;
       
    85   *list = g_slist_prepend (*list, key);
       
    86 }
       
    87 
       
    88 static GSList *
       
    89 get_hash_keys (GHashTable *table)
       
    90 {
       
    91   GSList *ret = NULL;
       
    92 
       
    93   g_hash_table_foreach (table, get_hash_key, &ret);
       
    94 
       
    95   return ret;
       
    96 }
       
    97 
       
    98 BaseInfo *
       
    99 base_info_ref (BaseInfo *info)
       
   100 {
       
   101   g_return_val_if_fail (info != NULL, NULL);
       
   102   g_return_val_if_fail (info->refcount > 0, NULL);
       
   103   
       
   104   info->refcount += 1;
       
   105 
       
   106   return info;
       
   107 }
       
   108 
       
   109 static void
       
   110 base_info_free (void *ptr)
       
   111 {
       
   112   BaseInfo *info;
       
   113 
       
   114   info = ptr;
       
   115   
       
   116   g_free (info->name);
       
   117   g_free (info);
       
   118 }
       
   119 
       
   120 void
       
   121 base_info_unref (BaseInfo *info)
       
   122 {
       
   123   g_return_if_fail (info != NULL);
       
   124   g_return_if_fail (info->refcount > 0);
       
   125   
       
   126   /* This is sort of bizarre, BaseInfo was tacked on later */
       
   127 
       
   128   switch (info->type)
       
   129     {
       
   130     case INFO_TYPE_NODE:
       
   131       node_info_unref ((NodeInfo*) info);
       
   132       break;
       
   133     case INFO_TYPE_INTERFACE:
       
   134       interface_info_unref ((InterfaceInfo*) info);
       
   135       break;
       
   136     case INFO_TYPE_SIGNAL:
       
   137       signal_info_unref ((SignalInfo*) info);
       
   138       break;
       
   139     case INFO_TYPE_METHOD:
       
   140       method_info_unref ((MethodInfo*) info);
       
   141       break;
       
   142     case INFO_TYPE_PROPERTY:
       
   143       property_info_unref ((PropertyInfo*) info);
       
   144       break;
       
   145     case INFO_TYPE_ARG:
       
   146       arg_info_unref ((ArgInfo*) info);
       
   147       break;
       
   148     }
       
   149 }
       
   150 
       
   151 InfoType
       
   152 base_info_get_type (BaseInfo      *info)
       
   153 {
       
   154   return info->type;
       
   155 }
       
   156 
       
   157 const char*
       
   158 base_info_get_name (BaseInfo *info)
       
   159 {
       
   160   return info->name;
       
   161 }
       
   162 
       
   163 void
       
   164 base_info_set_name (BaseInfo      *info,
       
   165                     const char    *name)
       
   166 {
       
   167   char *old;
       
   168 
       
   169   old = info->name;
       
   170   info->name = g_strdup (name);
       
   171   g_free (old);
       
   172 }
       
   173 
       
   174 GType
       
   175 base_info_get_gtype (void)
       
   176 {
       
   177  
       
   178   #if EMULATOR
       
   179 GET_STATIC_VAR_FROM_TLS(out_type,dbus_gidl,GType )
       
   180 #define our_type (*GET_DBUS_WSD_VAR_NAME(our_type,dbus_gidl,s)())
       
   181 #else
       
   182   static GType our_type = 0;
       
   183 #endif
       
   184 
       
   185   
       
   186   if (our_type == 0)
       
   187     our_type = g_boxed_type_register_static ("BaseInfo",
       
   188                                              (GBoxedCopyFunc) base_info_ref,
       
   189                                              (GBoxedFreeFunc) base_info_unref);
       
   190 
       
   191   return our_type;
       
   192 }
       
   193 
       
   194 static void
       
   195 free_interface_list (GSList **interfaces_p)
       
   196 {
       
   197   GSList *tmp;
       
   198   tmp = *interfaces_p;
       
   199   while (tmp != NULL)
       
   200     {
       
   201       interface_info_unref (tmp->data);
       
   202       tmp = tmp->next;
       
   203     }
       
   204   g_slist_free (*interfaces_p);
       
   205   *interfaces_p = NULL;
       
   206 }
       
   207 
       
   208 static void
       
   209 free_node_list (GSList **nodes_p)
       
   210 {
       
   211   GSList *tmp;
       
   212   tmp = *nodes_p;
       
   213   while (tmp != NULL)
       
   214     {
       
   215       node_info_unref (tmp->data);
       
   216       tmp = tmp->next;
       
   217     }
       
   218   g_slist_free (*nodes_p);
       
   219   *nodes_p = NULL;
       
   220 }
       
   221 
       
   222 static void
       
   223 free_method_list (GSList **methods_p)
       
   224 {
       
   225   GSList *tmp;
       
   226   tmp = *methods_p;
       
   227   while (tmp != NULL)
       
   228     {
       
   229       method_info_unref (tmp->data);
       
   230       tmp = tmp->next;
       
   231     }
       
   232   g_slist_free (*methods_p);
       
   233   *methods_p = NULL;
       
   234 }
       
   235 
       
   236 static void
       
   237 free_signal_list (GSList **signals_p)
       
   238 {
       
   239   GSList *tmp;
       
   240   tmp = *signals_p;
       
   241   while (tmp != NULL)
       
   242     {
       
   243       signal_info_unref (tmp->data);
       
   244       tmp = tmp->next;
       
   245     }
       
   246   g_slist_free (*signals_p);
       
   247   *signals_p = NULL;
       
   248 }
       
   249 
       
   250 static void
       
   251 free_property_list (GSList **props_p)
       
   252 {
       
   253   GSList *tmp;
       
   254   tmp = *props_p;
       
   255   while (tmp != NULL)
       
   256     {
       
   257       property_info_unref (tmp->data);
       
   258       tmp = tmp->next;
       
   259     }
       
   260   g_slist_free (*props_p);
       
   261   *props_p = NULL;
       
   262 }
       
   263 
       
   264 NodeInfo*
       
   265 node_info_new (const char *name)
       
   266 {
       
   267   NodeInfo *info;
       
   268 
       
   269   /* name can be NULL */
       
   270   
       
   271   info = g_new0 (NodeInfo, 1);
       
   272   info->base.refcount = 1;
       
   273   info->base.name = g_strdup (name);
       
   274   info->base.type = INFO_TYPE_NODE;
       
   275   
       
   276   return info;
       
   277 }
       
   278 
       
   279 NodeInfo *
       
   280 node_info_ref (NodeInfo *info)
       
   281 {
       
   282   info->base.refcount += 1;
       
   283 
       
   284   return info;
       
   285 }
       
   286 
       
   287 void
       
   288 node_info_unref (NodeInfo *info)
       
   289 {
       
   290   info->base.refcount -= 1;
       
   291   if (info->base.refcount == 0)
       
   292     {
       
   293       free_interface_list (&info->interfaces);
       
   294       free_node_list (&info->nodes);
       
   295       base_info_free (info);
       
   296     }
       
   297 }
       
   298 
       
   299 const char*
       
   300 node_info_get_name (NodeInfo *info)
       
   301 {
       
   302   return info->base.name;
       
   303 }
       
   304 
       
   305 GSList*
       
   306 node_info_get_interfaces (NodeInfo *info)
       
   307 {
       
   308   return info->interfaces;
       
   309 }
       
   310 
       
   311 void
       
   312 node_info_add_interface (NodeInfo *info,
       
   313                          InterfaceInfo    *interface)
       
   314 {
       
   315   interface_info_ref (interface);
       
   316   info->interfaces = g_slist_append (info->interfaces, interface);
       
   317 }
       
   318 
       
   319 GSList*
       
   320 node_info_get_nodes (NodeInfo *info)
       
   321 {
       
   322   return info->nodes;
       
   323 }
       
   324 
       
   325 void
       
   326 node_info_add_node (NodeInfo *info,
       
   327                     NodeInfo *node)
       
   328 {
       
   329   node_info_ref (node);
       
   330   info->nodes = g_slist_append (info->nodes, node);
       
   331 }
       
   332 
       
   333 void
       
   334 node_info_replace_node (NodeInfo            *info,
       
   335                         NodeInfo            *old_child,
       
   336                         NodeInfo            *new_child)
       
   337 {
       
   338   GSList *link;
       
   339 
       
   340   node_info_ref (new_child); /* before unref old_child in case they are the same */
       
   341   link = g_slist_find (info->nodes, old_child);
       
   342   g_assert (link != NULL);
       
   343   node_info_unref (old_child);
       
   344   link->data = new_child;
       
   345 }
       
   346 
       
   347 InterfaceInfo*
       
   348 interface_info_new (const char *name)
       
   349 {
       
   350   InterfaceInfo *info;
       
   351 
       
   352   info = g_new0 (InterfaceInfo, 1);
       
   353   info->base.refcount = 1;
       
   354   info->base.name = g_strdup (name);
       
   355   info->base.type = INFO_TYPE_INTERFACE;
       
   356   info->annotations = g_hash_table_new_full (g_str_hash, g_str_equal,
       
   357 					     (GDestroyNotify) g_free,
       
   358 					     (GDestroyNotify) g_free);
       
   359   
       
   360   return info;
       
   361 }
       
   362 
       
   363 InterfaceInfo *
       
   364 interface_info_ref (InterfaceInfo *info)
       
   365 {
       
   366   info->base.refcount += 1;
       
   367 
       
   368   return info;
       
   369 }
       
   370 
       
   371 void
       
   372 interface_info_unref (InterfaceInfo *info)
       
   373 {
       
   374   info->base.refcount -= 1;
       
   375   if (info->base.refcount == 0)
       
   376     {
       
   377       g_hash_table_destroy (info->annotations);
       
   378       free_method_list (&info->methods);
       
   379       free_signal_list (&info->signals);
       
   380       free_property_list (&info->properties);
       
   381       base_info_free (info);
       
   382     }
       
   383 }
       
   384 
       
   385 const char*
       
   386 interface_info_get_name (InterfaceInfo *info)
       
   387 {
       
   388   return info->base.name;
       
   389 }
       
   390 
       
   391 GSList *
       
   392 interface_info_get_annotations (InterfaceInfo *info)
       
   393 {
       
   394   return get_hash_keys (info->annotations);
       
   395 }
       
   396 
       
   397 const char*
       
   398 interface_info_get_annotation (InterfaceInfo *info,
       
   399 			       const char    *name)
       
   400 {
       
   401   return g_hash_table_lookup (info->annotations, name);
       
   402 }
       
   403 
       
   404 GSList*
       
   405 interface_info_get_methods (InterfaceInfo *info)
       
   406 {
       
   407   return info->methods;
       
   408 }
       
   409 
       
   410 GSList*
       
   411 interface_info_get_signals (InterfaceInfo *info)
       
   412 {
       
   413   return info->signals;
       
   414 }
       
   415 
       
   416 GSList*
       
   417 interface_info_get_properties (InterfaceInfo *info)
       
   418 {
       
   419   return info->properties;
       
   420 }
       
   421 
       
   422 void
       
   423 interface_info_add_annotation (InterfaceInfo *info,
       
   424 			       const char    *name,
       
   425 			       const char    *value)
       
   426 {
       
   427   g_hash_table_insert (info->annotations,
       
   428 		       g_strdup (name),
       
   429 		       g_strdup (value));
       
   430 }
       
   431 
       
   432 void
       
   433 interface_info_add_method (InterfaceInfo *info,
       
   434                            MethodInfo    *method)
       
   435 {
       
   436   method_info_ref (method);
       
   437   info->methods = g_slist_append (info->methods, method);
       
   438 }
       
   439 
       
   440 void
       
   441 interface_info_add_signal (InterfaceInfo *info,
       
   442                            SignalInfo    *signal)
       
   443 {
       
   444   signal_info_ref (signal);
       
   445   info->signals = g_slist_append (info->signals, signal);
       
   446 }
       
   447 
       
   448 void
       
   449 interface_info_add_property (InterfaceInfo *info,
       
   450                              PropertyInfo  *property)
       
   451 {
       
   452   property_info_ref (property);
       
   453   info->properties = g_slist_append (info->properties, property);
       
   454 }
       
   455 
       
   456 static void
       
   457 free_arg_list (GSList **args_p)
       
   458 {
       
   459   GSList *tmp;
       
   460   tmp = *args_p;
       
   461   while (tmp != NULL)
       
   462     {
       
   463       ArgInfo *ai = tmp->data;
       
   464       g_assert (ai->base.type == INFO_TYPE_ARG);
       
   465       arg_info_unref (tmp->data);
       
   466       tmp = tmp->next;
       
   467     }
       
   468   g_slist_free (*args_p);
       
   469   *args_p = NULL;
       
   470 }
       
   471 
       
   472 MethodInfo*
       
   473 method_info_new (const char *name)
       
   474 {
       
   475   MethodInfo *info;
       
   476 
       
   477   info = g_new0 (MethodInfo, 1);
       
   478   info->base.refcount = 1;
       
   479   info->base.name = g_strdup (name);
       
   480   info->base.type = INFO_TYPE_METHOD;
       
   481   info->annotations = g_hash_table_new_full (g_str_hash, g_str_equal,
       
   482 					  (GDestroyNotify) g_free,
       
   483 					  (GDestroyNotify) g_free);
       
   484   
       
   485   return info;
       
   486 }
       
   487 
       
   488 MethodInfo *
       
   489 method_info_ref (MethodInfo *info)
       
   490 {
       
   491   info->base.refcount += 1;
       
   492 
       
   493   return info;
       
   494 }
       
   495 
       
   496 void
       
   497 method_info_unref (MethodInfo *info)
       
   498 {
       
   499   info->base.refcount -= 1;
       
   500   if (info->base.refcount == 0)
       
   501     {
       
   502       g_hash_table_destroy (info->annotations);
       
   503       free_arg_list (&info->args);
       
   504       base_info_free (info);
       
   505     }
       
   506 }
       
   507 
       
   508 const char*
       
   509 method_info_get_name (MethodInfo *info)
       
   510 {
       
   511   return info->base.name;
       
   512 }
       
   513 
       
   514 GSList *
       
   515 method_info_get_annotations (MethodInfo *info)
       
   516 {
       
   517   return get_hash_keys (info->annotations);
       
   518 }
       
   519 
       
   520 const char*
       
   521 method_info_get_annotation (MethodInfo *info,
       
   522 			    const char *name)
       
   523 {
       
   524   return g_hash_table_lookup (info->annotations, name);
       
   525 }
       
   526 
       
   527 GSList*
       
   528 method_info_get_args (MethodInfo *info)
       
   529 {
       
   530   return info->args;
       
   531 }
       
   532 
       
   533 int
       
   534 method_info_get_n_args (MethodInfo *info)
       
   535 {
       
   536   return g_slist_length (info->args);
       
   537 }
       
   538 
       
   539 static int
       
   540 args_sort_by_direction (const void *a,
       
   541                         const void *b)
       
   542 {
       
   543   const ArgInfo *arg_a = a;
       
   544   const ArgInfo *arg_b = b;
       
   545 
       
   546   if (arg_a->direction == arg_b->direction)
       
   547     return 0;
       
   548   else if (arg_a->direction == ARG_IN)
       
   549     return -1; /* in is less than out */
       
   550   else
       
   551     return 1;
       
   552 }                  
       
   553 
       
   554 void
       
   555 method_info_add_annotation (MethodInfo  *info,
       
   556 			    const char  *name,
       
   557 			    const char  *value)
       
   558 {
       
   559   g_hash_table_insert (info->annotations,
       
   560 		       g_strdup (name),
       
   561 		       g_strdup (value));
       
   562 }
       
   563 
       
   564 void
       
   565 method_info_add_arg (MethodInfo    *info,
       
   566                      ArgInfo       *arg)
       
   567 {
       
   568   arg_info_ref (arg);
       
   569   info->args = g_slist_append (info->args, arg);
       
   570 
       
   571   /* Keep "in" args sorted before "out" and otherwise maintain
       
   572    * stable order (g_slist_sort is stable, at least in sufficiently
       
   573    * new glib)
       
   574    */
       
   575   info->args = g_slist_sort (info->args, args_sort_by_direction);
       
   576 }
       
   577 
       
   578 SignalInfo*
       
   579 signal_info_new (const char *name)
       
   580 {
       
   581   SignalInfo *info;
       
   582 
       
   583   info = g_new0 (SignalInfo, 1);
       
   584   info->base.refcount = 1;
       
   585   info->base.name = g_strdup (name);
       
   586   info->base.type = INFO_TYPE_SIGNAL;
       
   587   
       
   588   return info;
       
   589 }
       
   590 
       
   591 SignalInfo *
       
   592 signal_info_ref (SignalInfo *info)
       
   593 {
       
   594   info->base.refcount += 1;
       
   595 
       
   596   return info;
       
   597 }
       
   598 
       
   599 void
       
   600 signal_info_unref (SignalInfo *info)
       
   601 {
       
   602   info->base.refcount -= 1;
       
   603   if (info->base.refcount == 0)
       
   604     {
       
   605       free_arg_list (&info->args);
       
   606       base_info_free (info);
       
   607     }
       
   608 }
       
   609 
       
   610 const char*
       
   611 signal_info_get_name (SignalInfo *info)
       
   612 {
       
   613   return info->base.name;
       
   614 }
       
   615 
       
   616 GSList*
       
   617 signal_info_get_args (SignalInfo *info)
       
   618 {
       
   619   return info->args;
       
   620 }
       
   621 
       
   622 int
       
   623 signal_info_get_n_args (SignalInfo *info)
       
   624 {
       
   625   return g_slist_length (info->args);
       
   626 }
       
   627 
       
   628 void
       
   629 signal_info_add_arg (SignalInfo    *info,
       
   630                      ArgInfo       *arg)
       
   631 {
       
   632   g_assert (arg->direction == ARG_OUT);
       
   633   
       
   634   arg_info_ref (arg);
       
   635   info->args = g_slist_append (info->args, arg);
       
   636   
       
   637   /* signal args don't need sorting since only "out" is allowed */
       
   638 }
       
   639 
       
   640 PropertyInfo*
       
   641 property_info_new (const char          *name,
       
   642                    const char          *type,
       
   643                    PropertyAccessFlags  access)
       
   644 {
       
   645   PropertyInfo *info;
       
   646 
       
   647   info = g_new0 (PropertyInfo, 1);
       
   648   info->base.refcount = 1;
       
   649   info->base.name = g_strdup (name);
       
   650   info->base.type = INFO_TYPE_PROPERTY;
       
   651 
       
   652   info->type = g_strdup (type);
       
   653   info->access = access;
       
   654   
       
   655   return info;
       
   656 }
       
   657 
       
   658 PropertyInfo*
       
   659 property_info_ref (PropertyInfo *info)
       
   660 {
       
   661   info->base.refcount += 1;
       
   662   
       
   663   return info;
       
   664 }
       
   665 
       
   666 void
       
   667 property_info_unref (PropertyInfo *info)
       
   668 {
       
   669   info->base.refcount -= 1;
       
   670   if (info->base.refcount == 0)
       
   671     {
       
   672       g_free (info->type);
       
   673       base_info_free (info);
       
   674     }
       
   675 }
       
   676 
       
   677 const char*
       
   678 property_info_get_name (PropertyInfo *info)
       
   679 {
       
   680   return info->base.name;
       
   681 }
       
   682 
       
   683 const char *
       
   684 property_info_get_type (PropertyInfo *info)
       
   685 {
       
   686   return info->type;
       
   687 }
       
   688 
       
   689 PropertyAccessFlags
       
   690 property_info_get_access (PropertyInfo *info)
       
   691 {
       
   692   return info->access;
       
   693 }
       
   694 
       
   695 ArgInfo*
       
   696 arg_info_new (const char  *name,
       
   697               ArgDirection direction,
       
   698               const char  *type)
       
   699 {
       
   700   ArgInfo *info;
       
   701 
       
   702   info = g_new0 (ArgInfo, 1);
       
   703   info->base.refcount = 1;
       
   704   info->base.type = INFO_TYPE_ARG;
       
   705   
       
   706   /* name can be NULL */
       
   707   info->base.name = g_strdup (name);
       
   708   info->direction = direction;
       
   709   info->type = g_strdup (type);
       
   710   info->annotations = g_hash_table_new_full (g_str_hash, g_str_equal,
       
   711 					     (GDestroyNotify) g_free,
       
   712 					     (GDestroyNotify) g_free);
       
   713 
       
   714   return info;
       
   715 }
       
   716 
       
   717 ArgInfo *
       
   718 arg_info_ref (ArgInfo *info)
       
   719 {
       
   720   info->base.refcount += 1;
       
   721 
       
   722   return info;
       
   723 }
       
   724 
       
   725 void
       
   726 arg_info_unref (ArgInfo *info)
       
   727 {
       
   728   info->base.refcount -= 1;
       
   729   if (info->base.refcount == 0)
       
   730     {
       
   731       g_hash_table_destroy (info->annotations);
       
   732       g_free (info->type);
       
   733       base_info_free (info);
       
   734     }
       
   735 }
       
   736 
       
   737 const char*
       
   738 arg_info_get_name (ArgInfo *info)
       
   739 {
       
   740   return info->base.name;
       
   741 }
       
   742 
       
   743 const char *
       
   744 arg_info_get_type (ArgInfo *info)
       
   745 {
       
   746   return info->type;
       
   747 }
       
   748 
       
   749 ArgDirection
       
   750 arg_info_get_direction (ArgInfo *info)
       
   751 {
       
   752   return info->direction;
       
   753 }
       
   754 
       
   755 GSList*
       
   756 arg_info_get_annotations (ArgInfo *info)
       
   757 {
       
   758   return get_hash_keys (info->annotations);
       
   759 }
       
   760 
       
   761 const char*
       
   762 arg_info_get_annotation (ArgInfo    *info,
       
   763 			 const char *annotation)
       
   764 {
       
   765   return g_hash_table_lookup (info->annotations, annotation);
       
   766 }
       
   767 
       
   768 void
       
   769 arg_info_add_annotation (ArgInfo             *info,
       
   770 			 const char          *name,
       
   771 			 const char          *value)
       
   772 {
       
   773   g_hash_table_insert (info->annotations,
       
   774 		       g_strdup (name),
       
   775 		       g_strdup (value));
       
   776 }
       
   777 
       
   778 
       
   779 #ifdef DBUS_BUILD_TESTS
       
   780 
       
   781 /**
       
   782  * @ingroup DBusGIDL
       
   783  * Unit test for GLib IDL internals
       
   784  * Returns: #TRUE on success.
       
   785  */
       
   786 gboolean
       
   787 _dbus_gidl_test (void)
       
   788 {
       
   789 
       
   790   return TRUE;
       
   791 }
       
   792 
       
   793 #endif /* DBUS_BUILD_TESTS */
       
   794 
       
   795 #endif /* DOXYGEN_SHOULD_SKIP_THIS */