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