| /* $Id$ | |
| * | |
| * Licensed to the Apache Software Foundation (ASF) under one or more | |
| * contributor license agreements. See the NOTICE file distributed with | |
| * this work for additional information regarding copyright ownership. | |
| * The ASF licenses this file to you under the Apache License, Version | |
| * 2.0 (the "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| /** | |
| * etch_collection.c -- collection support | |
| */ | |
| #include "etch_collection.h" | |
| #include "etch_global.h" | |
| #include "etchobj.h" | |
| int default_iterable_first (etch_iterator*); | |
| int default_iterable_next (etch_iterator*); | |
| int default_iterable_has_next(etch_iterator*); | |
| /** | |
| * new_iterable() | |
| * constructor for an i_iterable interface | |
| */ | |
| i_iterable* new_iterable(i_iterable* thisp, i_iterable* parent, iterable_first func_first, | |
| iterable_next func_next, iterable_has_next func_hasnext) | |
| { | |
| i_iterable* vtab = NULL; | |
| if (thisp) /* initializing existing object? */ | |
| vtab = thisp; | |
| else vtab = new_vtable(parent, sizeof(i_iterable), CLASSID_ITERABLE_VTAB); | |
| if (NULL == vtab) return NULL; | |
| vtab->first = func_first? func_first: default_iterable_first; | |
| vtab->next = func_next? func_next: default_iterable_next; | |
| vtab->has_next = func_hasnext? func_hasnext: default_iterable_has_next; | |
| return vtab; | |
| } | |
| /** | |
| * destroy_iterator() | |
| * iterator destructor | |
| */ | |
| int destroy_iterator(etch_iterator* iterator) | |
| { | |
| if (iterator->refcount > 0) /* if object is refcounted */ | |
| if (--iterator->refcount > 0) /* destroy only if last ref */ | |
| return -1; | |
| /* iterator owns itself, and possibly the collection. | |
| * its vtable is owned by the collection. */ | |
| if (!is_etchobj_static_shell(iterator)) | |
| { | |
| if (iterator->is_own_collection) | |
| ((objmask*)iterator->collection)->destroy(iterator->collection); | |
| etch_free(iterator); | |
| } | |
| return 0; | |
| } | |
| /** | |
| * clone_iterator() | |
| * iterator copy constructor | |
| */ | |
| etch_iterator* clone_iterator(etch_iterator* iterator) | |
| { | |
| etch_iterator* newobj = etch_malloc(sizeof(struct etch_iterator), ETCHTYPEB_ITERATOR); | |
| memcpy(newobj, iterator, sizeof(struct etch_iterator)); | |
| return newobj; | |
| } | |
| /** | |
| * new_iterator() | |
| * constructor for an etch_iterator object. | |
| */ | |
| etch_iterator* new_iterator(void* collection, i_iterable* iterable) | |
| { | |
| etch_iterator* iterator = etch_malloc(sizeof(etch_iterator), ETCHTYPEB_ITERATOR); | |
| set_iterator(iterator, collection, iterable); | |
| return iterator; | |
| } | |
| /** | |
| * set_iterator() | |
| * constructor for an existing etch_iterator object. | |
| */ | |
| int set_iterator(etch_iterator* iterator, void* collection, i_iterable* iterable) | |
| { | |
| memset(iterator, 0, sizeof(etch_iterator)); | |
| iterator->obj_type = ETCHTYPEB_ITERATOR; | |
| iterator->class_id = CLASSID_ITERATOR; | |
| iterator->vtab = iterable; | |
| iterator->collection = collection; | |
| iterator->destroy = destroy_iterator; | |
| iterator->clone = clone_iterator; | |
| iterator->first = iterable->first; | |
| iterator->next = iterable->next; | |
| iterator->has_next = iterable->has_next; | |
| iterator->first(iterator); /* establish initial position */ | |
| return 0; | |
| } | |
| /** | |
| * new_empty_iterator() | |
| * constructor for an empty etch_iterator object, i.e. has_next() is false | |
| */ | |
| etch_iterator* new_empty_iterator() | |
| { | |
| etch_iterator* iterator = etch_malloc(sizeof(etch_iterator), ETCHTYPEB_ITERATOR); | |
| iterator->obj_type = ETCHTYPEB_ITERATOR; | |
| iterator->class_id = CLASSID_ITERATOR; | |
| iterator->destroy = destroy_iterator; | |
| iterator->first = default_iterable_first; | |
| iterator->next = default_iterable_next; | |
| iterator->has_next = default_iterable_has_next; | |
| return iterator; | |
| } | |
| /** | |
| * default_iterable_first() | |
| * i_iterable first() default virtual method | |
| */ | |
| int default_iterable_first(etch_iterator* i) | |
| { | |
| return -1; | |
| } | |
| /** | |
| * default_iterable_next() | |
| * i_iterable next() default virtual method | |
| */ | |
| int default_iterable_next(etch_iterator* i) | |
| { | |
| return -1; | |
| } | |
| /** | |
| * default_iterable_has_next() | |
| * i_iterable has_next() default virtual method | |
| */ | |
| int default_iterable_has_next (etch_iterator* i) | |
| { | |
| return FALSE; | |
| } | |
| /** | |
| * etch_comparator_noteq(), etch_comparator_equal | |
| * comparators to use when a result not dependent on parameters is desired, | |
| * such as when using an add_from method to add to a collection when the | |
| * target collection is empty and thus no contains() comparison is needed. | |
| */ | |
| int etch_comparator_noteq(void* a, void* b) { return -1;} | |
| int etch_comparator_equal(void* a, void* b) { return 0; } |