Skip to content

Commit 5831dc3

Browse files
committed
Improve some strings initiation
1 parent eb352b2 commit 5831dc3

File tree

2 files changed

+82
-65
lines changed

2 files changed

+82
-65
lines changed

struct.nim

Lines changed: 41 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import endians
21
import strutils
32
import tables
43

@@ -207,7 +206,7 @@ proc getString*(node: StructNode): string =
207206
return node.str
208207

209208
proc calcsize(format: string): int =
210-
var repeat = ""
209+
var repeat = newString(0)
211210
for i in 0..format.len-1:
212211
let f: char = format[i]
213212
if f in '0'..'9':
@@ -368,7 +367,7 @@ proc unpack*(fmt, buf: string): seq[StructNode] =
368367

369368
let size = calcsize(fmt)
370369
if buf.len < size:
371-
raise newException(ValueError, "unpack requires a string argument of length " & $size)
370+
raise newException(ValueError, "unpack requires a string argument of length " & $size & ", input: " & $buf.len)
372371

373372
var context = newStructContext()
374373
context.buffer = buf
@@ -418,83 +417,98 @@ proc unpack*(fmt, buf: string): seq[StructNode] =
418417
raise newException(ValueError, "bad char in struct format")
419418

420419
proc pack_char(vars: varargs[StructNode], ctx: StructContext): string =
421-
result = ""
420+
result = newString(ctx.repeat)
422421
for i in 0..ctx.repeat-1:
423422
assert vars[ctx.offset].kind == StructChar
424-
result &= $vars[ctx.offset].chr
423+
result[i] = vars[ctx.offset].chr
425424
ctx.offset += 1
426425

427426
proc pack_bool(vars: varargs[StructNode], ctx: StructContext): string =
428-
result = ""
427+
result = newString(ctx.repeat)
429428
for i in 0..ctx.repeat-1:
430429
assert vars[ctx.offset].kind == StructBool
431430
if vars[ctx.offset].bval == true:
432-
result &= "\x01"
431+
result[0] = '\x01'
433432
else:
434-
result &= "\x00"
433+
result[0] = '\x00'
435434
ctx.offset += 1
436435

437436
proc pack_16(vars: varargs[StructNode], ctx: StructContext): string =
438-
result = ""
437+
result = newString(2*ctx.repeat)
439438
for i in 0..ctx.repeat-1:
440439
case vars[ctx.offset].kind:
441440
of StructShort:
442-
result &= extract_16(vars[ctx.offset].sval, ctx.byteOrder)
441+
let value = extract_16(vars[ctx.offset].sval, ctx.byteOrder)
442+
result[i] = value[0]
443+
result[i+1] = value[1]
443444
of StructUShort:
444-
result &= extract_16(vars[ctx.offset].usval, ctx.byteOrder)
445+
let value = extract_16(vars[ctx.offset].usval, ctx.byteOrder)
446+
result[i] = value[0]
447+
result[i+1] = value[1]
445448
else:
446449
raise newException(ValueError, "not supported")
447450
ctx.offset += 1
448451

449452

450453
proc pack_32(vars: varargs[StructNode], ctx: StructContext): string =
451-
result = ""
454+
result = newString(4*ctx.repeat)
452455
for i in 0..ctx.repeat-1:
456+
var value: string
453457
case vars[ctx.offset].kind:
454458
of StructFloat:
455-
result &= extract_32(vars[ctx.offset].fval, ctx.byteOrder)
459+
value = extract_32(vars[ctx.offset].fval, ctx.byteOrder)
456460
of StructInt:
457-
result &= extract_32(vars[ctx.offset].ival, ctx.byteOrder)
461+
value = extract_32(vars[ctx.offset].ival, ctx.byteOrder)
458462
of StructUInt:
459-
result &= extract_32(vars[ctx.offset].uival, ctx.byteOrder)
463+
value = extract_32(vars[ctx.offset].uival, ctx.byteOrder)
460464
else:
461465
raise newException(ValueError, "not supported")
466+
467+
for j in 0..3:
468+
result[i+j] = value[j]
469+
462470
ctx.offset += 1
463471

464472
proc pack_64(vars: varargs[StructNode], ctx: StructContext): string =
465-
result = ""
473+
result = newString(8*ctx.repeat)
466474
for i in 0..ctx.repeat-1:
475+
var value: string
467476
case vars[ctx.offset].kind:
468477
of StructDouble:
469-
result &= extract_64(vars[ctx.offset].dval, ctx.byteOrder)
478+
value = extract_64(vars[ctx.offset].dval, ctx.byteOrder)
470479
of StructQuad:
471-
result &= extract_64(vars[ctx.offset].qval, ctx.byteOrder)
480+
value = extract_64(vars[ctx.offset].qval, ctx.byteOrder)
472481
of StructUQuad:
473-
result &= extract_64(vars[ctx.offset].uqval, ctx.byteOrder)
482+
value= extract_64(vars[ctx.offset].uqval, ctx.byteOrder)
474483
else:
475484
raise newException(ValueError, "not supported")
485+
486+
for j in 0..7:
487+
result[i+j] = value[j]
488+
476489
ctx.offset += 1
477490

478491
proc pack_string(vars: varargs[StructNode], ctx: StructContext): string =
479-
result = ""
492+
result = newString(ctx.repeat)
480493
assert vars[ctx.offset].kind == StructString
481-
result &= vars[ctx.offset].str[0..ctx.repeat-1]
482494

483-
var pad = ctx.repeat - vars[ctx.offset].str.len
484-
if pad > 0:
485-
result &= "\x00".repeat(pad)
495+
let value = vars[ctx.offset].str
496+
for i in 0..value.len-1:
497+
result[i] = value[i]
498+
if(value.len < ctx.repeat):
499+
for i in value.len..ctx.repeat-1:
500+
result[i] = '\x00'
486501

487502
ctx.offset += 1
488503

489504
proc pack_pad(ctx: StructContext): string =
490-
result = ""
505+
result = newString(ctx.repeat)
491506
for i in 0..ctx.repeat-1:
492-
result &= "\x00"
507+
result[i] = '\x00'
493508

494509
proc pack*(fmt: string, vars: varargs[StructNode]): string =
495510
result = ""
496511
var context = newStructContext()
497-
498512
var repeat = ""
499513
for i in 0..fmt.len-1:
500514
let f: char = fmt[i]
@@ -581,40 +595,3 @@ proc add*(s: Struct, str: string): Struct =
581595

582596
proc pack*(s: Struct): string =
583597
result = pack(s.fmt, s.vars)
584-
585-
586-
when isMainModule:
587-
let buf ="\x41\x42\x43\x44\x45\x01\x00\x07\x08\x01\x02\x03\x04\x0D\x00\x00\x00"
588-
let result1 = unpack("<5b2?h2i", buf)
589-
assert result1.len == 10
590-
assert result1[5].getBool == true
591-
assert result1[6].getBool == false
592-
echo result1
593-
let result2 = unpack(">5b2?hQ", buf)
594-
assert result2.len == 9
595-
echo result2
596-
echo unpack("<5b2?hQ", buf)
597-
598-
let buf2 = "\x40\xA6\x66\x66\xCD\xCC\xCC\xCC\xCC\xCC\x14\x40"
599-
let result3 = unpack(">fd", buf2)
600-
assert result3.len == 2
601-
echo result3
602-
let buf3 = "Viet Nam"
603-
let result4 = unpack("4sx3s", buf3)
604-
assert result4.len == 2
605-
assert result4[0].getString == "Viet"
606-
assert result4[1].getString == "Nam"
607-
echo result4
608-
609-
#echo pack("<fi?c", newStructFloat(5.2), newStructInt(8), newStructBool(true), newStructChar('a'))
610-
var format = "<ffb2?biQdH"
611-
var st = newStruct(format)
612-
discard st.add(5.2'f32).add(6.4'f32).add('A').add(true).add(false)
613-
var out1 = st.add('a').add(8'i32).add(8589934591).add(10.4'f64).add(32767.int16).pack()
614-
echo out1
615-
echo unpack(format, out1)
616-
617-
assert newStruct("h").add(32767.int16).pack() == "\xff\x7f"
618-
619-
assert newStruct("4s3s").add("Viet").add("Nam").pack() == "VietNam"
620-
assert newStruct("6sxxxxx3s").add("Viet").add("Nam").pack().len == 14

test.nim

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,48 @@
11
# >>> from struct import *
22
import struct
33

4+
let buf ="\x41\x42\x43\x44\x45\x01\x00\x07\x08\x01\x02\x03\x04\x0D\x00\x00\x00"
5+
let result1 = unpack("<5b2?h2i", buf)
6+
assert result1.len == 10
7+
assert result1[5].getBool == true
8+
assert result1[6].getBool == false
9+
echo result1
10+
let result2 = unpack(">5b2?hQ", buf)
11+
assert result2.len == 9
12+
echo result2
13+
echo unpack("<5b2?hQ", buf)
14+
15+
let buf2 = "\x40\xA6\x66\x66\xCD\xCC\xCC\xCC\xCC\xCC\x14\x40"
16+
let result3 = unpack(">fd", buf2)
17+
assert result3.len == 2
18+
echo result3
19+
let buf3 = "Viet Nam"
20+
let result4 = unpack("4sx3s", buf3)
21+
assert result4.len == 2
22+
assert result4[0].getString == "Viet"
23+
assert result4[1].getString == "Nam"
24+
echo result4
25+
26+
#echo pack("<fi?c", newStructFloat(5.2), newStructInt(8), newStructBool(true), newStructChar('a'))
27+
var format = "<ffb2?biQdH"
28+
var st = newStruct(format)
29+
discard st.add(5.2'f32).add(6.4'f32).add('A').add(true).add(false)
30+
var out1 = st.add('a').add(8'i32).add(8589934591).add(10.4'f64).add(32767.int16).pack()
31+
echo out1
32+
echo unpack(format, out1)
33+
34+
assert newStruct("h").add(32767.int16).pack() == "\xff\x7f"
35+
36+
assert newStruct("4s3s").add("Viet").add("Nam").pack() == "VietNam"
37+
38+
assert newStruct("5s6s4s").add("Ho").add("Chi").add("Minh").pack() == "Ho\x00\x00\x00Chi\x00\x00\x00Minh"
39+
40+
assert newStruct("6sxxxxx3s").add("Viet").add("Nam").pack().len == 14
41+
42+
43+
444
# >>> pack('hhi', 1, 2, 3)
5-
var st = newStruct("hhi")
45+
st = newStruct("hhi")
646
var output = st.add(1.int16).add(2.int16).add(3.int32).pack()
747

848
# alternative way to pack

0 commit comments

Comments
 (0)