From 714de48ee817b294cb02156247369bd48855b133 Mon Sep 17 00:00:00 2001 From: manuelbl Date: Mon, 14 Jan 2019 22:10:11 +0100 Subject: [PATCH] API documentation cleanup --- dotnet/QrCodeGenerator/BitArrayExtensions.cs | 47 +-- .../QrCodeGenerator/DataTooLongException.cs | 29 +- dotnet/QrCodeGenerator/Objects.cs | 15 +- dotnet/QrCodeGenerator/QrCode.cs | 387 +++++++++--------- dotnet/QrCodeGenerator/QrSegment.cs | 228 +++++++---- dotnet/QrCodeGenerator/QrSegmentAdvanced.cs | 89 ++-- .../QrCodeGenerator/ReedSolomonGenerator.cs | 39 +- dotnet/QrCodeGeneratorDemo/Program.cs | 26 +- .../BitArrayExtensionsTest.cs | 2 +- dotnet/QrCodeGeneratorTest/KanjiTest.cs | 2 +- .../QrCodeGeneratorTest/OptimalSegmentTest.cs | 2 +- dotnet/QrCodeGeneratorTest/PngTest.cs | 2 +- dotnet/QrCodeGeneratorTest/QrCodeTest.cs | 14 +- .../QrSegmentEncodingTest.cs | 2 +- .../QrCodeGeneratorTest/QrSegmentRegexTest.cs | 2 +- dotnet/QrCodeGeneratorTest/SvgTest.cs | 2 +- dotnet/QrCodeGeneratorTest/TestHelper.cs | 2 +- 17 files changed, 498 insertions(+), 392 deletions(-) diff --git a/dotnet/QrCodeGenerator/BitArrayExtensions.cs b/dotnet/QrCodeGenerator/BitArrayExtensions.cs index 290ba3d..c0c4ca7 100644 --- a/dotnet/QrCodeGenerator/BitArrayExtensions.cs +++ b/dotnet/QrCodeGenerator/BitArrayExtensions.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library @@ -27,38 +27,39 @@ using System.Collections; namespace IO.Nayuki.QrCodeGen { /// - /// Provides extension methods for the class. + /// Extension methods for the class. /// public static class BitArrayExtensions { /// - /// Appends the specified number of low-order bits of the specified value to this - /// bit array. Requires 0 ≤ len ≤ 31 and 0 ≤ val < 2len. + /// Appends the specified number bits of the specified value to this bit array. + /// + /// The least significant bits of the specified value are added. They are appended in reverse order, + /// from the most significant to the least significant one, i.e. bits 0 to len-1 + /// are appended in the order len-1, len-2 ... 1, 0. + /// + /// + /// Requires 0 ≤ len ≤ 31, and 0 ≤ val < 2len. + /// /// - /// this bit array - /// the value to append - /// the number of low-order bits in the value to take - /// Thrown if the value or number of bits is out of range - /// Thrown if appending the data would make bit length exceed + /// The BitArray instance that this method extends. + /// The value to append. + /// The number of low-order bits in the value to append. + /// Value or number of bits is out of range. public static void AppendBits(this BitArray bitArray, uint val, int len) { - if (len < 0 || len > 31 || (val >> len) != 0) + if (len < 0 || len > 31 || val >> len != 0) { throw new ArgumentOutOfRangeException(nameof(len), "'len' out of range"); } - if (len < 0 || len > 31 || (val >> len) != 0) + if (len < 0 || len > 31 || val >> len != 0) { throw new ArgumentOutOfRangeException(nameof(val), "'val' out of range"); } int bitLength = bitArray.Length; - if (int.MaxValue - bitLength < len) - { - throw new InvalidOperationException("Maximum length reached"); - } - bitArray.Length = bitLength + len; uint mask = 1U << (len - 1); for (int i = bitLength; i < bitLength + len; i++) // Append bit by bit @@ -74,21 +75,15 @@ namespace IO.Nayuki.QrCodeGen /// - /// Appends the content of the specified bit array to this array. + /// Appends the content of the specified bit array to the end of this array. /// - /// this bit array - /// the bit array whose data to append (not null) - /// Thrown if the bit array is null - /// Thrown if appending the data would make the bit length exceed + /// The BitArray instance that this method extends. + /// The bit array to append + /// If bitArray is null. public static void AppendData(this BitArray bitArray, BitArray otherArray) { Objects.RequireNonNull(otherArray); int bitLength = bitArray.Length; - if (int.MaxValue - bitLength < otherArray.Length) - { - throw new InvalidOperationException("Maximum length reached"); - } - bitArray.Length = bitLength + otherArray.Length; for (int i = 0; i < otherArray.Length; i++, bitLength++) // Append bit by bit { diff --git a/dotnet/QrCodeGenerator/DataTooLongException.cs b/dotnet/QrCodeGenerator/DataTooLongException.cs index 25c8841..822c296 100644 --- a/dotnet/QrCodeGenerator/DataTooLongException.cs +++ b/dotnet/QrCodeGenerator/DataTooLongException.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library @@ -26,31 +26,34 @@ using System.Collections.Generic; namespace IO.Nayuki.QrCodeGen { /// - /// Thrown when the supplied data does not fit any QR Code version. + /// The exception that is thrown when the supplied data does not fit in the QR code. /// /// /// Ways to handle this exception include: /// /// /// /// - /// /// /// public class DataTooLongException : ArgumentException { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. public DataTooLongException(string message) : base(message) { } diff --git a/dotnet/QrCodeGenerator/Objects.cs b/dotnet/QrCodeGenerator/Objects.cs index cea4296..79e3114 100644 --- a/dotnet/QrCodeGenerator/Objects.cs +++ b/dotnet/QrCodeGenerator/Objects.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library @@ -25,8 +25,21 @@ using System; namespace IO.Nayuki.QrCodeGen { + /// + /// Helper functions to check for valid arguments. + /// internal class Objects { + /// + /// Ensures that the specified argument is not null. + /// + /// Throws a exception if the argument is null. + /// + /// + /// The type of the argument. + /// The argument to check. + /// Argument passed to function. + /// The specified argument is null. internal static T RequireNonNull(T arg) { if (arg == null) diff --git a/dotnet/QrCodeGenerator/QrCode.cs b/dotnet/QrCodeGenerator/QrCode.cs index 41251f1..3b694ed 100644 --- a/dotnet/QrCodeGenerator/QrCode.cs +++ b/dotnet/QrCodeGenerator/QrCode.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library @@ -33,26 +33,35 @@ using System.Text; namespace IO.Nayuki.QrCodeGen { /// - /// A QR Code symbol, which is a type of two-dimension barcode. + /// Represents a QR code containing text or binary data. + /// + /// Instances of this class represent an immutable square grid of black and white pixels + /// (called modules by the QR code specification). + /// Static factory methods are provided to create QR codes from text or binary data. + /// Some of the methods provide detailed control about the encoding parameters such a QR + /// code size (called version by the standard), error correction level and mask. + /// + /// + /// QR codes are a type of two-dimensional barcodes, invented by Denso Wave and + /// described in the ISO/IEC 18004 standard. + /// + /// + /// This class covers the QR Code Model 2 specification, supporting all versions (sizes) + /// from 1 to 40, all 4 error correction levels, and 4 character encoding modes. /// /// - /// Invented by Denso Wave and described in the ISO/IEC 18004 standard. - /// araInstances of this class represent an immutable square grid of black and white cells. - /// The class provides static factory functions to create a QR Code from text or binary data. - /// The class covers the QR Code Model 2 specification, supporting all versions (sizes) - /// from 1 to 40, all 4 error correction levels, and 4 character encoding modes. - /// Ways to create a QR Code object: + /// + /// To create a QR code instance: + /// ///
    ///
  • High level: Take the payload data and call - /// or .
  • - ///
  • Mid level: Custom-make the list of - /// and call or - ///
  • - ///
  • Low level: Custom-make the array of data codeword bytes (including segment headers and - /// final padding, excluding error correction codewords), supply the appropriate version number, - /// and call the .
  • + /// or . + ///
  • Mid level: Custom-make a list of instances and call + ///
  • + ///
  • Low level: Custom-make an array of data codeword bytes (including segment headers and + /// final padding, excluding error correction codewords), supply the appropriate version number, + /// and call the .
  • ///
- /// (Note that all ways require supplying the desired error correction level.) ///
/// public class QrCode @@ -60,20 +69,20 @@ namespace IO.Nayuki.QrCodeGen #region Static factory functions (high level) /// - /// Returns a QR Code representing the specified Unicode text string at the specified error correction level. + /// Creates a QR code representing the specified text using the specified error correction level. + /// + /// As a conservative upper bound, this function is guaranteed to succeed for strings with up to 738 + /// Unicode code points (not UTF-16 code units) if the low error correction level is used. The smallest possible + /// QR code version (size) is automatically chosen. The resulting ECC level will be higher than the one + /// specified if it can be achieved without increasing the size (version). + /// /// - /// - /// As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer - /// Unicode code points(not UTF-16 code units) if the low error correction level is used.The smallest possible - /// QR Code version is automatically chosen for the output.The ECC level of the result may be higher than the - /// ecl argument if it can be done without increasing the version. - /// - /// the text to be encoded (not null), which can be any Unicode string - /// the error correction level to use (not null) (boostable) - /// a QR Code (not null) representing the text - /// Thrown if the text or error correction level is null - /// Thrown if the text fails to fit in the - /// largest version QR Code at the ECL, which means it is too long + /// The text to be encoded. The full range of Unicode characters may be used. + /// The minimum error correction level to use. + /// The created QR code instance representing the specified text. + /// or is null. + /// The text is too long to fit in the largest QR code size (version) + /// at the specified error correction level. public static QrCode EncodeText(string text, Ecc ecl) { Objects.RequireNonNull(text); @@ -83,19 +92,19 @@ namespace IO.Nayuki.QrCodeGen } /// - /// Returns a QR Code representing the specified binary data at the specified error correction level. + /// Creates a QR code representing the specified binary data using the specified error correction level. + /// + /// This function encodes the data in the binary segment mode. The maximum number of + /// bytes allowed is 2953. The smallest possible QR code version is automatically chosen. + /// The resulting ECC level will be higher than the one specified if it can be achieved without increasing the size (version). + /// /// - /// - /// This function always encodes using the binary segment mode, not any text mode. The maximum number of - /// bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output. - /// The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version. - /// - /// the binary data to encode (not null) - /// the error correction level to use (not null) (boostable) - /// a QR Code (not null) representing the data - /// Thrown if the data or error correction level is null - /// Thrown if the data fails to fit in the - /// largest version QR Code at the ECL, which means it is too long + /// The binary data to encode. + /// The minimum error correction level to use. + /// The created QR code representing the specified data. + /// or is null. + /// The specified data is too long to fit in the largest QR code size (version) + /// at the specified error correction level. public static QrCode EncodeBinary(byte[] data, Ecc ecl) { Objects.RequireNonNull(data); @@ -110,56 +119,44 @@ namespace IO.Nayuki.QrCodeGen #region Static factory functions (mid level) /// - /// Returns a QR Code representing the specified segments at the specified error correction level. - /// - /// - /// The smallest possible QR Code version is automatically chosen for the output. The ECC level - /// of the result may be higher than the ecl argument if it can be done without increasing the version. - /// This function allows the user to create a custom sequence of segments that switches - /// between modes (such as alphanumeric and byte) to encode text in less space. - /// This is a mid-level API; the high-level API is - /// and - /// - /// the segments to encode - /// the error correction level to use (not null) (boostable) - /// a QR Code (not null) representing the segments - /// Thrown if the data or error correction level is null - /// Thrown if the segments fail to fit in the - /// largest version QR Code at the ECL, which means it is too long - public static QrCode EncodeSegments(List segs, Ecc ecl) - { - return EncodeSegments(segs, ecl, MinVersion, MaxVersion, -1, true); - } - - /// - /// Returns a QR Code representing the specified segments with the specified encoding parameters. + /// Creates a QR code representing the specified segments with the specified encoding parameters. + /// + /// The smallest possible QR code version (size) is used. The range of versions can be + /// restricted by the and parameters. + /// + /// + /// If is true, the resulting ECC level will be higher than the + /// one specified if it can be achieved without increasing the size (version). + /// + /// + /// The QR code mask is usually automatically chosen. It can be explicitly set with the + /// parameter by using a value between 0 to 7 (inclusive). -1 is for automatic mode (which may be slow). + /// + /// + /// This function allows the user to create a custom sequence of segments that switches + /// between modes (such as alphanumeric and byte) to encode text in less space and gives full control over all + /// encoding paramters. + /// /// /// - /// The smallest possible QR Code version within the specified range is automatically - /// chosen for the output. Iff boostEcl is true, then the ECC level of the - /// result may be higher than the ecl argument if it can be done without increasing - /// the version. The mask number is either between 0 to 7 (inclusive) to force that - /// mask, or −1 to automatically choose an appropriate mask (which may be slow). - /// This function allows the user to create a custom sequence of segments that switches - /// between modes (such as alphanumeric and byte) to encode text in less space. - /// This is a mid-level API; the high-level API is - /// and . + /// This is a mid-level API; the high-level APIs are + /// and . /// - /// the segments to encode - /// the error correction level to use (not null) (boostable) - /// the minimum allowed version of the QR Code (at least 1) - /// the maximum allowed version of the QR Code (at most 40) - /// the mask number to use (between 0 and 7 (inclusive)), or −1 for automatic mask - /// increases the ECC level as long as it doesn't increase the version number - /// a QR Code (not null) representing the segments - /// Thrown if the list of segments, any segment, or the error correction level is null - /// Thrown if 1 ≤ minVersion ≤ maxVersion ≤ 40 - /// or −1 ≤ mask ≤ 7 is violated - /// Thrown DataTooLongException if the segments fail to fit in - /// the maxVersion QR Code at the ECL, which means they are too long - public static QrCode EncodeSegments(List segs, Ecc ecl, int minVersion, int maxVersion, int mask, bool boostEcl) + /// The segments to encode. + /// The minimal or fixed error correction level to use . + /// The minimum version (size) of the QR code (between 1 and 40). + /// The maximum version (size) of the QR code (between 1 and 40). + /// The mask number to use (between 0 and 7), or -1 for automatic mask selection. + /// If true the ECC level wil be increased if it can be achieved without increasing the size (version). + /// The created QR code representing the segments. + /// , any list element, or is null. + /// 1 ≤ minVersion ≤ maxVersion ≤ 40 + /// or -1 ≤ mask ≤ 7 is violated. + /// The segments are too long to fit in the largest QR code size (version) + /// at the specified error correction level. + public static QrCode EncodeSegments(List segments, Ecc ecl, int minVersion = MinVersion, int maxVersion = MaxVersion, int mask = -1, bool boostEcl = true) { - Objects.RequireNonNull(segs); + Objects.RequireNonNull(segments); Objects.RequireNonNull(ecl); if (minVersion < MinVersion || minVersion > maxVersion) { @@ -179,7 +176,7 @@ namespace IO.Nayuki.QrCodeGen for (version = minVersion; ; version++) { int numDataBits = GetNumDataCodewords(version, ecl) * 8; // Number of data bits available - dataUsedBits = QrSegment.GetTotalBits(segs, version); + dataUsedBits = QrSegment.GetTotalBits(segments, version); if (dataUsedBits != -1 && dataUsedBits <= numDataBits) { break; // This version number is found to be suitable @@ -209,7 +206,7 @@ namespace IO.Nayuki.QrCodeGen // Concatenate all segments to create the data bit string BitArray ba = new BitArray(0); - foreach (QrSegment seg in segs) + foreach (QrSegment seg in segments) { ba.AppendBits(seg.EncodingMode.ModeBits, 4); ba.AppendBits((uint)seg.NumChars, seg.EncodingMode.NumCharCountBits(version)); @@ -240,7 +237,7 @@ namespace IO.Nayuki.QrCodeGen } } - // Create the QR Code object + // Create the QR code object return new QrCode(version, ecl, dataCodewords, mask); } @@ -250,28 +247,33 @@ namespace IO.Nayuki.QrCodeGen #region Public immutable properties /// - /// The version number of this QR Code, which is between 1 and 40 (inclusive). - /// This determines the size of this barcode. + /// The version (size) of this QR code (between 1 for the smallest and 40 for the biggest). /// + /// The QR code version (size). public int Version { get; } /// - /// The width and height of this QR Code, measured in modules, between - /// 21 and 177 (inclusive). This is equal to version × 4 + 17. + /// The width and height of this QR code, in modules (pixels). + /// The size is a value between 21 and 177. + /// This is equal to version × 4 + 17. /// + /// The QR code size. public int Size { get; } /// - /// The error correction level used in this QR Code, which is not null. + /// The error correction level used for this QR code. /// + /// The error correction level. public Ecc ErrorCorrectionLevel { get; } /// - /// The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive). + /// The index of the mask pattern used fort this QR code (between 0 and 7). + /// + /// Even if a QR code is created with automatic mask selection (mask = 1), + /// this property returns the effective mask used. + /// /// - /// Even if a QR Code is created with automatic masking requested (mask = - /// −1), the resulting object still has a mask value between 0 and 7. - /// + /// The mask pattern index. public int Mask { get; } #endregion @@ -279,8 +281,8 @@ namespace IO.Nayuki.QrCodeGen #region Private grids of modules/pixels, with dimensions of size * size - // The modules of this QR Code (false = white, true = black). - // Immutable after constructor finishes. Accessed through getModule(). + // The modules of this QR code (false = white, true = black). + // Immutable after constructor finishes. Accessed through GetModule(). private readonly bool[,] _modules; // Indicates function modules that are not subjected to masking. Discarded when constructor finishes. @@ -292,26 +294,26 @@ namespace IO.Nayuki.QrCodeGen #region Constructor (low level) /// - /// Constructs a QR Code with the specified version number, + /// Constructs a QR code with the specified version number, /// error correction level, data codeword bytes, and mask number. /// /// /// This is a low-level API that most users should not use directly. A mid-level - /// API is the function. + /// API is the function. /// - /// the version number to use, which must be in the range 1 to 40 (inclusive) - /// the error correction level to use - /// the bytes representing segments to encode (without ECC) - /// the mask pattern to use, which is either −1 for automatic choice or from 0 to 7 for fixed choice - /// Thrown if the byte array or error correction level is null - /// Thrown if the version or mask value is out of range, - /// or if the data is the wrong length for the specified version and error correction level - public QrCode(int ver, Ecc ecl, byte[] dataCodewords, int mask) + /// The version (size) to use (between 1 to 40). + /// The error correction level to use. + /// The bytes representing segments to encode (without ECC). + /// The mask pattern to use (either -1 for automatic selection, or a value from 0 to 7 for fixed choice). + /// or is null. + /// The version or mask value is out of range, + /// or the data has an invalid length for the specified version and error correction level. + public QrCode(int version, Ecc ecl, byte[] dataCodewords, int mask = -1) { // Check arguments and initialize fields - if (ver < MinVersion || ver > MaxVersion) + if (version < MinVersion || version > MaxVersion) { - throw new ArgumentOutOfRangeException(nameof(ver), "Version value out of range"); + throw new ArgumentOutOfRangeException(nameof(version), "Version value out of range"); } if (mask < -1 || mask > 7) @@ -319,8 +321,8 @@ namespace IO.Nayuki.QrCodeGen throw new ArgumentOutOfRangeException(nameof(mask), "Mask value out of range"); } - Version = ver; - Size = ver * 4 + 17; + Version = version; + Size = version * 4 + 17; Objects.RequireNonNull(ecl); ErrorCorrectionLevel = ecl; Objects.RequireNonNull(dataCodewords); @@ -342,18 +344,19 @@ namespace IO.Nayuki.QrCodeGen #region Public methods /// - /// Returns the color of the module (pixel) at the specified coordinates, which is false - /// for white or true for black. + /// Gets the color of the module (pixel) at the specified coordinates. + /// + /// The top left corner has the coordinates (x=0, y=0). x-coordinates extend from left to right, + /// y-coordinates extend from top to bottom. + /// + /// + /// If coordinates outside the bounds of this QR code are specified, white (false) is returned. + /// /// - /// - /// The top left corner has the coordinates (x=0, y=0). - /// If the specified coordinates are out of bounds, then false - /// (white) is returned. - /// - /// the x coordinate, where 0 is the left edge and size−1 is the right edge - /// the y coordinate, where 0 is the top edge and size−1 is the bottom edge - /// true if the coordinates are in bounds and the module - /// at that location is black, or false (white) otherwise + /// The x coordinate. + /// The y coordinate. + /// The color of the specified module: true for black modules and false + /// for white modules (or if the coordinates are outside the bounds). public bool GetModule(int x, int y) { return 0 <= x && x < Size && 0 <= y && y < Size && _modules[y, x]; @@ -361,18 +364,26 @@ namespace IO.Nayuki.QrCodeGen /// - /// Returns a bitmap (raster image) depicting this QR Code, with the specified module scale and border modules. - /// - /// - /// For example, ToBitmap(scale: 10, border: 4) means to pad the QR Code with 4 white + /// Creates a bitmap (raster image) of this QR code. + /// + /// The parameter specifies the scale of the image, which is + /// equivalent to the width and height of each QR code module. Additionally, the number + /// of modules to add as a border to all four sides can be specified. + /// + /// + /// For example, ToBitmap(scale: 10, border: 4) means to pad the QR code with 4 white /// border modules on all four sides, and use 10×10 pixels to represent each module. - /// The resulting image only contains the hex colors 000000 and FFFFFF. - /// - /// the side length (measured in pixels, must be positive) of each module - /// the number of border modules to add, which must be non-negative - /// a new image representing this QR Code, with padding and scaling - /// Thrown if the scale is 0 or negative, if the border is negative - /// or if the resulting image is wider than 32,768 pixels + /// + /// + /// The resulting bitmap uses the pixel format and + /// only contains black (0x000000) and white (0xFFFFFF) pixels. + /// + /// + /// The width and height, in pixels, of each module. + /// The number of border modules to add to each of the four sides. + /// The created bitmap representing this QR code. + /// is 0 or negative, is negative + /// or the resulting image is wider than 32,768 pixels. public Bitmap ToBitmap(int scale, int border) { if (scale <= 0) @@ -408,14 +419,14 @@ namespace IO.Nayuki.QrCodeGen /// - /// Returns a string of SVG code for an image depicting this QR Code, with the specified number of border modules. + /// Creates an SVG image of this QR code. + /// + /// The images uses Unix newlines (\n), regardless of the platform. + /// /// - /// - /// The string always uses Unix newlines (\n), regardless of the platform. - /// - /// the number of border modules to add, which must be non-negative - /// a string representing this QR Code as an SVG XML document - /// Thrown if the border is negative + /// The number of border modules to add on all four sides. + /// The created SVG XML document of this QR code as a string. + /// is negative. public string ToSvgString(int border) { if (border < 0) @@ -424,23 +435,22 @@ namespace IO.Nayuki.QrCodeGen } int dim = Size + border * 2; - var sb = new StringBuilder() + StringBuilder sb = new StringBuilder() .Append("\n") .Append("\n") .Append($"\n") .Append("\t\n") .Append("\t> 3], 7 - (i & 7)); + _modules[y, x] = GetBit(data[(uint)i >> 3], 7 - (i & 7)); i++; } - // If this QR Code has any remainder bits (0 to 7), they were assigned as + // If this QR code has any remainder bits (0 to 7), they were assigned as // 0/false/white by the constructor and are left unchanged by this method } } @@ -701,11 +711,11 @@ namespace IO.Nayuki.QrCodeGen } - // XORs the codeword modules in this QR Code with the given mask pattern. + // XORs the codeword modules in this QR code with the given mask pattern. // The function modules must be marked and the codeword bits must be drawn // before masking. Due to the arithmetic of XOR, calling applyMask() with // the same mask value a second time will undo the mask. A final well-formed - // QR Code needs exactly one (not zero, two, etc.) mask applied. + // QR code needs exactly one (not zero, two, etc.) mask applied. private void ApplyMask(uint mask) { if (mask > 7) @@ -736,7 +746,7 @@ namespace IO.Nayuki.QrCodeGen } - // A messy helper function for the constructor. This QR Code must be in an unmasked state when this + // A messy helper function for the constructor. This QR code must be in an unmasked state when this // method is called. The given argument is the requested mask, which is -1 for auto or 0 to 7 for fixed. // This method applies and returns the actual mask chosen, from 0 to 7. private int HandleConstructorMasking(int mask) @@ -765,7 +775,7 @@ namespace IO.Nayuki.QrCodeGen } - // Calculates and returns the penalty score based on state of this QR Code's current modules. + // Calculates and returns the penalty score based on state of this QR code's current modules. // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. private int GetPenaltyScore() { @@ -932,7 +942,7 @@ namespace IO.Nayuki.QrCodeGen } } - // Returns the number of data bits that can be stored in a QR Code of the given version number, after + // Returns the number of data bits that can be stored in a QR code of the given version number, after // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. private static int GetNumRawDataModules(int ver) @@ -943,28 +953,28 @@ namespace IO.Nayuki.QrCodeGen } int size = ver * 4 + 17; - int result = size * size; // Number of modules in the whole QR Code square + int result = size * size; // Number of modules in the whole QR code square result -= 8 * 8 * 3; // Subtract the three finders with separators result -= 15 * 2 + 1; // Subtract the format information and black module result -= (size - 16) * 2; // Subtract the timing patterns (excluding finders) // The five lines above are equivalent to: int result = (16 * ver + 128) * ver + 64; - if (ver >= 2) + + if (ver < 2) return result; + + int numAlign = ver / 7 + 2; + result -= (numAlign - 1) * (numAlign - 1) * 25; // Subtract alignment patterns not overlapping with timing patterns + result -= (numAlign - 2) * 2 * 20; // Subtract alignment patterns that overlap with timing patterns + // The two lines above are equivalent to: result -= (25 * numAlign - 10) * numAlign - 55; + if (ver >= 7) { - int numAlign = ver / 7 + 2; - result -= (numAlign - 1) * (numAlign - 1) * 25; // Subtract alignment patterns not overlapping with timing patterns - result -= (numAlign - 2) * 2 * 20; // Subtract alignment patterns that overlap with timing patterns - // The two lines above are equivalent to: result -= (25 * numAlign - 10) * numAlign - 55; - if (ver >= 7) - { - result -= 6 * 3 * 2; // Subtract version information - } + result -= 6 * 3 * 2; // Subtract version information } return result; } // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any - // QR Code of the given version number and error correction level, with remainder bits discarded. + // QR code of the given version number and error correction level, with remainder bits discarded. // This stateless pure function could be implemented as a (40*4)-cell lookup table. internal static int GetNumDataCodewords(int ver, Ecc ecl) { @@ -1022,21 +1032,23 @@ namespace IO.Nayuki.QrCodeGen #region Constants and tables /// - /// The minimum version number (1) supported in the QR Code Model 2 standard. + /// The minimum version (size) supported in the QR Code Model 2 standard – namely 1. /// - public static readonly int MinVersion = 1; + /// The minimum version. + public const int MinVersion = 1; /// - /// The maximum version number (40) supported in the QR Code Model 2 standard. + /// The maximum version (size) supported in the QR Code Model 2 standard – namely 40. /// - public static readonly int MaxVersion = 40; + /// The maximum version. + public const int MaxVersion = 40; // For use in getPenaltyScore(), when evaluating which mask is best. - private static readonly int PenaltyN1 = 3; - private static readonly int PenaltyN2 = 3; - private static readonly int PenaltyN3 = 40; - private static readonly int PenaltyN4 = 10; + private const int PenaltyN1 = 3; + private const int PenaltyN2 = 3; + private const int PenaltyN3 = 40; + private const int PenaltyN4 = 10; private static readonly byte[,] EccCodewordsPerBlock = { @@ -1063,28 +1075,32 @@ namespace IO.Nayuki.QrCodeGen #region Public helper enumeration /// - /// The error correction level in a QR Code symbol. + /// Error correction level in QR code symbol. /// public sealed class Ecc { /// - /// The QR Code can tolerate about 7% erroneous codewords. + /// Low error correction level. The QR code can tolerate about 7% erroneous codewords. /// + /// Low error correction level. public static readonly Ecc Low = new Ecc(0, 1); /// - /// The QR Code can tolerate about 15% erroneous codewords. + /// Medium error correction level. The QR code can tolerate about 15% erroneous codewords. /// + /// Medium error correction level. public static readonly Ecc Medium = new Ecc(1, 0); /// - /// The QR Code can tolerate about 25% erroneous codewords. + /// Quartile error correction level. The QR code can tolerate about 25% erroneous codewords. /// + /// Quartile error correction level. public static readonly Ecc Quartile = new Ecc(2, 3); /// - /// The QR Code can tolerate about 30% erroneous codewords. + /// High error correction level. The QR code can tolerate about 30% erroneous codewords. /// + /// High error correction level. public static readonly Ecc High = new Ecc(3, 2); @@ -1096,6 +1112,7 @@ namespace IO.Nayuki.QrCodeGen /// /// Higher number represent a higher amount of error tolerance. /// + /// Ordinal number. public int Ordinal { get; } // In the range 0 to 3 (unsigned 2-bit integer). diff --git a/dotnet/QrCodeGenerator/QrSegment.cs b/dotnet/QrCodeGenerator/QrSegment.cs index fa9318f..2f174f7 100644 --- a/dotnet/QrCodeGenerator/QrSegment.cs +++ b/dotnet/QrCodeGenerator/QrSegment.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library @@ -31,35 +31,45 @@ using System.Text.RegularExpressions; namespace IO.Nayuki.QrCodeGen { /// - /// A segment of character/binary/control data in a QR Code symbol. + /// Represents 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 . The low-level - /// way to create a segment is to custom-make the bit buffer and call the - /// with appropriate values. - /// This segment class imposes no length restrictions, but QR Codes have restrictions. - /// Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. - /// Any segment longer than this is meaningless for the purpose of generating QR Codes. + /// + /// The easiest way to deal with QR code segments is to call + /// or , and not + /// to use instances of this class directly. The mid-level way is to take the payload + /// data and call a static factory function such as . + /// The low-level way is to custom-make the bit array and call the + /// constructor with appropriate values. + /// + /// + /// This segment class imposes no length restrictions, but QR codes have restrictions. + /// Even in the most favorable conditions, a QR code can only hold 7089 characters of data. + /// Any segment longer than this is meaningless for the purpose of generating QR codes. + /// + /// /// This class can represent kanji mode segments, but provides no help in encoding them - /// - see for full kanji support. + /// - see for full kanji support. + /// + /// + /// Instances of this class are immutable. + /// /// public class QrSegment { #region Static factory functions (mid level) /// - /// Returns a segment representing the specified binary data + /// Creates 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 (Encoding.UTF8.GetBytes(s)) + /// + /// Any text string can be converted to UTF-8 bytes (using Encoding.UTF8.GetBytes(str)) /// and encoded as a byte mode segment. - /// - /// the binary data (not null) - /// a segment (not null) containing the data - /// Thrown if the array is null + /// + /// + /// The binary data to encode. + /// The created segment containing the specified data. + /// data is null. public static QrSegment MakeBytes(byte[] data) { Objects.RequireNonNull(data); @@ -74,12 +84,13 @@ namespace IO.Nayuki.QrCodeGen /// - /// Returns a segment representing the specified string of decimal digits encoded in numeric mode. + /// Creates a segment representing the specified string of decimal digits. + /// The segment is encoded in numeric mode. /// - /// the text (not null), with only digits from 0 to 9 allowed - /// a segment (not null) containing the text - /// Thrown if the string is null - /// Thrown if the string contains non-digit characters + /// The text to encode, consisting of digits from 0 to 9 only. + /// The created segment containing the text. + /// digits is null. + /// digits contains non-digit characters public static QrSegment MakeNumeric(string digits) { Objects.RequireNonNull(digits); @@ -101,14 +112,17 @@ namespace IO.Nayuki.QrCodeGen /// - /// 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, + /// Creates a segment representing the specified text string. + /// The segment is encoded in alphanumeric mode. + /// + /// Allowed characters are: 0 to 9, A to Z (uppercase only), space, /// dollar, percent, asterisk, plus, hyphen, period, slash, colon. + /// /// - /// the text (not null), with only certain characters allowed - /// a segment (not null) containing the text - /// Thrown if the string is null - /// Thrown iif the string contains non-encodable characters + /// The text to encode, consisting of allowed characters only. + /// The created segment containing the text. + /// text is null. + /// text contains non-encodable characters. public static QrSegment MakeAlphanumeric(string text) { Objects.RequireNonNull(text); @@ -136,18 +150,26 @@ namespace IO.Nayuki.QrCodeGen /// - /// 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. + /// Creates a list of zero or more segments representing the specified text string. + /// + /// The text may contain the full range of Unicode characters. + /// + /// + /// The result may multiple segments with various encoding modes in order to minimize the length of the bit stream. + /// /// - /// the text to be encoded, which can be any Unicode string - /// a new mutable list (not null) of segments (not null) containing the text - /// Thrown if the text is null + /// The text to be encoded. + /// The created mutable list of segments representing the specified text. + /// text is null. + /// + /// The current implementation does not use multiple segments. + /// public static List MakeSegments(string text) { Objects.RequireNonNull(text); // Select the most efficient segment encoding automatically - List result = new List(); + var result = new List(); if (text == "") { // Leave result empty @@ -170,12 +192,12 @@ namespace IO.Nayuki.QrCodeGen /// - /// Returns a segment representing an Extended Channel Interpretation + /// Creates a segment representing an Extended Channel Interpretation /// (ECI) designator with the specified assignment value. /// - /// the ECI assignment number (see the AIM ECI specification) - /// a segment (not null) containing the data - /// Thrown if the value is outside the range [0, 106) + /// The ECI assignment number (see the AIM ECI specification). + /// The created segment containing the data. + /// assignValis outside the range [0, 106). public static QrSegment MakeEci(int assignVal) { BitArray ba = new BitArray(0); @@ -184,11 +206,11 @@ namespace IO.Nayuki.QrCodeGen throw new ArgumentOutOfRangeException(nameof(assignVal), "ECI assignment value out of range"); } - if (assignVal < (1 << 7)) + if (assignVal < 1 << 7) { ba.AppendBits((uint)assignVal, 8); } - else if (assignVal < (1 << 14)) + else if (assignVal < 1 << 14) { ba.AppendBits(2, 2); ba.AppendBits((uint)assignVal, 14); @@ -211,16 +233,21 @@ namespace IO.Nayuki.QrCodeGen #region Instance fields - /// - /// The mode indicator of this segment. Not null. - /// + /// The encoding mode of this segment. + /// Encoding mode. public Mode EncodingMode { get; } /// - /// 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. + /// 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. + /// + /// + /// Different from the data's bit length. + /// /// + /// Length of the segment's unencoded data. public int NumChars { get; } // The data bits of this segment. Not null. Accessed through GetData(). @@ -232,25 +259,27 @@ namespace IO.Nayuki.QrCodeGen #region Constructor (low level) /// - /// 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. + /// Initializes a QR code segment with the specified attributes and data. + /// + /// The character count must agree with the mode and the bit array length, + /// but the constraint isn't checked. The specified bit array is cloned. + /// /// - /// the mode (not null) - /// the data length in characters or bytes, which is non-negative - /// the data bits (not null) - /// Thrown if the mode or data is null - /// Thrown if the character count is negative - public QrSegment(Mode md, int numCh, BitArray data) + /// The segment mode used to encode this segment. + /// The data length in characters or bytes (depending on the segment mode). + /// The data bits. + /// or is null. + /// is negative. + public QrSegment(Mode mode, int numChars, BitArray data) { - EncodingMode = Objects.RequireNonNull(md); + EncodingMode = Objects.RequireNonNull(mode); Objects.RequireNonNull(data); - if (numCh < 0) + if (numChars < 0) { - throw new ArgumentOutOfRangeException(nameof(numCh), "Invalid value"); + throw new ArgumentOutOfRangeException(nameof(numChars), "Invalid value"); } - NumChars = numCh; + NumChars = numChars; _data = (BitArray)data.Clone(); // Make defensive copy } @@ -260,9 +289,9 @@ namespace IO.Nayuki.QrCodeGen #region Methods /// - /// Returns the data bits of this segment. + /// Returns a copy of this segment's data bits. /// - /// a new copy of the data bits(notnull) + /// A copy of the data bits. public BitArray GetData() { return (BitArray)_data.Clone(); // Make defensive copy @@ -280,7 +309,7 @@ namespace IO.Nayuki.QrCodeGen { Objects.RequireNonNull(seg); int ccbits = seg.EncodingMode.NumCharCountBits(version); - if (seg.NumChars >= (1 << ccbits)) + if (seg.NumChars >= 1 << ccbits) { return -1; // The segment's length doesn't fit the field's bit width } @@ -300,29 +329,35 @@ namespace IO.Nayuki.QrCodeGen #region Constants /// - /// Describes precisely all strings that are encodable in numeric mode. + /// Immutable regular expression describing all strings encodable in numeric mode. + /// + /// A string is encodable iff each character is in the range 0 to 9. + /// /// /// /// To test whether a string s is encodable: /// /// bool ok = NumericRegex.IsMatch(s); /// - /// A string is encodable iff each character is in the range 0 to 9. /// + /// Regular exprression describing strings encodable in numeric mode. /// public static readonly Regex NumericRegex = new Regex("^[0-9]*$", RegexOptions.Compiled); /// - /// Describes precisely all strings that are encodable in alphanumeric mode. + /// Immutable regular expression describing all strings that are encodable in alphanumeric mode. + /// + /// 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. + /// /// /// /// To test whether a string s is encodable: /// /// bool ok = AlphanumericRegex.IsMatch(s); /// - /// 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. /// + /// Regular exprression describing strings encodable in alphanumeric mode. /// public static readonly Regex AlphanumericRegex = new Regex("^[A-Z0-9 $%*+./:-]*$", RegexOptions.Compiled); @@ -337,34 +372,79 @@ namespace IO.Nayuki.QrCodeGen #region Public helper enumeration /// - /// Describes how a segment's data bits are interpreted. + /// Segment encoding mode. + /// + /// Describes how text or binary data is encoded into bits. + /// /// public sealed class Mode { + /// + /// Numeric encoding mode. + /// + /// Numeric encoding mode. public static readonly Mode Numeric = new Mode(0x1, 10, 12, 14); + /// + /// Alphanumeric encoding mode. + /// + /// Alphanumeric encoding mode. public static readonly Mode Alphanumeric = new Mode(0x2, 9, 11, 13); + /// + /// Byte encoding mode. + /// + /// Byte encoding mode. public static readonly Mode Byte = new Mode(0x4, 8, 16, 16); + /// + /// Kanji encoding mode. + /// + /// Kanji encoding mode. public static readonly Mode Kanji = new Mode(0x8, 8, 10, 12); + /// + /// ECI encoding mode. + /// + /// ECI encoding mode. public static readonly Mode Eci = new Mode(0x7, 0, 0, 0); - // The mode indicator bits, which is a uint4 value (range 0 to 15). + + /// + /// Mode indicator value. + /// + /// 4 bit value in the QR segment header indicating the encoding mode. + /// + /// + /// Mode indicator value internal uint ModeBits { get; } - // Number of character count bits for three different version ranges. + + /// + /// Array of character count bit length. + /// + /// Number of bits for character count in QR segment header. + /// The three array values apply to versions 0 to 9, 10 to 26 and 27 to 40 + /// respectively. All array values are in the range [0, 16]. + /// + /// + /// Array of character count bit length internal int[] NumBitsCharCount { get; } - // Returns the bit width of the character count field for a segment in this mode - // in a QR Code at the given version number. The result is in the range [0, 16]. + + /// + /// Returns the bith length of the character count in the QR segment header + /// for the specified QR code version. The result is in the range [0, 16]. + /// + /// the QR code version (between 1 and 40) + /// internal int NumCharCountBits(int ver) { Debug.Assert(QrCode.MinVersion <= ver && ver <= QrCode.MaxVersion); return NumBitsCharCount[(ver + 7) / 17]; } + // private constructor to initializes the constants private Mode(uint modeBits, params int[] numBitsCharCount) { ModeBits = modeBits; diff --git a/dotnet/QrCodeGenerator/QrSegmentAdvanced.cs b/dotnet/QrCodeGenerator/QrSegmentAdvanced.cs index 1f6f188..918e035 100644 --- a/dotnet/QrCodeGenerator/QrSegmentAdvanced.cs +++ b/dotnet/QrCodeGenerator/QrSegmentAdvanced.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library @@ -32,11 +32,8 @@ using static IO.Nayuki.QrCodeGen.QrSegment; namespace IO.Nayuki.QrCodeGen { /// - /// Splits text into optimal segments and encodes kanji segments. + /// Advanced methods for encoding QR codes using Kanji mode or using multiple segments with different encodings. /// - /// - /// Provides static functions only; not instantiable. - /// /// /// public static class QrSegmentAdvanced @@ -44,26 +41,26 @@ namespace IO.Nayuki.QrCodeGen #region Optimal list of segments encoder /// - /// Returns a list of zero or more segments to represent the specified Unicode text string. + /// Creates a list of zero or more segments to represent the specified text string. /// The resulting list optimally minimizes the total encoded bit length, subjected to the constraints - /// in the specified {error correction level, minimum version number, maximum version number}. + /// of the specified error correction level, minimum and maximum version number. + /// + /// This function potentially uses all four text encoding modes: numeric, alphanumeric, byte (UTF-8), + /// and Kanji. It is a more sophisticated but slower replacement for . + /// + /// + /// The text to be encoded can contain the full set of Unicode characters (code points). + /// /// - /// - /// This function can utilize all four text encoding modes: numeric, alphanumeric, byte (UTF-8), - /// and kanji. This can be considered as a sophisticated but slower replacement for - /// . This requires more input parameters because it searches a - /// range of versions, like . - /// - /// the text to be encoded (not null), which can be any Unicode string - /// the error correction level to use (not null) - /// the minimum allowed version of the QR Code (at least 1) - /// the maximum allowed version of the QR Code (at most 40) - /// a new mutable list (not null) of segments (not null) - /// containing the text, minimizing the bit length with respect to the constraints - /// Thrown if the text or error correction level is null - /// Thrown if 1 ≤ minVersion ≤ maxVersion ≤ 40 is violated - /// Thrown if the text fails to fit in the maxVersion QR Code at the ECL - public static List MakeSegmentsOptimally(string text, QrCode.Ecc ecl, int minVersion, int maxVersion) + /// The text to be encoded. + /// The error correction level to use. + /// The minimum version (size) of the QR code (between 1 and 40). + /// The maximum version (size) of the QR code (between 1 and 40). + /// The created mutable list of segments encoding the specified text with a minimal bit length. + /// or is null. + /// 1 ≤ minVersion ≤ maxVersion ≤ 40 is violated. + /// The text is too long to fit into the QR code with the given encoding parameters. + public static List MakeSegmentsOptimally(string text, QrCode.Ecc ecl, int minVersion = QrCode.MinVersion, int maxVersion = QrCode.MaxVersion) { // Check arguments Objects.RequireNonNull(text); @@ -181,7 +178,7 @@ namespace IO.Nayuki.QrCodeGen { // From mode int newCost = (curCosts[k] + 5) / 6 * 6 + headCosts[j]; - if (charModes[i, k] == null || (charModes[i, j] != null && newCost >= curCosts[j])) + if (charModes[i, k] == null || charModes[i, j] != null && newCost >= curCosts[j]) continue; curCosts[j] = newCost; charModes[i, j] = modeTypes[k]; @@ -266,7 +263,7 @@ namespace IO.Nayuki.QrCodeGen } - public static string FromCodePoints(int[] codepoints, int startIndex, int count) + private static string FromCodePoints(int[] codepoints, int startIndex, int count) { bool useBigEndian = !BitConverter.IsLittleEndian; Encoding utf32 = new UTF32Encoding(useBigEndian, false , true); @@ -321,18 +318,18 @@ namespace IO.Nayuki.QrCodeGen #region Kanji mode segment encoder /// - /// Returns a segment representing the specified text string encoded in kanji mode. + /// Creates a segment encoding the specified text in Kanji mode. + /// + /// Broadly speaking, the set of encodable characters are Kanji used in Japan, + /// Hiragana, Katakana, East Asian punctuation, full-width ASCII, Greek, and Cyrillic. + /// Examples of non-encodable characters include ordinary ASCII, half-width Katakana, + /// more extensive Chinese Hanzi. + /// /// - /// - /// Broadly speaking, the set of encodable characters are {kanji used in Japan, - /// hiragana, katakana, East Asian punctuation, full-width ASCII, Greek, Cyrillic}. - /// Examples of non-encodable characters include {ordinary ASCII, half-width katakana, - /// more extensive Chinese hanzi}. - /// - /// the text (not null), with only certain characters allowed - /// a segment (not null) containing the text - /// Thrown if the string is null - /// Thrown if the string contains non-encodable characters + /// The text to encoding, containing only characters allowed by the Kanji encoding. + /// The created segment respresenting the specified text. + /// is null. + /// contains non-encodable characters. /// public static QrSegment MakeKanji(string text) { @@ -355,17 +352,17 @@ namespace IO.Nayuki.QrCodeGen /// - /// Tests whether the specified string can be encoded as a segment in kanji mode. + /// Tests whether the specified string can be encoded as a segment in Kanji mode. + /// + /// Broadly speaking, the set of encodable characters are Kanji used in Japan, + /// Hiragana, Katakana, East Asian punctuation, full-width ASCII, Greek, and Cyrillic. + /// Examples of non-encodable characters include ordinary ASCII, half-width Katakana, + /// more extensive Chinese Hanzi. + /// /// - /// - /// Broadly speaking, the set of encodable characters are {kanji used in Japan, - /// hiragana, katakana, East Asian punctuation, full-width ASCII, Greek, Cyrillic}. - /// Examples of non-encodable characters include {ordinary ASCII, half-width katakana, - /// more extensive Chinese hanzi}. - /// - /// the string to test for encodability (not null) - /// true iff each character is in the kanji mode character set - /// Thrown if the string is null + /// The text to test for encodability. + /// true iff each character is in the Kanji mode character set. + /// is null. public static bool IsEncodableAsKanji(string text) { Objects.RequireNonNull(text); foreach (char t in text) diff --git a/dotnet/QrCodeGenerator/ReedSolomonGenerator.cs b/dotnet/QrCodeGenerator/ReedSolomonGenerator.cs index 4c33dad..4397b62 100644 --- a/dotnet/QrCodeGenerator/ReedSolomonGenerator.cs +++ b/dotnet/QrCodeGenerator/ReedSolomonGenerator.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library @@ -29,11 +29,11 @@ namespace IO.Nayuki.QrCodeGen { /// /// Computes the Reed-Solomon error correction codewords for a sequence of data codewords at a given degree. + /// + /// Instances are immutable, and the state only depends on the degree. + /// This class is useful because all data blocks in a QR code share the same the divisor polynomial. + /// /// - /// - /// Objects are immutable, and the state only depends on the degree. - /// This class exists because each data block in a QR Code shares the same the divisor polynomial. - /// internal class ReedSolomonGenerator { #region Fields @@ -48,11 +48,13 @@ namespace IO.Nayuki.QrCodeGen #region Constructors /// - /// Constructs a Reed-Solomon ECC generator for the specified degree. This could be implemented - /// as a lookup table over all possible parameter values, instead of as an algorithm. + /// Initializes a new Reed-Solomon ECC generator for the specified degree. /// - /// the divisor polynomial degree, which must be between 1 and 255 (inclusive) - /// Thrown if degree < 1 or degree > 255 + /// + /// This could be implemented as a lookup table over all possible parameter values, instead of as an algorithm. + /// + /// The divisor polynomial degree (between 1 and 255). + /// degree < 1 or degree > 255 internal ReedSolomonGenerator(int degree) { if (degree < 1 || degree > 255) @@ -89,16 +91,15 @@ namespace IO.Nayuki.QrCodeGen #region Methods /// - /// Computes and returns the Reed-Solomon error correction codewords for the specified + /// Computes the Reed-Solomon error correction codewords for the specified /// sequence of data codewords. + /// + /// This method does not alter this object's state (as it is immutable). + /// /// - /// - /// The returned object is always a new byte array. - /// This method does not alter this object's state (because it is immutable). - /// - /// the sequence of data codewords - /// the Reed-Solomon error correction codewords - /// Thrown if the data is null + /// The sequence of data codewords. + /// The Reed-Solomon error correction codewords, as a byte array. + /// If data is null. internal byte[] GetRemainder(byte[] data) { Objects.RequireNonNull(data); @@ -127,7 +128,7 @@ namespace IO.Nayuki.QrCodeGen // are unsigned 8-bit integers. This could be implemented as a lookup table of 256*256 entries of uint8. private static byte Multiply(uint x, uint y) { - Debug.Assert((x >> 8) == 0 && (y >> 8) == 0); + Debug.Assert(x >> 8 == 0 && y >> 8 == 0); // Russian peasant multiplication uint z = 0; for (int i = 7; i >= 0; i--) @@ -135,7 +136,7 @@ namespace IO.Nayuki.QrCodeGen z = (z << 1) ^ ((z >> 7) * 0x11D); z ^= ((y >> i) & 1) * x; } - Debug.Assert((z >> 8) == 0); + Debug.Assert(z >> 8 == 0); return (byte)z; } diff --git a/dotnet/QrCodeGeneratorDemo/Program.cs b/dotnet/QrCodeGeneratorDemo/Program.cs index a946181..9a28627 100644 --- a/dotnet/QrCodeGeneratorDemo/Program.cs +++ b/dotnet/QrCodeGeneratorDemo/Program.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library @@ -42,13 +42,13 @@ namespace IO.Nayuki.QrCodeGen.Demo #region Demo suite - // Creates a single QR Code, then writes it to a PNG file and an SVG file. + // Creates a single QR code, then writes it to a PNG file and an SVG file. private static void DoBasicDemo() { const string text = "Hello, world!"; // User-supplied Unicode text var errCorLvl = QrCode.Ecc.Low; // Error correction level - var qr = QrCode.EncodeText(text, errCorLvl); // Make the QR Code symbol + var qr = QrCode.EncodeText(text, errCorLvl); // Make the QR code symbol using (var img = qr.ToBitmap(10, 4)) // Convert to bitmap image { @@ -60,7 +60,7 @@ namespace IO.Nayuki.QrCodeGen.Demo } - // Creates a variety of QR Codes that exercise different features of the library, and writes each one to file. + // Creates a variety of QR codes that exercise different features of the library, and writes each one to file. private static void DoVarietyDemo() { // Numeric mode encoding (3.33 bits per digit) var qr = QrCode.EncodeText("314159265358979323846264338327950288419716939937510", QrCode.Ecc.Medium); @@ -74,7 +74,7 @@ namespace IO.Nayuki.QrCodeGen.Demo qr = QrCode.EncodeText("こんにちwa、世界! αβγδ", QrCode.Ecc.Quartile); SaveAsPng(qr, "unicode-QR.png", 10, 3); - // Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland) + // Moderately large QR code using longer text (from Lewis Carroll's Alice in Wonderland) qr = QrCode.EncodeText( "Alice was beginning to get very tired of sitting by her sister on the bank, " + "and of having nothing to do: once or twice she had peeped into the book her sister was reading, " @@ -87,7 +87,7 @@ namespace IO.Nayuki.QrCodeGen.Demo } - // Creates QR Codes with manually specified segments for better compactness. + // Creates QR codes with manually specified segments for better compactness. private static void DoSegmentDemo() { // Illustration "silver" @@ -133,24 +133,24 @@ namespace IO.Nayuki.QrCodeGen.Demo } - // Creates QR Codes with the same size and contents but different mask patterns. + // Creates QR codes with the same size and contents but different mask patterns. private static void DoMaskDemo() { // Project Nayuki URL var segs = QrSegment.MakeSegments("https://www.nayuki.io/"); - var qr = QrCode.EncodeSegments(segs, QrCode.Ecc.High, QrCode.MinVersion, QrCode.MaxVersion, -1, true); + var qr = QrCode.EncodeSegments(segs, QrCode.Ecc.High); SaveAsPng(qr, "project-nayuki-automask-QR.png", 8, 6); - qr = QrCode.EncodeSegments(segs, QrCode.Ecc.High, QrCode.MinVersion, QrCode.MaxVersion, 3, true); // Force mask 3 + qr = QrCode.EncodeSegments(segs, QrCode.Ecc.High, QrCode.MinVersion, QrCode.MaxVersion, 3); // Force mask 3 SaveAsPng(qr, "project-nayuki-mask3-QR.png", 8, 6); // Chinese text as UTF-8 segs = QrSegment.MakeSegments("維基百科(Wikipedia,聆聽i/ˌwɪkᵻˈpiːdi.ə/)是一個自由內容、公開編輯且多語言的網路百科全書協作計畫"); - qr = QrCode.EncodeSegments(segs, QrCode.Ecc.Medium, QrCode.MinVersion, QrCode.MaxVersion, 0, true); // Force mask 0 + qr = QrCode.EncodeSegments(segs, QrCode.Ecc.Medium, QrCode.MinVersion, QrCode.MaxVersion, 0); // Force mask 0 SaveAsPng(qr, "unicode-mask0-QR.png", 10, 3); - qr = QrCode.EncodeSegments(segs, QrCode.Ecc.Medium, QrCode.MinVersion, QrCode.MaxVersion, 1, true); // Force mask 1 + qr = QrCode.EncodeSegments(segs, QrCode.Ecc.Medium, QrCode.MinVersion, QrCode.MaxVersion, 1); // Force mask 1 SaveAsPng(qr, "unicode-mask1-QR.png", 10, 3); - qr = QrCode.EncodeSegments(segs, QrCode.Ecc.Medium, QrCode.MinVersion, QrCode.MaxVersion, 5, true); // Force mask 5 + qr = QrCode.EncodeSegments(segs, QrCode.Ecc.Medium, QrCode.MinVersion, QrCode.MaxVersion, 5); // Force mask 5 SaveAsPng(qr, "unicode-mask5-QR.png", 10, 3); - qr = QrCode.EncodeSegments(segs, QrCode.Ecc.Medium, QrCode.MinVersion, QrCode.MaxVersion, 7, true); // Force mask 7 + qr = QrCode.EncodeSegments(segs, QrCode.Ecc.Medium, QrCode.MinVersion, QrCode.MaxVersion, 7); // Force mask 7 SaveAsPng(qr, "unicode-mask7-QR.png", 10, 3); } diff --git a/dotnet/QrCodeGeneratorTest/BitArrayExtensionsTest.cs b/dotnet/QrCodeGeneratorTest/BitArrayExtensionsTest.cs index b0df70c..637c0f5 100644 --- a/dotnet/QrCodeGeneratorTest/BitArrayExtensionsTest.cs +++ b/dotnet/QrCodeGeneratorTest/BitArrayExtensionsTest.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library diff --git a/dotnet/QrCodeGeneratorTest/KanjiTest.cs b/dotnet/QrCodeGeneratorTest/KanjiTest.cs index efa7810..1686846 100644 --- a/dotnet/QrCodeGeneratorTest/KanjiTest.cs +++ b/dotnet/QrCodeGeneratorTest/KanjiTest.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library diff --git a/dotnet/QrCodeGeneratorTest/OptimalSegmentTest.cs b/dotnet/QrCodeGeneratorTest/OptimalSegmentTest.cs index beeb35d..5446a2c 100644 --- a/dotnet/QrCodeGeneratorTest/OptimalSegmentTest.cs +++ b/dotnet/QrCodeGeneratorTest/OptimalSegmentTest.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library diff --git a/dotnet/QrCodeGeneratorTest/PngTest.cs b/dotnet/QrCodeGeneratorTest/PngTest.cs index 0565524..20d7646 100644 --- a/dotnet/QrCodeGeneratorTest/PngTest.cs +++ b/dotnet/QrCodeGeneratorTest/PngTest.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library diff --git a/dotnet/QrCodeGeneratorTest/QrCodeTest.cs b/dotnet/QrCodeGeneratorTest/QrCodeTest.cs index d672fe0..90c2047 100644 --- a/dotnet/QrCodeGeneratorTest/QrCodeTest.cs +++ b/dotnet/QrCodeGeneratorTest/QrCodeTest.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library @@ -613,7 +613,7 @@ namespace IO.Nayuki.QrCodeGen.Test private void TestCode9() { var segments = QrSegment.MakeSegments(Text9); - var qrCode = EncodeSegments(segments, Ecc.High, 1, 40, -1, true); + var qrCode = EncodeSegments(segments, Ecc.High); Assert.Same(Ecc.High, qrCode.ErrorCorrectionLevel); Assert.Equal(29, qrCode.Size); Assert.Equal(1, qrCode.Mask); @@ -658,7 +658,7 @@ namespace IO.Nayuki.QrCodeGen.Test private void TestCode10() { var segments = QrSegment.MakeSegments(Text10); - var qrCode = EncodeSegments(segments, Ecc.High, 1, 40, 3, true); + var qrCode = EncodeSegments(segments, Ecc.High, 1, 40, 3); Assert.Same(Ecc.High, qrCode.ErrorCorrectionLevel); Assert.Equal(29, qrCode.Size); Assert.Equal(3, qrCode.Mask); @@ -723,7 +723,7 @@ namespace IO.Nayuki.QrCodeGen.Test private void TestCode11() { var segments = QrSegment.MakeSegments(Text11); - var qrCode = EncodeSegments(segments, Ecc.Medium, 1, 40, 0, true); + var qrCode = EncodeSegments(segments, Ecc.Medium, 1, 40, 0); Assert.Same(Ecc.Medium, qrCode.ErrorCorrectionLevel); Assert.Equal(49, qrCode.Size); Assert.Equal(0, qrCode.Mask); @@ -788,7 +788,7 @@ namespace IO.Nayuki.QrCodeGen.Test private void TestCode12() { var segments = QrSegment.MakeSegments(Text12); - var qrCode = EncodeSegments(segments, Ecc.Medium, 1, 40, 1, true); + var qrCode = EncodeSegments(segments, Ecc.Medium, 1, 40, 1); Assert.Same(Ecc.Medium, qrCode.ErrorCorrectionLevel); Assert.Equal(49, qrCode.Size); Assert.Equal(1, qrCode.Mask); @@ -853,7 +853,7 @@ namespace IO.Nayuki.QrCodeGen.Test private void TestCode13() { var segments = QrSegment.MakeSegments(Text13); - var qrCode = EncodeSegments(segments, Ecc.Medium, 1, 40, 5, true); + var qrCode = EncodeSegments(segments, Ecc.Medium, 1, 40, 5); Assert.Same(Ecc.Medium, qrCode.ErrorCorrectionLevel); Assert.Equal(49, qrCode.Size); Assert.Equal(5, qrCode.Mask); @@ -918,7 +918,7 @@ namespace IO.Nayuki.QrCodeGen.Test private void TestCode14() { var segments = QrSegment.MakeSegments(Text14); - var qrCode = EncodeSegments(segments, Ecc.Medium, 1, 40, 7, true); + var qrCode = EncodeSegments(segments, Ecc.Medium, 1, 40, 7); Assert.Same(Ecc.Medium, qrCode.ErrorCorrectionLevel); Assert.Equal(49, qrCode.Size); Assert.Equal(7, qrCode.Mask); diff --git a/dotnet/QrCodeGeneratorTest/QrSegmentEncodingTest.cs b/dotnet/QrCodeGeneratorTest/QrSegmentEncodingTest.cs index e659fbe..534d732 100644 --- a/dotnet/QrCodeGeneratorTest/QrSegmentEncodingTest.cs +++ b/dotnet/QrCodeGeneratorTest/QrSegmentEncodingTest.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library diff --git a/dotnet/QrCodeGeneratorTest/QrSegmentRegexTest.cs b/dotnet/QrCodeGeneratorTest/QrSegmentRegexTest.cs index 5b3f784..17a9667 100644 --- a/dotnet/QrCodeGeneratorTest/QrSegmentRegexTest.cs +++ b/dotnet/QrCodeGeneratorTest/QrSegmentRegexTest.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library diff --git a/dotnet/QrCodeGeneratorTest/SvgTest.cs b/dotnet/QrCodeGeneratorTest/SvgTest.cs index 4f49e63..be8cf89 100644 --- a/dotnet/QrCodeGeneratorTest/SvgTest.cs +++ b/dotnet/QrCodeGeneratorTest/SvgTest.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library diff --git a/dotnet/QrCodeGeneratorTest/TestHelper.cs b/dotnet/QrCodeGeneratorTest/TestHelper.cs index 6aa292a..5c08104 100644 --- a/dotnet/QrCodeGeneratorTest/TestHelper.cs +++ b/dotnet/QrCodeGeneratorTest/TestHelper.cs @@ -1,5 +1,5 @@ /* - * QR Code generator library (.NET) + * QR code generator library (.NET) * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library