1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
4  *
5  * This library is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library. If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Authors: Christopher James Lahey <clahey@umich.edu>
18  */
19 
20 #include "evolution-data-server-config.h"
21 
22 #include "e-list-iterator.h"
23 #include "e-list.h"
24 
25 static void        e_list_iterator_invalidate (EIterator *iterator);
26 static gboolean    e_list_iterator_is_valid   (EIterator *iterator);
27 static void        e_list_iterator_set        (EIterator  *iterator,
28 					       gconstpointer object);
29 static void        e_list_iterator_remove     (EIterator  *iterator);
30 static void        e_list_iterator_insert     (EIterator  *iterator,
31 					       gconstpointer object,
32 					       gboolean    before);
33 static gboolean    e_list_iterator_prev       (EIterator  *iterator);
34 static gboolean    e_list_iterator_next       (EIterator  *iterator);
35 static void        e_list_iterator_reset      (EIterator *iterator);
36 static void        e_list_iterator_last       (EIterator *iterator);
37 static gconstpointer e_list_iterator_get        (EIterator *iterator);
38 static void        e_list_iterator_dispose    (GObject *object);
39 
G_DEFINE_TYPE(EListIterator,e_list_iterator,E_TYPE_ITERATOR)40 G_DEFINE_TYPE (EListIterator, e_list_iterator, E_TYPE_ITERATOR)
41 
42 static void
43 e_list_iterator_class_init (EListIteratorClass *class)
44 {
45 	GObjectClass *object_class;
46 	EIteratorClass *iterator_class;
47 
48 	object_class = G_OBJECT_CLASS (class);
49 	object_class->dispose = e_list_iterator_dispose;
50 
51 	iterator_class = E_ITERATOR_CLASS (class);
52 	iterator_class->invalidate = e_list_iterator_invalidate;
53 	iterator_class->get = e_list_iterator_get;
54 	iterator_class->reset = e_list_iterator_reset;
55 	iterator_class->last = e_list_iterator_last;
56 	iterator_class->next = e_list_iterator_next;
57 	iterator_class->prev = e_list_iterator_prev;
58 	iterator_class->remove = e_list_iterator_remove;
59 	iterator_class->insert = e_list_iterator_insert;
60 	iterator_class->set = e_list_iterator_set;
61 	iterator_class->is_valid = e_list_iterator_is_valid;
62 }
63 
64 /**
65  * e_list_iterator_init:
66  */
67 static void
e_list_iterator_init(EListIterator * list)68 e_list_iterator_init (EListIterator *list)
69 {
70 }
71 
72 EIterator *
e_list_iterator_new(EList * list)73 e_list_iterator_new (EList *list)
74 {
75 	EListIterator *iterator = NULL;
76 
77 	g_return_val_if_fail (list != NULL, NULL);
78 	g_return_val_if_fail (E_IS_LIST (list), NULL);
79 
80 	iterator = g_object_new (E_TYPE_LIST_ITERATOR, NULL);
81 	if (!iterator)
82 		return NULL;
83 	iterator->list = list;
84 	g_object_ref (list);
85 	iterator->iterator = list->list;
86 
87 	return E_ITERATOR (iterator);
88 }
89 
90 /*
91  * Virtual functions:
92  */
93 static void
e_list_iterator_dispose(GObject * object)94 e_list_iterator_dispose (GObject *object)
95 {
96 	EListIterator *iterator = E_LIST_ITERATOR (object);
97 	e_list_remove_iterator (iterator->list, E_ITERATOR (iterator));
98 	g_object_unref (iterator->list);
99 
100 	/* Chain up to parent's dispose() method. */
101 	G_OBJECT_CLASS (e_list_iterator_parent_class)->dispose (object);
102 }
103 
104 static gconstpointer
e_list_iterator_get(EIterator * _iterator)105 e_list_iterator_get (EIterator *_iterator)
106 {
107 	EListIterator *iterator = E_LIST_ITERATOR (_iterator);
108 	if (iterator->iterator)
109 		return iterator->iterator->data;
110 	else
111 		return NULL;
112 }
113 
114 static void
e_list_iterator_reset(EIterator * _iterator)115 e_list_iterator_reset (EIterator *_iterator)
116 {
117 	EListIterator *iterator = E_LIST_ITERATOR (_iterator);
118 	iterator->iterator = iterator->list->list;
119 }
120 
121 static void
e_list_iterator_last(EIterator * _iterator)122 e_list_iterator_last (EIterator *_iterator)
123 {
124 	EListIterator *iterator = E_LIST_ITERATOR (_iterator);
125 	iterator->iterator = g_list_last (iterator->list->list);
126 }
127 
128 static gboolean
e_list_iterator_next(EIterator * _iterator)129 e_list_iterator_next (EIterator *_iterator)
130 {
131 	EListIterator *iterator = E_LIST_ITERATOR (_iterator);
132 	if (iterator->iterator)
133 		iterator->iterator = g_list_next (iterator->iterator);
134 	else
135 		iterator->iterator = iterator->list->list;
136 	return (iterator->iterator != NULL);
137 }
138 
139 static gboolean
e_list_iterator_prev(EIterator * _iterator)140 e_list_iterator_prev (EIterator *_iterator)
141 {
142 	EListIterator *iterator = E_LIST_ITERATOR (_iterator);
143 	if (iterator->iterator)
144 		iterator->iterator = g_list_previous (iterator->iterator);
145 	else
146 		iterator->iterator = g_list_last (iterator->list->list);
147 	return (iterator->iterator != NULL);
148 }
149 
150 static void
e_list_iterator_insert(EIterator * _iterator,gconstpointer object,gboolean before)151 e_list_iterator_insert (EIterator *_iterator,
152                         gconstpointer object,
153                         gboolean before)
154 {
155 	EListIterator *iterator = E_LIST_ITERATOR (_iterator);
156 	gpointer data;
157 	if (iterator->list->copy)
158 		data = iterator->list->copy (object, iterator->list->closure);
159 	else
160 		data = (gpointer) object;
161 	if (iterator->iterator) {
162 		if (before) {
163 			iterator->list->list = g_list_first (g_list_prepend (iterator->iterator, data));
164 			iterator->iterator = iterator->iterator->prev;
165 		} else {
166 			if (iterator->iterator->next)
167 				iterator->iterator->next = g_list_prepend (iterator->iterator->next, data);
168 			else
169 				iterator->iterator = g_list_append (iterator->iterator, data);
170 			iterator->iterator = iterator->iterator->next;
171 		}
172 		e_list_invalidate_iterators (iterator->list, E_ITERATOR (iterator));
173 	} else {
174 		if (before) {
175 			iterator->list->list = g_list_append (iterator->list->list, data);
176 			iterator->iterator = g_list_last (iterator->list->list);
177 		} else {
178 			iterator->list->list = g_list_prepend (iterator->list->list, data);
179 			iterator->iterator = iterator->list->list;
180 		}
181 		e_list_invalidate_iterators (iterator->list, E_ITERATOR (iterator));
182 	}
183 }
184 
185 static void
e_list_iterator_remove(EIterator * _iterator)186 e_list_iterator_remove (EIterator *_iterator)
187 {
188 	EListIterator *iterator = E_LIST_ITERATOR (_iterator);
189 	if (iterator->iterator) {
190 		e_list_remove_link (iterator->list, iterator->iterator);
191 	}
192 }
193 
194 static void
e_list_iterator_set(EIterator * _iterator,gconstpointer object)195 e_list_iterator_set (EIterator *_iterator,
196                      gconstpointer object)
197 {
198 	EListIterator *iterator = E_LIST_ITERATOR (_iterator);
199 	if (iterator->iterator) {
200 		if (iterator->list->free)
201 			iterator->list->free (iterator->iterator->data, iterator->list->closure);
202 		if (iterator->list->copy)
203 			iterator->iterator->data = iterator->list->copy (object, iterator->list->closure);
204 		else
205 			iterator->iterator->data = (gpointer) object;
206 	}
207 }
208 
209 static gboolean
e_list_iterator_is_valid(EIterator * _iterator)210 e_list_iterator_is_valid (EIterator *_iterator)
211 {
212 	EListIterator *iterator = E_LIST_ITERATOR (_iterator);
213 	return iterator->iterator != NULL;
214 }
215 
216 static void
e_list_iterator_invalidate(EIterator * _iterator)217 e_list_iterator_invalidate (EIterator *_iterator)
218 {
219 	EListIterator *iterator = E_LIST_ITERATOR (_iterator);
220 	iterator->iterator = NULL;
221 }
222