Category talk:Wren-array: Difference between revisions

Content added Content deleted
(→‎Source code: Numerous changes to BitArray and ByteArray classes including new methods.)
(→‎Source code: Added CharArray class.)
Line 462: Line 462:
return toList.reduce("") { |acc, b| acc + digits[b>>4] + digits[b%16] }
return toList.reduce("") { |acc, b| acc + digits[b>>4] + digits[b%16] }
}
}
}

/*
CharArray represents a List<Char> whose size cannot be changed after it has been constructed
but whose elements can be changed. A 'Char' for this purpose is a unicode character with a
codepoint less than 256 (i.e. Latin-1). Internally, a ByteArray is used for storage.
This means that it only uses a quarter as much memory as a 'normal' List<Byte> (or about an
eighth as much as a List of single character strings) but is around 5 times slower to index.
*/
class CharArray is Sequence {
// Constructs a new CharArray of a given size and sets all elements to the same Char 'c'.
// As a ByteArray is used for storage, its size is rounded to the higher multiple of 4
// where necessary.
construct new(size, c) {
Check.char("c", c, 0, 255)
_a = ByteArray.new(size, c.codePoints[0])
_rng = 0..._a.count
}

// Constructs a new CharArray from a List<Char>, checking that the character values
// are valid. As a ByteArray is used for storage, its size is rounded to the
// higher multiple of 4 and filled out with space characters, where necessary.
construct fromList(a) {
Check.typedList("a", a, String, 1)
var size = (a.count / 4).ceil * 4
var ca = List.filled(size, 32)
for (i in 0...a.count) {
Check.char("a[%(i)]", a[i], 0, 255)
ca[i] = a[i].codePoints[0]
}
_a = ByteArray.fromList(ca, false)
_rng = 0...size
}

// Constructs a new ByteArray from a string of Chars.
// As a ByteArray is used for storage, its size is rounded to the higher
// multiple of 4 and filled out with space characters, where necessary.
construct fromString(s) {
Check.str("s", s, 1)
var size = (s.count / 4).ceil * 4
if (s.count < size) s = s + " " * (size - s.count)
_a = ByteArray.fromList(s.codePoints.toList, true)
_rng = 0...size
}

// As 'fromList' except constructs the new CharArray from an Array<Char> instead.
static fromArray(a) { fromList(a.toList) }

// Convenience version of 'new' which sets all elements to the space character.
static new(size) { new(size, " ") }

// Returns the number of elements in the CharArray.
count { _a.count }

// Creates a copy of the current instance.
copy() {
var ca = CharArray.new(count, " ")
for (i in _rng) ca[i] = this[i]
return ca
}

// Resets all elements of the CharArray to 'c'.
reset(c) {
Check.char("c", c, 0, 255)
_a.reset(c.codePoints[0])
}

// Gets the element at 'index'. If index is negative, it counts backwards
// from the end of the array where -1 is the last element.
// To maximize access speed, this method doesn't validate the index.
// Use the 'get' method instead if you need to do that.
[index] { String.fromCodePoint(_a[index]) }

// Sets the element at 'index'. Negative indices are treated as in the getter.
// To maximize access speed, this method doesn't validate the index nor the new value.
// Use the 'set' method instead if you need to do that.
[index]=(c) {
_a[index] = c.codePoints[0]
}

// As [index] method but validates the index.
get(index) { String.fromCodePoint(_a.get(index)) }

// As [index]=(c) method but validates the index and the new value.
set(index, c) {
Check.char("c", c)
_a.set(index, c.codePoints[0])
}
// Writes the string 's' into the CharArray buffer starting from index 'start'.
// Throws an error if 'start' is out of range, if 's' is too long to fit into
// the buffer or if it contains an invalid Char.
write(start, s) {
Check.str("s", s, 1)
var i = 0
for (cp in s.codePoints) {
_a.set(start + i, cp)
i = i + 1
}
}

// Returns the index of 'c' in the current instance or -1 if 'c' is not found.
// Throws an error if 'c' is an invalid Char.
indexOf(c) {
Check.char("c", c, 0, 255)
return _a.indexOf(c.codePoints[0])
}

// Returns the index of the last occurrence of 'c' in the current instance
// or -1 if 'c' is not found. Throws an error if 'c' is an invalid Char.
lastIndexOf(c) {
Check.char("c", c, 0, 255)
for (i in count-1..0) if (this[i] == c) return i
return -1
}

// Replaces all occurrences of 'old' by 'new' in the current instance
// and returns ['old', 'new'].
replace(old, new) {
Check.char("old", old, 0, 255)
Check.char("new", new, 0, 255)
for (i in _rng) if (this[i] == old) this[i] = new
return [old, new]
}

// Swaps the elements at index1 and index2 within the CharArray.
swap(index1, index2) {
var t = this[index1]
this[index1] = this[index2]
this[index2] = t
}

// Applies a function to each element of the CharArray.
apply(fn) {
Check.func("fn", fn, 1)
for (i in 0..._rng) this[i] = fn.call(this[i])
}

// Converts 'in place' all upper case Chars in this instance to lower case.
toLower {
for (i in _rng) {
var c = this[i].codePoints[0]
if ((c >= 65 && c <= 90) || (c >= 192 && c <= 214) || (c >= 216 && c <= 222)) {
this[i] = String.fromCodePoint(c + 32)
}
}
}

// Converts 'in place' all lower case Chars in this instance to upper case.
toUpper {
for (i in _rng) {
var c = this[i].codePoints[0]
if ((c >= 97 && c <= 122) || (c >= 224 && c <= 246) || (c >= 248 && c <= 254)) {
this[i] = String.fromCodePoint(c - 32)
}
}
}

// Capitalizes 'in place' the first Char of this instance.
capitalize {
var c = this[0].codePoints[0]
if ((c >= 97 && c <= 122) || (c >= 224 && c <= 246) || (c >= 248 && c <= 254)) {
this[0] = String.fromCodePoint(c - 32)
}
}

// Iterator protocol methods.
iterate(iterator) { _rng.iterate(iterator) }
iteratorValue(iterator) { this[iterator] }

// Returns a List<Char> using the normal 8 bytes for each element.
toList {
var chars = List.filled(count, null)
for (i in _rng) chars[i] = this[i]
return chars
}

// Returns an Array<Char> using the normal 8 bytes for each element.
toArray {
var chars = List.filled(count, null)
for (i in _rng) chars[i] = this[i]
return chars
}

// Returns a string representation of this instance, optionally trimming trailing
// whitespace (space, tab, carriage return, and line feed characters).
toString(trimEnd) {
var res = toList.join()
return trimEnd ? res : res.trimEnd()
}

// Returns a string representation of this instance with trailing whitespace removed.
toString { toList.join() }

// Returns a string representation of this instance as if it were a list.
toListString { toList.toString }
}</syntaxhighlight>
}</syntaxhighlight>