Tweaked TypeScript code to make it compatible with ECMAScript 5. Main change is demoting class BitBuffer into plain arrays. This makes the TypeScript code architecture diverge slightly from the other 5 supported OOP languages.

pull/65/head
Project Nayuki 5 years ago
parent 907813a82c
commit 1e24fcf67a

@ -29,7 +29,7 @@ namespace app {
function initialize(): void { function initialize(): void {
let elems = document.querySelectorAll("input[type=number], textarea"); let elems = document.querySelectorAll("input[type=number], textarea");
for (let el of elems) { for (let el of elems) {
if (!el.id.startsWith("version-")) if (el.id.indexOf("version-") != 0)
(el as any).oninput = redrawQrCode; (el as any).oninput = redrawQrCode;
} }
elems = document.querySelectorAll("input[type=radio], input[type=checkbox]"); elems = document.querySelectorAll("input[type=radio], input[type=checkbox]");

@ -114,10 +114,10 @@ namespace qrcodegen {
} }
// Concatenate all segments to create the data bit string // Concatenate all segments to create the data bit string
let bb = new BitBuffer(); let bb: Array<bit> = []
for (const seg of segs) { for (const seg of segs) {
bb.appendBits(seg.mode.modeBits, 4); appendBits(seg.mode.modeBits, 4, bb);
bb.appendBits(seg.numChars, seg.mode.numCharCountBits(version)); appendBits(seg.numChars, seg.mode.numCharCountBits(version), bb);
for (const b of seg.getData()) for (const b of seg.getData())
bb.push(b); bb.push(b);
} }
@ -128,14 +128,14 @@ namespace qrcodegen {
const dataCapacityBits: int = QrCode.getNumDataCodewords(version, ecl) * 8; const dataCapacityBits: int = QrCode.getNumDataCodewords(version, ecl) * 8;
if (bb.length > dataCapacityBits) if (bb.length > dataCapacityBits)
throw "Assertion error"; throw "Assertion error";
bb.appendBits(0, Math.min(4, dataCapacityBits - bb.length)); appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb);
bb.appendBits(0, (8 - bb.length % 8) % 8); appendBits(0, (8 - bb.length % 8) % 8, bb);
if (bb.length % 8 != 0) if (bb.length % 8 != 0)
throw "Assertion error"; throw "Assertion error";
// Pad with alternating bytes until data capacity is reached // Pad with alternating bytes until data capacity is reached
for (let padByte = 0xEC; bb.length < dataCapacityBits; padByte ^= 0xEC ^ 0x11) for (let padByte = 0xEC; bb.length < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8); appendBits(padByte, 8, bb);
// Pack bits into bytes in big endian // Pack bits into bytes in big endian
let dataCodewords: Array<byte> = []; let dataCodewords: Array<byte> = [];
@ -757,6 +757,16 @@ namespace qrcodegen {
} }
// Appends the given number of low-order bits of the given value
// to the given buffer. Requires 0 <= len <= 31 and 0 <= val < 2^len.
function appendBits(val: int, len: int, bb: Array<bit>): void {
if (len < 0 || len > 31 || val >>> len != 0)
throw "Value out of range";
for (let i = len - 1; i >= 0; i--) // Append bit by bit
bb.push((val >>> i) & 1);
}
// Returns true iff the i'th bit of x is set to 1. // Returns true iff the i'th bit of x is set to 1.
function getBit(x: int, i: int): boolean { function getBit(x: int, i: int): boolean {
return ((x >>> i) & 1) != 0; return ((x >>> i) & 1) != 0;
@ -785,9 +795,9 @@ namespace qrcodegen {
// byte mode. All input byte arrays are acceptable. Any text string // byte mode. All input byte arrays are acceptable. Any text string
// can be converted to UTF-8 bytes and encoded as a byte mode segment. // can be converted to UTF-8 bytes and encoded as a byte mode segment.
public static makeBytes(data: Array<byte>): QrSegment { public static makeBytes(data: Array<byte>): QrSegment {
let bb = new BitBuffer(); let bb: Array<bit> = []
for (const b of data) for (const b of data)
bb.appendBits(b, 8); appendBits(b, 8, bb);
return new QrSegment(QrSegment.Mode.BYTE, data.length, bb); return new QrSegment(QrSegment.Mode.BYTE, data.length, bb);
} }
@ -796,10 +806,10 @@ namespace qrcodegen {
public static makeNumeric(digits: string): QrSegment { public static makeNumeric(digits: string): QrSegment {
if (!this.NUMERIC_REGEX.test(digits)) if (!this.NUMERIC_REGEX.test(digits))
throw "String contains non-numeric characters"; throw "String contains non-numeric characters";
let bb = new BitBuffer(); let bb: Array<bit> = []
for (let i = 0; i < digits.length; ) { // Consume up to 3 digits per iteration for (let i = 0; i < digits.length; ) { // Consume up to 3 digits per iteration
const n: int = Math.min(digits.length - i, 3); const n: int = Math.min(digits.length - i, 3);
bb.appendBits(parseInt(digits.substr(i, n), 10), n * 3 + 1); appendBits(parseInt(digits.substr(i, n), 10), n * 3 + 1, bb);
i += n; i += n;
} }
return new QrSegment(QrSegment.Mode.NUMERIC, digits.length, bb); return new QrSegment(QrSegment.Mode.NUMERIC, digits.length, bb);
@ -812,15 +822,15 @@ namespace qrcodegen {
public static makeAlphanumeric(text: string): QrSegment { public static makeAlphanumeric(text: string): QrSegment {
if (!this.ALPHANUMERIC_REGEX.test(text)) if (!this.ALPHANUMERIC_REGEX.test(text))
throw "String contains unencodable characters in alphanumeric mode"; throw "String contains unencodable characters in alphanumeric mode";
let bb = new BitBuffer(); let bb: Array<bit> = []
let i: int; let i: int;
for (i = 0; i + 2 <= text.length; i += 2) { // Process groups of 2 for (i = 0; i + 2 <= text.length; i += 2) { // Process groups of 2
let temp: int = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; let temp: int = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45;
temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1));
bb.appendBits(temp, 11); appendBits(temp, 11, bb);
} }
if (i < text.length) // 1 character remaining if (i < text.length) // 1 character remaining
bb.appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6, bb);
return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length, bb); return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length, bb);
} }
@ -843,17 +853,17 @@ namespace qrcodegen {
// Returns a segment representing an Extended Channel Interpretation // Returns a segment representing an Extended Channel Interpretation
// (ECI) designator with the given assignment value. // (ECI) designator with the given assignment value.
public static makeEci(assignVal: int): QrSegment { public static makeEci(assignVal: int): QrSegment {
let bb = new BitBuffer(); let bb: Array<bit> = []
if (assignVal < 0) if (assignVal < 0)
throw "ECI assignment value out of range"; throw "ECI assignment value out of range";
else if (assignVal < (1 << 7)) else if (assignVal < (1 << 7))
bb.appendBits(assignVal, 8); appendBits(assignVal, 8, bb);
else if (assignVal < (1 << 14)) { else if (assignVal < (1 << 14)) {
bb.appendBits(2, 2); appendBits(2, 2, bb);
bb.appendBits(assignVal, 14); appendBits(assignVal, 14, bb);
} else if (assignVal < 1000000) { } else if (assignVal < 1000000) {
bb.appendBits(6, 3); appendBits(6, 3, bb);
bb.appendBits(assignVal, 21); appendBits(assignVal, 21, bb);
} else } else
throw "ECI assignment value out of range"; throw "ECI assignment value out of range";
return new QrSegment(QrSegment.Mode.ECI, 0, bb); return new QrSegment(QrSegment.Mode.ECI, 0, bb);
@ -940,27 +950,6 @@ namespace qrcodegen {
} }
/*---- Private helper class ----*/
/*
* An appendable sequence of bits (0s and 1s). Mainly used by QrSegment.
* The implicit constructor creates an empty bit buffer (length 0).
*/
class BitBuffer extends Array<bit> {
// Appends the given number of low-order bits of the given value
// to this buffer. Requires 0 <= len <= 31 and 0 <= val < 2^len.
public appendBits(val: int, len: int): void {
if (len < 0 || len > 31 || val >>> len != 0)
throw "Value out of range";
for (let i = len - 1; i >= 0; i--) // Append bit by bit
this.push((val >>> i) & 1);
}
}
} }

Loading…
Cancel
Save