Skip to content

Commit 549d9d8

Browse files
author
Huy Doan
committed
fix wrong offset for unpack number values with repeat, closes #6
1 parent 05ae214 commit 549d9d8

File tree

5 files changed

+45
-38
lines changed

5 files changed

+45
-38
lines changed

Diff for: struct.nim renamed to src/struct.nim

+36-35
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,13 @@
88

99
## This module implements Python struct for Nim
1010

11-
import strutils
12-
import endians
13-
import macros
11+
import strutils, endians, macros
1412

1513
type
1614
SomeByte* = byte|char|int8|uint8
17-
1815
StructError* = object of OSError
1916

20-
StructKind* = enum ## possible JSON node types
17+
StructKind* = enum
2118
StructChar,
2219
StructBool,
2320
StructInt,
@@ -48,9 +45,8 @@ type
4845
repeat: int
4946
index: int
5047

51-
5248
const
53-
VERSION* = "0.1.1"
49+
STRUCT_VERSION* = "0.2.2"
5450

5551
proc getSize(t: char): int {.noSideEffect, inline.} =
5652
case t
@@ -64,8 +60,7 @@ proc newStructChar*(c: char): StructNode = StructNode(kind: StructChar, ch: c)
6460

6561
proc newStructBool*(b: bool): StructNode = StructNode(kind: StructBool, bval: b)
6662

67-
proc newStructInt*[T: SomeInteger](i: T): StructNode =
68-
result = StructNode(kind: StructInt, num: i.BiggestInt)
63+
proc newStructInt*[T: SomeInteger](i: T): StructNode = StructNode(kind: StructInt, num: i.BiggestInt)
6964

7065
proc newStructFloat*(d: BiggestFloat): StructNode = StructNode(kind: StructFloat, fval: d)
7166

@@ -150,15 +145,15 @@ proc parse_prefix(ctx: var StructContext, f: char) =
150145

151146
proc load_16*[T: SomeByte](a, b: T, endian: Endianness): int16 {.inline.} =
152147
if endian == littleEndian:
153-
a.int16 + b.int16 shl 8
148+
a.int16 or b.int16 shl 8
154149
else:
155-
b.int16 + a.int16 shl 8
150+
b.int16 or a.int16 shl 8
156151

157152
proc load_32*[T: SomeByte](a, b, c, d: T, endian: Endianness): int32 {.inline.} =
158153
if endian == littleEndian:
159-
a.int32 + b.int32 shl 8 + c.int32 shl 16 + d.int32 shl 24
154+
a.int32 or b.int32 shl 8 or c.int32 shl 16 or d.int32 shl 24
160155
else:
161-
d.int32 + c.int32 shl 8 + b.int32 shl 16 + a.int32 shl 24
156+
d.int32 or c.int32 shl 8 or b.int32 shl 16 or a.int32 shl 24
162157

163158
proc load_32f*[T: SomeByte](a, b, c, d: T, endian: Endianness): float32 {.inline.} =
164159
var o = cast[cstring](addr result)
@@ -211,42 +206,52 @@ proc extract_64*[T:float64|int64|uint64](v: T, endian: Endianness): array[0..7,
211206
bigEndian64(addr result, addr v)
212207

213208
proc unpack_char(vars: var seq[StructNode], ctx: var StructContext) =
214-
for i in 0..ctx.repeat-1:
209+
for i in 0..<ctx.repeat:
215210
vars.add(newStructChar(ctx.buffer[ctx.offset]))
216211
inc(ctx.offset)
217212

218213
proc unpack_bool(vars: var seq[StructNode], ctx: var StructContext) =
219-
for i in 0..ctx.repeat-1:
214+
for i in 0..<ctx.repeat:
220215
vars.add(newStructBool(ctx.buffer[ctx.offset].bool))
221216
inc(ctx.offset)
222217

223218
proc unpack_short(vars: var seq[StructNode], ctx: var StructContext, f: char, signed: bool = false) =
224-
for i in 0..ctx.repeat-1:
225-
var value = load_16(ctx.buffer[ctx.offset], ctx.buffer[ctx.offset+1], ctx.byteOrder)
219+
for i in 0..<ctx.repeat:
220+
let
221+
offset = ctx.offset + i * 2
222+
value = load_16(ctx.buffer[offset], ctx.buffer[offset+1], ctx.byteOrder)
226223
vars.add(newStructInt(value))
227224
inc(ctx.offset, ctx.repeat * getSize(f))
228225

229226
proc unpack_int(vars: var seq[StructNode], ctx: var StructContext, f: char, signed: bool = false) =
230-
for i in 0..ctx.repeat-1:
231-
var value = load_32(ctx.buffer[ctx.offset], ctx.buffer[ctx.offset+1], ctx.buffer[ctx.offset+2], ctx.buffer[ctx.offset+3], ctx.byteOrder)
227+
for i in 0..<ctx.repeat:
228+
let
229+
offset = ctx.offset + i * 4
230+
value = load_32(ctx.buffer[offset], ctx.buffer[offset+1], ctx.buffer[offset+2], ctx.buffer[offset+3], ctx.byteOrder)
232231
vars.add(newStructInt(value))
233232
inc(ctx.offset, ctx.repeat * getSize(f))
234233

235234
proc unpack_quad(vars: var seq[StructNode], ctx: var StructContext, f: char, signed: bool = false) =
236-
for i in 0..ctx.repeat-1:
237-
var value = load_64(ctx.buffer[ctx.offset..ctx.offset+7], ctx.byteOrder)
235+
for i in 0..<ctx.repeat:
236+
let
237+
offset = ctx.offset + i * 8
238+
value = load_64(ctx.buffer[offset..offset+7], ctx.byteOrder)
238239
vars.add(newStructInt(value))
239240
inc(ctx.offset, ctx.repeat * getSize(f))
240241

241242
proc unpack_float(vars: var seq[StructNode], ctx: var StructContext) =
242-
for i in 0..ctx.repeat-1:
243-
var value = load_32f(ctx.buffer[ctx.offset], ctx.buffer[ctx.offset+1], ctx.buffer[ctx.offset+2], ctx.buffer[ctx.offset+3], ctx.byteOrder)
243+
for i in 0..<ctx.repeat:
244+
let
245+
offset = ctx.offset + i * 4
246+
value = load_32f(ctx.buffer[offset], ctx.buffer[offset+1], ctx.buffer[offset+2], ctx.buffer[offset+3], ctx.byteOrder)
244247
vars.add(newStructFloat(value.float32))
245248
inc(ctx.offset, ctx.repeat * getSize('f'))
246249

247250
proc unpack_double(vars: var seq[StructNode], ctx: var StructContext) =
248-
for i in 0..ctx.repeat-1:
249-
var value = load_64f(ctx.buffer[ctx.offset..ctx.offset+7], ctx.byteOrder)
251+
for i in 0..<ctx.repeat:
252+
let
253+
offset = ctx.offset + i * 8
254+
value = load_64f(ctx.buffer[offset..offset+7], ctx.byteOrder)
250255
vars.add(newStructFloat(value))
251256
inc(ctx.offset, ctx.repeat * getSize('d'))
252257

@@ -273,7 +278,6 @@ proc unpack*(fmt, buf: string): seq[StructNode] =
273278
var repeat = newString(0)
274279
for i in 0..fmt.len-1:
275280
let f: char = fmt[i]
276-
277281
if f in '0'..'9':
278282
repeat.add($f)
279283
continue
@@ -315,14 +319,14 @@ proc unpack*(fmt, buf: string): seq[StructNode] =
315319
raise newException(ValueError, "bad char in struct format")
316320

317321
proc pack_char(result: var string, vars: openarray[StructNode], ctx: var StructContext) =
318-
for i in 0..ctx.repeat-1:
322+
for i in 0..<ctx.repeat:
319323
assert vars[ctx.offset].kind == StructChar
320324
result[ctx.index + i] = vars[ctx.offset].ch
321325
inc(ctx.offset)
322326
inc(ctx.index, ctx.repeat)
323327

324328
proc pack_bool(result: var string, vars: openarray[StructNode], ctx: var StructContext) =
325-
for i in 0..ctx.repeat-1:
329+
for i in 0..<ctx.repeat:
326330
assert vars[ctx.offset].kind == StructBool
327331
if vars[ctx.offset].bval == true:
328332
result[ctx.index] = '\x01'
@@ -333,7 +337,7 @@ proc pack_bool(result: var string, vars: openarray[StructNode], ctx: var StructC
333337
inc(ctx.index, ctx.repeat)
334338

335339
proc pack_16(result: var string, vars: openarray[StructNode], ctx: var StructContext, signed: bool) =
336-
for i in 0..ctx.repeat-1:
340+
for i in 0..<ctx.repeat:
337341
let value =
338342
if signed:
339343
extract_16(vars[ctx.offset].num.int16, ctx.byteOrder)
@@ -347,7 +351,7 @@ proc pack_16(result: var string, vars: openarray[StructNode], ctx: var StructCon
347351
inc(ctx.index, 2 * ctx.repeat)
348352

349353
proc pack_32(result: var string, vars: openarray[StructNode], ctx: var StructContext, signed: bool) =
350-
for i in 0..ctx.repeat-1:
354+
for i in 0..<ctx.repeat:
351355
var value: array[0..3, char]
352356
case vars[ctx.offset].kind:
353357
of StructFloat:
@@ -367,8 +371,7 @@ proc pack_32(result: var string, vars: openarray[StructNode], ctx: var StructCon
367371
inc(ctx.index, 4 * ctx.repeat)
368372

369373
proc pack_64(result: var string, vars: openarray[StructNode], ctx: var StructContext, signed: bool) =
370-
371-
for i in 0..ctx.repeat-1:
374+
for i in 0..<ctx.repeat:
372375
var value: array[0..7, char]
373376
case vars[ctx.offset].kind:
374377
of StructFloat:
@@ -398,13 +401,11 @@ proc pack_string(result: var string, vars: openarray[StructNode], ctx: var Struc
398401
result[ctx.index + i] = '\x00'
399402

400403
inc(ctx.offset)
401-
402404
inc(ctx.index, ctx.repeat)
403405

404406
proc pack_pad(result: var string, ctx: var StructContext) =
405-
for i in 0..ctx.repeat-1:
407+
for i in 0..<ctx.repeat:
406408
result[ctx.index + i] = '\x00'
407-
408409
inc(ctx.index, ctx.repeat)
409410

410411
proc pack*(fmt: string, vars: varargs[StructNode]): string =

Diff for: struct.nimble

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
[Package]
22
name = "struct"
3-
version = "0.2.1"
3+
version = "0.2.2"
44
author = "Huy Doan"
55
description = "Python-like 'struct' for Nim"
66
license = "MIT"
7-
7+
srcDir = "src"
88
skipFiles = "test.nim"
99

1010
[Deps]

Diff for: tests/nim.cfg

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--path:"../src"

Diff for: test.nim renamed to tests/test.nim

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,4 @@ assert struct.unpack(">H", parseHexStr("FFFF"))[0].getShort == int16(-1)
5454
assert struct.unpack(">H", parseHexStr("FFFF"))[0].getUShort == 65535
5555

5656
assert struct.unpack(">I", parseHexStr("FFFFFFFF"))[0].getInt == int32(-1)
57-
assert struct.unpack(">I", parseHexStr("FFFFFFFF"))[0].getUInt == uint32(4294967295)
57+
assert struct.unpack(">I", parseHexStr("FFFFFFFF"))[0].getUInt == uint32(4294967295)

Diff for: tests/test_issue6.nim

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import struct
2+
3+
let val = unpack(">3I", "Hello World ")
4+
echo val
5+
assert $val == "@[1214606444, 1864390511, 1919706144]"

0 commit comments

Comments
 (0)