Initial packaging for Tizen
[profile/ivi/gobject-introspection.git] / girepository / gibaseinfo.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2  * GObject introspection: Base struct implementation
3  *
4  * Copyright (C) 2005 Matthias Clasen
5  * Copyright (C) 2008,2009 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <glib.h>
27 #include <glib-object.h>
28
29 #include "gitypelib-internal.h"
30 #include "girepository-private.h"
31
32 #define INVALID_REFCOUNT 0x7FFFFFFF
33
34 /* GBoxed registration of BaseInfo. */
35 GType
36 g_base_info_gtype_get_type (void)
37 {
38   static GType our_type = 0;
39   
40   if (our_type == 0)
41     our_type =
42         g_boxed_type_register_static ("GIBaseInfo",
43                                       (GBoxedCopyFunc) g_base_info_ref,
44                                       (GBoxedFreeFunc) g_base_info_unref);
45
46   return our_type;
47 }
48
49 /* info creation */
50 GIBaseInfo *
51 _g_info_new_full (GIInfoType     type,
52                   GIRepository  *repository,
53                   GIBaseInfo    *container,
54                   GITypelib      *typelib,
55                   guint32        offset)
56 {
57   GIRealInfo *info;
58
59   g_return_val_if_fail (container != NULL || repository != NULL, NULL);
60
61   info = g_slice_new (GIRealInfo);
62
63   _g_info_init (info, type, repository, container, typelib, offset);
64   info->ref_count = 1;
65
66   if (container && ((GIRealInfo *) container)->ref_count != INVALID_REFCOUNT)
67     g_base_info_ref (info->container);
68
69   g_object_ref (info->repository);
70
71   return (GIBaseInfo*)info;
72 }
73
74 GIBaseInfo *
75 g_info_new (GIInfoType     type,
76             GIBaseInfo    *container,
77             GITypelib      *typelib,
78             guint32        offset)
79 {
80   return _g_info_new_full (type, ((GIRealInfo*)container)->repository, container, typelib, offset);
81 }
82
83 void
84 _g_info_init (GIRealInfo     *info,
85               GIInfoType      type,
86               GIRepository   *repository,
87               GIBaseInfo     *container,
88               GITypelib       *typelib,
89               guint32         offset)
90 {
91   memset (info, 0, sizeof (GIRealInfo));
92
93   /* Invalid refcount used to flag stack-allocated infos */
94   info->ref_count = INVALID_REFCOUNT;
95   info->type = type;
96
97   info->typelib = typelib;
98   info->offset = offset;
99
100   if (container)
101     info->container = container;
102
103   g_assert (G_IS_IREPOSITORY (repository));
104   info->repository = repository;
105 }
106
107 GIBaseInfo *
108 _g_info_from_entry (GIRepository *repository,
109                     GITypelib     *typelib,
110                     guint16       index)
111 {
112   GIBaseInfo *result;
113   DirEntry *entry = g_typelib_get_dir_entry (typelib, index);
114
115   if (entry->local)
116     result = _g_info_new_full (entry->blob_type, repository, NULL, typelib, entry->offset);
117   else
118     {
119       const gchar *namespace = g_typelib_get_string (typelib, entry->offset);
120       const gchar *name = g_typelib_get_string (typelib, entry->name);
121
122       result = g_irepository_find_by_name (repository, namespace, name);
123       if (result == NULL)
124         {
125           GIUnresolvedInfo *unresolved;
126
127           unresolved = g_slice_new0 (GIUnresolvedInfo);
128
129           unresolved->type = GI_INFO_TYPE_UNRESOLVED;
130           unresolved->ref_count = 1;
131           unresolved->repository = g_object_ref (repository);
132           unresolved->container = NULL;
133           unresolved->name = name;
134           unresolved->namespace = namespace;
135
136           return (GIBaseInfo *)unresolved;
137         }
138       return (GIBaseInfo *)result;
139     }
140
141   return (GIBaseInfo *)result;
142 }
143
144 GITypeInfo *
145 _g_type_info_new (GIBaseInfo    *container,
146                  GITypelib      *typelib,
147                  guint32        offset)
148 {
149   SimpleTypeBlob *type = (SimpleTypeBlob *)&typelib->data[offset];
150
151   return (GITypeInfo *) g_info_new (GI_INFO_TYPE_TYPE, container, typelib,
152                                     (type->flags.reserved == 0 && type->flags.reserved2 == 0) ? offset : type->offset);
153 }
154
155 void
156 _g_type_info_init (GIBaseInfo *info,
157                    GIBaseInfo *container,
158                    GITypelib   *typelib,
159                    guint32     offset)
160 {
161   GIRealInfo *rinfo = (GIRealInfo*)container;
162   SimpleTypeBlob *type = (SimpleTypeBlob *)&typelib->data[offset];
163
164   _g_info_init ((GIRealInfo*)info, GI_INFO_TYPE_TYPE, rinfo->repository, container, typelib,
165                 (type->flags.reserved == 0 && type->flags.reserved2 == 0) ? offset : type->offset);
166 }
167
168 /* GIBaseInfo functions */
169
170 /**
171  * SECTION:gibaseinfo
172  * @Short_description: Base struct for all GITypelib structs
173  * @Title: GIBaseInfo
174  *
175  * GIBaseInfo is the common base struct of all other *Info structs
176  * accessible through the #GIRepository API.
177  * All other structs can be casted to a #GIBaseInfo, for instance:
178  * <example>
179  * <title>Casting a #GIFunctionInfo to #GIBaseInfo</title>
180  * <programlisting>
181  *    GIFunctionInfo *function_info = ...;
182  *    GIBaseInfo *info = (GIBaseInfo*)function_info;
183  * </programlisting>
184  * </example>
185  * Most #GIRepository APIs returning a #GIBaseInfo is actually creating a new struct, in other
186  * words, g_base_info_unref() has to be called when done accessing the data.
187  * GIBaseInfos are normally accessed by calling either
188  * g_irepository_find_by_name(), g_irepository_find_by_gtype() or g_irepository_get_info().
189  *
190  * <example>
191  * <title>Getting the Button of the Gtk typelib</title>
192  * <programlisting>
193  *    GIBaseInfo *button_info = g_irepository_find_by_name(NULL, "Gtk", "Button");
194  *    ... use button_info ...
195  *    g_base_info_unref(button_info);
196  * </programlisting>
197  * </example>
198  *
199  * <refsect1 id="gi-gibaseinfo.struct-hierarchy" role="struct_hierarchy">
200  * <title role="struct_hierarchy.title">Struct hierarchy</title>
201  * <synopsis>
202  *   GIBaseInfo
203  *    +----<link linkend="gi-GIArgInfo">GIArgInfo</link>
204  *    +----<link linkend="gi-GICallableInfo">GICallableInfo</link>
205  *    +----<link linkend="gi-GIConstantInfo">GIConstantInfo</link>
206  *    +----<link linkend="gi-GIFieldInfo">GIFieldInfo</link>
207  *    +----<link linkend="gi-GIPropertyInfo">GIPropertyInfo</link>
208  *    +----<link linkend="gi-GIRegisteredTypeInfo">GIRegisteredTypeInfo</link>
209  *    +----<link linkend="gi-GITypeInfo">GITypeInfo</link>
210  * </synopsis>
211  * </refsect1>
212  *
213  */
214
215 /**
216  * g_base_info_ref: (skip)
217  * @info: a #GIBaseInfo
218  *
219  * Increases the reference count of @info.
220  *
221  * Returns: the same @info.
222  */
223 GIBaseInfo *
224 g_base_info_ref (GIBaseInfo *info)
225 {
226   GIRealInfo *rinfo = (GIRealInfo*)info;
227
228   g_assert (rinfo->ref_count != INVALID_REFCOUNT);
229   ((GIRealInfo*)info)->ref_count++;
230
231   return info;
232 }
233
234 /**
235  * g_base_info_unref: (skip)
236  * @info: a #GIBaseInfo
237  *
238  * Decreases the reference count of @info. When its reference count
239  * drops to 0, the info is freed.
240  */
241 void
242 g_base_info_unref (GIBaseInfo *info)
243 {
244   GIRealInfo *rinfo = (GIRealInfo*)info;
245
246   g_assert (rinfo->ref_count > 0 && rinfo->ref_count != INVALID_REFCOUNT);
247   rinfo->ref_count--;
248
249   if (!rinfo->ref_count)
250     {
251       if (rinfo->container && ((GIRealInfo *) rinfo->container)->ref_count != INVALID_REFCOUNT)
252         g_base_info_unref (rinfo->container);
253
254       if (rinfo->repository)
255         g_object_unref (rinfo->repository);
256
257       if (rinfo->type == GI_INFO_TYPE_UNRESOLVED)
258         g_slice_free (GIUnresolvedInfo, (GIUnresolvedInfo *) rinfo);
259       else
260         g_slice_free (GIRealInfo, rinfo);
261     }
262 }
263
264 /**
265  * g_base_info_get_type:
266  * @info: a #GIBaseInfo
267  *
268  * Obtain the info type of the GIBaseInfo.
269  *
270  * Returns: the info type of @info
271  */
272 GIInfoType
273 g_base_info_get_type (GIBaseInfo *info)
274 {
275
276   return ((GIRealInfo*)info)->type;
277 }
278
279 /**
280  * g_base_info_get_name:
281  * @info: a #GIBaseInfo
282  *
283  * Obtain the name of the @info. What the name represents depends on
284  * the #GIInfoType of the @info. For instance for #GIFunctionInfo it is
285  * the name of the function.
286  *
287  * Returns: the name of @info or %NULL if it lacks a name.
288  */
289 const gchar *
290 g_base_info_get_name (GIBaseInfo *info)
291 {
292   GIRealInfo *rinfo = (GIRealInfo*)info;
293   g_assert (rinfo->ref_count > 0);
294   switch (rinfo->type)
295     {
296     case GI_INFO_TYPE_FUNCTION:
297     case GI_INFO_TYPE_CALLBACK:
298     case GI_INFO_TYPE_STRUCT:
299     case GI_INFO_TYPE_BOXED:
300     case GI_INFO_TYPE_ENUM:
301     case GI_INFO_TYPE_FLAGS:
302     case GI_INFO_TYPE_OBJECT:
303     case GI_INFO_TYPE_INTERFACE:
304     case GI_INFO_TYPE_CONSTANT:
305     case GI_INFO_TYPE_INVALID_0:
306     case GI_INFO_TYPE_UNION:
307       {
308         CommonBlob *blob = (CommonBlob *)&rinfo->typelib->data[rinfo->offset];
309
310         return g_typelib_get_string (rinfo->typelib, blob->name);
311       }
312       break;
313
314     case GI_INFO_TYPE_VALUE:
315       {
316         ValueBlob *blob = (ValueBlob *)&rinfo->typelib->data[rinfo->offset];
317
318         return g_typelib_get_string (rinfo->typelib, blob->name);
319       }
320       break;
321
322     case GI_INFO_TYPE_SIGNAL:
323       {
324         SignalBlob *blob = (SignalBlob *)&rinfo->typelib->data[rinfo->offset];
325
326         return g_typelib_get_string (rinfo->typelib, blob->name);
327       }
328       break;
329
330     case GI_INFO_TYPE_PROPERTY:
331       {
332         PropertyBlob *blob = (PropertyBlob *)&rinfo->typelib->data[rinfo->offset];
333
334         return g_typelib_get_string (rinfo->typelib, blob->name);
335       }
336       break;
337
338     case GI_INFO_TYPE_VFUNC:
339       {
340         VFuncBlob *blob = (VFuncBlob *)&rinfo->typelib->data[rinfo->offset];
341
342         return g_typelib_get_string (rinfo->typelib, blob->name);
343       }
344       break;
345
346     case GI_INFO_TYPE_FIELD:
347       {
348         FieldBlob *blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
349
350         return g_typelib_get_string (rinfo->typelib, blob->name);
351       }
352       break;
353
354     case GI_INFO_TYPE_ARG:
355       {
356         ArgBlob *blob = (ArgBlob *)&rinfo->typelib->data[rinfo->offset];
357
358         return g_typelib_get_string (rinfo->typelib, blob->name);
359       }
360       break;
361     case GI_INFO_TYPE_UNRESOLVED:
362       {
363         GIUnresolvedInfo *unresolved = (GIUnresolvedInfo *)info;
364
365         return unresolved->name;
366       }
367       break;
368     case GI_INFO_TYPE_TYPE:
369     default: ;
370       g_assert_not_reached ();
371       /* unnamed */
372     }
373
374   return NULL;
375 }
376
377 /**
378  * g_base_info_get_namespace:
379  * @info: a #GIBaseInfo
380  *
381  * Obtain the namespace of @info.
382  *
383  * Returns: the namespace
384  */
385 const gchar *
386 g_base_info_get_namespace (GIBaseInfo *info)
387 {
388   GIRealInfo *rinfo = (GIRealInfo*) info;
389   Header *header = (Header *)rinfo->typelib->data;
390
391   g_assert (rinfo->ref_count > 0);
392
393   if (rinfo->type == GI_INFO_TYPE_UNRESOLVED)
394     {
395       GIUnresolvedInfo *unresolved = (GIUnresolvedInfo *)info;
396
397       return unresolved->namespace;
398     }
399
400   return g_typelib_get_string (rinfo->typelib, header->namespace);
401 }
402
403 /**
404  * g_base_info_is_deprecated:
405  * @info: a #GIBaseInfo
406  *
407  * Obtain whether the @info is represents a metadata which is
408  * deprecated or not.
409  *
410  * Returns: %TRUE if deprecated
411  */
412 gboolean
413 g_base_info_is_deprecated (GIBaseInfo *info)
414 {
415   GIRealInfo *rinfo = (GIRealInfo*) info;
416   switch (rinfo->type)
417     {
418     case GI_INFO_TYPE_FUNCTION:
419     case GI_INFO_TYPE_CALLBACK:
420     case GI_INFO_TYPE_STRUCT:
421     case GI_INFO_TYPE_BOXED:
422     case GI_INFO_TYPE_ENUM:
423     case GI_INFO_TYPE_FLAGS:
424     case GI_INFO_TYPE_OBJECT:
425     case GI_INFO_TYPE_INTERFACE:
426     case GI_INFO_TYPE_CONSTANT:
427     case GI_INFO_TYPE_INVALID_0:
428       {
429         CommonBlob *blob = (CommonBlob *)&rinfo->typelib->data[rinfo->offset];
430
431         return blob->deprecated;
432       }
433       break;
434
435     case GI_INFO_TYPE_VALUE:
436       {
437         ValueBlob *blob = (ValueBlob *)&rinfo->typelib->data[rinfo->offset];
438
439         return blob->deprecated;
440       }
441       break;
442
443     case GI_INFO_TYPE_SIGNAL:
444       {
445         SignalBlob *blob = (SignalBlob *)&rinfo->typelib->data[rinfo->offset];
446
447         return blob->deprecated;
448       }
449       break;
450
451     case GI_INFO_TYPE_PROPERTY:
452       {
453         PropertyBlob *blob = (PropertyBlob *)&rinfo->typelib->data[rinfo->offset];
454
455         return blob->deprecated;
456       }
457       break;
458
459     case GI_INFO_TYPE_VFUNC:
460     case GI_INFO_TYPE_FIELD:
461     case GI_INFO_TYPE_ARG:
462     case GI_INFO_TYPE_TYPE:
463     default: ;
464       /* no deprecation flag for these */
465     }
466
467   return FALSE;
468 }
469
470 /**
471  * g_base_info_get_attribute:
472  * @info: a #GIBaseInfo
473  * @name: a freeform string naming an attribute
474  *
475  * Retrieve an arbitrary attribute associated with this node.
476  *
477  * Returns: The value of the attribute, or %NULL if no such attribute exists
478  */
479 const gchar *
480 g_base_info_get_attribute (GIBaseInfo   *info,
481                            const gchar  *name)
482 {
483   GIAttributeIter iter = { 0, };
484   gchar *curname, *curvalue;
485   while (g_base_info_iterate_attributes (info, &iter, &curname, &curvalue))
486     {
487       if (strcmp (name, curname) == 0)
488         return (const gchar*) curvalue;
489     }
490
491   return NULL;
492 }
493
494 static int
495 cmp_attribute (const void *av,
496                const void *bv)
497 {
498   const AttributeBlob *a = av;
499   const AttributeBlob *b = bv;
500
501   if (a->offset < b->offset)
502     return -1;
503   else if (a->offset == b->offset)
504     return 0;
505   else
506     return 1;
507 }
508
509 /*
510  * _attribute_blob_find_first:
511  * @GIBaseInfo: A #GIBaseInfo.
512  * @blob_offset: The offset for the blob to find the first attribute for.
513  *
514  * Searches for the first #AttributeBlob for @blob_offset and returns
515  * it if found.
516  *
517  * Returns: A pointer to #AttributeBlob or %NULL if not found.
518  */
519 AttributeBlob *
520 _attribute_blob_find_first (GIBaseInfo *info,
521                             guint32     blob_offset)
522 {
523   GIRealInfo *rinfo = (GIRealInfo *) info;
524   Header *header = (Header *)rinfo->typelib->data;
525   AttributeBlob blob, *first, *res, *previous;
526
527   blob.offset = blob_offset;
528
529   first = (AttributeBlob *) &rinfo->typelib->data[header->attributes];
530
531   res = bsearch (&blob, first, header->n_attributes,
532                  header->attribute_blob_size, cmp_attribute);
533
534   if (res == NULL)
535     return NULL;
536
537   previous = res - 1;
538   while (previous >= first && previous->offset == blob_offset)
539     {
540       res = previous;
541       previous = res - 1;
542     }
543
544   return res;
545 }
546
547 /**
548  * g_base_info_iterate_attributes:
549  * @info: a #GIBaseInfo
550  * @iterator: a #GIAttributeIter structure, must be initialized; see below
551  * @name: (out) (transfer none): Returned name, must not be freed
552  * @value: (out) (transfer none): Returned name, must not be freed
553  *
554  * Iterate over all attributes associated with this node.  The iterator
555  * structure is typically stack allocated, and must have its first
556  * member initialized to %NULL.
557  *
558  * Both the @name and @value should be treated as constants
559  * and must not be freed.
560  *
561  * <example>
562  * <title>Iterating over attributes</title>
563  * <programlisting>
564  * void
565  * print_attributes (GIBaseInfo *info)
566  * {
567  *   GIAttributeIter iter = { 0, };
568  *   char *name;
569  *   char *value;
570  *   while (g_base_info_iterate_attributes (info, &iter, &name, &value))
571  *     {
572  *       g_print ("attribute name: %s value: %s", name, value);
573  *     }
574  * }
575  * </programlisting>
576  * </example>
577  *
578  * Returns: %TRUE if there are more attributes
579  */
580 gboolean
581 g_base_info_iterate_attributes (GIBaseInfo      *info,
582                                 GIAttributeIter *iterator,
583                                 gchar           **name,
584                                 gchar           **value)
585 {
586   GIRealInfo *rinfo = (GIRealInfo *)info;
587   Header *header = (Header *)rinfo->typelib->data;
588   AttributeBlob *next, *after;
589
590   after = (AttributeBlob *) &rinfo->typelib->data[header->attributes +
591                                                   header->n_attributes * header->attribute_blob_size];
592
593   if (iterator->data != NULL)
594     next = (AttributeBlob *) iterator->data;
595   else
596     next = _attribute_blob_find_first (info, rinfo->offset);
597
598   if (next == NULL || next->offset != rinfo->offset || next >= after)
599     return FALSE;
600
601   *name = (gchar*) g_typelib_get_string (rinfo->typelib, next->name);
602   *value = (gchar*) g_typelib_get_string (rinfo->typelib, next->value);
603   iterator->data = next + 1;
604
605   return TRUE;
606 }
607
608 /**
609  * g_base_info_get_container:
610  * @info: a #GIBaseInfo
611  *
612  * Obtain the container of the @info. The container is the parent
613  * GIBaseInfo. For instance, the parent of a #GIFunctionInfo is an
614  * #GIObjectInfo or #GIInterfaceInfo.
615  *
616  * Returns: (transfer none): the container
617  */
618 GIBaseInfo *
619 g_base_info_get_container (GIBaseInfo *info)
620 {
621   return ((GIRealInfo*)info)->container;
622 }
623
624 /**
625  * g_base_info_get_typelib:
626  * @info: a #GIBaseInfo
627  *
628  * Obtain the typelib this @info belongs to
629  *
630  * Returns: (transfer none): the typelib.
631  */
632 GITypelib *
633 g_base_info_get_typelib (GIBaseInfo *info)
634 {
635   return ((GIRealInfo*)info)->typelib;
636 }
637
638 /**
639  * g_base_info_equal:
640  * @info1: a #GIBaseInfo
641  * @info2: a #GIBaseInfo
642  *
643  * Compare two #GIBaseInfo.
644  *
645  * Using pointer comparison is not practical since many functions return
646  * different instances of #GIBaseInfo that refers to the same part of the
647  * TypeLib; use this function instead to do #GIBaseInfo comparisons.
648  *
649  * Returns: %TRUE if and only if @info1 equals @info2.
650  */
651 gboolean
652 g_base_info_equal (GIBaseInfo *info1, GIBaseInfo *info2)
653 {
654   /* Compare the TypeLib pointers, which are mmapped. */
655   GIRealInfo *rinfo1 = (GIRealInfo*)info1;
656   GIRealInfo *rinfo2 = (GIRealInfo*)info2;
657   return rinfo1->typelib->data + rinfo1->offset == rinfo2->typelib->data + rinfo2->offset;
658 }
659
660