readData function
Reads the content of QR code encoded data, according to its version.
Implementation
QrContent? readData(Uint8ClampedList data, int version) {
final stream = _BitStream(data);
// There are 3 'sizes' based on the version. 1-9 is small (0), 10-26 is medium (1) and 27-40 is large (2).
final size = version <= 9
? 0
: version <= 26
? 1
: 2;
String text = "";
List<int> bytes = [];
List<Chunk> chunks = [];
while (stream.available() >= 4) {
final mode = stream.readBits(4);
if (mode == _modeByteIndex[_ModeByte.terminator]) {
return QrContent(
text: text,
bytes: bytes,
chunks: chunks,
version: version,
);
} else if (mode == _modeByteIndex[_ModeByte.eci]) {
if (stream.readBits(1) == 0) {
chunks.add(Chunk(
type: ChunkMode.eci,
assignmentNumber: stream.readBits(7),
));
} else if (stream.readBits(1) == 0) {
chunks.add(Chunk(
type: ChunkMode.eci,
assignmentNumber: stream.readBits(14),
));
} else if (stream.readBits(1) == 0) {
chunks.add(Chunk(
type: ChunkMode.eci,
assignmentNumber: stream.readBits(21),
));
} else {
// ECI data seems corrupted
chunks.add(Chunk(
type: ChunkMode.eci,
assignmentNumber: -1,
));
}
} else if (mode == _modeByteIndex[_ModeByte.numeric]) {
final numericResult = decodeNumeric(stream, size);
text += numericResult.text;
bytes.addAll(numericResult.bytes);
chunks.add(Chunk(
type: ChunkMode.numeric,
text: numericResult.text,
));
} else if (mode == _modeByteIndex[_ModeByte.alphanumeric]) {
final alphanumericResult = _decodeAlphanumeric(stream, size);
text += alphanumericResult.text;
bytes.addAll(alphanumericResult.bytes);
chunks.add(Chunk(
type: ChunkMode.alphanumeric,
text: alphanumericResult.text,
));
} else if (mode == _modeByteIndex[_ModeByte.byte]) {
final byteResult = _decodeByte(stream, size);
text += byteResult.text;
bytes.addAll(byteResult.bytes);
chunks.add(
Chunk(
type: ChunkMode.byte,
bytes: byteResult.bytes,
text: byteResult.text,
),
);
} else if (mode == _modeByteIndex[_ModeByte.kanji]) {
final kanjiResult = _decodeKanji(stream, size);
text += kanjiResult.text;
bytes.addAll(kanjiResult.bytes);
chunks.add(Chunk(
type: ChunkMode.kanji,
bytes: kanjiResult.bytes,
text: kanjiResult.text,
));
}
}
// If there is no data left, or the remaining bits are all 0, then that counts as a termination marker
if (stream.available() == 0 || stream.readBits(stream.available()) == 0) {
return QrContent(
text: text,
bytes: bytes,
chunks: chunks,
version: version,
);
}
return null;
}