From 1f0c6a7638353d1ebbbc4ba1a8de0887d5f68e98 Mon Sep 17 00:00:00 2001 From: pacien Date: Fri, 30 Nov 2018 21:06:39 +0100 Subject: isolate blocks --- src/blocks/lzssblock.nim | 32 ++++++++++++++ src/blocks/rawblock.nim | 40 +++++++++++++++++ src/blocks/streamblock.nim | 68 ++++++++++++++++++++++++++++ src/lzssblock.nim | 32 -------------- src/main.nim | 2 +- src/rawblock.nim | 40 ----------------- src/streamblock.nim | 68 ---------------------------- tests/tblocks.nim | 107 +++++++++++++++++++++++++++++++++++++++++++++ tests/trawblock.nim | 57 ------------------------ tests/tstreamblock.nim | 68 ---------------------------- 10 files changed, 248 insertions(+), 266 deletions(-) create mode 100644 src/blocks/lzssblock.nim create mode 100644 src/blocks/rawblock.nim create mode 100644 src/blocks/streamblock.nim delete mode 100644 src/lzssblock.nim delete mode 100644 src/rawblock.nim delete mode 100644 src/streamblock.nim create mode 100644 tests/tblocks.nim delete mode 100644 tests/trawblock.nim delete mode 100644 tests/tstreamblock.nim diff --git a/src/blocks/lzssblock.nim b/src/blocks/lzssblock.nim new file mode 100644 index 0000000..f68f665 --- /dev/null +++ b/src/blocks/lzssblock.nim @@ -0,0 +1,32 @@ +# gzip-like LZSS compressor +# Copyright (C) 2018 Pacien TRAN-GIRARD +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import ../bitio/bitreader, ../bitio/bitwriter + +type LzssBlock* = object + discard + +proc readSerialised*(bitReader: BitReader): LzssBlock = + discard + +proc writeSerialisedTo*(lzssBlock: LzssBlock, bitWriter: BitWriter) = + discard + +proc readRaw*(bitReader: BitReader): LzssBlock = + discard + +proc writeRawTo*(lzssBlock: LzssBlock, bitWriter: BitWriter) = + discard diff --git a/src/blocks/rawblock.nim b/src/blocks/rawblock.nim new file mode 100644 index 0000000..2b32831 --- /dev/null +++ b/src/blocks/rawblock.nim @@ -0,0 +1,40 @@ +# gzip-like LZSS compressor +# Copyright (C) 2018 Pacien TRAN-GIRARD +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import ../bitio/integers, ../bitio/bitreader, ../bitio/bitwriter + +const maxDataBitLength = high(uint16).int +const bitLengthFieldBitLength = 2 * wordBitLength + +type RawBlock* = object + bitLength: int + data: seq[uint8] + +proc readSerialised*(bitReader: BitReader): RawBlock = + let bitLength = bitReader.readBits(bitLengthFieldBitLength, uint16).int + let data = bitReader.readSeq(bitLength, uint8) + RawBlock(bitLength: bitLength, data: data.data) + +proc writeSerialisedTo*(rawBlock: RawBlock, bitWriter: BitWriter) = + bitWriter.writeBits(bitLengthFieldBitLength, rawBlock.bitLength.uint16) + bitWriter.writeSeq(rawBlock.bitLength, rawBlock.data) + +proc readRaw*(bitReader: BitReader, bits: int = maxDataBitLength): RawBlock = + let data = bitReader.readSeq(bits, uint8) + RawBlock(bitLength: data.bitLength, data: data.data) + +proc writeRawTo*(rawBlock: RawBlock, bitWriter: BitWriter) = + bitWriter.writeSeq(rawBlock.bitLength, rawBlock.data) diff --git a/src/blocks/streamblock.nim b/src/blocks/streamblock.nim new file mode 100644 index 0000000..c904af7 --- /dev/null +++ b/src/blocks/streamblock.nim @@ -0,0 +1,68 @@ +# gzip-like LZSS compressor +# Copyright (C) 2018 Pacien TRAN-GIRARD +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import sequtils +import ../bitio/integers, ../bitio/bitreader, ../bitio/bitwriter +import rawblock, lzssblock + +type BlockKind* = enum + uncompressed = 0b00'u8, + lzss = 0b01, + reserved1 = 0b10, + reserved2 = 0b11 + +type StreamBlock* = object + last: bool + case kind: BlockKind + of uncompressed: + rawBlock: RawBlock + of lzss: + lzssBlock: LzssBlock + else: + discard + +proc isLast*(streamBlock: StreamBlock): bool = + streamBlock.last + +proc readSerialised*(bitReader: BitReader): StreamBlock = + result.last = bitReader.readBool() + result.kind = bitReader.readBits(2, uint8).BlockKind + case result.kind: + of uncompressed: result.rawBlock = rawblock.readSerialised(bitReader) + of lzss: result.lzssBlock = lzssblock.readSerialised(bitReader) + else: raise newException(ValueError, "unhandled block type") + +proc writeSerialisedTo*(streamBlock: StreamBlock, bitWriter: BitWriter) = + bitWriter.writeBool(streamBlock.last) + bitWriter.writeBits(2, streamBlock.kind.uint8) + case streamBlock.kind: + of uncompressed: streamBlock.rawBlock.writeSerialisedTo(bitWriter) + of lzss: streamBlock.lzssBlock.writeSerialisedTo(bitWriter) + else: raise newException(ValueError, "unhandled block type") + +proc readRaw*(bitReader: BitReader, kind: BlockKind = uncompressed): StreamBlock = + result.kind = kind + case kind: + of uncompressed: result.rawBlock = rawblock.readRaw(bitReader) + of lzss: result.lzssBlock = lzssblock.readRaw(bitReader) + else: raise newException(ValueError, "unhandled block type") + result.last = bitReader.atEnd() + +proc writeRawTo*(streamBlock: StreamBlock, bitWriter: BitWriter) = + case streamBlock.kind: + of uncompressed: streamBlock.rawBlock.writeRawTo(bitWriter) + of lzss: streamBlock.lzssBlock.writeRawTo(bitWriter) + else: raise newException(ValueError, "unhandled block type") diff --git a/src/lzssblock.nim b/src/lzssblock.nim deleted file mode 100644 index 317e768..0000000 --- a/src/lzssblock.nim +++ /dev/null @@ -1,32 +0,0 @@ -# gzip-like LZSS compressor -# Copyright (C) 2018 Pacien TRAN-GIRARD -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -import bitio/bitreader, bitio/bitwriter - -type LzssBlock* = object - discard - -proc readSerialised*(bitReader: BitReader): LzssBlock = - discard - -proc writeSerialisedTo*(lzssBlock: LzssBlock, bitWriter: BitWriter) = - discard - -proc readRaw*(bitReader: BitReader): LzssBlock = - discard - -proc writeRawTo*(lzssBlock: LzssBlock, bitWriter: BitWriter) = - discard diff --git a/src/main.nim b/src/main.nim index 450f52d..cf76f5e 100644 --- a/src/main.nim +++ b/src/main.nim @@ -15,7 +15,7 @@ # along with this program. If not, see . import os, streams, sugar -import bitio/bitreader, bitio/bitwriter, streamblock +import bitio/bitreader, bitio/bitwriter, blocks/streamblock proc transform*(operation: (BitReader, BitWriter) -> void, input, output: string) = let inputStream = openFileStream(input, fmRead) diff --git a/src/rawblock.nim b/src/rawblock.nim deleted file mode 100644 index b4920fc..0000000 --- a/src/rawblock.nim +++ /dev/null @@ -1,40 +0,0 @@ -# gzip-like LZSS compressor -# Copyright (C) 2018 Pacien TRAN-GIRARD -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -import bitio/integers, bitio/bitreader, bitio/bitwriter - -const maxDataBitLength = high(uint16).int -const bitLengthFieldBitLength = 2 * wordBitLength - -type RawBlock* = object - bitLength: int - data: seq[uint8] - -proc readSerialised*(bitReader: BitReader): RawBlock = - let bitLength = bitReader.readBits(bitLengthFieldBitLength, uint16).int - let data = bitReader.readSeq(bitLength, uint8) - RawBlock(bitLength: bitLength, data: data.data) - -proc writeSerialisedTo*(rawBlock: RawBlock, bitWriter: BitWriter) = - bitWriter.writeBits(bitLengthFieldBitLength, rawBlock.bitLength.uint16) - bitWriter.writeSeq(rawBlock.bitLength, rawBlock.data) - -proc readRaw*(bitReader: BitReader, bits: int = maxDataBitLength): RawBlock = - let data = bitReader.readSeq(bits, uint8) - RawBlock(bitLength: data.bitLength, data: data.data) - -proc writeRawTo*(rawBlock: RawBlock, bitWriter: BitWriter) = - bitWriter.writeSeq(rawBlock.bitLength, rawBlock.data) diff --git a/src/streamblock.nim b/src/streamblock.nim deleted file mode 100644 index 489097e..0000000 --- a/src/streamblock.nim +++ /dev/null @@ -1,68 +0,0 @@ -# gzip-like LZSS compressor -# Copyright (C) 2018 Pacien TRAN-GIRARD -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -import sequtils -import bitio/integers, bitio/bitreader, bitio/bitwriter -import rawblock, lzssblock - -type BlockKind* = enum - uncompressed = 0b00'u8, - lzss = 0b01, - reserved1 = 0b10, - reserved2 = 0b11 - -type StreamBlock* = object - last: bool - case kind: BlockKind - of uncompressed: - rawBlock: RawBlock - of lzss: - lzssBlock: LzssBlock - else: - discard - -proc isLast*(streamBlock: StreamBlock): bool = - streamBlock.last - -proc readSerialised*(bitReader: BitReader): StreamBlock = - result.last = bitReader.readBool() - result.kind = bitReader.readBits(2, uint8).BlockKind - case result.kind: - of uncompressed: result.rawBlock = rawblock.readSerialised(bitReader) - of lzss: result.lzssBlock = lzssblock.readSerialised(bitReader) - else: raise newException(ValueError, "unhandled block type") - -proc writeSerialisedTo*(streamBlock: StreamBlock, bitWriter: BitWriter) = - bitWriter.writeBool(streamBlock.last) - bitWriter.writeBits(2, streamBlock.kind.uint8) - case streamBlock.kind: - of uncompressed: streamBlock.rawBlock.writeSerialisedTo(bitWriter) - of lzss: streamBlock.lzssBlock.writeSerialisedTo(bitWriter) - else: raise newException(ValueError, "unhandled block type") - -proc readRaw*(bitReader: BitReader, kind: BlockKind = uncompressed): StreamBlock = - result.kind = kind - case kind: - of uncompressed: result.rawBlock = rawblock.readRaw(bitReader) - of lzss: result.lzssBlock = lzssblock.readRaw(bitReader) - else: raise newException(ValueError, "unhandled block type") - result.last = bitReader.atEnd() - -proc writeRawTo*(streamBlock: StreamBlock, bitWriter: BitWriter) = - case streamBlock.kind: - of uncompressed: streamBlock.rawBlock.writeRawTo(bitWriter) - of lzss: streamBlock.lzssBlock.writeRawTo(bitWriter) - else: raise newException(ValueError, "unhandled block type") diff --git a/tests/tblocks.nim b/tests/tblocks.nim new file mode 100644 index 0000000..540317d --- /dev/null +++ b/tests/tblocks.nim @@ -0,0 +1,107 @@ +# gzip-like LZSS compressor +# Copyright (C) 2018 Pacien TRAN-GIRARD +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import unittest, streams +import bitio/bitreader, bitio/bitwriter, blocks/rawblock, blocks/streamblock + +suite "rawblock": + test "serialise": + let rawStream = newStringStream() + defer: rawStream.close() + rawStream.write(0xFEDC_BA98_7654_3210'u64) + rawStream.setPosition(0) + let rawBitReader = rawStream.bitReader() + let rawBlock = rawblock.readRaw(rawBitReader) + + let outputStream = newStringStream() + defer: outputStream.close() + let outputBitWriter = outputStream.bitWriter() + rawBlock.writeSerialisedTo(outputBitWriter) + outputBitWriter.flush() + + outputStream.setPosition(0) + check outputStream.readUint16() == 64 + check outputStream.readUint64() == 0xFEDC_BA98_7654_3210'u64 + check outputStream.atEnd() + + test "deserialise": + let serialisedStream = newStringStream() + defer: serialisedStream.close() + serialisedStream.write(60'u16) + serialisedStream.write(0xFEDC_BA98_7654_3210'u64) + serialisedStream.setPosition(0) + let serialisedBitReader = serialisedStream.bitReader() + let rawBlock = rawBlock.readSerialised(serialisedBitReader) + + let outputStream = newStringStream() + defer: outputStream.close() + let outputBitWriter = outputStream.bitWriter() + rawBlock.writeRawTo(outputBitWriter) + outputBitWriter.flush() + + outputStream.setPosition(0) + check outputStream.readUint64 == 0x0EDC_BA98_7654_3210'u64 + check outputStream.atEnd() + +suite "streamblock": + test "serialise": + let rawStream = newStringStream() + defer: rawStream.close() + rawStream.write(0xFEDC_BA98_7654_3210'u64) + rawStream.setPosition(0) + let rawBitReader = rawStream.bitReader() + let streamBlock = readRaw(rawBitReader, uncompressed) + check streamBlock.isLast() + + let outputStream = newStringStream() + defer: outputStream.close() + let outputBitWriter = outputStream.bitWriter() + streamBlock.writeSerialisedTo(outputBitWriter) + outputBitWriter.flush() + + outputStream.setPosition(0) + let produceReader = outputStream.bitReader() + check produceReader.readBool() == true # last block flag + check produceReader.readBits(2, uint8) == 0x00'u8 # block kind + check produceReader.readBits(16, uint16) == 64 # raw block length + check produceReader.readSeq(64, uint8) == (64, @[0x10'u8, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE]) # raw block content + discard produceReader.readBits(8 - 2 - 1, uint8) + check produceReader.atEnd() + + test "deserialise": + let serialisedStream = newStringStream() + defer: serialisedStream.close() + let serialisedBitWriter = serialisedStream.bitWriter() + serialisedBitWriter.writeBool(true) + serialisedBitWriter.writeBits(2, 0x00'u8) + serialisedBitWriter.writeBits(16, 64'u16) + serialisedBitWriter.writeBits(64, 0xFEDC_BA98_7654_3210'u64) + serialisedBitWriter.flush() + + serialisedStream.setPosition(0) + let serialisedBitReader = serialisedStream.bitReader() + let streamBlock = streamblock.readSerialised(serialisedBitReader) + + let outputStream = newStringStream() + defer: outputStream.close() + let outputBitWriter = outputStream.bitWriter() + check streamBlock.isLast() + streamBlock.writeRawTo(outputBitWriter) + outputBitWriter.flush() + + outputStream.setPosition(0) + check outputStream.readUint64 == 0xFEDC_BA98_7654_3210'u64 + check outputStream.atEnd() diff --git a/tests/trawblock.nim b/tests/trawblock.nim deleted file mode 100644 index 0271e33..0000000 --- a/tests/trawblock.nim +++ /dev/null @@ -1,57 +0,0 @@ -# gzip-like LZSS compressor -# Copyright (C) 2018 Pacien TRAN-GIRARD -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -import unittest, streams -import bitio/bitreader, bitio/bitwriter, rawblock - -suite "rawblock": - test "serialise": - let rawStream = newStringStream() - defer: rawStream.close() - rawStream.write(0xFEDC_BA98_7654_3210'u64) - rawStream.setPosition(0) - let rawBitReader = rawStream.bitReader() - let rawBlock = rawblock.readRaw(rawBitReader) - - let outputStream = newStringStream() - defer: outputStream.close() - let outputBitWriter = outputStream.bitWriter() - rawBlock.writeSerialisedTo(outputBitWriter) - outputBitWriter.flush() - - outputStream.setPosition(0) - check outputStream.readUint16() == 64 - check outputStream.readUint64() == 0xFEDC_BA98_7654_3210'u64 - check outputStream.atEnd() - - test "deserialise": - let serialisedStream = newStringStream() - defer: serialisedStream.close() - serialisedStream.write(60'u16) - serialisedStream.write(0xFEDC_BA98_7654_3210'u64) - serialisedStream.setPosition(0) - let serialisedBitReader = serialisedStream.bitReader() - let rawBlock = rawBlock.readSerialised(serialisedBitReader) - - let outputStream = newStringStream() - defer: outputStream.close() - let outputBitWriter = outputStream.bitWriter() - rawBlock.writeRawTo(outputBitWriter) - outputBitWriter.flush() - - outputStream.setPosition(0) - check outputStream.readUint64 == 0x0EDC_BA98_7654_3210'u64 - check outputStream.atEnd() diff --git a/tests/tstreamblock.nim b/tests/tstreamblock.nim deleted file mode 100644 index 57eaf3a..0000000 --- a/tests/tstreamblock.nim +++ /dev/null @@ -1,68 +0,0 @@ -# gzip-like LZSS compressor -# Copyright (C) 2018 Pacien TRAN-GIRARD -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -import unittest, streams -import bitio/bitreader, bitio/bitwriter, streamblock - -suite "streamblock": - test "serialise": - let rawStream = newStringStream() - defer: rawStream.close() - rawStream.write(0xFEDC_BA98_7654_3210'u64) - rawStream.setPosition(0) - let rawBitReader = rawStream.bitReader() - let streamBlock = readRaw(rawBitReader, uncompressed) - check streamBlock.isLast() - - let outputStream = newStringStream() - defer: outputStream.close() - let outputBitWriter = outputStream.bitWriter() - streamBlock.writeSerialisedTo(outputBitWriter) - outputBitWriter.flush() - - outputStream.setPosition(0) - let produceReader = outputStream.bitReader() - check produceReader.readBool() == true # last block flag - check produceReader.readBits(2, uint8) == 0x00'u8 # block kind - check produceReader.readBits(16, uint16) == 64 # raw block length - check produceReader.readSeq(64, uint8) == (64, @[0x10'u8, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE]) # raw block content - discard produceReader.readBits(8 - 2 - 1, uint8) - check produceReader.atEnd() - - test "deserialise": - let serialisedStream = newStringStream() - defer: serialisedStream.close() - let serialisedBitWriter = serialisedStream.bitWriter() - serialisedBitWriter.writeBool(true) - serialisedBitWriter.writeBits(2, 0x00'u8) - serialisedBitWriter.writeBits(16, 64'u16) - serialisedBitWriter.writeBits(64, 0xFEDC_BA98_7654_3210'u64) - serialisedBitWriter.flush() - - serialisedStream.setPosition(0) - let serialisedBitReader = serialisedStream.bitReader() - let streamBlock = readSerialised(serialisedBitReader) - - let outputStream = newStringStream() - defer: outputStream.close() - let outputBitWriter = outputStream.bitWriter() - check streamBlock.isLast() - streamBlock.writeRawTo(outputBitWriter) - outputBitWriter.flush() - - outputStream.setPosition(0) - check outputStream.readUint64 == 0xFEDC_BA98_7654_3210'u64 - check outputStream.atEnd() -- cgit v1.2.3