|
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