/* * Copyright (C) 2004-2005 Vadim Berezniker * http://www.kryptolus.com * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include "alloc.h" #include "kry_marker.h" #include "kry_region.h" #include "kry_region_fixed_list.h" #include "pavl.h" enum { REGION_ADDED, REGION_REMOVED, LAST_SIGNAL }; static void kry_region_fixed_list_class_init (KryRegionFixedListClass *klass); static void kry_region_fixed_list_init (KryRegionFixedList *marker); static void kry_region_fixed_list_finalize(GObject *obj); static guint kry_region_fixed_list_signals[LAST_SIGNAL] = { 0 }; GType kry_region_fixed_list_get_type (void) { static GType kry_region_fixed_list_type = 0; if (!kry_region_fixed_list_type) { static const GTypeInfo kry_region_fixed_list_info = { sizeof (KryRegionFixedListClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) kry_region_fixed_list_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (KryRegionFixedList), 0, /* n_preallocs */ (GInstanceInitFunc) kry_region_fixed_list_init, }; kry_region_fixed_list_type = g_type_register_static (G_TYPE_OBJECT, "KryRegionFixedList", &kry_region_fixed_list_info, (GTypeFlags) 0); } return kry_region_fixed_list_type; } static void kry_region_fixed_list_class_init (KryRegionFixedListClass *klass) { GObjectClass *objklass = G_OBJECT_CLASS(klass); klass->region_added = NULL; klass->region_removed = NULL; objklass->finalize = kry_region_fixed_list_finalize; kry_region_fixed_list_signals[REGION_ADDED] = g_signal_new ("region_added", G_OBJECT_CLASS_TYPE (klass), (GSignalFlags) (G_SIGNAL_RUN_FIRST), G_STRUCT_OFFSET (KryRegionFixedListClass, region_added), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); kry_region_fixed_list_signals[REGION_REMOVED] = g_signal_new ("region_removed", G_OBJECT_CLASS_TYPE (klass), (GSignalFlags) (G_SIGNAL_RUN_FIRST), G_STRUCT_OFFSET (KryRegionFixedListClass, region_removed), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } static void kry_region_fixed_list_init (KryRegionFixedList *region) { } static int kry_region_fixed_list_compare_region_info(const void *a, const void *b, void * param) { struct KryRegionFixedInfo *data_left = (struct KryRegionFixedInfo *) a; struct KryRegionFixedInfo *data_right = (struct KryRegionFixedInfo *) b; struct KryRegionFixed *r1 = (struct KryRegionFixed *) data_left->regions->data; struct KryRegionFixed *r2 = (struct KryRegionFixed *) data_right->regions->data; if(r1->start < r2->start) { return -1; } else if(r1->start > r2->start) { return 1; } else { return 0; } } void kry_region_fixed_list_free_region_info(void *a, void *param) { struct KryRegionFixedInfo *data = (struct KryRegionFixedInfo*) a; g_list_foreach(data->regions, (GFunc) kry_free_minimal, NULL); g_list_free(data->regions); kry_free(data); } static void kry_region_fixed_list_finalize(GObject *obj) { g_return_if_fail(KRY_IS_REGION_LIST(obj)); KryRegionFixedList *list = KRY_REGION_FIXED_LIST(obj); if(list->tree) { pavl_destroy(list->tree, kry_region_fixed_list_free_region_info); list->tree = NULL; } } GObject* kry_region_fixed_list_new () { KryRegionFixedList *region_list; region_list = KRY_REGION_FIXED_LIST(g_object_new (KRY_TYPE_REGION_FIXED_LIST, NULL)); region_list->tree = pavl_create(kry_region_fixed_list_compare_region_info, NULL, NULL); return G_OBJECT (region_list); } void kry_region_fixed_list_print(KryRegionFixedList *list) { pavl_traverser trav; pavl_t_init(&trav, list->tree); while(struct KryRegionFixedInfo *rv = (struct KryRegionFixedInfo *) pavl_t_next(&trav)) { for(GList *ptr = rv->regions; ptr; ptr = ptr->next) { struct KryRegionFixed *region = (struct KryRegionFixed *) ptr->data; printf("%10d - %10d\n", region->start, region->end); } } } void kry_region_fixed_list_add(KryRegionFixedList *list, int start, int end) { g_return_if_fail(KRY_IS_REGION_LIST(list)); struct KryRegionFixed *region = kry_new(struct KryRegionFixed, 1); region->start = start; region->end = end; struct KryRegionFixedInfo *info = kry_new(struct KryRegionFixedInfo, 1); info->regions = g_list_append(NULL, region); struct KryRegionFixedInfo *rv = (struct KryRegionFixedInfo *) pavl_find(list->tree, info); if(rv) { rv->regions = g_list_append(rv->regions, region); kry_free(info); } else { pavl_insert(list->tree, info); } g_signal_emit(G_OBJECT(list), kry_region_fixed_list_signals[REGION_ADDED], 0, region); } void kry_region_fixed_list_remove(KryRegionFixedList *list, int start, int end) { struct KryRegionFixed *region = kry_new(struct KryRegionFixed, 1); region->start = start; region->end = end; struct KryRegionFixedInfo *info = kry_new(struct KryRegionFixedInfo, 1); info->regions = g_list_append(NULL, region); struct KryRegionFixedInfo *rv = (struct KryRegionFixedInfo *) pavl_find(list->tree, info); if(!rv) { kry_free(region); kry_free(info); g_warning("region not found in tree"); return; } if(!rv->regions->next) { pavl_delete(list->tree, rv); g_list_free(rv->regions); kry_free(rv); } else { int found = 0; for(GList *ptr = rv->regions; ptr; ptr = ptr->next) { struct KryRegionFixed *regionCur = (struct KryRegionFixed *) ptr->data; if(regionCur->start == region->start && regionCur->end == region->end) { rv->regions = g_list_delete_link(rv->regions, ptr); found = 1; break; } } if(!found) { g_warning("region not found in tree (in sublist)\n"); kry_free(region); return; } } g_signal_emit(G_OBJECT(list), kry_region_fixed_list_signals[REGION_REMOVED], 0, region); kry_free(region); } void kry_region_fixed_list_get_iter(KryRegionFixedList *list, struct pavl_traverser *iter) { g_return_if_fail (KRY_IS_REGION_LIST (list)); pavl_t_init(iter, list->tree); }