Removed the test worker program in every language and the Python batch tester, because this is not core functionality and is hard to explain.
parent
d4080974f2
commit
2261248957
@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
* QR Code generator test worker (C)
|
|
||||||
*
|
|
||||||
* This program reads data and encoding parameters from standard input and writes
|
|
||||||
* QR Code bitmaps to standard output. The I/O format is one integer per line.
|
|
||||||
* Run with no command line arguments. The program is intended for automated
|
|
||||||
* batch testing of end-to-end functionality of this QR Code generator library.
|
|
||||||
*
|
|
||||||
* Copyright (c) Project Nayuki. (MIT License)
|
|
||||||
* https://www.nayuki.io/page/qr-code-generator-library
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
* this software and associated documentation files (the "Software"), to deal in
|
|
||||||
* the Software without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
* subject to the following conditions:
|
|
||||||
* - The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
* - The Software is provided "as is", without warranty of any kind, express or
|
|
||||||
* implied, including but not limited to the warranties of merchantability,
|
|
||||||
* fitness for a particular purpose and noninfringement. In no event shall the
|
|
||||||
* authors or copyright holders be liable for any claim, damages or other
|
|
||||||
* liability, whether in an action of contract, tort or otherwise, arising from,
|
|
||||||
* out of or in connection with the Software or the use or other dealings in the
|
|
||||||
* Software.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "qrcodegen.h"
|
|
||||||
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
while (true) {
|
|
||||||
|
|
||||||
// Read data length or exit
|
|
||||||
size_t length;
|
|
||||||
{
|
|
||||||
int temp;
|
|
||||||
if (scanf("%d", &temp) != 1)
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
if (temp == -1)
|
|
||||||
break;
|
|
||||||
length = (size_t)temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read data bytes
|
|
||||||
bool isAscii = true;
|
|
||||||
uint8_t *data = malloc(length * sizeof(uint8_t));
|
|
||||||
if (data == NULL) {
|
|
||||||
perror("malloc");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < length; i++) {
|
|
||||||
int b;
|
|
||||||
if (scanf("%d", &b) != 1)
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
data[i] = (uint8_t)b;
|
|
||||||
isAscii &= 0 < b && b < 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read encoding parameters
|
|
||||||
int errCorLvl, minVersion, maxVersion, mask, boostEcl;
|
|
||||||
if (scanf("%d %d %d %d %d", &errCorLvl, &minVersion, &maxVersion, &mask, &boostEcl) != 5)
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
|
|
||||||
// Allocate memory for QR Code
|
|
||||||
size_t bufferLen = (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion);
|
|
||||||
uint8_t *qrcode = malloc(bufferLen * sizeof(uint8_t));
|
|
||||||
uint8_t *tempBuffer = malloc(bufferLen * sizeof(uint8_t));
|
|
||||||
if (qrcode == NULL || tempBuffer == NULL) {
|
|
||||||
perror("malloc");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to make QR Code symbol
|
|
||||||
bool ok;
|
|
||||||
if (isAscii) {
|
|
||||||
char *text = malloc((length + 1) * sizeof(char));
|
|
||||||
if (text == NULL) {
|
|
||||||
perror("malloc");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < length; i++)
|
|
||||||
text[i] = (char)data[i];
|
|
||||||
text[length] = '\0';
|
|
||||||
ok = qrcodegen_encodeText(text, tempBuffer, qrcode, (enum qrcodegen_Ecc)errCorLvl,
|
|
||||||
minVersion, maxVersion, (enum qrcodegen_Mask)mask, boostEcl == 1);
|
|
||||||
free(text);
|
|
||||||
} else if (length <= bufferLen) {
|
|
||||||
memcpy(tempBuffer, data, length * sizeof(data[0]));
|
|
||||||
ok = qrcodegen_encodeBinary(tempBuffer, length, qrcode, (enum qrcodegen_Ecc)errCorLvl,
|
|
||||||
minVersion, maxVersion, (enum qrcodegen_Mask)mask, boostEcl == 1);
|
|
||||||
} else
|
|
||||||
ok = false;
|
|
||||||
free(data);
|
|
||||||
free(tempBuffer);
|
|
||||||
|
|
||||||
if (ok) {
|
|
||||||
// Print grid of modules
|
|
||||||
int size = qrcodegen_getSize(qrcode);
|
|
||||||
printf("%d\n", (size - 17) / 4);
|
|
||||||
for (int y = 0; y < size; y++) {
|
|
||||||
for (int x = 0; x < size; x++)
|
|
||||||
printf("%d\n", qrcodegen_getModule(qrcode, x, y) ? 1 : 0);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
printf("-1\n");
|
|
||||||
free(qrcode);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
/*
|
|
||||||
* QR Code generator test worker (C++)
|
|
||||||
*
|
|
||||||
* This program reads data and encoding parameters from standard input and writes
|
|
||||||
* QR Code bitmaps to standard output. The I/O format is one integer per line.
|
|
||||||
* Run with no command line arguments. The program is intended for automated
|
|
||||||
* batch testing of end-to-end functionality of this QR Code generator library.
|
|
||||||
*
|
|
||||||
* Copyright (c) Project Nayuki. (MIT License)
|
|
||||||
* https://www.nayuki.io/page/qr-code-generator-library
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
* this software and associated documentation files (the "Software"), to deal in
|
|
||||||
* the Software without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
* subject to the following conditions:
|
|
||||||
* - The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
* - The Software is provided "as is", without warranty of any kind, express or
|
|
||||||
* implied, including but not limited to the warranties of merchantability,
|
|
||||||
* fitness for a particular purpose and noninfringement. In no event shall the
|
|
||||||
* authors or copyright holders be liable for any claim, damages or other
|
|
||||||
* liability, whether in an action of contract, tort or otherwise, arising from,
|
|
||||||
* out of or in connection with the Software or the use or other dealings in the
|
|
||||||
* Software.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include "qrcodegen.hpp"
|
|
||||||
|
|
||||||
using qrcodegen::QrCode;
|
|
||||||
using qrcodegen::QrSegment;
|
|
||||||
|
|
||||||
|
|
||||||
static const std::vector<QrCode::Ecc> ECC_LEVELS{
|
|
||||||
QrCode::Ecc::LOW,
|
|
||||||
QrCode::Ecc::MEDIUM,
|
|
||||||
QrCode::Ecc::QUARTILE,
|
|
||||||
QrCode::Ecc::HIGH,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
while (true) {
|
|
||||||
|
|
||||||
// Read data length or exit
|
|
||||||
int length;
|
|
||||||
std::cin >> length;
|
|
||||||
if (length == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Read data bytes
|
|
||||||
bool isAscii = true;
|
|
||||||
std::vector<uint8_t> data;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
int b;
|
|
||||||
std::cin >> b;
|
|
||||||
data.push_back(static_cast<uint8_t>(b));
|
|
||||||
isAscii &= 0 < b && b < 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read encoding parameters
|
|
||||||
int errCorLvl, minVersion, maxVersion, mask, boostEcl;
|
|
||||||
std::cin >> errCorLvl;
|
|
||||||
std::cin >> minVersion;
|
|
||||||
std::cin >> maxVersion;
|
|
||||||
std::cin >> mask;
|
|
||||||
std::cin >> boostEcl;
|
|
||||||
|
|
||||||
// Make list of segments
|
|
||||||
std::vector<QrSegment> segs;
|
|
||||||
if (isAscii) {
|
|
||||||
std::vector<char> text(data.cbegin(), data.cend());
|
|
||||||
text.push_back('\0');
|
|
||||||
segs = QrSegment::makeSegments(text.data());
|
|
||||||
} else
|
|
||||||
segs.push_back(QrSegment::makeBytes(data));
|
|
||||||
|
|
||||||
try { // Try to make QR Code symbol
|
|
||||||
const QrCode qr = QrCode::encodeSegments(segs,
|
|
||||||
ECC_LEVELS.at(static_cast<std::size_t>(errCorLvl)), minVersion, maxVersion, mask, boostEcl == 1);
|
|
||||||
// Print grid of modules
|
|
||||||
std::cout << qr.getVersion() << std::endl;
|
|
||||||
for (int y = 0; y < qr.getSize(); y++) {
|
|
||||||
for (int x = 0; x < qr.getSize(); x++)
|
|
||||||
std::cout << (qr.getModule(x, y) ? 1 : 0) << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (const qrcodegen::data_too_long &ex) {
|
|
||||||
std::cout << -1 << std::endl;
|
|
||||||
}
|
|
||||||
std::cout << std::flush;
|
|
||||||
}
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
* QR Code generator test worker (Java)
|
|
||||||
*
|
|
||||||
* This program reads data and encoding parameters from standard input and writes
|
|
||||||
* QR Code bitmaps to standard output. The I/O format is one integer per line.
|
|
||||||
* Run with no command line arguments. The program is intended for automated
|
|
||||||
* batch testing of end-to-end functionality of this QR Code generator library.
|
|
||||||
*
|
|
||||||
* Copyright (c) Project Nayuki. (MIT License)
|
|
||||||
* https://www.nayuki.io/page/qr-code-generator-library
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
* this software and associated documentation files (the "Software"), to deal in
|
|
||||||
* the Software without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
* subject to the following conditions:
|
|
||||||
* - The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
* - The Software is provided "as is", without warranty of any kind, express or
|
|
||||||
* implied, including but not limited to the warranties of merchantability,
|
|
||||||
* fitness for a particular purpose and noninfringement. In no event shall the
|
|
||||||
* authors or copyright holders be liable for any claim, damages or other
|
|
||||||
* liability, whether in an action of contract, tort or otherwise, arising from,
|
|
||||||
* out of or in connection with the Software or the use or other dealings in the
|
|
||||||
* Software.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.nayuki.qrcodegen;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Scanner;
|
|
||||||
|
|
||||||
|
|
||||||
public final class QrCodeGeneratorWorker {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
// Set up input stream and start loop
|
|
||||||
try (Scanner input = new Scanner(System.in, "US-ASCII")) {
|
|
||||||
input.useDelimiter("\r\n|\n|\r");
|
|
||||||
while (processCase(input));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static boolean processCase(Scanner input) {
|
|
||||||
// Read data length or exit
|
|
||||||
int length = input.nextInt();
|
|
||||||
if (length == -1)
|
|
||||||
return false;
|
|
||||||
if (length > Short.MAX_VALUE)
|
|
||||||
throw new RuntimeException();
|
|
||||||
|
|
||||||
// Read data bytes
|
|
||||||
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)
|
|
||||||
throw new RuntimeException();
|
|
||||||
data[i] = (byte)b;
|
|
||||||
isAscii &= b < 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read encoding parameters
|
|
||||||
int errCorLvl = input.nextInt();
|
|
||||||
int minVersion = input.nextInt();
|
|
||||||
int maxVersion = input.nextInt();
|
|
||||||
int mask = input.nextInt();
|
|
||||||
int boostEcl = input.nextInt();
|
|
||||||
if (!(0 <= errCorLvl && errCorLvl <= 3) || !(-1 <= mask && mask <= 7) || (boostEcl >>> 1) != 0
|
|
||||||
|| !(QrCode.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= QrCode.MAX_VERSION))
|
|
||||||
throw new RuntimeException();
|
|
||||||
|
|
||||||
// Make segments for encoding
|
|
||||||
List<QrSegment> segs;
|
|
||||||
if (isAscii)
|
|
||||||
segs = QrSegment.makeSegments(new String(data, StandardCharsets.US_ASCII));
|
|
||||||
else
|
|
||||||
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);
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (DataTooLongException e) {
|
|
||||||
System.out.println(-1);
|
|
||||||
}
|
|
||||||
System.out.flush();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,144 +0,0 @@
|
|||||||
#
|
|
||||||
# QR Code generator batch test (Python)
|
|
||||||
#
|
|
||||||
# Runs various versions of the QR Code generator test worker as subprocesses,
|
|
||||||
# feeds each one the same random input, and compares their output for equality.
|
|
||||||
#
|
|
||||||
# Copyright (c) Project Nayuki. (MIT License)
|
|
||||||
# https://www.nayuki.io/page/qr-code-generator-library
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
# this software and associated documentation files (the "Software"), to deal in
|
|
||||||
# the Software without restriction, including without limitation the rights to
|
|
||||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
# subject to the following conditions:
|
|
||||||
# - The above copyright notice and this permission notice shall be included in
|
|
||||||
# all copies or substantial portions of the Software.
|
|
||||||
# - The Software is provided "as is", without warranty of any kind, express or
|
|
||||||
# implied, including but not limited to the warranties of merchantability,
|
|
||||||
# fitness for a particular purpose and noninfringement. In no event shall the
|
|
||||||
# authors or copyright holders be liable for any claim, damages or other
|
|
||||||
# liability, whether in an action of contract, tort or otherwise, arising from,
|
|
||||||
# out of or in connection with the Software or the use or other dealings in the
|
|
||||||
# Software.
|
|
||||||
#
|
|
||||||
|
|
||||||
import itertools, random, subprocess, sys, time
|
|
||||||
from typing import List, Optional, TypeVar
|
|
||||||
|
|
||||||
|
|
||||||
CHILD_PROGRAMS: List[List[str]] = [
|
|
||||||
["python3", "-B", "../python/qrcodegen-worker.py"], # Python program
|
|
||||||
["java", "-cp", "../java/bin", "-ea:io.nayuki.qrcodegen...", "io/nayuki/qrcodegen/QrCodeGeneratorWorker"], # Java program
|
|
||||||
["node", "../typescript-javascript/qrcodegen-worker.js"], # TypeScript program
|
|
||||||
["../c/qrcodegen-worker"], # C program
|
|
||||||
["../cpp/QrCodeGeneratorWorker"], # C++ program
|
|
||||||
["../rust/target/debug/examples/qrcodegen-worker"], # Rust program
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
subprocs: List[subprocess.Popen] = []
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
# Launch workers
|
|
||||||
global subprocs
|
|
||||||
try:
|
|
||||||
for args in CHILD_PROGRAMS:
|
|
||||||
subprocs.append(subprocess.Popen(args, universal_newlines=True,
|
|
||||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE))
|
|
||||||
except FileNotFoundError:
|
|
||||||
write_all(-1)
|
|
||||||
raise
|
|
||||||
|
|
||||||
# Check if any died
|
|
||||||
time.sleep(0.3)
|
|
||||||
if any(proc.poll() is not None for proc in subprocs):
|
|
||||||
for proc in subprocs:
|
|
||||||
if proc.poll() is None:
|
|
||||||
print(-1, file=proc.stdin)
|
|
||||||
not_none(proc.stdin).flush()
|
|
||||||
sys.exit("Error: One or more workers failed to start")
|
|
||||||
|
|
||||||
# Do tests
|
|
||||||
for i in itertools.count():
|
|
||||||
print("Trial {}: ".format(i), end="")
|
|
||||||
do_trial()
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
def do_trial() -> None:
|
|
||||||
mode: int = random.randrange(4)
|
|
||||||
length: int
|
|
||||||
data: List[int]
|
|
||||||
if mode == 0: # Numeric
|
|
||||||
length = round((2 * 7089) ** random.random())
|
|
||||||
data = random.choices(b"0123456789", k=length)
|
|
||||||
elif mode == 1: # Alphanumeric
|
|
||||||
length = round((2 * 4296) ** random.random())
|
|
||||||
data = random.choices(b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:", k=length)
|
|
||||||
elif mode == 2: # ASCII
|
|
||||||
length = round((2 * 2953) ** random.random())
|
|
||||||
data = [random.randrange(128) for _ in range(length)]
|
|
||||||
elif mode == 3: # Byte
|
|
||||||
length = round((2 * 2953) ** random.random())
|
|
||||||
data = [random.randrange(256) for _ in range(length)]
|
|
||||||
else:
|
|
||||||
raise AssertionError()
|
|
||||||
|
|
||||||
write_all(length)
|
|
||||||
for b in data:
|
|
||||||
write_all(b)
|
|
||||||
|
|
||||||
errcorlvl: int = random.randrange(4)
|
|
||||||
minversion: int = random.randint(1, 40)
|
|
||||||
maxversion: int = random.randint(1, 40)
|
|
||||||
if minversion > maxversion:
|
|
||||||
minversion, maxversion = maxversion, minversion
|
|
||||||
mask: int = -1
|
|
||||||
if random.random() < 0.5:
|
|
||||||
mask = random.randrange(8)
|
|
||||||
boostecl = int(random.random() < 0.2)
|
|
||||||
print("mode={} len={} ecl={} minv={} maxv={} mask={} boost={}".format(mode, length, errcorlvl, minversion, maxversion, mask, boostecl), end="")
|
|
||||||
|
|
||||||
write_all(errcorlvl)
|
|
||||||
write_all(minversion)
|
|
||||||
write_all(maxversion)
|
|
||||||
write_all(mask)
|
|
||||||
write_all(boostecl)
|
|
||||||
flush_all()
|
|
||||||
|
|
||||||
version: int = read_verify()
|
|
||||||
print(" version={}".format(version), end="")
|
|
||||||
if version == -1:
|
|
||||||
return
|
|
||||||
size: int = version * 4 + 17
|
|
||||||
for _ in range(size**2):
|
|
||||||
read_verify()
|
|
||||||
|
|
||||||
|
|
||||||
def write_all(val: int) -> None:
|
|
||||||
for proc in subprocs:
|
|
||||||
print(val, file=proc.stdin)
|
|
||||||
|
|
||||||
def flush_all() -> None:
|
|
||||||
for proc in subprocs:
|
|
||||||
not_none(proc.stdin).flush()
|
|
||||||
|
|
||||||
def read_verify() -> int:
|
|
||||||
val: str = not_none(subprocs[0].stdout).readline().rstrip("\r\n")
|
|
||||||
for proc in subprocs[1 : ]:
|
|
||||||
if not_none(proc.stdout).readline().rstrip("\r\n") != val:
|
|
||||||
raise ValueError("Mismatch")
|
|
||||||
return int(val)
|
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar("T")
|
|
||||||
def not_none(obj: Optional[T]) -> T:
|
|
||||||
if obj is None:
|
|
||||||
raise TypeError()
|
|
||||||
return obj
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -1,82 +0,0 @@
|
|||||||
#
|
|
||||||
# QR Code generator test worker (Python)
|
|
||||||
#
|
|
||||||
# This program reads data and encoding parameters from standard input and writes
|
|
||||||
# QR Code bitmaps to standard output. The I/O format is one integer per line.
|
|
||||||
# Run with no command line arguments. The program is intended for automated
|
|
||||||
# batch testing of end-to-end functionality of this QR Code generator library.
|
|
||||||
#
|
|
||||||
# Copyright (c) Project Nayuki. (MIT License)
|
|
||||||
# https://www.nayuki.io/page/qr-code-generator-library
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
# this software and associated documentation files (the "Software"), to deal in
|
|
||||||
# the Software without restriction, including without limitation the rights to
|
|
||||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
# subject to the following conditions:
|
|
||||||
# - The above copyright notice and this permission notice shall be included in
|
|
||||||
# all copies or substantial portions of the Software.
|
|
||||||
# - The Software is provided "as is", without warranty of any kind, express or
|
|
||||||
# implied, including but not limited to the warranties of merchantability,
|
|
||||||
# fitness for a particular purpose and noninfringement. In no event shall the
|
|
||||||
# authors or copyright holders be liable for any claim, damages or other
|
|
||||||
# liability, whether in an action of contract, tort or otherwise, arising from,
|
|
||||||
# out of or in connection with the Software or the use or other dealings in the
|
|
||||||
# Software.
|
|
||||||
#
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from typing import List, Sequence
|
|
||||||
import qrcodegen
|
|
||||||
|
|
||||||
|
|
||||||
def read_int() -> int:
|
|
||||||
return int(input())
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
while True:
|
|
||||||
|
|
||||||
# Read data or exit
|
|
||||||
length: int = read_int()
|
|
||||||
if length == -1:
|
|
||||||
break
|
|
||||||
data = bytearray(read_int() for _ in range(length))
|
|
||||||
|
|
||||||
# Read encoding parameters
|
|
||||||
errcorlvl : int = read_int()
|
|
||||||
minversion: int = read_int()
|
|
||||||
maxversion: int = read_int()
|
|
||||||
mask : int = read_int()
|
|
||||||
boostecl : int = read_int()
|
|
||||||
|
|
||||||
# Make segments for encoding
|
|
||||||
if all((b < 128) for b in data): # Is ASCII
|
|
||||||
segs: List[qrcodegen.QrSegment] = qrcodegen.QrSegment.make_segments(data.decode("ASCII"))
|
|
||||||
else:
|
|
||||||
segs = [qrcodegen.QrSegment.make_bytes(data)]
|
|
||||||
|
|
||||||
try: # Try to make QR Code symbol
|
|
||||||
qr: qrcodegen.QrCode = qrcodegen.QrCode.encode_segments(segs, ECC_LEVELS[errcorlvl], minversion, maxversion, mask, boostecl != 0)
|
|
||||||
# Print grid of modules
|
|
||||||
print(qr.get_version())
|
|
||||||
for y in range(qr.get_size()):
|
|
||||||
for x in range(qr.get_size()):
|
|
||||||
print(1 if qr.get_module(x, y) else 0)
|
|
||||||
|
|
||||||
except qrcodegen.DataTooLongError:
|
|
||||||
print(-1)
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
|
|
||||||
ECC_LEVELS: Sequence[qrcodegen.QrCode.Ecc] = (
|
|
||||||
qrcodegen.QrCode.Ecc.LOW,
|
|
||||||
qrcodegen.QrCode.Ecc.MEDIUM,
|
|
||||||
qrcodegen.QrCode.Ecc.QUARTILE,
|
|
||||||
qrcodegen.QrCode.Ecc.HIGH,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
* QR Code generator test worker (Rust)
|
|
||||||
*
|
|
||||||
* This program reads data and encoding parameters from standard input and writes
|
|
||||||
* QR Code bitmaps to standard output. The I/O format is one integer per line.
|
|
||||||
* Run with no command line arguments. The program is intended for automated
|
|
||||||
* batch testing of end-to-end functionality of this QR Code generator library.
|
|
||||||
*
|
|
||||||
* Copyright (c) Project Nayuki. (MIT License)
|
|
||||||
* https://www.nayuki.io/page/qr-code-generator-library
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
* this software and associated documentation files (the "Software"), to deal in
|
|
||||||
* the Software without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
* subject to the following conditions:
|
|
||||||
* - The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
* - The Software is provided "as is", without warranty of any kind, express or
|
|
||||||
* implied, including but not limited to the warranties of merchantability,
|
|
||||||
* fitness for a particular purpose and noninfringement. In no event shall the
|
|
||||||
* authors or copyright holders be liable for any claim, damages or other
|
|
||||||
* liability, whether in an action of contract, tort or otherwise, arising from,
|
|
||||||
* out of or in connection with the Software or the use or other dealings in the
|
|
||||||
* Software.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern crate qrcodegen;
|
|
||||||
use qrcodegen::Mask;
|
|
||||||
use qrcodegen::QrCode;
|
|
||||||
use qrcodegen::QrCodeEcc;
|
|
||||||
use qrcodegen::QrSegment;
|
|
||||||
use qrcodegen::Version;
|
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
loop {
|
|
||||||
|
|
||||||
// Read data length or exit
|
|
||||||
let length: i16 = read_int();
|
|
||||||
if length == -1 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read data bytes
|
|
||||||
let mut data = Vec::<u8>::with_capacity(length as usize);
|
|
||||||
for _ in 0 .. length {
|
|
||||||
let b: i16 = read_int();
|
|
||||||
assert_eq!(i16::from(b as u8), b, "Byte value out of range");
|
|
||||||
data.push(b as u8);
|
|
||||||
}
|
|
||||||
let isascii: bool = data.iter().all(|b| *b < 128);
|
|
||||||
|
|
||||||
// Read encoding parameters
|
|
||||||
let errcorlvl = read_int();
|
|
||||||
let minversion = read_int();
|
|
||||||
let maxversion = read_int();
|
|
||||||
let mask = read_int();
|
|
||||||
let boostecl = read_int();
|
|
||||||
assert!(0 <= errcorlvl && errcorlvl <= 3);
|
|
||||||
assert!(i16::from(Version::MIN.value()) <= minversion
|
|
||||||
&& minversion <= maxversion
|
|
||||||
&& maxversion <= i16::from(Version::MAX.value()));
|
|
||||||
assert!(-1 <= mask && mask <= 7);
|
|
||||||
assert!(boostecl >> 1 == 0);
|
|
||||||
|
|
||||||
// Make segments for encoding
|
|
||||||
let segs: Vec<QrSegment> = if isascii {
|
|
||||||
let chrs: Vec<char> = std::str::from_utf8(&data).unwrap().chars().collect();
|
|
||||||
QrSegment::make_segments(&chrs)
|
|
||||||
} else {
|
|
||||||
vec![QrSegment::make_bytes(&data)]
|
|
||||||
};
|
|
||||||
|
|
||||||
// Try to make QR Code symbol
|
|
||||||
let msk = if mask == -1 { None } else { Some(Mask::new(mask as u8)) };
|
|
||||||
match QrCode::encode_segments_advanced(&segs, ECC_LEVELS[errcorlvl as usize],
|
|
||||||
Version::new(minversion as u8), Version::new(maxversion as u8), msk, boostecl != 0) {
|
|
||||||
|
|
||||||
Ok(qr) => {
|
|
||||||
// Print grid of modules
|
|
||||||
println!("{}", qr.version().value());
|
|
||||||
for y in 0 .. qr.size() {
|
|
||||||
for x in 0 .. qr.size() {
|
|
||||||
println!("{}", qr.get_module(x, y) as i8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(_) => println!("-1"),
|
|
||||||
}
|
|
||||||
use std::io::Write;
|
|
||||||
std::io::stdout().flush().unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn read_int() -> i16 {
|
|
||||||
let mut line = String::new();
|
|
||||||
std::io::stdin().read_line(&mut line).unwrap();
|
|
||||||
let mut chrs: Vec<char> = line.chars().collect();
|
|
||||||
assert_eq!(chrs.pop().unwrap(), '\n');
|
|
||||||
let line: String = chrs.iter().cloned().collect();
|
|
||||||
line.parse::<i16>().expect("Invalid number")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ECC_LEVELS: [QrCodeEcc; 4] = [
|
|
||||||
QrCodeEcc::Low,
|
|
||||||
QrCodeEcc::Medium,
|
|
||||||
QrCodeEcc::Quartile,
|
|
||||||
QrCodeEcc::High,
|
|
||||||
];
|
|
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* QR Code generator test worker (TypeScript)
|
|
||||||
*
|
|
||||||
* This program reads data and encoding parameters from standard input and writes
|
|
||||||
* QR Code bitmaps to standard output. The I/O format is one integer per line.
|
|
||||||
* Run with no command line arguments. The program is intended for automated
|
|
||||||
* batch testing of end-to-end functionality of this QR Code generator library.
|
|
||||||
*
|
|
||||||
* Copyright (c) Project Nayuki. (MIT License)
|
|
||||||
* https://www.nayuki.io/page/qr-code-generator-library
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
* this software and associated documentation files (the "Software"), to deal in
|
|
||||||
* the Software without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
* subject to the following conditions:
|
|
||||||
* - The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
* - The Software is provided "as is", without warranty of any kind, express or
|
|
||||||
* implied, including but not limited to the warranties of merchantability,
|
|
||||||
* fitness for a particular purpose and noninfringement. In no event shall the
|
|
||||||
* authors or copyright holders be liable for any claim, damages or other
|
|
||||||
* liability, whether in an action of contract, tort or otherwise, arising from,
|
|
||||||
* out of or in connection with the Software or the use or other dealings in the
|
|
||||||
* Software.
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
|
|
||||||
async function main(): Promise<void> {
|
|
||||||
while (true) {
|
|
||||||
// Read data or exit
|
|
||||||
const length: number = await input.readInt();
|
|
||||||
if (length == -1)
|
|
||||||
break;
|
|
||||||
let data: Array<number> = [];
|
|
||||||
for (let i = 0; i < length; i++)
|
|
||||||
data.push(await input.readInt());
|
|
||||||
|
|
||||||
// Read encoding parameters
|
|
||||||
const errCorLvl : number = await input.readInt();
|
|
||||||
const minVersion: number = await input.readInt();
|
|
||||||
const maxVersion: number = await input.readInt();
|
|
||||||
const mask : number = await input.readInt();
|
|
||||||
const boostEcl : number = await input.readInt();
|
|
||||||
|
|
||||||
// Make segments for encoding
|
|
||||||
let segs: Array<qrcodegen.QrSegment>;
|
|
||||||
if (data.every(b => b < 128)) { // Is ASCII
|
|
||||||
const s: string = data.map(b => String.fromCharCode(b)).join("");
|
|
||||||
segs = qrcodegen.QrSegment.makeSegments(s);
|
|
||||||
} else
|
|
||||||
segs = [qrcodegen.QrSegment.makeBytes(data)];
|
|
||||||
|
|
||||||
try { // Try to make QR Code symbol
|
|
||||||
const qr = qrcodegen.QrCode.encodeSegments(
|
|
||||||
segs, ECC_LEVELS[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0);
|
|
||||||
// Print grid of modules
|
|
||||||
await printLine(qr.version);
|
|
||||||
for (let y = 0; y < qr.size; y++) {
|
|
||||||
for (let x = 0; x < qr.size; x++)
|
|
||||||
await printLine(qr.getModule(x, y) ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
if (e == "Data too long")
|
|
||||||
await printLine(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace input {
|
|
||||||
|
|
||||||
let queue: Array<string> = [];
|
|
||||||
let callback: ((line:string)=>void)|null = null;
|
|
||||||
|
|
||||||
const readline = require("readline");
|
|
||||||
let reader = readline.createInterface({
|
|
||||||
input: process.stdin,
|
|
||||||
terminal: false,
|
|
||||||
});
|
|
||||||
reader.on("line", (line: string) => {
|
|
||||||
queue.push(line);
|
|
||||||
if (callback !== null) {
|
|
||||||
callback(queue.shift() as string);
|
|
||||||
callback = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
async function readLine(): Promise<string> {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
if (callback !== null)
|
|
||||||
throw "Illegal state";
|
|
||||||
if (queue.length > 0)
|
|
||||||
resolve(queue.shift() as string);
|
|
||||||
else
|
|
||||||
callback = resolve;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export async function readInt(): Promise<number> {
|
|
||||||
let s = await readLine();
|
|
||||||
if (!/^-?\d+$/.test(s))
|
|
||||||
throw "Invalid number syntax";
|
|
||||||
return parseInt(s, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function printLine(x: Object): Promise<void> {
|
|
||||||
return new Promise(resolve =>
|
|
||||||
process.stdout.write(x + "\n", "utf-8", ()=>resolve()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const ECC_LEVELS: Array<qrcodegen.QrCode.Ecc> = [
|
|
||||||
qrcodegen.QrCode.Ecc.LOW,
|
|
||||||
qrcodegen.QrCode.Ecc.MEDIUM,
|
|
||||||
qrcodegen.QrCode.Ecc.QUARTILE,
|
|
||||||
qrcodegen.QrCode.Ecc.HIGH,
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
main();
|
|
Loading…
Reference in new issue