2 Copyright (C) 2001-2009, Parrot Foundation.
7 src/pmc/hashiterator.pmc - Implementation of Iterator for Hashes.
11 Generic iterator for traversing Hash.
17 .local pmc iterator, hash, key, entry
20 unless iterator, iter_end # while (more values)
21 key = shift iterator # get the key. Some key
27 =head2 C++-style usage
29 .local pmc iterator, hash, iter_key, key, entry
32 unless iterator, iter_end # while (more values)
33 iter_key = shift iterator # get the key
34 key = iter_key.'key'() # get an original key used to put value
35 key = iter_key.'value'() # get an entry
50 #include "pmc_hashiteratorkey.h"
54 Advance to next position. Return found (if any) HashBucket.
58 advance_to_next(PARROT_INTERP, PMC *self) {
59 Parrot_HashIterator_attributes * const attrs = PARROT_HASHITERATOR(self);
60 HashBucket *bucket = attrs->bucket;
62 /* Try to advance current bucket */
64 bucket = bucket->next;
67 /* If there is no more buckets */
68 if (attrs->pos == attrs->total_buckets)
71 bucket = attrs->parrot_hash->bi[attrs->pos++];
73 attrs->bucket = bucket;
78 pmclass HashIterator extends Iterator no_ro {
79 ATTR PMC *pmc_hash; /* the Hash which this Iterator iterates */
80 ATTR Hash *parrot_hash; /* Underlying implementation of hash */
81 ATTR HashBucket *bucket; /* Current bucket */
82 ATTR INTVAL total_buckets; /* Total buckets in index */
83 ATTR INTVAL pos; /* Current position in index */
84 ATTR INTVAL elements; /* How many elements left to iterate over */
88 =item C<void init_pmc(PMC *initializer)>
90 Initializes the iterator with an aggregate PMC.
91 Defaults iteration mode to iterate from start.
97 VTABLE void init_pmc(PMC *hash) {
98 Parrot_HashIterator_attributes * const attrs =
99 mem_allocate_zeroed_typed(Parrot_HashIterator_attributes);
101 attrs->pmc_hash = hash;
102 attrs->parrot_hash = (Hash*)VTABLE_get_pointer(INTERP, hash);
103 attrs->total_buckets = attrs->parrot_hash->mask + 1;
106 /* Will be decreased on initial advance_to_next */
107 /* XXX Do we really need to support this use-case ? */
108 attrs->elements = attrs->parrot_hash->entries + 1;
109 PMC_data(SELF) = attrs;
111 PObj_custom_mark_destroy_SETALL(SELF);
113 /* Initial state of iterator is "before start" */
114 /* So, advance to first element */
115 advance_to_next(INTERP, SELF);
120 =item C<void destroy()>
128 VTABLE void destroy() {
129 mem_sys_free(PMC_data(SELF));
130 PMC_data(SELF) = NULL;
137 Marks the hash as live.
144 PMC *hash = PARROT_HASHITERATOR(SELF)->pmc_hash;
146 Parrot_gc_mark_PObj_alive(INTERP, (PObj *)hash);
147 /* We don't mark underlying parrot_hash. Hash PMC will mark it */
152 =item C<PMC *clone()>
157 VTABLE PMC* clone() {
163 =item C<void set_integer_native()>
168 VTABLE void set_integer_native(INTVAL value) {
169 Parrot_HashIterator_attributes * const attrs =
170 PARROT_HASHITERATOR(SELF);
173 /* Restart iterator */
176 advance_to_next(INTERP, SELF);
180 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
181 "HashIterator: unknown iterator type");
186 =item C<PMC *get_pmc()>
188 Returns this Iterator's Hash.
192 VTABLE PMC* get_pmc() {
193 return PARROT_HASHITERATOR(SELF)->pmc_hash;
198 =item C<INTVAL get_bool()>
200 Returns true if there is more elements to iterate over.
206 VTABLE INTVAL get_bool() {
207 return PARROT_HASHITERATOR(SELF)->bucket != 0;
212 =item C<INTVAL elements()>
214 Returns the number of remaining elements in the Hash.
220 VTABLE INTVAL elements() {
221 return PARROT_HASHITERATOR(SELF)->elements;
224 VTABLE INTVAL get_integer() {
225 return SELF.elements();
230 =item C<PMC *shift_pmc()>
232 Returns the HashIteratorKey for the current position and advance
239 VTABLE PMC *shift_pmc() {
240 Parrot_HashIterator_attributes * const attrs =
241 PARROT_HASHITERATOR(SELF);
246 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
249 ret = pmc_new(INTERP, enum_class_HashIteratorKey);
250 /* Poke directly into HIK. We don't want to create any kind of public API for this */
251 PARROT_HASHITERATORKEY(ret)->parrot_hash = attrs->parrot_hash;
252 PARROT_HASHITERATORKEY(ret)->bucket = attrs->bucket;
254 /* Move to next bucket */
255 advance_to_next(INTERP, SELF);
264 VTABLE STRING* shift_string() {
265 PMC * const key = SELF.shift_pmc();
266 return VTABLE_get_string(INTERP, key);
281 * c-file-style: "parrot"
283 * vim: expandtab shiftwidth=4: