Updated comments for QrSegment.getTotalBits() in all language versions, but somewhat differently per language.

pull/39/merge
Project Nayuki 6 years ago
parent b095504d5c
commit 4c882636bb

@ -970,10 +970,9 @@ bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], siz
} }
// Returns the number of bits needed to encode the given list of segments at the given version. // Calculates the number of bits needed to encode the given segments at the given version.
// The result is in the range [0, 32767] if successful. Otherwise, -1 is returned if any segment // Returns a non-negative number if successful. Otherwise returns -1 if a segment has too
// has more characters than allowed by that segment's mode's character count field at the version, // many characters to fit its length field, or the total bits exceeds INT16_MAX.
// or if the actual answer exceeds INT16_MAX.
testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) { testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) {
assert(segs != NULL || len == 0); assert(segs != NULL || len == 0);
assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX);
@ -985,12 +984,11 @@ testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int
assert(0 <= bitLength && bitLength <= INT16_MAX); assert(0 <= bitLength && bitLength <= INT16_MAX);
int ccbits = numCharCountBits(segs[i].mode, version); int ccbits = numCharCountBits(segs[i].mode, version);
assert(0 <= ccbits && ccbits <= 16); assert(0 <= ccbits && ccbits <= 16);
// Fail if segment length value doesn't fit in the length field's bit-width
if (numChars >= (1L << ccbits)) if (numChars >= (1L << ccbits))
return -1; return -1; // The segment's length doesn't fit the field's bit width
result += 4L + ccbits + bitLength; result += 4L + ccbits + bitLength;
if (result > INT16_MAX) if (result > INT16_MAX)
return -1; return -1; // The sum might overflow an int type
} }
assert(0 <= result && result <= INT16_MAX); assert(0 <= result && result <= INT16_MAX);
return (int)result; return (int)result;

@ -176,14 +176,13 @@ int QrSegment::getTotalBits(const vector<QrSegment> &segs, int version) {
int result = 0; int result = 0;
for (const QrSegment &seg : segs) { for (const QrSegment &seg : segs) {
int ccbits = seg.mode.numCharCountBits(version); int ccbits = seg.mode.numCharCountBits(version);
// Fail if segment length value doesn't fit in the length field's bit-width
if (seg.numChars >= (1L << ccbits)) if (seg.numChars >= (1L << ccbits))
return -1; return -1; // The segment's length doesn't fit the field's bit width
if (4 + ccbits > INT_MAX - result) if (4 + ccbits > INT_MAX - result)
return -1; return -1; // The sum will overflow an int type
result += 4 + ccbits; result += 4 + ccbits;
if (seg.data.size() > static_cast<unsigned int>(INT_MAX - result)) if (seg.data.size() > static_cast<unsigned int>(INT_MAX - result))
return -1; return -1; // The sum will overflow an int type
result += static_cast<int>(seg.data.size()); result += static_cast<int>(seg.data.size());
} }
return result; return result;

@ -172,7 +172,9 @@ class QrSegment final {
public: const std::vector<bool> &getData() const; public: const std::vector<bool> &getData() const;
// Package-private helper function. // 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 INT_MAX.
public: static int getTotalBits(const std::vector<QrSegment> &segs, int version); public: static int getTotalBits(const std::vector<QrSegment> &segs, int version);

@ -197,7 +197,9 @@ public final class QrSegment {
} }
// Package-private helper function. // 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<QrSegment> segs, int version) { static int getTotalBits(List<QrSegment> segs, int version) {
Objects.requireNonNull(segs); Objects.requireNonNull(segs);
if (version < 1 || version > 40) if (version < 1 || version > 40)
@ -207,12 +209,11 @@ public final class QrSegment {
for (QrSegment seg : segs) { for (QrSegment seg : segs) {
Objects.requireNonNull(seg); Objects.requireNonNull(seg);
int ccbits = seg.mode.numCharCountBits(version); int ccbits = seg.mode.numCharCountBits(version);
// Fail if segment length value doesn't fit in the length field's bit-width
if (seg.numChars >= (1 << ccbits)) if (seg.numChars >= (1 << ccbits))
return -1; return -1; // The segment's length doesn't fit the field's bit width
result += 4L + ccbits + seg.data.bitLength(); result += 4L + ccbits + seg.data.bitLength();
if (result > Integer.MAX_VALUE) if (result > Integer.MAX_VALUE)
return -1; return -1; // The sum will overflow an int type
} }
return (int)result; return (int)result;
} }

@ -817,7 +817,8 @@ var qrcodegen = new function() {
}; };
// Package-private helper function. // Calculates and returns the number of bits needed to encode the given segments at the given version.
// The result is infinity if a segment has too many characters to fit its length field.
this.QrSegment.getTotalBits = function(segs, version) { this.QrSegment.getTotalBits = function(segs, version) {
if (version < MIN_VERSION || version > MAX_VERSION) if (version < MIN_VERSION || version > MAX_VERSION)
throw "Version number out of range"; throw "Version number out of range";
@ -825,9 +826,8 @@ var qrcodegen = new function() {
for (var i = 0; i < segs.length; i++) { for (var i = 0; i < segs.length; i++) {
var seg = segs[i]; var seg = segs[i];
var ccbits = seg.mode.numCharCountBits(version); var ccbits = seg.mode.numCharCountBits(version);
// Fail if segment length value doesn't fit in the length field's bit-width
if (seg.numChars >= (1 << ccbits)) if (seg.numChars >= (1 << ccbits))
return Infinity; return Infinity; // The segment's length doesn't fit the field's bit width
result += 4 + ccbits + seg.getBits().length; result += 4 + ccbits + seg.getBits().length;
} }
return result; return result;

@ -700,7 +700,9 @@ class QrSegment(object):
return list(self._bitdata) # Make defensive copy return list(self._bitdata) # Make defensive copy
# Package-private helper function. # Calculates the number of bits needed to encode the given segments at the given version.
# Returns a non-negative number if successful. Otherwise returns None if a segment has
# too many characters to fit its length field.
@staticmethod @staticmethod
def get_total_bits(segs, version): def get_total_bits(segs, version):
if not (QrCode.MIN_VERSION <= version <= QrCode.MAX_VERSION): if not (QrCode.MIN_VERSION <= version <= QrCode.MAX_VERSION):
@ -708,9 +710,8 @@ class QrSegment(object):
result = 0 result = 0
for seg in segs: for seg in segs:
ccbits = seg.get_mode().num_char_count_bits(version) ccbits = seg.get_mode().num_char_count_bits(version)
# Fail if segment length value doesn't fit in the length field's bit-width
if seg.get_num_chars() >= (1 << ccbits): if seg.get_num_chars() >= (1 << ccbits):
return None return None # The segment's length doesn't fit the field's bit width
result += 4 + ccbits + len(seg._bitdata) result += 4 + ccbits + len(seg._bitdata)
return result return result

@ -974,16 +974,18 @@ impl QrSegment {
/*---- Other static functions ----*/ /*---- Other static functions ----*/
// Package-private helper function. // Calculates and returns the number of bits needed to encode the given
// segments at the given version. The result is None if a segment has too many
// characters to fit its length field, or the total bits exceeds usize::MAX.
fn get_total_bits(segs: &[Self], version: Version) -> Option<usize> { fn get_total_bits(segs: &[Self], version: Version) -> Option<usize> {
let mut result: usize = 0; let mut result: usize = 0;
for seg in segs { for seg in segs {
let ccbits = seg.mode.num_char_count_bits(version); let ccbits = seg.mode.num_char_count_bits(version);
if seg.numchars >= 1 << ccbits { if seg.numchars >= 1 << ccbits {
return None; return None; // The segment's length doesn't fit the field's bit width
} }
match result.checked_add(4 + (ccbits as usize) + seg.data.len()) { match result.checked_add(4 + (ccbits as usize) + seg.data.len()) {
None => return None, None => return None, // The sum will overflow a usize type
Some(val) => result = val, Some(val) => result = val,
} }
} }

@ -773,7 +773,8 @@ namespace qrcodegen {
} }
// Package-private helper function. // Calculates and returns the number of bits needed to encode the given segments at the given version.
// The result is infinity if a segment has too many characters to fit its length field.
public static getTotalBits(segs: Array<QrSegment>, version: int): number { public static getTotalBits(segs: Array<QrSegment>, version: int): number {
if (version < QrCode.MIN_VERSION || version > QrCode.MAX_VERSION) if (version < QrCode.MIN_VERSION || version > QrCode.MAX_VERSION)
throw "Version number out of range"; throw "Version number out of range";
@ -781,9 +782,8 @@ namespace qrcodegen {
for (let i = 0; i < segs.length; i++) { for (let i = 0; i < segs.length; i++) {
let seg: QrSegment = segs[i]; let seg: QrSegment = segs[i];
let ccbits: int = seg.mode.numCharCountBits(version); let ccbits: int = seg.mode.numCharCountBits(version);
// Fail if segment length value doesn't fit in the length field's bit-width
if (seg.numChars >= (1 << ccbits)) if (seg.numChars >= (1 << ccbits))
return Infinity; return Infinity; // The segment's length doesn't fit the field's bit width
result += 4 + ccbits + seg.getBits().length; result += 4 + ccbits + seg.getBits().length;
} }
return result; return result;

Loading…
Cancel
Save