Skip to content

Commit 454c938

Browse files
Implement compare for bytearray (#771)
Fixes #748 --------- Co-authored-by: Jonathan Immanuel Brachthäuser <[email protected]>
1 parent d9b8292 commit 454c938

File tree

5 files changed

+86
-7
lines changed

5 files changed

+86
-7
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Equal()
2+
Equal()
3+
Greater()
4+
Less()
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module examples/pos/bytearray_compare
2+
3+
import bytearray
4+
5+
def main() = {
6+
val b1 = fromString("Hey")
7+
val b2 = fromString("Hey")
8+
val b3 = fromString("He")
9+
val b4 = fromString("Heys")
10+
println(compareByteArray(b1, b1))
11+
println(compareByteArray(b1, b2))
12+
println(compareByteArray(b1, b3))
13+
println(compareByteArray(b1, b4))
14+
}

libraries/common/bytearray.effekt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,35 @@ extern js """
8888
bytes[index] = value;
8989
return $effekt.unit;
9090
}
91+
92+
function bytearray$compare(arr1, arr2) {
93+
const len = Math.min(arr1.length, arr2.length);
94+
95+
for (let i = 0; i < len; i++) {
96+
if (arr1[i] !== arr2[i]) {
97+
return arr1[i] < arr2[i] ? -1 : 1;
98+
}
99+
}
100+
101+
if (arr1.length !== arr2.length) {
102+
return arr1.length < arr2.length ? -1 : 1;
103+
} else {
104+
return 0;
105+
}
106+
}
91107
"""
108+
109+
extern pure def compareByteArrayImpl(b1: ByteArray, b2: ByteArray): Int =
110+
js "bytearray$compare(${b1}, ${b2})"
111+
llvm """
112+
%x = call %Int @c_bytearray_compare(%Pos ${b1}, %Pos ${b2})
113+
ret %Int %x
114+
"""
115+
116+
def compareByteArray(b1: ByteArray, b2: ByteArray): Ordering =
117+
compareByteArrayImpl(b1, b2) match {
118+
case -1 => Less()
119+
case 0 => Equal()
120+
case 1 => Greater()
121+
case _ => <{ "Impossible: ByteArray comparison returned invalid value!" }>
122+
}

libraries/llvm/bytearray.c

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,16 +152,45 @@ struct Pos c_bytearray_equal(const struct Pos left, const struct Pos right) {
152152
erasePositive(right);
153153
return BooleanFalse;
154154
}
155-
for (uint64_t j = 0; j < left_size; ++j) {
156-
if (c_bytearray_data(left)[j] != c_bytearray_data(right)[j]) {
157-
erasePositive(left);
158-
erasePositive(right);
159-
return BooleanFalse;
160-
}
155+
156+
int cmp = memcmp(c_bytearray_data(left), c_bytearray_data(right), left_size);
157+
erasePositive(left);
158+
erasePositive(right);
159+
return (cmp == 0 ? BooleanTrue : BooleanFalse);
160+
}
161+
162+
Int c_bytearray_compare(const struct Pos left, const struct Pos right) {
163+
uint64_t left_size = left.tag;
164+
uint64_t right_size = right.tag;
165+
uint64_t min_size = (left_size < right_size) ? left_size : right_size;
166+
167+
uint8_t* left_data = c_bytearray_data(left);
168+
uint8_t* right_data = c_bytearray_data(right);
169+
170+
if (left_data == right_data) {
171+
erasePositive(left);
172+
erasePositive(right);
173+
return 0;
161174
}
175+
176+
int cmp = memcmp(left_data, right_data, min_size);
177+
162178
erasePositive(left);
163179
erasePositive(right);
164-
return BooleanTrue;
180+
181+
if (cmp < 0) {
182+
return -1;
183+
} else if (cmp > 0) {
184+
return 1;
185+
}
186+
187+
if (left_size < right_size) {
188+
return -1;
189+
} else if (left_size > right_size) {
190+
return 1;
191+
}
192+
193+
return 0;
165194
}
166195

167196
// TODO deprecate

libraries/llvm/forward-declare-c.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ declare %Pos @c_bytearray_show_Double(double)
3737

3838
declare %Pos @c_bytearray_concatenate(%Pos, %Pos)
3939
declare %Pos @c_bytearray_equal(%Pos, %Pos)
40+
declare %Int @c_bytearray_compare(%Pos, %Pos)
4041

4142
declare %Pos @c_bytearray_substring(%Pos, i64, i64)
4243
declare %Int @c_bytearray_character_at(%Pos, i64)

0 commit comments

Comments
 (0)