From 2fc396a607df86519a4bdea29f0fef9304118a0b Mon Sep 17 00:00:00 2001 From: Project Nayuki Date: Thu, 23 Nov 2017 06:13:10 +0000 Subject: [PATCH] Implemented some supporting methods and changes for BitBuffer, QrSegment, QrTemplate. --- src/io/nayuki/fastqrcodegen/BitBuffer.java | 42 +++++++++++++++++++++ src/io/nayuki/fastqrcodegen/QrSegment.java | 21 +++++++++++ src/io/nayuki/fastqrcodegen/QrTemplate.java | 2 +- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/io/nayuki/fastqrcodegen/BitBuffer.java b/src/io/nayuki/fastqrcodegen/BitBuffer.java index a73158b..875d1f8 100644 --- a/src/io/nayuki/fastqrcodegen/BitBuffer.java +++ b/src/io/nayuki/fastqrcodegen/BitBuffer.java @@ -24,6 +24,7 @@ package io.nayuki.fastqrcodegen; import java.util.Arrays; +import java.util.Objects; final class BitBuffer { @@ -54,6 +55,16 @@ final class BitBuffer { } + public byte[] getBytes() { + if (bitLength % 8 != 0) + throw new IllegalStateException("Data is not a whole number of bytes"); + byte[] result = new byte[bitLength / 8]; + for (int i = 0; i < result.length; i++) + result[i] = (byte)(data[i >>> 2] >>> (~i << 3)); + return result; + } + + public void appendBits(int val, int len) { if (len < 0 || len > 31 || val >>> len != 0) throw new IllegalArgumentException("Value out of range"); @@ -76,4 +87,35 @@ final class BitBuffer { bitLength += len; } + + public void appendBits(int[] vals, int len) { + Objects.requireNonNull(vals); + if (len == 0) + return; + if (len < 0 || len > vals.length * 32) + throw new IllegalArgumentException("Value out of range"); + int wholeWords = len / 32; + int tailBits = len % 32; + if (tailBits > 0 && vals[wholeWords] << tailBits != 0) + throw new IllegalArgumentException("Last word must have low bits clear"); + + while (bitLength + len > data.length * 32) + data = Arrays.copyOf(data, data.length * 2); + + int shift = bitLength % 32; + if (shift == 0) { + System.arraycopy(vals, 0, data, bitLength / 32, (len + 31) / 32); + bitLength += len; + } else { + for (int i = 0; i < wholeWords; i++) { + int word = vals[i]; + data[bitLength >>> 5] |= word >>> shift; + bitLength += 32; + data[bitLength >>> 5] = word << (32 - shift); + } + if (tailBits > 0) + appendBits(vals[wholeWords] >>> (32 - tailBits), tailBits); + } + } + } diff --git a/src/io/nayuki/fastqrcodegen/QrSegment.java b/src/io/nayuki/fastqrcodegen/QrSegment.java index 44a9689..91f0545 100644 --- a/src/io/nayuki/fastqrcodegen/QrSegment.java +++ b/src/io/nayuki/fastqrcodegen/QrSegment.java @@ -167,6 +167,27 @@ public final class QrSegment { } + // Package-private helper function. + static int getTotalBits(List segs, int version) { + Objects.requireNonNull(segs); + if (version < 1 || version > 40) + throw new IllegalArgumentException("Version number out of range"); + + long result = 0; + for (QrSegment seg : segs) { + Objects.requireNonNull(seg); + int ccbits = seg.mode.numCharCountBits(version); + // Fail if segment length value doesn't fit in the length field's bit-width + if (seg.numChars >= (1 << ccbits)) + return -1; + result += 4L + ccbits + seg.bitLength; + if (result > Integer.MAX_VALUE) + return -1; + } + return (int)result; + } + + /*---- Constants ----*/ diff --git a/src/io/nayuki/fastqrcodegen/QrTemplate.java b/src/io/nayuki/fastqrcodegen/QrTemplate.java index 492e58c..b60ce81 100644 --- a/src/io/nayuki/fastqrcodegen/QrTemplate.java +++ b/src/io/nayuki/fastqrcodegen/QrTemplate.java @@ -300,7 +300,7 @@ final class QrTemplate { // Returns the number of data bits that can be stored in a QR Code of the given version number, after // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. - private static int getNumRawDataModules(int ver) { + static int getNumRawDataModules(int ver) { if (ver < MIN_VERSION || ver > MAX_VERSION) throw new IllegalArgumentException("Version number out of range"); int result = (16 * ver + 128) * ver + 64;