~ubuntu-branches/ubuntu/maverick/gimp/maverick-updates

« back to all changes in this revision

Viewing changes to app/core/gimpparasitelist.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-12-09 19:44:52 UTC
  • Revision ID: james.westby@ubuntu.com-20051209194452-yggpemjlofpjqyf4
Tags: upstream-2.2.9
ImportĀ upstreamĀ versionĀ 2.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* parasitelist.c: Copyright 1998 Jay Cox <jaycox@earthlink.net>
 
2
 *
 
3
 * This program is free software; you can redistribute it and/or modify
 
4
 * it under the terms of the GNU General Public License as published by
 
5
 * the Free Software Foundation; either version 2 of the License, or
 
6
 * (at your option) any later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program; if not, write to the Free Software
 
15
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
16
 */
 
17
 
 
18
#include "config.h"
 
19
 
 
20
#include <string.h>
 
21
#ifdef HAVE_UNISTD_H
 
22
#include <unistd.h>
 
23
#endif
 
24
 
 
25
#include <glib-object.h>
 
26
 
 
27
#ifdef G_OS_WIN32
 
28
#include <io.h>
 
29
#endif
 
30
 
 
31
#include "libgimpbase/gimpbase.h"
 
32
 
 
33
#include "core-types.h"
 
34
 
 
35
#include "config/gimpconfig.h"
 
36
#include "config/gimpconfigwriter.h"
 
37
#include "config/gimpscanner.h"
 
38
 
 
39
#include "gimp-utils.h"
 
40
#include "gimpmarshal.h"
 
41
#include "gimpparasitelist.h"
 
42
 
 
43
 
 
44
enum
 
45
{
 
46
  ADD,
 
47
  REMOVE,
 
48
  LAST_SIGNAL
 
49
};
 
50
 
 
51
 
 
52
static void     gimp_parasite_list_class_init  (GimpParasiteListClass *klass);
 
53
static void     gimp_parasite_list_init        (GimpParasiteList      *list);
 
54
static void     gimp_parasite_list_finalize          (GObject     *object);
 
55
static gint64   gimp_parasite_list_get_memsize       (GimpObject  *object,
 
56
                                                      gint64      *gui_size);
 
57
 
 
58
static void     gimp_parasite_list_config_iface_init (gpointer     iface,
 
59
                                                      gpointer     iface_data);
 
60
static gboolean gimp_parasite_list_serialize    (GimpConfig       *list,
 
61
                                                 GimpConfigWriter *writer,
 
62
                                                 gpointer          data);
 
63
static gboolean gimp_parasite_list_deserialize  (GimpConfig       *list,
 
64
                                                 GScanner         *scanner,
 
65
                                                 gint              nest_level,
 
66
                                                 gpointer          data);
 
67
 
 
68
static void     parasite_serialize           (const gchar      *key,
 
69
                                              GimpParasite     *parasite,
 
70
                                              GimpConfigWriter *writer);
 
71
static void     parasite_copy                (const gchar      *key,
 
72
                                              GimpParasite     *parasite,
 
73
                                              GimpParasiteList *list);
 
74
static gboolean parasite_free                (const gchar      *key,
 
75
                                              GimpParasite     *parasite,
 
76
                                              gpointer          unused);
 
77
static void     parasite_count_if_persistent (const gchar      *key,
 
78
                                              GimpParasite     *parasite,
 
79
                                              gint             *count);
 
80
 
 
81
 
 
82
static guint parasite_list_signals[LAST_SIGNAL] = { 0 };
 
83
 
 
84
static GimpObjectClass *parent_class = NULL;
 
85
 
 
86
static const gchar     *parasite_symbol = "parasite";
 
87
 
 
88
 
 
89
GType
 
90
gimp_parasite_list_get_type (void)
 
91
{
 
92
  static GType list_type = 0;
 
93
 
 
94
  if (! list_type)
 
95
    {
 
96
      static const GTypeInfo list_info =
 
97
      {
 
98
        sizeof (GimpParasiteListClass),
 
99
        (GBaseInitFunc) NULL,
 
100
        (GBaseFinalizeFunc) NULL,
 
101
        (GClassInitFunc) gimp_parasite_list_class_init,
 
102
        NULL,           /* class_finalize */
 
103
        NULL,           /* class_data     */
 
104
        sizeof (GimpParasiteList),
 
105
        0,              /* n_preallocs    */
 
106
        (GInstanceInitFunc) gimp_parasite_list_init,
 
107
      };
 
108
      static const GInterfaceInfo list_iface_info =
 
109
      {
 
110
        gimp_parasite_list_config_iface_init,
 
111
        NULL,           /* iface_finalize */
 
112
        NULL            /* iface_data     */
 
113
      };
 
114
 
 
115
      list_type = g_type_register_static (GIMP_TYPE_OBJECT,
 
116
                                          "GimpParasiteList",
 
117
                                          &list_info, 0);
 
118
      g_type_add_interface_static (list_type, GIMP_TYPE_CONFIG,
 
119
                                   &list_iface_info);
 
120
    }
 
121
 
 
122
  return list_type;
 
123
}
 
124
 
 
125
static void
 
126
gimp_parasite_list_class_init (GimpParasiteListClass *klass)
 
127
{
 
128
  GObjectClass    *object_class      = G_OBJECT_CLASS (klass);
 
129
  GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
 
130
 
 
131
  parent_class = g_type_class_peek_parent (klass);
 
132
 
 
133
  parasite_list_signals[ADD] =
 
134
    g_signal_new ("add",
 
135
                  G_TYPE_FROM_CLASS (klass),
 
136
                  G_SIGNAL_RUN_FIRST,
 
137
                  G_STRUCT_OFFSET (GimpParasiteListClass, add),
 
138
                  NULL, NULL,
 
139
                  gimp_marshal_VOID__POINTER,
 
140
                  G_TYPE_NONE, 1,
 
141
                  G_TYPE_POINTER);
 
142
 
 
143
  parasite_list_signals[REMOVE] =
 
144
    g_signal_new ("remove",
 
145
                  G_TYPE_FROM_CLASS (klass),
 
146
                  G_SIGNAL_RUN_FIRST,
 
147
                  G_STRUCT_OFFSET (GimpParasiteListClass, remove),
 
148
                  NULL, NULL,
 
149
                  gimp_marshal_VOID__POINTER,
 
150
                  G_TYPE_NONE, 1,
 
151
                  G_TYPE_POINTER);
 
152
 
 
153
  object_class->finalize         = gimp_parasite_list_finalize;
 
154
 
 
155
  gimp_object_class->get_memsize = gimp_parasite_list_get_memsize;
 
156
 
 
157
  klass->add                     = NULL;
 
158
  klass->remove                  = NULL;
 
159
}
 
160
 
 
161
static void
 
162
gimp_parasite_list_config_iface_init (gpointer  iface,
 
163
                                      gpointer  iface_data)
 
164
{
 
165
  GimpConfigInterface *config_iface = (GimpConfigInterface *) iface;
 
166
 
 
167
  config_iface->serialize   = gimp_parasite_list_serialize;
 
168
  config_iface->deserialize = gimp_parasite_list_deserialize;
 
169
}
 
170
 
 
171
static void
 
172
gimp_parasite_list_init (GimpParasiteList *list)
 
173
{
 
174
  list->table = NULL;
 
175
}
 
176
 
 
177
static void
 
178
gimp_parasite_list_finalize (GObject *object)
 
179
{
 
180
  GimpParasiteList *list = GIMP_PARASITE_LIST (object);
 
181
 
 
182
  if (list->table)
 
183
    {
 
184
      g_hash_table_foreach_remove (list->table, (GHRFunc) parasite_free, NULL);
 
185
      g_hash_table_destroy (list->table);
 
186
      list->table = NULL;
 
187
    }
 
188
 
 
189
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
190
}
 
191
 
 
192
static void
 
193
gimp_parasite_list_get_memsize_foreach (gpointer key,
 
194
                                        gpointer p,
 
195
                                        gpointer m)
 
196
{
 
197
  GimpParasite *parasite = p;
 
198
  gint64       *memsize  = m;
 
199
 
 
200
  *memsize += (sizeof (GimpParasite) +
 
201
               strlen (parasite->name) + 1 +
 
202
               parasite->size);
 
203
}
 
204
 
 
205
static gint64
 
206
gimp_parasite_list_get_memsize (GimpObject *object,
 
207
                                gint64     *gui_size)
 
208
{
 
209
  GimpParasiteList *list    = GIMP_PARASITE_LIST (object);
 
210
  gint64            memsize = 0;
 
211
 
 
212
  if (list->table)
 
213
    {
 
214
      memsize += gimp_g_hash_table_get_memsize (list->table);
 
215
 
 
216
      g_hash_table_foreach (list->table,
 
217
                            gimp_parasite_list_get_memsize_foreach,
 
218
                            &memsize);
 
219
    }
 
220
 
 
221
  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
 
222
                                                                  gui_size);
 
223
}
 
224
 
 
225
static gboolean
 
226
gimp_parasite_list_serialize (GimpConfig       *list,
 
227
                              GimpConfigWriter *writer,
 
228
                              gpointer          data)
 
229
{
 
230
  if (GIMP_PARASITE_LIST (list)->table)
 
231
    g_hash_table_foreach (GIMP_PARASITE_LIST (list)->table,
 
232
                          (GHFunc) parasite_serialize,
 
233
                          writer);
 
234
 
 
235
  return TRUE;
 
236
}
 
237
 
 
238
static gboolean
 
239
gimp_parasite_list_deserialize (GimpConfig *list,
 
240
                                GScanner   *scanner,
 
241
                                gint        nest_level,
 
242
                                gpointer    data)
 
243
{
 
244
  GTokenType token;
 
245
 
 
246
  g_scanner_scope_add_symbol (scanner, 0,
 
247
                              parasite_symbol, (gpointer) parasite_symbol);
 
248
 
 
249
  token = G_TOKEN_LEFT_PAREN;
 
250
 
 
251
  while (g_scanner_peek_next_token (scanner) == token)
 
252
    {
 
253
      token = g_scanner_get_next_token (scanner);
 
254
 
 
255
      switch (token)
 
256
        {
 
257
        case G_TOKEN_LEFT_PAREN:
 
258
          token = G_TOKEN_SYMBOL;
 
259
          break;
 
260
 
 
261
        case G_TOKEN_SYMBOL:
 
262
          if (scanner->value.v_symbol == parasite_symbol)
 
263
            {
 
264
              gchar        *parasite_name      = NULL;
 
265
              gint          parasite_flags     = 0;
 
266
              guint8       *parasite_data      = NULL;
 
267
              gint          parasite_data_size = 0;
 
268
              GimpParasite *parasite;
 
269
 
 
270
              token = G_TOKEN_STRING;
 
271
 
 
272
              if (g_scanner_peek_next_token (scanner) != token)
 
273
                break;
 
274
 
 
275
              if (! gimp_scanner_parse_string (scanner, &parasite_name))
 
276
                break;
 
277
 
 
278
              token = G_TOKEN_INT;
 
279
 
 
280
              if (g_scanner_peek_next_token (scanner) != token)
 
281
                goto cleanup;
 
282
 
 
283
              if (! gimp_scanner_parse_int (scanner, &parasite_flags))
 
284
                goto cleanup;
 
285
 
 
286
              token = G_TOKEN_INT;
 
287
 
 
288
              if (g_scanner_peek_next_token (scanner) != token)
 
289
                {
 
290
                  /*  old format -- plain string  */
 
291
 
 
292
                  gchar *str;
 
293
 
 
294
                  if (g_scanner_peek_next_token (scanner) != G_TOKEN_STRING)
 
295
                    goto cleanup;
 
296
 
 
297
                  if (! gimp_scanner_parse_string (scanner, &str))
 
298
                    goto cleanup;
 
299
 
 
300
                  parasite_data_size = strlen (str);
 
301
                  parasite_data      = str;
 
302
                }
 
303
              else
 
304
                {
 
305
                  /*  new format -- properly encoded binary data  */
 
306
 
 
307
                  if (! gimp_scanner_parse_int (scanner, &parasite_data_size))
 
308
                    goto cleanup;
 
309
 
 
310
                  token = G_TOKEN_STRING;
 
311
 
 
312
                  if (g_scanner_peek_next_token (scanner) != token)
 
313
                    goto cleanup;
 
314
 
 
315
                  if (! gimp_scanner_parse_data (scanner, parasite_data_size,
 
316
                                                 &parasite_data))
 
317
                    goto cleanup;
 
318
                }
 
319
 
 
320
              parasite = gimp_parasite_new (parasite_name,
 
321
                                            parasite_flags,
 
322
                                            parasite_data_size,
 
323
                                            parasite_data);
 
324
              gimp_parasite_list_add (GIMP_PARASITE_LIST (list),
 
325
                                      parasite);  /* adds a copy */
 
326
              gimp_parasite_free (parasite);
 
327
 
 
328
              token = G_TOKEN_RIGHT_PAREN;
 
329
 
 
330
              g_free (parasite_data);
 
331
            cleanup:
 
332
              g_free (parasite_name);
 
333
            }
 
334
          break;
 
335
 
 
336
        case G_TOKEN_RIGHT_PAREN:
 
337
          token = G_TOKEN_LEFT_PAREN;
 
338
          break;
 
339
 
 
340
        default: /* do nothing */
 
341
          break;
 
342
        }
 
343
    }
 
344
 
 
345
  return gimp_config_deserialize_return (scanner, token, nest_level);
 
346
}
 
347
 
 
348
GimpParasiteList *
 
349
gimp_parasite_list_new (void)
 
350
{
 
351
  GimpParasiteList *list;
 
352
 
 
353
  list = g_object_new (GIMP_TYPE_PARASITE_LIST, NULL);
 
354
 
 
355
  return list;
 
356
}
 
357
 
 
358
GimpParasiteList *
 
359
gimp_parasite_list_copy (const GimpParasiteList *list)
 
360
{
 
361
  GimpParasiteList *newlist;
 
362
 
 
363
  g_return_val_if_fail (GIMP_IS_PARASITE_LIST (list), NULL);
 
364
 
 
365
  newlist = gimp_parasite_list_new ();
 
366
 
 
367
  if (list->table)
 
368
    g_hash_table_foreach (list->table, (GHFunc) parasite_copy, newlist);
 
369
 
 
370
  return newlist;
 
371
}
 
372
 
 
373
void
 
374
gimp_parasite_list_add (GimpParasiteList *list,
 
375
                        GimpParasite     *parasite)
 
376
{
 
377
  g_return_if_fail (GIMP_IS_PARASITE_LIST (list));
 
378
  g_return_if_fail (parasite != NULL);
 
379
  g_return_if_fail (parasite->name != NULL);
 
380
 
 
381
  if (list->table == NULL)
 
382
    list->table = g_hash_table_new (g_str_hash, g_str_equal);
 
383
 
 
384
  gimp_parasite_list_remove (list, parasite->name);
 
385
  parasite = gimp_parasite_copy (parasite);
 
386
  g_hash_table_insert (list->table, parasite->name, parasite);
 
387
 
 
388
  g_signal_emit (list, parasite_list_signals[ADD], 0, parasite);
 
389
}
 
390
 
 
391
void
 
392
gimp_parasite_list_remove (GimpParasiteList *list,
 
393
                           const gchar      *name)
 
394
{
 
395
  GimpParasite *parasite;
 
396
 
 
397
  g_return_if_fail (GIMP_IS_PARASITE_LIST (list));
 
398
 
 
399
  if (list->table)
 
400
    {
 
401
      parasite = gimp_parasite_list_find (list, name);
 
402
 
 
403
      if (parasite)
 
404
        {
 
405
          g_hash_table_remove (list->table, name);
 
406
 
 
407
          g_signal_emit (list, parasite_list_signals[REMOVE], 0, parasite);
 
408
 
 
409
          gimp_parasite_free (parasite);
 
410
        }
 
411
    }
 
412
}
 
413
 
 
414
gint
 
415
gimp_parasite_list_length (GimpParasiteList *list)
 
416
{
 
417
  g_return_val_if_fail (GIMP_IS_PARASITE_LIST (list), 0);
 
418
 
 
419
  if (! list->table)
 
420
    return 0;
 
421
 
 
422
  return g_hash_table_size (list->table);
 
423
}
 
424
 
 
425
gint
 
426
gimp_parasite_list_persistent_length (GimpParasiteList *list)
 
427
{
 
428
  gint len = 0;
 
429
 
 
430
  g_return_val_if_fail (GIMP_IS_PARASITE_LIST (list), 0);
 
431
 
 
432
  if (! list->table)
 
433
    return 0;
 
434
 
 
435
  gimp_parasite_list_foreach (list,
 
436
                              (GHFunc) parasite_count_if_persistent, &len);
 
437
 
 
438
  return len;
 
439
}
 
440
 
 
441
void
 
442
gimp_parasite_list_foreach (GimpParasiteList *list,
 
443
                            GHFunc            function,
 
444
                            gpointer          user_data)
 
445
{
 
446
  g_return_if_fail (GIMP_IS_PARASITE_LIST (list));
 
447
 
 
448
  if (! list->table)
 
449
    return;
 
450
 
 
451
  g_hash_table_foreach (list->table, function, user_data);
 
452
}
 
453
 
 
454
GimpParasite *
 
455
gimp_parasite_list_find (GimpParasiteList *list,
 
456
                         const gchar      *name)
 
457
{
 
458
  g_return_val_if_fail (GIMP_IS_PARASITE_LIST (list), NULL);
 
459
 
 
460
  if (list->table)
 
461
    return (GimpParasite *) g_hash_table_lookup (list->table, name);
 
462
 
 
463
  return NULL;
 
464
}
 
465
 
 
466
 
 
467
static void
 
468
parasite_serialize (const gchar      *key,
 
469
                    GimpParasite     *parasite,
 
470
                    GimpConfigWriter *writer)
 
471
{
 
472
  if (! gimp_parasite_is_persistent (parasite))
 
473
    return;
 
474
 
 
475
  gimp_config_writer_open (writer, parasite_symbol);
 
476
 
 
477
  gimp_config_writer_printf (writer, "\"%s\" %lu %lu",
 
478
                             gimp_parasite_name (parasite),
 
479
                             gimp_parasite_flags (parasite),
 
480
                             gimp_parasite_data_size (parasite));
 
481
 
 
482
  gimp_config_writer_data (writer,
 
483
                           gimp_parasite_data_size (parasite),
 
484
                           gimp_parasite_data (parasite));
 
485
 
 
486
  gimp_config_writer_close (writer);
 
487
  gimp_config_writer_linefeed (writer);
 
488
}
 
489
 
 
490
static void
 
491
parasite_copy (const gchar      *key,
 
492
               GimpParasite     *parasite,
 
493
               GimpParasiteList *list)
 
494
{
 
495
  gimp_parasite_list_add (list, parasite);
 
496
}
 
497
 
 
498
static gboolean
 
499
parasite_free (const gchar  *key,
 
500
               GimpParasite *parasite,
 
501
               gpointer     unused)
 
502
{
 
503
  gimp_parasite_free (parasite);
 
504
 
 
505
  return TRUE;
 
506
}
 
507
 
 
508
static void
 
509
parasite_count_if_persistent (const gchar  *key,
 
510
                              GimpParasite *parasite,
 
511
                              gint         *count)
 
512
{
 
513
  if (gimp_parasite_is_persistent (parasite))
 
514
    *count = *count + 1;
 
515
}