|
1 | | -import endians |
2 | 1 | import strutils |
3 | 2 | import tables |
4 | 3 |
|
@@ -207,7 +206,7 @@ proc getString*(node: StructNode): string = |
207 | 206 | return node.str |
208 | 207 |
|
209 | 208 | proc calcsize(format: string): int = |
210 | | - var repeat = "" |
| 209 | + var repeat = newString(0) |
211 | 210 | for i in 0..format.len-1: |
212 | 211 | let f: char = format[i] |
213 | 212 | if f in '0'..'9': |
@@ -368,7 +367,7 @@ proc unpack*(fmt, buf: string): seq[StructNode] = |
368 | 367 |
|
369 | 368 | let size = calcsize(fmt) |
370 | 369 | 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) |
372 | 371 |
|
373 | 372 | var context = newStructContext() |
374 | 373 | context.buffer = buf |
@@ -418,83 +417,98 @@ proc unpack*(fmt, buf: string): seq[StructNode] = |
418 | 417 | raise newException(ValueError, "bad char in struct format") |
419 | 418 |
|
420 | 419 | proc pack_char(vars: varargs[StructNode], ctx: StructContext): string = |
421 | | - result = "" |
| 420 | + result = newString(ctx.repeat) |
422 | 421 | for i in 0..ctx.repeat-1: |
423 | 422 | assert vars[ctx.offset].kind == StructChar |
424 | | - result &= $vars[ctx.offset].chr |
| 423 | + result[i] = vars[ctx.offset].chr |
425 | 424 | ctx.offset += 1 |
426 | 425 |
|
427 | 426 | proc pack_bool(vars: varargs[StructNode], ctx: StructContext): string = |
428 | | - result = "" |
| 427 | + result = newString(ctx.repeat) |
429 | 428 | for i in 0..ctx.repeat-1: |
430 | 429 | assert vars[ctx.offset].kind == StructBool |
431 | 430 | if vars[ctx.offset].bval == true: |
432 | | - result &= "\x01" |
| 431 | + result[0] = '\x01' |
433 | 432 | else: |
434 | | - result &= "\x00" |
| 433 | + result[0] = '\x00' |
435 | 434 | ctx.offset += 1 |
436 | 435 |
|
437 | 436 | proc pack_16(vars: varargs[StructNode], ctx: StructContext): string = |
438 | | - result = "" |
| 437 | + result = newString(2*ctx.repeat) |
439 | 438 | for i in 0..ctx.repeat-1: |
440 | 439 | case vars[ctx.offset].kind: |
441 | 440 | 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] |
443 | 444 | 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] |
445 | 448 | else: |
446 | 449 | raise newException(ValueError, "not supported") |
447 | 450 | ctx.offset += 1 |
448 | 451 |
|
449 | 452 |
|
450 | 453 | proc pack_32(vars: varargs[StructNode], ctx: StructContext): string = |
451 | | - result = "" |
| 454 | + result = newString(4*ctx.repeat) |
452 | 455 | for i in 0..ctx.repeat-1: |
| 456 | + var value: string |
453 | 457 | case vars[ctx.offset].kind: |
454 | 458 | of StructFloat: |
455 | | - result &= extract_32(vars[ctx.offset].fval, ctx.byteOrder) |
| 459 | + value = extract_32(vars[ctx.offset].fval, ctx.byteOrder) |
456 | 460 | of StructInt: |
457 | | - result &= extract_32(vars[ctx.offset].ival, ctx.byteOrder) |
| 461 | + value = extract_32(vars[ctx.offset].ival, ctx.byteOrder) |
458 | 462 | of StructUInt: |
459 | | - result &= extract_32(vars[ctx.offset].uival, ctx.byteOrder) |
| 463 | + value = extract_32(vars[ctx.offset].uival, ctx.byteOrder) |
460 | 464 | else: |
461 | 465 | raise newException(ValueError, "not supported") |
| 466 | + |
| 467 | + for j in 0..3: |
| 468 | + result[i+j] = value[j] |
| 469 | + |
462 | 470 | ctx.offset += 1 |
463 | 471 |
|
464 | 472 | proc pack_64(vars: varargs[StructNode], ctx: StructContext): string = |
465 | | - result = "" |
| 473 | + result = newString(8*ctx.repeat) |
466 | 474 | for i in 0..ctx.repeat-1: |
| 475 | + var value: string |
467 | 476 | case vars[ctx.offset].kind: |
468 | 477 | of StructDouble: |
469 | | - result &= extract_64(vars[ctx.offset].dval, ctx.byteOrder) |
| 478 | + value = extract_64(vars[ctx.offset].dval, ctx.byteOrder) |
470 | 479 | of StructQuad: |
471 | | - result &= extract_64(vars[ctx.offset].qval, ctx.byteOrder) |
| 480 | + value = extract_64(vars[ctx.offset].qval, ctx.byteOrder) |
472 | 481 | of StructUQuad: |
473 | | - result &= extract_64(vars[ctx.offset].uqval, ctx.byteOrder) |
| 482 | + value= extract_64(vars[ctx.offset].uqval, ctx.byteOrder) |
474 | 483 | else: |
475 | 484 | raise newException(ValueError, "not supported") |
| 485 | + |
| 486 | + for j in 0..7: |
| 487 | + result[i+j] = value[j] |
| 488 | + |
476 | 489 | ctx.offset += 1 |
477 | 490 |
|
478 | 491 | proc pack_string(vars: varargs[StructNode], ctx: StructContext): string = |
479 | | - result = "" |
| 492 | + result = newString(ctx.repeat) |
480 | 493 | assert vars[ctx.offset].kind == StructString |
481 | | - result &= vars[ctx.offset].str[0..ctx.repeat-1] |
482 | 494 |
|
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' |
486 | 501 |
|
487 | 502 | ctx.offset += 1 |
488 | 503 |
|
489 | 504 | proc pack_pad(ctx: StructContext): string = |
490 | | - result = "" |
| 505 | + result = newString(ctx.repeat) |
491 | 506 | for i in 0..ctx.repeat-1: |
492 | | - result &= "\x00" |
| 507 | + result[i] = '\x00' |
493 | 508 |
|
494 | 509 | proc pack*(fmt: string, vars: varargs[StructNode]): string = |
495 | 510 | result = "" |
496 | 511 | var context = newStructContext() |
497 | | - |
498 | 512 | var repeat = "" |
499 | 513 | for i in 0..fmt.len-1: |
500 | 514 | let f: char = fmt[i] |
@@ -581,40 +595,3 @@ proc add*(s: Struct, str: string): Struct = |
581 | 595 |
|
582 | 596 | proc pack*(s: Struct): string = |
583 | 597 | 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 |
0 commit comments