Commit 497f370a authored by Rico Tzschichholz's avatar Rico Tzschichholz

gee: Add some useful symbols from gee-0.8

parent a828342c
......@@ -220,11 +220,9 @@ public class Vala.CCodeFunction : CCodeNode {
}
public void else_if (CCodeExpression condition) {
var parent_if = (CCodeIfStatement) statement_stack[statement_stack.size - 1];
var parent_if = (CCodeIfStatement) statement_stack.remove_at (statement_stack.size - 1);
assert (parent_if.false_statement == null);
statement_stack.remove_at (statement_stack.size - 1);
current_block = new CCodeBlock ();
var cif = new CCodeIfStatement (condition, current_block);
......@@ -318,8 +316,7 @@ public class Vala.CCodeFunction : CCodeNode {
public void close () {
do {
var top = statement_stack[statement_stack.size - 1];
statement_stack.remove_at (statement_stack.size - 1);
var top = statement_stack.remove_at (statement_stack.size - 1);
current_block = top as CCodeBlock;
} while (current_block == null);
}
......
......@@ -53,8 +53,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
}
public void pop_symbol () {
current_symbol = symbol_stack[symbol_stack.size - 1];
symbol_stack.remove_at (symbol_stack.size - 1);
current_symbol = symbol_stack.remove_at (symbol_stack.size - 1);
}
}
......@@ -568,8 +567,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
public void pop_context () {
if (emit_context_stack.size > 0) {
this.emit_context = emit_context_stack[emit_context_stack.size - 1];
emit_context_stack.remove_at (emit_context_stack.size - 1);
this.emit_context = emit_context_stack.remove_at (emit_context_stack.size - 1);
if (ccode != null) {
ccode.current_line = current_line;
}
......@@ -589,8 +587,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
}
public void pop_line () {
current_line = line_directive_stack[line_directive_stack.size - 1];
line_directive_stack.remove_at (line_directive_stack.size - 1);
current_line = line_directive_stack.remove_at (line_directive_stack.size - 1);
if (ccode != null) {
ccode.current_line = current_line;
}
......@@ -603,8 +600,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
}
public void pop_function () {
emit_context.ccode = emit_context.ccode_stack[emit_context.ccode_stack.size - 1];
emit_context.ccode_stack.remove_at (emit_context.ccode_stack.size - 1);
emit_context.ccode = emit_context.ccode_stack.remove_at (emit_context.ccode_stack.size - 1);
if (ccode != null) {
ccode.current_line = current_line;
}
......
......@@ -24,6 +24,7 @@ libgee_la_VALASOURCES = \
list.vala \
map.vala \
set.vala \
timsort.vala \
$(NULL)
libgee_la_SOURCES = \
......
......@@ -36,8 +36,8 @@ public class Vala.ArrayList<G> : List<G> {
set { _equal_func = value; }
}
private G[] _items = new G[4];
private int _size;
internal G[] _items = new G[4];
internal int _size;
private EqualFunc<G> _equal_func;
// concurrent modification protection
......@@ -110,14 +110,16 @@ public class Vala.ArrayList<G> : List<G> {
return false;
}
public override void remove_at (int index) {
public override G remove_at (int index) {
assert (index >= 0 && index < _size);
G item = _items[index];
_items[index] = null;
shift (index + 1, -1);
_stamp++;
return item;
}
public override void clear () {
......@@ -162,6 +164,7 @@ public class Vala.ArrayList<G> : List<G> {
private ArrayList<G> _list;
private int _index = -1;
protected bool _removed = false;
// concurrent modification protection
public int _stamp = 0;
......@@ -174,12 +177,19 @@ public class Vala.ArrayList<G> : List<G> {
assert (_stamp == _list._stamp);
if (_index < _list._size) {
_index++;
_removed = false;
}
return (_index < _list._size);
}
public override bool has_next () {
assert (_stamp == _list._stamp);
return (_index + 1 < _list._size);
}
public override G? get () {
assert (_stamp == _list._stamp);
assert (! _removed);
if (_index < 0 || _index >= _list._size) {
return null;
......@@ -187,6 +197,23 @@ public class Vala.ArrayList<G> : List<G> {
return _list.get (_index);
}
public override void remove () {
assert (_stamp == _list._stamp);
assert (! _removed && _index >= 0);
assert (_index < _list._size);
_list.remove_at (_index);
_index--;
_removed = true;
_stamp = _list._stamp;
}
public override bool valid {
get {
return _index >= 0 && _index < _list._size && ! _removed;
}
}
}
}
......@@ -30,6 +30,11 @@ public abstract class Vala.Collection<G> : Iterable<G> {
*/
public abstract int size { get; }
/**
* Specifies whether this collection is empty.
*/
public virtual bool is_empty { get { return size == 0; } }
/**
* Determines whether this collection contains the specified item.
*
......@@ -64,5 +69,165 @@ public abstract class Vala.Collection<G> : Iterable<G> {
* read-only collections.
*/
public abstract void clear ();
/**
* Adds all items in the input collection to this collection.
*
* @param collection the collection which items will be added to this
* collection.
*
* @return ``true`` if the collection has been changed, ``false`` otherwise
*/
public virtual bool add_all (Collection<G> collection) {
bool changed = false;
for (Iterator<G> iter = collection.iterator (); iter.next ();) {
G item = iter.get ();
if (!contains (item)) {
add (item);
changed = true;
}
}
return changed;
}
/**
* Returns an array containing all of items from this collection.
*
* @return an array containing all of items from this collection
*/
public virtual G[] to_array () {
var t = typeof (G);
if (t == typeof (bool)) {
return (G[]) to_bool_array ((Collection<bool>) this);
} else if (t == typeof (char)) {
return (G[]) to_char_array ((Collection<char>) this);
} else if (t == typeof (uchar)) {
return (G[]) to_uchar_array ((Collection<uchar>) this);
} else if (t == typeof (int)) {
return (G[]) to_int_array ((Collection<int>) this);
} else if (t == typeof (uint)) {
return (G[]) to_uint_array ((Collection<uint>) this);
} else if (t == typeof (int64)) {
return (G[]) to_int64_array ((Collection<int64>) this);
} else if (t == typeof (uint64)) {
return (G[]) to_uint64_array ((Collection<uint64>) this);
} else if (t == typeof (long)) {
return (G[]) to_long_array ((Collection<long>) this);
} else if (t == typeof (ulong)) {
return (G[]) to_ulong_array ((Collection<ulong>) this);
} else if (t == typeof (float)) {
return (G[]) to_float_array ((Collection<float>) this);
} else if (t == typeof (double)) {
return (G[]) to_double_array ((Collection<double>) this);
} else if (t.is_enum () || t.is_flags ()) {
return (G[]) to_int_array ((Collection<int>) this);
} else {
G[] array = new G[size];
int index = 0;
foreach (G element in this) {
array[index++] = (owned)element;
}
return array;
}
}
private static bool[] to_bool_array (Collection<bool> coll) {
bool[] array = new bool[coll.size];
int index = 0;
foreach (bool element in coll) {
array[index++] = element;
}
return array;
}
private static char[] to_char_array (Collection<char> coll) {
char[] array = new char[coll.size];
int index = 0;
foreach (char element in coll) {
array[index++] = element;
}
return array;
}
private static uchar[] to_uchar_array (Collection<uchar> coll) {
uchar[] array = new uchar[coll.size];
int index = 0;
foreach (uchar element in coll) {
array[index++] = element;
}
return array;
}
private static int[] to_int_array (Collection<int> coll) {
int[] array = new int[coll.size];
int index = 0;
foreach (int element in coll) {
array[index++] = element;
}
return array;
}
private static uint[] to_uint_array (Collection<uint> coll) {
uint[] array = new uint[coll.size];
int index = 0;
foreach (uint element in coll) {
array[index++] = element;
}
return array;
}
private static int64?[] to_int64_array (Collection<int64?> coll) {
int64?[] array = new int64?[coll.size];
int index = 0;
foreach (int64? element in coll) {
array[index++] = (owned)element;
}
return array;
}
private static uint64?[] to_uint64_array (Collection<uint64?> coll) {
uint64?[] array = new uint64?[coll.size];
int index = 0;
foreach (uint64? element in coll) {
array[index++] = (owned)element;
}
return array;
}
private static long[] to_long_array (Collection<long> coll) {
long[] array = new long[coll.size];
int index = 0;
foreach (long element in coll) {
array[index++] = element;
}
return array;
}
private static ulong[] to_ulong_array (Collection<ulong> coll) {
ulong[] array = new ulong[coll.size];
int index = 0;
foreach (ulong element in coll) {
array[index++] = element;
}
return array;
}
private static float?[] to_float_array (Collection<float?> coll) {
float?[] array = new float?[coll.size];
int index = 0;
foreach (float? element in coll) {
array[index++] = (owned)element;
}
return array;
}
private static double?[] to_double_array (Collection<double?> coll) {
double?[] array = new double?[coll.size];
int index = 0;
foreach (double? element in coll) {
array[index++] = (owned)element;
}
return array;
}
}
......@@ -282,6 +282,7 @@ public class Vala.HashMap<K,V> : Map<K,V> {
private HashMap<K,V> _map;
private int _index = -1;
private weak Node<K,V> _node;
private weak Node<K,V> _next;
// concurrent modification protection
private int _stamp;
......@@ -291,21 +292,45 @@ public class Vala.HashMap<K,V> : Map<K,V> {
}
public override bool next () {
if (_node != null) {
_node = _node.next;
}
while (_node == null && _index + 1 < _map._array_size) {
_index++;
_node = _map._nodes[_index];
assert (_stamp == _map._stamp);
if (!has_next ()) {
return false;
}
_node = _next;
_next = null;
return (_node != null);
}
public override bool has_next () {
assert (_stamp == _map._stamp);
if (_next == null) {
_next = _node;
if (_next != null) {
_next = _next.next;
}
while (_next == null && _index + 1 < _map._array_size) {
_index++;
_next = _map._nodes[_index];
}
}
return (_next != null);
}
public override K? get () {
assert (_stamp == _map._stamp);
assert (_node != null);
return _node.key;
}
public override void remove () {
assert_not_reached ();
}
public override bool valid {
get {
return _node != null;
}
}
}
private class ValueCollection<K,V> : Collection<V> {
......@@ -365,6 +390,7 @@ public class Vala.HashMap<K,V> : Map<K,V> {
private HashMap<V,K> _map;
private int _index = -1;
private weak Node<K,V> _node;
private weak Node<K,V> _next;
// concurrent modification protection
private int _stamp;
......@@ -374,21 +400,45 @@ public class Vala.HashMap<K,V> : Map<K,V> {
}
public override bool next () {
if (_node != null) {
_node = _node.next;
}
while (_node == null && _index + 1 < _map._array_size) {
_index++;
_node = _map._nodes[_index];
assert (_stamp == _map._stamp);
if (!has_next ()) {
return false;
}
_node = _next;
_next = null;
return (_node != null);
}
public override bool has_next () {
assert (_stamp == _map._stamp);
if (_next == null) {
_next = _node;
if (_next != null) {
_next = _next.next;
}
while (_next == null && _index + 1 < _map._array_size) {
_index++;
_next = _map._nodes[_index];
}
}
return (_next != null);
}
public override V? get () {
assert (_stamp == _map._stamp);
assert (_node != null);
return _node.value;
}
public override void remove () {
assert_not_reached ();
}
public override bool valid {
get {
return _node != null;
}
}
}
}
......@@ -127,6 +127,24 @@ public class Vala.HashSet<G> : Set<G> {
resize ();
}
private inline bool remove_helper (G key) {
Node<G>** node = lookup_node (key);
if (*node != null) {
assert (*node != null);
Node<G> next = (owned) (*node)->next;
(*node)->key = null;
delete *node;
*node = (owned) next;
_nnodes--;
_stamp++;
return true;
}
return false;
}
private void resize () {
if ((_array_size >= 3 * _nnodes && _array_size >= MIN_SIZE) ||
(3 * _array_size <= _nnodes && _array_size < MAX_SIZE)) {
......@@ -177,6 +195,7 @@ public class Vala.HashSet<G> : Set<G> {
private HashSet<G> _set;
private int _index = -1;
private weak Node<G> _node;
private weak Node<G> _next;
// concurrent modification protection
private int _stamp = 0;
......@@ -186,21 +205,50 @@ public class Vala.HashSet<G> : Set<G> {
}
public override bool next () {
if (_node != null) {
_node = _node.next;
}
while (_node == null && _index + 1 < _set._array_size) {
_index++;
_node = _set._nodes[_index];
assert (_stamp == _set._stamp);
if (!has_next ()) {
return false;
}
_node = _next;
_next = null;
return (_node != null);
}
public override bool has_next () {
assert (_stamp == _set._stamp);
if (_next == null) {
_next = _node;
if (_next != null) {
_next = _next.next;
}
while (_next == null && _index + 1 < _set._array_size) {
_index++;
_next = _set._nodes[_index];
}
}
return (_next != null);
}
public override G? get () {
assert (_stamp == _set._stamp);
assert (_node != null);
return _node.key;
}
public override void remove () {
assert (_stamp == _set._stamp);
assert (_node != null);
has_next ();
_set.remove_helper (_node.key);
_node = null;
_stamp = _set._stamp;
}
public override bool valid {
get {
return _node != null;
}
}
}
}
......@@ -32,11 +32,31 @@ public abstract class Vala.Iterator<G> {
*/
public abstract bool next ();
/**
* Checks whether there is a next element in the iteration.
*
* @return ``true`` if the iterator has a next element
*/
public abstract bool has_next ();
/**
* Returns the current element in the iteration.
*
* @return the current element in the iteration
*/
public abstract G? get ();
/**
* Removes the current element in the iteration. The cursor is set in an
* in-between state. Both {@link get} and {@link remove} will fail until
* the next move of the cursor (calling {@link next}).
*/
public abstract void remove ();
/**
* Determines wheather the call to {@link get} is legal. It is false at the
* beginning and after {@link remove} call and true otherwise.
*/
public abstract bool valid { get; }
}
......@@ -61,7 +61,51 @@ public abstract class Vala.List<G> : Collection<G> {
* Removes the item at the specified index of this list.
*
* @param index zero-based index of the item to be removed
*
* @return the removed element
*/
public abstract G remove_at (int index);
/**
* Returns the first item of the list. Fails if the list is empty.
*
* @return first item in the list
*/
public virtual G first () {
return @get (0);
}
/**
* Returns the last item of the list. Fails if the list is empty.
*
* @return last item in the list
*/
public virtual G last () {
return @get (size - 1);
}
/**
* Inserts items into this list for the input collection at the
* specified position.
*
* @param index zero-based index of the items to be inserted
* @param collection collection of items to be inserted
*/
public virtual void insert_all (int index, Collection<G> collection) {
for (Iterator<G> iter = collection.iterator (); iter.next ();) {
G item = iter.get ();
insert (index, item);
index++;
}
}
/**
* Sorts items by comparing with the specified compare function.
*
* @param compare_func compare function to use to compare items
*/
public abstract void remove_at (int index);
public virtual void sort (owned CompareDataFunc<G> compare_func) {
TimSort.sort<G> (this, compare_func);
}
}
/* timsort.vala
*
* Copyright (C) 2009 Didier Villevalois
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Author:
* Didier 'Ptitjes Villevalois <ptitjes@free.fr>
*/
/**
* A stable, adaptive, iterative mergesort that requires far fewer than n*lg(n)
* comparisons when running on partially sorted arrays, while offering
* performance comparable to a traditional mergesort when run on random arrays.
* Like all proper mergesorts, this sort is stable and runs O(n*log(n)) time
* (worst case). In the worst case, this sort requires temporary storage space
* for n/2 object references; in the best case, it requires only a small
* constant amount of space.
*
* This implementation was adapted from Tim Peters's list sort for Python,
* which is described in detail here:
* [[http://svn.python.org/projects/python/trunk/Objects/listsort.txt]]
*
* Tim's C code may be found here:
* [[http://svn.python.org/projects/python/trunk/Objects/listobject.c]]
*
* The underlying techniques are described in this paper (and may have even
* earlier origins):
*
* "Optimistic Sorting and Information Theoretic Complexity"
* Peter McIlroy
* SODA (Fourth Annual ACM-SIAM Symposium on Discrete Algorithms), pp
* 467-474, Austin, Texas, 25-27 January 1993.
*/
internal class Vala.TimSort<G> {
public static void sort<G> (List<G> list, CompareDataFunc<G> compare) {
if (list is ArrayList) {
TimSort.sort_arraylist<G> ((ArrayList<G>) list, compare);
} else {
TimSort.sort_list<G> (list, compare);
}
}
private static void sort_list<G> (List<G> list, CompareDataFunc<G> compare) {
TimSort<G> helper = new TimSort<G> ();
helper.list_collection = list;
helper.array = list.to_array ();
helper.list = helper.array;
helper.index = 0;
helper.size = list.size;
helper.compare = compare;
helper.do_sort ();
// TODO Use a list iterator and use iter.set (item)
list.clear ();
foreach (G item in helper.array) {
list.add (item);
}
}
private static void sort_arraylist<G> (ArrayList<G> list, CompareDataFunc<G> compare) {
TimSort<G> helper = new TimSort<G> ();
helper.list_collection = list;
helper.list = list._items;
helper.index = 0;
helper.size = list._size;
helper.compare = compare;
helper.do_sort ();
}
private const int MINIMUM_GALLOP = 7;
private List<G> list_collection;
private G[] array;
private void** list;
private int index;
private int size;
private Slice<G>[] pending;
private int minimum_gallop;
private unowned CompareDataFunc<G> compare;
private void do_sort () {
if (size < 2) {
return;
}
pending = new Slice<G>[0];
minimum_gallop = MINIMUM_GALLOP;
Slice<G> remaining = new Slice<G> (list, index, size);
int minimum_length = compute_minimum_run_length (remaining.length);
while (remaining.length > 0) {
// Get the next run
bool descending;
Slice<G> run = compute_longest_run (remaining, out descending);
#if DEBUG
message ("New run (%d, %d) %s", run.index, run.length,
descending ? "descending" : "ascending");
#endif
if (descending) {
run.reverse ();
}
// Extend it to minimum_length, if needed