1 /*
2 * Copyright (C) 2004-2005 Vadim Berezniker
3 * http://www.kryptolus.com
4 *
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 */
21
22 #include "stdafx.h"
23
24 #include "alloc.h"
25 #include "kry_marker.h"
26 #include "kry_region.h"
27 #include "kry_region_fixed_list.h"
28 #include "pavl.h"
29
30 enum {
31 REGION_ADDED,
32 REGION_REMOVED,
33 LAST_SIGNAL
34 };
35
36
37 static void kry_region_fixed_list_class_init (KryRegionFixedListClass *klass);
38 static void kry_region_fixed_list_init (KryRegionFixedList *marker);
39 static void kry_region_fixed_list_finalize(GObject *obj);
40
41
42 static guint kry_region_fixed_list_signals[LAST_SIGNAL] = { 0 };
43
44
kry_region_fixed_list_get_type(void)45 GType kry_region_fixed_list_get_type (void)
46 {
47 static GType kry_region_fixed_list_type = 0;
48
49 if (!kry_region_fixed_list_type)
50 {
51 static const GTypeInfo kry_region_fixed_list_info =
52 {
53 sizeof (KryRegionFixedListClass),
54 NULL, /* base_init */
55 NULL, /* base_finalize */
56 (GClassInitFunc) kry_region_fixed_list_class_init,
57 NULL, /* class_finalize */
58 NULL, /* class_data */
59 sizeof (KryRegionFixedList),
60 0, /* n_preallocs */
61 (GInstanceInitFunc) kry_region_fixed_list_init,
62 };
63
64 kry_region_fixed_list_type =
65 g_type_register_static (G_TYPE_OBJECT, "KryRegionFixedList",
66 &kry_region_fixed_list_info, (GTypeFlags) 0);
67 }
68
69 return kry_region_fixed_list_type;
70 }
71
kry_region_fixed_list_class_init(KryRegionFixedListClass * klass)72 static void kry_region_fixed_list_class_init (KryRegionFixedListClass *klass)
73 {
74 GObjectClass *objklass = G_OBJECT_CLASS(klass);
75
76 klass->region_added = NULL;
77 klass->region_removed = NULL;
78
79 objklass->finalize = kry_region_fixed_list_finalize;
80
81 kry_region_fixed_list_signals[REGION_ADDED] =
82 g_signal_new ("region_added",
83 G_OBJECT_CLASS_TYPE (klass),
84 (GSignalFlags) (G_SIGNAL_RUN_FIRST),
85 G_STRUCT_OFFSET (KryRegionFixedListClass, region_added),
86 NULL, NULL,
87 g_cclosure_marshal_VOID__POINTER,
88 G_TYPE_NONE, 1, G_TYPE_POINTER);
89
90 kry_region_fixed_list_signals[REGION_REMOVED] =
91 g_signal_new ("region_removed",
92 G_OBJECT_CLASS_TYPE (klass),
93 (GSignalFlags) (G_SIGNAL_RUN_FIRST),
94 G_STRUCT_OFFSET (KryRegionFixedListClass, region_removed),
95 NULL, NULL,
96 g_cclosure_marshal_VOID__POINTER,
97 G_TYPE_NONE, 1, G_TYPE_POINTER);
98 }
99
kry_region_fixed_list_init(KryRegionFixedList * region)100 static void kry_region_fixed_list_init (KryRegionFixedList *region)
101 {
102 }
103
kry_region_fixed_list_compare_region_info(const void * a,const void * b,void * param)104 static int kry_region_fixed_list_compare_region_info(const void *a, const void *b, void * param)
105 {
106 struct KryRegionFixedInfo *data_left = (struct KryRegionFixedInfo *) a;
107 struct KryRegionFixedInfo *data_right = (struct KryRegionFixedInfo *) b;
108
109 struct KryRegionFixed *r1 = (struct KryRegionFixed *) data_left->regions->data;
110 struct KryRegionFixed *r2 = (struct KryRegionFixed *) data_right->regions->data;
111
112 if(r1->start < r2->start)
113 {
114 return -1;
115 }
116 else if(r1->start > r2->start)
117 {
118 return 1;
119 }
120 else
121 {
122 return 0;
123 }
124 }
125
kry_region_fixed_list_free_region_info(void * a,void * param)126 void kry_region_fixed_list_free_region_info(void *a, void *param)
127 {
128 struct KryRegionFixedInfo *data = (struct KryRegionFixedInfo*) a;
129 g_list_foreach(data->regions, (GFunc) kry_free_minimal, NULL);
130 g_list_free(data->regions);
131 kry_free(data);
132 }
133
kry_region_fixed_list_finalize(GObject * obj)134 static void kry_region_fixed_list_finalize(GObject *obj)
135 {
136 g_return_if_fail(KRY_IS_REGION_LIST(obj));
137
138 KryRegionFixedList *list = KRY_REGION_FIXED_LIST(obj);
139
140 if(list->tree)
141 {
142 pavl_destroy(list->tree, kry_region_fixed_list_free_region_info);
143 list->tree = NULL;
144 }
145 }
146
kry_region_fixed_list_new()147 GObject* kry_region_fixed_list_new ()
148 {
149 KryRegionFixedList *region_list;
150
151 region_list = KRY_REGION_FIXED_LIST(g_object_new (KRY_TYPE_REGION_FIXED_LIST, NULL));
152
153 region_list->tree = pavl_create(kry_region_fixed_list_compare_region_info, NULL, NULL);
154
155 return G_OBJECT (region_list);
156 }
157
kry_region_fixed_list_print(KryRegionFixedList * list)158 void kry_region_fixed_list_print(KryRegionFixedList *list)
159 {
160 pavl_traverser trav;
161 pavl_t_init(&trav, list->tree);
162 while(struct KryRegionFixedInfo *rv = (struct KryRegionFixedInfo *) pavl_t_next(&trav))
163 {
164 for(GList *ptr = rv->regions; ptr; ptr = ptr->next)
165 {
166 struct KryRegionFixed *region = (struct KryRegionFixed *) ptr->data;
167 printf("%10d - %10d\n", region->start, region->end);
168 }
169 }
170 }
171
kry_region_fixed_list_add(KryRegionFixedList * list,int start,int end)172 void kry_region_fixed_list_add(KryRegionFixedList *list, int start, int end)
173 {
174 g_return_if_fail(KRY_IS_REGION_LIST(list));
175
176 struct KryRegionFixed *region = kry_new(struct KryRegionFixed, 1);
177 region->start = start;
178 region->end = end;
179
180 struct KryRegionFixedInfo *info = kry_new(struct KryRegionFixedInfo, 1);
181 info->regions = g_list_append(NULL, region);
182
183 struct KryRegionFixedInfo *rv = (struct KryRegionFixedInfo *) pavl_find(list->tree, info);
184 if(rv)
185 {
186 rv->regions = g_list_append(rv->regions, region);
187 kry_free(info);
188 }
189 else
190 {
191 pavl_insert(list->tree, info);
192 }
193
194 g_signal_emit(G_OBJECT(list), kry_region_fixed_list_signals[REGION_ADDED], 0, region);
195 }
196
kry_region_fixed_list_remove(KryRegionFixedList * list,int start,int end)197 void kry_region_fixed_list_remove(KryRegionFixedList *list, int start, int end)
198 {
199 struct KryRegionFixed *region = kry_new(struct KryRegionFixed, 1);
200 region->start = start;
201 region->end = end;
202
203 struct KryRegionFixedInfo *info = kry_new(struct KryRegionFixedInfo, 1);
204 info->regions = g_list_append(NULL, region);
205
206 struct KryRegionFixedInfo *rv = (struct KryRegionFixedInfo *) pavl_find(list->tree, info);
207 if(!rv)
208 {
209 kry_free(region);
210 kry_free(info);
211 g_warning("region not found in tree");
212 return;
213 }
214
215 if(!rv->regions->next)
216 {
217 pavl_delete(list->tree, rv);
218 g_list_free(rv->regions);
219 kry_free(rv);
220 }
221 else
222 {
223 int found = 0;
224 for(GList *ptr = rv->regions; ptr; ptr = ptr->next)
225 {
226 struct KryRegionFixed *regionCur = (struct KryRegionFixed *) ptr->data;
227 if(regionCur->start == region->start && regionCur->end == region->end)
228 {
229 rv->regions = g_list_delete_link(rv->regions, ptr);
230 found = 1;
231 break;
232 }
233 }
234
235 if(!found)
236 {
237 g_warning("region not found in tree (in sublist)\n");
238 kry_free(region);
239 return;
240 }
241 }
242
243 g_signal_emit(G_OBJECT(list), kry_region_fixed_list_signals[REGION_REMOVED], 0, region);
244
245 kry_free(region);
246 }
247
kry_region_fixed_list_get_iter(KryRegionFixedList * list,struct pavl_traverser * iter)248 void kry_region_fixed_list_get_iter(KryRegionFixedList *list, struct pavl_traverser *iter)
249 {
250 g_return_if_fail (KRY_IS_REGION_LIST (list));
251
252 pavl_t_init(iter, list->tree);
253 }
254