From b65dad6f4179f3950ecdd5d8b6d09c5844e4e410 Mon Sep 17 00:00:00 2001 From: minsu4107 <32637512+minsu4107@users.noreply.github.com> Date: Fri, 5 Jun 2020 23:45:52 +0900 Subject: [PATCH 01/35] 1.Strategy Pattern 2. AlphanumericMode, ByteMode, EciMode, NumericMode, QrMode 3. Add java class for using Strategy Pattern --- .../io/nayuki/qrcodegen/AlphanumericMode.java | 25 +++++++++++ .../java/io/nayuki/qrcodegen/ByteMode.java | 25 +++++++++++ .../java/io/nayuki/qrcodegen/EciMode.java | 23 ++++++++++ .../java/io/nayuki/qrcodegen/NumericMode.java | 23 ++++++++++ .../main/java/io/nayuki/qrcodegen/QrMode.java | 43 +++++++++++++++++++ 5 files changed, 139 insertions(+) create mode 100644 java/src/main/java/io/nayuki/qrcodegen/AlphanumericMode.java create mode 100644 java/src/main/java/io/nayuki/qrcodegen/ByteMode.java create mode 100644 java/src/main/java/io/nayuki/qrcodegen/EciMode.java create mode 100644 java/src/main/java/io/nayuki/qrcodegen/NumericMode.java create mode 100644 java/src/main/java/io/nayuki/qrcodegen/QrMode.java diff --git a/java/src/main/java/io/nayuki/qrcodegen/AlphanumericMode.java b/java/src/main/java/io/nayuki/qrcodegen/AlphanumericMode.java new file mode 100644 index 0000000..f0d59ba --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/AlphanumericMode.java @@ -0,0 +1,25 @@ +package io.nayuki.qrcodegen; + +import java.nio.charset.StandardCharsets; + +public class AlphanumericMode extends QrMode { + protected AlphanumericMode(int mode, int... ccbits) { + modeBits = mode; + numBitsCharCount = ccbits; + } + + protected AlphanumericMode() { + modeBits = 0x2; + numBitsCharCount[0] = 9; + numBitsCharCount[1] = 11; + numBitsCharCount[2] = 13; + } + + public int getcost(int pre, int codePoint) { + return pre + 33; + } + + public QrSegment making(String str) { + return QrSegment.makeAlphanumeric(str); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/ByteMode.java b/java/src/main/java/io/nayuki/qrcodegen/ByteMode.java new file mode 100644 index 0000000..1270381 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/ByteMode.java @@ -0,0 +1,25 @@ +package io.nayuki.qrcodegen; + +import java.nio.charset.StandardCharsets; + +public class ByteMode extends QrMode { + protected ByteMode(int mode, int... ccbits) { + modeBits = mode; + numBitsCharCount = ccbits; + } + + protected ByteMode() { + modeBits = 0x4; + numBitsCharCount[0] = 8; + numBitsCharCount[1] = 16; + numBitsCharCount[2] = 16; + } + + public int getcost(int pre, int codePoint) { + return pre + QrSegmentAdvanced.countUtf8Bytes(codePoint) * 8 * 6; + } + + public QrSegment making(String str) { + return QrSegment.makeBytes(str.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/EciMode.java b/java/src/main/java/io/nayuki/qrcodegen/EciMode.java new file mode 100644 index 0000000..ce33fa9 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/EciMode.java @@ -0,0 +1,23 @@ +package io.nayuki.qrcodegen; + +public class EciMode extends QrMode { + protected EciMode(int mode, int... ccbits) { + modeBits = mode; + numBitsCharCount = ccbits; + } + + protected EciMode() { + modeBits = 0x7; + numBitsCharCount[0] = 0; + numBitsCharCount[1] = 0; + numBitsCharCount[2] = 0; + } + + public QrSegment making(int prmt) { + return QrSegment.makeEci(prmt); + } + + public int getcost(int pre, int codePoint) { + return pre; + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/NumericMode.java b/java/src/main/java/io/nayuki/qrcodegen/NumericMode.java new file mode 100644 index 0000000..a8af039 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/NumericMode.java @@ -0,0 +1,23 @@ +package io.nayuki.qrcodegen; + +public class NumericMode extends QrMode { + protected NumericMode(int mode, int... ccbits) { + modeBits = mode; + numBitsCharCount = ccbits; + } + + protected NumericMode() { + modeBits = 0x1; + numBitsCharCount[0] = 10; + numBitsCharCount[1] = 12; + numBitsCharCount[2] = 1; + } + + public int getcost(int pre, int codePoint) { + return pre + 20; + } + + public QrSegment making(String str) { + return QrSegment.makeNumeric(str); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrMode.java b/java/src/main/java/io/nayuki/qrcodegen/QrMode.java new file mode 100644 index 0000000..3f0127f --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/QrMode.java @@ -0,0 +1,43 @@ +package io.nayuki.qrcodegen; + +public abstract class QrMode { + /*-- Fields --*/ + + // The mode indicator bits, which is a uint4 value (range 0 to 15). + int modeBits; + + // Number of character count bits for three different version ranges. + protected int[] numBitsCharCount; + + int headCost; + /*-- Method --*/ + + // Returns the bit width of the character count field for a segment in this mode + // in a QR Code at the given version number. The result is in the range [0, 16]. + int numCharCountBits(int ver) { + assert QrCode.MIN_VERSION <= ver && ver <= QrCode.MAX_VERSION; + return numBitsCharCount[(ver + 7) / 17]; + } + + protected QrMode() { + this.modeBits = 0; + this.numBitsCharCount = null; + } + + public void get(QrMode md) { + this.modeBits = md.modeBits; + this.numBitsCharCount = md.numBitsCharCount; + } + + public int whichMode() { + return modeBits; + } + + protected QrSegment making(String s) { + return null; + } + + public int getcost(int pre, int codePoint) { + return pre; + } +} \ No newline at end of file From b0f9f99273229dcb47e405779f92d8b6027e20e7 Mon Sep 17 00:00:00 2001 From: jaemi Date: Sat, 6 Jun 2020 16:48:01 +0900 Subject: [PATCH 02/35] Refactoring operation name : rename Refactoring object : QrSegment.java Reason : BitBuffer bb is too simple to express meaning bitBuffer. So, rename bb to bitBuffer --- .../java/io/nayuki/qrcodegen/QrSegment.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index f416200..170d9d2 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -58,10 +58,10 @@ public final class QrSegment { */ public static QrSegment makeBytes(byte[] data) { Objects.requireNonNull(data); - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); for (byte b : data) - bb.appendBits(b & 0xFF, 8); - return new QrSegment(Mode.BYTE, data.length, bb); + bitBuffer.appendBits(b & 0xFF, 8); + return new QrSegment(Mode.BYTE, data.length, bitBuffer); } @@ -77,13 +77,13 @@ public final class QrSegment { if (!NUMERIC_REGEX.matcher(digits).matches()) throw new IllegalArgumentException("String contains non-numeric characters"); - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration int n = Math.min(digits.length() - i, 3); - bb.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); + bitBuffer.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); i += n; } - return new QrSegment(Mode.NUMERIC, digits.length(), bb); + return new QrSegment(Mode.NUMERIC, digits.length(), bitBuffer); } @@ -101,16 +101,16 @@ public final class QrSegment { if (!ALPHANUMERIC_REGEX.matcher(text).matches()) throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); int i; for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 int temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); - bb.appendBits(temp, 11); + bitBuffer.appendBits(temp, 11); } if (i < text.length()) // 1 character remaining - bb.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); - return new QrSegment(Mode.ALPHANUMERIC, text.length(), bb); + bitBuffer.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); + return new QrSegment(Mode.ALPHANUMERIC, text.length(), bitBuffer); } @@ -145,20 +145,20 @@ public final class QrSegment { * @throws IllegalArgumentException if the value is outside the range [0, 106) */ public static QrSegment makeEci(int assignVal) { - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); if (assignVal < 0) throw new IllegalArgumentException("ECI assignment value out of range"); else if (assignVal < (1 << 7)) - bb.appendBits(assignVal, 8); + bitBuffer.appendBits(assignVal, 8); else if (assignVal < (1 << 14)) { - bb.appendBits(2, 2); - bb.appendBits(assignVal, 14); + bitBuffer.appendBits(2, 2); + bitBuffer.appendBits(assignVal, 14); } else if (assignVal < 1_000_000) { - bb.appendBits(6, 3); - bb.appendBits(assignVal, 21); + bitBuffer.appendBits(6, 3); + bitBuffer.appendBits(assignVal, 21); } else throw new IllegalArgumentException("ECI assignment value out of range"); - return new QrSegment(Mode.ECI, 0, bb); + return new QrSegment(Mode.ECI, 0, bitBuffer); } From 42ef659ef3415d23ef47c686e33794e9c98bacc1 Mon Sep 17 00:00:00 2001 From: jaemi Date: Sat, 6 Jun 2020 17:10:53 +0900 Subject: [PATCH 03/35] hello --- .../java/io/nayuki/qrcodegen/QrSegment.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 170d9d2..f416200 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -58,10 +58,10 @@ public final class QrSegment { */ public static QrSegment makeBytes(byte[] data) { Objects.requireNonNull(data); - BitBuffer bitBuffer = new BitBuffer(); + BitBuffer bb = new BitBuffer(); for (byte b : data) - bitBuffer.appendBits(b & 0xFF, 8); - return new QrSegment(Mode.BYTE, data.length, bitBuffer); + bb.appendBits(b & 0xFF, 8); + return new QrSegment(Mode.BYTE, data.length, bb); } @@ -77,13 +77,13 @@ public final class QrSegment { if (!NUMERIC_REGEX.matcher(digits).matches()) throw new IllegalArgumentException("String contains non-numeric characters"); - BitBuffer bitBuffer = new BitBuffer(); + BitBuffer bb = new BitBuffer(); for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration int n = Math.min(digits.length() - i, 3); - bitBuffer.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); + bb.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); i += n; } - return new QrSegment(Mode.NUMERIC, digits.length(), bitBuffer); + return new QrSegment(Mode.NUMERIC, digits.length(), bb); } @@ -101,16 +101,16 @@ public final class QrSegment { if (!ALPHANUMERIC_REGEX.matcher(text).matches()) throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); - BitBuffer bitBuffer = new BitBuffer(); + BitBuffer bb = new BitBuffer(); int i; for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 int temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); - bitBuffer.appendBits(temp, 11); + bb.appendBits(temp, 11); } if (i < text.length()) // 1 character remaining - bitBuffer.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); - return new QrSegment(Mode.ALPHANUMERIC, text.length(), bitBuffer); + bb.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); + return new QrSegment(Mode.ALPHANUMERIC, text.length(), bb); } @@ -145,20 +145,20 @@ public final class QrSegment { * @throws IllegalArgumentException if the value is outside the range [0, 106) */ public static QrSegment makeEci(int assignVal) { - BitBuffer bitBuffer = new BitBuffer(); + BitBuffer bb = new BitBuffer(); if (assignVal < 0) throw new IllegalArgumentException("ECI assignment value out of range"); else if (assignVal < (1 << 7)) - bitBuffer.appendBits(assignVal, 8); + bb.appendBits(assignVal, 8); else if (assignVal < (1 << 14)) { - bitBuffer.appendBits(2, 2); - bitBuffer.appendBits(assignVal, 14); + bb.appendBits(2, 2); + bb.appendBits(assignVal, 14); } else if (assignVal < 1_000_000) { - bitBuffer.appendBits(6, 3); - bitBuffer.appendBits(assignVal, 21); + bb.appendBits(6, 3); + bb.appendBits(assignVal, 21); } else throw new IllegalArgumentException("ECI assignment value out of range"); - return new QrSegment(Mode.ECI, 0, bitBuffer); + return new QrSegment(Mode.ECI, 0, bb); } From 9064c8816e9a29a04fb98ec866780b94330e82d1 Mon Sep 17 00:00:00 2001 From: jaemi Date: Sat, 6 Jun 2020 17:13:05 +0900 Subject: [PATCH 04/35] Refactoring object : QrSegment.java Reason : BitBuffer bb is too simple to express meaning bitBuffer. So, rename bb to bitBuffer --- .../java/io/nayuki/qrcodegen/QrSegment.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index f416200..170d9d2 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -58,10 +58,10 @@ public final class QrSegment { */ public static QrSegment makeBytes(byte[] data) { Objects.requireNonNull(data); - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); for (byte b : data) - bb.appendBits(b & 0xFF, 8); - return new QrSegment(Mode.BYTE, data.length, bb); + bitBuffer.appendBits(b & 0xFF, 8); + return new QrSegment(Mode.BYTE, data.length, bitBuffer); } @@ -77,13 +77,13 @@ public final class QrSegment { if (!NUMERIC_REGEX.matcher(digits).matches()) throw new IllegalArgumentException("String contains non-numeric characters"); - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration int n = Math.min(digits.length() - i, 3); - bb.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); + bitBuffer.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); i += n; } - return new QrSegment(Mode.NUMERIC, digits.length(), bb); + return new QrSegment(Mode.NUMERIC, digits.length(), bitBuffer); } @@ -101,16 +101,16 @@ public final class QrSegment { if (!ALPHANUMERIC_REGEX.matcher(text).matches()) throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); int i; for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 int temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); - bb.appendBits(temp, 11); + bitBuffer.appendBits(temp, 11); } if (i < text.length()) // 1 character remaining - bb.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); - return new QrSegment(Mode.ALPHANUMERIC, text.length(), bb); + bitBuffer.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); + return new QrSegment(Mode.ALPHANUMERIC, text.length(), bitBuffer); } @@ -145,20 +145,20 @@ public final class QrSegment { * @throws IllegalArgumentException if the value is outside the range [0, 106) */ public static QrSegment makeEci(int assignVal) { - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); if (assignVal < 0) throw new IllegalArgumentException("ECI assignment value out of range"); else if (assignVal < (1 << 7)) - bb.appendBits(assignVal, 8); + bitBuffer.appendBits(assignVal, 8); else if (assignVal < (1 << 14)) { - bb.appendBits(2, 2); - bb.appendBits(assignVal, 14); + bitBuffer.appendBits(2, 2); + bitBuffer.appendBits(assignVal, 14); } else if (assignVal < 1_000_000) { - bb.appendBits(6, 3); - bb.appendBits(assignVal, 21); + bitBuffer.appendBits(6, 3); + bitBuffer.appendBits(assignVal, 21); } else throw new IllegalArgumentException("ECI assignment value out of range"); - return new QrSegment(Mode.ECI, 0, bb); + return new QrSegment(Mode.ECI, 0, bitBuffer); } From 4d458bd91ac0d26eb5844d8b97a959c8bff652af Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 17:19:12 +0900 Subject: [PATCH 05/35] hello --- .../java/io/nayuki/qrcodegen/QrSegment.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 170d9d2..f416200 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -58,10 +58,10 @@ public final class QrSegment { */ public static QrSegment makeBytes(byte[] data) { Objects.requireNonNull(data); - BitBuffer bitBuffer = new BitBuffer(); + BitBuffer bb = new BitBuffer(); for (byte b : data) - bitBuffer.appendBits(b & 0xFF, 8); - return new QrSegment(Mode.BYTE, data.length, bitBuffer); + bb.appendBits(b & 0xFF, 8); + return new QrSegment(Mode.BYTE, data.length, bb); } @@ -77,13 +77,13 @@ public final class QrSegment { if (!NUMERIC_REGEX.matcher(digits).matches()) throw new IllegalArgumentException("String contains non-numeric characters"); - BitBuffer bitBuffer = new BitBuffer(); + BitBuffer bb = new BitBuffer(); for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration int n = Math.min(digits.length() - i, 3); - bitBuffer.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); + bb.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); i += n; } - return new QrSegment(Mode.NUMERIC, digits.length(), bitBuffer); + return new QrSegment(Mode.NUMERIC, digits.length(), bb); } @@ -101,16 +101,16 @@ public final class QrSegment { if (!ALPHANUMERIC_REGEX.matcher(text).matches()) throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); - BitBuffer bitBuffer = new BitBuffer(); + BitBuffer bb = new BitBuffer(); int i; for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 int temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); - bitBuffer.appendBits(temp, 11); + bb.appendBits(temp, 11); } if (i < text.length()) // 1 character remaining - bitBuffer.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); - return new QrSegment(Mode.ALPHANUMERIC, text.length(), bitBuffer); + bb.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); + return new QrSegment(Mode.ALPHANUMERIC, text.length(), bb); } @@ -145,20 +145,20 @@ public final class QrSegment { * @throws IllegalArgumentException if the value is outside the range [0, 106) */ public static QrSegment makeEci(int assignVal) { - BitBuffer bitBuffer = new BitBuffer(); + BitBuffer bb = new BitBuffer(); if (assignVal < 0) throw new IllegalArgumentException("ECI assignment value out of range"); else if (assignVal < (1 << 7)) - bitBuffer.appendBits(assignVal, 8); + bb.appendBits(assignVal, 8); else if (assignVal < (1 << 14)) { - bitBuffer.appendBits(2, 2); - bitBuffer.appendBits(assignVal, 14); + bb.appendBits(2, 2); + bb.appendBits(assignVal, 14); } else if (assignVal < 1_000_000) { - bitBuffer.appendBits(6, 3); - bitBuffer.appendBits(assignVal, 21); + bb.appendBits(6, 3); + bb.appendBits(assignVal, 21); } else throw new IllegalArgumentException("ECI assignment value out of range"); - return new QrSegment(Mode.ECI, 0, bitBuffer); + return new QrSegment(Mode.ECI, 0, bb); } From fd8f38b395df8b7b127f66f343e0085a88f06e1f Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 17:25:18 +0900 Subject: [PATCH 06/35] Refactoring operation name : rename Refactoring object : QrSegment.java Reason : BitBuffer bb is too simple to express meaning bitBuffer.So,rename bb to bitBuffer --- .../java/io/nayuki/qrcodegen/QrSegment.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index f416200..170d9d2 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -58,10 +58,10 @@ public final class QrSegment { */ public static QrSegment makeBytes(byte[] data) { Objects.requireNonNull(data); - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); for (byte b : data) - bb.appendBits(b & 0xFF, 8); - return new QrSegment(Mode.BYTE, data.length, bb); + bitBuffer.appendBits(b & 0xFF, 8); + return new QrSegment(Mode.BYTE, data.length, bitBuffer); } @@ -77,13 +77,13 @@ public final class QrSegment { if (!NUMERIC_REGEX.matcher(digits).matches()) throw new IllegalArgumentException("String contains non-numeric characters"); - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration int n = Math.min(digits.length() - i, 3); - bb.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); + bitBuffer.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); i += n; } - return new QrSegment(Mode.NUMERIC, digits.length(), bb); + return new QrSegment(Mode.NUMERIC, digits.length(), bitBuffer); } @@ -101,16 +101,16 @@ public final class QrSegment { if (!ALPHANUMERIC_REGEX.matcher(text).matches()) throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); int i; for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 int temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); - bb.appendBits(temp, 11); + bitBuffer.appendBits(temp, 11); } if (i < text.length()) // 1 character remaining - bb.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); - return new QrSegment(Mode.ALPHANUMERIC, text.length(), bb); + bitBuffer.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); + return new QrSegment(Mode.ALPHANUMERIC, text.length(), bitBuffer); } @@ -145,20 +145,20 @@ public final class QrSegment { * @throws IllegalArgumentException if the value is outside the range [0, 106) */ public static QrSegment makeEci(int assignVal) { - BitBuffer bb = new BitBuffer(); + BitBuffer bitBuffer = new BitBuffer(); if (assignVal < 0) throw new IllegalArgumentException("ECI assignment value out of range"); else if (assignVal < (1 << 7)) - bb.appendBits(assignVal, 8); + bitBuffer.appendBits(assignVal, 8); else if (assignVal < (1 << 14)) { - bb.appendBits(2, 2); - bb.appendBits(assignVal, 14); + bitBuffer.appendBits(2, 2); + bitBuffer.appendBits(assignVal, 14); } else if (assignVal < 1_000_000) { - bb.appendBits(6, 3); - bb.appendBits(assignVal, 21); + bitBuffer.appendBits(6, 3); + bitBuffer.appendBits(assignVal, 21); } else throw new IllegalArgumentException("ECI assignment value out of range"); - return new QrSegment(Mode.ECI, 0, bb); + return new QrSegment(Mode.ECI, 0, bitBuffer); } From da0b9906e4634e9201a9a4f7693118c8b679d461 Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 17:30:02 +0900 Subject: [PATCH 07/35] Refactoring operation name : rename Refactoring object : makeBytes(byte[] data) Reason : byte b is too simple to express meaning one byte. So,rename b to one_byte --- java/src/main/java/io/nayuki/qrcodegen/QrSegment.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 170d9d2..59606e5 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -59,9 +59,9 @@ public final class QrSegment { public static QrSegment makeBytes(byte[] data) { Objects.requireNonNull(data); BitBuffer bitBuffer = new BitBuffer(); - for (byte b : data) - bitBuffer.appendBits(b & 0xFF, 8); - return new QrSegment(Mode.BYTE, data.length, bitBuffer); + for (byte one_byte : data) + bitBuffer.appendBits(one_byte & 0xFF, 8); + return new QrSegment(QrSegment.Mode.BYTE, data.length, bitBuffer); } From bc243c25433405a4652ee59fe61a5b47fd460547 Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 17:35:36 +0900 Subject: [PATCH 08/35] Refactoring operation name : rename Refactoring object : makeSegments(String text) Reason : List result is too simple to express meaning segments. So,rename result to segments --- java/src/main/java/io/nayuki/qrcodegen/QrSegment.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 59606e5..f4c4b5d 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -125,15 +125,15 @@ public final class QrSegment { Objects.requireNonNull(text); // Select the most efficient segment encoding automatically - List result = new ArrayList<>(); + List segments = new ArrayList<>(); if (text.equals("")); // Leave result empty else if (NUMERIC_REGEX.matcher(text).matches()) - result.add(makeNumeric(text)); + segments.add(makeNumeric(text)); else if (ALPHANUMERIC_REGEX.matcher(text).matches()) - result.add(makeAlphanumeric(text)); + segments.add(makeAlphanumeric(text)); else - result.add(makeBytes(text.getBytes(StandardCharsets.UTF_8))); - return result; + segments.add(makeBytes(text.getBytes(StandardCharsets.UTF_8))); + return segments; } From 98ba80ec067c4c32d94bb7b9c43e51b4c84d3ed4 Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 17:38:17 +0900 Subject: [PATCH 09/35] Refactoring operation name : rename Refactoring object : makeEci(int assignValue) Reason : int assignVal is short to express meaning assignValue. So,rename assignVal to assignValue. --- .../main/java/io/nayuki/qrcodegen/QrSegment.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index f4c4b5d..6111865 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -144,18 +144,18 @@ public final class QrSegment { * @return a segment (not {@code null}) containing the data * @throws IllegalArgumentException if the value is outside the range [0, 106) */ - public static QrSegment makeEci(int assignVal) { + public static QrSegment makeEci(int assignValue) { BitBuffer bitBuffer = new BitBuffer(); - if (assignVal < 0) + if (assignValue < 0) throw new IllegalArgumentException("ECI assignment value out of range"); - else if (assignVal < (1 << 7)) - bitBuffer.appendBits(assignVal, 8); - else if (assignVal < (1 << 14)) { + else if (assignValue < (1 << 7)) + bitBuffer.appendBits(assignValue, 8); + else if (assignValue < (1 << 14)) { bitBuffer.appendBits(2, 2); - bitBuffer.appendBits(assignVal, 14); - } else if (assignVal < 1_000_000) { + bitBuffer.appendBits(assignValue, 14); + } else if (assignValue < 1_000_000) { bitBuffer.appendBits(6, 3); - bitBuffer.appendBits(assignVal, 21); + bitBuffer.appendBits(assignValue, 21); } else throw new IllegalArgumentException("ECI assignment value out of range"); return new QrSegment(Mode.ECI, 0, bitBuffer); From 76b671b7677d3eddcc5dd75a1885e0781fbe24c0 Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 17:40:40 +0900 Subject: [PATCH 10/35] Refactoring operation name : rename Refactoring object : QrSegment(Mode md, int numCh, BitBuffer data) Reason : Mode md, int numCh is short to express meaning . So,rename md to _mode and numCh to _numberOfCharacters --- java/src/main/java/io/nayuki/qrcodegen/QrSegment.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 6111865..52c9d69 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -29,6 +29,8 @@ import java.util.List; import java.util.Objects; import java.util.regex.Pattern; +import QrSegment.Mode; + /** * A segment of character/binary/control data in a QR Code symbol. @@ -189,16 +191,15 @@ public final class QrSegment { * @throws NullPointerException if the mode or data is {@code null} * @throws IllegalArgumentException if the character count is negative */ - public QrSegment(Mode md, int numCh, BitBuffer data) { - mode = Objects.requireNonNull(md); + public QrSegment(Mode _mode, int _numberOfCharacters, BitBuffer data) { + mode = Objects.requireNonNull(_mode); Objects.requireNonNull(data); - if (numCh < 0) + if (_numberOfCharacters < 0) throw new IllegalArgumentException("Invalid value"); - numChars = numCh; + numberOfCharacters = _numberOfCharacters; this.data = data.clone(); // Make defensive copy } - /*---- Methods ----*/ /** From 27b1a3a23889ca9b28512260b5353664a85e8269 Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 17:48:06 +0900 Subject: [PATCH 11/35] Refactoring operation name : rename Refactoring object : getTotalBits(List segments, int version) Reason : some value names are too simple to express meaning . So,rename result to TotalBits, seg to segment, segs to segments, ccbits to characterCountBits --- .../main/java/io/nayuki/qrcodegen/QrSegment.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 52c9d69..0fb22b6 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -229,6 +229,20 @@ public final class QrSegment { return (int)result; } + static int getTotalBits(List segments, int version) { + Objects.requireNonNull(segments); + long TotalBits = 0; + for (QrSegment segment : segments) { + Objects.requireNonNull(segment); + int characterCountBits = segment.mode.numCharCountBits(version); + if (segment.numberOfCharacters >= (1 << characterCountBits)) + return -1; // The segment's length doesn't fit the field's bit width + TotalBits += 4L + characterCountBits + segment.data.bitLength(); + if (TotalBits > Integer.MAX_VALUE) + return -1; // The sum will overflow an int type + } + return (int)TotalBits; + } /*---- Constants ----*/ From fe6c3980afb29637e981a6d3185709e0a0c790f9 Mon Sep 17 00:00:00 2001 From: gerzees Date: Sat, 6 Jun 2020 18:01:16 +0900 Subject: [PATCH 12/35] 1. Extract class 2. Ecc from QrCode 3. QrCode is too big --- .../main/java/io/nayuki/qrcodegen/Ecc.java | 61 +++++++++++++++++++ .../main/java/io/nayuki/qrcodegen/QrCode.java | 55 ++--------------- .../nayuki/qrcodegen/QrCodeGeneratorDemo.java | 34 +++++------ .../qrcodegen/QrCodeGeneratorWorker.java | 2 +- 4 files changed, 85 insertions(+), 67 deletions(-) create mode 100644 java/src/main/java/io/nayuki/qrcodegen/Ecc.java diff --git a/java/src/main/java/io/nayuki/qrcodegen/Ecc.java b/java/src/main/java/io/nayuki/qrcodegen/Ecc.java new file mode 100644 index 0000000..1ce9752 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/Ecc.java @@ -0,0 +1,61 @@ +package io.nayuki.qrcodegen; + +/** + * The error correction level in a QR Code symbol. + */ +public class Ecc { + /** The QR Code can tolerate about 7% erroneous codewords. */ + public static final Ecc LOW = new Ecc(1, + new byte[] { -1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, + 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, + new byte[] { -1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, + 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25 }); + /** The QR Code can tolerate about 15% erroneous codewords. */ + public static final Ecc MEDIUM = new Ecc(0, + new byte[] { -1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28 }, + new byte[] { -1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, + 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49 }); + /** The QR Code can tolerate about 25% erroneous codewords. */ + public static final Ecc QUARTILE = new Ecc(3, + new byte[] { -1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, + 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, + new byte[] { -1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, + 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68 }); + /** The QR Code can tolerate about 30% erroneous codewords. */ + public static final Ecc HIGH = new Ecc(2, + new byte[] { -1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, + new byte[] { -1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, + 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81 }); + + private final int formatBits; + private final byte[] blockLength; + private final byte[] numberOfBlocks; + + // For formatBits and blockLength, array index is Version: (note that index 0 is + // for padding, and is set to an illegal value) + private Ecc(int formatBits, byte[] blockLength, byte[] numberOfBlocks) { + this.formatBits = formatBits; + this.blockLength = blockLength; + this.numberOfBlocks = numberOfBlocks; + } + + public int getFormatBits() { + return formatBits; + } + + public byte getBlockLength(int version) { + return blockLength[version]; + } + + public byte getNumberOfBlock(int version) { + return numberOfBlocks[version]; + } + + // Must in ascending order of error protection + // so that values() work properly + public static Ecc[] values() { + return new Ecc[] { LOW, MEDIUM, QUARTILE, HIGH }; + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCode.java b/java/src/main/java/io/nayuki/qrcodegen/QrCode.java index dcb8b6b..5ade16c 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCode.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCode.java @@ -421,7 +421,7 @@ public final class QrCode { // based on the given mask and this object's error correction level field. private void drawFormatBits(int msk) { // Calculate error correction code and pack bits - int data = errorCorrectionLevel.formatBits << 3 | msk; // errCorrLvl is uint2, mask is uint3 + int data = errorCorrectionLevel.getFormatBits() << 3 | msk; // errCorrLvl is uint2, mask is uint3 int rem = data; for (int i = 0; i < 10; i++) rem = (rem << 1) ^ ((rem >>> 9) * 0x537); @@ -512,8 +512,8 @@ public final class QrCode { throw new IllegalArgumentException(); // Calculate parameter numbers - int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[errorCorrectionLevel.ordinal()][version]; - int blockEccLen = ECC_CODEWORDS_PER_BLOCK [errorCorrectionLevel.ordinal()][version]; + int numBlocks = errorCorrectionLevel.getNumberOfBlock(version); + int blockEccLen = errorCorrectionLevel.getBlockLength(version); int rawCodewords = getNumRawDataModules(version) / 8; int numShortBlocks = numBlocks - rawCodewords % numBlocks; int shortBlockLen = rawCodewords / numBlocks; @@ -830,9 +830,9 @@ public final class QrCode { // QR Code of the given version number and error correction level, with remainder bits discarded. // This stateless pure function could be implemented as a (40*4)-cell lookup table. static int getNumDataCodewords(int ver, Ecc ecl) { - return getNumRawDataModules(ver) / 8 - - ECC_CODEWORDS_PER_BLOCK [ecl.ordinal()][ver] - * NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal()][ver]; + return getNumRawDataModules(ver) / 8 + - ecl.getBlockLength(ver) + * ecl.getNumberOfBlock(ver); } @@ -889,47 +889,4 @@ public final class QrCode { private static final int PENALTY_N3 = 40; private static final int PENALTY_N4 = 10; - - private static final byte[][] ECC_CODEWORDS_PER_BLOCK = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low - {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium - {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile - {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High - }; - - private static final byte[][] NUM_ERROR_CORRECTION_BLOCKS = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low - {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium - {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile - {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High - }; - - - - /*---- Public helper enumeration ----*/ - - /** - * The error correction level in a QR Code symbol. - */ - public enum Ecc { - // Must be declared in ascending order of error protection - // so that the implicit ordinal() and values() work properly - /** The QR Code can tolerate about 7% erroneous codewords. */ LOW(1), - /** The QR Code can tolerate about 15% erroneous codewords. */ MEDIUM(0), - /** The QR Code can tolerate about 25% erroneous codewords. */ QUARTILE(3), - /** The QR Code can tolerate about 30% erroneous codewords. */ HIGH(2); - - // In the range 0 to 3 (unsigned 2-bit integer). - final int formatBits; - - // Constructor. - private Ecc(int fb) { - formatBits = fb; - } - } - } \ No newline at end of file diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java index 3c50bda..f9316d7 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java @@ -53,7 +53,7 @@ public final class QrCodeGeneratorDemo { // Creates a single QR Code, then writes it to a PNG file and an SVG file. private static void doBasicDemo() throws IOException { String text = "Hello, world!"; // User-supplied Unicode text - QrCode.Ecc errCorLvl = QrCode.Ecc.LOW; // Error correction level + Ecc errCorLvl = Ecc.LOW; // Error correction level QrCode qr = QrCode.encodeText(text, errCorLvl); // Make the QR Code symbol @@ -73,15 +73,15 @@ public final class QrCodeGeneratorDemo { QrCode qr; // Numeric mode encoding (3.33 bits per digit) - qr = QrCode.encodeText("314159265358979323846264338327950288419716939937510", QrCode.Ecc.MEDIUM); + qr = QrCode.encodeText("314159265358979323846264338327950288419716939937510", Ecc.MEDIUM); writePng(qr.toImage(13, 1), "pi-digits-QR.png"); // Alphanumeric mode encoding (5.5 bits per character) - qr = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode.Ecc.HIGH); + qr = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", Ecc.HIGH); writePng(qr.toImage(10, 2), "alphanumeric-QR.png"); // Unicode text as UTF-8 - qr = QrCode.encodeText("こんにちwa、世界! αβγδ", QrCode.Ecc.QUARTILE); + qr = QrCode.encodeText("こんにちwa、世界! αβγδ", Ecc.QUARTILE); writePng(qr.toImage(10, 3), "unicode-QR.png"); // Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland) @@ -92,7 +92,7 @@ public final class QrCodeGeneratorDemo { + "'without pictures or conversations?' So she was considering in her own mind (as well as she could, " + "for the hot day made her feel very sleepy and stupid), whether the pleasure of making a " + "daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly " - + "a White Rabbit with pink eyes ran close by her.", QrCode.Ecc.HIGH); + + "a White Rabbit with pink eyes ran close by her.", Ecc.HIGH); writePng(qr.toImage(6, 10), "alice-wonderland-QR.png"); } @@ -105,36 +105,36 @@ public final class QrCodeGeneratorDemo { // Illustration "silver" String silver0 = "THE SQUARE ROOT OF 2 IS 1."; String silver1 = "41421356237309504880168872420969807856967187537694807317667973799"; - qr = QrCode.encodeText(silver0 + silver1, QrCode.Ecc.LOW); + qr = QrCode.encodeText(silver0 + silver1, Ecc.LOW); writePng(qr.toImage(10, 3), "sqrt2-monolithic-QR.png"); segs = Arrays.asList( QrSegment.makeAlphanumeric(silver0), QrSegment.makeNumeric(silver1)); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW); + qr = QrCode.encodeSegments(segs, Ecc.LOW); writePng(qr.toImage(10, 3), "sqrt2-segmented-QR.png"); // Illustration "golden" String golden0 = "Golden ratio φ = 1."; String golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374"; String golden2 = "......"; - qr = QrCode.encodeText(golden0 + golden1 + golden2, QrCode.Ecc.LOW); + qr = QrCode.encodeText(golden0 + golden1 + golden2, Ecc.LOW); writePng(qr.toImage(8, 5), "phi-monolithic-QR.png"); segs = Arrays.asList( QrSegment.makeBytes(golden0.getBytes(StandardCharsets.UTF_8)), QrSegment.makeNumeric(golden1), QrSegment.makeAlphanumeric(golden2)); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW); + qr = QrCode.encodeSegments(segs, Ecc.LOW); writePng(qr.toImage(8, 5), "phi-segmented-QR.png"); // Illustration "Madoka": kanji, kana, Cyrillic, full-width Latin, Greek characters String madoka = "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?"; - qr = QrCode.encodeText(madoka, QrCode.Ecc.LOW); + qr = QrCode.encodeText(madoka, Ecc.LOW); writePng(qr.toImage(9, 4), "madoka-utf8-QR.png"); segs = Arrays.asList(QrSegmentAdvanced.makeKanji(madoka)); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW); + qr = QrCode.encodeSegments(segs, Ecc.LOW); writePng(qr.toImage(9, 4), "madoka-kanji-QR.png"); } @@ -146,20 +146,20 @@ public final class QrCodeGeneratorDemo { // Project Nayuki URL segs = QrSegment.makeSegments("https://www.nayuki.io/"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true); // Automatic mask + qr = QrCode.encodeSegments(segs, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true); // Automatic mask writePng(qr.toImage(8, 6), "project-nayuki-automask-QR.png"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true); // Force mask 3 + qr = QrCode.encodeSegments(segs, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true); // Force mask 3 writePng(qr.toImage(8, 6), "project-nayuki-mask3-QR.png"); // Chinese text as UTF-8 segs = QrSegment.makeSegments("維基百科(Wikipedia,聆聽i/ˌwɪkᵻˈpiːdi.ə/)是一個自由內容、公開編輯且多語言的網路百科全書協作計畫"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true); // Force mask 0 + qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true); // Force mask 0 writePng(qr.toImage(10, 3), "unicode-mask0-QR.png"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true); // Force mask 1 + qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true); // Force mask 1 writePng(qr.toImage(10, 3), "unicode-mask1-QR.png"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true); // Force mask 5 + qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true); // Force mask 5 writePng(qr.toImage(10, 3), "unicode-mask5-QR.png"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true); // Force mask 7 + qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true); // Force mask 7 writePng(qr.toImage(10, 3), "unicode-mask7-QR.png"); } diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java index 4cf9de3..54f3dbf 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java @@ -82,7 +82,7 @@ public final class QrCodeGeneratorWorker { segs = Arrays.asList(QrSegment.makeBytes(data)); try { // Try to make QR Code symbol - QrCode qr = QrCode.encodeSegments(segs, QrCode.Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); + QrCode qr = QrCode.encodeSegments(segs, Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); // Print grid of modules System.out.println(qr.version); for (int y = 0; y < qr.size; y++) { From 1980ace59524357baa69bb4f89362945774aa856 Mon Sep 17 00:00:00 2001 From: minsu4107 <32637512+minsu4107@users.noreply.github.com> Date: Sat, 6 Jun 2020 18:18:11 +0900 Subject: [PATCH 13/35] 1. Strategy Pattern 2. QrSemgmentAdvanced.java 3. Remain Concrete Strategy upload --- .../java/io/nayuki/qrcodegen/KanjiMode.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java diff --git a/java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java b/java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java new file mode 100644 index 0000000..9729f93 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java @@ -0,0 +1,23 @@ +package io.nayuki.qrcodegen; + +public class KanjiMode extends QrMode { + protected KanjiMode(int mode, int... ccbits) { + modeBits = mode; + numBitsCharCount = ccbits; + } + + protected KanjiMode() { + modeBits = 0x8; + numBitsCharCount[0] = 8; + numBitsCharCount[1] = 10; + numBitsCharCount[2] = 12; + } + + public int getcost(int pre, int codePoint) { + return pre + 78; + } + + public QrSegment making(String str) { + return QrSegmentAdvanced.makeKanji(str); + } +} From 419466168efdc50c02e9ea979b1739739be17925 Mon Sep 17 00:00:00 2001 From: gerzees Date: Sat, 6 Jun 2020 18:23:26 +0900 Subject: [PATCH 14/35] 1. Extract method 2. Ecc from QrCode 3. I did not changed QrCode.Ecc to Ecc in signature of makeSegmentsOptimally() --- java/src/main/java/io/nayuki/qrcodegen/QrSegmentAdvanced.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegmentAdvanced.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegmentAdvanced.java index b125f18..50066e8 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegmentAdvanced.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegmentAdvanced.java @@ -68,7 +68,7 @@ public final class QrSegmentAdvanced { * @throws IllegalArgumentException if 1 ≤ minVersion ≤ maxVersion ≤ 40 is violated * @throws DataTooLongException if the text fails to fit in the maxVersion QR Code at the ECL */ - public static List makeSegmentsOptimally(String text, QrCode.Ecc ecl, int minVersion, int maxVersion) { + public static List makeSegmentsOptimally(String text, Ecc ecl, int minVersion, int maxVersion) { // Check arguments Objects.requireNonNull(text); Objects.requireNonNull(ecl); From dd7d92aee6a52000ea3efaeb28631c4f06fff0fb Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 18:39:32 +0900 Subject: [PATCH 15/35] Refactoring operation name : extract method Refactoring object : makeBytes(byte[] data) Reason : part of code has possibility to change so, make this part to method(changeByteToSegment). --- java/src/main/java/io/nayuki/qrcodegen/QrSegment.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 0fb22b6..ab8201b 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -62,10 +62,14 @@ public final class QrSegment { Objects.requireNonNull(data); BitBuffer bitBuffer = new BitBuffer(); for (byte one_byte : data) - bitBuffer.appendBits(one_byte & 0xFF, 8); + changeByteToSegment(bitBuffer, one_byte); return new QrSegment(QrSegment.Mode.BYTE, data.length, bitBuffer); } + public static void changeByteToSegment(BitBuffer bitBuffer, byte one_byte) { + bitBuffer.appendBits(one_byte & 0xFF, 8); + } + /** * Returns a segment representing the specified string of decimal digits encoded in numeric mode. From 50bf7cf2dc099ccd1d9a5b55e8782d273d4b3952 Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 18:44:47 +0900 Subject: [PATCH 16/35] Refactoring operation name : extract method Refactoring object : makeNumeric(String digits) Reason : part of code has possibility to change so, make this part to method(changeNumericToSegment). And part of code is complicated boolean expression so, make this part to method(containNonNumericCharaters) --- .../main/java/io/nayuki/qrcodegen/QrSegment.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index ab8201b..4953ab9 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -78,20 +78,28 @@ public final class QrSegment { * @throws NullPointerException if the string is {@code null} * @throws IllegalArgumentException if the string contains non-digit characters */ - public static QrSegment makeNumeric(String digits) { + public QrSegment makeNumeric(String digits) { Objects.requireNonNull(digits); - if (!NUMERIC_REGEX.matcher(digits).matches()) + if (containNonNumericCharaters(digits)) throw new IllegalArgumentException("String contains non-numeric characters"); BitBuffer bitBuffer = new BitBuffer(); + changeNumericToSegment(digits, bitBuffer); + return new QrSegment(QrSegment.Mode.NUMERIC, digits.length(), bitBuffer); + } + + public static void changeNumericToSegment(String digits, BitBuffer bitBuffer) { for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration int n = Math.min(digits.length() - i, 3); bitBuffer.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); i += n; } - return new QrSegment(Mode.NUMERIC, digits.length(), bitBuffer); } + public static boolean containNonNumericCharaters(String digits) { + return !QrSegment.NUMERIC_REGEX.matcher(digits).matches(); + } + /** /** * Returns a segment representing the specified text string encoded in alphanumeric mode. From 658630752ee7b2c22746411c334f2237e4cfc2db Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 18:46:29 +0900 Subject: [PATCH 17/35] Refactoring operation name : extract method Refactoring object : makeAlphanumeric(String text) Reason : part of code has possibility to change so, make this part to method(changeAlphaNumericStringToSegment). --- .../java/io/nayuki/qrcodegen/QrSegment.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 4953ab9..92c8746 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -109,25 +109,27 @@ public final class QrSegment { * @return a segment (not {@code null}) containing the text * @throws NullPointerException if the string is {@code null} * @throws IllegalArgumentException if the string contains non-encodable characters - */ - public static QrSegment makeAlphanumeric(String text) { + */ + public QrSegment makeAlphanumeric(String text) { Objects.requireNonNull(text); - if (!ALPHANUMERIC_REGEX.matcher(text).matches()) + if (!QrSegment.ALPHANUMERIC_REGEX.matcher(text).matches()) throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); BitBuffer bitBuffer = new BitBuffer(); + changeAlphaNumericStringToSegment(text, bitBuffer); + return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length(), bitBuffer); + } + + public static void changeAlphaNumericStringToSegment(String text, BitBuffer bitBuffer) { int i; for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 - int temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; - temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); + int temp = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; + temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); bitBuffer.appendBits(temp, 11); } if (i < text.length()) // 1 character remaining - bitBuffer.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); - return new QrSegment(Mode.ALPHANUMERIC, text.length(), bitBuffer); + bitBuffer.appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); } - - /** * Returns a list of zero or more segments to represent the specified Unicode text string. * The result may use various segment modes and switch modes to optimize the length of the bit stream. From 33c8042f00a6c38e913c694322145d7e2128f3ce Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 20:31:10 +0900 Subject: [PATCH 18/35] Refactoring operation name : extract class Refactoring object : MakeBytesToSegment Reason : makeBytes, changeByteToSegment has independent role. So, make these function to class(MakeBytesToSegment). --- .../nayuki/qrcodegen/MakeBytesToSegment.java | 36 +++++++++++++++++++ .../java/io/nayuki/qrcodegen/QrSegment.java | 22 ------------ 2 files changed, 36 insertions(+), 22 deletions(-) create mode 100644 java/src/main/java/io/nayuki/qrcodegen/MakeBytesToSegment.java diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeBytesToSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeBytesToSegment.java new file mode 100644 index 0000000..807d574 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeBytesToSegment.java @@ -0,0 +1,36 @@ +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +public class MakeBytesToSegment implements MakeSegment { + + /** + * Returns a segment representing the specified binary data + * encoded in byte mode. All input byte arrays are acceptable. + *

Any text string can be converted to UTF-8 bytes ({@code + * s.getBytes(StandardCharsets.UTF_8)}) and encoded as a byte mode segment.

+ * @param data the binary data (not {@code null}) + * @return a segment (not {@code null}) containing the data + * @throws NullPointerException if the array is {@code null} + */ + public QrSegment excute(String text) { + byte[] data = text.getBytes(StandardCharsets.UTF_8)); + + Objects.requireNonNull(data); + BitBuffer bitBuffer = new BitBuffer(); + for (byte bits : data) + changeByteToSegment(bitBuffer, bits); + return new QrSegment(QrSegment.Mode.BYTE, data.length, bitBuffer); + } + + public QrSegment excuteForBytedata(byte[] data) { + Objects.requireNonNull(data); + BitBuffer bitBuffer = new BitBuffer(); + for (byte bits : data) + changeByteToSegment(bitBuffer, bits); + return new QrSegment(QrSegment.Mode.BYTE, data.length, bitBuffer); + } + + public static void changeByteToSegment(BitBuffer bitBuffer, byte bits) { + bitBuffer.appendBits(bits & 0xFF, 8); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 92c8746..67cce84 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -49,28 +49,6 @@ public final class QrSegment { /*---- Static factory functions (mid level) ----*/ - /** - * Returns a segment representing the specified binary data - * encoded in byte mode. All input byte arrays are acceptable. - *

Any text string can be converted to UTF-8 bytes ({@code - * s.getBytes(StandardCharsets.UTF_8)}) and encoded as a byte mode segment.

- * @param data the binary data (not {@code null}) - * @return a segment (not {@code null}) containing the data - * @throws NullPointerException if the array is {@code null} - */ - public static QrSegment makeBytes(byte[] data) { - Objects.requireNonNull(data); - BitBuffer bitBuffer = new BitBuffer(); - for (byte one_byte : data) - changeByteToSegment(bitBuffer, one_byte); - return new QrSegment(QrSegment.Mode.BYTE, data.length, bitBuffer); - } - - public static void changeByteToSegment(BitBuffer bitBuffer, byte one_byte) { - bitBuffer.appendBits(one_byte & 0xFF, 8); - } - - /** * Returns a segment representing the specified string of decimal digits encoded in numeric mode. * @param digits the text (not {@code null}), with only digits from 0 to 9 allowed From 937a2dfc53ca041b17d612fe1aae478d088ef329 Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 20:34:23 +0900 Subject: [PATCH 19/35] Refactoring operation name : extract class Refactoring object : MakeBytesToSegment Reason : makeNumeric, changeNumericToSegment, containNonNumericCharaters has independent role. So, make these function to class(MakeNumericToSegment). --- .../qrcodegen/MakeNumericToSegment.java | 33 +++++++++++++++++++ .../java/io/nayuki/qrcodegen/QrSegment.java | 30 ----------------- 2 files changed, 33 insertions(+), 30 deletions(-) create mode 100644 java/src/main/java/io/nayuki/qrcodegen/MakeNumericToSegment.java diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeNumericToSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeNumericToSegment.java new file mode 100644 index 0000000..3da7b7e --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeNumericToSegment.java @@ -0,0 +1,33 @@ +import java.util.Objects; + +public class MakeNumericToSegment implements MakeSegment { + + /** + * Returns a segment representing the specified string of decimal digits encoded in numeric mode. + * @param digits the text (not {@code null}), with only digits from 0 to 9 allowed + * @return a segment (not {@code null}) containing the text + * @throws NullPointerException if the string is {@code null} + * @throws IllegalArgumentException if the string contains non-digit characters + */ + public QrSegment excute(String digits) { + Objects.requireNonNull(digits); + if (containNonNumericCharaters(digits)) + throw new IllegalArgumentException("String contains non-numeric characters"); + + BitBuffer bitBuffer = new BitBuffer(); + changeNumericToSegment(digits, bitBuffer); + return new QrSegment(QrSegment.Mode.NUMERIC, digits.length(), bitBuffer); + } + + public static void changeNumericToSegment(String digits, BitBuffer bitBuffer) { + for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration + int n = Math.min(digits.length() - i, 3); + bitBuffer.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); + i += n; + } + } + + public static boolean containNonNumericCharaters(String digits) { + return !QrSegment.NUMERIC_REGEX.matcher(digits).matches(); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 67cce84..4b12881 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -49,36 +49,6 @@ public final class QrSegment { /*---- Static factory functions (mid level) ----*/ - /** - * Returns a segment representing the specified string of decimal digits encoded in numeric mode. - * @param digits the text (not {@code null}), with only digits from 0 to 9 allowed - * @return a segment (not {@code null}) containing the text - * @throws NullPointerException if the string is {@code null} - * @throws IllegalArgumentException if the string contains non-digit characters - */ - public QrSegment makeNumeric(String digits) { - Objects.requireNonNull(digits); - if (containNonNumericCharaters(digits)) - throw new IllegalArgumentException("String contains non-numeric characters"); - - BitBuffer bitBuffer = new BitBuffer(); - changeNumericToSegment(digits, bitBuffer); - return new QrSegment(QrSegment.Mode.NUMERIC, digits.length(), bitBuffer); - } - - public static void changeNumericToSegment(String digits, BitBuffer bitBuffer) { - for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration - int n = Math.min(digits.length() - i, 3); - bitBuffer.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); - i += n; - } - } - - public static boolean containNonNumericCharaters(String digits) { - return !QrSegment.NUMERIC_REGEX.matcher(digits).matches(); - } - /** - /** * Returns a segment representing the specified text string encoded in alphanumeric mode. * The characters allowed are: 0 to 9, A to Z (uppercase only), space, From 27dc7057c9a154bb46efbfa771e55452477b9597 Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 20:36:50 +0900 Subject: [PATCH 20/35] Refactoring operation name : extract class Refactoring object : MakeAlphaNumericToSegment Reason : makeAlphanumeric, changeAlphaNumericStringToSegment has independent role. So, make these function to class(MakeAlphaNumericToSegment). --- .../qrcodegen/MakeAlphaNumericToSegment.java | 34 +++++++++++++++++++ .../java/io/nayuki/qrcodegen/QrSegment.java | 29 ---------------- 2 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 java/src/main/java/io/nayuki/qrcodegen/MakeAlphaNumericToSegment.java diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeAlphaNumericToSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeAlphaNumericToSegment.java new file mode 100644 index 0000000..66bd854 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeAlphaNumericToSegment.java @@ -0,0 +1,34 @@ +import java.util.Objects; + +public class MakeAlphaNumericToSegment implements MakeSegment { + + /** + * Returns a segment representing the specified text string encoded in alphanumeric mode. + * The characters allowed are: 0 to 9, A to Z (uppercase only), space, + * dollar, percent, asterisk, plus, hyphen, period, slash, colon. + * @param text the text (not {@code null}), with only certain characters allowed + * @return a segment (not {@code null}) containing the text + * @throws NullPointerException if the string is {@code null} + * @throws IllegalArgumentException if the string contains non-encodable characters + */ + public QrSegment excute(String text) { + Objects.requireNonNull(text); + if (!QrSegment.ALPHANUMERIC_REGEX.matcher(text).matches()) + throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); + + BitBuffer bitBuffer = new BitBuffer(); + changeAlphaNumericStringToSegment(text, bitBuffer); + return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length(), bitBuffer); + } + + public static void changeAlphaNumericStringToSegment(String text, BitBuffer bitBuffer) { + int i; + for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 + int temp = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; + temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); + bitBuffer.appendBits(temp, 11); + } + if (i < text.length()) // 1 character remaining + bitBuffer.appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 4b12881..3d261f7 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -49,35 +49,6 @@ public final class QrSegment { /*---- Static factory functions (mid level) ----*/ - /** - * Returns a segment representing the specified text string encoded in alphanumeric mode. - * The characters allowed are: 0 to 9, A to Z (uppercase only), space, - * dollar, percent, asterisk, plus, hyphen, period, slash, colon. - * @param text the text (not {@code null}), with only certain characters allowed - * @return a segment (not {@code null}) containing the text - * @throws NullPointerException if the string is {@code null} - * @throws IllegalArgumentException if the string contains non-encodable characters - */ - public QrSegment makeAlphanumeric(String text) { - Objects.requireNonNull(text); - if (!QrSegment.ALPHANUMERIC_REGEX.matcher(text).matches()) - throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); - - BitBuffer bitBuffer = new BitBuffer(); - changeAlphaNumericStringToSegment(text, bitBuffer); - return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length(), bitBuffer); - } - - public static void changeAlphaNumericStringToSegment(String text, BitBuffer bitBuffer) { - int i; - for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 - int temp = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; - temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); - bitBuffer.appendBits(temp, 11); - } - if (i < text.length()) // 1 character remaining - bitBuffer.appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); - } /** * Returns a list of zero or more segments to represent the specified Unicode text string. * The result may use various segment modes and switch modes to optimize the length of the bit stream. From 9f70303e5ded7def81ff607cafabcac397325b61 Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 21:12:34 +0900 Subject: [PATCH 21/35] 1. Design pattern name : Factory method pattern 2. Design pattern object : QrSegment, MakeAlphaNumericToSegment,MakeBytesToSegment, MakeNumericToSegment 3. reason : function to make segment is changed by kind of string. And there is possible to add function to make segment. 4. explanation : product : MakeSegment, concrete product : MakeBytesToSegment, MakeNumericToSegment, MakeAlphaNumericToSegment creator : QrSegmentTo concrete creator : MakeSegmentFactory --- .../java/io/nayuki/qrcodegen/MakeSegment.java | 4 ++++ .../io/nayuki/qrcodegen/MakeSegmentFactory.java | 15 +++++++++++++++ .../main/java/io/nayuki/qrcodegen/QrSegment.java | 10 ++++++++++ 3 files changed, 29 insertions(+) create mode 100644 java/src/main/java/io/nayuki/qrcodegen/MakeSegment.java create mode 100644 java/src/main/java/io/nayuki/qrcodegen/MakeSegmentFactory.java diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeSegment.java new file mode 100644 index 0000000..ccca2ba --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeSegment.java @@ -0,0 +1,4 @@ + +public interface MakeSegment { + public QrSegment excute(String text); +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeSegmentFactory.java b/java/src/main/java/io/nayuki/qrcodegen/MakeSegmentFactory.java new file mode 100644 index 0000000..b21a516 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeSegmentFactory.java @@ -0,0 +1,15 @@ +public class MakeSegmentFactory { + public static MakeSegment getMakeSegment(String text) { + MakeSegment makeSegment = null; + + if (text.equals("")); // Leave result empty + else if (QrSegment.NUMERIC_REGEX.matcher(text).matches()) + makeSegment = new MakeNumericToSegment(); + else if (QrSegment.ALPHANUMERIC_REGEX.matcher(text).matches()) + makeSegment = new MakeAlphaNumericToSegment(); + else + makeSegment = new MakeBytesToSegment(); + + return makeSegment; + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 3d261f7..780b1bc 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -71,7 +71,17 @@ public final class QrSegment { return segments; } + public static List makeSegments(String text) { + Objects.requireNonNull(text); + // Select the most efficient segment encoding automatically + List segments = new ArrayList<>(); + + MakeSegment makeSegment = MakeSegmentFactory.getMakeSegment(text); + + segments.add(makeSegment.excute(text)); + return segments; + } /** * Returns a segment representing an Extended Channel Interpretation * (ECI) designator with the specified assignment value. From ec2976f6fa8a6747b0a9e7b2d85466ed863dfd9a Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 21:15:40 +0900 Subject: [PATCH 22/35] Refactoring operation name : rename Refactoring object : QrCodeGeneratorDemo.java Reason : QrCode qr, List segs is too simple to express meaning. So,rename qr to qrCode and segs to segments. --- .settings/org.eclipse.core.resources.prefs | 2 + .../nayuki/qrcodegen/QrCodeGeneratorDemo.java | 88 +++++++++---------- 2 files changed, 46 insertions(+), 44 deletions(-) create mode 100644 .settings/org.eclipse.core.resources.prefs diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..e5bd3bf --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding//java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java=UTF-8 diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java index 3c50bda..a001ff9 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java @@ -70,22 +70,22 @@ public final class QrCodeGeneratorDemo { // Creates a variety of QR Codes that exercise different features of the library, and writes each one to file. private static void doVarietyDemo() throws IOException { - QrCode qr; + QrCode qrCode; // Numeric mode encoding (3.33 bits per digit) - qr = QrCode.encodeText("314159265358979323846264338327950288419716939937510", QrCode.Ecc.MEDIUM); - writePng(qr.toImage(13, 1), "pi-digits-QR.png"); + qrCode = QrCode.encodeText("314159265358979323846264338327950288419716939937510", QrCode.Ecc.MEDIUM); + writePng(qrCode.toImage(13, 1), "pi-digits-QR.png"); // Alphanumeric mode encoding (5.5 bits per character) - qr = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode.Ecc.HIGH); - writePng(qr.toImage(10, 2), "alphanumeric-QR.png"); + qrCode = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode.Ecc.HIGH); + writePng(qrCode.toImage(10, 2), "alphanumeric-QR.png"); // Unicode text as UTF-8 - qr = QrCode.encodeText("こんにちwa、世界! αβγδ", QrCode.Ecc.QUARTILE); - writePng(qr.toImage(10, 3), "unicode-QR.png"); + qrCode = QrCode.encodeText("占쎄괭占쎄뎐占쎄쾽占쎄굶wa占쎄낌�닟占쎈르塋딉옙 �뀭汝뷸Ь�걣", QrCode.Ecc.QUARTILE); + writePng(qrCode.toImage(10, 3), "unicode-QR.png"); // Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland) - qr = QrCode.encodeText( + qrCode = QrCode.encodeText( "Alice was beginning to get very tired of sitting by her sister on the bank, " + "and of having nothing to do: once or twice she had peeped into the book her sister was reading, " + "but it had no pictures or conversations in it, 'and what is the use of a book,' thought Alice " @@ -93,74 +93,74 @@ public final class QrCodeGeneratorDemo { + "for the hot day made her feel very sleepy and stupid), whether the pleasure of making a " + "daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly " + "a White Rabbit with pink eyes ran close by her.", QrCode.Ecc.HIGH); - writePng(qr.toImage(6, 10), "alice-wonderland-QR.png"); + writePng(qrCode.toImage(6, 10), "alice-wonderland-QR.png"); } // Creates QR Codes with manually specified segments for better compactness. private static void doSegmentDemo() throws IOException { - QrCode qr; - List segs; + QrCode qrCode; + List segments; // Illustration "silver" String silver0 = "THE SQUARE ROOT OF 2 IS 1."; String silver1 = "41421356237309504880168872420969807856967187537694807317667973799"; - qr = QrCode.encodeText(silver0 + silver1, QrCode.Ecc.LOW); - writePng(qr.toImage(10, 3), "sqrt2-monolithic-QR.png"); + qrCode = QrCode.encodeText(silver0 + silver1, QrCode.Ecc.LOW); + writePng(qrCode.toImage(10, 3), "sqrt2-monolithic-QR.png"); - segs = Arrays.asList( + segments = Arrays.asList( QrSegment.makeAlphanumeric(silver0), QrSegment.makeNumeric(silver1)); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW); - writePng(qr.toImage(10, 3), "sqrt2-segmented-QR.png"); + qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.LOW); + writePng(qrCode.toImage(10, 3), "sqrt2-segmented-QR.png"); // Illustration "golden" - String golden0 = "Golden ratio φ = 1."; + String golden0 = "Golden ratio 占쏙옙 = 1."; String golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374"; String golden2 = "......"; - qr = QrCode.encodeText(golden0 + golden1 + golden2, QrCode.Ecc.LOW); - writePng(qr.toImage(8, 5), "phi-monolithic-QR.png"); + qrCode = QrCode.encodeText(golden0 + golden1 + golden2, QrCode.Ecc.LOW); + writePng(qrCode.toImage(8, 5), "phi-monolithic-QR.png"); - segs = Arrays.asList( + segments = Arrays.asList( QrSegment.makeBytes(golden0.getBytes(StandardCharsets.UTF_8)), QrSegment.makeNumeric(golden1), QrSegment.makeAlphanumeric(golden2)); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW); - writePng(qr.toImage(8, 5), "phi-segmented-QR.png"); + qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.LOW); + writePng(qrCode.toImage(8, 5), "phi-segmented-QR.png"); // Illustration "Madoka": kanji, kana, Cyrillic, full-width Latin, Greek characters - String madoka = "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?"; - qr = QrCode.encodeText(madoka, QrCode.Ecc.LOW); - writePng(qr.toImage(9, 4), "madoka-utf8-QR.png"); + String madoka = "占쎈슞異몌쫲類앹빼阿잙뀍寃뀐옙寃묕옙嫄�占쎌겳占쎄묻占쎄텤占쎄텠占쎈씞寃귨옙寃랃옙怨ο옙占쏙옙�꺂癒믪꼨占쏙옙影�袁ы맀影�蹂⑺맟占쏙옙鰲��뀭塋딉옙"; + qrCode = QrCode.encodeText(madoka, QrCode.Ecc.LOW); + writePng(qrCode.toImage(9, 4), "madoka-utf8-QR.png"); - segs = Arrays.asList(QrSegmentAdvanced.makeKanji(madoka)); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW); - writePng(qr.toImage(9, 4), "madoka-kanji-QR.png"); + segments = Arrays.asList(QrSegmentAdvanced.makeKanji(madoka)); + qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.LOW); + writePng(qrCode.toImage(9, 4), "madoka-kanji-QR.png"); } // Creates QR Codes with the same size and contents but different mask patterns. private static void doMaskDemo() throws IOException { - QrCode qr; - List segs; + QrCode qrCode; + List segments; // Project Nayuki URL - segs = QrSegment.makeSegments("https://www.nayuki.io/"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true); // Automatic mask - writePng(qr.toImage(8, 6), "project-nayuki-automask-QR.png"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true); // Force mask 3 - writePng(qr.toImage(8, 6), "project-nayuki-mask3-QR.png"); + segments = QrSegment.makeSegments("https://www.nayuki.io/"); + qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true); // Automatic mask + writePng(qrCode.toImage(8, 6), "project-nayuki-automask-QR.png"); + qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true); // Force mask 3 + writePng(qrCode.toImage(8, 6), "project-nayuki-mask3-QR.png"); // Chinese text as UTF-8 - segs = QrSegment.makeSegments("維基百科(Wikipedia,聆聽i/ˌwɪkᵻˈpiːdi.ə/)是一個自由內容、公開編輯且多語言的網路百科全書協作計畫"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true); // Force mask 0 - writePng(qr.toImage(10, 3), "unicode-mask0-QR.png"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true); // Force mask 1 - writePng(qr.toImage(10, 3), "unicode-mask1-QR.png"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true); // Force mask 5 - writePng(qr.toImage(10, 3), "unicode-mask5-QR.png"); - qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true); // Force mask 7 - writePng(qr.toImage(10, 3), "unicode-mask7-QR.png"); + segments = QrSegment.makeSegments("力놂옙占쎌쓢占쎌뇥�뇖臾뺥렩Wikipedia塋딅슜嫄앾옙寃켲/占쎈샆�뎚藥�戮먮뒰i占쎈쫨i.占쏙옙/塋딅맚�궦鼇앾옙占쎈뿨�닅占쎈뎨占쎈�깍Ⅴ諛ㅿ옙怨⑸�띰옙堉�歷뜯몼�꽎鼇앸떱姨�亦껋쉮占쏙옙�돦力녠엽�윭占쎌뇥�뇖臾덈�뀐옙�럱占쎈쐭俑앹뮂怡ワ옙鍮�"); + qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true); // Force mask 0 + writePng(qrCode.toImage(10, 3), "unicode-mask0-QR.png"); + qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true); // Force mask 1 + writePng(qrCode.toImage(10, 3), "unicode-mask1-QR.png"); + qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true); // Force mask 5 + writePng(qrCode.toImage(10, 3), "unicode-mask5-QR.png"); + qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true); // Force mask 7 + writePng(qrCode.toImage(10, 3), "unicode-mask7-QR.png"); } From b4a141b111b45370f06ea3c691e3ee0ee5b0c0ae Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sat, 6 Jun 2020 21:21:48 +0900 Subject: [PATCH 23/35] Refactoring operation name : rename Refactoring object : processCase(Scanner input) Reason : int b, List segs, QrCode qr is too simple to express meaning. So,rename b to one_byte, segs to segments, qr to qrCode. --- .../qrcodegen/QrCodeGeneratorWorker.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java index 4cf9de3..a11a39e 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java @@ -57,11 +57,11 @@ public final class QrCodeGeneratorWorker { boolean isAscii = true; byte[] data = new byte[length]; for (int i = 0; i < data.length; i++) { - int b = input.nextInt(); - if (b < 0 || b > 255) + int one_byte = input.nextInt(); + if (one_byte < 0 || one_byte > 255) throw new RuntimeException(); - data[i] = (byte)b; - isAscii &= b < 128; + data[i] = (byte)one_byte; + isAscii &= one_byte < 128; } // Read encoding parameters @@ -75,19 +75,19 @@ public final class QrCodeGeneratorWorker { throw new RuntimeException(); // Make segments for encoding - List segs; + List segments; if (isAscii) - segs = QrSegment.makeSegments(new String(data, StandardCharsets.US_ASCII)); + segments = QrSegment.makeSegments(new String(data, StandardCharsets.US_ASCII)); else - segs = Arrays.asList(QrSegment.makeBytes(data)); + segments = Arrays.asList(QrSegment.makeBytes(data)); try { // Try to make QR Code symbol - QrCode qr = QrCode.encodeSegments(segs, QrCode.Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); + QrCode qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); // Print grid of modules - System.out.println(qr.version); - for (int y = 0; y < qr.size; y++) { - for (int x = 0; x < qr.size; x++) - System.out.println(qr.getModule(x, y) ? 1 : 0); + System.out.println(qrCode.version); + for (int y = 0; y < qrCode.size; y++) { + for (int x = 0; x < qrCode.size; x++) + System.out.println(qrCode.getModule(x, y) ? 1 : 0); } } catch (DataTooLongException e) { From 112cf4a538627cabb0dce93d44546ab213dd53ca Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sun, 7 Jun 2020 12:43:53 +0900 Subject: [PATCH 24/35] final commit --- .../java/io/nayuki/qrcodegen/QrSegment.java | 109 +++++++++++------- 1 file changed, 68 insertions(+), 41 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 780b1bc..5fbba48 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -29,14 +29,12 @@ import java.util.List; import java.util.Objects; import java.util.regex.Pattern; -import QrSegment.Mode; - /** * A segment of character/binary/control data in a QR Code symbol. * Instances of this class are immutable. *

The mid-level way to create a segment is to take the payload data and call a - * static factory function such as {@link QrSegment#makeNumeric(String)}. The low-level + * static factory function such as {@link MakeNumericToSegment#makeNumericToSegment(String)}. The low-level * way to create a segment is to custom-make the bit buffer and call the {@link * QrSegment#QrSegment(Mode,int,BitBuffer) constructor} with appropriate values.

*

This segment class imposes no length restrictions, but QR Codes have restrictions. @@ -49,6 +47,51 @@ public final class QrSegment { /*---- Static factory functions (mid level) ----*/ + /** + * Returns a segment representing the specified binary data + * encoded in byte mode. All input byte arrays are acceptable. + *

Any text string can be converted to UTF-8 bytes ({@code + * s.getBytes(StandardCharsets.UTF_8)}) and encoded as a byte mode segment.

+ * @param data the binary data (not {@code null}) + * @return a segment (not {@code null}) containing the data + * @throws NullPointerException if the array is {@code null} + */ + public static QrSegment makeBytes(byte[] data) { + MakeBytesToSegment makeBytesToSegment = new MakeBytesToSegment(); + + return makeBytesToSegment.excuteForBytedata(data); + } + + + /** + * Returns a segment representing the specified string of decimal digits encoded in numeric mode. + * @param digits the text (not {@code null}), with only digits from 0 to 9 allowed + * @return a segment (not {@code null}) containing the text + * @throws NullPointerException if the string is {@code null} + * @throws IllegalArgumentException if the string contains non-digit characters + */ + public static QrSegment makeNumeric(String digits) { + MakeSegment makeSegment = new MakeNumericToSegment(); + + return makeSegment.excute(digits); + } + + + /** + * Returns a segment representing the specified text string encoded in alphanumeric mode. + * The characters allowed are: 0 to 9, A to Z (uppercase only), space, + * dollar, percent, asterisk, plus, hyphen, period, slash, colon. + * @param text the text (not {@code null}), with only certain characters allowed + * @return a segment (not {@code null}) containing the text + * @throws NullPointerException if the string is {@code null} + * @throws IllegalArgumentException if the string contains non-encodable characters + */ + public static QrSegment makeAlphanumeric(String text) { + MakeSegment makeSegment = new MakeAlphaNumericToSegment(); + + return makeSegment.excute(text); + } + /** * Returns a list of zero or more segments to represent the specified Unicode text string. * The result may use various segment modes and switch modes to optimize the length of the bit stream. @@ -56,21 +99,6 @@ public final class QrSegment { * @return a new mutable list (not {@code null}) of segments (not {@code null}) containing the text * @throws NullPointerException if the text is {@code null} */ - public static List makeSegments(String text) { - Objects.requireNonNull(text); - - // Select the most efficient segment encoding automatically - List segments = new ArrayList<>(); - if (text.equals("")); // Leave result empty - else if (NUMERIC_REGEX.matcher(text).matches()) - segments.add(makeNumeric(text)); - else if (ALPHANUMERIC_REGEX.matcher(text).matches()) - segments.add(makeAlphanumeric(text)); - else - segments.add(makeBytes(text.getBytes(StandardCharsets.UTF_8))); - return segments; - } - public static List makeSegments(String text) { Objects.requireNonNull(text); // Select the most efficient segment encoding automatically @@ -82,10 +110,12 @@ public final class QrSegment { return segments; } + + /** * Returns a segment representing an Extended Channel Interpretation * (ECI) designator with the specified assignment value. - * @param assignVal the ECI assignment number (see the AIM ECI specification) + * @param assignValue the ECI assignment number (see the AIM ECI specification) * @return a segment (not {@code null}) containing the data * @throws IllegalArgumentException if the value is outside the range [0, 106) */ @@ -116,7 +146,7 @@ public final class QrSegment { /** The length of this segment's unencoded data. Measured in characters for * numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. * Always zero or positive. Not the same as the data's bit length. */ - public final int numChars; + public final int numberOfCharacters; // The data bits of this segment. Not null. Accessed through getData(). final BitBuffer data; @@ -128,8 +158,8 @@ public final class QrSegment { * Constructs a QR Code segment with the specified attributes and data. * The character count (numCh) must agree with the mode and the bit buffer length, * but the constraint isn't checked. The specified bit buffer is cloned and stored. - * @param md the mode (not {@code null}) - * @param numCh the data length in characters or bytes, which is non-negative + * @param _mode the mode (not {@code null}) + * @param _numberOfCharacters the data length in characters or bytes, which is non-negative * @param data the data bits (not {@code null}) * @throws NullPointerException if the mode or data is {@code null} * @throws IllegalArgumentException if the character count is negative @@ -143,6 +173,7 @@ public final class QrSegment { this.data = data.clone(); // Make defensive copy } + /*---- Methods ----*/ /** @@ -157,49 +188,45 @@ public final class QrSegment { // Calculates the number of bits needed to encode the given segments at the given version. // Returns a non-negative number if successful. Otherwise returns -1 if a segment has too // many characters to fit its length field, or the total bits exceeds Integer.MAX_VALUE. - static int getTotalBits(List segs, int version) { - Objects.requireNonNull(segs); - long result = 0; - for (QrSegment seg : segs) { - Objects.requireNonNull(seg); - int ccbits = seg.mode.numCharCountBits(version); - if (seg.numChars >= (1 << ccbits)) - return -1; // The segment's length doesn't fit the field's bit width - result += 4L + ccbits + seg.data.bitLength(); - if (result > Integer.MAX_VALUE) - return -1; // The sum will overflow an int type - } - return (int)result; - } - static int getTotalBits(List segments, int version) { Objects.requireNonNull(segments); long TotalBits = 0; for (QrSegment segment : segments) { Objects.requireNonNull(segment); int characterCountBits = segment.mode.numCharCountBits(version); - if (segment.numberOfCharacters >= (1 << characterCountBits)) + if (DoesNotSegmentLengthFitTheFieldBitWidth(segment, characterCountBits)) return -1; // The segment's length doesn't fit the field's bit width TotalBits += 4L + characterCountBits + segment.data.bitLength(); - if (TotalBits > Integer.MAX_VALUE) + if (IsTotalBitsOutOfIntegerRange(TotalBits)) return -1; // The sum will overflow an int type } return (int)TotalBits; } + + + public static boolean IsTotalBitsOutOfIntegerRange(long result) { + return result > Integer.MAX_VALUE; + } + + + public static boolean DoesNotSegmentLengthFitTheFieldBitWidth(QrSegment segment, int characterCountBits) { + return segment.numberOfCharacters >= (1 << characterCountBits); + } + /*---- Constants ----*/ /** Describes precisely all strings that are encodable in numeric mode. To test whether a * string {@code s} is encodable: {@code boolean ok = NUMERIC_REGEX.matcher(s).matches();}. * A string is encodable iff each character is in the range 0 to 9. - * @see #makeNumeric(String) */ + * @see MakeNumericToSegment#makeNumericToSegment(String) */ public static final Pattern NUMERIC_REGEX = Pattern.compile("[0-9]*"); /** Describes precisely all strings that are encodable in alphanumeric mode. To test whether a * string {@code s} is encodable: {@code boolean ok = ALPHANUMERIC_REGEX.matcher(s).matches();}. * A string is encodable iff each character is in the following set: 0 to 9, A to Z * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. - * @see #makeAlphanumeric(String) */ + * @see MakeAlphaNumericToSegment#makeAlphaNumericToSegment(String) */ public static final Pattern ALPHANUMERIC_REGEX = Pattern.compile("[A-Z0-9 $%*+./:-]*"); // The set of all legal characters in alphanumeric mode, where From 032f145df56dc25a6ffb6b1d0c46959decca214b Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sun, 7 Jun 2020 12:45:16 +0900 Subject: [PATCH 25/35] final commit 2 --- .../java/io/nayuki/qrcodegen/QrSegment.java | 37 ++++++------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index 5fbba48..307f549 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -29,12 +29,14 @@ import java.util.List; import java.util.Objects; import java.util.regex.Pattern; +import QrSegment.Mode; + /** * A segment of character/binary/control data in a QR Code symbol. * Instances of this class are immutable. *

The mid-level way to create a segment is to take the payload data and call a - * static factory function such as {@link MakeNumericToSegment#makeNumericToSegment(String)}. The low-level + * static factory function such as {@link QrSegment#makeNumeric(String)}. The low-level * way to create a segment is to custom-make the bit buffer and call the {@link * QrSegment#QrSegment(Mode,int,BitBuffer) constructor} with appropriate values.

*

This segment class imposes no length restrictions, but QR Codes have restrictions. @@ -46,7 +48,6 @@ import java.util.regex.Pattern; public final class QrSegment { /*---- Static factory functions (mid level) ----*/ - /** * Returns a segment representing the specified binary data * encoded in byte mode. All input byte arrays are acceptable. @@ -91,7 +92,6 @@ public final class QrSegment { return makeSegment.excute(text); } - /** * Returns a list of zero or more segments to represent the specified Unicode text string. * The result may use various segment modes and switch modes to optimize the length of the bit stream. @@ -99,6 +99,7 @@ public final class QrSegment { * @return a new mutable list (not {@code null}) of segments (not {@code null}) containing the text * @throws NullPointerException if the text is {@code null} */ + public static List makeSegments(String text) { Objects.requireNonNull(text); // Select the most efficient segment encoding automatically @@ -110,12 +111,10 @@ public final class QrSegment { return segments; } - - /** * Returns a segment representing an Extended Channel Interpretation * (ECI) designator with the specified assignment value. - * @param assignValue the ECI assignment number (see the AIM ECI specification) + * @param assignVal the ECI assignment number (see the AIM ECI specification) * @return a segment (not {@code null}) containing the data * @throws IllegalArgumentException if the value is outside the range [0, 106) */ @@ -146,7 +145,7 @@ public final class QrSegment { /** The length of this segment's unencoded data. Measured in characters for * numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. * Always zero or positive. Not the same as the data's bit length. */ - public final int numberOfCharacters; + public final int numChars; // The data bits of this segment. Not null. Accessed through getData(). final BitBuffer data; @@ -158,8 +157,8 @@ public final class QrSegment { * Constructs a QR Code segment with the specified attributes and data. * The character count (numCh) must agree with the mode and the bit buffer length, * but the constraint isn't checked. The specified bit buffer is cloned and stored. - * @param _mode the mode (not {@code null}) - * @param _numberOfCharacters the data length in characters or bytes, which is non-negative + * @param md the mode (not {@code null}) + * @param numCh the data length in characters or bytes, which is non-negative * @param data the data bits (not {@code null}) * @throws NullPointerException if the mode or data is {@code null} * @throws IllegalArgumentException if the character count is negative @@ -173,7 +172,6 @@ public final class QrSegment { this.data = data.clone(); // Make defensive copy } - /*---- Methods ----*/ /** @@ -194,39 +192,28 @@ public final class QrSegment { for (QrSegment segment : segments) { Objects.requireNonNull(segment); int characterCountBits = segment.mode.numCharCountBits(version); - if (DoesNotSegmentLengthFitTheFieldBitWidth(segment, characterCountBits)) + if (segment.numberOfCharacters >= (1 << characterCountBits)) return -1; // The segment's length doesn't fit the field's bit width TotalBits += 4L + characterCountBits + segment.data.bitLength(); - if (IsTotalBitsOutOfIntegerRange(TotalBits)) + if (TotalBits > Integer.MAX_VALUE) return -1; // The sum will overflow an int type } return (int)TotalBits; } - - - public static boolean IsTotalBitsOutOfIntegerRange(long result) { - return result > Integer.MAX_VALUE; - } - - - public static boolean DoesNotSegmentLengthFitTheFieldBitWidth(QrSegment segment, int characterCountBits) { - return segment.numberOfCharacters >= (1 << characterCountBits); - } - /*---- Constants ----*/ /** Describes precisely all strings that are encodable in numeric mode. To test whether a * string {@code s} is encodable: {@code boolean ok = NUMERIC_REGEX.matcher(s).matches();}. * A string is encodable iff each character is in the range 0 to 9. - * @see MakeNumericToSegment#makeNumericToSegment(String) */ + * @see #makeNumeric(String) */ public static final Pattern NUMERIC_REGEX = Pattern.compile("[0-9]*"); /** Describes precisely all strings that are encodable in alphanumeric mode. To test whether a * string {@code s} is encodable: {@code boolean ok = ALPHANUMERIC_REGEX.matcher(s).matches();}. * A string is encodable iff each character is in the following set: 0 to 9, A to Z * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. - * @see MakeAlphaNumericToSegment#makeAlphaNumericToSegment(String) */ + * @see #makeAlphanumeric(String) */ public static final Pattern ALPHANUMERIC_REGEX = Pattern.compile("[A-Z0-9 $%*+./:-]*"); // The set of all legal characters in alphanumeric mode, where From 5124c442036bb836b6ddd11ad504b8a88510f6ad Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sun, 7 Jun 2020 12:47:44 +0900 Subject: [PATCH 26/35] ananananna --- .../io/nayuki/qrcodegen/QrCodeGeneratorWorker.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java index a11a39e..4378963 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java @@ -82,12 +82,12 @@ public final class QrCodeGeneratorWorker { segments = Arrays.asList(QrSegment.makeBytes(data)); try { // Try to make QR Code symbol - QrCode qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); + QrCode qr = QrCode.encodeSegments(segments, QrCode.Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); // Print grid of modules - System.out.println(qrCode.version); - for (int y = 0; y < qrCode.size; y++) { - for (int x = 0; x < qrCode.size; x++) - System.out.println(qrCode.getModule(x, y) ? 1 : 0); + System.out.println(qr.version); + for (int y = 0; y < qr.size; y++) { + for (int x = 0; x < qr.size; x++) + System.out.println(qr.getModule(x, y) ? 1 : 0); } } catch (DataTooLongException e) { From f879fec68dc717c092cae56c84f85f93bd135a9a Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sun, 7 Jun 2020 12:55:19 +0900 Subject: [PATCH 27/35] error correction --- .../nayuki/qrcodegen/QrCodeGeneratorDemo.java | 40 +++++++++---------- .../qrcodegen/QrCodeGeneratorWorker.java | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java index a001ff9..828eae6 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java @@ -53,15 +53,15 @@ public final class QrCodeGeneratorDemo { // Creates a single QR Code, then writes it to a PNG file and an SVG file. private static void doBasicDemo() throws IOException { String text = "Hello, world!"; // User-supplied Unicode text - QrCode.Ecc errCorLvl = QrCode.Ecc.LOW; // Error correction level + Ecc errCorLvl = Ecc.LOW; // Error correction level - QrCode qr = QrCode.encodeText(text, errCorLvl); // Make the QR Code symbol + QrCode qrCode = QrCode.encodeText(text, errCorLvl); // Make the QR Code symbol - BufferedImage img = qr.toImage(10, 4); // Convert to bitmap image + BufferedImage img = qrCode.toImage(10, 4); // Convert to bitmap image File imgFile = new File("hello-world-QR.png"); // File path for output ImageIO.write(img, "png", imgFile); // Write image to file - String svg = qr.toSvgString(4); // Convert to SVG XML code + String svg = qrCode.toSvgString(4); // Convert to SVG XML code File svgFile = new File("hello-world-QR.svg"); // File path for output Files.write(svgFile.toPath(), // Write image to file svg.getBytes(StandardCharsets.UTF_8)); @@ -73,15 +73,15 @@ public final class QrCodeGeneratorDemo { QrCode qrCode; // Numeric mode encoding (3.33 bits per digit) - qrCode = QrCode.encodeText("314159265358979323846264338327950288419716939937510", QrCode.Ecc.MEDIUM); + qrCode = QrCode.encodeText("314159265358979323846264338327950288419716939937510", Ecc.MEDIUM); writePng(qrCode.toImage(13, 1), "pi-digits-QR.png"); // Alphanumeric mode encoding (5.5 bits per character) - qrCode = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode.Ecc.HIGH); + qrCode = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", Ecc.HIGH); writePng(qrCode.toImage(10, 2), "alphanumeric-QR.png"); // Unicode text as UTF-8 - qrCode = QrCode.encodeText("占쎄괭占쎄뎐占쎄쾽占쎄굶wa占쎄낌�닟占쎈르塋딉옙 �뀭汝뷸Ь�걣", QrCode.Ecc.QUARTILE); + qrCode = QrCode.encodeText("占쎄괭占쎄뎐占쎄쾽占쎄굶wa占쎄낌�닟占쎈르塋딉옙 �뀭汝뷸Ь�걣", Ecc.QUARTILE); writePng(qrCode.toImage(10, 3), "unicode-QR.png"); // Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland) @@ -92,7 +92,7 @@ public final class QrCodeGeneratorDemo { + "'without pictures or conversations?' So she was considering in her own mind (as well as she could, " + "for the hot day made her feel very sleepy and stupid), whether the pleasure of making a " + "daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly " - + "a White Rabbit with pink eyes ran close by her.", QrCode.Ecc.HIGH); + + "a White Rabbit with pink eyes ran close by her.", Ecc.HIGH); writePng(qrCode.toImage(6, 10), "alice-wonderland-QR.png"); } @@ -105,36 +105,36 @@ public final class QrCodeGeneratorDemo { // Illustration "silver" String silver0 = "THE SQUARE ROOT OF 2 IS 1."; String silver1 = "41421356237309504880168872420969807856967187537694807317667973799"; - qrCode = QrCode.encodeText(silver0 + silver1, QrCode.Ecc.LOW); + qrCode = QrCode.encodeText(silver0 + silver1, Ecc.LOW); writePng(qrCode.toImage(10, 3), "sqrt2-monolithic-QR.png"); segments = Arrays.asList( QrSegment.makeAlphanumeric(silver0), QrSegment.makeNumeric(silver1)); - qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.LOW); + qrCode = QrCode.encodeSegments(segments, Ecc.LOW); writePng(qrCode.toImage(10, 3), "sqrt2-segmented-QR.png"); // Illustration "golden" String golden0 = "Golden ratio 占쏙옙 = 1."; String golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374"; String golden2 = "......"; - qrCode = QrCode.encodeText(golden0 + golden1 + golden2, QrCode.Ecc.LOW); + qrCode = QrCode.encodeText(golden0 + golden1 + golden2, Ecc.LOW); writePng(qrCode.toImage(8, 5), "phi-monolithic-QR.png"); segments = Arrays.asList( QrSegment.makeBytes(golden0.getBytes(StandardCharsets.UTF_8)), QrSegment.makeNumeric(golden1), QrSegment.makeAlphanumeric(golden2)); - qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.LOW); + qrCode = QrCode.encodeSegments(segments, Ecc.LOW); writePng(qrCode.toImage(8, 5), "phi-segmented-QR.png"); // Illustration "Madoka": kanji, kana, Cyrillic, full-width Latin, Greek characters String madoka = "占쎈슞異몌쫲類앹빼阿잙뀍寃뀐옙寃묕옙嫄�占쎌겳占쎄묻占쎄텤占쎄텠占쎈씞寃귨옙寃랃옙怨ο옙占쏙옙�꺂癒믪꼨占쏙옙影�袁ы맀影�蹂⑺맟占쏙옙鰲��뀭塋딉옙"; - qrCode = QrCode.encodeText(madoka, QrCode.Ecc.LOW); + qrCode = QrCode.encodeText(madoka, Ecc.LOW); writePng(qrCode.toImage(9, 4), "madoka-utf8-QR.png"); segments = Arrays.asList(QrSegmentAdvanced.makeKanji(madoka)); - qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.LOW); + qrCode = QrCode.encodeSegments(segments, Ecc.LOW); writePng(qrCode.toImage(9, 4), "madoka-kanji-QR.png"); } @@ -146,20 +146,20 @@ public final class QrCodeGeneratorDemo { // Project Nayuki URL segments = QrSegment.makeSegments("https://www.nayuki.io/"); - qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true); // Automatic mask + qrCode = QrCode.encodeSegments(segments, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true); // Automatic mask writePng(qrCode.toImage(8, 6), "project-nayuki-automask-QR.png"); - qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true); // Force mask 3 + qrCode = QrCode.encodeSegments(segments, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true); // Force mask 3 writePng(qrCode.toImage(8, 6), "project-nayuki-mask3-QR.png"); // Chinese text as UTF-8 segments = QrSegment.makeSegments("力놂옙占쎌쓢占쎌뇥�뇖臾뺥렩Wikipedia塋딅슜嫄앾옙寃켲/占쎈샆�뎚藥�戮먮뒰i占쎈쫨i.占쏙옙/塋딅맚�궦鼇앾옙占쎈뿨�닅占쎈뎨占쎈�깍Ⅴ諛ㅿ옙怨⑸�띰옙堉�歷뜯몼�꽎鼇앸떱姨�亦껋쉮占쏙옙�돦力녠엽�윭占쎌뇥�뇖臾덈�뀐옙�럱占쎈쐭俑앹뮂怡ワ옙鍮�"); - qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true); // Force mask 0 + qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true); // Force mask 0 writePng(qrCode.toImage(10, 3), "unicode-mask0-QR.png"); - qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true); // Force mask 1 + qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true); // Force mask 1 writePng(qrCode.toImage(10, 3), "unicode-mask1-QR.png"); - qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true); // Force mask 5 + qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true); // Force mask 5 writePng(qrCode.toImage(10, 3), "unicode-mask5-QR.png"); - qrCode = QrCode.encodeSegments(segments, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true); // Force mask 7 + qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true); // Force mask 7 writePng(qrCode.toImage(10, 3), "unicode-mask7-QR.png"); } diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java index 4378963..12d77e7 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java @@ -82,7 +82,7 @@ public final class QrCodeGeneratorWorker { segments = Arrays.asList(QrSegment.makeBytes(data)); try { // Try to make QR Code symbol - QrCode qr = QrCode.encodeSegments(segments, QrCode.Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); + QrCode qr = QrCode.encodeSegments(segments, Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); // Print grid of modules System.out.println(qr.version); for (int y = 0; y < qr.size; y++) { From 81444bc47903497c2f5321d67691b1a615128160 Mon Sep 17 00:00:00 2001 From: minsu4107 <32637512+minsu4107@users.noreply.github.com> Date: Fri, 19 Jun 2020 22:18:53 +0900 Subject: [PATCH 28/35] When user insert too long message, THis program have to occur exception. So, I check this problem in QrSegmentAdvanced.java --- java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java | 1 + java/src/main/java/io/nayuki/qrcodegen/QrMode.java | 2 +- .../main/java/io/nayuki/qrcodegen/QrSegmentAdvanced.java | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java b/java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java index 9729f93..a5321ba 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java +++ b/java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java @@ -20,4 +20,5 @@ public class KanjiMode extends QrMode { public QrSegment making(String str) { return QrSegmentAdvanced.makeKanji(str); } + } diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrMode.java b/java/src/main/java/io/nayuki/qrcodegen/QrMode.java index 3f0127f..f5636b3 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrMode.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrMode.java @@ -7,7 +7,7 @@ public abstract class QrMode { int modeBits; // Number of character count bits for three different version ranges. - protected int[] numBitsCharCount; + protected int[] numBitsCharCount = new int[4]; int headCost; /*-- Method --*/ diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegmentAdvanced.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegmentAdvanced.java index 50066e8..94783a9 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegmentAdvanced.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegmentAdvanced.java @@ -98,12 +98,12 @@ public final class QrSegmentAdvanced { } - private static boolean is_valid_version(int minVersion, int version) { + public static boolean is_valid_version(int minVersion, int version) { return version == minVersion || version == 10 || version == 27; } - private static boolean not_Valid_Version(int minVersion, int maxVersion) { + public static boolean not_Valid_Version(int minVersion, int maxVersion) { return !(QrCode.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= QrCode.MAX_VERSION); } @@ -217,12 +217,12 @@ public final class QrSegmentAdvanced { } - private static boolean is_numeric(int convertedPoint) { + public static boolean is_numeric(int convertedPoint) { return '0' <= convertedPoint && convertedPoint <= '9'; } - private static boolean is_alphanumeric(int convertedPoint) { + public static boolean is_alphanumeric(int convertedPoint) { return QrSegment.ALPHANUMERIC_CHARSET.indexOf(convertedPoint) != -1; } From f44b35fcec677a2aed4b3a9d8be0a3bee6024a38 Mon Sep 17 00:00:00 2001 From: minsu4107 <32637512+minsu4107@users.noreply.github.com> Date: Fri, 19 Jun 2020 22:22:18 +0900 Subject: [PATCH 29/35] When user insert too long message, This program have to occur exception. --- .../qrcodegen/testQrSegmentAdvanced.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java diff --git a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java new file mode 100644 index 0000000..e6a135f --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java @@ -0,0 +1,43 @@ +package io.nayuki.qrcodegen; +import static org.junit.Assert.*; + +import org.junit.Test; + +public class testQrSegmentAdvanced { + private QrSegmentAdvanced testing; + private String overString = "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd" + + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd" + + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd" + + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd" + + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd"; + + private static int min_version = QrCode.MIN_VERSION; + private static int max_version = QrCode.MAX_VERSION; + + /** + *Purpose: Testing when user insert over text length + *Input: overString, Ecc.LOW, minversion = 1, maxversion = 40 + *Expected: + * Return throw + */ + @Test(expected=DataTooLongException.class) + public void makeSegmentsOptimallyThrowtest() { + testing.makeSegmentsOptimally(overString, Ecc.LOW, 1, 40); + } + + /** + *Purpose: Using MCDC, Testing version set correctly. + *Input: overString, Ecc.LOW, minversion = 1, maxversion = 40 + *Expected: + * Return throw + */ +// return version == minVersion || version == 10 || version == 27; + @Test + public void is_valid_Test() { + assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 1),1); + assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 10),1); + assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 27),1); + assertNotEquals(QrSegmentAdvanced.is_valid_version(min_version, 0),1); + } + +} From 9205e0284f36fb934570b27eddf6e74c4319ce54 Mon Sep 17 00:00:00 2001 From: minsu4107 <32637512+minsu4107@users.noreply.github.com> Date: Fri, 19 Jun 2020 22:24:15 +0900 Subject: [PATCH 30/35] Using MCDC, I check flag that checking whether this version is valid. --- .../qrcodegen/testQrSegmentAdvanced.java | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java index e6a135f..dba70c2 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java +++ b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java @@ -9,11 +9,7 @@ public class testQrSegmentAdvanced { + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd" + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd" + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd" - + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd"; - - private static int min_version = QrCode.MIN_VERSION; - private static int max_version = QrCode.MAX_VERSION; - + + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd"; /** *Purpose: Testing when user insert over text length *Input: overString, Ecc.LOW, minversion = 1, maxversion = 40 @@ -24,20 +20,5 @@ public class testQrSegmentAdvanced { public void makeSegmentsOptimallyThrowtest() { testing.makeSegmentsOptimally(overString, Ecc.LOW, 1, 40); } - - /** - *Purpose: Using MCDC, Testing version set correctly. - *Input: overString, Ecc.LOW, minversion = 1, maxversion = 40 - *Expected: - * Return throw - */ -// return version == minVersion || version == 10 || version == 27; - @Test - public void is_valid_Test() { - assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 1),1); - assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 10),1); - assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 27),1); - assertNotEquals(QrSegmentAdvanced.is_valid_version(min_version, 0),1); - } } From 6db605e0fd60529078a7ccdfafb9b71c2f5dc28d Mon Sep 17 00:00:00 2001 From: minsu4107 <32637512+minsu4107@users.noreply.github.com> Date: Fri, 19 Jun 2020 22:49:50 +0900 Subject: [PATCH 31/35] Checking your's min, max version whether over range in program's min, max version. --- .../qrcodegen/testQrSegmentAdvanced.java | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java index dba70c2..8b8e780 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java +++ b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java @@ -9,7 +9,11 @@ public class testQrSegmentAdvanced { + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd" + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd" + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd" - + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd"; + + "asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd"; + + private static int min_version = QrCode.MIN_VERSION; + private static int max_version = QrCode.MAX_VERSION; + /** *Purpose: Testing when user insert over text length *Input: overString, Ecc.LOW, minversion = 1, maxversion = 40 @@ -20,5 +24,36 @@ public class testQrSegmentAdvanced { public void makeSegmentsOptimallyThrowtest() { testing.makeSegmentsOptimally(overString, Ecc.LOW, 1, 40); } + + /** + *Purpose: Using MCDC, Testing version set correctly. + *Input: nin_version, 1, 10, 27, 0 + *Expected: + * All True + */ + + @Test + public void is_valid_Test() { + assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 1),1); + assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 10),1); + assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 27),1); + assertNotEquals(QrSegmentAdvanced.is_valid_version(min_version, 0),1); + } + /** + *Purpose: Using MCDC, Testing version set correctly. + *Input: 1, 40, 41, 0, 3, 4 + *Expected: + * Overrange factor has return 0, So, not equal to 1 + * Unless it has correct range in version's range, if you insert min_version is bigger that max_version, it return 0; + */ + + public void not_Valid_Version_test() { + assertEquals(QrSegmentAdvanced.not_Valid_Version(1, 40), 1); + assertNotEquals(QrSegmentAdvanced.not_Valid_Version(1, 41), 1); + assertNotEquals(QrSegmentAdvanced.not_Valid_Version(0, 40), 1); + assertNotEquals(QrSegmentAdvanced.not_Valid_Version(5, 4), 1); + } + + } From b10a3977433063ffe71d1c953222ac7b52466ee8 Mon Sep 17 00:00:00 2001 From: minsu4107 <32637512+minsu4107@users.noreply.github.com> Date: Fri, 19 Jun 2020 23:09:13 +0900 Subject: [PATCH 32/35] This program checking whether its String is empty. SO, i test it working correctly --- .../qrcodegen/testQrSegmentAdvanced.java | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java index 8b8e780..75266fa 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java +++ b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java @@ -1,6 +1,8 @@ package io.nayuki.qrcodegen; import static org.junit.Assert.*; +import java.util.EmptyStackException; + import org.junit.Test; public class testQrSegmentAdvanced { @@ -14,6 +16,8 @@ public class testQrSegmentAdvanced { private static int min_version = QrCode.MIN_VERSION; private static int max_version = QrCode.MAX_VERSION; + private String nullstring = ""; + /** *Purpose: Testing when user insert over text length *Input: overString, Ecc.LOW, minversion = 1, maxversion = 40 @@ -34,26 +38,37 @@ public class testQrSegmentAdvanced { @Test public void is_valid_Test() { - assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 1),1); - assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 10),1); - assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 27),1); - assertNotEquals(QrSegmentAdvanced.is_valid_version(min_version, 0),1); + assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 1),true); + assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 10),true); + assertEquals(QrSegmentAdvanced.is_valid_version(min_version, 27),true); + assertNotEquals(QrSegmentAdvanced.is_valid_version(min_version, 0),true); } /** *Purpose: Using MCDC, Testing version set correctly. *Input: 1, 40, 41, 0, 3, 4 *Expected: - * Overrange factor has return 0, So, not equal to 1 + * Over range factor has return 0, So, not equal to 1 * Unless it has correct range in version's range, if you insert min_version is bigger that max_version, it return 0; */ + @Test public void not_Valid_Version_test() { - assertEquals(QrSegmentAdvanced.not_Valid_Version(1, 40), 1); - assertNotEquals(QrSegmentAdvanced.not_Valid_Version(1, 41), 1); - assertNotEquals(QrSegmentAdvanced.not_Valid_Version(0, 40), 1); - assertNotEquals(QrSegmentAdvanced.not_Valid_Version(5, 4), 1); + assertEquals(QrSegmentAdvanced.not_Valid_Version(1, 40), false); + assertNotEquals(QrSegmentAdvanced.not_Valid_Version(1, 41), false); + assertNotEquals(QrSegmentAdvanced.not_Valid_Version(0, 40), false); + assertNotEquals(QrSegmentAdvanced.not_Valid_Version(5, 4), false); } - - + + /** + *Purpose: This program checking whether its String is empty. SO, i test it working correctly + *Input: 1, nullstring, Ecc.Low, 1, 40 + *Expected: + * occur AssertError + */ + @Test(expected = AssertionError.class) + public void emptyString_test() { + testing.makeSegmentsOptimally(nullstring, Ecc.LOW, 1, 40); + } + } From 601a0de46a932909fb10f9c9ef48a3ffb4039953 Mon Sep 17 00:00:00 2001 From: minsu4107 <32637512+minsu4107@users.noreply.github.com> Date: Fri, 19 Jun 2020 23:37:47 +0900 Subject: [PATCH 33/35] This program has several mode and making these. When making these mode, find suitable mode using flag. So, i test this functions. --- .../qrcodegen/testQrSegmentAdvanced.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java index 75266fa..4f9b0e6 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java +++ b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java @@ -71,4 +71,32 @@ public class testQrSegmentAdvanced { testing.makeSegmentsOptimally(nullstring, Ecc.LOW, 1, 40); } + /** + *Purpose: This program has several mode and making these. When making these mode, find suitable mode using flag. So, i test this functions. + * is_numeric -> 0 ~ 9 's UTF-8 number, is_alphanumeric -> "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:" stinrg set, + *Input: "0123456780", "A", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:" + *Expected: + * All is correct + */ + @Test + public void is_Corredt_Mode_test() { + int[] correctStr = "09".codePoints().toArray(); + for (int forcnt : correctStr){ + assertEquals(QrSegmentAdvanced.is_numeric(forcnt), true); + } + int[] wrongStr = "a".codePoints().toArray(); + for (int forcnt : wrongStr){ + assertEquals(QrSegmentAdvanced.is_numeric(forcnt), false); + } + + correctStr = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".codePoints().toArray(); + for (int forcnt : correctStr){ + assertEquals(QrSegmentAdvanced.is_alphanumeric(forcnt), true); + } + + wrongStr = "\\".codePoints().toArray(); + for (int forcnt : wrongStr){ + assertEquals(QrSegmentAdvanced.is_alphanumeric(forcnt), false); + } + } } From 5b2085e2cfabcd84d38efcc58b2c27f2c01a7534 Mon Sep 17 00:00:00 2001 From: minsu4107 <32637512+minsu4107@users.noreply.github.com> Date: Fri, 19 Jun 2020 23:48:44 +0900 Subject: [PATCH 34/35] Testing 'toCodePoints' function whether it distinguish UTF-8 character or not. --- .../nayuki/qrcodegen/testQrSegmentAdvanced.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java index 4f9b0e6..f672289 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java +++ b/java/src/main/java/io/nayuki/qrcodegen/testQrSegmentAdvanced.java @@ -99,4 +99,19 @@ public class testQrSegmentAdvanced { assertEquals(QrSegmentAdvanced.is_alphanumeric(forcnt), false); } } + + /** + *Purpose: 'toCodePoints' function is convert String to integer, if String is in UTF-8. + * In UTF-8 has variable character why I haven't check all UTF-8's string. + * So, I just test character that are excluded at UTF-8. + * For checking exception occurs when a character other than UTF-8 is entered. + *Input: "A�" + *Expected: + * occur IllegalArgumentException + */ + @Test(expected = IllegalArgumentException.class) + public void toCodePoints_test() { + String not_UTF = "A�"; + testing.makeSegmentsOptimally(not_UTF, Ecc.LOW, 1, 40); + } } From 87ec8b2a8fc19ba9ca7210e371e8ac3f272b8c4d Mon Sep 17 00:00:00 2001 From: gerzees Date: Sun, 21 Jun 2020 23:39:16 +0900 Subject: [PATCH 35/35] White box test Aim over 90% of MCDC coverage --- .../qrcodegen/QrCodeTestEncodeSegments.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 java/src/main/java/io/nayuki/qrcodegen/QrCodeTestEncodeSegments.java diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeTestEncodeSegments.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeTestEncodeSegments.java new file mode 100644 index 0000000..1a46337 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeTestEncodeSegments.java @@ -0,0 +1,86 @@ + +package io.nayuki.qrcodegen; + +import static org.junit.Assert.*; + +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; + + +public class QrCodeTestEncodeSegments { + private static List qrSegments; + + @BeforeClass + public static void oneTimeSetUp() { + qrSegments = QrSegment.makeSegments("Hello, World!"); + } + + /** + * Purpose: Make QrCode + * Input: QrSegment.makeSegments("Hello, World!"), Ecc.LOW, 10, 20, 3, true + * Expected: + * QrCode made without Exception + */ + @Test + public void testInRange() { + assertNotNull(QrCode.encodeSegments(qrSegments, Ecc.LOW, 10, 20, 3, true)); + } + + /** + * Purpose: Try to make QrCode with a invalid argument(0 is less than minimal value in valid version range) + * Input: QrSegment.makeSegments("Hello, World!"), Ecc.LOW, 0, QrCode.MAX_VERSION, 3, true + * Expected: + * throw IllegalArgumentException + */ + @Test(expected = IllegalArgumentException.class) + public void testMinVersionOverLeftBoundary() { + QrCode.encodeSegments(qrSegments, Ecc.LOW, 0, QrCode.MAX_VERSION, 3, true); + } + + /** + * Purpose: Try to make QrCode with a invalid argument(41 is greater than maximal value in valid version range) + * Input: QrSegment.makeSegments("Hello, World!"), Ecc.LOW, QrCode.MIN_VERSION, 41, 3, true + * Expected: + * throw IllegalArgumentException + */ + @Test(expected = IllegalArgumentException.class) + public void testMaxVersionOverRightBoundary() { + QrCode.encodeSegments(qrSegments, Ecc.LOW, QrCode.MIN_VERSION, 41, 3, true); + } + + /** + * Purpose: Try to make QrCode with a invalid argument(minimal version input must be small or equal than maximal version input) + * Input: QrSegment.makeSegments("Hello, World!"), Ecc.LOW, QrCode.MAX_VERSION, QrCode.MIN_VERSION, 3, true + * Expected: + * throw IllegalArgumentException + */ + @Test(expected = IllegalArgumentException.class) + public void testMinVersionGreaterThanMaxVersion() { + QrCode.encodeSegments(qrSegments, Ecc.LOW, QrCode.MAX_VERSION, QrCode.MIN_VERSION, 3, true); + } + + /** + * Purpose: Try to make QrCode with a invalid argument(mask must be -1 or greater than -1) + * Input: QrSegment.makeSegments("Hello, World!"), Ecc.LOW, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -2, true + * Expected: + * throw IllegalArgumentException + */ + @Test(expected = IllegalArgumentException.class) + public void testMaskOverLeftBoundary() { + QrCode.encodeSegments(qrSegments, Ecc.LOW, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -2, true); + } + + /** + * Purpose: Try to make QrCode with a invalid argument(mask must be 7 or less than 7) + * Input: QrSegment.makeSegments("Hello, World!"), Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 8, true + * Expected: + * throw IllegalArgumentException + */ + @Test(expected = IllegalArgumentException.class) + public void testMaksOverRightBoundary() { + QrCode.encodeSegments(qrSegments, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 8, true); + } + +}