summaryrefslogtreecommitdiff
path: root/hieroglyph/hglist.c
diff options
context:
space:
mode:
Diffstat (limited to 'hieroglyph/hglist.c')
-rw-r--r--hieroglyph/hglist.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/hieroglyph/hglist.c b/hieroglyph/hglist.c
index 9b97bba..43225e8 100644
--- a/hieroglyph/hglist.c
+++ b/hieroglyph/hglist.c
@@ -51,6 +51,7 @@ struct _HieroGlyphListIter {
HgList *top;
HgList *last;
HgList *current;
+ gint32 index;
};
#define hg_list_next(_list) ((_list)->next)
@@ -522,6 +523,7 @@ hg_list_iter_new(HgList *list)
iter->top = list;
iter->last = hg_list_previous(list);
iter->current = list;
+ iter->index = 0;
return iter;
}
@@ -536,6 +538,7 @@ hg_list_get_iter_first(HgList *list,
g_return_val_if_fail (iter->last == hg_list_previous(list), FALSE);
iter->current = iter->top;
+ iter->index = 0;
return TRUE;
}
@@ -548,10 +551,12 @@ hg_list_get_iter_next(HgList *list,
g_return_val_if_fail (iter != NULL, FALSE);
g_return_val_if_fail (iter->top == list, FALSE);
g_return_val_if_fail (iter->last == hg_list_previous(list), FALSE);
+ g_return_val_if_fail (iter->index < G_MAXINT32, FALSE);
iter->current = hg_list_next(iter->current);
if (iter->current == iter->top)
return FALSE;
+ iter->index++;
return TRUE;
}
@@ -564,10 +569,12 @@ hg_list_get_iter_previous(HgList *list,
g_return_val_if_fail (iter != NULL, FALSE);
g_return_val_if_fail (iter->top == list, FALSE);
g_return_val_if_fail (iter->last == hg_list_previous(list), FALSE);
+ g_return_val_if_fail (iter->index != 0, FALSE);
iter->current = hg_list_previous(iter->current);
if (iter->current == iter->last)
return FALSE;
+ iter->index--;
return TRUE;
}
@@ -582,6 +589,8 @@ hg_list_get_iter_last(HgList *list,
g_return_val_if_fail (iter->last == hg_list_previous(list), FALSE);
iter->current = hg_list_last(iter->current);
+ /* postpone to calculate current index */
+ iter->index = -1;
return TRUE;
}
@@ -633,10 +642,98 @@ hg_list_iter_delete_link(HgListIter iter)
iter->top = next;
list = iter->top;
iter->current = prev;
+ iter->index--;
return list;
}
+gint32
+hg_list_iter_get_index(HgListIter iter)
+{
+ g_return_val_if_fail (iter != NULL, -1);
+
+ if (iter->index < 0)
+ iter->index += hg_list_length(iter->top);
+
+ return iter->index;
+}
+
+HgList *
+hg_list_iter_roll(HgListIter start,
+ HgListIter end,
+ guint n)
+{
+ guint n_blocks, start_offset, end_offset;
+ HgList *l, *beginning = NULL, *ending = NULL, *out_beginning = NULL, *out_ending = NULL;
+
+ g_return_val_if_fail (start != NULL, NULL);
+ g_return_val_if_fail (end != NULL, NULL);
+ g_return_val_if_fail (start->top == end->top, NULL);
+ g_return_val_if_fail (start->last == end->last, NULL);
+
+ if (n == 0)
+ return start->top;
+
+ start_offset = hg_list_iter_get_index(start);
+ end_offset = hg_list_iter_get_index(end);
+ if (start_offset < end_offset)
+ n_blocks = end_offset - start_offset + 1;
+ else
+ n_blocks = start_offset - end_offset + 1;
+
+ if (n_blocks == 0)
+ return start->top;
+ n %= n_blocks;
+ if (n != 0) {
+ HG_LIST_SET_LAST_NODE (start->last, FALSE);
+ if (start_offset < end_offset) {
+ out_beginning = hg_list_previous(start->current);
+ out_ending = hg_list_next(end->current);
+ hg_list_next(end->current) = start->current;
+ hg_list_previous(start->current) = end->current;
+ } else {
+ out_beginning = hg_list_previous(end->current);
+ out_ending = hg_list_next(start->current);
+ hg_list_previous(end->current) = start->current;
+ hg_list_next(start->current) = end->current;
+ }
+ if (out_beginning == start->last &&
+ out_ending == start->top) {
+ out_beginning = NULL;
+ out_ending = NULL;
+ }
+
+ if (start_offset > end_offset) {
+ for (l = start->current; n > 0; l = hg_list_next(l), n--);
+ beginning = hg_list_next(l);
+ ending = l;
+ } else {
+ for (l = start->current; n > 0; l = hg_list_previous(l), n--);
+ beginning = l;
+ ending = hg_list_previous(l);
+ }
+ if (out_beginning) {
+ hg_list_next(out_beginning) = beginning;
+ hg_list_previous(beginning) = out_beginning;
+ }
+ if (out_ending) {
+ hg_list_previous(out_ending) = ending;
+ hg_list_next(ending) = out_ending;
+ }
+ if (start_offset < end_offset) {
+ if (start->current == start->top)
+ start->top = end->top = beginning;
+ } else {
+ if (end->current == end->top)
+ start->top = end->top = beginning;
+ }
+ start->last = end->last = hg_list_previous(start->top);
+ HG_LIST_SET_LAST_NODE (start->last, TRUE);
+ }
+
+ return start->top;
+}
+
HgListIter
hg_list_find_iter(HgList *list,
gconstpointer data)