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.
  • [get | view] (2021-02-25 09:56:51, 18.7 KB) [[attachment:glib-iter-branch-1.patch]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.