Skip to content

Commit 235176e

Browse files
author
Dr. Brandon Wiley
committed
Fixed Int / UInt conversion bugs
1 parent 35e36d8 commit 235176e

3 files changed

Lines changed: 358 additions & 62 deletions

File tree

ion/src/main/java/org/operatorfoundation/ion/squeeze.kt

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@ fun squeeze_int(v: Int): ByteArray
77
{
88
if (v == 0) return byteArrayOf(0)
99
val neg = v < 0
10-
var pos = if (neg) -v else v
10+
var pos = if (neg) {
11+
if (v == Int.MIN_VALUE) 0x80000000u
12+
else (-v).toUInt()
13+
} else v.toUInt()
14+
1115
val b = mutableListOf<Byte>()
12-
while (pos != 0)
16+
while (pos != 0u)
1317
{
14-
b.add(0, (pos and 0xFF).toByte())
15-
pos = pos ushr 8
18+
b.add(0, (pos and 0xFFu).toByte())
19+
pos = pos shr 8
1620
}
1721
var len = b.size.toByte()
1822
if (neg) len = (len.toInt() or 0x80).toByte()
@@ -54,11 +58,39 @@ fun expand_int(v: ByteArray): Pair<Varint, ByteArray>
5458
val data = v.sliceArray(1 until 1 + len)
5559
val rest = v.sliceArray(1 + len until v.size)
5660
var i = expand_int_from_bytes(data)
57-
if (neg) i = when (i)
61+
62+
if (neg)
5863
{
59-
is Varint.IonInt -> Varint.IonInt(-i.value)
60-
is Varint.IonInts -> Varint.IonInts(listOf(-i.value.first()) + i.value.drop(1))
64+
i = when (i)
65+
{
66+
is Varint.IonInt -> Varint.IonInt(-i.value)
67+
is Varint.IonInts ->
68+
{
69+
// Check if this bigint can actually fit as a negative Int
70+
if (i.value.size == 1)
71+
{
72+
val uval = i.value[0].toUInt()
73+
// Special case: 0x80000000 unsigned = Int.MIN_VALUE when negated
74+
if (uval == 0x80000000u)
75+
{
76+
Varint.IonInt(Int.MIN_VALUE)
77+
}
78+
else
79+
{
80+
// This shouldn't happen - expand_int_from_bytes should have returned IonInt
81+
// But if it does, add negative flag to bigint
82+
Varint.IonInts(listOf(1) + i.value)
83+
}
84+
}
85+
else
86+
{
87+
// Multiple limbs - add negative flag (1) to front
88+
Varint.IonInts(listOf(1) + i.value)
89+
}
90+
}
91+
}
6192
}
93+
6294
return Pair(i, rest)
6395
}
6496

@@ -106,8 +138,12 @@ fun expand_int_from_bytes(b: ByteArray): Varint
106138
}
107139
}
108140
}
109-
return if (ints.size == 1 && ints[0].toUInt() <= Int.MAX_VALUE.toUInt())
110-
Varint.IonInt(ints[0]) else Varint.IonInts(ints)
141+
return if (ints.size == 1 &&
142+
(ints[0].toUInt() <= Int.MAX_VALUE.toUInt() ||
143+
ints[0].toUInt() == 0x80000000u))
144+
Varint.IonInt(ints[0])
145+
else
146+
Varint.IonInts(ints)
111147
}
112148

113149
fun squeeze_floating(v: Floating): ByteArray = when (v)
@@ -160,33 +196,6 @@ fun squeeze_ints(v: List<Int>): ByteArray = if (v.isEmpty()) byteArrayOf(0) else
160196
squeeze_int(v.size).toList().plus(v.flatMap
161197
{ it: Int -> squeeze_int(it).toList() }).toByteArray()
162198

163-
fun expand_ints(v: ByteArray): Pair<List<Int>, ByteArray>
164-
{
165-
if (v.isEmpty()) return Pair(emptyList(), v)
166-
val (sz, rest1) = expand_int(v)
167-
return when (sz)
168-
{
169-
is Varint.IonInt ->
170-
{
171-
if (sz.value == 0) return Pair(emptyList(), rest1)
172-
var r = rest1
173-
val ints = mutableListOf<Int>()
174-
for (i in 0 until sz.value)
175-
{
176-
val (int, rest2) = expand_int(r)
177-
r = rest2
178-
when (int)
179-
{
180-
is Varint.IonInt -> ints.add(int.value)
181-
else -> return Pair(emptyList(), byteArrayOf())
182-
}
183-
}
184-
Pair(ints.toList(), r)
185-
}
186-
else -> Pair(emptyList(), byteArrayOf())
187-
}
188-
}
189-
190199
fun squeeze_floats(v: List<Float>): ByteArray = if (v.isEmpty()) byteArrayOf(0) else
191200
squeeze_int(v.size).toList().plus(v.flatMap
192201
{ it: Float -> squeeze_floating(Floating.IonFloat(it)).toList() }).toByteArray()

0 commit comments

Comments
 (0)