Skip to content

Commit 7224898

Browse files
committed
Started fixing bugs relating to the writing part. Also thinking of support for endianness
1 parent ea42c0b commit 7224898

File tree

1 file changed

+116
-27
lines changed

1 file changed

+116
-27
lines changed

binaryparse.nim

Lines changed: 116 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,44 @@ macro typeGetter*(body: typed): untyped =
109109
## Helper macro to get the return type of custom parsers
110110
body.getTypeImpl[0][1][0][0]
111111

112+
template writeDataBE*(stream: Stream, buffer: pointer, size: int) =
113+
for i in 0..<size:
114+
let tmp = cast[pointer](cast[int](buffer) + ((size-1)-i))
115+
stream.writeData(tmp, 1)
116+
117+
template writeDataLE*(stream: Stream, buffer: pointer, size: int) =
118+
for i in 0..<size:
119+
let tmp = cast[pointer](cast[int](buffer) + i)
120+
stream.writeData(tmp, 1)
121+
122+
template readDataBE*(stream: Stream, buffer: pointer, size: int) =
123+
for i in 0..<size:
124+
let tmp = cast[pointer](cast[int](buffer) + ((size-1)-i))
125+
if stream.readData(tmp, 1) != 1:
126+
raise newException(IOError,
127+
"Unable to read the requested amount of bytes from file")
128+
129+
template readDataLE*(stream: Stream, buffer: pointer, size: int) =
130+
for i in 0..<size:
131+
let tmp = cast[pointer](cast[int](buffer) + i)
132+
if stream.readData(tmp, 1) != 1:
133+
raise newException(IOError,
134+
"Unable to read the requested amount of bytes from file")
135+
136+
template peekDataBE*(stream: Stream, buffer: pointer, size: int) =
137+
for i in 0..<size:
138+
let tmp = cast[pointer](cast[int](buffer) + ((size-1)-i))
139+
if stream.peekData(tmp, 1) != 1:
140+
raise newException(IOError,
141+
"Unable to peek the requested amount of bytes from file")
142+
143+
template peekDataLE*(stream: Stream, buffer: pointer, size: int) =
144+
for i in 0..<size:
145+
let tmp = cast[pointer](cast[int](buffer) + i)
146+
if stream.peekData(tmp, 1) != 1:
147+
raise newException(IOError,
148+
"Unable to peek the requested amount of bytes from file")
149+
112150
proc replace(node: var NimNode, seenFields: seq[string]) =
113151
if node.kind == nnkIdent:
114152
if $node.ident in seenFields:
@@ -305,9 +343,17 @@ proc createWriteStatement(
305343
result = newStmtList()
306344
if info.size mod 8 == 0:
307345
result.add(quote do:
308-
`stream`.writeData(`field`.addr, `write`)
346+
`stream`.writeDataLE(`field`.addr, `write`)
309347
)
310348
else:
349+
if tmpVar == nil:
350+
raise newException(AssertionError, "tmpVar cannot be nil when size mod" &
351+
"8 != 0 and info.kind = " & $info.kind)
352+
if tmpVar != nil and skip != 0 and skip != size div 8:
353+
let addspace = (size div 8) * 8
354+
result.add(quote do:
355+
`tmpVar` = `tmpVar` shl `addspace`
356+
)
311357
if shift > 0:
312358
result.add(quote do:
313359
`tmpVar` = `tmpVar` or (`field` and `mask`) shl `shift`
@@ -319,16 +365,19 @@ proc createWriteStatement(
319365
if skip != 0:
320366
if tmpVar != nil:
321367
result.add(quote do:
322-
`stream`.writeData(`tmpVar`.addr, `skip`)
368+
`stream`.writeDataLE(`tmpVar`.addr, `skip`)
369+
`tmpVar` = 0
323370
)
324371
else:
325372
result.add(quote do:
326-
`stream`.writeData(`field`.addr, `skip`)
373+
`stream`.writeDataLE(`field`.addr, `skip`)
327374
)
375+
#[
328376
if offset + size > (offset + size) mod 8:
329377
result.add(quote do:
330378
`tmpVar` = (`field` and `mask`) shl (8 + `shift`)
331379
)
380+
]#
332381
offset += size
333382
offset = offset mod 8
334383

@@ -345,14 +394,16 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
345394
res = newIdentNode("result")
346395
stream = newIdentNode("stream")
347396
input = newIdentNode("input")
397+
tmpVar = genSym(nskVar)
348398
#input = genSym(nskParam)
349399
var
350400
inner = newStmtList()
351401
writer = newStmtList()
352402
tupleMeat = nnkTupleTy.newNimNode
353403
i = 0
354404
field = 0
355-
offset: BiggestInt = 0
405+
readOffset: BiggestInt = 0
406+
writeOffset: BiggestInt = 0
356407
seenFields = newSeq[string]()
357408
extraParams = newSeq[NimNode]()
358409
while i < paramsAndDef.len - 1:
@@ -402,8 +453,8 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
402453
tupleMeat.add(nnkIdentDefs.newTree(resfield, kind, newEmptyNode()))
403454
if $info.kind == "string":
404455
info.size = ($magic).len
405-
inner.add(createReadStatement(sym, info, offset, stream))
406-
writer.add(createWriteStatement(writeSym, info, offset, stream))
456+
inner.add(createReadStatement(sym, info, readOffset, stream))
457+
writer.add(createWriteStatement(writeSym, info, writeOffset, stream))
407458
inner.add(quote do:
408459
if `sym` != `magic`:
409460
raise newException(MagicError,
@@ -424,27 +475,28 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
424475
)
425476
let
426477
ii = genSym(nskVar)
427-
tmpVar = genSym(nskVar)
428-
startOffset = offset
478+
#tmpVar = genSym(nskVar)
479+
startReadOffset = readOffset
480+
startWriteOffset = writeOffset
429481
var
430482
readFieldOps = @[
431483
createReadStatement(
432-
(quote do: `res`[`field`][`ii`]), info, offset, stream
484+
(quote do: `res`[`field`][`ii`]), info, readOffset, stream
433485
)
434486
]
435-
while startOffset != offset:
487+
while startReadOffset != readOffset:
436488
readFieldOps.add createReadStatement(
437-
(quote do: `res`[`field`][`ii`]), info, offset, stream
489+
(quote do: `res`[`field`][`ii`]), info, readOffset, stream
438490
)
439491
var
440492
writeFieldOps = @[
441493
createWriteStatement(
442-
(quote do: `input`[`field`][`ii`]), info, offset, stream, tmpVar
494+
(quote do: `input`[`field`][`ii`]), info, writeOffset, stream, tmpVar
443495
)
444496
]
445-
while startOffset != offset:
497+
while startWriteOffset != writeOffset:
446498
writeFieldOps.add createWriteStatement(
447-
(quote do: `input`[`field`][`ii`]), info, offset, stream, tmpVar
499+
(quote do: `input`[`field`][`ii`]), info, writeOffset, stream, tmpVar
448500
)
449501
let
450502
readFieldCount = readFieldOps.len
@@ -523,7 +575,7 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
523575
magic = endMagic[1][0][1]
524576
endKind = endInfo.kind
525577
peek = newIdentNode("peek" & $endInfo.kind)
526-
bitInfo = getBitInfo(endInfo.size, offset)
578+
bitInfo = getBitInfo(endInfo.size, readOffset)
527579
shift = bitInfo.shift
528580
mask = bitInfo.mask
529581
inner.add(quote do:
@@ -548,7 +600,8 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
548600
`readField`
549601
inc `ii`
550602
)
551-
offset = 0
603+
readOffset = 0
604+
writeOffset = 0
552605
of nnkIdent:
553606
if $def[1][0].ident == "_":
554607
if def[0].kind == nnkIdent and $def[0].ident == "s":
@@ -560,20 +613,28 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
560613
)
561614
dec field
562615
else:
563-
let jump =
564-
if size mod 8 != 0:
565-
if (offset+size) mod 8 < offset+size: 1 else: 0
566-
else:
567-
0
616+
let
617+
readJump =
618+
if size mod 8 != 0:
619+
if (readOffset+size) mod 8 < readOffset+size: 1 else: 0
620+
else:
621+
0
622+
writeJump =
623+
if size mod 8 != 0:
624+
if (writeOffset+size) mod 8 < writeOffset+size: 1 else: 0
625+
else:
626+
0
568627
writer.add(quote do:
569-
for i in 0..<(`size` div 8 + `jump`):
628+
for i in 0..<(`size` div 8 + `writeJump`):
570629
`stream`.write(0'u8)
571630
)
572631
inner.add(quote do:
573-
`stream`.setPosition(`stream`.getPosition()+`size` div 8 + `jump`)
632+
`stream`.setPosition(`stream`.getPosition()+`size` div 8 + `readJump`)
574633
)
575-
offset += size
576-
offset = offset mod 8
634+
readOffset += size
635+
readOffset = readOffset mod 8
636+
writeOffset += size
637+
writeOffset = writeOffset mod 8
577638
dec field
578639
else:
579640
let
@@ -583,12 +644,14 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
583644
tupleMeat.add(nnkIdentDefs.newTree(resfield, kind, newEmptyNode()))
584645
inner.add(
585646
createReadStatement(
586-
(quote do: `res`[`field`]), info, offset, stream
647+
(quote do: `res`[`field`]), info, readOffset, stream
587648
)
588649
)
650+
echo $sym
651+
echo "(" & $info.size & ", " & $writeOffset & ") -> " & $getBitInfo(info.size, writeOffset)
589652
writer.add(
590653
createWriteStatement(
591-
(quote do: `input`[`field`]), info, offset, stream
654+
(quote do: `input`[`field`]), info, writeOffset, stream, tmpVar
592655
)
593656
)
594657
else:
@@ -611,6 +674,7 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
611674
proc `readerName`(`stream`: Stream): `tupleMeat` =
612675
`inner`
613676
proc `writerName`(`stream`: Stream, `input`: var `tupleMeat`) =
677+
var `tmpVar`: int64 = 0
614678
`writer`
615679
let `name` = (get: `readerName`, put: `writerName`)
616680
for p in extraParams:
@@ -636,6 +700,12 @@ when isMainModule:
636700
createParser(tert):
637701
3: test[8]
638702

703+
createParser(ccsds_header):
704+
u3: version
705+
u1: packet_type
706+
u1: secondary_header
707+
u11: apid
708+
639709
block parse:
640710
var fs = newFileStream("data.hex", fmRead)
641711
defer: fs.close()
@@ -651,3 +721,22 @@ when isMainModule:
651721
var data: typeGetter(tert)
652722
data.test = @[1'i8, 2, 3, 4, 5, 6, 7, 0]
653723
tert.put(fs2, data)
724+
var fs3 = newFileStream("ccsds.hex", fmReadWrite)
725+
defer: fs3.close()
726+
if not fs3.isNil:
727+
var data: typeGetter(ccsds_header)
728+
data.version = 0
729+
data.packet_type = 0
730+
data.secondary_header = 1
731+
data.apid = 6
732+
ccsds_header.put(fs3, data)
733+
var test: int64 = 0x31_32_33_34_35_36_37_38
734+
var test2: int64 = 0
735+
echo test
736+
echo test.toHex
737+
fs3.writeDataBE(test.addr, 8)
738+
fs3.setPosition(2)
739+
fs3.readDataLE(test2.addr, 8)
740+
echo test2
741+
echo test2.toHex
742+

0 commit comments

Comments
 (0)