Coverage Report

Created: 2025-07-23 08:13

/src/pango/subprojects/glib/gio/gfileattribute.c
Line
Count
Source (jump to first uncovered line)
1
/* GIO - GLib Input, Output and Streaming Library
2
 *
3
 * Copyright (C) 2006-2007 Red Hat, Inc.
4
 *
5
 * SPDX-License-Identifier: LGPL-2.1-or-later
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General
18
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19
 *
20
 * Author: Alexander Larsson <alexl@redhat.com>
21
 */
22
23
#include "config.h"
24
25
#include <string.h>
26
27
#include "gfileattribute.h"
28
#include "gfileattribute-priv.h"
29
#include <glib-object.h>
30
#include "glibintl.h"
31
32
33
/**
34
 * _g_file_attribute_value_free:
35
 * @attr: a #GFileAttributeValue.
36
 *
37
 * Frees the memory used by @attr.
38
 *
39
 **/
40
void
41
_g_file_attribute_value_free (GFileAttributeValue *attr)
42
0
{
43
0
  g_return_if_fail (attr != NULL);
44
45
0
  _g_file_attribute_value_clear (attr);
46
0
  g_free (attr);
47
0
}
48
49
/**
50
 * _g_file_attribute_value_clear:
51
 * @attr: a #GFileAttributeValue.
52
 *
53
 * Clears the value of @attr and sets its type to
54
 * %G_FILE_ATTRIBUTE_TYPE_INVALID.
55
 *
56
 **/
57
void
58
_g_file_attribute_value_clear (GFileAttributeValue *attr)
59
0
{
60
0
  g_return_if_fail (attr != NULL);
61
62
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
63
0
      attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
64
0
    g_free (attr->u.string);
65
66
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
67
0
    g_strfreev (attr->u.stringv);
68
69
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
70
0
      attr->u.obj != NULL)
71
0
    g_object_unref (attr->u.obj);
72
73
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
74
0
}
75
76
/**
77
 * g_file_attribute_value_set:
78
 * @attr: a #GFileAttributeValue to set the value in.
79
 * @new_value: a #GFileAttributeValue to get the value from.
80
 *
81
 * Sets an attribute's value from another attribute.
82
 **/
83
void
84
_g_file_attribute_value_set (GFileAttributeValue        *attr,
85
           const GFileAttributeValue *new_value)
86
0
{
87
0
  g_return_if_fail (attr != NULL);
88
0
  g_return_if_fail (new_value != NULL);
89
90
0
  _g_file_attribute_value_clear (attr);
91
0
  *attr = *new_value;
92
93
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
94
0
      attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
95
0
    attr->u.string = g_strdup (attr->u.string);
96
97
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
98
0
    attr->u.stringv = g_strdupv (attr->u.stringv);
99
100
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
101
0
      attr->u.obj != NULL)
102
0
    g_object_ref (attr->u.obj);
103
0
}
104
105
/**
106
 * _g_file_attribute_value_new:
107
 *
108
 * Creates a new file attribute.
109
 *
110
 * Returns: a #GFileAttributeValue.
111
 **/
112
GFileAttributeValue *
113
_g_file_attribute_value_new (void)
114
0
{
115
0
  GFileAttributeValue *attr;
116
117
0
  attr = g_new (GFileAttributeValue, 1);
118
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
119
0
  return attr;
120
0
}
121
122
gpointer
123
_g_file_attribute_value_peek_as_pointer (GFileAttributeValue *attr)
124
0
{
125
0
  switch (attr->type) {
126
0
  case G_FILE_ATTRIBUTE_TYPE_STRING:
127
0
  case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
128
0
    return attr->u.string;
129
0
  case G_FILE_ATTRIBUTE_TYPE_STRINGV:
130
0
    return attr->u.stringv;
131
0
  case G_FILE_ATTRIBUTE_TYPE_OBJECT:
132
0
    return attr->u.obj;
133
0
  default:
134
0
    return (gpointer) &attr->u;
135
0
  }
136
0
}
137
138
/**
139
 * g_file_attribute_value_dup:
140
 * @other: a #GFileAttributeValue to duplicate.
141
 *
142
 * Duplicates a file attribute.
143
 *
144
 * Returns: a duplicate of the @other.
145
 **/
146
GFileAttributeValue *
147
_g_file_attribute_value_dup (const GFileAttributeValue *other)
148
0
{
149
0
  GFileAttributeValue *attr;
150
151
0
  g_return_val_if_fail (other != NULL, NULL);
152
153
0
  attr = g_new (GFileAttributeValue, 1);
154
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
155
0
  _g_file_attribute_value_set (attr, other);
156
0
  return attr;
157
0
}
158
159
G_DEFINE_BOXED_TYPE (GFileAttributeInfoList, g_file_attribute_info_list,
160
                     g_file_attribute_info_list_dup,
161
                     g_file_attribute_info_list_unref)
162
163
static gboolean
164
valid_char (char c)
165
0
{
166
0
  return c >= 32 && c <= 126 && c != '\\';
167
0
}
168
169
static char *
170
escape_byte_string (const char *str)
171
0
{
172
0
  size_t i, len;
173
0
  int num_invalid;
174
0
  char *escaped_val, *p;
175
0
  unsigned char c;
176
0
  const char hex_digits[] = "0123456789abcdef";
177
178
0
  len = strlen (str);
179
180
0
  num_invalid = 0;
181
0
  for (i = 0; i < len; i++)
182
0
    {
183
0
      if (!valid_char (str[i]))
184
0
  num_invalid++;
185
0
    }
186
187
0
  if (num_invalid == 0)
188
0
    return g_strdup (str);
189
0
  else
190
0
    {
191
0
      escaped_val = g_malloc (len + num_invalid*3 + 1);
192
193
0
      p = escaped_val;
194
0
      for (i = 0; i < len; i++)
195
0
  {
196
0
    c = str[i];
197
0
    if (valid_char (c))
198
0
      *p++ = c;
199
0
    else
200
0
      {
201
0
        *p++ = '\\';
202
0
        *p++ = 'x';
203
0
        *p++ = hex_digits[(c >> 4) & 0xf];
204
0
        *p++ = hex_digits[c & 0xf];
205
0
      }
206
0
  }
207
0
      *p++ = 0;
208
0
      return escaped_val;
209
0
    }
210
0
}
211
212
/**
213
 * _g_file_attribute_value_as_string:
214
 * @attr: a #GFileAttributeValue.
215
 *
216
 * Converts a #GFileAttributeValue to a string for display.
217
 * The returned string should be freed when no longer needed.
218
 *
219
 * Returns: a string from the @attr, %NULL on error, or "<invalid>"
220
 * if @attr is of type %G_FILE_ATTRIBUTE_TYPE_INVALID.
221
 */
222
char *
223
_g_file_attribute_value_as_string (const GFileAttributeValue *attr)
224
0
{
225
0
  GString *s;
226
0
  int i;
227
0
  char *str;
228
229
0
  g_return_val_if_fail (attr != NULL, NULL);
230
231
0
  switch (attr->type)
232
0
    {
233
0
    case G_FILE_ATTRIBUTE_TYPE_STRING:
234
0
      str = g_strdup (attr->u.string);
235
0
      break;
236
0
    case G_FILE_ATTRIBUTE_TYPE_STRINGV:
237
0
      s = g_string_new ("[");
238
0
      for (i = 0; attr->u.stringv[i] != NULL; i++)
239
0
  {
240
0
    g_string_append (s, attr->u.stringv[i]);
241
0
    if (attr->u.stringv[i+1] != NULL)
242
0
      g_string_append (s, ", ");
243
0
  }
244
0
      g_string_append (s, "]");
245
0
      str = g_string_free (s, FALSE);
246
0
      break;
247
0
    case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
248
0
      str = escape_byte_string (attr->u.string);
249
0
      break;
250
0
    case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
251
0
      str = g_strdup_printf ("%s", attr->u.boolean?"TRUE":"FALSE");
252
0
      break;
253
0
    case G_FILE_ATTRIBUTE_TYPE_UINT32:
254
0
      str = g_strdup_printf ("%u", (unsigned int)attr->u.uint32);
255
0
      break;
256
0
    case G_FILE_ATTRIBUTE_TYPE_INT32:
257
0
      str = g_strdup_printf ("%i", (int)attr->u.int32);
258
0
      break;
259
0
    case G_FILE_ATTRIBUTE_TYPE_UINT64:
260
0
      str = g_strdup_printf ("%"G_GUINT64_FORMAT, attr->u.uint64);
261
0
      break;
262
0
    case G_FILE_ATTRIBUTE_TYPE_INT64:
263
0
      str = g_strdup_printf ("%"G_GINT64_FORMAT, attr->u.int64);
264
0
      break;
265
0
    case G_FILE_ATTRIBUTE_TYPE_OBJECT:
266
0
      str = g_strdup_printf ("%s:%p", g_type_name_from_instance
267
0
                                          ((GTypeInstance *) attr->u.obj),
268
0
                                      attr->u.obj);
269
0
      break;
270
0
    case G_FILE_ATTRIBUTE_TYPE_INVALID:
271
0
      str = g_strdup ("<unset>");
272
0
      break;
273
0
    default:
274
0
      g_warning ("Invalid type in GFileInfo attribute");
275
0
      str = g_strdup ("<invalid>");
276
0
      break;
277
0
    }
278
279
0
  return str;
280
0
}
281
282
/**
283
 * _g_file_attribute_value_get_string:
284
 * @attr: a #GFileAttributeValue.
285
 *
286
 * Gets the string from a file attribute value. If the value is not the
287
 * right type then %NULL will be returned.
288
 *
289
 * Returns: the UTF-8 string value contained within the attribute, or %NULL.
290
 */
291
const char *
292
_g_file_attribute_value_get_string (const GFileAttributeValue *attr)
293
0
{
294
0
  if (attr == NULL)
295
0
    return NULL;
296
297
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING, NULL);
298
299
0
  return attr->u.string;
300
0
}
301
302
/**
303
 * _g_file_attribute_value_get_byte_string:
304
 * @attr: a #GFileAttributeValue.
305
 *
306
 * Gets the byte string from a file attribute value. If the value is not the
307
 * right type then %NULL will be returned.
308
 *
309
 * Returns: the byte string contained within the attribute or %NULL.
310
 */
311
const char *
312
_g_file_attribute_value_get_byte_string (const GFileAttributeValue *attr)
313
0
{
314
0
  if (attr == NULL)
315
0
    return NULL;
316
317
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, NULL);
318
319
0
  return attr->u.string;
320
0
}
321
322
char **
323
_g_file_attribute_value_get_stringv (const GFileAttributeValue *attr)
324
0
{
325
0
  if (attr == NULL)
326
0
    return NULL;
327
328
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV, NULL);
329
330
0
  return attr->u.stringv;
331
0
}
332
333
/**
334
 * _g_file_attribute_value_get_boolean:
335
 * @attr: a #GFileAttributeValue.
336
 *
337
 * Gets the boolean value from a file attribute value. If the value is not the
338
 * right type then %FALSE will be returned.
339
 *
340
 * Returns: the boolean value contained within the attribute, or %FALSE.
341
 */
342
gboolean
343
_g_file_attribute_value_get_boolean (const GFileAttributeValue *attr)
344
0
{
345
0
  if (attr == NULL)
346
0
    return FALSE;
347
348
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BOOLEAN, FALSE);
349
350
0
  return attr->u.boolean;
351
0
}
352
353
/**
354
 * _g_file_attribute_value_get_uint32:
355
 * @attr: a #GFileAttributeValue.
356
 *
357
 * Gets the unsigned 32-bit integer from a file attribute value. If the value
358
 * is not the right type then 0 will be returned.
359
 *
360
 * Returns: the unsigned 32-bit integer from the attribute, or 0.
361
 */
362
guint32
363
_g_file_attribute_value_get_uint32 (const GFileAttributeValue *attr)
364
0
{
365
0
  if (attr == NULL)
366
0
    return 0;
367
368
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT32, 0);
369
370
0
  return attr->u.uint32;
371
0
}
372
373
/**
374
 * _g_file_attribute_value_get_int32:
375
 * @attr: a #GFileAttributeValue.
376
 *
377
 * Gets the signed 32-bit integer from a file attribute value. If the value
378
 * is not the right type then 0 will be returned.
379
 *
380
 * Returns: the signed 32-bit integer from the attribute, or 0.
381
 */
382
gint32
383
_g_file_attribute_value_get_int32 (const GFileAttributeValue *attr)
384
0
{
385
0
  if (attr == NULL)
386
0
    return 0;
387
388
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT32, 0);
389
390
0
  return attr->u.int32;
391
0
}
392
393
/**
394
 * _g_file_attribute_value_get_uint64:
395
 * @attr: a #GFileAttributeValue.
396
 *
397
 * Gets the unsigned 64-bit integer from a file attribute value. If the value
398
 * is not the right type then 0 will be returned.
399
 *
400
 * Returns: the unsigned 64-bit integer from the attribute, or 0.
401
 */
402
guint64
403
_g_file_attribute_value_get_uint64 (const GFileAttributeValue *attr)
404
0
{
405
0
  if (attr == NULL)
406
0
    return 0;
407
408
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT64, 0);
409
410
0
  return attr->u.uint64;
411
0
}
412
413
/**
414
 * _g_file_attribute_value_get_int64:
415
 * @attr: a #GFileAttributeValue.
416
 *
417
 * Gets the signed 64-bit integer from a file attribute value. If the value
418
 * is not the right type then 0 will be returned.
419
 *
420
 * Returns: the signed 64-bit integer from the attribute, or 0.
421
 */
422
gint64
423
_g_file_attribute_value_get_int64 (const GFileAttributeValue *attr)
424
0
{
425
0
  if (attr == NULL)
426
0
    return 0;
427
428
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT64, 0);
429
430
0
  return attr->u.int64;
431
0
}
432
433
/**
434
 * _g_file_attribute_value_get_object:
435
 * @attr: a #GFileAttributeValue.
436
 *
437
 * Gets the GObject from a file attribute value. If the value
438
 * is not the right type then %NULL will be returned.
439
 *
440
 * Returns: the GObject from the attribute, or %NULL.
441
 **/
442
GObject *
443
_g_file_attribute_value_get_object (const GFileAttributeValue *attr)
444
0
{
445
0
  if (attr == NULL)
446
0
    return NULL;
447
448
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT, NULL);
449
450
0
  return attr->u.obj;
451
0
}
452
453
454
void
455
_g_file_attribute_value_set_from_pointer (GFileAttributeValue *value,
456
            GFileAttributeType   type,
457
            gpointer             value_p,
458
            gboolean             dup)
459
0
{
460
0
  _g_file_attribute_value_clear (value);
461
0
  value->type = type;
462
0
  switch (type)
463
0
    {
464
0
    case G_FILE_ATTRIBUTE_TYPE_STRING:
465
0
    case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
466
0
      if (dup)
467
0
  value->u.string = g_strdup (value_p);
468
0
      else
469
0
  value->u.string = value_p;
470
0
      break;
471
472
0
    case G_FILE_ATTRIBUTE_TYPE_STRINGV:
473
0
      if (dup)
474
0
  value->u.stringv = g_strdupv (value_p);
475
0
      else
476
0
  value->u.stringv = value_p;
477
0
      break;
478
479
0
    case G_FILE_ATTRIBUTE_TYPE_OBJECT:
480
0
      if (dup)
481
0
  value->u.obj = g_object_ref (value_p);
482
0
      else
483
0
  value->u.obj = value_p;
484
0
      break;
485
486
0
    case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
487
0
      value->u.boolean = *(gboolean *)value_p;
488
0
      break;
489
490
0
    case G_FILE_ATTRIBUTE_TYPE_UINT32:
491
0
      value->u.uint32 = *(guint32 *)value_p;
492
0
      break;
493
494
0
    case G_FILE_ATTRIBUTE_TYPE_INT32:
495
0
      value->u.int32 = *(gint32 *)value_p;
496
0
      break;
497
498
0
    case G_FILE_ATTRIBUTE_TYPE_UINT64:
499
0
      value->u.uint64 = *(guint64 *)value_p;
500
0
      break;
501
502
0
    case G_FILE_ATTRIBUTE_TYPE_INT64:
503
0
      value->u.int64 = *(gint64 *)value_p;
504
0
      break;
505
506
0
    case G_FILE_ATTRIBUTE_TYPE_INVALID:
507
0
      break;
508
509
0
    default:
510
0
      g_warning ("Unknown type specified in g_file_info_set_attribute");
511
0
      break;
512
0
    }
513
0
}
514
515
/**
516
 * _g_file_attribute_value_set_string:
517
 * @attr: a #GFileAttributeValue.
518
 * @string: a UTF-8 string to set within the type.
519
 *
520
 * Sets the attribute value to a given UTF-8 string.
521
 */
522
void
523
_g_file_attribute_value_set_string (GFileAttributeValue *attr,
524
            const char          *string)
525
0
{
526
0
  g_return_if_fail (attr != NULL);
527
0
  g_return_if_fail (string != NULL);
528
529
0
  _g_file_attribute_value_clear (attr);
530
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_STRING;
531
0
  attr->u.string = g_strdup (string);
532
0
}
533
534
/**
535
 * _g_file_attribute_value_set_byte_string:
536
 * @attr: a #GFileAttributeValue.
537
 * @string: a byte string to set within the type.
538
 *
539
 * Sets the attribute value to a given byte string.
540
 */
541
void
542
_g_file_attribute_value_set_byte_string (GFileAttributeValue *attr,
543
           const char          *string)
544
0
{
545
0
  g_return_if_fail (attr != NULL);
546
0
  g_return_if_fail (string != NULL);
547
548
0
  _g_file_attribute_value_clear (attr);
549
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
550
0
  attr->u.string = g_strdup (string);
551
0
}
552
553
void
554
_g_file_attribute_value_set_stringv (GFileAttributeValue *attr,
555
             char               **value)
556
0
{
557
0
  g_return_if_fail (attr != NULL);
558
0
  g_return_if_fail (value != NULL);
559
560
0
  _g_file_attribute_value_clear (attr);
561
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_STRINGV;
562
0
  attr->u.stringv = g_strdupv (value);
563
0
}
564
565
566
/**
567
 * _g_file_attribute_value_set_boolean:
568
 * @attr: a #GFileAttributeValue.
569
 * @value: a #gboolean to set within the type.
570
 *
571
 * Sets the attribute value to the given boolean value.
572
 */
573
void
574
_g_file_attribute_value_set_boolean (GFileAttributeValue *attr,
575
             gboolean             value)
576
0
{
577
0
  g_return_if_fail (attr != NULL);
578
579
0
  _g_file_attribute_value_clear (attr);
580
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
581
0
  attr->u.boolean = !!value;
582
0
}
583
584
/**
585
 * _g_file_attribute_value_set_uint32:
586
 * @attr: a #GFileAttributeValue.
587
 * @value: a #guint32 to set within the type.
588
 *
589
 * Sets the attribute value to the given unsigned 32-bit integer.
590
 */
591
void
592
_g_file_attribute_value_set_uint32 (GFileAttributeValue *attr,
593
            guint32              value)
594
0
{
595
0
  g_return_if_fail (attr != NULL);
596
597
0
  _g_file_attribute_value_clear (attr);
598
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_UINT32;
599
0
  attr->u.uint32 = value;
600
0
}
601
602
/**
603
 * _g_file_attribute_value_set_int32:
604
 * @attr: a #GFileAttributeValue.
605
 * @value: a #gint32 to set within the type.
606
 *
607
 * Sets the attribute value to the given signed 32-bit integer.
608
 */
609
void
610
_g_file_attribute_value_set_int32 (GFileAttributeValue *attr,
611
           gint32               value)
612
0
{
613
0
  g_return_if_fail (attr != NULL);
614
615
0
  _g_file_attribute_value_clear (attr);
616
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INT32;
617
0
  attr->u.int32 = value;
618
0
}
619
620
/**
621
 * _g_file_attribute_value_set_uint64:
622
 * @attr: a #GFileAttributeValue.
623
 * @value: a #guint64 to set within the type.
624
 *
625
 * Sets the attribute value to a given unsigned 64-bit integer.
626
 */
627
void
628
_g_file_attribute_value_set_uint64 (GFileAttributeValue *attr,
629
            guint64              value)
630
0
{
631
0
  g_return_if_fail (attr != NULL);
632
633
0
  _g_file_attribute_value_clear (attr);
634
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_UINT64;
635
0
  attr->u.uint64 = value;
636
0
}
637
638
/**
639
 * _g_file_attribute_value_set_int64:
640
 * @attr: a #GFileAttributeValue.
641
 * @value: a #gint64 to set within the type.
642
 *
643
 * Sets the attribute value to a given signed 64-bit integer.
644
 */
645
void
646
_g_file_attribute_value_set_int64 (GFileAttributeValue *attr,
647
           gint64               value)
648
0
{
649
0
  g_return_if_fail (attr != NULL);
650
651
0
  _g_file_attribute_value_clear (attr);
652
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INT64;
653
0
  attr->u.int64 = value;
654
0
}
655
656
/**
657
 * _g_file_attribute_value_set_object:
658
 * @attr: a #GFileAttributeValue.
659
 * @obj: a #GObject.
660
 *
661
 * Sets the attribute to contain the value @obj.
662
 * The @attr references the GObject internally.
663
 */
664
void
665
_g_file_attribute_value_set_object (GFileAttributeValue *attr,
666
            GObject             *obj)
667
0
{
668
0
  g_return_if_fail (attr != NULL);
669
0
  g_return_if_fail (obj != NULL);
670
671
0
  _g_file_attribute_value_clear (attr);
672
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_OBJECT;
673
0
  attr->u.obj = g_object_ref (obj);
674
0
}
675
676
typedef struct {
677
  GFileAttributeInfoList public;
678
  GArray *array;
679
  int ref_count;
680
} GFileAttributeInfoListPriv;
681
682
static void
683
list_update_public (GFileAttributeInfoListPriv *priv)
684
0
{
685
0
  priv->public.infos = (GFileAttributeInfo *)priv->array->data;
686
0
  priv->public.n_infos = priv->array->len;
687
0
}
688
689
/**
690
 * g_file_attribute_info_list_new:
691
 *
692
 * Creates a new file attribute info list.
693
 *
694
 * Returns: a #GFileAttributeInfoList.
695
 */
696
GFileAttributeInfoList *
697
g_file_attribute_info_list_new (void)
698
0
{
699
0
  GFileAttributeInfoListPriv *priv;
700
701
0
  priv = g_new0 (GFileAttributeInfoListPriv, 1);
702
703
0
  priv->ref_count = 1;
704
0
  priv->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
705
706
0
  list_update_public (priv);
707
708
0
  return (GFileAttributeInfoList *)priv;
709
0
}
710
711
/**
712
 * g_file_attribute_info_list_dup:
713
 * @list: a #GFileAttributeInfoList to duplicate.
714
 *
715
 * Makes a duplicate of a file attribute info list.
716
 *
717
 * Returns: a copy of the given @list.
718
 */
719
GFileAttributeInfoList *
720
g_file_attribute_info_list_dup (GFileAttributeInfoList *list)
721
0
{
722
0
  GFileAttributeInfoListPriv *new;
723
0
  int i;
724
725
0
  g_return_val_if_fail (list != NULL, NULL);
726
727
0
  new = g_new0 (GFileAttributeInfoListPriv, 1);
728
0
  new->ref_count = 1;
729
0
  new->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
730
731
0
  g_array_set_size (new->array, list->n_infos);
732
0
  list_update_public (new);
733
0
  for (i = 0; i < list->n_infos; i++)
734
0
    {
735
0
      new->public.infos[i].name = g_strdup (list->infos[i].name);
736
0
      new->public.infos[i].type = list->infos[i].type;
737
0
      new->public.infos[i].flags = list->infos[i].flags;
738
0
    }
739
740
0
  return (GFileAttributeInfoList *)new;
741
0
}
742
743
/**
744
 * g_file_attribute_info_list_ref:
745
 * @list: a #GFileAttributeInfoList to reference.
746
 *
747
 * References a file attribute info list.
748
 *
749
 * Returns: #GFileAttributeInfoList or %NULL on error.
750
 */
751
GFileAttributeInfoList *
752
g_file_attribute_info_list_ref (GFileAttributeInfoList *list)
753
0
{
754
0
  GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
755
0
  int old_ref_count;
756
757
0
  g_return_val_if_fail (list != NULL, NULL);
758
759
0
  old_ref_count = g_atomic_int_add (&priv->ref_count, 1);
760
0
  g_return_val_if_fail (old_ref_count > 0, NULL);
761
762
0
  return list;
763
0
}
764
765
/**
766
 * g_file_attribute_info_list_unref:
767
 * @list: The #GFileAttributeInfoList to unreference.
768
 *
769
 * Removes a reference from the given @list. If the reference count
770
 * falls to zero, the @list is deleted.
771
 */
772
void
773
g_file_attribute_info_list_unref (GFileAttributeInfoList *list)
774
0
{
775
0
  GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
776
0
  int i;
777
778
0
  g_return_if_fail (list != NULL);
779
0
  g_return_if_fail (priv->ref_count > 0);
780
781
0
  if (g_atomic_int_dec_and_test (&priv->ref_count))
782
0
    {
783
0
      for (i = 0; i < list->n_infos; i++)
784
0
        g_free (list->infos[i].name);
785
0
      g_array_free (priv->array, TRUE);
786
0
      g_free (list);
787
0
    }
788
0
}
789
790
static int
791
g_file_attribute_info_list_bsearch (GFileAttributeInfoList *list,
792
            const char             *name)
793
0
{
794
0
  int start, end, mid;
795
796
0
  start = 0;
797
0
  end = list->n_infos;
798
799
0
  while (start != end)
800
0
    {
801
0
      mid = start + (end - start) / 2;
802
803
0
      if (strcmp (name, list->infos[mid].name) < 0)
804
0
  end = mid;
805
0
      else if (strcmp (name, list->infos[mid].name) > 0)
806
0
  start = mid + 1;
807
0
      else
808
0
  return mid;
809
0
    }
810
0
  return start;
811
0
}
812
813
/**
814
 * g_file_attribute_info_list_lookup:
815
 * @list: a #GFileAttributeInfoList.
816
 * @name: the name of the attribute to look up.
817
 *
818
 * Gets the file attribute with the name @name from @list.
819
 *
820
 * Returns: a #GFileAttributeInfo for the @name, or %NULL if an
821
 * attribute isn't found.
822
 */
823
const GFileAttributeInfo *
824
g_file_attribute_info_list_lookup (GFileAttributeInfoList *list,
825
           const char             *name)
826
0
{
827
0
  int i;
828
829
0
  g_return_val_if_fail (list != NULL, NULL);
830
0
  g_return_val_if_fail (name != NULL, NULL);
831
832
0
  i = g_file_attribute_info_list_bsearch (list, name);
833
834
0
  if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
835
0
    return &list->infos[i];
836
837
0
  return NULL;
838
0
}
839
840
/**
841
 * g_file_attribute_info_list_add:
842
 * @list: a #GFileAttributeInfoList.
843
 * @name: the name of the attribute to add.
844
 * @type: the #GFileAttributeType for the attribute.
845
 * @flags: #GFileAttributeInfoFlags for the attribute.
846
 *
847
 * Adds a new attribute with @name to the @list, setting
848
 * its @type and @flags.
849
 */
850
void
851
g_file_attribute_info_list_add (GFileAttributeInfoList *list,
852
        const char             *name,
853
        GFileAttributeType      type,
854
        GFileAttributeInfoFlags flags)
855
0
{
856
0
  GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
857
0
  GFileAttributeInfo info;
858
0
  int i;
859
860
0
  g_return_if_fail (list != NULL);
861
0
  g_return_if_fail (name != NULL);
862
863
0
  i = g_file_attribute_info_list_bsearch (list, name);
864
865
0
  if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
866
0
    {
867
0
      list->infos[i].type = type;
868
0
      return;
869
0
    }
870
871
0
  info.name = g_strdup (name);
872
0
  info.type = type;
873
0
  info.flags = flags;
874
0
  g_array_insert_vals (priv->array, i, &info, 1);
875
876
0
  list_update_public (priv);
877
0
}