1 /* LIBGIMP - The GIMP Library
2 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
3 *
4 * gimpparasite.c
5 * Copyright (C) 1998 Jay Cox <jaycox@gimp.org>
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 3 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 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <https://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #include <stdio.h>
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28 #include <string.h>
29
30 #include <glib-object.h>
31
32 #ifdef G_OS_WIN32
33 #include <process.h> /* For _getpid() */
34 #endif
35
36 #include "gimpbasetypes.h"
37
38 #include "gimpparasite.h"
39
40
41 /**
42 * SECTION: gimpparasite
43 * @title: GimpParasite
44 * @short_description: Arbitrary pieces of data which can be attached
45 * to various GIMP objects.
46 * @see_also: gimp_image_parasite_attach(),
47 * gimp_drawable_parasite_attach(), gimp_parasite_attach()
48 * and their related functions.
49 *
50 * Arbitrary pieces of data which can be attached to various GIMP objects.
51 **/
52
53
54 /*
55 * GIMP_TYPE_PARASITE
56 */
57
58 GType
gimp_parasite_get_type(void)59 gimp_parasite_get_type (void)
60 {
61 static GType type = 0;
62
63 if (! type)
64 type = g_boxed_type_register_static ("GimpParasite",
65 (GBoxedCopyFunc) gimp_parasite_copy,
66 (GBoxedFreeFunc) gimp_parasite_free);
67
68 return type;
69 }
70
71
72 /*
73 * GIMP_TYPE_PARAM_PARASITE
74 */
75
76 #define GIMP_PARAM_SPEC_PARASITE(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_PARASITE, GimpParamSpecParasite))
77
78 typedef struct _GimpParamSpecParasite GimpParamSpecParasite;
79
80 struct _GimpParamSpecParasite
81 {
82 GParamSpecBoxed parent_instance;
83 };
84
85 static void gimp_param_parasite_class_init (GParamSpecClass *class);
86 static void gimp_param_parasite_init (GParamSpec *pspec);
87 static gboolean gimp_param_parasite_validate (GParamSpec *pspec,
88 GValue *value);
89 static gint gimp_param_parasite_values_cmp (GParamSpec *pspec,
90 const GValue *value1,
91 const GValue *value2);
92
93 GType
gimp_param_parasite_get_type(void)94 gimp_param_parasite_get_type (void)
95 {
96 static GType type = 0;
97
98 if (! type)
99 {
100 const GTypeInfo type_info =
101 {
102 sizeof (GParamSpecClass),
103 NULL, NULL,
104 (GClassInitFunc) gimp_param_parasite_class_init,
105 NULL, NULL,
106 sizeof (GimpParamSpecParasite),
107 0,
108 (GInstanceInitFunc) gimp_param_parasite_init
109 };
110
111 type = g_type_register_static (G_TYPE_PARAM_BOXED,
112 "GimpParamParasite",
113 &type_info, 0);
114 }
115
116 return type;
117 }
118
119 static void
gimp_param_parasite_class_init(GParamSpecClass * class)120 gimp_param_parasite_class_init (GParamSpecClass *class)
121 {
122 class->value_type = GIMP_TYPE_PARASITE;
123 class->value_validate = gimp_param_parasite_validate;
124 class->values_cmp = gimp_param_parasite_values_cmp;
125 }
126
127 static void
gimp_param_parasite_init(GParamSpec * pspec)128 gimp_param_parasite_init (GParamSpec *pspec)
129 {
130 }
131
132 static gboolean
gimp_param_parasite_validate(GParamSpec * pspec,GValue * value)133 gimp_param_parasite_validate (GParamSpec *pspec,
134 GValue *value)
135 {
136 GimpParasite *parasite = value->data[0].v_pointer;
137
138 if (! parasite)
139 {
140 return TRUE;
141 }
142 else if (parasite->name == NULL ||
143 *parasite->name == '\0' ||
144 ! g_utf8_validate (parasite->name, -1, NULL) ||
145 (parasite->size == 0 && parasite->data != NULL) ||
146 (parasite->size > 0 && parasite->data == NULL))
147 {
148 g_value_set_boxed (value, NULL);
149 return TRUE;
150 }
151
152 return FALSE;
153 }
154
155 static gint
gimp_param_parasite_values_cmp(GParamSpec * pspec,const GValue * value1,const GValue * value2)156 gimp_param_parasite_values_cmp (GParamSpec *pspec,
157 const GValue *value1,
158 const GValue *value2)
159 {
160 GimpParasite *parasite1 = value1->data[0].v_pointer;
161 GimpParasite *parasite2 = value2->data[0].v_pointer;
162
163 /* try to return at least *something*, it's useless anyway... */
164
165 if (! parasite1)
166 return parasite2 != NULL ? -1 : 0;
167 else if (! parasite2)
168 return parasite1 != NULL;
169 else
170 return gimp_parasite_compare (parasite1, parasite2);
171 }
172
173 GParamSpec *
gimp_param_spec_parasite(const gchar * name,const gchar * nick,const gchar * blurb,GParamFlags flags)174 gimp_param_spec_parasite (const gchar *name,
175 const gchar *nick,
176 const gchar *blurb,
177 GParamFlags flags)
178 {
179 GimpParamSpecParasite *parasite_spec;
180
181 parasite_spec = g_param_spec_internal (GIMP_TYPE_PARAM_PARASITE,
182 name, nick, blurb, flags);
183
184 return G_PARAM_SPEC (parasite_spec);
185 }
186
187
188 #ifdef DEBUG
189 static void
gimp_parasite_print(GimpParasite * parasite)190 gimp_parasite_print (GimpParasite *parasite)
191 {
192 if (parasite == NULL)
193 {
194 g_print ("pid %d: attempt to print a null parasite\n", getpid ());
195 return;
196 }
197
198 g_print ("pid %d: parasite: %p\n", getpid (), parasite);
199
200 if (parasite->name)
201 g_print ("\tname: %s\n", parasite->name);
202 else
203 g_print ("\tname: NULL\n");
204
205 g_print ("\tflags: %d\n", parasite->flags);
206 g_print ("\tsize: %d\n", parasite->size);
207 if (parasite->size > 0)
208 g_print ("\tdata: %p\n", parasite->data);
209 }
210 #endif
211
212 GimpParasite *
gimp_parasite_new(const gchar * name,guint32 flags,guint32 size,gconstpointer data)213 gimp_parasite_new (const gchar *name,
214 guint32 flags,
215 guint32 size,
216 gconstpointer data)
217 {
218 GimpParasite *parasite;
219
220 if (! (name && *name))
221 return NULL;
222
223 parasite = g_slice_new (GimpParasite);
224 parasite->name = g_strdup (name);
225 parasite->flags = (flags & 0xFF);
226 parasite->size = size;
227
228 if (size)
229 parasite->data = g_memdup (data, size);
230 else
231 parasite->data = NULL;
232
233 return parasite;
234 }
235
236 void
gimp_parasite_free(GimpParasite * parasite)237 gimp_parasite_free (GimpParasite *parasite)
238 {
239 if (parasite == NULL)
240 return;
241
242 if (parasite->name)
243 g_free (parasite->name);
244
245 if (parasite->data)
246 g_free (parasite->data);
247
248 g_slice_free (GimpParasite, parasite);
249 }
250
251 gboolean
gimp_parasite_is_type(const GimpParasite * parasite,const gchar * name)252 gimp_parasite_is_type (const GimpParasite *parasite,
253 const gchar *name)
254 {
255 if (!parasite || !parasite->name)
256 return FALSE;
257
258 return (strcmp (parasite->name, name) == 0);
259 }
260
261 GimpParasite *
gimp_parasite_copy(const GimpParasite * parasite)262 gimp_parasite_copy (const GimpParasite *parasite)
263 {
264 if (parasite == NULL)
265 return NULL;
266
267 return gimp_parasite_new (parasite->name, parasite->flags,
268 parasite->size, parasite->data);
269 }
270
271 gboolean
gimp_parasite_compare(const GimpParasite * a,const GimpParasite * b)272 gimp_parasite_compare (const GimpParasite *a,
273 const GimpParasite *b)
274 {
275 if (a && b &&
276 a->name && b->name &&
277 strcmp (a->name, b->name) == 0 &&
278 a->flags == b->flags &&
279 a->size == b->size)
280 {
281 if (a->data == NULL && b->data == NULL)
282 return TRUE;
283 else if (a->data && b->data && memcmp (a->data, b->data, a->size) == 0)
284 return TRUE;
285 }
286
287 return FALSE;
288 }
289
290 gulong
gimp_parasite_flags(const GimpParasite * parasite)291 gimp_parasite_flags (const GimpParasite *parasite)
292 {
293 if (parasite == NULL)
294 return 0;
295
296 return parasite->flags;
297 }
298
299 gboolean
gimp_parasite_is_persistent(const GimpParasite * parasite)300 gimp_parasite_is_persistent (const GimpParasite *parasite)
301 {
302 if (parasite == NULL)
303 return FALSE;
304
305 return (parasite->flags & GIMP_PARASITE_PERSISTENT);
306 }
307
308 gboolean
gimp_parasite_is_undoable(const GimpParasite * parasite)309 gimp_parasite_is_undoable (const GimpParasite *parasite)
310 {
311 if (parasite == NULL)
312 return FALSE;
313
314 return (parasite->flags & GIMP_PARASITE_UNDOABLE);
315 }
316
317 gboolean
gimp_parasite_has_flag(const GimpParasite * parasite,gulong flag)318 gimp_parasite_has_flag (const GimpParasite *parasite,
319 gulong flag)
320 {
321 if (parasite == NULL)
322 return FALSE;
323
324 return (parasite->flags & flag);
325 }
326
327 const gchar *
gimp_parasite_name(const GimpParasite * parasite)328 gimp_parasite_name (const GimpParasite *parasite)
329 {
330 if (parasite)
331 return parasite->name;
332
333 return NULL;
334 }
335
336 gconstpointer
gimp_parasite_data(const GimpParasite * parasite)337 gimp_parasite_data (const GimpParasite *parasite)
338 {
339 if (parasite)
340 return parasite->data;
341
342 return NULL;
343 }
344
345 glong
gimp_parasite_data_size(const GimpParasite * parasite)346 gimp_parasite_data_size (const GimpParasite *parasite)
347 {
348 if (parasite)
349 return parasite->size;
350
351 return 0;
352 }
353