Attachment 'glib-iter-branch-1.patch'
Download 1 === modified file 'glib/glib-object.h'
2 --- glib/glib-object.h 2001-11-18 00:38:48 +0000
3 +++ glib/glib-object.h 2008-07-18 11:46:11 +0000
4 @@ -24,6 +24,7 @@
5 /* topmost include file for GObject header files */
6 #include <gobject/gboxed.h>
7 #include <gobject/genums.h>
8 +#include <gobject/giterable.h>
9 #include <gobject/gobject.h>
10 #include <gobject/gparam.h>
11 #include <gobject/gparamspecs.h>
12
13 === modified file 'gobject/Makefile.am'
14 --- gobject/Makefile.am 2008-05-28 16:16:55 +0000
15 +++ gobject/Makefile.am 2008-07-18 11:29:39 +0000
16 @@ -91,6 +91,7 @@
17 # GObject library header files for public installation
18 gobject_public_h_sources = \
19 gboxed.h \
20 + giterable.h \
21 gclosure.h \
22 genums.h \
23 gobject.h \
24 @@ -113,6 +114,7 @@
25 # GObject library C sources to build the library from
26 gobject_c_sources = \
27 gboxed.c \
28 + giterable.c \
29 gclosure.c \
30 genums.c \
31 gobject.c \
32
33 === added file 'gobject/giterable.c'
34 --- gobject/giterable.c 1970-01-01 00:00:00 +0000
35 +++ gobject/giterable.c 2008-07-18 12:49:21 +0000
36 @@ -0,0 +1,266 @@
37 +/* GObject - GLib Type, Object, Parameter and Signal Library
38 + * Copyright (C) 2000-2001 Red Hat, Inc.
39 + *
40 + * giterable.h and giterable.c are written and copyright by
41 + * Mikkel Kamstrup Erlandsen 2008
42 + *
43 + * This library is free software; you can redistribute it and/or
44 + * modify it under the terms of the GNU Lesser General Public
45 + * License as published by the Free Software Foundation; either
46 + * version 2 of the License, or (at your option) any later version.
47 + *
48 + * This library is distributed in the hope that it will be useful,
49 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
50 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
51 + * Lesser General Public License for more details.
52 + *
53 + * You should have received a copy of the GNU Lesser General
54 + * Public License along with this library; if not, write to the
55 + * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
56 + * Boston, MA 02111-1307, USA.
57 + */
58 +
59 +#include "config.h"
60 +
61 +#include <string.h>
62 +
63 +#include "giterable.h"
64 +#include "gboxed.h"
65 +#include "gbsearcharray.h"
66 +#include "gvalue.h"
67 +#include "gvaluearray.h"
68 +#include "gclosure.h"
69 +#include "gvaluecollector.h"
70 +#include "gobjectalias.h"
71 +
72 +/*
73 + * TODO
74 + *
75 + * - Implement a GParamSpecIterable
76 + * - Implement GSList, GList, GArray, and GPtrArray as GIterables
77 + */
78 +
79 +/**
80 + * SECTION:giterable
81 + * @short_description: A mechanism to iterate over opaque data structures that
82 + * expose a set-like interface
83 + * @see_also: #GParamSpecIterable, g_param_spec_iterable()
84 + * @title: Iterable Types
85 + *
86 + * GIterable is a generic wrapper mechanism for arbitrary C structures that
87 + * model a set-like structure.
88 + * The only thing the type system needs to know about the structures is how to
89 + * copy and free them as well as how to iterate over its members, beyond that
90 + * they are treated as opaque chunks of memory.
91 + *
92 + * Iterable types are useful for snafu
93 + */
94 +
95 +/* --- typedefs & structures --- */
96 +typedef struct
97 +{
98 + GType type;
99 + GIterNextFunc next;
100 + GIterHasNextFunc has_next;
101 + GIterBreakFunc brake; /* don't use the C keyword 'break' */
102 +} IterableNode;
103 +
104 +/* --- prototypes --- */
105 +static gint iterable_nodes_cmp (gconstpointer p1,
106 + gconstpointer p2);
107 +
108 +
109 +/* --- variables --- */
110 +static GBSearchArray *iterable_bsa = NULL;
111 +static const GBSearchConfig iterable_bconfig = {
112 + sizeof (IterableNode),
113 + iterable_nodes_cmp,
114 + 0,
115 +};
116 +
117 +
118 +/* --- functions --- */
119 +static gint
120 +iterable_nodes_cmp (gconstpointer p1,
121 + gconstpointer p2)
122 +{
123 + const IterableNode *node1 = p1, *node2 = p2;
124 +
125 + return G_BSEARCH_ARRAY_CMP (node1->type, node2->type);
126 +}
127 +
128 +/* Declared in gtype.h and invoked by g_type_init() */
129 +void
130 +g_iterable_type_init (void)
131 +{
132 + static const GTypeInfo info = {
133 + 0, /* class_size */
134 + NULL, /* base_init */
135 + NULL, /* base_destroy */
136 + NULL, /* class_init */
137 + NULL, /* class_destroy */
138 + NULL, /* class_data */
139 + 0, /* instance_size */
140 + 0, /* n_preallocs */
141 + NULL, /* instance_init */
142 + NULL, /* value_table */
143 + };
144 + const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_DERIVABLE |
145 + G_TYPE_FLAG_DEEP_DERIVABLE, };
146 + GType type;
147 +
148 + iterable_bsa = g_bsearch_array_create (&iterable_bconfig);
149 +
150 + /* G_TYPE_ITERABLE
151 + */
152 + type = g_type_register_fundamental (G_TYPE_ITERABLE, g_intern_static_string ("GIterable"), &info, &finfo,
153 + G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT);
154 + g_assert (type == G_TYPE_ITERABLE);
155 +}
156 +
157 +/**
158 + * g_iterable_type_register_static:
159 + * @name: Name of the new iterable type.
160 + * @boxed_copy: Boxed structure copy function.
161 + * @boxed_free: Boxed structure free function.
162 + *
163 + * This function creates a new %G_TYPE_ITERABLE derived type id for a new
164 + * iterable type with name @name.
165 + *
166 + * Returns: New %G_TYPE_ITERABLE derived type id for @name.
167 + */
168 +GType
169 +g_iterable_type_register_static (const gchar *name,
170 + GIterNextFunc next,
171 + GIterHasNextFunc has_next,
172 + GIterBreakFunc brake)
173 +{
174 + static const GTypeInfo type_info = {
175 + 0, /* class_size */
176 + NULL, /* base_init */
177 + NULL, /* base_finalize */
178 + NULL, /* class_init */
179 + NULL, /* class_finalize */
180 + NULL, /* class_data */
181 + 0, /* instance_size */
182 + 0, /* n_preallocs */
183 + NULL, /* instance_init */
184 + NULL, /* value_table */
185 + };
186 + GType type;
187 +
188 + g_return_val_if_fail (name != NULL, 0);
189 + g_return_val_if_fail (next != NULL, 0);
190 + g_return_val_if_fail (has_next != NULL, 0);
191 + g_return_val_if_fail (brake != NULL, 0);
192 + g_return_val_if_fail (g_type_from_name (name) == 0, 0);
193 +
194 + type = g_type_register_static (G_TYPE_ITERABLE, name, &type_info, 0);
195 +
196 + /* install proxy functions upon successfull registration */
197 + if (type)
198 + {
199 + IterableNode key;
200 +
201 + key.type = type;
202 + key.next = next;
203 + key.has_next = has_next;
204 + key.brake = brake;
205 + iterable_bsa = g_bsearch_array_insert (iterable_bsa, &iterable_bconfig,
206 + &key);
207 + }
208 +
209 + return type;
210 +}
211 +
212 +gpointer
213 +g_iter_next (GType iterable_type,
214 + GIter *iter,
215 + gpointer iterable)
216 +{
217 + IterableNode key, *node;
218 +
219 + g_return_val_if_fail (G_TYPE_IS_ITERABLE (iterable_type), NULL);
220 + g_return_val_if_fail (G_TYPE_IS_ABSTRACT (iterable_type) == FALSE, NULL);
221 + g_return_val_if_fail (iter != NULL, NULL);
222 + g_return_val_if_fail (iterable != NULL, NULL);
223 +
224 + key.type = iterable_type;
225 + node = g_bsearch_array_lookup (iterable_bsa, &iterable_bconfig, &key);
226 + return node->next (iter, iterable);
227 +}
228 +
229 +gboolean
230 +g_iter_has_next (GType iterable_type,
231 + GIter *iter,
232 + gpointer iterable)
233 +{
234 + IterableNode key, *node;
235 +
236 + g_return_val_if_fail (G_TYPE_IS_ITERABLE (iterable_type), NULL);
237 + g_return_val_if_fail (G_TYPE_IS_ABSTRACT (iterable_type) == FALSE, NULL);
238 + g_return_val_if_fail (iter != NULL, NULL);
239 + g_return_val_if_fail (iterable != NULL, NULL);
240 +
241 + key.type = iterable_type;
242 + node = g_bsearch_array_lookup (iterable_bsa, &iterable_bconfig, &key);
243 + return node->has_next (iter, iterable);
244 +}
245 +
246 +void
247 +g_iter_break (GType iterable_type,
248 + GIter *iter,
249 + gpointer iterable)
250 +{
251 + IterableNode key, *node;
252 +
253 + g_return_val_if_fail (G_TYPE_IS_ITERABLE (iterable_type), NULL);
254 + g_return_val_if_fail (G_TYPE_IS_ABSTRACT (iterable_type) == FALSE, NULL);
255 + g_return_val_if_fail (iter != NULL, NULL);
256 + g_return_val_if_fail (iterable != NULL, NULL);
257 +
258 + key.type = iterable_type;
259 + node = g_bsearch_array_lookup (iterable_bsa, &iterable_bconfig, &key);
260 + node->brake (iter, iterable);
261 +}
262 +
263 +gpointer
264 +g_iter_get_user_data (GIter *iter)
265 +{
266 + g_return_val_if_fail (iter != NULL, NULL);
267 +
268 + return iter->user_data;
269 +}
270 +
271 +gpointer
272 +g_iter_set_user_data (GIter *iter,
273 + gpointer user_data)
274 +{
275 + g_return_val_if_fail (iter != NULL, NULL);
276 +
277 + iter->user_data = user_data;
278 +
279 + return user_data;
280 +}
281 +
282 +gpointer
283 +g_iter_get_iter_data (GIter *iter)
284 +{
285 + g_return_val_if_fail (iter != NULL, NULL);
286 +
287 + return iter->iter_data;
288 +}
289 +
290 +gpointer
291 +g_iter_set_iter_data (GIter *iter,
292 + gpointer iter_data)
293 +{
294 + g_return_val_if_fail (iter != NULL, NULL);
295 +
296 + iter->iter_data = iter_data;
297 +
298 + return iter_data;
299 +}
300 +
301 +#define __G_ITERABLE_C__
302 +#include "gobjectaliasdef.c"
303
304 === added file 'gobject/giterable.h'
305 --- gobject/giterable.h 1970-01-01 00:00:00 +0000
306 +++ gobject/giterable.h 2008-07-18 12:35:49 +0000
307 @@ -0,0 +1,107 @@
308 +/* GObject - GLib Type, Object, Parameter and Signal Library
309 + * Copyright (C) 2000-2001 Red Hat, Inc.
310 + *
311 + * giterable.h and giterable.c are written and copyright by
312 + * Mikkel Kamstrup Erlandsen 2008
313 + *
314 + * This library is free software; you can redistribute it and/or
315 + * modify it under the terms of the GNU Lesser General Public
316 + * License as published by the Free Software Foundation; either
317 + * version 2 of the License, or (at your option) any later version.
318 + *
319 + * This library is distributed in the hope that it will be useful,
320 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
321 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
322 + * Lesser General Public License for more details.
323 + *
324 + * You should have received a copy of the GNU Lesser General
325 + * Public License along with this library; if not, write to the
326 + * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
327 + * Boston, MA 02111-1307, USA.
328 + */
329 +#if !defined (__GLIB_GOBJECT_H_INSIDE__) && !defined (GOBJECT_COMPILATION)
330 +#error "Only <glib-object.h> can be included directly."
331 +#endif
332 +
333 +#ifndef __G_ITERABLE_H__
334 +#define __G_ITERABLE_H__
335 +
336 +#include <gobject/gtype.h>
337 +
338 +G_BEGIN_DECLS
339 +
340 +/* --- type macros --- */
341 +#define G_TYPE_IS_ITERABLE(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_ITERABLE)
342 +
343 +/* --- typedefs --- */
344 +typedef struct {
345 + gpointer user_data;
346 + gpointer iter_data;
347 + gpointer padding_1;
348 + gpointer padding_2;
349 +} GIter;
350 +
351 +/**
352 + * GIterNextFunc:
353 + * @iter:
354 + * @iterable:
355 + *
356 + *
357 + */
358 +typedef gpointer (*GIterNextFunc) (GIter *iter, gpointer iterable);
359 +
360 +/**
361 + * GIterHasNextFunc:
362 + * @iter:
363 + * @iterable:
364 + *
365 + * This function is provided by the user and should free the boxed
366 + * structure passed.
367 + */
368 +typedef gboolean (*GIterHasNextFunc) (GIter *iter, gpointer iterable);
369 +
370 +/**
371 + * GIterBreakFunc:
372 + * @iter:
373 + * @iterable:
374 + *
375 + *
376 + */
377 +typedef void (*GIterBreakFunc) (GIter *iter, gpointer iterable);
378 +
379 +/* --- prototypes --- */
380 +gpointer g_iter_next (GType boxed_type,
381 + GIter *iter,
382 + gpointer iterable);
383 +gboolean g_iter_has_next (GType boxed_type,
384 + GIter *iter,
385 + gpointer iterable);
386 +void g_iter_break (GType boxed_type,
387 + GIter *iter,
388 + gpointer iterable);
389 +gpointer g_iter_get_user_data (GIter *iter);
390 +gpointer g_iter_set_user_data (GIter *iter,
391 + gpointer user_data);
392 +gpointer g_iter_get_iter_data (GIter *iter);
393 +gpointer g_iter_set_iter_data (GIter *iter,
394 + gpointer iter_data);
395 +
396 +
397 +/* --- convenience --- */
398 +GType g_iterable_type_register_static (const gchar *name,
399 + GIterNextFunc next,
400 + GIterHasNextFunc has_next,
401 + GIterBreakFunc brake);
402 +
403 +
404 +/* --- GLib iterable types --- */
405 +/**
406 + * G_TYPE_SLIST:
407 + *
408 + * The #GType for #GClosure.
409 + */
410 +#define G_TYPE_SLIST (g_slist_get_type ())
411 +
412 +G_END_DECLS
413 +
414 +#endif /* __G_ITERABLE_H__ */
415
416 === modified file 'gobject/gtype.c'
417 --- gobject/gtype.c 2008-07-02 03:43:13 +0000
418 +++ gobject/gtype.c 2008-07-18 11:26:35 +0000
419 @@ -4054,6 +4054,10 @@
420 */
421 g_boxed_type_init ();
422
423 + /* G_TYPE_ITERABLE
424 + */
425 + g_iterable_type_init ();
426 +
427 /* G_TYPE_PARAM
428 */
429 g_param_type_init ();
430
431 === modified file 'gobject/gtype.h'
432 --- gobject/gtype.h 2008-06-22 10:10:59 +0000
433 +++ gobject/gtype.h 2008-07-18 11:36:23 +0000
434 @@ -179,7 +179,12 @@
435 * The fundamental type for #GObject.
436 */
437 #define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20)
438 -
439 +/**
440 + * G_TYPE_ITERABLE:
441 + *
442 + * The fundamental type from which all iterable types are derived
443 + */
444 +#define G_TYPE_ITERABLE G_TYPE_MAKE_FUNDAMENTAL (21)
445
446 /* Reserved fundamental type numbers to create new fundamental
447 * type IDs with G_TYPE_MAKE_FUNDAMENTAL().
448 @@ -208,7 +213,7 @@
449 * First fundamental type number to create a new fundamental type id with
450 * G_TYPE_MAKE_FUNDAMENTAL() reserved for GLib.
451 */
452 -#define G_TYPE_RESERVED_GLIB_FIRST (21)
453 +#define G_TYPE_RESERVED_GLIB_FIRST (22)
454 /**
455 * G_TYPE_RESERVED_GLIB_LAST:
456 *
457 @@ -1455,6 +1460,7 @@
458 G_GNUC_INTERNAL void g_enum_types_init (void); /* sync with genums.c */
459 G_GNUC_INTERNAL void g_param_type_init (void); /* sync with gparam.c */
460 G_GNUC_INTERNAL void g_boxed_type_init (void); /* sync with gboxed.c */
461 +G_GNUC_INTERNAL void g_iterable_type_init (void); /* sync with giterable.c */
462 G_GNUC_INTERNAL void g_object_type_init (void); /* sync with gobject.c */
463 G_GNUC_INTERNAL void g_param_spec_types_init (void); /* sync with gparamspecs.c */
464 G_GNUC_INTERNAL void g_value_transforms_init (void); /* sync with gvaluetransform.c */
465
466 === modified file 'gobject/tests/Makefile.am'
467 --- gobject/tests/Makefile.am 2008-02-05 17:42:09 +0000
468 +++ gobject/tests/Makefile.am 2008-07-18 11:42:21 +0000
469 @@ -8,3 +8,7 @@
470 TEST_PROGS += threadtests
471 threadtests_SOURCES = threadtests.c
472 threadtests_LDADD = $(libgobject_LDADD)
473 +
474 +TEST_PROGS += iterabletests
475 +iterabletests_SOURCES = iterabletests.c
476 +iterabletests_LDADD = $(libgobject_LDADD)
477
478 === added file 'gobject/tests/iterabletests.c'
479 --- gobject/tests/iterabletests.c 1970-01-01 00:00:00 +0000
480 +++ gobject/tests/iterabletests.c 2008-07-18 13:03:04 +0000
481 @@ -0,0 +1,214 @@
482 +/* GLib testing framework examples and tests
483 + * Copyright (C) 2008 Mikkel Kamstrup Erlandsen
484 + * Authors: Mikkel Kamstrup Erlandsen
485 + *
486 + * This work is provided "as is"; redistribution and modification
487 + * in whole or in part, in any medium, physical or electronic is
488 + * permitted without restriction.
489 + *
490 + * This work is distributed in the hope that it will be useful,
491 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
492 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
493 + *
494 + * In no event shall the authors or contributors be liable for any
495 + * direct, indirect, incidental, special, exemplary, or consequential
496 + * damages (including, but not limited to, procurement of substitute
497 + * goods or services; loss of use, data, or profits; or business
498 + * interruption) however caused and on any theory of liability, whether
499 + * in contract, strict liability, or tort (including negligence or
500 + * otherwise) arising in any way out of the use of this software, even
501 + * if advised of the possibility of such damage.
502 + */
503 +#include <glib.h>
504 +#include <glib-object.h>
505 +
506 +/* Shortcut to defining a test */
507 +#define TEST(func,iterable,type) g_test_add ("/GObject/iterable/"#func, Fixture, type, (void (*) (Fixture*, gconstpointer))setup_##iterable, test_##func, teardown_##iterable);
508 +
509 +/* Test fixture passed to all tests */
510 +typedef struct {
511 + gpointer iterable;
512 + GIter *iter;
513 +} Fixture;
514 +
515 +/*
516 + * GType shortcuts. We must use this naming scheme for the macro magic of TEST()
517 + * to work.
518 + */
519 +GType custom_type = G_TYPE_INVALID;
520 +//GType slist_type = G_TYPE_SLIST;
521 +
522 +/*
523 + * CUSTOM ITERABLE
524 + *
525 + * Here follows a *crappy* implementation of GStrv as an iterable
526 + */
527 +typedef struct {
528 + guint idx;
529 +} CustomIterCtx;
530 +
531 +/* Poison element used to signal when an iteration should stop */
532 +const CustomIterCtx custom_terminator = {0,};
533 +const gchar *custom_data[] = {"foo", "bar", "qiz", NULL};
534 +
535 +static gpointer
536 +custom_next (GIter *iter, gpointer iterable)
537 +{
538 + GStrv strv = iterable;
539 + gchar *val;
540 + CustomIterCtx *ctx;
541 +
542 + ctx = g_iter_get_iter_data (iter);
543 +
544 + /* Start a new iteration if there is no iter_data */
545 + if (ctx == NULL)
546 + {
547 + ctx = g_new0 (CustomIterCtx, 1);
548 + ctx->idx = 0;
549 + g_iter_set_iter_data (iter, ctx);
550 + }
551 +
552 + if (ctx == &custom_terminator)
553 + {
554 + g_critical ("Iteration past array size");
555 + return NULL;
556 + }
557 +
558 + val = strv[ctx->idx];
559 + ++ctx->idx;
560 +
561 + /* If this was the last element free ctx, and set iter_data to
562 + * our terminator context */
563 + if (ctx->idx == g_strv_length (strv))
564 + {
565 + g_free (ctx);
566 + g_iter_set_iter_data (iter, &custom_terminator);
567 + }
568 +
569 + return val;
570 +
571 +}
572 +
573 +static gboolean
574 +custom_has_next (GIter *iter, gpointer iterable)
575 +{
576 + GStrv strv = iterable;
577 + CustomIterCtx *ctx;
578 +
579 + ctx = g_iter_get_iter_data (iter);
580 +
581 + /* Start a new iteration if there is no iter_data */
582 + if (ctx == NULL)
583 + {
584 + ctx = g_new0 (CustomIterCtx, 1);
585 + ctx->idx = 0;
586 + g_iter_set_iter_data (iter, ctx);
587 + }
588 +
589 + return (ctx != &custom_terminator &&
590 + ctx->idx < g_strv_length(strv));
591 +}
592 +
593 +static void
594 +custom_break (GIter *iter, gpointer iterable)
595 +{
596 + CustomIterCtx *ctx;
597 +
598 + ctx = g_iter_get_iter_data (iter);
599 + g_assert (ctx != NULL);
600 +
601 + if (ctx != &custom_terminator)
602 + {
603 + g_free (ctx);
604 + g_iter_set_iter_data (iter, &custom_terminator);
605 + }
606 +}
607 +
608 +/*
609 + * CUSTOM FIXTURE HANDLING
610 + */
611 +
612 +static void
613 +setup_custom (Fixture *fix,
614 + gconstpointer data)
615 +{
616 + if (custom_type == G_TYPE_INVALID)
617 + {
618 + custom_type = g_iterable_type_register_static ("CustomGStrvIterable",
619 + custom_next,
620 + custom_has_next,
621 + custom_break);
622 + }
623 +
624 + fix->iterable = custom_data;
625 + fix->iter = g_new0 (GIter, 1);
626 +}
627 +
628 +static void
629 +teardown_custom (Fixture *fix,
630 + gconstpointer test_data)
631 +{
632 + g_free (fix->iter);
633 +}
634 +
635 +/*
636 + * TEST CASES
637 + */
638 +
639 +/* If this test passes the fixture setup and teardown work */
640 +static void
641 +test_fixture (Fixture *fix,
642 + GType *iterable_type)
643 +{
644 + g_assert (TRUE);
645 +
646 + g_debug ("Testing fixture for %s", g_type_name (*iterable_type));
647 +}
648 +
649 +static void
650 +test_values (Fixture *fix,
651 + GType *iterable_type)
652 +{
653 + GType type = *iterable_type;
654 + guint count = 0;
655 +
656 + g_assert (type == custom_type);
657 + g_assert (fix->iterable == custom_data);
658 +
659 +
660 +
661 + while (g_iter_has_next (type, fix->iter, fix->iterable))
662 + {
663 + count++;
664 + gchar *val = g_iter_next(type, fix->iter, fix->iterable);
665 + switch (count)
666 + {
667 + case 1 :
668 + g_assert_cmpstr ("foo", ==, val);
669 + break;
670 + case 2 :
671 + g_assert_cmpstr ("bar", ==, val);
672 + break;
673 + case 3 :
674 + g_assert_cmpstr ("qiz", ==, val);
675 + break;
676 + default :
677 + g_critical ("Iteration out of bounds");
678 + }
679 + }
680 +
681 + g_assert_cmpint (3, ==, count);
682 +}
683 +
684 +int
685 +main (int argc,
686 + char *argv[])
687 +{
688 + g_test_init (&argc, &argv, NULL);
689 + g_type_init ();
690 +
691 + TEST (fixture, custom, &custom_type);
692 + TEST (values, custom, &custom_type);
693 +
694 + return g_test_run();
695 +}
696
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.