Add g_file_info_has_namespace
[platform/upstream/glib.git] / gio / gfileinfo.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 /**
24  * SECTION:gfileinfo
25  * @short_description: File Information and Attributes
26  * @include: gio/gio.h
27  * @see_also: #GFile, <link linkend="gio-GFileAttribute">GFileAttribute</link>
28  * 
29  * Functionality for manipulating basic metadata for files. #GFileInfo
30  * implements methods for getting information that all files should 
31  * contain, and allows for manipulation of extended attributes. 
32  *
33  * See <link linkend="gio-GFileAttribute">GFileAttribute</link> for more
34  * information on how GIO handles file attributes.
35  *
36  * To obtain a #GFileInfo for a #GFile, use g_file_query_info() (or its 
37  * async variant). To obtain a #GFileInfo for a file input or output 
38  * stream, use g_file_input_stream_query_info() or 
39  * g_file_output_stream_query_info() (or their async variants).
40  *
41  * To change the actual attributes of a file, you should then set the 
42  * attribute in the #GFileInfo and call g_file_set_attributes_from_info() 
43  * or g_file_set_attributes_async() on a GFile.
44  *
45  * However, not all attributes can be changed in the file. For instance, 
46  * the actual size of a file cannot be changed via g_file_info_set_size(). 
47  * You may call g_file_query_settable_attributes() and 
48  * g_file_query_writable_namespaces() to discover the settable attributes 
49  * of a particular file at runtime.
50  *
51  * #GFileAttributeMatcher allows for searching through a #GFileInfo for 
52  * attributes.
53  **/
54
55 #include "config.h"
56
57 #include <string.h>
58
59 #include "gfileinfo.h"
60 #include "gfileattribute-priv.h"
61 #include "gicon.h"
62 #include "glibintl.h"
63
64 #include "gioalias.h"
65
66 /* We use this nasty thing, because NULL is a valid attribute matcher (matches nothing) */
67 #define NO_ATTRIBUTE_MASK ((GFileAttributeMatcher *)1)
68
69 typedef struct  {
70   guint32 attribute;
71   GFileAttributeValue value;
72 } GFileAttribute;
73
74 struct _GFileInfo
75 {
76   GObject parent_instance;
77
78   GArray *attributes;
79   GFileAttributeMatcher *mask;
80 };
81
82 struct _GFileInfoClass
83 {
84   GObjectClass parent_class;
85 };
86
87
88 static gboolean g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
89                                                      guint32 id);
90
91 G_DEFINE_TYPE (GFileInfo, g_file_info, G_TYPE_OBJECT);
92
93 typedef struct {
94   guint32 id;
95   guint32 attribute_id_counter;
96 } NSInfo;
97
98 G_LOCK_DEFINE_STATIC (attribute_hash);
99 static int namespace_id_counter = 0;
100 static GHashTable *ns_hash = NULL;
101 static GHashTable *attribute_hash = NULL;
102 static char ***attributes = NULL;
103
104 /* Attribute ids are 32bit, we split it up like this:
105  * |------------|--------------------|
106  *   12 bit          20 bit       
107  *   namespace      attribute id    
108  *
109  * This way the attributes gets sorted in namespace order
110  */
111
112 #define NS_POS 20
113 #define NS_MASK ((guint32)((1<<12) - 1))
114 #define ID_POS 0
115 #define ID_MASK ((guint32)((1<<20) - 1))
116
117 #define GET_NS(_attr_id) \
118     (((guint32) (_attr_id) >> NS_POS) & NS_MASK)
119 #define GET_ID(_attr_id) \
120     (((guint32)(_attr_id) >> ID_POS) & ID_MASK)
121
122 #define MAKE_ATTR_ID(_ns, _id)                          \
123     ( ((((guint32) _ns) & NS_MASK) << NS_POS) |         \
124       ((((guint32) _id) & ID_MASK) << ID_POS) )
125
126 static NSInfo *
127 _lookup_namespace (const char *namespace)
128 {
129   NSInfo *ns_info;
130   
131   ns_info = g_hash_table_lookup (ns_hash, namespace);
132   if (ns_info == NULL)
133     {
134       ns_info = g_new0 (NSInfo, 1);
135       ns_info->id = ++namespace_id_counter;
136       g_hash_table_insert (ns_hash, g_strdup (namespace), ns_info);
137       attributes = g_realloc (attributes, (ns_info->id + 1) * sizeof (char **));
138       attributes[ns_info->id] = NULL;
139     }
140   return ns_info;
141 }
142
143 static guint32
144 lookup_namespace (const char *namespace)
145 {
146   NSInfo *ns_info;
147   guint32 id;
148   
149   G_LOCK (attribute_hash);
150   
151   if (attribute_hash == NULL)
152     {
153       ns_hash = g_hash_table_new (g_str_hash, g_str_equal);
154       attribute_hash = g_hash_table_new (g_str_hash, g_str_equal);
155     }
156
157   ns_info = _lookup_namespace (namespace);
158   id = 0;
159   if (ns_info)
160     id = ns_info->id;
161   
162   G_UNLOCK (attribute_hash);
163
164   return id;
165 }
166
167 static char *
168 get_attribute_for_id (int attribute)
169 {
170   char *s;
171   G_LOCK (attribute_hash);
172   s = attributes[GET_NS(attribute)][GET_ID(attribute)];
173   G_UNLOCK (attribute_hash);
174   return s;
175 }
176
177 static guint32
178 lookup_attribute (const char *attribute)
179 {
180   guint32 attr_id, id;
181   char *ns;
182   const char *colon;
183   NSInfo *ns_info;
184   
185   G_LOCK (attribute_hash);
186   if (attribute_hash == NULL)
187     {
188       ns_hash = g_hash_table_new (g_str_hash, g_str_equal);
189       attribute_hash = g_hash_table_new (g_str_hash, g_str_equal);
190     }
191
192   attr_id = GPOINTER_TO_UINT (g_hash_table_lookup (attribute_hash, attribute));
193
194   if (attr_id != 0)
195     {
196       G_UNLOCK (attribute_hash);
197       return attr_id;
198     }
199
200   colon = strstr (attribute, "::");
201   if (colon)
202     ns = g_strndup (attribute, colon - attribute);
203   else
204     ns = g_strdup ("");
205
206   ns_info = _lookup_namespace (ns);
207   g_free (ns);
208
209   id = ++ns_info->attribute_id_counter;
210   attributes[ns_info->id] = g_realloc (attributes[ns_info->id], (id + 1) * sizeof (char *));
211   attributes[ns_info->id][id] = g_strdup (attribute);
212   
213   attr_id = MAKE_ATTR_ID (ns_info->id, id);
214
215   g_hash_table_insert (attribute_hash, attributes[ns_info->id][id], GUINT_TO_POINTER (attr_id));
216   
217   G_UNLOCK (attribute_hash);
218   
219   return attr_id;
220 }
221
222 static void
223 g_file_info_finalize (GObject *object)
224 {
225   GFileInfo *info;
226   int i;
227   GFileAttribute *attrs;
228
229   info = G_FILE_INFO (object);
230
231   attrs = (GFileAttribute *)info->attributes->data;
232   for (i = 0; i < info->attributes->len; i++)
233     _g_file_attribute_value_clear (&attrs[i].value);
234   g_array_free (info->attributes, TRUE);  
235
236   if (info->mask != NO_ATTRIBUTE_MASK)
237     g_file_attribute_matcher_unref (info->mask);
238
239   G_OBJECT_CLASS (g_file_info_parent_class)->finalize (object);
240 }
241
242 static void
243 g_file_info_class_init (GFileInfoClass *klass)
244 {
245   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
246   
247   gobject_class->finalize = g_file_info_finalize;
248 }
249
250 static void
251 g_file_info_init (GFileInfo *info)
252 {
253   info->mask = NO_ATTRIBUTE_MASK;
254   info->attributes = g_array_new (FALSE, FALSE,
255                                   sizeof (GFileAttribute));
256 }
257
258 /**
259  * g_file_info_new:
260  * 
261  * Creates a new file info structure.
262  * 
263  * Returns: a #GFileInfo.
264  **/
265 GFileInfo *
266 g_file_info_new (void)
267 {
268   return g_object_new (G_TYPE_FILE_INFO, NULL);
269 }
270
271 /**
272  * g_file_info_copy_into:
273  * @src_info: source to copy attributes from.
274  * @dest_info: destination to copy attributes to.
275  * 
276  * Copies all of the #GFileAttribute<!-- -->s from @src_info to @dest_info.
277  **/
278 void
279 g_file_info_copy_into (GFileInfo *src_info, 
280                        GFileInfo *dest_info)
281 {
282   GFileAttribute *source, *dest;
283   int i;
284
285   g_return_if_fail (G_IS_FILE_INFO (src_info));
286   g_return_if_fail (G_IS_FILE_INFO (dest_info));
287
288   dest = (GFileAttribute *)dest_info->attributes->data;
289   for (i = 0; i < dest_info->attributes->len; i++)
290     _g_file_attribute_value_clear (&dest[i].value);
291   
292   g_array_set_size (dest_info->attributes,
293                     src_info->attributes->len);
294
295   source = (GFileAttribute *)src_info->attributes->data;
296   dest = (GFileAttribute *)dest_info->attributes->data;
297   
298   for (i = 0; i < src_info->attributes->len; i++)
299     {
300       dest[i].attribute = source[i].attribute;
301       dest[i].value.type = G_FILE_ATTRIBUTE_TYPE_INVALID;
302       _g_file_attribute_value_set (&dest[i].value, &source[i].value);
303     }
304
305   if (dest_info->mask != NO_ATTRIBUTE_MASK)
306     g_file_attribute_matcher_unref (dest_info->mask);
307
308   if (src_info->mask == NO_ATTRIBUTE_MASK)
309     dest_info->mask = NO_ATTRIBUTE_MASK;
310   else
311     dest_info->mask = g_file_attribute_matcher_ref (src_info->mask);
312 }
313
314 /**
315  * g_file_info_dup:
316  * @other: a #GFileInfo.
317  * 
318  * Duplicates a file info structure.
319  * 
320  * Returns: a duplicate #GFileInfo of @other.
321  **/
322 GFileInfo *
323 g_file_info_dup (GFileInfo *other)
324 {
325   GFileInfo *new;
326   
327   g_return_val_if_fail (G_IS_FILE_INFO (other), NULL);
328   
329   new = g_file_info_new ();
330   g_file_info_copy_into (other, new);
331   return new;
332 }
333
334 /**
335  * g_file_info_set_attribute_mask:
336  * @info: a #GFileInfo.
337  * @mask: a #GFileAttributeMatcher.
338  *
339  * Sets @mask on @info to match specific attribute types.
340  **/
341 void
342 g_file_info_set_attribute_mask (GFileInfo             *info,
343                                 GFileAttributeMatcher *mask)
344 {
345   GFileAttribute *attr;
346   int i;
347   
348   g_return_if_fail (G_IS_FILE_INFO (info));
349   
350   if (mask != info->mask)
351     {
352       if (info->mask != NO_ATTRIBUTE_MASK)
353         g_file_attribute_matcher_unref (info->mask);
354       info->mask = g_file_attribute_matcher_ref (mask);
355
356       /* Remove non-matching attributes */
357       for (i = 0; i < info->attributes->len; i++)
358         {
359           attr = &g_array_index (info->attributes, GFileAttribute, i);
360           if (!g_file_attribute_matcher_matches_id (mask,
361                                                     attr->attribute))
362             {
363               _g_file_attribute_value_clear (&attr->value);
364               g_array_remove_index (info->attributes, i);
365               i--;
366             }
367         }
368     }
369 }
370
371 /**
372  * g_file_info_unset_attribute_mask:
373  * @info: #GFileInfo.
374  * 
375  * Unsets a mask set by g_file_info_set_attribute_mask(), if one
376  * is set.
377  **/
378 void
379 g_file_info_unset_attribute_mask (GFileInfo *info)
380 {
381   g_return_if_fail (G_IS_FILE_INFO (info));
382
383   if (info->mask != NO_ATTRIBUTE_MASK)
384     g_file_attribute_matcher_unref (info->mask);
385   info->mask = NO_ATTRIBUTE_MASK;
386 }
387
388 /**
389  * g_file_info_clear_status:
390  * @info: a #GFileInfo.
391  *
392  * Clears the status information from @info.
393  **/
394 void
395 g_file_info_clear_status (GFileInfo  *info)
396 {
397   GFileAttribute *attrs;
398   int i;
399   
400   g_return_if_fail (G_IS_FILE_INFO (info));
401
402   attrs = (GFileAttribute *)info->attributes->data;
403   for (i = 0; i < info->attributes->len; i++)
404     attrs[i].value.status = G_FILE_ATTRIBUTE_STATUS_UNSET;
405 }
406
407 static int
408 g_file_info_find_place (GFileInfo  *info,
409                         guint32     attribute)
410 {
411   int min, max, med;
412   GFileAttribute *attrs;
413   /* Binary search for the place where attribute would be, if it's
414      in the array */
415
416   min = 0;
417   max = info->attributes->len;
418
419   attrs = (GFileAttribute *)info->attributes->data;
420
421   while (min < max)
422     {
423       med = min + (max - min) / 2;
424       if (attrs[med].attribute == attribute)
425         {
426           min = med;
427           break;
428         }
429       else if (attrs[med].attribute < attribute)
430         min = med + 1;
431       else /* attrs[med].attribute > attribute */
432         max = med;
433     }
434
435   return min;
436 }
437
438 static GFileAttributeValue *
439 g_file_info_find_value (GFileInfo *info,
440                         guint32    attr_id)
441 {
442   GFileAttribute *attrs;
443   int i;
444
445   i = g_file_info_find_place (info, attr_id);
446   attrs = (GFileAttribute *)info->attributes->data;
447   if (i < info->attributes->len &&
448       attrs[i].attribute == attr_id)
449     return &attrs[i].value;
450   
451   return NULL;
452 }
453
454 static GFileAttributeValue *
455 g_file_info_find_value_by_name (GFileInfo  *info,
456                                 const char *attribute)
457 {
458   guint32 attr_id;
459
460   attr_id = lookup_attribute (attribute);
461   return g_file_info_find_value (info, attr_id);
462 }
463
464 /**
465  * g_file_info_has_attribute:
466  * @info: a #GFileInfo.
467  * @attribute: a file attribute key.
468  * 
469  * Checks if a file info structure has an attribute named @attribute.
470  * 
471  * Returns: %TRUE if @Ginfo has an attribute named @attribute, 
472  *     %FALSE otherwise.
473  **/
474 gboolean
475 g_file_info_has_attribute (GFileInfo  *info,
476                            const char *attribute)
477 {
478   GFileAttributeValue *value;
479
480   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
481   g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
482
483   value = g_file_info_find_value_by_name (info, attribute);
484   return value != NULL;
485 }
486
487 /**
488  * g_file_info_has_namespace:
489  * @info: a #GFileInfo.
490  * @name_space: a file attribute namespace.
491  *
492  * Checks if a file info structure has an attribute in the
493  * specified @name_space.
494  *
495  * Returns: %TRUE if @Ginfo has an attribute in @name_space,
496  *     %FALSE otherwise.
497  *
498  * Since: 2.22
499  **/
500 gboolean
501 g_file_info_has_namespace (GFileInfo  *info,
502                            const char *name_space)
503 {
504   GFileAttribute *attrs;
505   guint32 ns_id;
506   int i;
507
508   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
509   g_return_val_if_fail (name_space != NULL, FALSE);
510
511   ns_id = lookup_namespace (name_space);
512
513   attrs = (GFileAttribute *)info->attributes->data;
514   for (i = 0; i < info->attributes->len; i++)
515     {
516       if (GET_NS (attrs[i].attribute) == ns_id)
517         return TRUE;
518     }
519
520   return FALSE;
521 }
522
523 /**
524  * g_file_info_list_attributes:
525  * @info: a #GFileInfo.
526  * @name_space: a file attribute key's namespace.
527  * 
528  * Lists the file info structure's attributes.
529  * 
530  * Returns: a null-terminated array of strings of all of the 
531  * possible attribute types for the given @name_space, or 
532  * %NULL on error.
533  **/
534 char **
535 g_file_info_list_attributes (GFileInfo  *info,
536                              const char *name_space)
537 {
538   GPtrArray *names;
539   GFileAttribute *attrs;
540   guint32 attribute;
541   guint32 ns_id = (name_space) ? lookup_namespace (name_space) : 0;
542   int i;
543  
544   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
545
546   names = g_ptr_array_new ();
547   attrs = (GFileAttribute *)info->attributes->data;
548   for (i = 0; i < info->attributes->len; i++)
549     {
550       attribute = attrs[i].attribute;
551       if (ns_id == 0 || GET_NS (attribute) == ns_id)
552         g_ptr_array_add (names, g_strdup (get_attribute_for_id (attribute)));
553     }
554
555   /* NULL terminate */
556   g_ptr_array_add (names, NULL);
557   
558   return (char **)g_ptr_array_free (names, FALSE);
559 }
560
561 /**
562  * g_file_info_get_attribute_type:
563  * @info: a #GFileInfo.
564  * @attribute: a file attribute key.
565  * 
566  * Gets the attribute type for an attribute key.
567  * 
568  * Returns: a #GFileAttributeType for the given @attribute, or 
569  * %G_FILE_ATTRIBUTE_TYPE_INVALID if the key is invalid.
570  **/
571 GFileAttributeType
572 g_file_info_get_attribute_type (GFileInfo  *info,
573                                 const char *attribute)
574 {
575   GFileAttributeValue *value;
576   
577   g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_ATTRIBUTE_TYPE_INVALID);
578   g_return_val_if_fail (attribute != NULL && *attribute != '\0', G_FILE_ATTRIBUTE_TYPE_INVALID);
579
580   value = g_file_info_find_value_by_name (info, attribute);
581   if (value)
582     return value->type;
583   else
584     return G_FILE_ATTRIBUTE_TYPE_INVALID;
585 }
586
587 /**
588  * g_file_info_remove_attribute:
589  * @info: a #GFileInfo.
590  * @attribute: a file attribute key.
591  * 
592  * Removes all cases of @attribute from @info if it exists.
593  **/
594 void
595 g_file_info_remove_attribute (GFileInfo  *info,
596                               const char *attribute)
597 {
598   guint32 attr_id;
599   GFileAttribute *attrs;
600   int i;
601
602   g_return_if_fail (G_IS_FILE_INFO (info));
603   g_return_if_fail (attribute != NULL && *attribute != '\0');
604
605   attr_id = lookup_attribute (attribute);
606   
607   i = g_file_info_find_place (info, attr_id);
608   attrs = (GFileAttribute *)info->attributes->data;
609   if (i < info->attributes->len &&
610       attrs[i].attribute == attr_id)
611     {
612       _g_file_attribute_value_clear (&attrs[i].value);
613       g_array_remove_index (info->attributes, i);
614     }
615 }
616
617 /**
618  * g_file_info_get_attribute_data:
619  * @info: a #GFileInfo
620  * @attribute: a file attribute key
621  * @type: return location for the attribute type, or %NULL
622  * @value_pp: return location for the attribute value, or %NULL
623  * @status: return location for the attribute status, or %NULL
624  *
625  * Gets the attribute type, value and status for an attribute key.
626  *
627  * Returns: %TRUE if @info has an attribute named @attribute, 
628  *      %FALSE otherwise.
629  */
630 gboolean
631 g_file_info_get_attribute_data (GFileInfo            *info,
632                                 const char           *attribute,
633                                 GFileAttributeType   *type,
634                                 gpointer             *value_pp,
635                                 GFileAttributeStatus *status)
636 {
637   GFileAttributeValue *value;
638
639   value = g_file_info_find_value_by_name (info, attribute);
640   if (value == NULL)
641     return FALSE;
642
643   if (status)
644     *status = value->status;
645
646   if (type)
647     *type = value->type;
648
649   if (value_pp)
650     *value_pp = _g_file_attribute_value_peek_as_pointer (value);
651   
652   return TRUE;
653 }
654
655 /** 
656  * g_file_info_get_attribute_status:
657  * @info: a #GFileInfo
658  * @attribute: a file attribute key
659  *
660  * Gets the attribute status for an attribute key.
661  *
662  * Returns: a #GFileAttributeStatus for the given @attribute, or 
663  *    %G_FILE_ATTRIBUTE_STATUS_UNSET if the key is invalid.
664  *
665  */
666 GFileAttributeStatus
667 g_file_info_get_attribute_status (GFileInfo  *info,
668                                   const char *attribute)
669 {
670   GFileAttributeValue *val;
671   
672   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
673   g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
674
675   val = g_file_info_find_value_by_name (info, attribute);
676   if (val)
677     return val->status;
678
679   return G_FILE_ATTRIBUTE_STATUS_UNSET;
680 }
681
682
683 GFileAttributeValue *
684 _g_file_info_get_attribute_value (GFileInfo  *info,
685                                   const char *attribute)
686   
687 {
688   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
689   g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
690
691   return g_file_info_find_value_by_name (info, attribute);
692 }
693
694 /**
695  * g_file_info_get_attribute_as_string:
696  * @info: a #GFileInfo.
697  * @attribute: a file attribute key.
698  * 
699  * Gets the value of a attribute, formated as a string.
700  * This escapes things as needed to make the string valid
701  * utf8.
702  * 
703  * Returns: a UTF-8 string associated with the given @attribute.
704  *    When you're done with the string it must be freed with g_free().
705  **/
706 char *
707 g_file_info_get_attribute_as_string (GFileInfo  *info,
708                                      const char *attribute)
709 {
710   GFileAttributeValue *val;
711   val = _g_file_info_get_attribute_value (info, attribute);
712   if (val) 
713     return _g_file_attribute_value_as_string (val);
714   return NULL;
715 }
716
717
718 /**
719  * g_file_info_get_attribute_object:
720  * @info: a #GFileInfo.
721  * @attribute: a file attribute key.
722  * 
723  * Gets the value of a #GObject attribute. If the attribute does 
724  * not contain a #GObject, %NULL will be returned.
725  * 
726  * Returns: a #GObject associated with the given @attribute, or
727  * %NULL otherwise.
728  **/
729 GObject *
730 g_file_info_get_attribute_object (GFileInfo  *info,
731                                   const char *attribute)
732 {
733   GFileAttributeValue *value;
734   
735   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
736   g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
737
738   value = g_file_info_find_value_by_name (info, attribute);
739   return _g_file_attribute_value_get_object (value);
740 }
741
742 /**
743  * g_file_info_get_attribute_string:
744  * @info: a #GFileInfo.
745  * @attribute: a file attribute key.
746  * 
747  * Gets the value of a string attribute. If the attribute does 
748  * not contain a string, %NULL will be returned.
749  * 
750  * Returns: the contents of the @attribute value as a string, or 
751  * %NULL otherwise.
752  **/
753 const char *
754 g_file_info_get_attribute_string (GFileInfo  *info,
755                                   const char *attribute)
756 {
757   GFileAttributeValue *value;
758   
759   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
760   g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
761
762   value = g_file_info_find_value_by_name (info, attribute);
763   return _g_file_attribute_value_get_string (value);
764 }
765
766 /**
767  * g_file_info_get_attribute_byte_string:
768  * @info: a #GFileInfo.
769  * @attribute: a file attribute key.
770  * 
771  * Gets the value of a byte string attribute. If the attribute does 
772  * not contain a byte string, %NULL will be returned.
773  * 
774  * Returns: the contents of the @attribute value as a byte string, or 
775  * %NULL otherwise.
776  **/
777 const char *
778 g_file_info_get_attribute_byte_string (GFileInfo  *info,
779                                        const char *attribute)
780 {
781   GFileAttributeValue *value;
782   
783   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
784   g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
785
786   value = g_file_info_find_value_by_name (info, attribute);
787   return _g_file_attribute_value_get_byte_string (value);
788 }
789
790 /**
791  * g_file_info_get_attribute_stringv:
792  * @info: a #GFileInfo.
793  * @attribute: a file attribute key.
794  *
795  * Gets the value of a stringv attribute. If the attribute does
796  * not contain a stringv, %NULL will be returned.
797  *
798  * Returns: the contents of the @attribute value as a stringv, or
799  * %NULL otherwise. Do not free.
800  **/
801 char **
802 g_file_info_get_attribute_stringv (GFileInfo  *info,
803                                    const char *attribute)
804 {
805   GFileAttributeValue *value;
806
807   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
808   g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
809
810   value = g_file_info_find_value_by_name (info, attribute);
811   return _g_file_attribute_value_get_stringv (value);
812 }
813
814 /**
815  * g_file_info_get_attribute_boolean:
816  * @info: a #GFileInfo.
817  * @attribute: a file attribute key.
818  * 
819  * Gets the value of a boolean attribute. If the attribute does not
820  * contain a boolean value, %FALSE will be returned.
821  * 
822  * Returns: the boolean value contained within the attribute. 
823  **/
824 gboolean
825 g_file_info_get_attribute_boolean (GFileInfo  *info,
826                                    const char *attribute)
827 {
828   GFileAttributeValue *value;
829   
830   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
831   g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
832
833   value = g_file_info_find_value_by_name (info, attribute);
834   return _g_file_attribute_value_get_boolean (value);
835 }
836
837 /**
838  * g_file_info_get_attribute_uint32:
839  * @info: a #GFileInfo.
840  * @attribute: a file attribute key.
841  * 
842  * Gets an unsigned 32-bit integer contained within the attribute. If the 
843  * attribute does not contain an unsigned 32-bit integer, or is invalid, 
844  * 0 will be returned.
845  * 
846  * Returns: an unsigned 32-bit integer from the attribute. 
847  **/
848 guint32
849 g_file_info_get_attribute_uint32 (GFileInfo  *info,
850                                   const char *attribute)
851 {
852   GFileAttributeValue *value;
853   
854   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
855   g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
856
857   value = g_file_info_find_value_by_name (info, attribute);
858   return _g_file_attribute_value_get_uint32 (value);
859 }
860
861 /**
862  * g_file_info_get_attribute_int32:
863  * @info: a #GFileInfo.
864  * @attribute: a file attribute key.
865  * 
866  * Gets a signed 32-bit integer contained within the attribute. If the 
867  * attribute does not contain a signed 32-bit integer, or is invalid, 
868  * 0 will be returned.
869  * 
870  * Returns: a signed 32-bit integer from the attribute.
871  **/
872 gint32
873 g_file_info_get_attribute_int32 (GFileInfo  *info,
874                                  const char *attribute)
875 {
876   GFileAttributeValue *value;
877
878   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
879   g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
880
881   value = g_file_info_find_value_by_name (info, attribute);
882   return _g_file_attribute_value_get_int32 (value);
883 }
884
885 /**
886  * g_file_info_get_attribute_uint64:
887  * @info: a #GFileInfo.
888  * @attribute: a file attribute key.
889  * 
890  * Gets a unsigned 64-bit integer contained within the attribute. If the 
891  * attribute does not contain an unsigned 64-bit integer, or is invalid, 
892  * 0 will be returned.
893  * 
894  * Returns: a unsigned 64-bit integer from the attribute. 
895  **/
896 guint64
897 g_file_info_get_attribute_uint64 (GFileInfo  *info,
898                                   const char *attribute)
899 {
900   GFileAttributeValue *value;
901
902   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
903   g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
904
905   value = g_file_info_find_value_by_name (info, attribute);
906   return _g_file_attribute_value_get_uint64 (value);
907 }
908
909 /**
910  * g_file_info_get_attribute_int64:
911  * @info: a #GFileInfo.
912  * @attribute: a file attribute key.
913  * 
914  * Gets a signed 64-bit integer contained within the attribute. If the 
915  * attribute does not contain an signed 64-bit integer, or is invalid, 
916  * 0 will be returned.
917  * 
918  * Returns: a signed 64-bit integer from the attribute. 
919  **/
920 gint64
921 g_file_info_get_attribute_int64  (GFileInfo  *info,
922                                   const char *attribute)
923 {
924   GFileAttributeValue *value;
925
926   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
927   g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
928
929   value = g_file_info_find_value_by_name (info, attribute);
930   return _g_file_attribute_value_get_int64 (value);
931 }
932
933 static GFileAttributeValue *
934 g_file_info_create_value (GFileInfo *info,
935                           guint32 attr_id)
936 {
937   GFileAttribute *attrs;
938   int i;
939
940   if (info->mask != NO_ATTRIBUTE_MASK &&
941       !g_file_attribute_matcher_matches_id (info->mask, attr_id))
942     return NULL;
943   
944   i = g_file_info_find_place (info, attr_id);
945   
946   attrs = (GFileAttribute *)info->attributes->data;
947   if (i < info->attributes->len &&
948       attrs[i].attribute == attr_id)
949     return &attrs[i].value;
950   else
951     {
952       GFileAttribute attr = { 0 };
953       attr.attribute = attr_id;
954       g_array_insert_val (info->attributes, i, attr);
955
956       attrs = (GFileAttribute *)info->attributes->data;
957       return &attrs[i].value;
958     }
959 }
960
961 static GFileAttributeValue *
962 g_file_info_create_value_by_name (GFileInfo *info,
963                                   const char *attribute)
964 {
965   guint32 attr_id;
966
967   attr_id = lookup_attribute (attribute);
968
969   return g_file_info_create_value (info, attr_id);
970 }
971
972 /**
973  * g_file_info_set_attribute:
974  * @info: a #GFileInfo.
975  * @attribute: a file attribute key.
976  * @type: a #GFileAttributeType
977  * @value_p: pointer to the value
978  * 
979  * Sets the @attribute to contain the given value, if possible.
980  **/
981 void
982 g_file_info_set_attribute (GFileInfo                 *info,
983                            const char                *attribute,
984                            GFileAttributeType         type,
985                            gpointer                   value_p)
986 {
987   GFileAttributeValue *value;
988
989   g_return_if_fail (G_IS_FILE_INFO (info));
990   g_return_if_fail (attribute != NULL && *attribute != '\0');
991
992   value = g_file_info_create_value_by_name (info, attribute);
993
994   if (value)
995     _g_file_attribute_value_set_from_pointer (value, type, value_p, TRUE);
996 }
997
998 /**
999  * g_file_info_set_attribute_object:
1000  * @info: a #GFileInfo.
1001  * @attribute: a file attribute key.
1002  * @attr_value: a #GObject.
1003  * 
1004  * Sets the @attribute to contain the given @attr_value, 
1005  * if possible.
1006  **/
1007 void
1008 g_file_info_set_attribute_object (GFileInfo  *info,
1009                                   const char *attribute,
1010                                   GObject    *attr_value)
1011 {
1012   GFileAttributeValue *value;
1013
1014   g_return_if_fail (G_IS_FILE_INFO (info));
1015   g_return_if_fail (attribute != NULL && *attribute != '\0');
1016   g_return_if_fail (G_IS_OBJECT (attr_value));
1017
1018   value = g_file_info_create_value_by_name (info, attribute);
1019   if (value)
1020     _g_file_attribute_value_set_object (value, attr_value);
1021 }
1022
1023 /**
1024  * g_file_info_set_attribute_stringv:
1025  * @info: a #GFileInfo.
1026  * @attribute: a file attribute key.
1027  * @attr_value: a %NULL terminated string array
1028  *
1029  * Sets the @attribute to contain the given @attr_value,
1030  * if possible.
1031  *
1032  * Sinze: 2.22
1033  **/
1034 void
1035 g_file_info_set_attribute_stringv (GFileInfo  *info,
1036                                    const char *attribute,
1037                                    char      **attr_value)
1038 {
1039   GFileAttributeValue *value;
1040
1041   g_return_if_fail (G_IS_FILE_INFO (info));
1042   g_return_if_fail (attribute != NULL && *attribute != '\0');
1043   g_return_if_fail (attr_value != NULL);
1044
1045   value = g_file_info_create_value_by_name (info, attribute);
1046   if (value)
1047     _g_file_attribute_value_set_stringv (value, attr_value);
1048 }
1049
1050 /**
1051  * g_file_info_set_attribute_string:
1052  * @info: a #GFileInfo.
1053  * @attribute: a file attribute key.
1054  * @attr_value: a string.
1055  * 
1056  * Sets the @attribute to contain the given @attr_value, 
1057  * if possible.
1058  **/
1059 void
1060 g_file_info_set_attribute_string (GFileInfo  *info,
1061                                   const char *attribute,
1062                                   const char *attr_value)
1063 {
1064   GFileAttributeValue *value;
1065   
1066   g_return_if_fail (G_IS_FILE_INFO (info));
1067   g_return_if_fail (attribute != NULL && *attribute != '\0');
1068   g_return_if_fail (attr_value != NULL);
1069
1070   value = g_file_info_create_value_by_name (info, attribute);
1071   if (value)
1072     _g_file_attribute_value_set_string (value, attr_value);
1073 }
1074
1075 /**
1076  * g_file_info_set_attribute_byte_string:
1077  * @info: a #GFileInfo.
1078  * @attribute: a file attribute key.
1079  * @attr_value: a byte string.
1080  * 
1081  * Sets the @attribute to contain the given @attr_value, 
1082  * if possible.
1083  **/
1084 void
1085 g_file_info_set_attribute_byte_string (GFileInfo  *info,
1086                                        const char *attribute,
1087                                        const char *attr_value)
1088 {
1089   GFileAttributeValue *value;
1090
1091   g_return_if_fail (G_IS_FILE_INFO (info));
1092   g_return_if_fail (attribute != NULL && *attribute != '\0');
1093   g_return_if_fail (attr_value != NULL);
1094
1095   value = g_file_info_create_value_by_name (info, attribute);
1096   if (value)
1097     _g_file_attribute_value_set_byte_string (value, attr_value);
1098 }
1099
1100 /**
1101  * g_file_info_set_attribute_boolean:
1102  * @info: a #GFileInfo.
1103  * @attribute: a file attribute key.
1104  * @attr_value: a boolean value.
1105  * 
1106  * Sets the @attribute to contain the given @attr_value, 
1107  * if possible.
1108  **/
1109 void
1110 g_file_info_set_attribute_boolean (GFileInfo  *info,
1111                                    const char *attribute,
1112                                    gboolean    attr_value)
1113 {
1114   GFileAttributeValue *value;
1115
1116   g_return_if_fail (G_IS_FILE_INFO (info));
1117   g_return_if_fail (attribute != NULL && *attribute != '\0');
1118
1119   value = g_file_info_create_value_by_name (info, attribute);
1120   if (value)
1121     _g_file_attribute_value_set_boolean (value, attr_value);
1122 }
1123
1124 /**
1125  * g_file_info_set_attribute_uint32:
1126  * @info: a #GFileInfo.
1127  * @attribute: a file attribute key.
1128  * @attr_value: an unsigned 32-bit integer.
1129  * 
1130  * Sets the @attribute to contain the given @attr_value, 
1131  * if possible.
1132  **/
1133 void
1134 g_file_info_set_attribute_uint32 (GFileInfo  *info,
1135                                   const char *attribute,
1136                                   guint32     attr_value)
1137 {
1138   GFileAttributeValue *value;
1139
1140   g_return_if_fail (G_IS_FILE_INFO (info));
1141   g_return_if_fail (attribute != NULL && *attribute != '\0');
1142
1143   value = g_file_info_create_value_by_name (info, attribute);
1144   if (value)
1145     _g_file_attribute_value_set_uint32 (value, attr_value);
1146 }
1147
1148
1149 /**
1150  * g_file_info_set_attribute_int32:
1151  * @info: a #GFileInfo.
1152  * @attribute: a file attribute key.
1153  * @attr_value: a signed 32-bit integer
1154  * 
1155  * Sets the @attribute to contain the given @attr_value, 
1156  * if possible.
1157  **/
1158 void
1159 g_file_info_set_attribute_int32 (GFileInfo  *info,
1160                                  const char *attribute,
1161                                  gint32      attr_value)
1162 {
1163   GFileAttributeValue *value;
1164  
1165   g_return_if_fail (G_IS_FILE_INFO (info));
1166   g_return_if_fail (attribute != NULL && *attribute != '\0');
1167
1168   value = g_file_info_create_value_by_name (info, attribute);
1169   if (value)
1170     _g_file_attribute_value_set_int32 (value, attr_value);
1171 }
1172
1173 /**
1174  * g_file_info_set_attribute_uint64:
1175  * @info: a #GFileInfo.
1176  * @attribute: a file attribute key.
1177  * @attr_value: an unsigned 64-bit integer.
1178  * 
1179  * Sets the @attribute to contain the given @attr_value, 
1180  * if possible.
1181  **/
1182 void
1183 g_file_info_set_attribute_uint64 (GFileInfo  *info,
1184                                   const char *attribute,
1185                                   guint64     attr_value)
1186 {
1187   GFileAttributeValue *value;
1188
1189   g_return_if_fail (G_IS_FILE_INFO (info));
1190   g_return_if_fail (attribute != NULL && *attribute != '\0');
1191
1192   value = g_file_info_create_value_by_name (info, attribute);
1193   if (value)
1194     _g_file_attribute_value_set_uint64 (value, attr_value);
1195 }
1196
1197 /**
1198  * g_file_info_set_attribute_int64:
1199  * @info: a #GFileInfo.
1200  * @attribute: attribute name to set.
1201  * @attr_value: int64 value to set attribute to.
1202  * 
1203  * Sets the @attribute to contain the given @attr_value, 
1204  * if possible.
1205  * 
1206  **/
1207 void
1208 g_file_info_set_attribute_int64  (GFileInfo  *info,
1209                                   const char *attribute,
1210                                   gint64      attr_value)
1211 {
1212   GFileAttributeValue *value;
1213
1214   g_return_if_fail (G_IS_FILE_INFO (info));
1215   g_return_if_fail (attribute != NULL && *attribute != '\0');
1216
1217   value = g_file_info_create_value_by_name (info, attribute);
1218   if (value)
1219     _g_file_attribute_value_set_int64 (value, attr_value);
1220 }
1221
1222 /* Helper getters */
1223 /**
1224  * g_file_info_get_file_type:
1225  * @info: a #GFileInfo.
1226  * 
1227  * Gets a file's type (whether it is a regular file, symlink, etc). 
1228  * This is different from the file's content type, see g_file_info_get_content_type().
1229  * 
1230  * Returns: a #GFileType for the given file.
1231  **/
1232 GFileType
1233 g_file_info_get_file_type (GFileInfo *info)
1234 {
1235   static guint32 attr = 0;
1236   GFileAttributeValue *value;
1237
1238   g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_TYPE_UNKNOWN);
1239   
1240   if (attr == 0)
1241     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_TYPE);
1242   
1243   value = g_file_info_find_value (info, attr);
1244   return (GFileType)_g_file_attribute_value_get_uint32 (value);
1245 }
1246
1247 /**
1248  * g_file_info_get_is_hidden:
1249  * @info: a #GFileInfo.
1250  * 
1251  * Checks if a file is hidden.
1252  * 
1253  * Returns: %TRUE if the file is a hidden file, %FALSE otherwise.
1254  **/
1255 gboolean
1256 g_file_info_get_is_hidden (GFileInfo *info)
1257 {
1258   static guint32 attr = 0;
1259   GFileAttributeValue *value;
1260   
1261   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1262   
1263   if (attr == 0)
1264     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
1265   
1266   value = g_file_info_find_value (info, attr);
1267   return (GFileType)_g_file_attribute_value_get_boolean (value);
1268 }
1269
1270 /**
1271  * g_file_info_get_is_backup:
1272  * @info: a #GFileInfo.
1273  * 
1274  * Checks if a file is a backup file.
1275  * 
1276  * Returns: %TRUE if file is a backup file, %FALSE otherwise.
1277  **/
1278 gboolean
1279 g_file_info_get_is_backup (GFileInfo *info)
1280 {
1281   static guint32 attr = 0;
1282   GFileAttributeValue *value;
1283   
1284   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1285   
1286   if (attr == 0)
1287     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP);
1288   
1289   value = g_file_info_find_value (info, attr);
1290   return (GFileType)_g_file_attribute_value_get_boolean (value);
1291 }
1292
1293 /**
1294  * g_file_info_get_is_symlink:
1295  * @info: a #GFileInfo.
1296  * 
1297  * Checks if a file is a symlink.
1298  * 
1299  * Returns: %TRUE if the given @info is a symlink.
1300  **/
1301 gboolean
1302 g_file_info_get_is_symlink (GFileInfo *info)
1303 {
1304   static guint32 attr = 0;
1305   GFileAttributeValue *value;
1306   
1307   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1308   
1309   if (attr == 0)
1310     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
1311   
1312   value = g_file_info_find_value (info, attr);
1313   return (GFileType)_g_file_attribute_value_get_boolean (value);
1314 }
1315
1316 /**
1317  * g_file_info_get_name:
1318  * @info: a #GFileInfo.
1319  * 
1320  * Gets the name for a file.
1321  * 
1322  * Returns: a string containing the file name.
1323  **/
1324 const char *
1325 g_file_info_get_name (GFileInfo *info)
1326 {
1327   static guint32 attr = 0;
1328   GFileAttributeValue *value;
1329   
1330   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1331   
1332   if (attr == 0)
1333     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_NAME);
1334   
1335   value = g_file_info_find_value (info, attr);
1336   return _g_file_attribute_value_get_byte_string (value);
1337 }
1338
1339 /**
1340  * g_file_info_get_display_name:
1341  * @info: a #GFileInfo.
1342  * 
1343  * Gets a display name for a file.
1344  * 
1345  * Returns: a string containing the display name.
1346  **/
1347 const char *
1348 g_file_info_get_display_name (GFileInfo *info)
1349 {
1350   static guint32 attr = 0;
1351   GFileAttributeValue *value;
1352   
1353   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1354   
1355   if (attr == 0)
1356     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
1357   
1358   value = g_file_info_find_value (info, attr);
1359   return _g_file_attribute_value_get_string (value);
1360 }
1361
1362 /**
1363  * g_file_info_get_edit_name:
1364  * @info: a #GFileInfo.
1365  * 
1366  * Gets the edit name for a file.
1367  * 
1368  * Returns: a string containing the edit name.
1369  **/
1370 const char *
1371 g_file_info_get_edit_name (GFileInfo *info)
1372 {
1373   static guint32 attr = 0;
1374   GFileAttributeValue *value;
1375   
1376   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1377   
1378   if (attr == 0)
1379     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
1380   
1381   value = g_file_info_find_value (info, attr);
1382   return _g_file_attribute_value_get_string (value);
1383 }
1384
1385 /**
1386  * g_file_info_get_icon:
1387  * @info: a #GFileInfo.
1388  * 
1389  * Gets the icon for a file.
1390  * 
1391  * Returns: #GIcon for the given @info.
1392  **/
1393 GIcon *
1394 g_file_info_get_icon (GFileInfo *info)
1395 {
1396   static guint32 attr = 0;
1397   GFileAttributeValue *value;
1398   GObject *obj;
1399   
1400   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1401   
1402   if (attr == 0)
1403     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_ICON);
1404   
1405   value = g_file_info_find_value (info, attr);
1406   obj = _g_file_attribute_value_get_object (value);
1407   if (G_IS_ICON (obj))
1408     return G_ICON (obj);
1409   return NULL;
1410 }
1411
1412 /**
1413  * g_file_info_get_content_type:
1414  * @info: a #GFileInfo.
1415  * 
1416  * Gets the file's content type.
1417  * 
1418  * Returns: a string containing the file's content type.
1419  **/
1420 const char *
1421 g_file_info_get_content_type (GFileInfo *info)
1422 {
1423   static guint32 attr = 0;
1424   GFileAttributeValue *value;
1425   
1426   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1427   
1428   if (attr == 0)
1429     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
1430   
1431   value = g_file_info_find_value (info, attr);
1432   return _g_file_attribute_value_get_string (value);
1433 }
1434
1435 /**
1436  * g_file_info_get_size:
1437  * @info: a #GFileInfo.
1438  * 
1439  * Gets the file's size.
1440  * 
1441  * Returns: a #goffset containing the file's size. 
1442  **/
1443 goffset
1444 g_file_info_get_size (GFileInfo *info)
1445 {
1446   static guint32 attr = 0;
1447   GFileAttributeValue *value;
1448  
1449   g_return_val_if_fail (G_IS_FILE_INFO (info), (goffset) 0);
1450   
1451   if (attr == 0)
1452     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SIZE);
1453   
1454   value = g_file_info_find_value (info, attr);
1455   return (goffset) _g_file_attribute_value_get_uint64 (value);
1456 }
1457
1458 /**
1459  * g_file_info_get_modification_time:
1460  * @info: a #GFileInfo.
1461  * @result: a #GTimeVal.
1462  * 
1463  * Gets the modification time of the current @info and sets it
1464  * in @result.
1465  **/
1466 void
1467 g_file_info_get_modification_time (GFileInfo *info,
1468                                    GTimeVal  *result)
1469 {
1470   static guint32 attr_mtime = 0, attr_mtime_usec;
1471   GFileAttributeValue *value;
1472
1473   g_return_if_fail (G_IS_FILE_INFO (info));
1474   g_return_if_fail (result != NULL);
1475   
1476   if (attr_mtime == 0)
1477     {
1478       attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1479       attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1480     }
1481   
1482   value = g_file_info_find_value (info, attr_mtime);
1483   result->tv_sec = _g_file_attribute_value_get_uint64 (value);
1484   value = g_file_info_find_value (info, attr_mtime_usec);
1485   result->tv_usec = _g_file_attribute_value_get_uint32 (value);
1486 }
1487
1488 /**
1489  * g_file_info_get_symlink_target:
1490  * @info: a #GFileInfo.
1491  * 
1492  * Gets the symlink target for a given #GFileInfo.
1493  * 
1494  * Returns: a string containing the symlink target.
1495  **/
1496 const char *
1497 g_file_info_get_symlink_target (GFileInfo *info)
1498 {
1499   static guint32 attr = 0;
1500   GFileAttributeValue *value;
1501   
1502   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1503   
1504   if (attr == 0)
1505     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
1506   
1507   value = g_file_info_find_value (info, attr);
1508   return _g_file_attribute_value_get_byte_string (value);
1509 }
1510
1511 /**
1512  * g_file_info_get_etag:
1513  * @info: a #GFileInfo.
1514  * 
1515  * Gets the <link linkend="gfile-etag">entity tag</link> for a given 
1516  * #GFileInfo. See %G_FILE_ATTRIBUTE_ETAG_VALUE.
1517  * 
1518  * Returns: a string containing the value of the "etag:value" attribute.
1519  **/
1520 const char *
1521 g_file_info_get_etag (GFileInfo *info)
1522 {
1523   static guint32 attr = 0;
1524   GFileAttributeValue *value;
1525   
1526   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1527   
1528   if (attr == 0)
1529     attr = lookup_attribute (G_FILE_ATTRIBUTE_ETAG_VALUE);
1530   
1531   value = g_file_info_find_value (info, attr);
1532   return _g_file_attribute_value_get_string (value);
1533 }
1534
1535 /**
1536  * g_file_info_get_sort_order:
1537  * @info: a #GFileInfo.
1538  * 
1539  * Gets the value of the sort_order attribute from the #GFileInfo.
1540  * See %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
1541  * 
1542  * Returns: a #gint32 containing the value of the "standard::sort_order" attribute.
1543  **/
1544 gint32
1545 g_file_info_get_sort_order (GFileInfo *info)
1546 {
1547   static guint32 attr = 0;
1548   GFileAttributeValue *value;
1549   
1550   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1551   
1552   if (attr == 0)
1553     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
1554   
1555   value = g_file_info_find_value (info, attr);
1556   return _g_file_attribute_value_get_int32 (value);
1557 }
1558
1559 /* Helper setters: */
1560 /**
1561  * g_file_info_set_file_type:
1562  * @info: a #GFileInfo.
1563  * @type: a #GFileType.
1564  * 
1565  * Sets the file type in a #GFileInfo to @type.
1566  * See %G_FILE_ATTRIBUTE_STANDARD_TYPE.
1567  **/
1568 void
1569 g_file_info_set_file_type (GFileInfo *info,
1570                            GFileType  type)
1571 {
1572   static guint32 attr = 0;
1573   GFileAttributeValue *value;
1574   
1575   g_return_if_fail (G_IS_FILE_INFO (info));
1576   
1577   if (attr == 0)
1578     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_TYPE);
1579   
1580   value = g_file_info_create_value (info, attr);
1581   if (value)
1582     _g_file_attribute_value_set_uint32 (value, type);
1583 }
1584
1585 /**
1586  * g_file_info_set_is_hidden:
1587  * @info: a #GFileInfo.
1588  * @is_hidden: a #gboolean.
1589  * 
1590  * Sets the "is_hidden" attribute in a #GFileInfo according to @is_symlink.
1591  * See %G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN.
1592  **/
1593 void
1594 g_file_info_set_is_hidden (GFileInfo *info,
1595                            gboolean   is_hidden)
1596 {
1597   static guint32 attr = 0;
1598   GFileAttributeValue *value;
1599   
1600   g_return_if_fail (G_IS_FILE_INFO (info));
1601   
1602   if (attr == 0)
1603     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
1604   
1605   value = g_file_info_create_value (info, attr);
1606   if (value)
1607     _g_file_attribute_value_set_boolean (value, is_hidden);
1608 }
1609
1610 /**
1611  * g_file_info_set_is_symlink:
1612  * @info: a #GFileInfo.
1613  * @is_symlink: a #gboolean.
1614  * 
1615  * Sets the "is_symlink" attribute in a #GFileInfo according to @is_symlink.
1616  * See %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
1617  **/
1618 void
1619 g_file_info_set_is_symlink (GFileInfo *info,
1620                             gboolean   is_symlink)
1621 {
1622   static guint32 attr = 0;
1623   GFileAttributeValue *value;
1624   
1625   g_return_if_fail (G_IS_FILE_INFO (info));
1626   
1627   if (attr == 0)
1628     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
1629   
1630   value = g_file_info_create_value (info, attr);
1631   if (value)
1632     _g_file_attribute_value_set_boolean (value, is_symlink);
1633 }
1634
1635 /**
1636  * g_file_info_set_name:
1637  * @info: a #GFileInfo.
1638  * @name: a string containing a name.
1639  * 
1640  * Sets the name attribute for the current #GFileInfo. 
1641  * See %G_FILE_ATTRIBUTE_STANDARD_NAME.
1642  **/
1643 void
1644 g_file_info_set_name (GFileInfo  *info,
1645                       const char *name)
1646 {
1647   static guint32 attr = 0;
1648   GFileAttributeValue *value;
1649   
1650   g_return_if_fail (G_IS_FILE_INFO (info));
1651   g_return_if_fail (name != NULL);
1652   
1653   if (attr == 0)
1654     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_NAME);
1655   
1656   value = g_file_info_create_value (info, attr);
1657   if (value)
1658     _g_file_attribute_value_set_byte_string (value, name);
1659 }
1660
1661 /**
1662  * g_file_info_set_display_name:
1663  * @info: a #GFileInfo.
1664  * @display_name: a string containing a display name.
1665  * 
1666  * Sets the display name for the current #GFileInfo.
1667  * See %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
1668  **/
1669 void
1670 g_file_info_set_display_name (GFileInfo  *info,
1671                               const char *display_name)
1672 {
1673   static guint32 attr = 0;
1674   GFileAttributeValue *value;
1675   
1676   g_return_if_fail (G_IS_FILE_INFO (info));
1677   g_return_if_fail (display_name != NULL);
1678   
1679   if (attr == 0)
1680     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
1681   
1682   value = g_file_info_create_value (info, attr);
1683   if (value)
1684     _g_file_attribute_value_set_string (value, display_name);
1685 }
1686
1687 /**
1688  * g_file_info_set_edit_name:
1689  * @info: a #GFileInfo.
1690  * @edit_name: a string containing an edit name.
1691  * 
1692  * Sets the edit name for the current file.
1693  * See %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
1694  **/
1695 void
1696 g_file_info_set_edit_name (GFileInfo  *info,
1697                            const char *edit_name)
1698 {
1699   static guint32 attr = 0;
1700   GFileAttributeValue *value;
1701   
1702   g_return_if_fail (G_IS_FILE_INFO (info));
1703   g_return_if_fail (edit_name != NULL);
1704   
1705   if (attr == 0)
1706     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
1707   
1708   value = g_file_info_create_value (info, attr);
1709   if (value)
1710     _g_file_attribute_value_set_string (value, edit_name);
1711 }
1712
1713 /**
1714  * g_file_info_set_icon:
1715  * @info: a #GFileInfo.
1716  * @icon: a #GIcon.
1717  * 
1718  * Sets the icon for a given #GFileInfo. 
1719  * See %G_FILE_ATTRIBUTE_STANDARD_ICON.
1720  **/
1721 void
1722 g_file_info_set_icon (GFileInfo *info,
1723                       GIcon     *icon)
1724 {
1725   static guint32 attr = 0;
1726   GFileAttributeValue *value;
1727   
1728   g_return_if_fail (G_IS_FILE_INFO (info));
1729   g_return_if_fail (G_IS_ICON (icon));
1730   
1731   if (attr == 0)
1732     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_ICON);
1733   
1734   value = g_file_info_create_value (info, attr);
1735   if (value)
1736     _g_file_attribute_value_set_object (value, G_OBJECT (icon));
1737 }
1738
1739 /**
1740  * g_file_info_set_content_type:
1741  * @info: a #GFileInfo.
1742  * @content_type: a content type. See #GContentType.
1743  * 
1744  * Sets the content type attribute for a given #GFileInfo.
1745  * See %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
1746  **/
1747 void
1748 g_file_info_set_content_type (GFileInfo  *info,
1749                               const char *content_type)
1750 {
1751   static guint32 attr = 0;
1752   GFileAttributeValue *value;
1753   
1754   g_return_if_fail (G_IS_FILE_INFO (info));
1755   g_return_if_fail (content_type != NULL);
1756   
1757   if (attr == 0)
1758     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
1759   
1760   value = g_file_info_create_value (info, attr);
1761   if (value)
1762     _g_file_attribute_value_set_string (value, content_type);
1763 }
1764
1765 /**
1766  * g_file_info_set_size:
1767  * @info: a #GFileInfo.
1768  * @size: a #goffset containing the file's size.
1769  * 
1770  * Sets the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute in the file info 
1771  * to the given size.
1772  **/
1773 void
1774 g_file_info_set_size (GFileInfo *info,
1775                       goffset    size)
1776 {
1777   static guint32 attr = 0;
1778   GFileAttributeValue *value;
1779   
1780   g_return_if_fail (G_IS_FILE_INFO (info));
1781   
1782   if (attr == 0)
1783     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SIZE);
1784   
1785   value = g_file_info_create_value (info, attr);
1786   if (value)
1787     _g_file_attribute_value_set_uint64 (value, size);
1788 }
1789
1790 /**
1791  * g_file_info_set_modification_time
1792  * @info: a #GFileInfo.
1793  * @mtime: a #GTimeVal.
1794  * 
1795  * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED attribute in the file
1796  * info to the given time value.
1797  **/
1798 void
1799 g_file_info_set_modification_time (GFileInfo *info,
1800                                    GTimeVal  *mtime)
1801 {
1802   static guint32 attr_mtime = 0, attr_mtime_usec;
1803   GFileAttributeValue *value;
1804   
1805   g_return_if_fail (G_IS_FILE_INFO (info));
1806   g_return_if_fail (mtime != NULL);
1807   
1808   if (attr_mtime == 0)
1809     {
1810       attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1811       attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1812     }
1813   
1814   value = g_file_info_create_value (info, attr_mtime);
1815   if (value)
1816     _g_file_attribute_value_set_uint64 (value, mtime->tv_sec);
1817   value = g_file_info_create_value (info, attr_mtime_usec);
1818   if (value)
1819     _g_file_attribute_value_set_uint32 (value, mtime->tv_usec);
1820 }
1821
1822 /**
1823  * g_file_info_set_symlink_target:
1824  * @info: a #GFileInfo.
1825  * @symlink_target: a static string containing a path to a symlink target.
1826  * 
1827  * Sets the %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET attribute in the file info 
1828  * to the given symlink target.
1829  **/
1830 void
1831 g_file_info_set_symlink_target (GFileInfo  *info,
1832                                 const char *symlink_target)
1833 {
1834   static guint32 attr = 0;
1835   GFileAttributeValue *value;
1836   
1837   g_return_if_fail (G_IS_FILE_INFO (info));
1838   g_return_if_fail (symlink_target != NULL);
1839   
1840   if (attr == 0)
1841     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
1842   
1843   value = g_file_info_create_value (info, attr);
1844   if (value)
1845     _g_file_attribute_value_set_byte_string (value, symlink_target);
1846 }
1847
1848 /**
1849  * g_file_info_set_sort_order:
1850  * @info: a #GFileInfo.
1851  * @sort_order: a sort order integer.
1852  * 
1853  * Sets the sort order attribute in the file info structure. See 
1854  * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
1855  **/
1856 void
1857 g_file_info_set_sort_order (GFileInfo *info,
1858                             gint32     sort_order)
1859 {
1860   static guint32 attr = 0;
1861   GFileAttributeValue *value;
1862   
1863   g_return_if_fail (G_IS_FILE_INFO (info));
1864   
1865   if (attr == 0)
1866     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
1867   
1868   value = g_file_info_create_value (info, attr);
1869   if (value)
1870     _g_file_attribute_value_set_int32 (value, sort_order);
1871 }
1872
1873
1874 #define ON_STACK_MATCHERS 5
1875
1876 typedef struct {
1877   guint32 id;
1878   guint32 mask;
1879 } SubMatcher;
1880
1881 struct _GFileAttributeMatcher {
1882   gboolean all;
1883   SubMatcher sub_matchers[ON_STACK_MATCHERS];
1884   GArray *more_sub_matchers;
1885
1886   /* Interator */
1887   guint32 iterator_ns;
1888   int iterator_pos;
1889   int ref;
1890 };
1891
1892 static void
1893 matcher_add (GFileAttributeMatcher *matcher,
1894              guint                  id,
1895              guint                  mask)
1896 {
1897   SubMatcher *sub_matchers;
1898   int i;
1899   SubMatcher s;
1900
1901   for (i = 0; i < ON_STACK_MATCHERS; i++)
1902     {
1903       /* First empty spot, not found, use this */
1904       if (matcher->sub_matchers[i].id == 0)
1905         {
1906           matcher->sub_matchers[i].id = id;
1907           matcher->sub_matchers[i].mask = mask;
1908           return;
1909         }
1910       
1911       /* Already added */
1912       if (matcher->sub_matchers[i].id == id &&
1913           matcher->sub_matchers[i].mask == mask)
1914         return;
1915     }
1916
1917   if (matcher->more_sub_matchers == NULL)
1918     matcher->more_sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
1919       
1920   sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data;
1921   for (i = 0; i < matcher->more_sub_matchers->len; i++)
1922     {
1923       /* Already added */
1924       if (sub_matchers[i].id == id &&
1925           sub_matchers[i].mask == mask)
1926         return;
1927     }
1928
1929   s.id = id;
1930   s.mask = mask;
1931   
1932   g_array_append_val (matcher->more_sub_matchers, s);
1933 }
1934
1935 /**
1936  * g_file_attribute_matcher_new:
1937  * @attributes: an attribute string to match.
1938  * 
1939  * Creates a new file attribute matcher, which matches attributes 
1940  * against a given string. #GFileAttributeMatcher<!-- -->s are reference 
1941  * counted structures, and are created with a reference count of 1. If 
1942  * the number of references falls to 0, the #GFileAttributeMatcher is 
1943  * automatically destroyed.
1944  * 
1945  * The @attribute string should be formatted with specific keys separated
1946  * from namespaces with a double colon. Several "namespace::key" strings may be 
1947  * concatenated with a single comma (e.g. "standard::type,standard::is-hidden"). 
1948  * The wildcard "*" may be used to match all keys and namespaces, or 
1949  * "namespace::*" will match all keys in a given namespace. 
1950  * 
1951  * Examples of strings to use:
1952  * <table>
1953  * <title>File Attribute Matcher strings and results</title>
1954  * <tgroup cols='2' align='left'><thead>
1955  * <row><entry> Matcher String </entry><entry> Matches </entry></row></thead>
1956  * <tbody>
1957  * <row><entry>"*"</entry><entry>matches all attributes.</entry></row>
1958  * <row><entry>"standard::is-hidden"</entry><entry>matches only the key is-hidden in the standard namespace.</entry></row>
1959  * <row><entry>"standard::type,unix::*"</entry><entry>matches the type key in the standard namespace and
1960  * all keys in the unix namespace.</entry></row>
1961  * </tbody></tgroup>
1962  * </table>
1963  * 
1964  * Returns: a #GFileAttributeMatcher.
1965  **/
1966 GFileAttributeMatcher *
1967 g_file_attribute_matcher_new (const char *attributes)
1968 {
1969   char **split;
1970   char *colon;
1971   int i;
1972   GFileAttributeMatcher *matcher;
1973
1974   if (attributes == NULL || *attributes == '\0')
1975     return NULL;
1976
1977   matcher = g_malloc0 (sizeof (GFileAttributeMatcher));
1978   matcher->ref = 1;
1979
1980   split = g_strsplit (attributes, ",", -1);
1981
1982   for (i = 0; split[i] != NULL; i++)
1983     {
1984       if (strcmp (split[i], "*") == 0)
1985         matcher->all = TRUE;
1986       else
1987         {
1988           guint32 id, mask;
1989   
1990           colon = strstr (split[i], "::");
1991           if (colon != NULL &&
1992               !(colon[2] == 0 ||
1993                 (colon[2] == '*' &&
1994                  colon[3] == 0)))
1995             {
1996               id = lookup_attribute (split[i]);
1997               mask = 0xffffffff;
1998             }
1999           else
2000             {
2001               if (colon)
2002                 *colon = 0;
2003
2004               id = lookup_namespace (split[i]) << NS_POS;
2005               mask = NS_MASK << NS_POS;
2006             }
2007           
2008           matcher_add (matcher, id, mask);
2009         }
2010     }
2011
2012   g_strfreev (split);
2013
2014   return matcher;
2015 }
2016
2017 /**
2018  * g_file_attribute_matcher_ref:
2019  * @matcher: a #GFileAttributeMatcher.
2020  * 
2021  * References a file attribute matcher.
2022  * 
2023  * Returns: a #GFileAttributeMatcher.
2024  **/
2025 GFileAttributeMatcher *
2026 g_file_attribute_matcher_ref (GFileAttributeMatcher *matcher)
2027 {
2028   if (matcher)
2029     {
2030       g_return_val_if_fail (matcher->ref > 0, NULL);
2031       g_atomic_int_inc (&matcher->ref);
2032     }
2033   return matcher;
2034 }
2035
2036 /**
2037  * g_file_attribute_matcher_unref:
2038  * @matcher: a #GFileAttributeMatcher.
2039  * 
2040  * Unreferences @matcher. If the reference count falls below 1, 
2041  * the @matcher is automatically freed.
2042  * 
2043  **/
2044 void
2045 g_file_attribute_matcher_unref (GFileAttributeMatcher *matcher)
2046 {
2047   if (matcher)
2048     {
2049       g_return_if_fail (matcher->ref > 0);
2050       
2051       if (g_atomic_int_dec_and_test (&matcher->ref))
2052         {
2053           if (matcher->more_sub_matchers)
2054             g_array_free (matcher->more_sub_matchers, TRUE);
2055           
2056           g_free (matcher);
2057         }
2058     }
2059 }
2060
2061 /**
2062  * g_file_attribute_matcher_matches_only:
2063  * @matcher: a #GFileAttributeMatcher.
2064  * @attribute: a file attribute key.
2065  * 
2066  * Checks if a attribute matcher only matches a given attribute. Always
2067  * returns %FALSE if "*" was used when creating the matcher.
2068  * 
2069  * Returns: %TRUE if the matcher only matches @attribute. %FALSE otherwise.
2070  **/
2071 gboolean
2072 g_file_attribute_matcher_matches_only (GFileAttributeMatcher *matcher,
2073                                        const char            *attribute)
2074 {
2075   guint32 id;
2076
2077   g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2078
2079   if (matcher == NULL ||
2080       matcher->all)
2081     return FALSE;
2082   
2083   id = lookup_attribute (attribute);
2084
2085   if (matcher->sub_matchers[0].id != 0 &&
2086       matcher->sub_matchers[1].id == 0 &&
2087       matcher->sub_matchers[0].mask == 0xffffffff &&
2088       matcher->sub_matchers[0].id == id)
2089     return TRUE;
2090   
2091   return FALSE;
2092 }
2093
2094 static gboolean
2095 matcher_matches_id (GFileAttributeMatcher *matcher,
2096                     guint32                id)
2097 {
2098   SubMatcher *sub_matchers;
2099   int i;
2100   
2101   for (i = 0; i < ON_STACK_MATCHERS; i++)
2102     {
2103       if (matcher->sub_matchers[i].id == 0)
2104         return FALSE;
2105       
2106       if (matcher->sub_matchers[i].id == (id & matcher->sub_matchers[i].mask))
2107         return TRUE;
2108     }
2109
2110   if (matcher->more_sub_matchers)
2111     {
2112       sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data;
2113       for (i = 0; i < matcher->more_sub_matchers->len; i++)
2114         {
2115           if (sub_matchers[i].id == (id & sub_matchers[i].mask))
2116             return TRUE;
2117         }
2118     }
2119   
2120   return FALSE;
2121 }
2122
2123 static gboolean
2124 g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
2125                                      guint32                id)
2126 {
2127   /* We return a NULL matcher for an empty match string, so handle this */
2128   if (matcher == NULL)
2129     return FALSE;
2130   
2131   if (matcher->all)
2132     return TRUE;
2133   
2134   return matcher_matches_id (matcher, id);
2135 }
2136
2137 /**
2138  * g_file_attribute_matcher_matches:
2139  * @matcher: a #GFileAttributeMatcher.
2140  * @attribute: a file attribute key.
2141  *
2142  * Checks if an attribute will be matched by an attribute matcher. If 
2143  * the matcher was created with the "*" matching string, this function
2144  * will always return %TRUE.
2145  * 
2146  * Returns: %TRUE if @attribute matches @matcher. %FALSE otherwise.
2147  **/
2148 gboolean
2149 g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher,
2150                                   const char            *attribute)
2151 {
2152   g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2153
2154   /* We return a NULL matcher for an empty match string, so handle this */
2155   if (matcher == NULL)
2156     return FALSE;
2157   
2158   if (matcher->all)
2159     return TRUE;
2160   
2161   return matcher_matches_id (matcher, lookup_attribute (attribute));
2162 }
2163
2164 /* return TRUE -> all */
2165 /**
2166  * g_file_attribute_matcher_enumerate_namespace:
2167  * @matcher: a #GFileAttributeMatcher.
2168  * @ns: a string containing a file attribute namespace.
2169  * 
2170  * Checks if the matcher will match all of the keys in a given namespace.
2171  * This will always return %TRUE if a wildcard character is in use (e.g. if 
2172  * matcher was created with "standard::*" and @ns is "standard", or if matcher was created
2173  * using "*" and namespace is anything.) 
2174  * 
2175  * TODO: this is awkwardly worded.
2176  * 
2177  * Returns: %TRUE if the matcher matches all of the entries
2178  * in the given @ns, %FALSE otherwise.
2179  **/
2180 gboolean
2181 g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher,
2182                                               const char            *ns)
2183 {
2184   SubMatcher *sub_matchers;
2185   int ns_id;
2186   int i;
2187   
2188   g_return_val_if_fail (ns != NULL && *ns != '\0', FALSE);
2189
2190   /* We return a NULL matcher for an empty match string, so handle this */
2191   if (matcher == NULL)
2192     return FALSE;
2193   
2194   if (matcher->all)
2195     return TRUE;
2196
2197   ns_id = lookup_namespace (ns) << NS_POS;
2198
2199   for (i = 0; i < ON_STACK_MATCHERS; i++)
2200     {
2201       if (matcher->sub_matchers[i].id == ns_id)
2202         return TRUE;
2203     }
2204
2205   if (matcher->more_sub_matchers)
2206     {
2207       sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data;
2208       for (i = 0; i < matcher->more_sub_matchers->len; i++)
2209         {
2210           if (sub_matchers[i].id == ns_id)
2211             return TRUE;
2212         }
2213     }
2214
2215   matcher->iterator_ns = ns_id;
2216   matcher->iterator_pos = 0;
2217   
2218   return FALSE;
2219 }
2220
2221 /**
2222  * g_file_attribute_matcher_enumerate_next:
2223  * @matcher: a #GFileAttributeMatcher.
2224  * 
2225  * Gets the next matched attribute from a #GFileAttributeMatcher.
2226  * 
2227  * Returns: a string containing the next attribute or %NULL if 
2228  * no more attribute exist.
2229  **/
2230 const char *
2231 g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher)
2232 {
2233   int i;
2234   SubMatcher *sub_matcher;
2235
2236   /* We return a NULL matcher for an empty match string, so handle this */
2237   if (matcher == NULL)
2238     return NULL;
2239
2240   while (1)
2241     {
2242       i = matcher->iterator_pos++;
2243
2244       if (i < ON_STACK_MATCHERS)
2245         {
2246           if (matcher->sub_matchers[i].id == 0)
2247             return NULL;
2248
2249           sub_matcher = &matcher->sub_matchers[i];
2250         }
2251       else
2252         {
2253           if (matcher->more_sub_matchers == NULL)
2254             return NULL;
2255       
2256           i -= ON_STACK_MATCHERS;
2257           if (i < matcher->more_sub_matchers->len)
2258             sub_matcher = &g_array_index (matcher->more_sub_matchers, SubMatcher, i);
2259           else
2260             return NULL;
2261         }
2262
2263       if (sub_matcher->mask == 0xffffffff &&
2264           (sub_matcher->id & (NS_MASK << NS_POS)) == matcher->iterator_ns)
2265         return get_attribute_for_id (sub_matcher->id);
2266     }
2267 }
2268
2269 #define __G_FILE_INFO_C__
2270 #include "gioaliasdef.c"