feat: add raw byte access methods and \x escape to String class

Add `byteAt(index)`, `codePointAt(index)`, and `bytes` sequence to String,
enabling direct byte-level manipulation of UTF-8 encoded strings. Introduce
`\x` hex escape sequence in string literals for specifying raw byte values.
Refactor Unicode escape parsing into a generic `readHexEscape` function
supporting variable digit counts. Implement `wrenUtf8Decode` utility for
decoding UTF-8 sequences from byte buffers. Add comprehensive tests for
`byteAt` including boundary conditions and error cases.
This commit is contained in:
Bob Nystrom
2015-03-28 03:44:07 +00:00
parent b7904a89c9
commit c3d0b66630
36 changed files with 402 additions and 15 deletions
@@ -0,0 +1,21 @@
// Bytes:
// 012345678
// Chars: sø mé ஃ
var bytes = "søméஃ".bytes
IO.print(bytes.iterate(null)) // expect: 0
IO.print("".bytes.iterate(null)) // expect: false
IO.print(bytes.iterate(0)) // expect: 1
IO.print(bytes.iterate(1)) // expect: 2
IO.print(bytes.iterate(2)) // expect: 3
IO.print(bytes.iterate(3)) // expect: 4
IO.print(bytes.iterate(4)) // expect: 5
IO.print(bytes.iterate(5)) // expect: 6
IO.print(bytes.iterate(6)) // expect: 7
IO.print(bytes.iterate(7)) // expect: 8
IO.print(bytes.iterate(8)) // expect: false
// Out of bounds.
IO.print(bytes.iterate(123)) // expect: false
IO.print(bytes.iterate(-1)) // expect: false
@@ -0,0 +1 @@
"str".bytes.iterate(12.34) // expect runtime error: Iterator must be an integer.
@@ -0,0 +1 @@
"str".bytes.iterate("not num") // expect runtime error: Iterator must be a number.
@@ -0,0 +1,24 @@
// Bytes:
// 012345678
// Chars: sø mé ஃ
var bytes = "søméஃ".bytes
IO.print(bytes.iteratorValue(0)) // expect: 115
IO.print(bytes.iteratorValue(1)) // expect: 195
IO.print(bytes.iteratorValue(2)) // expect: 184
IO.print(bytes.iteratorValue(3)) // expect: 109
IO.print(bytes.iteratorValue(4)) // expect: 195
IO.print(bytes.iteratorValue(5)) // expect: 169
IO.print(bytes.iteratorValue(6)) // expect: 224
IO.print(bytes.iteratorValue(7)) // expect: 174
IO.print(bytes.iteratorValue(8)) // expect: 131
IO.print(bytes.iteratorValue(-9)) // expect: 115
IO.print(bytes.iteratorValue(-8)) // expect: 195
IO.print(bytes.iteratorValue(-7)) // expect: 184
IO.print(bytes.iteratorValue(-6)) // expect: 109
IO.print(bytes.iteratorValue(-5)) // expect: 195
IO.print(bytes.iteratorValue(-4)) // expect: 169
IO.print(bytes.iteratorValue(-3)) // expect: 224
IO.print(bytes.iteratorValue(-2)) // expect: 174
IO.print(bytes.iteratorValue(-1)) // expect: 131
@@ -0,0 +1 @@
"abcd".bytes.iteratorValue(12.34) // expect runtime error: Index must be an integer.
@@ -0,0 +1 @@
"abcd".bytes.iteratorValue("not num") // expect runtime error: Index must be a number.
@@ -0,0 +1 @@
"abcd".bytes.iteratorValue(4) // expect runtime error: Index out of bounds.
@@ -0,0 +1 @@
"abcd".bytes.iteratorValue(-5) // expect runtime error: Index out of bounds.
@@ -0,0 +1,24 @@
// Bytes:
// 012345678
// Chars: sø mé ஃ
var bytes = "søméஃ".bytes
IO.print(bytes[0]) // expect: 115
IO.print(bytes[1]) // expect: 195
IO.print(bytes[2]) // expect: 184
IO.print(bytes[3]) // expect: 109
IO.print(bytes[4]) // expect: 195
IO.print(bytes[5]) // expect: 169
IO.print(bytes[6]) // expect: 224
IO.print(bytes[7]) // expect: 174
IO.print(bytes[8]) // expect: 131
IO.print(bytes[-9]) // expect: 115
IO.print(bytes[-8]) // expect: 195
IO.print(bytes[-7]) // expect: 184
IO.print(bytes[-6]) // expect: 109
IO.print(bytes[-5]) // expect: 195
IO.print(bytes[-4]) // expect: 169
IO.print(bytes[-3]) // expect: 224
IO.print(bytes[-2]) // expect: 174
IO.print(bytes[-1]) // expect: 131
@@ -0,0 +1 @@
"abcd".bytes[12.34] // expect runtime error: Index must be an integer.
@@ -0,0 +1 @@
"abcd".bytes["not num"] // expect runtime error: Index must be a number.
@@ -0,0 +1 @@
"abcd".bytes[4] // expect runtime error: Index out of bounds.
@@ -0,0 +1 @@
"abcd".bytes[-5] // expect runtime error: Index out of bounds.