Permalink
Fetching contributors…
Cannot retrieve contributors at this time
5578 lines (4853 sloc) 111 KB
#~~
# Core class libraries for Objeck
# Copyright (c) 2008-2013 Randy Hollines
#
# credits:
# H.W. Lang - merge sort implementation
# Map classes uses a red-black tree variant called an Arne Andersson tree
~~#
use System.IO.Net;
use System.IO.File;
use System.Time;
#~
Provides support for conversions
~#
bundle System.Time {
#~
Utilities for handling dates. Located in the 'collect.obl' library.
~#
class DateUtility {
#~
Parses a date from a String. Format <i>MM: </i>month, <i>dd: </i>day, <i>yy(yy): </i>year, <i>hh: </i>hour, <i>mm: </i>minutes and <i>ss: </i>seconds.
@param format date string format
@param date_str date
@param gmt true is GMT, false otherwise
@return Date instance
~#
function : Parse(date_str : String, format : String, gmt : Bool) ~ Date {
parts := IntMap->New();
# month
month := format->Find("MM");
if(month > -1) {
parts->Insert(month, DatePart->New(month, DatePart->Type->Month));
};
# day
day := format->Find("dd");
if(day > -1) {
parts->Insert(day, DatePart->New(day, DatePart->Type->Day));
};
# year
long_year_format := true;
year := format->Find("yyyy");
if(year > -1) {
parts->Insert(year, DatePart->New(year, DatePart->Type->Year));
}
else {
year := format->Find("yy");
if(year > -1) {
parts->Insert(year, DatePart->New(year, DatePart->Type->Year));
long_year_format := false;
};
};
# hour
hours := format->Find("hh");
if(hours > -1) {
parts->Insert(hours, DatePart->New(hours, DatePart->Type->Hour));
};
# mins
mins := format->Find("mm");
if(mins > -1) {
parts->Insert(mins, DatePart->New(mins, DatePart->Type->Min));
};
# secs
secs := format->Find("ss");
if(secs > -1) {
parts->Insert(secs, DatePart->New(secs, DatePart->Type->Sec));
};
date_month := 0; date_day := 0; date_year := 0;
date_hours := 0; date_mins := 0; date_secs := 0;
offset := 0;
values := parts->GetValues();
each(i : values) {
part := values->Get(i)->As(DatePart);
index := part->GetIndex();
type := part->GetType();
select(type) {
label DatePart->Type->Month: {
pos := month + offset + 1;
if(pos > -1 & pos < date_str->Size()) {
if(date_str->Get(pos)->IsDigit()) {
date_month := date_str->SubString(month + offset, 2)->ToInt();
}
else {
date_month := date_str->SubString(month + offset, 1)->ToInt();
offset -= 1;
};
};
}
label DatePart->Type->Day: {
pos := day + offset + 1;
if(pos > -1 & pos < date_str->Size()) {
if(date_str->Get(pos)->IsDigit()) {
date_day := date_str->SubString(day + offset, 2)->ToInt();
}
else {
date_day := date_str->SubString(day + offset, 1)->ToInt();
offset -= 1;
};
};
}
label DatePart->Type->Year: {
pos := year + offset;
if(pos > -1 & pos < date_str->Size()) {
if(long_year_format) {
date_year := date_str->SubString(year + offset, 4)->ToInt();
}
else {
date_year := 2000;
date_year += date_str->SubString(year + offset, 2)->ToInt();
};
};
}
label DatePart->Type->Hour: {
pos := hours + offset + 1;
if(pos > -1 & pos < date_str->Size()) {
if(date_str->Get(pos)->IsDigit()) {
date_hours := date_str->SubString(hours + offset, 2)->ToInt();
}
else {
date_hours := date_str->SubString(hours + offset, 1)->ToInt();
offset -= 1;
};
};
}
label DatePart->Type->Min: {
pos := mins + offset + 1;
if(pos > -1 & pos < date_str->Size()) {
if(date_str->Get(pos)->IsDigit()) {
date_mins := date_str->SubString(mins + offset, 2)->ToInt();
}
else {
date_mins := date_str->SubString(mins + offset, 1)->ToInt();
offset -= 1;
};
};
}
label DatePart->Type->Sec: {
pos := secs + offset + 1;
if(pos > -1 & pos < date_str->Size()) {
if(date_str->Get(pos)->IsDigit()) {
date_secs := date_str->SubString(secs + offset, 2)->ToInt();
}
else {
date_secs := date_str->SubString(secs + offset, 1)->ToInt();
offset -= 1;
};
};
}
};
};
date := Date->New(date_day, date_month, date_year, gmt);
date->AddHours(date_hours);
date->AddMinutes(date_mins);
date->AddSeconds(date_secs);
return date;
}
}
class DatePart {
@index : Int;
@type : Type;
enum Type {
Month,
Day,
Year,
Hour,
Min,
Sec
}
New(index : Int, type : Type) {
@index := index;
@type := type;
}
method : public : GetType() ~ Type {
return @type;
}
method : public : GetIndex() ~ Int {
return @index;
}
}
}
#~
Collection classes
~#
bundle Collection {
#~
Holds a growable array of integer values
~#
class IntVector {
@values : Int[];
@size : Int;
#~
Default constructor
~#
New() {
@values := Int->New[8];
@size := 0;
}
#~
Copy constructor
@param values values to copy
~#
New(values : IntVector) {
@values := values->ToArray();
@size := values->Size();
}
#~
Copy constructor
@param values values to copy
~#
New(values : Int[]) {
@values := Int->New[values->Size() + values->Size() / 2];
@size := values->Size();
Runtime->Copy(@values, 0, values, 0, @size);
}
method : native : Expand() ~ Nil {
if(@size >= @values->Size()) {
temp : Int[] := Int->New[@size * 2];
Runtime->Copy(temp, 0, @values, 0, @size);
@values := temp;
};
}
#~
Swap two values in the vector
@param a first value
@param b second value
@return true if values were swapped
~#
method : public : native : Swap(a : Int, b : Int) ~ Bool {
if(a < -1 | b < -1 | a > @size | b > @size) {
return false;
};
temp := @values[a];
@values[a] := @values[b];
@values[b] := temp;
return true;
}
#~
Adds a vector of values to the end of the vector
@param values values to append
~#
method : public : AddBack(values : IntVector) ~ Nil {
max := values->Size() + @size;
if(max >= @values->Size()) {
temp : Int[] := Int->New[max + max / 2];
Runtime->Copy(temp, 0, @values, 0, @size);
@values := temp;
};
temp := values->ToArray();
Runtime->Copy(@values, @size, temp, 0, temp->Size());
@size := max;
}
#~
Adds a value to the end
@param value value to append
~#
method : public : AddBack(value : Int) ~ Nil {
Expand();
@values[@size] := value;
@size := @size + 1;
}
#~
Removes the last value
@return value
~#
method : public : RemoveBack() ~ Int {
if(@size > 0) {
@size -= 1;
return @values[@size];
};
return 0;
}
#~
Removes an indexed value
@param i index
@return value
~#
method : public : Remove(i : Int) ~ Int {
if(i > -1 & i < @size) {
temp := Int->New[@values->Size()];
Runtime->Copy(temp, 0, @values, 0, i);
Runtime->Copy(temp, i, @values, i + 1, @size - i - 1);
value := @values[i];
@values := temp;
@size -= 1;
return value;
};
return 0;
}
#~
Gets an indexed value
@param index index
@return value
~#
method : public : Get(index : Int) ~ Int {
if(index > -1 & index < @size) {
return @values[index];
};
return 0;
}
#~
Sets an indexed value
@param value value
@param index index
~#
method : public : Set(value : Int, index : Int) ~ Bool {
if(index > -1 & index < @size) {
@values[index] := value;
return true;
};
return false;
}
#~
Size of vector
@return size of vector
~#
method : public : Size() ~ Int {
return @size;
}
#~
Checks to see if the vector is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @size = 0;
}
#~
Clears the vector
~#
method : public : Empty() ~ Nil {
@values := Int->New[8];
@size := 0;
}
#~
Calculates the average of the values in the vector
@return calculated average
~#
method : public : native : Average() ~ Int {
if(@size <= 0) {
return 0;
};
total := 0;
for(i : Int := 0; i < @size; i += 1;) {
total := total + @values[i];
};
return total / @size;
}
#~
Finds the smallest value in the vector
@return smallest found value
~#
method : public : native : Min() ~ Int {
if(@size <= 0) {
return 0;
};
if(@size = 1) {
return @values[0];
};
min := @values[0];
for(i : Int := 1; i < @size; i += 1;) {
if(@values[i] < min) {
min := @values[i];
};
};
return min;
}
#~
Finds the largest value in the vector
@return largest found value
~#
method : public : native : Max() ~ Int {
if(@size <= 0) {
return 0;
};
if(@size = 1) {
return @values[0];
};
max := @values[0];
for(i : Int := 1; i < @size; i += 1;) {
if(@values[i] > max) {
max := @values[i];
};
};
return max;
}
#~
Sorts the values in the vector
~#
method : public : native : Sort() ~ Nil {
a : Int[] := @values;
b : Int[] := Int->New[@size];
MergeSort(0, @size - 1, a, b);
}
method : native : MergeSort(low : Int, hi : Int, a : Int[], b : Int[]) ~ Nil {
if(low < hi) {
mid := (low + hi) / 2;
MergeSort(low, mid, a, b);
MergeSort(mid + 1, hi, a, b);
Merge(low, mid, hi, a, b);
};
}
method : native : Merge(low : Int, mid : Int, hi : Int, a : Int[], b : Int[]) ~ Nil {
# copy both halves of a to auxiliary array b
for(i := low; i <= hi; i += 1;) {
b[i] := a[i];
};
i := low;
j := mid + 1;
k := low;
# copy back next-greatest element at each time
while(i <= mid & j <= hi) {
if(b[i] <= b[j]) {
a[k] := b[i];
k := k + 1;
i += 1;
}
else {
a[k] := b[j];
k := k + 1;
j := j + 1;
};
};
# copy back remaining elements of first half (if any)
while(i <= mid) {
a[k] := b[i];
k := k + 1;
i += 1;
};
}
#~
Finds a given value in the vector via linear search
@param value value to search for
@return index of found value, -1 if not found
~#
method : public : native : Find(value : Int) ~ Int {
for(i := 0; i < @size; i += 1;) {
if(@values[i] = value) {
return i;
};
};
return -1;
}
#~
Performs a binary search O(log n)
@param value value to search for
@return index of found value, -1 if not found
~#
method : public : native : BinarySearch(value : Int) ~ Int {
low := 0;
high := @size - 1;
while(low <= high) {
mid := (low + high) / 2;
if(@values[mid] > value) {
high := mid - 1;
}
else if(@values[mid] < value) {
low := mid + 1;
}
else {
return mid;
};
};
return -1;
}
#~
Converts the vector into an integer array
@return integer array
~#
method : public : native : ToArray() ~ Int[] {
array : Int[] := Int->New[@size];
Runtime->Copy(array, 0, @values, 0, @size);
return array;
}
#~
Check of the given value is in the vector
@param value value to check for
@return true if found, false otherwise
~#
method : public : Has(value : Int) ~ Bool {
for(i : Int := 0; i < @size; i += 1;) {
if(@values[i] = value) {
return true;
};
};
return false;
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (Int) ~ Bool) ~ IntVector {
filtered := IntVector->New();
for(i : Int := 0; i < @size; i += 1;) {
if(f(@values[i])) {
filtered->AddBack(@values[i]);
};
};
return filtered;
}
#~
Applies the given function to each value in the vector
@param f function to apply
@return newly calculated vector
~#
method : public : Apply(f : (Int) ~ Int) ~ IntVector {
array : Int[] := Int->New[@size];
for(i : Int := 0; i < @size; i += 1;) {
array[i] := @values[i];
};
for(i : Int := 0; i < @size; i += 1;) {
array[i] := f(array[i]);
};
return IntVector->New(array);
}
#~
Reduces elements in the vector
@param f function to apply
@return reduced value
~#
method : public : Reduce(f : (Int, Int) ~ Int) ~ Int {
return Reduce(f, @size);
}
#~
Reduces elements in the vector
@param f function to apply
@param num number of elements to reduce
@return reduced value
~#
method : public : Reduce(f : (Int, Int) ~ Int, num : Int) ~ Int {
val := 0;
if(@size > 0 & @size <= num) {
val := @values[0];
for(i := 1; i < num; i++;) {
val := f(val, @values[i]);
};
};
return val;
}
method : public : ToString() ~ String {
buffer := "[";
for(i := 0; i < @size; i += 1;) {
buffer->Append(@values[i]);
if(i + 1 < @size) {
buffer->Append(',');
};
};
buffer->Append(']');
return buffer;
}
}
#~
Holds a growable array of float values
~#
class FloatVector {
@values : Float[];
@size : Int;
#~
Default constructor
~#
New() {
@values := Float->New[8];
@size := 0;
}
#~
Copy constructor
@param values values to copy
~#
New(values : FloatVector) {
@values := values->ToArray();
@size := values->Size();
}
#~
Copy constructor
@param values values to copy
~#
New(values : Float[]) {
@values := Float->New[values->Size() + values->Size() / 2];
@size := values->Size();
Runtime->Copy(@values, 0, values, 0, @size);
}
#~
Swap two values in the vector
@param a first value
@param b second value
@return true if values were swapped
~#
method : public : native : Swap(a : Int, b : Int) ~ Bool {
if(a < -1 | b < -1 | a > @size | b > @size) {
return false;
};
temp := @values[a];
@values[a] := @values[b];
@values[b] := temp;
return true;
}
method : native : Expand() ~ Nil {
if(@size >= @values->Size()) {
temp : Float[] := Float->New[@size * 2];
Runtime->Copy(temp, 0, @values, 0, @size);
@values := temp;
};
}
#~
Adds a vector of values to the end of the vector
@param values values to append
~#
method : public : AddBack(values : FloatVector) ~ Nil {
max := values->Size() + @size;
if(max >= @values->Size()) {
temp : Float[] := Float->New[max + max / 2];
Runtime->Copy(temp, 0, @values, 0, @size);
@values := temp;
};
temp := values->ToArray();
Runtime->Copy(@values, @size, temp, 0, temp->Size());
@size := max;
}
#~
Adds a value to the end
@param value value to append
~#
method : public : AddBack(value : Float) ~ Nil {
Expand();
@values[@size] := value;
@size := @size + 1;
}
#~
Removes the last value
@return value
~#
method : public : RemoveBack() ~ Float {
if(@size > 0) {
@size -= 1;
return @values[@size];
};
return 0.0;
}
#~
Removes an indexed value
@param i index
@return value
~#
method : public : Remove(i : Int) ~ Float {
if(i > -1 & i < @size) {
temp := Float->New[@values->Size()];
Runtime->Copy(temp, 0, @values, 0, i);
Runtime->Copy(temp, i, @values, i + 1, @size - i - 1);
value := @values[i];
@values := temp;
@size -= 1;
return value;
};
return 0.0;
}
#~
Gets an indexed value
@param index index
@return value
~#
method : public : Get(index : Int) ~ Float {
if(index > -1 & index < @size) {
return @values[index];
};
return 0.0;
}
#~
Sets an indexed value
@param value value
@param index index
~#
method : public : Set(value : Float, index : Int) ~ Bool {
if(index > -1 & index < @size) {
@values[index] := value;
return true;
};
return false;
}
#~
Size of vector
@return size of vector
~#
method : public : Size() ~ Int {
return @size;
}
#~
Checks to see if the vector is empty
@return true if empty, false otherwise
~#
method : public : Empty() ~ Nil {
@values := Float->New[8];
@size := 0;
}
#~
Calculates the average of the values in the vector
@return calculated average
~#
method : public : native : Average() ~ Float {
if(@size <= 0) {
return 0.0;
};
total := 0.0;
for(i : Int := 0; i < @size; i += 1;) {
total := total + @values[i];
};
return total / @size;
}
#~
Finds the smallest value in the vector
@return smallest found value
~#
method : public : native : Min() ~ Float {
if(@size <= 0) {
return 0.0;
};
if(@size = 1) {
return @values[0];
};
min := @values[0];
for(i : Int := 1; i < @size; i += 1;) {
if(@values[i] < min) {
min := @values[i];
};
};
return min;
}
#~
Finds the largest value in the vector
@return largest found value
~#
method : public : native : Max() ~ Float {
if(@size <= 0) {
return 0.0;
};
if(@size = 1) {
return @values[0];
};
max := @values[0];
for(i : Int := 1; i < @size; i += 1;) {
if(@values[i] > max) {
max := @values[i];
};
};
return max;
}
#~
Sorts the values in the vector
~#
method : public : native : Sort() ~ Nil {
a : Float[] := @values;
b : Float[] := Float->New[@size];
MergeSort(0, @size - 1, a, b);
}
method : native : MergeSort(low : Int, hi : Int, a : Float[], b : Float[]) ~ Nil {
if(low < hi) {
mid := (low + hi) / 2;
MergeSort(low, mid, a, b);
MergeSort(mid + 1, hi, a, b);
Merge(low, mid, hi, a, b);
};
}
method : native : Merge(low : Int, mid : Int, hi : Int, a : Float[], b : Float[]) ~ Nil {
# copy both halves of a to auxiliary array b
for(i := low; i <= hi; i += 1;) {
b[i] := a[i];
};
i := low;
j := mid + 1;
k := low;
# copy back next-greatest element at each time
while(i <= mid & j <= hi) {
if(b[i] <= b[j]) {
a[k] := b[i];
k := k + 1;
i += 1;
}
else {
a[k] := b[j];
k := k + 1;
j := j + 1;
};
};
# copy back remaining elements of first half (if any)
while(i <= mid) {
a[k] := b[i];
k := k + 1;
i += 1;
};
}
#~
Finds a given value in the vector via linear search
@param value value to search for
@return index of found value, -1 if not found
~#
method : public : native : Find(value : Float) ~ Int {
for(i := 0; i < @size; i += 1;) {
if(@values[i] = value) {
return i;
};
};
return -1;
}
#~
Performs a binary search O(log n)
@param value value to search for
@return index of found value, -1 if not found
~#
method : public : native : BinarySearch(value : Float) ~ Int {
low := 0;
high := @size - 1;
while(low <= high) {
mid := (low + high) / 2;
if(@values[mid] > value) {
high := mid - 1;
}
else if(@values[mid] < value) {
low := mid + 1;
}
else {
return mid;
};
};
return -1;
}
#~
Converts the vector into an float array
@return float array
~#
method : public : native : ToArray() ~ Float[] {
array : Float[] := Float->New[@size];
Runtime->Copy(array, 0, @values, 0, @size);
return array;
}
#~
Check of the given value is in the vector
@param value value to check for
@return true if found, false otherwise
~#
method : public : Has(value : Float) ~ Bool {
for(i : Int := 0; i < @size; i += 1;) {
if(@values[i] = value) {
return true;
};
};
return false;
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (Float) ~ Bool) ~ FloatVector {
filtered := FloatVector->New();
for(i : Int := 0; i < @size; i += 1;) {
if(f(@values[i])) {
filtered->AddBack(@values[i]);
};
};
return filtered;
}
#~
Applies the given function to each value in the vector
@param f function to apply
@return newly calculated vector
~#
method : public : Apply(f : (Float) ~ Float) ~ FloatVector {
array : Float[] := Float->New[@size];
Runtime->Copy(array, 0, @values, 0, @size);
for(i : Int := 0; i < @size; i += 1;) {
array[i] := f(array[i]);
};
return FloatVector->New(array);
}
#~
Reduces elements in the vector
@param f function to apply
@return reduced value
~#
method : public : Reduce(f : (Float, Float) ~ Float) ~ Float {
return Reduce(f, @size);
}
#~
Reduces elements in the vector
@param f function to apply
@param num number of elements to reduce
@return reduced value
~#
method : public : Reduce(f : (Float, Float) ~ Float, num : Int) ~ Float {
val := 0.0;
if(@size > 0 & @size <= num) {
val := @values[0];
for(i := 1; i < num; i++;) {
val := f(val, @values[i]);
};
};
return val;
}
method : public : ToString() ~ String {
buffer := "[";
for(i := 0; i < @size; i += 1;) {
buffer->Append(@values[i]);
if(i + 1 < @size) {
buffer->Append(',');
};
};
buffer->Append(']');
return buffer;
}
}
#~
Holds a growable array of comparable objects
~#
class CompareVector {
@values : Compare[];
@size : Int;
#~
Default constructor
~#
New() {
@values := Compare->New[8];
@size := 0;
}
#~
Copy constructor
@param values values to copy
~#
New(values : Compare[]) {
@values := Compare->New[values->Size() + values->Size() / 2];
@size := values->Size();
Runtime->Copy(@values, 0, values, 0, @size);
}
#~
Copy constructor
@param values values to copy
~#
New(values : CompareVector) {
@values := values->ToArray();
@size := values->Size();
}
method : native : Expand() ~ Nil {
if(@size >= @values->Size()) {
temp : Compare[] := Compare->New[@size * 2];
Runtime->Copy(temp, 0, @values, 0, @size);
@values := temp;
};
}
#~
Swap two values in the vector
@param a first value
@param b second value
@return true if values were swapped
~#
method : public : native : Swap(a : Int, b : Int) ~ Bool {
if(a < -1 | b < -1 | a > @size | b > @size) {
return false;
};
temp := @values[a];
@values[a] := @values[b];
@values[b] := temp;
return true;
}
#~
Adds a vector of values to the end of the vector
@param values values to append
~#
method : public : AddBack(values : CompareVector) ~ Nil {
max := values->Size() + @size;
if(max >= @values->Size()) {
temp : Compare[] := Compare->New[max + max / 2];
Runtime->Copy(temp, 0, @values, 0, @size);
@values := temp;
};
temp := values->ToArray();
Runtime->Copy(@values, @size, temp, 0, temp->Size());
@size := max;
}
#~
Adds a value to the end
@param value value to append
~#
method : public : AddBack(value : Compare) ~ Nil {
Expand();
@values[@size] := value;
@size := @size + 1;
}
#~
Removes the last value
@return value
~#
method : public : RemoveBack() ~ Compare {
if(@size > 0) {
@size -= 1;
return @values[@size];
};
return Nil;
}
#~
Removes an indexed value
@param i index
@return value
~#
method : public : Remove(i : Int) ~ Compare {
if(i > -1 & i < @size) {
temp := Compare->New[@values->Size()];
Runtime->Copy(temp, 0, @values, 0, i);
Runtime->Copy(temp, i, @values, i + 1, @size - i - 1);
value := @values[i];
@values := temp;
@size -= 1;
return value;
};
return Nil;
}
#~
Gets an indexed value
@param index index
@return value
~#
method : public : Get(index : Int) ~ Compare {
if(index > -1 & index < @size) {
return @values[index];
};
return Nil;
}
#~
Sets an indexed value
@param value value
@param index index
~#
method : public : Set(value : Compare, index : Int) ~ Bool {
if(index > -1 & index < @size) {
@values[index] := value;
return true;
};
return false;
}
#~
Clears the vector
~#
method : public : Empty() ~ Nil {
@values := Compare->New[8];
@size := 0;
}
#~
Size of vector
@return size of vector
~#
method : public : Size() ~ Int {
return @size;
}
#~
Checks to see if the vector is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @size = 0;
}
#~
Sorts the values in the vector
~#
method : public : native : Sort() ~ Nil {
a : Compare[] := @values;
b : Compare[] := Compare->New[@size];
MergeSort(0, @size - 1, a, b);
}
method : native : MergeSort(low : Int, hi : Int, a : Compare[], b : Compare[]) ~ Nil {
if(low < hi) {
mid := (low + hi) / 2;
MergeSort(low, mid, a, b);
MergeSort(mid + 1, hi, a, b);
Merge(low, mid, hi, a, b);
};
}
method : native : Merge(low : Int, mid : Int, hi : Int, a : Compare[], b : Compare[]) ~ Nil {
# copy both halves of a to auxiliary array b
for(i := low; i <= hi; i += 1;) {
b[i] := a[i];
};
i := low;
j := mid + 1;
k := low;
# copy back next-greatest element at each time
while(i <= mid & j <= hi) {
if(b[i]->Compare(b[j]) < 0 | b[i]->Compare(b[j]) = 0) {
a[k] := b[i];
k := k + 1;
i += 1;
}
else {
a[k] := b[j];
k := k + 1;
j := j + 1;
};
};
# copy back remaining elements of first half (if any)
while(i <= mid) {
a[k] := b[i];
k := k + 1;
i += 1;
};
}
#~
Finds a given value in the vector via linear search
@param value value to search for
@return index of found value, -1 if not found
~#
method : public : native : Find(value : Compare) ~ Int {
for(i := 0; i < @size; i += 1;) {
if(@values[i]->Compare(value) = 0) {
return i;
};
};
return -1;
}
#~
Performs a binary search O(log n)
@param value value to search for
@return index of found value, -1 if not found
~#
method : public : native : BinarySearch(value : Compare) ~ Int {
low := 0;
high := @size - 1;
while(low <= high) {
mid := (low + high) / 2;
if(@values[mid]->Compare(value) > 0) {
high := mid - 1;
}
else if(@values[mid]->Compare(value) < 0) {
low := mid + 1;
}
else {
return mid;
};
};
return -1;
}
#~
Check of the given value is in the vector
@param value value to check for
@return true if found, false otherwise
~#
method : public : Has(value : Compare) ~ Bool {
for(i : Int := 0; i < @size; i += 1;) {
if(@values[i]->Compare(value) = 0) {
return true;
};
};
return false;
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (Compare) ~ Bool) ~ CompareVector {
filtered := CompareVector->New();
for(i : Int := 0; i < @size; i += 1;) {
if(f(@values[i])) {
filtered->AddBack(@values[i]);
};
};
return filtered;
}
#~
Converts the vector into an object array
@return object array
~#
method : public : native : ToArray() ~ Compare[] {
array : Compare[] := Compare->New[@size];
Runtime->Copy(array, 0, @values, 0, @size);
return array;
}
}
#~
Holds a growable array of base objects
~#
class Vector {
@values : Base[];
@size : Int;
#~
Default constructor
~#
New() {
@values := Base->New[8];
@size := 0;
}
#~
Copy constructor
@param values values to copy
~#
New(values : Base[]) {
@values := Base->New[values->Size() + values->Size() / 2];
@size := values->Size();
Runtime->Copy(@values, 0, values, 0, @size);
}
#~
Copy constructor
@param values values to copy
~#
New(values : Vector) {
@values := values->ToArray();
@size := values->Size();
}
method : native : Expand() ~ Nil {
if(@size >= @values->Size()) {
temp : Base[] := Base->New[@size * 2];
Runtime->Copy(temp, 0, @values, 0, @size);
@values := temp;
};
}
#~
Removes an element from the vector
@param value value to remove
~#
method : public : Find(value : Base) ~ Int {
for(i := 0; i < @size; i+= 1;) {
if(@values[i] = value) {
return i;
};
};
return -1;
}
#~
Adds a vector of values to the end of the vector
@param values values to append
~#
method : public : AddBack(values : Vector) ~ Nil {
max := values->Size() + @size;
if(max >= @values->Size()) {
temp : Base[] := Base->New[max + max / 2];
Runtime->Copy(temp, 0, @values, 0, @size);
@values := temp;
};
temp := values->ToArray();
Runtime->Copy(@values, @size, temp, 0, temp->Size());
@size := max;
}
#~
Adds a value to the end
@param value value to append
~#
method : public : AddBack(value : Base) ~ Nil {
Expand();
@values[@size] := value;
@size := @size + 1;
}
#~
Removes the last value
@return value
~#
method : public : RemoveBack() ~ Base {
if(@size > 0) {
@size -= 1;
return @values[@size];
};
return Nil;
}
#~
Swap two values in the vector
@param a first value
@param b second value
@return true if values were swapped
~#
method : public : native : Swap(a : Int, b : Int) ~ Bool {
if(a < -1 | b < -1 | a > @size | b > @size) {
return false;
};
temp := @values[a];
@values[a] := @values[b];
@values[b] := temp;
return true;
}
#~
Removes an indexed value
@param i index
@return value
~#
method : public : Remove(i : Int) ~ Base {
if(i > -1 & i < @size) {
temp := Base->New[@values->Size()];
Runtime->Copy(temp, 0, @values, 0, i);
Runtime->Copy(temp, i, @values, i + 1, @size - i - 1);
value := @values[i];
@values := temp;
@size -= 1;
return value;
};
return Nil;
}
#~
Gets an indexed value
@param index index
@return value
~#
method : public : Get(index : Int) ~ Base {
if(index > -1 & index < @size) {
return @values[index];
};
return Nil;
}
#~
Sets an indexed value
@param value value
@param index index
~#
method : public : Set(value : Base, index : Int) ~ Bool {
if(index > -1 & index < @size) {
@values[index] := value;
return true;
};
return false;
}
#~
Size of vector
@return size of vector
~#
method : public : Size() ~ Int {
return @size;
}
#~
Checks to see if the vector is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @size = 0;
}
#~
Clears the vector
~#
method : public : Empty() ~ Nil {
@values := Base->New[8];
@size := 0;
}
#~
Converts the vector into an object array
@return objeck array
~#
method : public : native : ToArray() ~ Base[] {
array : Base[] := Base->New[@size];
Runtime->Copy(array, 0, @values, 0, @size);
return array;
}
}
#~
Growable integer based stack
~#
class IntStack {
@values : IntVector;
#~
Default constructor
~#
New() {
@values := IntVector->New();
}
#~
Pushes a value onto the stack
@value value to push
~#
method : public: native : Push(value : Int) ~ Nil {
@values->AddBack(value);
}
#~
Pushes a value from the stack
@return popped valued, 0 if stack is empty
~#
method : public: native : Pop() ~ Int {
if(@values->Size() > 0) {
value : Int := @values->Get(@values->Size() - 1);
@values->RemoveBack();
return value;
};
return 0;
}
#~
Check the top of the stack
@return value on the top of stack, 0 if stack is empty
~#
method : public: native : Top() ~ Int {
if(@values->Size() > 0) {
return @values->Get(@values->Size() - 1);
};
return 0;
}
#~
Clears the vector
~#
method : public : Empty() ~ Nil {
@values->Empty();
}
#~
Checks to see if the vector is empty
@return true if empty, false otherwise
~#
method : public: IsEmpty() ~ Bool {
return @values->Size() = 0;
}
#~
Size of stack
@return size of stack
~#
method : public: Size() ~ Int {
return @values->Size();
}
}
#~
Growable float based stack
~#
class FloatStack {
@values : FloatVector;
#~
Default constructor
~#
New() {
@values := FloatVector->New();
}
#~
Pushes a value onto the stack
@value value to push
~#
method : public : native : Push(value : Float) ~ Nil {
@values->AddBack(value);
}
#~
Pushes a value from the stack
@return popped valued, 0.0 if stack is empty
~#
method : public: native : Pop() ~ Float {
if(@values->Size() > 0) {
value : Float := @values->Get(@values->Size() - 1);
@values->RemoveBack();
return value;
};
return 0.0;
}
#~
Check the top of the stack
@return value on the top of stack, 0 if stack is empty
~#
method : public: native : Top() ~ Float {
if(@values->Size() > 0) {
return @values->Get(@values->Size() - 1);
};
return 0.0;
}
#~
Size of stack
@return size of stack
~#
method : public: Size() ~ Int {
return @values->Size();
}
#~
Clears the vector
~#
method : public : Empty() ~ Nil {
@values->Empty();
}
#~
Checks to see if the vector is empty
@return true if empty, false otherwise
~#
method : public: IsEmpty() ~ Bool {
return @values->Size() = 0;
}
}
#~
Growable object based stack
~#
class Stack {
@values : Vector;
#~
Default constructor
~#
New() {
@values := Vector->New();
}
#~
Pushes a value onto the stack
@value value to push
~#
method : public: native : Push(value : Base) ~ Nil {
@values->AddBack(value);
}
#~
Pushes a value from the stack
@return popped valued, Nil if stack is empty
~#
method : public : native : Pop() ~ Base {
if(@values->Size() > 0) {
value : Base := @values->Get(@values->Size() - 1);
@values->RemoveBack();
return value;
};
return Nil;
}
#~
Check the top of the stack
@return value on the top of stack, Nil if stack is empty
~#
method : public: native : Top() ~ Base {
if(@values->Size() > 0) {
return @values->Get(@values->Size() - 1);
};
return Nil;
}
#~
Clears the vector
~#
method : public : Empty() ~ Nil {
@values->Empty();
}
#~
Checks to see if the vector is empty
@return true if empty, false otherwise
~#
method : public: IsEmpty() ~ Bool {
return @values->Size() = 0;
}
#~
Size of stack
@return size of stack
~#
method : public: Size() ~ Int {
return @values->Size();
}
}
#~
Stores a linked list of integer values
~#
class IntList {
@list : CompareList;
#~
Default constructor
~#
New() {
@list := CompareList->New();
}
#~
Adds a value to the end
@param value value to append
~#
method : public : AddBack(value : Int) ~ Nil {
@list->AddBack(IntHolder->New(value));
}
#~
Adds a value to the front
@param value value to prepend
~#
method : public : AddFront(value : Int) ~ Nil {
@list->AddFront(IntHolder->New(value));
}
#~
Gets the value that's currently pointed to
@return value value
~#
method : public : Get() ~ Int {
return @list->Get()->As(IntHolder)->Get();
}
#~
Finds a value in the list and sets the pointer
@param value value to search for
@return true if found, false otherwise
~#
method : public : Find(value : Int) ~ Bool {
return @list->Find(IntHolder->New(value)) <> Nil;
}
#~
Inserts a value into the list based upon the pointer location
@param value value to insert
~#
method : public : Insert(value : Int) ~ Nil {
@list->Insert(IntHolder->New(value));
}
#~
Removes the last value from the list
~#
method : public : RemoveBack() ~ Nil {
@list->RemoveBack();
}
#~
Removes the first value from the list
~#
method : public : RemoveFront() ~ Nil {
@list->RemoveFront();
}
#~
Moves the pointer to the start of the list
~#
method : public : Rewind() ~ Nil {
@list->Rewind();
}
#~
Moves the pointer to the end of the list
~#
method : public : Forward() ~ Nil {
@list->Forward();
}
#~
Advances the pointer
~#
method : public : Next() ~ Nil {
@list->Next();
}
#~
Retreats the pointer
~#
method : public : Previous() ~ Nil {
@list->Previous();
}
#~
Removes the element at the pointer position
~#
method : public : Remove() ~ Nil {
@list->Remove();
}
#~
Checks to see if the pointer is at the front of the list
@return true if pointer is at the front of the list, false otherwise
~#
method : public : IsFront() ~ Bool {
return @list->IsFront();
}
#~
Checks to see if the pointer is at the end of the list
@return true if pointer is at the end of the list, false otherwise
~#
method : public : IsBack() ~ Bool {
return @list->IsBack();
}
#~
Checks to see the pointer can be advanced
@return true if pointer can be advanced, false otherwise
~#
method : public : More() ~ Bool {
return @list->More();
}
#~
Returns the first element in the list
@return first element in the list, 0 if the list is empty
~#
method : public : Front() ~ Int {
holder := @list->Front()->As(IntHolder);
if(holder <> Nil) {
return holder->Get();
};
return 0;
}
#~
Returns the last element in the list
@return last element in the list, 0 if the list is empty
~#
method : public : Back() ~ Int {
holder := @list->Back()->As(IntHolder);
if(holder <> Nil) {
return holder->Get();
};
return 0;
}
#~
Clears the list
~#
method : public : Empty() ~ Nil {
@list->Empty();
}
#~
Checks to see if the list is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @list->IsEmpty();
}
#~
Size of list
@return size of list
~#
method : public : Size() ~ Int {
return @list->Size();
}
}
#~
Holds a growable array of float values
~#
class FloatList {
@list : CompareList;
#~
Default constructor
~#
New() {
@list := CompareList->New();
}
#~
Adds a value to the end
@param value value to append
~#
method : public : AddBack(value : Float) ~ Nil {
@list->AddBack(FloatHolder->New(value));
}
#~
Adds a value to the front
@param value value to prepend
~#
method : public : AddFront(value : Float) ~ Nil {
@list->AddFront(FloatHolder->New(value));
}
#~
Gets the value that's currently pointed to
@return value value
~#
method : public : Get() ~ Float {
return @list->Get()->As(FloatHolder)->Get();
}
#~
Searches for a value
@param value value to check for
@return true if value is found, false otherwise
~#
method : public : Has(value : Float) ~ Bool {
return @list->Has(FloatHolder->New(value));
}
#~
Finds a value in the list and sets the pointer
@param value value to search for
@return value that's found
~#
method : public : Find(value : Float) ~ Float {
found := @list->Find(FloatHolder->New(value))->As(FloatHolder);
if(found <> Nil) {
return found->Get();
}
else {
return 0.0;
};
}
#~
Inserts a value into the list based upon the pointer location
@param value value to insert
~#
method : public : Insert(value : Float) ~ Nil {
@list->Insert(FloatHolder->New(value));
}
#~
Removes the last value from the list
~#
method : public : RemoveBack() ~ Nil {
@list->RemoveBack();
}
#~
Removes the first value from the list
~#
method : public : RemoveFront() ~ Nil {
@list->RemoveFront();
}
#~
Moves the pointer to the start of the list
~#
method : public : Rewind() ~ Nil {
@list->Rewind();
}
#~
Moves the pointer to the end of the list
~#
method : public : Forward() ~ Nil {
@list->Forward();
}
#~
Advances the pointer
~#
method : public : Next() ~ Nil {
@list->Next();
}
#~
Retreats the pointer
~#
method : public : Previous() ~ Nil {
@list->Previous();
}
#~
Removes the element at the pointer position
~#
method : public : Remove() ~ Nil {
@list->Remove();
}
#~
Checks to see if the pointer is at the front of the list
@return true if pointer is at the front of the list, false otherwise
~#
method : public : IsFront() ~ Bool {
return @list->IsFront();
}
#~
Checks to see if the pointer is at the end of the list
@return true if pointer is at the end of the list, false otherwise
~#
method : public : IsBack() ~ Bool {
return @list->IsBack();
}
#~
Checks to see the pointer can be advanced
@return true if pointer can be advanced, false otherwise
~#
method : public : More() ~ Bool {
return @list->More();
}
#~
Returns the first element in the list
@return first element in the list, 0.0 if the list is empty
~#
method : public : Front() ~ Int {
holder := @list->Front()->As(FloatHolder);
if(holder <> Nil) {
return holder->Get();
};
return 0.0;
}
#~
Returns the last element in the list
@return last element in the list, 0.0 if the list is empty
~#
method : public : Back() ~ Int {
holder := @list->Back()->As(FloatHolder);
if(holder <> Nil) {
return holder->Get();
};
return 0.0;
}
#~
Clears the list
~#
method : public : Empty() ~ Nil {
@list->Empty();
}
#~
Checks to see if the list is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @list->IsEmpty();
}
#~
Size of list
@return size of list
~#
method : public : Size() ~ Int {
return @list->Size();
}
}
#~
Stores a linked list of object values
~#
class List {
@size : Int;
@head : ListNode;
@tail : ListNode;
@cursor : ListNode;
#~
Default constructor
~#
New() {
@size := 0;
}
#~
Adds a value to the end
@param value value to append
~#
method : public : native : AddBack(value : Base) ~ Nil {
node := ListNode->New(value);
if(@head = Nil) {
@head := node;
@tail := @head;
@cursor := @head;
}
else {
@tail->SetNext(node);
node->SetPrevious(@tail);
@tail := node;
};
@size += 1;
}
#~
Removes the last value from the list
~#
method : public : RemoveBack() ~ Nil {
Forward();
Remove();
}
#~
Adds a value to the front
@param value value to prepend
~#
method : public : native : AddFront(value : Base) ~ Nil {
node := ListNode->New(value);
if(@head = Nil) {
@head := node;
@tail := @head;
@cursor := @head;
}
else {
@head->SetPrevious(node);
node->SetNext(@head);
@head := node;
@cursor := @head;
};
@size += 1;
}
#~
Removes the first value from the list
~#
method : public : RemoveFront() ~ Nil {
Rewind();
Remove();
}
#~
Moves the pointer to the start of the list
~#
method : public : Rewind() ~ Nil {
@cursor := @head;
}
#~
Moves the pointer to the end of the list
~#
method : public : Forward() ~ Nil {
@cursor := @tail;
}
#~
Advances the pointer
~#
method : public : Next() ~ Nil {
if(@cursor <> Nil) {
@cursor := @cursor->GetNext();
};
}
#~
Retreats the pointer
~#
method : public : Previous() ~ Nil {
if(@cursor <> Nil) {
@cursor := @cursor->GetPrevious();
};
}
#~
Gets the value that's currently pointed to
@return value value
~#
method : public : Get() ~ Base {
if(@cursor <> Nil) {
return @cursor->Get();
};
return Nil;
}
#~
Inserts a value into the list based upon the pointer location
@param value value to insert
~#
method : public : native : Insert(value : Base) ~ Bool {
if(@cursor <> Nil & @head <> Nil & @tail <> Nil) {
node := ListNode->New(value);
if(@cursor = @head & @cursor = @tail) {
@head->SetNext(node);
node->SetPrevious(@head);
@tail := node;
}
else if(@cursor = @tail) {
@tail->SetNext(node);
node->SetPrevious(@tail);
@tail := node;
}
else {
@cursor->GetNext()->SetPrevious(node);
node->SetNext(@cursor->GetNext());
@cursor->SetNext(node);
node->SetPrevious(@cursor);
};
@size += 1;
return true;
}
else if(@head = Nil & @tail = Nil) {
AddBack(value);
return true;
};
return false;
}
#~
Removes the element at the pointer position
~#
method : public : native : Remove() ~ Nil {
if(@cursor <> Nil) {
if(@cursor->GetPrevious() <> Nil) {
@cursor->GetPrevious()->SetNext(@cursor->GetNext());
};
if(@cursor = @head & @cursor = @tail) {
@cursor := @cursor->GetNext();
@head := @cursor;
@tail := @cursor;
}
else if(@cursor = @head) {
@cursor := @cursor->GetNext();
@head := @cursor;
}
else if(@cursor = @tail) {
@cursor := @cursor->GetNext();
@tail := @cursor;
}
else {
@cursor := @cursor->GetNext();
};
@size -= 1;
};
}
#~
Checks to see if the pointer is at the front of the list
@return true if pointer is at the front of the list, false otherwise
~#
method : public : IsFront() ~ Bool {
return @cursor = @head;
}
#~
Checks to see if the pointer is at the end of the list
@return true if pointer is at the end of the list, false otherwise
~#
method : public : IsBack() ~ Bool {
return @cursor = @tail;
}
#~
Checks to see the pointer can be advanced
@return true if pointer can be advanced, false otherwise
~#
method : public : More() ~ Bool {
return @cursor <> Nil;
}
#~
Returns the first element in the list
@return first element in the list, 0.0 if the list is empty
~#
method : public : Front() ~ Base {
if(@head <> Nil) {
return @head->Get();
};
return Nil;
}
#~
Returns the last element in the list
@return last element in the list, 0.0 if the list is empty
~#
method : public : Back() ~ Base {
if(@tail <> Nil) {
return @tail->Get();
};
return Nil;
}
#~
Clears the list
~#
method : public : Empty() ~ Nil {
@size := 0;
@head := Nil;
@tail := Nil;
@cursor := Nil;
}
#~
Checks to see if the list is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @size = 0;
}
#~
Size of list
@return size of list
~#
method : public : Size() ~ Int {
return @size;
}
}
#~
Stores a linked list of comparable values
~#
class CompareList {
@size : Int;
@head : ListNode;
@tail : ListNode;
@cursor : ListNode;
#~
Default constructor
~#
New() {
@size := 0;
}
#~
Adds a value to the end
@param value value to append
~#
method : public : native : AddBack(value : Compare) ~ Nil {
node := ListNode->New(value);
if(@head = Nil) {
@head := node;
@tail := @head;
@cursor := @head;
}
else {
@tail->SetNext(node);
node->SetPrevious(@tail);
@tail := node;
};
@size += 1;
}
#~
Removes the last value from the list
~#
method : public : RemoveBack() ~ Nil {
Forward();
Remove();
}
#~
Adds a value to the front
@param value value to prepend
~#
method : public : native : AddFront(value : Compare) ~ Nil {
node := ListNode->New(value);
if(@head = Nil) {
@head := node;
@tail := @head;
@cursor := @head;
}
else {
@head->SetPrevious(node);
node->SetNext(@head);
@head := node;
@cursor := @head;
};
@size += 1;
}
#~
Removes the first value from the list
~#
method : public : RemoveFront() ~ Nil {
Rewind();
Remove();
}
#~
Moves the pointer to the start of the list
~#
method : public : Rewind() ~ Nil {
@cursor := @head;
}
#~
Moves the pointer to the end of the list
~#
method : public : Forward() ~ Nil {
@cursor := @tail;
}
#~
Advances the pointer
~#
method : public : Next() ~ Nil {
if(@cursor <> Nil) {
@cursor := @cursor->GetNext();
};
}
#~
Retreats the pointer
~#
method : public : Previous() ~ Nil {
if(@cursor <> Nil) {
@cursor := @cursor->GetPrevious();
};
}
#~
Gets the value that's currently pointed to
@return value value
~#
method : public : Get() ~ Compare {
if(@cursor <> Nil) {
return @cursor->Get();
};
return Nil;
}
#~
Searches for a value
@param value value to check for
@return true if value is found, false otherwise
~#
method : public : Has(value : Compare) ~ Bool {
start := @head;
end := @tail;
while(start <> end) {
if(value->Compare(start->Get()->As(Compare)) = 0) {
return true;
}
else if(value->Compare(end->Get()->As(Compare)) = 0) {
return true;
};
start := start->GetNext();
end := end->GetPrevious();
};
if(start <> Nil & value->Compare(start->Get()->As(Compare)) = 0) {
return true;
};
return false;
}
#~
Finds a value in the list and sets the pointer
@param value value to search for
@return value that's found
~#
method : public : Find(value : Compare) ~ Compare {
@cursor := @head;
while(@cursor <> Nil) {
if(value->Compare(@cursor->Get()->As(Compare)) = 0) {
return value;
};
@cursor := @cursor->GetNext();
};
return Nil;
}
#~
Inserts a value into the list based upon the pointer location
@param value value to insert
~#
method : public : native : Insert(value : Compare) ~ Bool {
if(@cursor <> Nil & @head <> Nil & @tail <> Nil) {
node := ListNode->New(value);
if(@cursor = @head & @cursor = @tail) {
@head->SetNext(node);
node->SetPrevious(@head);
@tail := node;
}
else if(@cursor = @tail) {
@tail->SetNext(node);
node->SetPrevious(@tail);
@tail := node;
}
else {
@cursor->GetNext()->SetPrevious(node);
node->SetNext(@cursor->GetNext());
@cursor->SetNext(node);
node->SetPrevious(@cursor);
};
@size += 1;
return true;
}
else if(@head = Nil & @tail = Nil) {
AddBack(value);
return true;
};
return false;
}
#~
Removes the element at the pointer position
~#
method : public : native : Remove() ~ Nil {
if(@cursor <> Nil) {
if(@cursor->GetPrevious() <> Nil) {
@cursor->GetPrevious()->SetNext(@cursor->GetNext());
};
if(@cursor = @head & @cursor = @tail) {
@cursor := @cursor->GetNext();
@head := @cursor;
@tail := @cursor;
}
else if(@cursor = @head) {
@cursor := @cursor->GetNext();
@head := @cursor;
}
else if(@cursor = @tail) {
@cursor := @cursor->GetNext();
@tail := @cursor;
}
else {
@cursor := @cursor->GetNext();
};
@size -= 1;
};
}
#~
Checks to see if the pointer is at the front of the list
@return true if pointer is at the front of the list, false otherwise
~#
method : public : IsFront() ~ Bool {
return @cursor = @head;
}
#~
Checks to see if the pointer is at the end of the list
@return true if pointer is at the end of the list, false otherwise
~#
method : public : IsBack() ~ Bool {
return @cursor = @tail;
}
#~
Checks to see the pointer can be advanced
@return true if pointer can be advanced, false otherwise
~#
method : public : More() ~ Bool {
return @cursor <> Nil;
}
#~
Returns the first element in the list
@return first element in the list, 0.0 if the list is empty
~#
method : public : Front() ~ Compare {
if(@head <> Nil) {
return @head->Get();
};
return Nil;
}
#~
Returns the last element in the list
@return last element in the list, 0.0 if the list is empty
~#
method : public : Back() ~ Compare {
if(@tail <> Nil) {
return @tail->Get();
};
return Nil;
}
#~
Clears the list
~#
method : public : Empty() ~ Nil {
@size := 0;
@head := Nil;
@tail := Nil;
@cursor := Nil;
}
#~
Checks to see if the list is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @size = 0;
}
#~
Size of list
@return size of list
~#
method : public : Size() ~ Int {
return @size;
}
}
class ListNode {
@value : Base;
@next : ListNode;
@previous: ListNode;
New(value : Base) {
@value := value;
}
method : public : Set(value : Base) ~ Nil {
@value := value;
}
method : public : Get() ~ Base {
return @value;
}
method : public : SetNext(next : Collection.ListNode) ~ Nil {
@next := next;
}
method : public : GetNext() ~ ListNode {
return @next;
}
method : public : SetPrevious(previous : Collection.ListNode) ~ Nil {
@previous := previous;
}
method : public : GetPrevious() ~ ListNode {
return @previous;
}
}
#~
Queue of float values
~#
class FloatQueue {
@queue : FloatList;
#~
Default constructor
~#
New() {
@queue := FloatList->New();
}
#~
Adds a value to the back of the queue
@param value value to add
~#
method : public: native : Add(value : Float) ~ Nil {
@queue->AddBack(value);
}
#~
Removes a value from the front of the queue
@return value removed
~#
method : public : native : Remove() ~ Float {
if(@queue->Size() > 0) {
value := @queue->Front();
@queue->RemoveFront();
return value;
};
return 0.0;
}
#~
Get the value from the head of the queue
@return head value, 0.0 if queue is empty
~#
method : public: native : Head() ~ Float {
if(@queue->Size() > 0) {
return @queue->Front();
};
return 0.0;
}
#~
Clears the queue
~#
method : public : Empty() ~ Nil {
@queue->Empty();
}
#~
Checks to see if the queue is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @queue->IsEmpty();
}
#~
Size of queue
@return size of queue
~#
method : public : Size() ~ Int {
return @queue->Size();
}
}
#~
Queue of integer values
~#
class IntQueue {
@queue : IntList;
#~
Default constructor
~#
New() {
@queue := IntList->New();
}
#~
Adds a value to the back of the queue
@param value value to add
~#
method : public: native : Add(value : Int) ~ Nil {
@queue->AddBack(value);
}
#~
Removes a value from the front of the queue
@return value removed
~#
method : public : native : Remove() ~ Int {
if(@queue->Size() > 0) {
value := @queue->Front();
@queue->RemoveFront();
return value;
};
return 0;
}
#~
Get the value from the head of the queue
@return head value, 0 if queue is empty
~#
method : public: native : Head() ~ Int {
if(@queue->Size() > 0) {
return @queue->Front();
};
return 0;
}
#~
Clears the queue
~#
method : public : Empty() ~ Nil {
@queue->Empty();
}
#~
Checks to see if the queue is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @queue->IsEmpty();
}
#~
Size of queue
@return size of queue
~#
method : public : Size() ~ Int {
return @queue->Size();
}
}
#~
Queue of objects
~#
class Queue {
@queue : CompareList;
#~
Default constructor
~#
New() {
@queue := CompareList->New();
}
#~
Adds a value to the back of the queue
@param value value to add
~#
method : public: native : Add(value : Compare) ~ Nil {
@queue->AddBack(value);
}
#~
Removes a value from the front of the queue
@return value removed
~#
method : public : native : Remove() ~ Compare {
if(@queue->Size() > 0) {
value := @queue->Front();
@queue->RemoveFront();
return value;
};
return Nil;
}
#~
Get the value from the head of the queue
@return head value, Nil if queue is empty
~#
method : public: native : Head() ~ Compare {
if(@queue->Size() > 0) {
return @queue->Front();
};
return Nil;
}
#~
Clears the queue
~#
method : public : Empty() ~ Nil {
@queue->Empty();
}
#~
Checks to see if the queue is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @queue->IsEmpty();
}
#~
Size of queue
@return size of queue
~#
method : public : Size() ~ Int {
return @queue->Size();
}
}
#~
Binary tree of integer values
~#
class IntMap {
@map : Map;
#~
Default constructor
~#
New() {
@map := Map->New();
}
#~
Inserts a value into the map
@param key key
@param value value
~#
method : public : Insert(key : Int, value : Base) ~ Nil {
@map->Insert(IntHolder->New(key), value);
}
#~
Removes a value from the map
@param key key for value to remove
@return true if removed, false otherwise
~#
method : public : Remove(key : Int) ~ Bool {
return @map->Remove(IntHolder->New(key));
}
#~
Searches for a value in a map
@param key search key
@return found value, 0 if not found
~#
method : public : Find(key : Int) ~ Base {
return @map->Find(IntHolder->New(key));
}
#~
Checks for a value in a map
@param key search key
@return true if found, false otherwise
~#
method : public : Has(key : Int) ~ Bool {
result : IntHolder := @map->Find(IntHolder->New(key))->As(IntHolder);
return result <> Nil;
}
#~
Get a collection of keys
@return vector of keys
~#
method : public : native : GetKeys() ~ IntVector {
keys := IntVector->New();
holder_keys := @map->GetKeys();
for(i := 0; i < holder_keys->Size(); i += 1;) {
holder_value : IntHolder := holder_keys->Get(i)->As(IntHolder);
keys->AddBack(holder_value->Get());
};
return keys;
}
#~
Gets a collection of values
@return vector of values
~#
method : public : GetValues() ~ Vector {
return @map->GetValues();
}
#~
Clears the map
~#
method : public : Empty() ~ Nil {
@map->Empty();
}
#~
Checks to see if the map is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @map->IsEmpty();
}
#~
Size of map
@return size of queue
~#
method : public : Size() ~ Int {
return @map->Size();
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (Int) ~ Bool) ~ IntMap {
filtered := IntMap->New();
keys := GetKeys();
each(i : keys) {
key := keys->Get(i);
if(f(key)) {
value := Find(key);
filtered->Insert(key, value);
};
};
return filtered;
}
#~
Gets the backing Compare map
@return backing Compare map
~#
method : public : GetMap() ~ Map {
return @map;
}
}
#~
Binary tree of float values
~#
class FloatMap {
@map : Map;
#~
Default constructor
~#
New() {
@map := Map->New();
}
#~
Inserts a value into the map
@param key key
@param value value
~#
method : public : Insert(key : Float, value : Base) ~ Nil {
@map->Insert(FloatHolder->New(key), value);
}
#~
Removes a value from the map
@param key key for value to remove
@return true if removed, false otherwise
~#
method : public : Remove(key : Float) ~ Bool {
return @map->Remove(FloatHolder->New(key));
}
#~
Searches for a value in a map
@param key search key
@return found value, Nil otherwise
~#
method : public : Find(key : Float) ~ Base {
return @map->Find(FloatHolder->New(key));
}
#~
Check of the given pair is in the map
@param key search key
@return true if found
~#
method : public : Has(key : Float) ~ Bool {
result : FloatHolder := @map->Find(FloatHolder->New(key))->As(FloatHolder);
return result <> Nil;
}
#~
Get a collection of keys
@return vector of keys
~#
method : public: native : GetKeys() ~ FloatVector {
keys := FloatVector->New();
holder_keys := @map->GetKeys();
for(i := 0; i < holder_keys->Size(); i += 1;) {
holder_value : FloatHolder := holder_keys->Get(i)->As(FloatHolder);
keys->AddBack(holder_value->Get());
};
return keys;
}
#~
Gets a collection of values
@return vector of values
~#
method : public : GetValues() ~ Vector {
return @map->GetValues();
}
#~
Clears the map
~#
method : public : Empty() ~ Nil {
@map->Empty();
}
#~
Checks to see if the map is empty
@return true if empty, false otherwise
~#
method : public : IsEmpty() ~ Bool {
return @map->IsEmpty();
}
#~
Size of queue
@return size of map
~#
method : public : Size() ~ Int {
return @map->Size();
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (Float) ~ Bool) ~ FloatMap {
filtered := FloatMap->New();
keys := GetKeys();
each(i : keys) {
key := keys->Get(i);
if(f(key)) {
value := Find(key);
filtered->Insert(key, value);
};
};
return filtered;
}
#~
Gets the backing Compare map
@return backing Compare map
~#
method : public : GetMap() ~ Map {
return @map;
}
}
class TreeNode {
@key : Compare;
@value : Base;
@left : TreeNode;
@right : TreeNode;
@level : Int;
New(key : Compare, value : Base, level : Int) {
@key := key;
@value := value;
@level := level;
@left := Nil;
@right := Nil;
}
method : public : SetKey(key : Compare) ~ Nil {
@key := key;
}
method : public : GetKey() ~ Compare {
return @key;
}
method : public : Get() ~ Base {
return @value;
}
method : public : GetLevel() ~ Int {
return @level;
}
method : public : SetLevel(level : Int) ~ Nil {
@level := level;
}
method : public : GetLeft() ~ TreeNode {
return @left;
}
method : public : SetLeft(left : TreeNode) ~ Nil {
@left := left;
}
method : public : GetRight() ~ TreeNode {
return @right;
}
method : public : SetRight(right : TreeNode) ~ Nil {
@right := right;
}
}
class Pair {
@key : Compare;
@value : Base;
New(key : Compare, value : Base) {
@key := key;
@value := value;
}
method : public : GetKey() ~ Compare {
return @key;
}
method : public : Get() ~ Base {
return @value;
}
}
#~
Binary tree of string values
~#
class StringMap {
@map : Map;
#~
Default constructor
~#
New() {
@map := Map->New();
}
#~
Inserts a value into the map
@param key key
@param value value
~#
method : public : Insert(key : String, value : Base) ~ Nil {
@map->Insert(key, value);
}
#~
Removes a value from the map
@param key key for value to remove
@return true if removed, false otherwise
~#
method : public : Remove(key : String) ~ Bool {
return @map->Remove(key);
}
#~
Searches for a value in a map
@param key search key
@return found value, Nil if not found
~#
method : public : Find(key : String) ~ Base {
return @map->Find(key);
}
#~
Checks for a value in a map
@param key search key
@return true if found, false otherwise
~#
method : public : Has(key : String) ~ Bool {
result := @map->Find(key);
return result <> Nil;
}
#~
Get a collection of keys
@return vector of keys
~#
method : public : GetKeys() ~ CompareVector {
return @map->GetKeys();
}
#~
Gets a collection of values
@return vector of values
~#
method : public : GetValues() ~ Vector {
return @map->GetValues();
}
#~
Clears the map
~#
method : public : native : Empty() ~ Nil {
@map->Empty();
}
#~
Checks to see if the map is empty
@return true if empty, false otherwise
~#
method : public : native : IsEmpty() ~ Bool {
return @map->IsEmpty();
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (String) ~ Bool) ~ StringMap {
filtered := StringMap->New();
keys := GetKeys();
each(i : keys) {
key := keys->Get(i)->As(String);
if(f(key)) {
value := Find(key);
filtered->Insert(key, value);
};
};
return filtered;
}
#~
Size of map
@return size of queue
~#
method : public : native : Size() ~ Int {
return @map->Size();
}
}
#~
Binary tree of objects values
~#
class Map {
@root : TreeNode;
@last : TreeNode;
@Removed : TreeNode;
@size : Int;
@found : Bool;
#~
Default constructor
~#
New() {
@root := Nil;
@size := 0;
}
method : native : Skew(node : Collection.TreeNode) ~ TreeNode {
if(node = Nil | node->GetLeft() = Nil) {
return node;
};
if(node->GetLeft()->GetLevel() = node->GetLevel()) {
left : TreeNode := node->GetLeft();
node->SetLeft(left->GetRight());
left->SetRight(node);
return left;
};
return node;
}
#~
Size of queue
@return size of queue
~#
method : public : native : Size() ~ Int {
return @size;
}
#~
Checks to see if the queue is empty
@return true if empty, false otherwise
~#
method : public : native : IsEmpty() ~ Bool {
return @size = 0;
}
#~
Clears the queue
~#
method : public : native : Empty() ~ Nil {
@root := Nil;
@last := Nil;
@Removed := Nil;
@size := 0;
@found := false;
}
method : native : Split(node : Collection.TreeNode) ~ TreeNode {
if(node = Nil | node->GetRight() = Nil |
node->GetRight()->GetRight() = Nil) {
return node;
};
if(node->GetRight()->GetRight()->GetLevel() = node->GetLevel()) {
right : TreeNode := node->GetRight();
node->SetRight(right->GetLeft());
right->SetLeft(node);
right->SetLevel(right->GetLevel() + 1);
return right;
};
return node;
}
#~
Searches for a value in a map
@param key search key
@return found value, Nil if not found
~#
method : public : Find(key : Compare) ~ Base {
return Find(key, @root);
}
#~
Checks for a value in a map
@param key search key
@return true if found, false otherwise
~#
method : public : Has(key : Compare) ~ Bool {
return Find(key, @root) <> Nil;
}
method : Find(key : Compare, node : Collection.TreeNode) ~ Base {
if(node <> Nil) {
if(key->Compare(node->GetKey()) < 0) {
return Find(key, node->GetLeft());
}
else if(key->Compare(node->GetKey()) > 0) {
return Find(key, node->GetRight());
}
else {
return node->Get();
};
};
return Nil;
}
#~
Get a collection of keys
@return vector of keys
~#
method : public : GetKeys() ~ Collection.CompareVector {
vector := CompareVector->New();
GetKeys(@root, vector);
return vector;
}
method : native : GetKeys(node : Collection.TreeNode, vector : Collection.CompareVector) ~ Nil {
if(node <> Nil) {
# process left
GetKeys(node->GetLeft(), vector);
key : Compare := node->GetKey();
vector->AddBack(key);
# process right
GetKeys(node->GetRight(), vector);
};
}
#~
Gets a collection of values
@return vector of values
~#
method : public : GetValues() ~ Collection.Vector {
vector := Vector->New();
GetValues(@root, vector);
return vector;
}
method : native : GetValues(node : Collection.TreeNode, vector : Collection.Vector) ~ Nil {
if(node <> Nil) {
# process left
GetValues(node->GetLeft(), vector);
value : Base := node->Get();
vector->AddBack(value);
# process right
GetValues(node->GetRight(), vector);
};
}
#~
Inserts a value into the map
@param key key
@param value value
~#
method : public : native : Insert(key : Compare, value : Base) ~ Nil {
if(@root = Nil) {
@root := Insert(key, value, Nil->As( Collection.TreeNode));
}
else {
@root := Insert(key, value, @root);
};
}
method : native : Insert(key : Compare, value : Base, node : Collection.TreeNode) ~ Collection.TreeNode {
if(node = Nil) {
node := TreeNode->New(key, value, 1);
@size := @size + 1;
}
else {
if(key->Compare(node->GetKey()) < 0) {
node->SetLeft(Insert(key, value, node->GetLeft()));
}
else if(key->Compare(node->GetKey()) > 0) {
node->SetRight(Insert(key, value, node->GetRight()));
}
else {
return node;
};
node := Skew(node);
node := Split(node);
};
return node;
}
#~
Removes a value from the map
@param key key for value to remove
~#
method : public : Remove(key : Compare) ~ Bool {
@found := true;
@root := Remove(key, @root);
if(@found) {
@size := @size - 1;
return true;
};
return false;
}
method : native : Remove(key : Compare, node : Collection.TreeNode) ~ Collection.TreeNode {
if(node = Nil) {
@found := false;
return Nil;
};
if(key->Compare(node->GetKey()) < 0) {
node->SetLeft(Remove(key, node->GetLeft()));
}
else if(key->Compare(node->GetKey()) > 0) {
node->SetRight(Remove(key, node->GetRight()));
}
else {
if(node->GetLeft() = Nil & node->GetRight() = Nil) {
return Nil;
}
else if(node->GetLeft() = Nil) {
left : Compare := Successor(node);
node->SetRight(Remove(left, node->GetRight()));
node->SetKey(left);
}
else {
left : Compare := Predecessor(node);
node->SetLeft(Remove(left, node->GetLeft()));
node->SetKey(left);
};
};
# rebalanced
node := DecreaseLevel(node);
node := Skew(node);
node->SetRight(Skew(node->GetRight()));
if(node->GetRight() <> Nil & node->GetRight()->GetRight() <> Nil) {
node->GetRight()->SetRight(Skew(node->GetRight()->GetRight()));
};
node := Split(node);
node->SetRight(Split(node->GetRight()));
return node;
}
method : native : Predecessor(node : Collection.TreeNode) ~ Compare {
if(node->GetLeft() <> Nil) {
left : TreeNode := node->GetLeft();
while(left->GetLeft() <> Nil) {
left := left->GetLeft();
};
return left->GetKey();
};
return node->GetKey();
}
method : native : Successor(node : Collection.TreeNode) ~ Compare {
if(node->GetRight() <> Nil) {
right : TreeNode := node->GetRight();
while(right->GetRight() <> Nil) {
right := right->GetRight();
};
return right->GetKey();
};
return node->GetKey();
}
method : native : DecreaseLevel(node : Collection.TreeNode) ~ TreeNode {
if(node->GetLeft() <> Nil & node->GetRight() <> Nil) {
left : Int := node->GetLeft()->GetLevel();
right : Int := node->GetRight()->GetLevel();
value : Int := Int->Min(left, right);
if(value < node->GetLevel()) {
node->SetLevel(value);
if(value < node->GetRight()->GetLevel()) {
node->GetRight()->SetLevel(value);
};
};
};
return node;
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (Compare) ~ Bool) ~ Map {
filtered := Map->New();
keys := GetKeys();
each(i : keys) {
key := keys->Get(i)->As(Compare);
if(f(key)) {
value := Find(key);
filtered->Insert(key, value);
};
};
return filtered;
}
}
#~
Binary tree that holds multiple values with the same key
~#
class MultiMap {
@map : Map;
#~
Default constructor
~#
New() {
@map := Map->New();
}
#~
Inserts a value into the map
@param key key
@param value value
~#
method : public : Insert(key : Compare, value : Base) ~ Nil {
values := Find(key);
if(values = Nil) {
values := Vector->New();
@map->Insert(key, values);
};
values->AddBack(value);
}
#~
Checks for a value in a map
@param key search key
@return true if found, false otherwise
~#
method : public : Find(key : Compare) ~ Vector {
return @map->Find(key)->As(Vector);
}
#~
Get a collection of keys
@return vector of keys
~#
method : public : GetKeys() ~ CompareVector {
return @map->GetKeys();
}
#~
Gets a collection of values
@return vector of values
~#
method : public : GetValues() ~ CompareVector {
values := CompareVector->New();
keys := @map->GetKeys();
keys->Sort();
each(i : keys) {
key := keys->Get(i)->As(Compare);
local_values := @map->Find(key)->As(CompareVector);
each(j : local_values) {
values->AddBack(local_values->Get(j));
};
};
return values;
}
#~
Checks to see if the queue is empty
@return true if empty, false otherwise
~#
method : public : native : IsEmpty() ~ Bool {
return @map->Size() = 0;
}
#~
Clears the set
~#
method : public : Empty() ~ Nil {
@map->Empty();
}
#~
Checks for a value in a map
@param key search key
@return true if found, false otherwise
~#
method : public : Has(key : Compare) ~ Bool {
return Find(key) <> Nil;
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (Compare) ~ Bool) ~ MultiMap {
filtered := MultiMap->New();
keys := GetKeys();
each(i : keys) {
key := keys->Get(i);
if(f(key)) {
value := Find(key);
filtered->Insert(key, value);
};
};
return filtered;
}
#~
Removes a set of values from the map
@param key key for values to remove
~#
method : public : Remove(key : Compare) ~ Bool {
return @map->Remove(key);
}
#~
Size of unique keys
@return size of unique keys
~#
method : public : Size() ~ Int {
return @map->Size();
}
#~
Size of values
@return size of values
~#
method : public : TotalSize() ~ Int {
return @map->GetValues()->Size();
}
}
#~
Set of int values
~#
class IntSet {
@map : Map;
#~
Default constructor
~#
New() {
@map := Map->New();
}
#~
Inserts a key into the set
@param key key
~#
method : public : Insert(key : Int) ~ Nil {
@map->Insert(IntHolder->New(key), Base->New());
}
#~
Removes a key from the set
@param key key for value to remove
@return true if removed, false otherwise
~#
method : public : Remove(key : Int) ~ Bool {
return @map->Remove(IntHolder->New(key));
}
#~
Checks for key in set
@param key search key
@return true if found, false otherwise
~#
method : public : Has(key : Int) ~ Bool {
result := @map->Find(IntHolder->New(key))->As(IntHolder);
return result <> Nil;
}
#~
Get a collection of keys
@return vector of keys
~#
method : public: native : GetKeys() ~ IntVector {
keys := IntVector->New();
holder_keys := @map->GetKeys();
for(i := 0; i < holder_keys->Size(); i += 1;) {
holder_value : IntHolder := holder_keys->Get(i)->As(IntHolder);
keys->AddBack(holder_value->Get());
};
return keys;
}
#~
Clears the set
~#
method : public : Empty() ~ Nil {
@map->Empty();
}
#~
Checks to see if the map is empty
@return true if empty, false otherwise
~#
method : public : native : IsEmpty() ~ Bool {
return @map->IsEmpty();
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (Int) ~ Bool) ~ IntSet {
filtered := IntSet->New();
keys := GetKeys();
each(i : keys) {
key := keys->Get(i);
if(f(key)) {
filtered->Insert(key);
};
};
return filtered;
}
#~
Size of map
@return size of queue
~#
method : public : native : Size() ~ Int {
return @map->Size();
}
}
#~
Set of float values
~#
class FloatSet {
@map : Map;
#~
Default constructor
~#
New() {
@map := Map->New();
}
#~
Inserts a key into the set
@param key key
~#
method : public : Insert(key : Float) ~ Nil {
@map->Insert(FloatHolder->New(key), Base->New());
}
#~
Removes a key from the set
@param key key for value to remove
@return true if removed, false otherwise
~#
method : public : Remove(key : Float) ~ Bool {
return @map->Remove(FloatHolder->New(key));
}
#~
Checks for key in set
@param key search key
@return true if found, false otherwise
~#
method : public : Has(key : Float) ~ Bool {
result := @map->Find(FloatHolder->New(key))->As(FloatHolder);
return result <> Nil;
}
#~
Get a collection of keys
@return vector of keys
~#
method : public: native : GetKeys() ~ FloatVector {
keys := FloatVector->New();
holder_keys := @map->GetKeys();
for(i := 0; i < holder_keys->Size(); i += 1;) {
holder_value : FloatHolder := holder_keys->Get(i)->As(FloatHolder);
keys->AddBack(holder_value->Get());
};
return keys;
}
#~
Clears the set
~#
method : public : Empty() ~ Nil {
@map->Empty();
}
#~
Checks to see if the map is empty
@return true if empty, false otherwise
~#
method : public : native : IsEmpty() ~ Bool {
return @map->IsEmpty();
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (Float) ~ Bool) ~ FloatSet {
filtered := FloatSet->New();
keys := GetKeys();
each(i : keys) {
key := keys->Get(i);
if(f(key)) {
filtered->Insert(key);
};
};
return filtered;
}
#~
Size of map
@return size of queue
~#
method : public : native : Size() ~ Int {
return @map->Size();
}
}
#~
Set of string values
~#
class StringSet {
@map : Map;
#~
Default constructor
~#
New() {
@map := Map->New();
}
#~
Inserts a key into the set
@param key key
~#
method : public : Insert(key : String) ~ Nil {
@map->Insert(key, Base->New());
}
#~
Removes a key from the set
@param key key for value to remove
@return true if removed, false otherwise
~#
method : public : Remove(key : String) ~ Bool {
return @map->Remove(key);
}
#~
Checks for key in set
@param key search key
@return true if found, false otherwise
~#
method : public : Has(key : String) ~ Bool {
return @map->Find(key) <> Nil;
}
#~
Get a collection of keys
@return vector of keys
~#
method : public : GetKeys() ~ CompareVector {
return @map->GetKeys();
}
#~
Clears the set
~#
method : public : native : Empty() ~ Nil {
@map->Empty();
}
#~
Checks to see if the map is empty
@return true if empty, false otherwise
~#
method : public : native : IsEmpty() ~ Bool {
return @map->IsEmpty();
}
#~
Uses the given function to filter out values
@param f function to use a filter. If the function evaluates to true the value is added to the collection.
@return filter vector
~#
method : public : Filter(f : (String) ~ Bool) ~ StringSet {
filtered := StringSet->New();
keys := GetKeys();
each(i : keys) {
key := keys->Get(i)->As(String);
if(f(key)) {
filtered->Insert(key);
};
};
return filtered;
}
#~
Size of map
@return size of queue
~#
method : public : native : Size() ~ Int {
return @map->Size();
}
}
#~
Set of objects
~#
class Set {
@map : Map;
#~
Default constructor
~#
New() {
@map := Map->New();
}
#~
Inserts a key into the set
@param key key
~#
method : public : Insert(key : Compare) ~ Nil {
@map->Insert(key, Base->New());
}
#~
Removes a key from the set
@param key key for value to remove
@return true if removed, false otherwise
~#
method : public : Remove(key : Compare) ~ Bool {
return @map->Remove(key);
}
#~
Checks for key in set
@param key search key
@return true if found, false otherwise
~#
method : public : Has(key : Compare) ~ Bool {
return @map->Find(key) <> Nil;
}
#~
Get a collection of keys
@return vector of keys
~#
method : public : GetKeys() ~ CompareVector {
return @map->GetKeys();
}
#~
Clears the set
~#
method : public : native : Empty() ~ Nil {
@map->Empty();
}
#~
Checks to see if the map is empty
@return true if empty, false otherwise
~#
method : public : native : IsEmpty() ~ Bool {
return @map->IsEmpty();
}
#~
Size of map
@return size of queue
~#
method : public : native : Size() ~ Int {
return @map->Size();
}
}
#~
Hash table that stores strings
~#
class StringHash {
@hash : Hash;
#~
Default constructor
~#
New() {
@hash := Hash->New();
}
#~
Inserts a value into the hash
@param key key
@param value value
~#
method : public : Insert(key : String, value : Base) ~ Nil {
@hash->Insert(key, value);
}
#~
Removes a value from the hash
@param key key for value to remove
@return true if removed, false otherwise
~#
method : public : Remove(key : String) ~ Bool {
return @hash->Remove(key);
}
#~
Searches for a value in a hash
@param key search key
@return found value, Nil if not found
~#
method : public : Find(key : String) ~ Base {
return @hash->Find(key);
}
#~
Checks for a value in a hash
@param key search key
@return true if found, false otherwise
~#
method : public : Has(key : String) ~ Bool {
return @hash->Find(key) <> Nil;
}
#~
Get a collection of keys
@return vector of keys
~#
method : public : GetKeys() ~ Vector {
return @hash->GetKeys();
}
#~
Gets a collection of values
@return vector of values
~#
method : public : GetValues() ~ Vector {
return @hash->GetValues();
}
#~
Clears the map
~#
method : public : native : Empty() ~ Nil {
@hash->Empty();
}
#~
Size of map
@return size of queue
~#
method : public : native : Size() ~ Int {
return @hash->Size();
}
}
#~
Hash table that stores objects
~#
class Hash {
@buckets : CompareList[];
@size : Int;
#~
Default constructor
~#
New() {
@buckets := CompareList->New[337];
@size := 0;
}
#~
Inserts a value into the hash
@param key key
@param value value
~#
method : public : Insert(key : Compare, value : Base) ~ Nil {
hash := (key->HashID() % @buckets->Size())->Abs();
list := @buckets[hash];
if(list = Nil) {
list := CompareList->New();
@buckets[hash] := list;
};
list->AddBack(HashPair->New(key, value));
@size := @size + 1;
}
#~
Searches for a value in a hash
@param key search key
@return found value, Nil if not found
~#
method : public : native : Find(key : Compare) ~ Base {
hash := (key->HashID() % @buckets->Size())->Abs();
list := @buckets[hash];
if(list <> Nil) {
list->Rewind();
while(list->More()) {
pair : HashPair := list->Get()->As(HashPair);
if(pair->Compare(key) = 0) {
return pair->Get();
};
list->Next();
};
return Nil;
};
return Nil;
}
#~
Checks for a value in a hash
@param key search key
@return true if found, false otherwise
~#
method : public : native : Has(key : Compare) ~ Bool {
result := Find(key);
return result <> Nil;
}
#~
Removes a value from the hash
@param key key for value to remove
~#
method : public : native : Remove(key : Compare) ~ Bool {
hash := (key->HashID() % @buckets->Size())->Abs();
list := @buckets[hash];
if(list <> Nil) {
list->Rewind();
while(list->More()) {
pair : HashPair := list->Get()->As(HashPair);
if(pair->Compare(key) = 0) {
list->Remove();
@size := @size - 1;
return true;
};
list->Next();
};
return false;
};
return false;
}
#~
Get a collection of keys
@return vector of keys
~#
method : public : native : GetKeys() ~ Vector {
keys := Vector->New();
for(i := 0; i < @buckets->Size(); i += 1;) {
if(@buckets[i] <> Nil) {
list := @buckets[i];
list->Rewind();
while(list->More()) {
pair : HashPair := list->Get()->As(HashPair);
keys->AddBack(pair->GetKey());
list->Next();
};
};
};
return keys;
}
#~
Gets a collection of values
@return vector of values
~#
method : public : native : GetValues() ~ Vector {
values := Vector->New();
for(i := 0; i < @buckets->Size(); i += 1;) {
if(@buckets[i] <> Nil) {
list := @buckets[i];
list->Rewind();
while(list->More()) {
pair : HashPair := list->Get()->As(HashPair);
values->AddBack(pair->Get());
list->Next();
};
};
};
return values;
}
#~
Clears the map
~#
method : public : Empty() ~ Nil {
@buckets := CompareList->New[337];
@size := 0;
}
#~
Size of map
@return size of queue
~#
method : public : Size() ~ Int {
return @size;
}
}
class HashPair implements Compare {
@key : Compare;
@value : Base;
New(key : Compare, value : Base) {
Parent();
@key := key;
@value := value;
}
method : public : native : Compare(rhs : Compare) ~ Int {
return @key->Compare(rhs);
}
method : public : HashID() ~ Int {
return @key->HashID();
}
method : public : native : GetKey() ~ Compare {
return @key;
}
method : public : native : Get() ~ Base {
return @value;
}
}
}
#~
HTTP and HTTPS client support
~#
bundle Web.HTTP {
#~
URL parser, encoder and decoder
~#
class Url {
@parsed : Bool;
@url : String;
@scheme : String;
@host : String;
@port : Int;
@query : String;
@frag : String;
@path : String;
#~
Parsed URL into components
@param url raw URL
~#
New(url : String) {
@url := url;
@port := -1;
@parsed := ParseUrl(url);
}
#~
Determines if given URL has been parsed correctly
@return true if parsed, false otherwise
~#
method : public : Parsed() ~ Bool {
return @parsed;
}
#~
Gets original URL
@return original URL
~#
method : public : GetUrl() ~ String {
return @url;
}
#~
Gets scheme
@return scheme, Nil if not present
~#
method : public : GetScheme() ~ String {
if(@parsed) {
return @scheme;
};
return Nil;
}
#~
Gets host
@return host, Nil if not present
~#
method : public : GetHost() ~ String {
if(@parsed) {
return @host;
};
return Nil;
}
#~
Gets scheme
@return scheme, Nil if not present
~#
method : public : GetQuery() ~ String {
if(@parsed) {
return @query;
};
return Nil;
}
#~
Gets port
@return por, -1 if not present
~#
method : public : GetPort() ~ Int {
if(@parsed) {
return @port;
};
return -1;
}
#~
Gets fragment
@return fragment, Nil if not present
~#
method : public : GetFragment() ~ String {
if(@parsed) {
return @frag;
};
return Nil;
}
#~
Gets path
@return path, Nil if not present
~#
method : public : GetPath() ~ String {
if(@parsed) {
return @path;
};
return Nil;
}
method : ParseUrl(url : String) ~ Bool {
scheme_index := url->Find(':');
if(scheme_index < 0) {
"--- No scheme ---"->ErrorLine();
return false;
};
@scheme := url->SubString(0, scheme_index);
scheme_index += 1;
rest := url->SubString(scheme_index, url->Size() - scheme_index);
if(<>rest->StartsWith("//")) {
@path := rest;
}
else {
@path := "";
parts := rest->Split("/");
if(parts->Size() > 0) {
each(i : parts) {
part := parts[i];
# parse host
if(i = 1) {
@host := part;
port_index := @host->Find(':');
if(port_index > -1) {
port_start := port_index + 1;
port_end := port_start;
while(port_end < @host->Size() & @host->Get(port_end)->IsDigit()) {
port_end += 1;
};
# adjust path and host
if(port_end > port_start) {
port := @host->SubString(port_start, port_end - port_start);
@path += @host->SubString(port_end, @host->Size() - port_end);
@host := @host->SubString(0, port_index);
@port := port->ToInt();
};
};
if(@host->Size() > 0 & @host->Get(0) = '/') {
@host := @host->SubString(1, @host->Size() - 1);
};
}
# parse last
else if(i = parts->Size() - 1) {
last := part;
# parse query and fragment
query_index := last->FindLast('?');
if(query_index > -1) {
query_index += 1;
@query := last->SubString(query_index, last->Size() - query_index);
part := last->SubString(0, query_index - 1);
@frag := ParseFragment(@query);
if(@frag <> Nil) {
@query := @query->SubString(0, @query->Size() - @frag->Size() - 1);
};
}
else {
@frag := ParseFragment(last);
if(@frag <> Nil) {
part := last->SubString(0, last->Size() - @frag->Size() - 1);
};
};
@path += '/';
@path += part;
}
# append path
else if(i > 1) {
@path += '/';
@path += part;
};
};
}
else {
@path := rest;
};
};
return true;
}
method : ParseFragment(part : String) ~ String {
frag_index := part->FindLast('#');
if(frag_index > -1) {
frag_index += 1;
frag := part->SubString(frag_index, part->Size() - frag_index);
return frag;
};
return Nil;
}
#~
General encoding for HTML or XML strings
@param str string to encode
@return encoded string
~#
function : native : Encode(str : String) ~ String {
buffer := String->New();
each(i : str) {
c := str->Get(i);
select(c) {
label ' ': {
buffer->Append("%20");
}
label ';': {
buffer->Append("%3B");
}
label '=': {
buffer->Append("%3D");
}
label '$': {
buffer->Append("%26");
}
label ',': {
buffer->Append("%2C");
}
label '<': {
buffer->Append("%3C");
}
label '>': {
buffer->Append("%3E");
}
label '^': {
buffer->Append("%5E");
}
label '`': {
buffer->Append("%60");
}
label '\\': {
buffer->Append("%5C");
}
label '[': {
buffer->Append("%5B");
}
label ']': {
buffer->Append("%5D");
}
label '{': {
buffer->Append("%7B");
}
label '}': {
buffer->Append("%7D");
}
label '|': {
buffer->Append("%7C");
}
label '"': {
buffer->Append("%22");
}
label ':': {
buffer->Append("%3A");
}
label '/': {
buffer->Append("%2F");
}
label '#': {
buffer->Append("%23");
}
label '?': {
buffer->Append("%3F");
}
label '&': {
buffer->Append("%24");
}
label '@': {
buffer->Append("%40");
}
label '%': {
buffer->Append("%25");
}
label '+': {
buffer->Append("%2B");
}
label '~': {
buffer->Append("%7E");
}
other: {
buffer->Append(c);
}
};
};
return buffer;
}
#~
General decoding for HTML or XML strings
@param str encoded string
@return decoded string
~#
function : native : Decode(str : String) ~ String {
buffer := String->New();
each(i : str) {
c := str->Get(i);
if(c = '%' & i + 2 < str->Size()) {
value := "0x";
value->Append(str->Get(i + 1));
value->Append(str->Get(i + 2));
buffer->Append(value->ToInt()->As(Char));
i += 2;
}
else {
buffer->Append(c);
};
};
return buffer;
}
#~
String representation of URL
@return string representation of URL
~#
method : public : ToString() ~ String {
buffer := "{$@url}\n";
if(@scheme <> Nil) {
buffer += "\tscheme='{$@scheme}'\n";
};
if(@host <> Nil) {
buffer += "\thost='{$@host}'\n";
};
if(@path <> Nil) {
buffer += "\tpath='{$@path}'\n";
};
if(@port > -1) {
buffer += "\tport='{$@port}'\n";
};
if(@query <> Nil) {
buffer += "\tquery='{$@query}'\n";
};
if(@frag <> Nil) {
buffer += "\tfragment='{$@frag}'\n";
};
return buffer;
}
}
#~
HTTP client
~#
class HttpClient {
@headers : StringHash;
@cookies_enabled : Bool;
@cookies: Vector;
#~
Default constructor
~#
New() {
@cookies_enabled := false;
@cookies := Vector->New();
}
#~
Gets the HTTP headers
@return HTTP headers
~#
method : GetHeaders() ~ StringHash {
return @headers;
}
#~
Sets cookie support
@param cookies_enabled true if cookies are enabled, false otherwise
~#
method : public : CookiesEnabled(cookies_enabled : Bool) ~ Nil {
@cookies_enabled := cookies_enabled;
}
#~
Gets the cookies
@return vector of cookies