From 112cf4a538627cabb0dce93d44546ab213dd53ca Mon Sep 17 00:00:00 2001 From: jaemin7666 Date: Sun, 7 Jun 2020 12:43:53 +0900 Subject: [PATCH] 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