# HG changeset patch # User Jacob Carlborg # Date 1275314796 -7200 # Node ID 11a31bd929f93c1d1dcdf93ba882bb299c196f66 # Parent f7b078e85f7fd9ab0e810203723d486ce453eb3e Removed dependency on private library diff -r f7b078e85f7f -r 11a31bd929f9 orange/util/CTFE.d --- a/orange/util/CTFE.d Wed May 26 17:19:13 2010 +0200 +++ b/orange/util/CTFE.d Mon May 31 16:06:36 2010 +0200 @@ -6,4 +6,157 @@ */ module orange.util.CTFE; -public import mambo.util.CTFE; \ No newline at end of file +import orange.util.string; +import orange.util.Traits; + +template format (ARGS...) +{ + static if (ARGS.length == 0) + const format = ""; + + else + { + static if (is(typeof(ARGS[0]) : string)) + const format = ARGS[0] ~ format!(ARGS[1 .. $]); + + else + { + pragma(msg, typeof(ARGS[0].stringof)); + const format = toString_!(ARGS[0]) ~ format!(ARGS[1 .. $]); + } + + } +} + +private +{ + template toString_ (T) + { + const toString_ = T.stringof; + } + + template toString_ (int i) + { + const toString_ = itoa!(i); + } + + template toString_ (long l) + { + const toString_ = itoa!(l); + } + + template toString_ (bool b) + { + const toString_ = b ? "true" : "false"; + } + + template toString_ (float f) + { + const toString_ = ""; + } + + template toString_ (alias a) + { + const toString_ = a.stringof; + } +} + +/** + * Compile-time function to get the index of the give element. + * + * Performs a linear scan, returning the index of the first occurrence + * of the specified element in the array, or U.max if the array does + * not contain the element. + * + * Params: + * arr = the array to get the index of the element from + * element = the element to find + * + * Returns: the index of the element or size_t.max if the element was not found. + */ +size_t indexOf (T) (T[] arr, T element) +{ + static if (is(T == char) || is(T == wchar) || is(T == dchar)) + { + foreach (i, e ; arr) + if (e == element) + return i; + } + + else + { + foreach (i, e ; arr) + if (e == element) + return i; + } + + return size_t.max; +} + +/** + * Returns true if the given array contains the given element, + * otherwise false. + * + * Params: + * arr = the array to search in for the element + * element = the element to search for + * + * Returns: true if the array contains the element, otherwise false + */ +bool contains (T) (T[] arr, T element) +{ + return arr.indexOf(element) != size_t.max; +} + +/** + * CTFE, splits the given string on the given pattern + * + * Params: + * str = the string to split + * splitChar = the character to split on + * + * Returns: an array of strings containing the splited string + */ +T[][] split (T) (T[] str, T splitChar = ',') +{ + T[][] arr; + size_t x; + + foreach (i, c ; str) + { + if (splitChar == c) + { + if (str[x] == splitChar) + x++; + + arr ~= str[x .. i]; + x = i; + } + } + + if (str[x] == splitChar) + x++; + + arr ~= str[x .. $]; + + return arr; +} + +private: + +template decimalDigit (int n) // [3] +{ + const decimalDigit = "0123456789"[n .. n + 1]; +} + +template itoa (long n) +{ + static if (n < 0) + const itoa = "-" ~ itoa!(-n); + + else static if (n < 10) + const itoa = decimalDigit!(n); + + else + const itoa = itoa!(n / 10L) ~ decimalDigit!(n % 10L); +} \ No newline at end of file diff -r f7b078e85f7f -r 11a31bd929f9 orange/util/Reflection.d --- a/orange/util/Reflection.d Wed May 26 17:19:13 2010 +0200 +++ b/orange/util/Reflection.d Mon May 31 16:06:36 2010 +0200 @@ -1,9 +1,468 @@ /** - * Copyright: Copyright (c) 2010 Jacob Carlborg. + * Copyright: Copyright (c) 2009 Jacob Carlborg. * Authors: Jacob Carlborg - * Version: Initial created: Jan 26, 2010 + * Version: Initial created: Oct 5, 2009 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) */ module orange.util.Reflection; -public import mambo.util.Reflection; \ No newline at end of file +import orange.util.CTFE; +import orange.util.string; + +/** + * Returns the name of the given function + * + * Params: + * func = the function alias to get the name of + * + * Returns: the name of the function + */ +template functionNameOf (alias func) +{ + version(LDC) + const functionNameOf = (&func).stringof[1 .. $]; + + else + const functionNameOf = (&func).stringof[2 .. $]; +} + +/** + * Returns the parameter names of the given function + * + * Params: + * func = the function alias to get the parameter names of + * + * Returns: an array of strings containing the parameter names + */ +template parameterNamesOf (alias func) +{ + const parameterNamesOf = parameterNamesOfImpl!(func); +} + +/** + * Returns the parameter names of the given function + * + * Params: + * func = the function alias to get the parameter names of + * + * Returns: an array of strings containing the parameter names + */ +private string[] parameterNamesOfImpl (alias func) () +{ + string funcStr = typeof(&func).stringof; + + auto start = funcStr.indexOf('('); + auto end = funcStr.indexOf(')'); + + const firstPattern = ' '; + const secondPattern = ','; + + funcStr = funcStr[start + 1 .. end]; + + if (funcStr == "") + return null; + + funcStr ~= secondPattern; + + string token; + string[] arr; + + foreach (c ; funcStr) + { + if (c != firstPattern && c != secondPattern) + token ~= c; + + else + { + if (token) + arr ~= token; + + token = null; + } + } + + if (arr.length == 1) + return arr; + + string[] result; + bool skip = false; + + foreach (str ; arr) + { + skip = !skip; + + if (skip) + continue; + + result ~= str; + } + + return result; +} + +/** + * Helper function for callWithNamedArguments + * + * Returns: + */ +private string buildFunction (alias func, string args) () +{ + const str = split(args); + string[] params; + string[] values; + auto mixinString = functionNameOf!(func) ~ "("; + + foreach (s ; str) + { + auto index = s.indexOf('='); + params ~= s[0 .. index]; + values ~= s[index + 1 .. $]; + } + + const parameterNames = parameterNamesOf!(func); + + foreach (i, s ; parameterNames) + { + auto index = params.indexOf(s); + + if (index != params.length) + mixinString ~= values[index] ~ ","; + } + + return mixinString[0 .. $ - 1] ~ ");"; +} + +/** + * Calls the given function with named arguments + * + * Params: + * func = an alias to the function to call + * args = a string containing the arguments to call using this syntax: `arg2=value,arg1="value"` + */ +void callWithNamedArguments (alias func, string args) () +{ + mixin(buildFunction!(func, args)); +} + +/** + * Evaluates to true if T has a instance method with the given name + * + * Params: + * T = the type of the class/struct + * method = the name of the method + */ +template hasInstanceMethod (T, string method) +{ + const hasInstanceMethod = is(typeof({ + T t; + mixin("auto f = &t." ~ method ~ ";"); + })); +} + +/** + * Evaluates to true if T has a class method with the given name + * + * Params: + * T = the type of the class/struct + * method = the name of the method + */ +template hasClassMethod (T, string method) +{ + const hasClassMethod = is(typeof({ + mixin("auto f = &T." ~ method ~ ";"); + })); +} + +/** + * Evaluates to true if T has a either a class method or a instance method with the given name + * + * Params: + * T = the type of the class/struct + * method = the name of the method + */ +template hasMethod (T, string method) +{ + const hasMethod = hasClassMethod!(T, method) || hasInstanceMethod!(T, method); +} + +/** + * Evaluates to true if T has a field with the given name + * + * Params: + * T = the type of the class/struct + * field = the name of the field + */ +template hasField (T, string field) +{ + const hasField = hasFieldImpl!(T, field, 0); +} + +private template hasFieldImpl (T, string field, size_t i) +{ + static if (T.tupleof.length == i) + const hasFieldImpl = false; + + else static if (T.tupleof[i].stringof[1 + T.stringof.length + 2 .. $] == field) + const hasFieldImpl = true; + + else + const hasFieldImpl = hasFieldImpl!(T, field, i + 1); +} + +/** + * Evaluates to an array of strings containing the names of the fields in the given type + */ +template fieldsOf (T) +{ + const fieldsOf = fieldsOfImpl!(T, 0); +} + +/** + * Implementation for fieldsOf + * + * Returns: an array of strings containing the names of the fields in the given type + */ +template fieldsOfImpl (T, size_t i) +{ + static if (T.tupleof.length == 0) + const fieldsOfImpl = [""]; + + else static if (T.tupleof.length - 1 == i) + const fieldsOfImpl = [T.tupleof[i].stringof[1 + T.stringof.length + 2 .. $]]; + + else + const fieldsOfImpl = T.tupleof[i].stringof[1 + T.stringof.length + 2 .. $] ~ fieldsOfImpl!(T, i + 1); +} + +/** + * Evaluates to the type of the field with the given name + * + * Params: + * T = the type of the class/struct + * field = the name of the field + */ +template TypeOfField (T, string field) +{ + static assert(hasField!(T, field), "The given field \"" ~ field ~ "\" doesn't exist in the type \"" ~ T.stringof ~ "\""); + + alias TypeOfFieldImpl!(T, field, 0) TypeOfField; +} + +private template TypeOfFieldImpl (T, string field, size_t i) +{ + static if (T.tupleof[i].stringof[1 + T.stringof.length + 2 .. $] == field) + alias typeof(T.tupleof[i]) TypeOfFieldImpl; + + else + alias TypeOfFieldImpl!(T, field, i + 1) TypeOfFieldImpl; +} + +/** + * Evaluates to a string containing the name of the field at given position in the type given type. + * + * Params: + * T = the type of the class/struct + * position = the position of the field in the tupleof array + */ +template nameOfFieldAt (T, size_t position) +{ + static if (T.tupleof[position].stringof.length > T.stringof.length + 3) + const nameOfFieldAt = T.tupleof[position].stringof[1 + T.stringof.length + 2 .. $]; + + else + const nameOfFieldAt = ""; +} + +/** + * Sets the given value to the filed with the given name + * + * Params: + * t = an instance of the type that has the field + * value = the value to set + */ +void setValueOfField (T, U, string field) (ref T t, U value) +in +{ + static assert(hasField!(T, field), "The given field \"" ~ field ~ "\" doesn't exist in the type \"" ~ T.stringof ~ "\""); +} +body +{ + const len = T.stringof.length; + + foreach (i, dummy ; typeof(T.tupleof)) + { + const f = T.tupleof[i].stringof[1 + len + 2 .. $]; + + static if (f == field) + { + t.tupleof[i] = value; + break; + } + } +} + +/** + * Gets the value of the field with the given name + * + * Params: + * t = an instance of the type that has the field + * + * Returns: the value of the field + */ +U getValueOfField (T, U, string field) (T t) +in +{ + static assert(hasField!(T, field), "The given field \"" ~ field ~ "\" doesn't exist in the type \"" ~ T.stringof ~ "\""); +} +body +{ + const len = T.stringof.length; + + foreach (i, dummy ; typeof(T.tupleof)) + { + const f = T.tupleof[i].stringof[1 + len + 2 .. $]; + + static if (f == field) + return t.tupleof[i]; + } +} + +/** + * Gets all the class names in the given string of D code + * + * Params: + * code = a string containg the code to get the class names from + * + * Returns: the class names + */ +string[] getClassNames (string code) () +{ + const fileContent = code; + const classString = "class"; + bool foundPossibleClass; + bool foundClass; + string[] classNames; + string className; + + for (size_t i = 0; i < fileContent.length; i++) + { + final c = fileContent[i]; + + if (foundPossibleClass) + { + if (c == ' ' || c == '\n') + foundClass = true; + + foundPossibleClass = false; + } + + else if (foundClass) + { + if (c == '{') + { + classNames ~= className; + foundClass = false; + className = ""; + } + + else if (c != ' ' && c != '\n') + className ~= c; + } + + else + { + if (i + classString.length < fileContent.length) + { + if (fileContent[i .. i + classString.length] == classString) + { + if (i > 0) + { + if (fileContent[i - 1] == ' ' || fileContent[i - 1] == '\n' || fileContent[i - 1] == ';' || fileContent[i - 1] == '}') + { + foundPossibleClass = true; + i += classString.length - 1; + continue; + } + } + + else + { + foundPossibleClass = true; + i += classString.length - 1; + continue; + } + } + } + } + } + + return classNames; +} + +/** + * Creates a new instance of class with the given name + * + * Params: + * name = the fully qualified name of the class + * args = the arguments to the constructor + * + * Returns: the newly created instance or null + */ +T factory (T, ARGS...) (string name, ARGS args) +{ + auto classInfo = ClassInfo.find(name); + + if (!classInfo) + return null; + + auto object = newInstance(classInfo); + + if (classInfo.flags & 8 && classInfo.defaultConstructor is null) + { + auto o = cast(T) object; + + static if (is(typeof(o._ctor(args)))) + return o._ctor(args); + + else + return null; + } + + else + { + if (classInfo.flags & 8 && classInfo.defaultConstructor !is null) + { + Object delegate () ctor; + ctor.ptr = cast(void*) object; + ctor.funcptr = cast(Object function()) classInfo.defaultConstructor; + + return cast(T) ctor(); + } + + else + return cast(T) object; + } +} + +private +{ + version (LDC) + extern (C) Object _d_allocclass(ClassInfo); + + else + extern (C) Object _d_newclass(ClassInfo); +} + +Object newInstance (ClassInfo classInfo) +{ + version (LDC) + { + Object object = _d_allocclass(classInfo); + (cast(byte*) object)[0 .. classInfo.init.length] = classInfo.init[]; + + return object; + } + + else + return _d_newclass(classInfo); +} \ No newline at end of file diff -r f7b078e85f7f -r 11a31bd929f9 orange/util/Traits.d --- a/orange/util/Traits.d Wed May 26 17:19:13 2010 +0200 +++ b/orange/util/Traits.d Mon May 31 16:06:36 2010 +0200 @@ -6,12 +6,172 @@ */ module orange.util.Traits; -public import mambo.util.Traits; - import orange.serialization.Serializable; import orange.serialization.archives.Archive; import orange.util._; +version (Tango) +{ + import Tango = tango.core.Traits; + alias Tango.BaseTypeTupleOf BaseTypeTupleOf; + alias Tango.ParameterTupleOf ParameterTupleOf; + alias Tango.ReturnTypeOf ReturnTypeOf; +} + +else +{ + import Phobos = std.traits; + alias Phobos.BaseTypeTuple BaseTypeTupleOf; + alias Phobos.ParameterTypeTuple ParameterTupleOf; + alias Phobos.ReturnType ReturnTypeOf; + + version = Phobos; +} + +template isPrimitive (T) +{ + const bool isPrimitive = is(T == bool) || + is(T == byte) || + is(T == cdouble) || + //is(T == cent) || + is(T == cfloat) || + is(T == char) || + is(T == creal) || + is(T == dchar) || + is(T == double) || + is(T == float) || + is(T == idouble) || + is(T == ifloat) || + is(T == int) || + is(T == ireal) || + is(T == long) || + is(T == real) || + is(T == short) || + is(T == ubyte) || + //is(T == ucent) || + is(T == uint) || + is(T == ulong) || + is(T == ushort) || + is(T == wchar); +} + +template isChar (T) +{ + const bool isChar = is(T == char) || is(T == wchar) || is(T == dchar); +} + +template isClass (T) +{ + const bool isClass = is(T == class); +} + +template isInterface (T) +{ + const bool isInterface = is(T == interface); +} + +template isObject (T) +{ + const bool isObject = isClass!(T) || isInterface!(T); +} + +template isStruct (T) +{ + const bool isStruct = is(T == struct); +} + +template isArray (T) +{ + static if (is(T U : U[])) + const bool isArray = true; + + else + const bool isArray = false; +} + +template isString (T) +{ + const bool isString = is(T : char[]) || is(T : wchar[]) || is(T : dchar[]); +} + +template isAssociativeArray (T) +{ + const bool isAssociativeArray = is(typeof(T.init.values[0])[typeof(T.init.keys[0])] == T); +} + +template isPointer (T) +{ + static if (is(T U : U*)) + const bool isPointer = true; + + else + const bool isPointer = false; +} + +template isFunctionPointer (T) +{ + const bool isFunctionPointer = is(typeof(*T) == function); +} + +template isEnum (T) +{ + const bool isEnum = is(T == enum); +} + +template isReference (T) +{ + const bool isReference = isObject!(T) || isPointer!(T); +} + +template isTypeDef (T) +{ + const bool isTypeDef = is(T == typedef); +} + +template isVoid (T) +{ + const bool isVoid = is(T == void); +} + +template BaseTypeOfArray (T) +{ + static if (is(T U : U[])) + alias BaseTypeOfArray!(U) BaseTypeOfArray; + + else + alias T BaseTypeOfArray; +} + +template BaseTypeOfPointer (T) +{ + static if (is(T U : U*)) + alias BaseTypeOfPointer!(U) BaseTypeOfPointer; + + else + alias T BaseTypeOfPointer; +} + +template BaseTypeOfTypeDef (T) +{ + static if (is(T U == typedef)) + alias BaseTypeOfTypeDef!(U) BaseTypeOfTypeDef; + + else + alias T BaseTypeOfTypeDef; +} + +template KeyTypeOfAssociativeArray (T) +{ + static assert(isAssociativeArray!(T), "The type needs to be an associative array"); + alias typeof(T.init.keys[0]) KeyTypeOfAssociativeArray; +} + +template ValueTypeOfAssociativeArray (T) +{ + static assert(isAssociativeArray!(T), "The type needs to be an associative array"); + alias typeof(T.init.values[0]) ValueTypeOfAssociativeArray; +} + template isArchive (T) { const isArchive = is(typeof({ diff -r f7b078e85f7f -r 11a31bd929f9 orange/util/Use.d --- a/orange/util/Use.d Wed May 26 17:19:13 2010 +0200 +++ b/orange/util/Use.d Mon May 31 16:06:36 2010 +0200 @@ -6,8 +6,6 @@ */ module orange.util.Use; -import mambo.io; - version (Tango) { import tango.core.Tuple; @@ -62,6 +60,7 @@ return dg(deleg, *value); } } + RestoreStruct!(U, T) restore (U = void, T) (ref T val) { RestoreStruct!(U, T) restoreStruct; diff -r f7b078e85f7f -r 11a31bd929f9 orange/util/collection/Array.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/orange/util/collection/Array.d Mon May 31 16:06:36 2010 +0200 @@ -0,0 +1,625 @@ +/** + * Copyright: Copyright (c) 2008-2009 Jacob Carlborg. All rights reserved. + * Authors: Jacob Carlborg + * Version: Initial created: 2008 + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) + * + */ +module orange.util.collection.Array; + +version (Tango) +{ + static import tango.core.Array; + import tango.stdc.string : memmove; + static import tango.text.Util; +} + +else +{ + version = Phobos; + + import std.c.string : memmove; +} + +/** + * Inserts the specified element at the specified position in the array. Shifts the + * element currently at that position (if any) and any subsequent elements to the right. + * + * Params: + * arr = the array to insert the element into + * index = the index at which the specified element is to be inserted + * element = the element to be inserted + * + * Returns: the modified array + * + * Throws: AssertException if the length of the array is 0 + * Throws: AssertException if the $(D_PARAM index) argument is + * greater than the length of this array. + */ +T[] insert (T, U = size_t) (ref T[] arr, U index, T element) +in +{ + assert(arr.length > 0, "mambo.collection.Array.insert: The length of the array was 0"); + assert(index <= arr.length, "mambo.collection.Array.insert: The index was greater than the length of the array"); +} +body +{ + if (index == arr.length) + { + arr ~= element; + return arr; + } + + else if (index == 0) + arr = element ~ arr; + + else + arr = arr[0 .. index] ~ element ~ arr[index .. $]; + + return arr; +} + +/** + * Inserts the specified elements at the specified position in the array. Shifts the + * element currently at that position (if any) and any subsequent elements to the right. + * + * Params: + * arr = the array to insert the element into + * index = the index at which the specified element is to be inserted + * element = the element to be inserted + * + * Returns: the modified array + * + * Throws: AssertException if the length of the array is 0 + * Throws: AssertException if the $(D_PARAM index) argument is + * not less or equal than the length of this array. + */ +T[] insert (T, U = size_t) (ref T[] arr, U index, T[] element) +in +{ + assert(arr.length > 0, "mambo.collection.Array.insert: The length of the array was 0"); + assert(index <= arr.length, "mambo.collection.Array.insert: The index was greater than the length of the array"); +} +body +{ + if (index == arr.length) + { + arr ~= element; + return arr; + } + + else if (index == 0) + arr = element ~ arr; + + else + arr = arr[0 .. index] ~ element ~ arr[index .. $]; + + return arr; +} + +/** + * Inserts the specified element at the specified position in the array. Shifts the + * element currently at that position (if any) and any subsequent elements to the right. + * + * Params: + * arr = the array to add the element to + * index = the index at which the specified element is to be inserted + * element = the element to be inserted + * + * Returns: the modified array + * + * Throws: AssertException if the length of the array is 0 + * Throws: AssertException if the $(D_PARAM index) argument is + * not less than the length of this array. + */ +T[] add (T, U = size_t) (ref T[] arr, U index, T element) +in +{ + assert(arr.length > 0, "mambo.collection.Array.add: The length of the array was 0"); + assert(index <= arr.length, "mambo.collection.Array.add: The index was greater than the length of the array"); +} +body +{ + return insert(arr, index, element); +} + +/** + * Appends the specified element to the end of the array. + * + * Params: + * arr = the array to add the element to + * element = element to be appended to this list + * + * Returns: the modified array + */ +T[] add (T) (ref T[] arr, T element) +{ + return arr ~= element; +} + +/** + * Removes the element at the specified position in the array if it could find it and + * returns it. Shifts any subsequent elements to the left. + * + * Params: + * arr = the array to remove the element from + * index = the index of the element to be removed + * + * Returns: the element that was removed + * + * Throws: AssertException if the length of the array is 0 + * Throws: AssertException if the $(D_PARAM index) argument is + * not less than the length of this array. + */ +T remove (T, U = size_t) (ref T[] arr, U index) +in +{ + assert(arr.length > 0, "mambo.collection.Array.remove: The length of the array was 0"); + assert(index < arr.length, "mambo.collection.Array.remove: The index was greater than the length of the array"); +} +body +{ + T ret = arr[index]; + + if (index == 0) + arr = arr[1 .. $]; + + else if (index == arr.length - 1) + arr = arr[0 .. $ - 1]; + + else + { + if (index < arr.length - 1) + memmove(&arr[index], &arr[index + 1], T.sizeof * (arr.length - index - 1)); + + arr.length = arr.length - 1; + } + + return ret; +} + +/** + * Removes the specified element from the array if it could find it and returns it. + * Shifts any subsequent elements to the left. + * + * Params: + * arr = the array to remove the element from + * element = the element to be removed + * + * Returns: the element that was removed or T.max + * + * Throws: AssertException if the length of the array is 0 + */ +T remove (T) (ref T[] arr, T element) +in +{ + assert(arr.length > 0, "mambo.collection.Array.remove: The length of the array was 0"); +} +out (result) +{ + assert(result is element); +} +body +{ + size_t index = arr.indexOf(element); + + if (index == size_t.max) + return T.max; + + return arr.remove(index); +} + +/** + * Returns the index of the first occurrence of the specified element in the array, or + * U.max if the array does not contain the element. + * + * Params: + * arr = the array to get the index of the element from + * element = the element to find + * start = the index where to begin the search + * + * Returns: the index of the element or U.max if it's not in the array + * + * Throws: AssertException if the length of the array is 0 + * Throws: AssertException if the return value is greater or + * equal to the length of the array. + */ +U indexOf (T, U = size_t) (T[] arr, T element, U start = 0) +in +{ + assert(start >= 0, "mambo.collection.Array.indexOf: The start index was less than 0"); +} +body +{ + version (Tango) + { + U index = tango.text.Util.locate(arr, element, start); + + if (index == arr.length) + index = U.max; + + return index; + } + + else + { + if (start > arr.length) + start = arr.length; + + for (U i = start; i < arr.length; i++) + if (arr[i] == element) + return i; + + return U.max; + } +} + +/** + * Returns $(D_KEYWORD true) if the array contains the specified element. + * + * Params: + * arr = the array to check if it contains the element + * element = the element whose presence in the array is to be tested + * + * Returns: $(D_KEYWORD true) if the array contains the specified element + * + * Throws: AssertException if the length of the array is 0 + */ +bool contains (T) (T[] arr, T element) +in +{ + assert(arr.length > 0, "mambo.collection.Array.contains: The length of the array was 0"); +} +body +{ + return arr.indexOf!(T, size_t)(element) < size_t.max; +} + +/** + * Returns $(D_KEYWORD true) if this array contains no elements. + * + * Params: + * arr = the array to check if it's empty + * + * Returns: $(D_KEYWORD true) if this array contains no elements + */ +bool isEmpty (T) (T[] arr) +{ + return arr.length == 0; +} + +/** + * Returns $(D_KEYWORD true) if this array contains no elements. + * + * Params: + * arr = the array to check if it's empty + * + * Returns: $(D_KEYWORD true) if this array contains no elements + */ +alias isEmpty empty; + +/** + * Removes all of the elements from this array. The array will be empty after this call + * returns. + * + * Params: + * arr = the array to clear + * + * Returns: the cleared array + * + * Throws: AssertException if length of the return array isn't 0 + */ +T[] clear (T) (T[] arr) +out (result) +{ + assert(result.length == 0, "mambo.collection.Array.clear: The length of the resulting array was not 0"); +} +body +{ + return arr.length = 0; +} + +/** + * Returns the element at the specified position in the array. + * + * Params: + * arr = the array to get the element from + * index = index of the element to return + * + * Returns: the element at the specified position in the array + * + * Throws: AssertException if the length of the array is 0 + * Throws: AssertException if the $(D_PARAM index) argument is + * not less than the length of this array. + */ +T get (T, U = size_t) (T[] arr, U index) +in +{ + assert(arr.length > 0, "mambo.collection.Array.get: The length of the array was 0"); + assert(index < arr.length, "mambo.collection.Array.get: The index was greater than the length of the array"); +} +body +{ + return arr[index]; +} + +/** + * Returns the index of the last occurrence of the specifed element + * + * Params: + * arr = the array to get the index of the element from + * element = the element to find the index of + * + * Returns: the index of the last occurrence of the element in the + * specified array, or U.max + * if the element does not occur. + * + * Throws: AssertException if the length of the array is 0 + * Throws: AssertException if the return value is less than -1 or + * greater than the length of the array - 1. + */ +U lastIndexOf (T, U = size_t) (T[] arr, T element) +in +{ + assert(arr.length > 0, "mambo.collection.Array.lastIndexOf: The length of the array was 0"); +} +body +{ + version (Tango) + { + U index = tango.text.Util.locatePrior(arr, element); + + if (index == arr.length) + return U.max; + + return index; + } + + else + { + foreach_reverse (i, e ; arr) + if (e is element) + return i; + + return U.max; + } +} + +/** + * Returns the number of elements in the specified array. + * + * Params: + * arr = the array to get the number of elements from + * + * Returns: the number of elements in this list + */ +U size (T, U = size_t) (T[] arr) +{ + return arr.length; +} + +/** + * Finds the first occurence of element in arr + * + * Params: + * arr = the array to find the element in + * element = the element to find + * start = at which position to start finding + * + * Returns: the index of the first match or U.max if no match was found. + */ +alias indexOf find; + +/** + * Replaces a section of $(D_PARAM arr) with elements starting at $(D_PARAM pos) ending + * $(D_PARAM n) elements after + * + * Params: + * arr = the array to do the replace in + * pos = position within the array of the first element of the section to be replaced + * n = length of the section to be replaced within the array + * elements = the elements to replace with + * + * Throws: + * AssertException if pos is greater than the length of the array + * + * Returns: the array + */ +T[] replace (T, U = size_t) (ref T[] arr, U pos, U n, T[] elements) +in +{ + assert(pos <= arr.length, "mambo.collection.Array.replace: The position was greter than the length of the array"); +} +body +{ + U i; + U nr = n; + + if (nr > arr.length) + nr = arr.length - 1; + + if (nr == elements.length) + { + U eIndex; + + for (i = pos, eIndex = 0; i <= nr; i++, eIndex++) + arr[i] = elements[eIndex]; + + return arr; + } + + else if (elements.length == 0) + { + U index = pos + n; + + if (index >= arr.length) + index = arr.length; + + return arr = arr[0 .. pos] ~ arr[index .. $]; + } + + else + { + U eIndex; + + for (i = pos, eIndex = 0; eIndex < nr && i < arr.length && eIndex < elements.length; i++, eIndex++) + arr[i] = elements[eIndex]; + + // no positions left and elements are left in elements, insert elements + if (eIndex < elements.length) + return arr = arr[0 .. i] ~ elements[eIndex .. $] ~ arr[i .. $]; + + // positions left to replace but no elements, remove those positions + else if (nr > eIndex) + { + U index = pos + nr; + + if (index >= arr.length) + index = arr.length; + + return arr = arr[0 .. pos + eIndex] ~ arr[index .. $]; + } + + } + + return arr; +} + +/** + * Erases a part of the array content, shortening the length of the array. + * + * Params: + * arr = the array to erase elements from + * start = the position within the array of the first element to be erased + * n = amount of elements to be removed. It may remove less elements if the + * end of the array is reached before the n elements have been erased. + * The default value of n indicates that all the elements until the end + * of the array should be erased. + * + * Throws: + * AssertException if pos is greater than the length of the array + * + * Returns: the array + */ +T[] erase (T, U = size_t) (ref T[] arr, U start = 0, U n = U.max) +in +{ + assert(start <= arr.length, "mambo.collection.Array.erase: The start position was greater than the length of the array"); +} +body +{ + U end; + + if (n == U.max) + end = arr.length; + + else + { + end = start + n; + + if (end > arr.length) + end = arr.length; + } + + return arr = arr[0 .. start] ~ arr[end .. $]; +} + +/** + * Compares to arrays. Returns 0 if the content matches, less than zero + * if a is "less" than b, or greater than zero where a is "bigger". + * + * Params: + * a = the first array + * b = the second array + * end = the index where the comparision will end + * + * Returns: Returns 0 if the content matches, less than zero if a is + * "less" than b, or greater than zero where a is "bigger". + */ +int compare (T, U = size_t) (T[] a, T[] b, U end = U.max) +{ + U ia = end; + U ib = end; + + if (ia > a.length) + ia = a.length; + + if (ib > b.length) + ib = b.length; + + return typeid(T[]).compare(&a[0 .. ia], &b[0 .. ib]); +} + +/** + * Compares the content of the given array to the content of a comparing + * array, which is formed according to the arguments passed. + * + * The function returns 0 if all the elements in the compared contents compare + * equal, a negative value if the first element that does not match compares to + * less in the array than in the comparing array, and a positive value in + * the opposite case. + * + * Params: + * a = the first array to compare with + * pos = position of the beginning of the compared slice, i.e. the first element in the array (in a) to be compared against the comparing array. + * n = length of the compared slice. + * b = array with the content to be used as comparing array. + * + * Returns: 0 if the compared array are equal, otherwise a number different from 0 is returned, with its sign indicating whether the array is considered greater than the comparing array passed as parameter (positive sign), or smaller (negative sign). + * + * Throws: AssertException if pos is specified with a position greater than the length of the corresponding array + */ +int compare (T, U = size_t) (T[] a, size_t pos, size_t n, T[] b) +in +{ + assert(pos <= b.length); +} +body +{ + U end = pos + n; + + if (end > b.length) + end = b.length; + + return typeid(T[]).compare(&b[pos .. end], &a[0 .. $]); +} + +/** + * Reserves the given amount of allocated storage for the given array. + * + * Params: + * a = the array to reserve allocated storage for + * capacity = the amount of allocated storage to be reserved + */ +void reserve (T) (ref T[] a, size_t amount = 0) +{ + a = (new T[amount])[0 .. 0]; +} + +/** + * Returns true if a begins with b + * + * Params: + * a = the array to + * b = + * + * Returns: true if a begins with b, otherwise false + */ +bool beginsWith (T) (T[] a, T[] b) +{ + return a.length > b.length && a[0 .. b.length] == b; +} + +/** + * Returns true if a ends with b + * + * Params: + * a = the array to + * b = + * + * Returns: true if a ends with b, otherwise false + */ +bool endsWith (T) (T[] a, T[] b) +{ + return a.length > b.length && a[$ - b.length .. $] == b; +} \ No newline at end of file diff -r f7b078e85f7f -r 11a31bd929f9 orange/util/io.d --- a/orange/util/io.d Wed May 26 17:19:13 2010 +0200 +++ b/orange/util/io.d Mon May 31 16:06:36 2010 +0200 @@ -1,3 +1,82 @@ +/** + * Copyright: Copyright (c) 2007-2008 Jacob Carlborg. All rights reserved. + * Authors: Jacob Carlborg + * Version: Initial created: 2007 + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) + * + */ module orange.util.io; -public import mambo.io; \ No newline at end of file +version (Tango) +{ + import tango.io.Stdout; + import tango.io.Console; + + import orange.util.string; +} + +else + import std.stdio; + +/** + * Print to the standard output + * + * Params: + * args = what to print + */ +void print (A...)(A args) +{ + version (Tango) + { + const string fmt = "{}{}{}{}{}{}{}{}" + "{}{}{}{}{}{}{}{}" + "{}{}{}{}{}{}{}{}"; + + static assert (A.length <= fmt.length / 2, "mambo.io.print :: too many arguments"); + + Stdout.format(fmt[0 .. args.length * 2], args).flush; + } + + + else + foreach(t ; a) + writef(t); +} + +/** + * Print to the standard output, adds a new line + * + * Params: + * args = what to print + */ +void println (A...)(A args) +{ + version (Tango) + { + const string fmt = "{}{}{}{}{}{}{}{}" + "{}{}{}{}{}{}{}{}" + "{}{}{}{}{}{}{}{}"; + + static assert (A.length <= fmt.length / 2, "mambo.io.println :: too many arguments"); + + Stdout.formatln(fmt[0 .. args.length * 2], args); + } + + else + { + foreach(t ; args) + writef(t); + + writef("\n"); + } +} + +/** + * Read from the standard input + * + * Returns: what was read + */ +string read () +{ + return Cin.get; +} diff -r f7b078e85f7f -r 11a31bd929f9 orange/util/string.d --- a/orange/util/string.d Wed May 26 17:19:13 2010 +0200 +++ b/orange/util/string.d Mon May 31 16:06:36 2010 +0200 @@ -1,9 +1,881 @@ /** - * Copyright: Copyright (c) 2010 Jacob Carlborg. + * Copyright: Copyright (c) 2008-2009 Jacob Carlborg. All rights reserved. * Authors: Jacob Carlborg - * Version: Initial created: Jan 26, 2010 + * Version: Initial created: 2008 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) + * */ module orange.util.string; -public import mambo.string; \ No newline at end of file +public import orange.util.collection.Array; + +version (Tango) +{ + static import tango.stdc.stringz; + import tango.text.Unicode : toFold, isDigit; + import tango.text.convert.Utf; + import tango.text.Util; + + alias tango.stdc.stringz.toStringz toStringz; + alias tango.stdc.stringz.toString16z toString16z; + alias tango.stdc.stringz.toString32z toString32z; + + alias tango.stdc.stringz.fromStringz fromStringz; + alias tango.stdc.stringz.fromString16z fromString16z; + alias tango.stdc.stringz.fromString32z fromString32z; + + alias tango.text.convert.Utf.toString16 toString16; + alias tango.text.convert.Utf.toString32 toString32; +} + +else +{ + import std.string; + import std.utf; + import std.ctype : isxdigit; + + version = Phobos; + + private alias std.string.tolower toFold; + + alias std.utf.toUTF8 toString; + alias std.utf.toUTF16 toString16; + alias std.utf.toUTF32 toString32; + + alias std.string.toStringz toStringz; + alias std.utf.toUTF16z toString16z; + + alias std.string.toString fromStringz; +} + +version (Tango) +{ + /** + * string alias + */ + alias char[] string; + + /** + * wstring alias + */ + alias wchar[] wstring; + + /** + * dstring alias + */ + alias dchar[] dstring; +} + +/** + * Compares the $(D_PSYMBOL string) to another $(D_PSYMBOL string), ignoring case + * considerations. Two strings are considered equal ignoring case if they are of the + * same length and corresponding characters in the two strings are equal ignoring case. + * + * Params: + * str = The $(D_PSYMBOL string) first string to compare to + * anotherString = The $(D_PSYMBOL string) to compare the first $(D_PSYMBOL string) with + * + * Returns: $(D_KEYWORD true) if the arguments is not $(D_KEYWORD null) and it + * represents an equivalent $(D_PSYMBOL string) ignoring case; $(D_KEYWORD false) otherwise + * + * Throws: AssertException if the length of any of the strings is 0 + * + * See_Also: opEquals(Object) + */ +bool equalsIgnoreCase (string str, string anotherString) +in +{ + assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0"); + assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0"); +} +body +{ + if (str == anotherString) + return true; + + return toFold(str) == toFold(anotherString); +} + +/** + * Compares the $(D_PSYMBOL wstring) to another $(D_PSYMBOL wstring), ignoring case + * considerations. Two wstrings are considered equal ignoring case if they are of the + * same length and corresponding characters in the two wstrings are equal ignoring case. + * + * Params: + * str = The $(D_PSYMBOL wstring) first string to compre to + * anotherString = The $(D_PSYMBOL wstring) to compare the first $(D_PSYMBOL wstring) against + * + * Returns: $(D_KEYWORD true) if the argument is not $(D_KEYWORD null) and it + * represents an equivalent $(D_PSYMBOL wstring) ignoring case; (D_KEYWORD + * false) otherwise + * + * Throws: AssertException if the length of any of the wstrings is 0 + * + * See_Also: opEquals(Object) + */ +bool equalsIgnoreCase (wstring str, wstring anotherString) +in +{ + assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0"); + assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0"); +} +body +{ + if (str == anotherString) + return true; + + version (Tango) + return toFold(str) == toFold(anotherString); + + else + return toFold(toUTF8(str)) == toFold(toUTF8(anotherString)); +} + +/** + * Compares the $(D_PSYMBOL dstring) to another $(D_PSYMBOL dstring), ignoring case + * considerations. Two wstrings are considered equal ignoring case if they are of the + * same length and corresponding characters in the two wstrings are equal ignoring case. + * + * Params: + * str = The $(D_PSYMBOL dstring) first string to compare to + * anotherString = The $(D_PSYMBOL wstring) to compare the first $(D_PSYMBOL dstring) against + * + * Returns: $(D_KEYWORD true) if the argument is not $(D_KEYWORD null) and it + * represents an equivalent $(D_PSYMBOL dstring) ignoring case; $(D_KEYWORD false) otherwise + * + * Throws: AssertException if the length of any of the dstrings are 0 + * + * See_Also: opEquals(Object) + */ +bool equalsIgnoreCase (dstring str, dstring anotherString) +in +{ + assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0"); + assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0"); +} +body +{ + if (str == anotherString) + return true; + + version (Tango) + return toFold(str) == toFold(anotherString); + + else + return toFold(toUTF8(str)) == toFold(toUTF8(anotherString)); +} + +/** + * Returns the char value at the specified index. An index ranges from 0 to length - 1. + * The first $(D_KEYWORD char) value of the sequence is at index 0, the next at index 1, + * and so on, as for array indexing. + * + * Params: + * str = the string to get the $(D_KEYWORD char) from + * index = the index of the $(D_KEYWORD char) value. + * + * Returns: the $(D_KEYWORD char) value at the specified index of the string. + * The first $(D_KEYWORD char) value is at index 0. + * + * Throws: AssertException if the length of the string is 0 + * Throws: AssertException if the $(D_CODE index) argument is + * not less than the length of the string. + */ +char charAt (string str, size_t index) +in +{ + assert(str.length > 0, "mambo.string.charAt: The length of the string was 0"); + assert(index <= str.length, "mambo.string.charAt: The index was to greater than the length of the string"); +} +body +{ + return str[index]; +} + +/** + * Returns the $(D_KEYWORD char) value at the specified index. An index ranges from 0 to + * length - 1. The first $(D_KEYWORD char) value of the sequence is at index 0, the next + * at index 1, and so on, as for array indexing. + * + * Params: + * str = the wstring to get the $(D_KEYWORD char) from + * index = the index of the $(D_KEYWORD char) value. + * + * Returns: the $(D_KEYWORD char) value at the specified index of the wstring. + * The first $(D_KEYWORD char) value is at index 0. + * + * Throws: AssertException if the length of the wstring is 0 + * Throws: AssertException if the $(D_CODE index) argument is + * not less than the length of the wstring. + */ +wchar charAt (wstring str, size_t index) +in +{ + assert(str.length > 0, "mambo.string.charAt: The length of the string was 0"); + assert(index <= str.length, "mambo.string.charAt: The index was to greater than the length of the string"); +} +body +{ + return str[index]; +} + +/** + * Returns the $(D_KEYWORD char) value at the specified index. An index ranges from 0 to + * length - 1. The first $(D_KEYWORD char) value of the sequence is at index 0, the next + * at index 1, and so on, as for array indexing. + * + * Params: + * str = the dstring to get the $(D_KEYWORD char) from + * index = the index of the $(D_KEYWORD char) value. + * + * Returns: the $(D_KEYWORD char) value at the specified index of the dstring. + * The first $(D_KEYWORD char) value is at index 0. + * + * Throws: AssertException if the length of the dstring is 0 + * Throws: AssertException if the $(D_CODE index) argument is + * not less than the length of the dstring. + */ +dchar charAt (dstring str, size_t index) +in +{ + assert(str.length > 0, "mambo.string.charAt: The length of the string was 0"); + assert(index <= str.length, "mambo.string.charAt: The index was to greater than the length of the string"); +} +body +{ + return str[index]; +} + +/** + * Returns a new string that is a substring of the specified string. The substring begins + * at the specified $(D_PARAM beginIndex) and extends to the character at index + * $(D_PARAM endIndex) - 1. Thus the length of the substring is $(D_PARAM endIndex - beginIndex). + * + * Examples: + * --- + * "hamburger".substring(4, 8) returns "urge" + * "smiles".substring(1, 5) returns "mile" + * --- + * + * Params: + * str = the string to get the substring from + * beginIndex = the beginning index, inclusive. + * endIndex = the ending index, exclusive. + * + * Returns: the specified substring. + * + * Throws: AssertException if the length of the string is 0 + * Throws: AssertException if the $(D_PARAM beginIndex) is + * larger than $(D_PARAM endIndex). + * Throws: AssertException if $(D_PARAM endIndex) is larger than the + * length of the $(D_PSYMBOL string). + */ +string substring (string str, size_t beginIndex, size_t endIndex) +in +{ + assert(str.length > 0, "mambo.string.substring: The length of the string was 0"); + assert(beginIndex < endIndex, "mambo.string.substring: The first index was greater the second"); + assert(endIndex <= str.length, "mambo.string.substring: The second index was greater then the length of the string"); +} +body +{ + return str[beginIndex .. endIndex].dup; +} + +/** + * Returns a new string that is a substring of the specified string. The substring begins + * at the specified $(D_PARAM beginIndex) and extends to the character at index + * $(D_PARAM endIndex) - 1. Thus the length of the substring is $(D_PARAM endIndex - beginIndex). + * + * Examples: + * --- + * "hamburger".substring(4, 8) returns "urge" + * "smiles".substring(1, 5) returns "mile" + * --- + * + * Params: + * str = the string to get the substring from + * beginIndex = the beginning index, inclusive. + * endIndex = the ending index, exclusive. + * + * Returns: the specified substring. + * + * Throws: AssertException if the length of the string is 0 + * Throws: AssertException if the $(D_PARAM beginIndex) is + * larger than $(D_PARAM endIndex). + * Throws: AssertException if $(D_PARAM endIndex) is larger than the + * length of the $(D_PSYMBOL string). + */ +wstring substring (wstring str, size_t beginIndex, size_t endIndex) +in +{ + assert(str.length > 0, "mambo.string.substring: The length of the string was 0"); + assert(beginIndex < endIndex, "mambo.string.substring: The first index was greater the second"); + assert(endIndex <= str.length, "mambo.string.substring: The second index was greater then the length of the string"); +} +body +{ + return str[beginIndex .. endIndex].dup; +} + +/** + * Returns a new string that is a substring of the specified string. The substring begins + * at the specified $(D_PARAM beginIndex) and extends to the character at index + * $(D_PARAM endIndex) - 1. Thus the length of the substring is $(D_PARAM endIndex - beginIndex). + * + * Examples: + * --- + * "hamburger".substring(4, 8) returns "urge" + * "smiles".substring(1, 5) returns "mile" + * --- + * + * Params: + * str = the string to get the substring from + * beginIndex = the beginning index, inclusive. + * endIndex = the ending index, exclusive. + * + * Returns: the specified substring. + * + * Throws: AssertException if the length of the string is 0 + * Throws: AssertException if the $(D_PARAM beginIndex) is + * larger than $(D_PARAM endIndex). + * Throws: AssertException if $(D_PARAM endIndex) is larger than the + * length of the $(D_PSYMBOL string). + */ +dstring substring (dstring str, size_t beginIndex, size_t endIndex) +in +{ + assert(str.length > 0, "mambo.string.substring: The length of the string was 0"); + assert(beginIndex < endIndex, "mambo.string.substring: The first index was greater the second"); + assert(endIndex <= str.length, "mambo.string.substring: The second index was greater then the length of the string"); +} +body +{ + return str[beginIndex .. endIndex].dup; +} + +/** + * Returns a new string that is a substring of the specified string. The substring begins + * with the character at the specified index and extends to the end of the string. + * + * Examples: + * --- + * "unhappy".substring(2) returns "happy" + * "Harbison".substring(3) returns "bison" + * "emptiness".substring(9) returns "" (an empty string) + * --- + * + * Params: + * str = the string to get the substring from + * beginIndex = the beginning index, inclusive + * + * Returns: the specified substring + * + * Throws: AssertException if the length of the string is 0 + * Throws: AssertException if the $(D_PARAM beginIndex) is + * larger than the length of the string. + */ +string substring (string str, size_t index) +in +{ + assert(str.length > 0, "mambo.string.substring: The length of the string was 0"); + assert(index < str.length, "mambo.string.substring: The index was greater than the length of the string"); +} +body +{ + return str.substring(index, str.length); +} + +/** + * Returns a new string that is a substring of the specified string. The substring begins + * with the character at the specified index and extends to the end of the string. + * + * Examples: + * --- + * "unhappy".substring(2) returns "happy" + * "Harbison".substring(3) returns "bison" + * "emptiness".substring(9) returns "" (an empty string) + * --- + * + * Params: + * str = the string to get the substring from + * beginIndex = the beginning index, inclusive + * + * Returns: the specified substring + * + * Throws: AssertException if the length of the string is 0 + * Throws: AssertException if the $(D_PARAM beginIndex) is + * larger than the length of the string. + */ +wstring substring (wstring str, size_t index) +in +{ + assert(str.length > 0, "mambo.string.substring: The length of the string was 0"); + assert(index < str.length, "mambo.string.substring: The index was greater than the length of the string"); +} +body +{ + return str.substring(index, str.length); +} + +/** + * Returns a new string that is a substring of the specified string. The substring begins + * with the character at the specified index and extends to the end of the string. + * + * Examples: + * --- + * "unhappy".substring(2) returns "happy" + * "Harbison".substring(3) returns "bison" + * "emptiness".substring(9) returns "" (an empty string) + * --- + * + * Params: + * str = the string to get the substring from + * beginIndex = the beginning index, inclusive + * + * Returns: the specified substring + * + * Throws: AssertException if the length of the string is 0 + * Throws: AssertException if the $(D_PARAM beginIndex) is + * larger than the length of the string. + */ +dstring substring (dstring str, size_t index) +in +{ + assert(str.length > 0, "mambo.string.substring: The length of the string was 0"); + assert(index < str.length, "mambo.string.substring: The index was greater than the length of the string"); +} +body +{ + return str.substring(index, str.length); +} + +/** + * Returns a new string that is a substring of the given string. + * + * This substring is the character sequence that starts at character + * position pos and has a length of n characters. + * + * Params: + * str = the string to get the substring from + * pos = position of a character in the current string to be used + * as starting character for the substring. + * n = Length of the substring. If this value would make the + * substring to span past the end of the current string content, + * only those characters until the end of the string are used. + * size_t.max is the greatest possible value for an element of + * type size_t, therefore, when this value is used, all the + * characters between pos and the end of the string are used as + * the initialization substring. + * + * Returns: a string containing a substring of the given string + * + * Throws: AssertException if pos is greater than the length of the string + */ +string substr (string str, size_t pos = 0, size_t n = size_t.max) +in +{ + assert(pos < str.length, "mambo.string.substr: The given position was greater than the length of the string."); +} +body +{ + size_t end; + + if (n == size_t.max) + end = str.length; + + else + { + end = pos + n; + + if (end > str.length) + end = str.length; + } + + return str[pos .. end].dup; +} + +/** + * Returns a new string that is a substring of the given string. + * + * This substring is the character sequence that starts at character + * position pos and has a length of n characters. + * + * Params: + * str = the string to get the substring from + * pos = position of a character in the current string to be used + * as starting character for the substring. + * n = Length of the substring. If this value would make the + * substring to span past the end of the current string content, + * only those characters until the end of the string are used. + * size_t.max is the greatest possible value for an element of + * type size_t, therefore, when this value is used, all the + * characters between pos and the end of the string are used as + * the initialization substring. + * + * Returns: a string containing a substring of the given string + * + * Throws: AssertException if pos is greater than the length of the string + */ +wstring substr (wstring str, size_t pos = 0, size_t n = size_t.max) +in +{ + assert(pos < str.length, "mambo.string.substr: The given position was greater than the length of the string."); +} +body +{ + size_t end; + + if (n == size_t.max) + end = str.length; + + else + { + end = pos + n; + + if (end > str.length) + end = str.length; + } + + return str[pos .. end].dup; +} + +/** + * Returns a new string that is a substring of the given string. + * + * This substring is the character sequence that starts at character + * position pos and has a length of n characters. + * + * Params: + * str = the string to get the substring from + * pos = position of a character in the current string to be used + * as starting character for the substring. + * n = Length of the substring. If this value would make the + * substring to span past the end of the current string content, + * only those characters until the end of the string are used. + * size_t.max is the greatest possible value for an element of + * type size_t, therefore, when this value is used, all the + * characters between pos and the end of the string are used as + * the initialization substring. + * + * Returns: a string containing a substring of the given string + * + * Throws: AssertException if pos is greater than the length of the string + */ +dstring substr (dstring str, size_t pos = 0, size_t n = size_t.max) +in +{ + assert(pos < str.length, "mambo.string.substr: The given position was greater than the length of the string."); +} +body +{ + size_t end; + + if (n == size_t.max) + end = str.length; + + else + { + end = pos + n; + + if (end > str.length) + end = str.length; + } + + return str[pos .. end].dup; +} + +/** + * Finds the first occurence of sub in str + * + * Params: + * str = the string to find in + * sub = the substring to find + * start = where to start finding + * + * Returns: the index of the substring or size_t.max when nothing was found + */ +size_t find (string str, string sub, size_t start = 0) +{ + version (Tango) + { + size_t index = str.locatePattern(sub, start); + + if (index == str.length) + return size_t.max; + + return index; + } + + else + return std.string.find(str, sub, start); +} + +/** + * Finds the first occurence of sub in str + * + * Params: + * str = the string to find in + * sub = the substring to find + * start = where to start finding + * + * Returns: the index of the substring or size_t.max when nothing was found + */ +size_t find (wstring str, wstring sub, size_t start = 0) +{ + version (Tango) + { + size_t index = str.locatePattern(sub, start); + + if (index == str.length) + return size_t.max; + + return index; + } + + else + return std.string.find(str, sub, start); +} + +/** + * Finds the first occurence of sub in str + * + * Params: + * str = the string to find in + * sub = the substring to find + * start = where to start finding + * + * Returns: the index of the substring or size_t.max when nothing was found + */ +size_t find (dstring str, dstring sub, size_t start = 0) +{ + version (Tango) + { + size_t index = str.locatePattern(sub, start); + + if (index == str.length) + return size_t.max; + + return index; + } + + else + return std.string.find(str, sub, start); +} + +/** + * Compares to strings, ignoring case differences. Returns 0 if the content + * matches, less than zero if a is "less" than b, or greater than zero + * where a is "bigger". + * + * Params: + * a = the first array + * b = the second array + * end = the index where the comparision will end + * + * Returns: Returns 0 if the content matches, less than zero if a is + * "less" than b, or greater than zero where a is "bigger". + * + * See_Also: mambo.collection.array.compare + */ +int compareIgnoreCase (U = size_t) (string a, string b, U end = U.max) +{ + return a.toFold().compare(b.toFold(), end); +} + +/** + * Compares to strings, ignoring case differences. Returns 0 if the content + * matches, less than zero if a is "less" than b, or greater than zero + * where a is "bigger". + * + * Params: + * a = the first array + * b = the second array + * end = the index where the comparision will end + * + * Returns: Returns 0 if the content matches, less than zero if a is + * "less" than b, or greater than zero where a is "bigger". + * + * See_Also: mambo.collection.array.compare + */ +int compareIgnoreCase (U = size_t) (wstring a, wstring b, U end = U.max) +{ + return a.toFold().compare(b.toFold(), end); +} + +/** + * Compares to strings, ignoring case differences. Returns 0 if the content + * matches, less than zero if a is "less" than b, or greater than zero + * where a is "bigger". + * + * Params: + * a = the first array + * b = the second array + * end = the index where the comparision will end + * + * Returns: Returns 0 if the content matches, less than zero if a is + * "less" than b, or greater than zero where a is "bigger". + * + * See_Also: mambo.collection.array.compare + */ +int compareIgnoreCase (U = size_t) (dstring a, dstring b, U end = U.max) +{ + return a.toFold().compare(b.toFold(), end); +} + +/** + * Compares to strings, ignoring case differences. Returns 0 if the content + * matches, less than zero if a is "less" than b, or greater than zero + * where a is "bigger". + * + * Params: + * a = the first array + * b = the second array + * end = the index where the comparision will end + * + * Returns: Returns 0 if the content matches, less than zero if a is + * "less" than b, or greater than zero where a is "bigger". + * + * See_Also: mambo.string.compareIgnoreCase + */ +alias compareIgnoreCase icompare; + +/** + * Checks if the given character is a hexdecimal digit character. + * Hexadecimal digits are any of: 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F + * + * Params: + * ch = the character to be checked + * + * Returns: true if the given character is a hexdecimal digit character otherwise false + */ +bool isHexDigit (dchar ch) +{ + version (Tango) + { + switch (ch) + { + case 'A': return true; + case 'B': return true; + case 'C': return true; + case 'D': return true; + case 'E': return true; + case 'F': return true; + + case 'a': return true; + case 'b': return true; + case 'c': return true; + case 'd': return true; + case 'e': return true; + case 'f': return true; + + default: break; + } + + if (isDigit(ch)) + return true; + } + + else + if (isxdigit(ch) != 0) + return true; + + return false; +} + +/*version (Tango) +{ + string toString (string str) + { + return str; + } + + string toString (wstring str) + { + return tango.text.convert.Utf.toString(str); + } + + string toString (dstring str) + { + return tango.text.convert.Utf.toString(str); + } +}*/ + +version (Phobos) +{ + /** + * Converts the given string to C-style 0 terminated string. + * + * Params: + * str = the string to convert + * + * Returns: the a C-style 0 terminated string. + */ + dchar* toString32z (dstring str) + { + return (str ~ '\0').ptr; + } + + /** + * Converts a C-style 0 terminated string to a wstring + * + * Params: + * str = the C-style 0 terminated string + * + * Returns: the converted wstring + */ + wstring fromString16z (wchar* str) + { + return str[0 .. strlen(str)]; + } + + /** + * Converts a C-style 0 terminated string to a dstring + * Params: + * str = the C-style 0 terminated string + * + * Returns: the converted dstring + */ + dstring fromString32z (dchar* str) + { + return str[0 .. strlen(str)]; + } + + /** + * Gets the length of the given C-style 0 terminated string + * + * Params: + * str = the C-style 0 terminated string to get the length of + * + * Returns: the length of the string + */ + size_t strlen (wchar* str) + { + size_t i = 0; + + if (str) + while(*str++) + ++i; + + return i; + } + + /** + * Gets the length of the given C-style 0 terminated string + * + * Params: + * str = the C-style 0 terminated string to get the length of + * + * Returns: the length of the string + */ + size_t strlen (dchar* str) + { + size_t i = 0; + + if (str) + while(*str++) + ++i; + + return i; + } +} \ No newline at end of file