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