From f4299689f522146ce40d9f9c95d063ca1e9423bc Mon Sep 17 00:00:00 2001 From: Manuel Bl Date: Sun, 3 Jul 2022 13:41:58 +0200 Subject: [PATCH] Code cleanup --- QrCodeGenerator/BitArrayExtensions.cs | 14 +- QrCodeGenerator/Objects.cs | 2 +- QrCodeGenerator/QrCode.cs | 226 ++++++++++--------- QrCodeGenerator/QrSegment.cs | 34 +-- QrCodeGenerator/QrSegmentAdvanced.cs | 48 ++-- QrCodeGenerator/ReedSolomonGenerator.cs | 14 +- QrCodeGeneratorTest/KanjiTest.cs | 2 + QrCodeGeneratorTest/OptimalSegmentTest.cs | 2 + QrCodeGeneratorTest/QrCodeTest.cs | 2 + QrCodeGeneratorTest/QrSegmentEncodingTest.cs | 46 ++-- QrCodeGeneratorTest/SvgTest.cs | 12 +- QrCodeGeneratorTest/TestHelper.cs | 12 +- 12 files changed, 208 insertions(+), 206 deletions(-) diff --git a/QrCodeGenerator/BitArrayExtensions.cs b/QrCodeGenerator/BitArrayExtensions.cs index 42adb22..5b7730f 100644 --- a/QrCodeGenerator/BitArrayExtensions.cs +++ b/QrCodeGenerator/BitArrayExtensions.cs @@ -53,20 +53,20 @@ public static class BitArrayExtensions /// 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) { throw new ArgumentOutOfRangeException(nameof(len), "'len' out of range"); } - if (len < 0 || len > 31 || val >> len != 0) + if (val >> len != 0) { throw new ArgumentOutOfRangeException(nameof(val), "'val' out of range"); } - int bitLength = bitArray.Length; + var bitLength = bitArray.Length; bitArray.Length = bitLength + len; - uint mask = 1U << (len - 1); - for (int i = bitLength; i < bitLength + len; i++) // Append bit by bit + var mask = 1U << (len - 1); + for (var i = bitLength; i < bitLength + len; i++) // Append bit by bit { if ((val & mask) != 0) { @@ -87,9 +87,9 @@ public static void AppendBits(this BitArray bitArray, uint val, int len) public static void AppendData(this BitArray bitArray, BitArray otherArray) { Objects.RequireNonNull(otherArray); - int bitLength = bitArray.Length; + var bitLength = bitArray.Length; bitArray.Length = bitLength + otherArray.Length; - for (int i = 0; i < otherArray.Length; i++, bitLength++) // Append bit by bit + for (var i = 0; i < otherArray.Length; i++, bitLength++) // Append bit by bit { if (otherArray[i]) { diff --git a/QrCodeGenerator/Objects.cs b/QrCodeGenerator/Objects.cs index c716303..2f78757 100644 --- a/QrCodeGenerator/Objects.cs +++ b/QrCodeGenerator/Objects.cs @@ -32,7 +32,7 @@ namespace Net.Codecrete.QrCodeGenerator /// /// Helper functions to check for valid arguments. /// - internal class Objects + internal static class Objects { /// /// Ensures that the specified argument is not null. diff --git a/QrCodeGenerator/QrCode.cs b/QrCodeGenerator/QrCode.cs index 9d9b73f..f54ef88 100644 --- a/QrCodeGenerator/QrCode.cs +++ b/QrCodeGenerator/QrCode.cs @@ -88,8 +88,8 @@ public static QrCode EncodeText(string text, Ecc ecl) { Objects.RequireNonNull(text); Objects.RequireNonNull(ecl); - List segs = QrSegment.MakeSegments(text); - return EncodeSegments(segs, ecl); + var segments = QrSegment.MakeSegments(text); + return EncodeSegments(segments, ecl); } /// @@ -110,7 +110,7 @@ public static QrCode EncodeBinary(byte[] data, Ecc ecl) { Objects.RequireNonNull(data); Objects.RequireNonNull(ecl); - QrSegment seg = QrSegment.MakeBytes(data); + var seg = QrSegment.MakeBytes(data); return EncodeSegments(new List { seg }, ecl); } @@ -136,7 +136,7 @@ public static QrCode EncodeBinary(byte[] data, Ecc ecl) /// /// 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. + /// encoding parameters. /// /// /// @@ -176,28 +176,30 @@ public static QrCode EncodeSegments(List segments, Ecc ecl, int minVe int version, dataUsedBits; for (version = minVersion; ; version++) { - int numDataBits = GetNumDataCodewords(version, ecl) * 8; // Number of data bits available + var numDataBits = GetNumDataCodewords(version, ecl) * 8; // Number of data bits available dataUsedBits = QrSegment.GetTotalBits(segments, version); if (dataUsedBits != -1 && dataUsedBits <= numDataBits) { break; // This version number is found to be suitable } - if (version >= maxVersion) - { // All versions in the range could not fit the given data - string msg = "Segment too long"; - if (dataUsedBits != -1) - { - msg = $"Data length = {dataUsedBits} bits, Max capacity = {numDataBits} bits"; - } - - throw new DataTooLongException(msg); + if (version < maxVersion) + { + continue; } + + // All versions in the range could not fit the given data + var msg = "Segment too long"; + if (dataUsedBits != -1) + { + msg = $"Data length = {dataUsedBits} bits, Max capacity = {numDataBits} bits"; + } + + throw new DataTooLongException(msg); } - Debug.Assert(dataUsedBits != -1); // Increase the error correction level while the data still fits in the current version number - foreach (Ecc newEcl in Ecc.AllValues) + foreach (var newEcl in Ecc.AllValues) { // From low to high if (boostEcl && dataUsedBits <= GetNumDataCodewords(version, newEcl) * 8) { @@ -206,8 +208,8 @@ public static QrCode EncodeSegments(List segments, Ecc ecl, int minVe } // Concatenate all segments to create the data bit string - BitArray ba = new BitArray(0); - foreach (QrSegment seg in segments) + var ba = new BitArray(0); + foreach (var seg in segments) { ba.AppendBits(seg.EncodingMode.ModeBits, 4); ba.AppendBits((uint)seg.NumChars, seg.EncodingMode.NumCharCountBits(version)); @@ -216,7 +218,7 @@ public static QrCode EncodeSegments(List segments, Ecc ecl, int minVe Debug.Assert(ba.Length == dataUsedBits); // Add terminator and pad up to a byte if applicable - int dataCapacityBits = GetNumDataCodewords(version, ecl) * 8; + var dataCapacityBits = GetNumDataCodewords(version, ecl) * 8; Debug.Assert(ba.Length <= dataCapacityBits); ba.AppendBits(0, Math.Min(4, dataCapacityBits - ba.Length)); ba.AppendBits(0, (8 - ba.Length % 8) % 8); @@ -229,8 +231,8 @@ public static QrCode EncodeSegments(List segments, Ecc ecl, int minVe } // Pack bits into bytes in big endian - byte[] dataCodewords = new byte[ba.Length / 8]; - for (int i = 0; i < ba.Length; i++) + var dataCodewords = new byte[ba.Length / 8]; + for (var i = 0; i < ba.Length; i++) { if (ba.Get(i)) { @@ -332,7 +334,7 @@ public QrCode(int version, Ecc ecl, byte[] dataCodewords, int mask = -1) // Compute ECC, draw modules, do masking DrawFunctionPatterns(); - byte[] allCodewords = AddEccAndInterleave(dataCodewords); + var allCodewords = AddEccAndInterleave(dataCodewords); DrawCodewords(allCodewords); Mask = HandleConstructorMasking(mask); _isFunction = null; @@ -396,8 +398,8 @@ public string ToSvgString(int border, string foreground, string background) throw new ArgumentOutOfRangeException(nameof(border), "Border must be non-negative"); } - int dim = Size + border * 2; - StringBuilder sb = new StringBuilder() + var dim = Size + border * 2; + var sb = new StringBuilder() .Append("\n") .Append("\n") .Append($"\n") @@ -547,7 +549,7 @@ private static void ClearRectangle(bool[,] modules, int x, int y, int width, int private void DrawFunctionPatterns() { // Draw horizontal and vertical timing patterns - for (int i = 0; i < Size; i++) + for (var i = 0; i < Size; i++) { SetFunctionModule(6, i, i % 2 == 0); SetFunctionModule(i, 6, i % 2 == 0); @@ -559,11 +561,11 @@ private void DrawFunctionPatterns() DrawFinderPattern(3, Size - 4); // Draw numerous alignment patterns - int[] alignPatPos = GetAlignmentPatternPositions(); - int numAlign = alignPatPos.Length; - for (int i = 0; i < numAlign; i++) + var alignPatPos = GetAlignmentPatternPositions(); + var numAlign = alignPatPos.Length; + for (var i = 0; i < numAlign; i++) { - for (int j = 0; j < numAlign; j++) + for (var j = 0; j < numAlign; j++) { // Don't draw on the three finder corners if (!(i == 0 && j == 0 || i == 0 && j == numAlign - 1 || i == numAlign - 1 && j == 0)) @@ -584,18 +586,18 @@ private void DrawFunctionPatterns() private void DrawFormatBits(uint mask) { // Calculate error correction code and pack bits - uint data = (ErrorCorrectionLevel.FormatBits << 3) | mask; // errCorrLvl is uint2, mask is uint3 - uint rem = data; - for (int i = 0; i < 10; i++) + var data = (ErrorCorrectionLevel.FormatBits << 3) | mask; // errCorrLvl is uint2, mask is uint3 + var rem = data; + for (var i = 0; i < 10; i++) { rem = (rem << 1) ^ ((rem >> 9) * 0x537); } - uint bits = ((data << 10) | rem) ^ 0x5412; // uint15 + var bits = ((data << 10) | rem) ^ 0x5412; // uint15 Debug.Assert(bits >> 15 == 0); // Draw first copy - for (int i = 0; i <= 5; i++) + for (var i = 0; i <= 5; i++) { SetFunctionModule(8, i, GetBit(bits, i)); } @@ -603,18 +605,18 @@ private void DrawFormatBits(uint mask) SetFunctionModule(8, 7, GetBit(bits, 6)); SetFunctionModule(8, 8, GetBit(bits, 7)); SetFunctionModule(7, 8, GetBit(bits, 8)); - for (int i = 9; i < 15; i++) + for (var i = 9; i < 15; i++) { SetFunctionModule(14 - i, 8, GetBit(bits, i)); } // Draw second copy - for (int i = 0; i < 8; i++) + for (var i = 0; i < 8; i++) { SetFunctionModule(Size - 1 - i, 8, GetBit(bits, i)); } - for (int i = 8; i < 15; i++) + for (var i = 8; i < 15; i++) { SetFunctionModule(8, Size - 15 + i, GetBit(bits, i)); } @@ -633,21 +635,21 @@ private void DrawVersion() } // Calculate error correction code and pack bits - uint rem = (uint)Version; // version is uint6, in the range [7, 40] - for (int i = 0; i < 12; i++) + var rem = (uint)Version; // version is uint6, in the range [7, 40] + for (var i = 0; i < 12; i++) { rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); } - uint bits = ((uint)Version << 12) | rem; // uint18 + var bits = ((uint)Version << 12) | rem; // uint18 Debug.Assert(bits >> 18 == 0); // Draw two copies - for (int i = 0; i < 18; i++) + for (var i = 0; i < 18; i++) { - bool bit = GetBit(bits, i); - int a = Size - 11 + i % 3; - int b = i / 3; + var bit = GetBit(bits, i); + var a = Size - 11 + i % 3; + var b = i / 3; SetFunctionModule(a, b, bit); SetFunctionModule(b, a, bit); } @@ -657,11 +659,11 @@ private void DrawVersion() // with the center module at (x, y). Modules can be out of bounds. private void DrawFinderPattern(int x, int y) { - for (int dy = -4; dy <= 4; dy++) + for (var dy = -4; dy <= 4; dy++) { - for (int dx = -4; dx <= 4; dx++) + for (var dx = -4; dx <= 4; dx++) { - int dist = Math.Max(Math.Abs(dx), Math.Abs(dy)); // Chebyshev/infinity norm + var dist = Math.Max(Math.Abs(dx), Math.Abs(dy)); // Chebyshev/infinity norm int xx = x + dx, yy = y + dy; if (0 <= xx && xx < Size && 0 <= yy && yy < Size) { @@ -676,9 +678,9 @@ private void DrawFinderPattern(int x, int y) // at (x, y). All modules must be in bounds. private void DrawAlignmentPattern(int x, int y) { - for (int dy = -2; dy <= 2; dy++) + for (var dy = -2; dy <= 2; dy++) { - for (int dx = -2; dx <= 2; dx++) + for (var dx = -2; dx <= 2; dx++) { SetFunctionModule(x + dx, y + dy, Math.Max(Math.Abs(dx), Math.Abs(dy)) != 1); } @@ -712,35 +714,37 @@ private byte[] AddEccAndInterleave(byte[] data) // Calculate parameter numbers int numBlocks = NumErrorCorrectionBlocks[ErrorCorrectionLevel.Ordinal, Version]; int blockEccLen = EccCodewordsPerBlock[ErrorCorrectionLevel.Ordinal, Version]; - int rawCodewords = GetNumRawDataModules(Version) / 8; - int numShortBlocks = numBlocks - rawCodewords % numBlocks; - int shortBlockLen = rawCodewords / numBlocks; + var rawCodewords = GetNumRawDataModules(Version) / 8; + var numShortBlocks = numBlocks - rawCodewords % numBlocks; + var shortBlockLen = rawCodewords / numBlocks; // Split data into blocks and append ECC to each block - byte[][] blocks = new byte[numBlocks][]; - ReedSolomonGenerator rs = new ReedSolomonGenerator(blockEccLen); + var blocks = new byte[numBlocks][]; + var rs = new ReedSolomonGenerator(blockEccLen); for (int i = 0, k = 0; i < numBlocks; i++) { - byte[] dat = CopyOfRange(data, k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)); + var dat = CopyOfRange(data, k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)); k += dat.Length; - byte[] block = CopyOf(dat, shortBlockLen + 1); - byte[] ecc = rs.GetRemainder(dat); + var block = CopyOf(dat, shortBlockLen + 1); + var ecc = rs.GetRemainder(dat); Array.Copy(ecc, 0, block, block.Length - blockEccLen, ecc.Length); blocks[i] = block; } // Interleave (not concatenate) the bytes from every block into a single sequence - byte[] result = new byte[rawCodewords]; + var result = new byte[rawCodewords]; for (int i = 0, k = 0; i < blocks[0].Length; i++) { - for (int j = 0; j < blocks.Length; j++) + for (var j = 0; j < blocks.Length; j++) { // Skip the padding byte in short blocks - if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) + if (i == shortBlockLen - blockEccLen && j < numShortBlocks) { - result[k] = blocks[j][i]; - k++; + continue; } + + result[k] = blocks[j][i]; + k++; } } return result; @@ -757,9 +761,9 @@ private void DrawCodewords(byte[] data) throw new ArgumentOutOfRangeException(); } - int i = 0; // Bit index into the data + var i = 0; // Bit index into the data // Do the funny zigzag scan - for (int right = Size - 1; right >= 1; right -= 2) + for (var right = Size - 1; right >= 1; right -= 2) { // Index of right column in each column pair if (right == 6) @@ -767,14 +771,14 @@ private void DrawCodewords(byte[] data) right = 5; } - for (int vert = 0; vert < Size; vert++) + for (var vert = 0; vert < Size; vert++) { // Vertical counter - for (int j = 0; j < 2; j++) + for (var j = 0; j < 2; j++) { - int x = right - j; // Actual x coordinate - bool upward = ((right + 1) & 2) == 0; - int y = upward ? Size - 1 - vert : vert; // Actual y coordinate + var x = right - j; // Actual x coordinate + var upward = ((right + 1) & 2) == 0; + var y = upward ? Size - 1 - vert : vert; // Actual y coordinate if (_isFunction[y * Size + x] || i >= data.Length * 8) { continue; @@ -803,12 +807,12 @@ private void ApplyMask(uint mask) throw new ArgumentOutOfRangeException(nameof(mask), "Mask value out of range"); } - int index = 0; - for (int y = 0; y < Size; y++) + var index = 0; + for (var y = 0; y < Size; y++) { - for (int x = 0; x < Size; x++) + for (var x = 0; x < Size; x++) { - bool invert; + var invert = false; switch (mask) { case 0: invert = (x + y) % 2 == 0; break; @@ -819,7 +823,6 @@ private void ApplyMask(uint mask) case 5: invert = x * y % 2 + x * y % 3 == 0; break; case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; - default: Debug.Assert(false); return; } _modules[index] ^= invert & !_isFunction[index]; index++; @@ -836,12 +839,12 @@ private int HandleConstructorMasking(int mask) if (mask == -1) { // Automatically choose best mask - int minPenalty = int.MaxValue; + var minPenalty = int.MaxValue; for (uint i = 0; i < 8; i++) { ApplyMask(i); DrawFormatBits(i); - int penalty = GetPenaltyScore(); + var penalty = GetPenaltyScore(); if (penalty < minPenalty) { mask = (int)i; @@ -861,17 +864,17 @@ private int HandleConstructorMasking(int mask) // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. private int GetPenaltyScore() { - int result = 0; - FinderPenalty finderPenalty = new FinderPenalty(Size); + var result = 0; + var finderPenalty = new FinderPenalty(Size); // Adjacent modules in row having same color, and finder-like patterns - int index = 0; - for (int y = 0; y < Size; y++) + var index = 0; + for (var y = 0; y < Size; y++) { - bool runColor = false; - int runX = 0; + var runColor = false; + var runX = 0; finderPenalty.Reset(); - for (int x = 0; x < Size; x++) + for (var x = 0; x < Size; x++) { if (_modules[index] == runColor) { @@ -903,13 +906,13 @@ private int GetPenaltyScore() } // Adjacent modules in column having same color, and finder-like patterns - for (int x = 0; x < Size; x++) + for (var x = 0; x < Size; x++) { index = x; - bool runColor = false; - int runY = 0; + var runColor = false; + var runY = 0; finderPenalty.Reset(); - for (int y = 0; y < Size; y++) + for (var y = 0; y < Size; y++) { if (_modules[index] == runColor) { @@ -942,11 +945,11 @@ private int GetPenaltyScore() // 2*2 blocks of modules having same color index = 0; - for (int y = 0; y < Size - 1; y++) + for (var y = 0; y < Size - 1; y++) { - for (int x = 0; x < Size - 1; x++) + for (var x = 0; x < Size - 1; x++) { - bool color = _modules[index]; + var color = _modules[index]; if (color == _modules[index + 1] && color == _modules[index + Size] && color == _modules[index + Size + 1]) @@ -961,12 +964,11 @@ private int GetPenaltyScore() } // Balance of dark and light modules - int dark = 0; + var dark = 0; index = 0; - for (int y = 0; y < Size; y++) + for (var y = 0; y < Size; y++) { - for (int x = 0; x < Size; x++) - + for (var x = 0; x < Size; x++) { if (_modules[index]) { @@ -976,9 +978,9 @@ private int GetPenaltyScore() index++; } } - int total = Size * Size; // Note that size is odd, so dark/total != 1/2 + var total = Size * Size; // Note that size is odd, so dark/total != 1/2 // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% - int k = (Math.Abs(dark * 20 - total * 10) + total - 1) / total - 1; + var k = (Math.Abs(dark * 20 - total * 10) + total - 1) / total - 1; result += k * PenaltyN4; return result; } @@ -999,7 +1001,7 @@ private int[] GetAlignmentPatternPositions() return new int[] { }; } - int numAlign = Version / 7 + 2; + var numAlign = Version / 7 + 2; int step; if (Version == 32) // Special snowflake { @@ -1010,7 +1012,7 @@ private int[] GetAlignmentPatternPositions() step = (Version * 4 + numAlign * 2 + 1) / (numAlign * 2 - 2) * 2; } - int[] result = new int[numAlign]; + var result = new int[numAlign]; result[0] = 6; for (int i = result.Length - 1, pos = Size - 7; i >= 1; i--, pos -= step) { @@ -1030,8 +1032,8 @@ private static int GetNumRawDataModules(int ver) throw new ArgumentOutOfRangeException(nameof(ver), "Version number out of range"); } - int size = ver * 4 + 17; - int result = size * size; // Number of modules in the whole QR code square + var size = ver * 4 + 17; + var 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 dark module result -= (size - 16) * 2; // Subtract the timing patterns (excluding finders) @@ -1042,7 +1044,7 @@ private static int GetNumRawDataModules(int ver) return result; } - int numAlign = ver / 7 + 2; + var 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; @@ -1069,7 +1071,7 @@ internal static int GetNumDataCodewords(int ver, Ecc ecl) // Internal the run history is organized in reverse order // (compared to Nayuki's code) to avoid the copying when // adding to the history. - internal struct FinderPenalty + private struct FinderPenalty { private int _length; private readonly short[] _runHistory; @@ -1097,11 +1099,11 @@ internal int CountPatterns() } int n = _runHistory[_length - 6]; Debug.Assert(n <= _size * 3); - bool core = n > 0 - && _runHistory[_length - 5] == n - && _runHistory[_length - 4] == n * 3 - && _runHistory[_length - 3] == n - && _runHistory[_length - 2] == n; + var core = n > 0 + && _runHistory[_length - 5] == n + && _runHistory[_length - 4] == n * 3 + && _runHistory[_length - 3] == n + && _runHistory[_length - 2] == n; return (core && _runHistory[_length - 7] >= n * 4 && _runHistory[_length - 1] >= n ? 1 : 0) + (core && _runHistory[_length - 1] >= n * 4 && _runHistory[_length - 7] >= n ? 1 : 0); } @@ -1131,7 +1133,7 @@ internal void AddHistory(int run) private static byte[] CopyOfRange(byte[] original, int from, int to) { - byte[] result = new byte[to - from]; + var result = new byte[to - from]; Array.Copy(original, from, result, 0, to - from); return result; } @@ -1139,7 +1141,7 @@ private static byte[] CopyOfRange(byte[] original, int from, int to) private static byte[] CopyOf(byte[] original, int newLength) { - byte[] result = new byte[newLength]; + var result = new byte[newLength]; Array.Copy(original, result, Math.Min(original.Length, newLength)); return result; } @@ -1182,7 +1184,7 @@ private static bool GetBit(uint x, int i) { 255, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, // Low { 255, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28 }, // Medium { 255, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, // Quartile - { 255, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, // High + { 255, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 } // High }; private static readonly byte[,] NumErrorCorrectionBlocks = { @@ -1191,7 +1193,7 @@ private static bool GetBit(uint x, int i) { 255, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25 }, // Low { 255, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49 }, // Medium { 255, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68 }, // Quartile - { 255, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81 }, // High + { 255, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81 } // High }; #endregion @@ -1229,7 +1231,7 @@ public sealed class Ecc public static readonly Ecc High = new Ecc(3, 2); - internal static Ecc[] AllValues = { Low, Medium, Quartile, High }; + internal static readonly Ecc[] AllValues = { Low, Medium, Quartile, High }; /// /// Ordinal number of error correction level (in the range 0 to 3). diff --git a/QrCodeGenerator/QrSegment.cs b/QrCodeGenerator/QrSegment.cs index 6037e25..bce1b08 100644 --- a/QrCodeGenerator/QrSegment.cs +++ b/QrCodeGenerator/QrSegment.cs @@ -77,8 +77,8 @@ public class QrSegment public static QrSegment MakeBytes(byte[] data) { Objects.RequireNonNull(data); - BitArray ba = new BitArray(0); - foreach (byte b in data) + var ba = new BitArray(0); + foreach (var b in data) { ba.AppendBits(b, 8); } @@ -103,11 +103,11 @@ public static QrSegment MakeNumeric(string digits) throw new ArgumentOutOfRangeException(nameof(digits), "String contains non-numeric characters"); } - BitArray ba = new BitArray(0); - for (int i = 0; i < digits.Length;) + var ba = new BitArray(0); + for (var i = 0; i < digits.Length;) { // Consume up to 3 digits per iteration - int n = Math.Min(digits.Length - i, 3); + var n = Math.Min(digits.Length - i, 3); ba.AppendBits(uint.Parse(digits.Substring(i, n)), n * 3 + 1); i += n; } @@ -135,12 +135,12 @@ public static QrSegment MakeAlphanumeric(string text) throw new ArgumentOutOfRangeException(nameof(text), "String contains unencodable characters in alphanumeric mode"); } - BitArray ba = new BitArray(0); + var ba = new BitArray(0); int i; for (i = 0; i <= text.Length - 2; i += 2) { // Process groups of 2 - uint temp = (uint)AlphanumericCharset.IndexOf(text[i]) * 45; + var temp = (uint)AlphanumericCharset.IndexOf(text[i]) * 45; temp += (uint)AlphanumericCharset.IndexOf(text[i + 1]); ba.AppendBits(temp, 11); } @@ -204,7 +204,7 @@ public static List MakeSegments(string text) /// assignValis outside the range [0, 106). public static QrSegment MakeEci(int assignVal) { - BitArray ba = new BitArray(0); + var ba = new BitArray(0); if (assignVal < 0) { throw new ArgumentOutOfRangeException(nameof(assignVal), "ECI assignment value out of range"); @@ -336,20 +336,20 @@ public BitArray GetData() // Calculates the number of bits needed to encode the given segments at the given version. // Returns a non-negative number if successful. Otherwise returns -1 if a segment has too // many characters to fit its length field, or the total bits exceeds int.MaxValue. - internal static int GetTotalBits(List segs, int version) + internal static int GetTotalBits(List segments, int version) { - Objects.RequireNonNull(segs); + Objects.RequireNonNull(segments); long result = 0; - foreach (QrSegment seg in segs) + foreach (var seg in segments) { Objects.RequireNonNull(seg); - int ccbits = seg.EncodingMode.NumCharCountBits(version); - if (seg.NumChars >= 1 << ccbits) + var ccBits = seg.EncodingMode.NumCharCountBits(version); + if (seg.NumChars >= 1 << ccBits) { return -1; // The segment's length doesn't fit the field's bit width } - result += 4L + ccbits + seg._data.Length; + result += 4L + ccBits + seg._data.Length; if (result > int.MaxValue) { return -1; // The sum will overflow an int type @@ -372,7 +372,7 @@ internal static int GetTotalBits(List segs, int version) // The set of all legal characters in alphanumeric mode, where // each character value maps to the index in the string. - internal static readonly string AlphanumericCharset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; + internal const string AlphanumericCharset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; #endregion @@ -437,11 +437,11 @@ public sealed class Mode /// /// /// Array of character count bit length - internal int[] NumBitsCharCount { get; } + private int[] NumBitsCharCount { get; } /// - /// Returns the bith length of the character count in the QR segment header + /// Returns the bit 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) diff --git a/QrCodeGenerator/QrSegmentAdvanced.cs b/QrCodeGenerator/QrSegmentAdvanced.cs index beeb875..d419c67 100644 --- a/QrCodeGenerator/QrSegmentAdvanced.cs +++ b/QrCodeGenerator/QrSegmentAdvanced.cs @@ -29,6 +29,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Text; using static Net.Codecrete.QrCodeGenerator.QrSegment; @@ -79,19 +80,19 @@ public static List MakeSegmentsOptimally(string text, QrCode.Ecc ecl, } // Iterate through version numbers, and make tentative segments - List segs = null; + List segments = null; var codePoints = ToCodePoints(text); - for (int version = minVersion; ; version++) + for (var version = minVersion; ; version++) { if (version == minVersion || version == 10 || version == 27) - segs = MakeSegmentsOptimally(codePoints, version); - Debug.Assert(segs != null); + segments = MakeSegmentsOptimally(codePoints, version); + Debug.Assert(segments != null); // Check if the segments fit - int dataCapacityBits = QrCode.GetNumDataCodewords(version, ecl) * 8; - int dataUsedBits = GetTotalBits(segs, version); + var dataCapacityBits = QrCode.GetNumDataCodewords(version, ecl) * 8; + var dataUsedBits = GetTotalBits(segments, version); if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) - return segs; // This version number is found to be suitable + return segments; // This version number is found to be suitable if (version < maxVersion) continue; @@ -123,7 +124,7 @@ private static Mode[] ComputeCharacterModes(int[] codePoints, int version) } Mode[] modeTypes = { Mode.Byte, Mode.Alphanumeric, Mode.Numeric, Mode.Kanji }; // Do not modify - int numModes = modeTypes.Length; + var numModes = modeTypes.Length; // Segment header sizes, measured in 1/6 bits var headCosts = new int[numModes]; @@ -145,7 +146,7 @@ private static Mode[] ComputeCharacterModes(int[] codePoints, int version) // Calculate costs using dynamic programming for (var i = 0; i < codePoints.Length; i++) { - int c = codePoints[i]; + var c = codePoints[i]; var curCosts = new int[numModes]; { // Always extend a byte mode segment @@ -180,7 +181,7 @@ private static Mode[] ComputeCharacterModes(int[] codePoints, int version) for (var k = 0; k < numModes; k++) { // From mode - int newCost = (curCosts[k] + 5) / 6 * 6 + headCosts[j]; + var newCost = (curCosts[k] + 5) / 6 * 6 + headCosts[j]; if (charModes[i, k] == null || charModes[i, j] != null && newCost >= curCosts[j]) continue; curCosts[j] = newCost; @@ -202,7 +203,7 @@ private static Mode[] ComputeCharacterModes(int[] codePoints, int version) // Get optimal mode for each code point by tracing backwards var result = new Mode[codePoints.Length]; - for (int i = result.Length - 1; i >= 0; i--) + for (var i = result.Length - 1; i >= 0; i--) { for (var j = 0; j < numModes; j++) { @@ -219,7 +220,7 @@ private static Mode[] ComputeCharacterModes(int[] codePoints, int version) // Returns a new list of segments based on the given text and modes, such that // consecutive code points in the same mode are put into the same segment. - private static List SplitIntoSegments(int[] codePoints, Mode[] charModes) + private static List SplitIntoSegments(int[] codePoints, IReadOnlyList charModes) { if (codePoints.Length == 0) throw new ArgumentOutOfRangeException(nameof(codePoints)); @@ -233,7 +234,7 @@ private static List SplitIntoSegments(int[] codePoints, Mode[] charMo if (i < codePoints.Length && charModes[i] == curMode) continue; - string s = FromCodePoints(codePoints, start, i - start); + var s = FromCodePoints(codePoints, start, i - start); if (curMode == Mode.Byte) { result.Add(MakeBytes(Encoding.UTF8.GetBytes(s))); @@ -266,9 +267,9 @@ private static List SplitIntoSegments(int[] codePoints, Mode[] charMo } - private static string FromCodePoints(int[] codepoints, int startIndex, int count) + private static string FromCodePoints(IReadOnlyList codepoints, int startIndex, int count) { - bool useBigEndian = !BitConverter.IsLittleEndian; + var useBigEndian = !BitConverter.IsLittleEndian; Encoding utf32 = new UTF32Encoding(useBigEndian, false, true); var octets = new byte[count * 4]; @@ -289,7 +290,7 @@ private static string FromCodePoints(int[] codepoints, int startIndex, int count // UTF-32 / UCS-4) representing the given UTF-16 string. private static int[] ToCodePoints(string s) { - bool useBigEndian = !BitConverter.IsLittleEndian; + var useBigEndian = !BitConverter.IsLittleEndian; Encoding utf32 = new UTF32Encoding(useBigEndian, false, true); var octets = utf32.GetBytes(s); @@ -330,7 +331,7 @@ private static int CountUtf8Bytes(int cp) /// /// /// The text to encoding, containing only characters allowed by the Kanji encoding. - /// The created segment respresenting the specified text. + /// The created segment representing the specified text. /// is null. /// contains non-encodable characters. /// @@ -339,9 +340,8 @@ public static QrSegment MakeKanji(string text) Objects.RequireNonNull(text); var ba = new BitArray(0); - foreach (char t in text) + foreach (var val in text.Select(t => UnicodeToQrKanji[t])) { - ushort val = UnicodeToQrKanji[t]; if (val == 0xffff) { throw new ArgumentOutOfRangeException(nameof(text), "String contains non-kanji-mode characters"); @@ -369,11 +369,7 @@ public static QrSegment MakeKanji(string text) public static bool IsEncodableAsKanji(string text) { Objects.RequireNonNull(text); - foreach (char t in text) - if (!IsKanji(t)) - return false; - - return true; + return text.All(t => IsKanji(t)); } @@ -505,10 +501,10 @@ static QrSegmentAdvanced() for (var i = 0; i < UnicodeToQrKanji.Length; i++) UnicodeToQrKanji[i] = 0xffff; - byte[] bytes = Convert.FromBase64String(PackedQrKanjiToUnicode); + var bytes = Convert.FromBase64String(PackedQrKanjiToUnicode); for (var i = 0; i < bytes.Length; i += 2) { - int c = (bytes[i] << 8) | bytes[i + 1]; + var c = (bytes[i] << 8) | bytes[i + 1]; if (c == 0xFFFF) continue; Debug.Assert(UnicodeToQrKanji[c] == 0xffff); diff --git a/QrCodeGenerator/ReedSolomonGenerator.cs b/QrCodeGenerator/ReedSolomonGenerator.cs index 08089f4..487adec 100644 --- a/QrCodeGenerator/ReedSolomonGenerator.cs +++ b/QrCodeGenerator/ReedSolomonGenerator.cs @@ -73,10 +73,10 @@ internal ReedSolomonGenerator(int degree) // drop the highest term, and store the rest of the coefficients in order of descending powers. // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). uint root = 1; - for (int i = 0; i < degree; i++) + for (var i = 0; i < degree; i++) { // Multiply the current product by (x - r^i) - for (int j = 0; j < _coefficients.Length; j++) + for (var j = 0; j < _coefficients.Length; j++) { _coefficients[j] = Multiply(_coefficients[j], root); if (j + 1 < _coefficients.Length) @@ -108,13 +108,13 @@ internal byte[] GetRemainder(byte[] data) Objects.RequireNonNull(data); // Compute the remainder by performing polynomial division - byte[] result = new byte[_coefficients.Length]; - foreach (byte b in data) + var result = new byte[_coefficients.Length]; + foreach (var b in data) { - uint factor = (uint)(b ^ result[0]); + var factor = (uint)(b ^ result[0]); Array.Copy(result, 1, result, 0, result.Length - 1); result[result.Length - 1] = 0; - for (int i = 0; i < result.Length; i++) + for (var i = 0; i < result.Length; i++) { result[i] ^= Multiply(_coefficients[i], factor); } @@ -134,7 +134,7 @@ private static byte Multiply(uint x, uint y) Debug.Assert(x >> 8 == 0 && y >> 8 == 0); // Russian peasant multiplication uint z = 0; - for (int i = 7; i >= 0; i--) + for (var i = 7; i >= 0; i--) { z = (z << 1) ^ ((z >> 7) * 0x11D); z ^= ((y >> i) & 1) * x; diff --git a/QrCodeGeneratorTest/KanjiTest.cs b/QrCodeGeneratorTest/KanjiTest.cs index 5c3d6b4..806e623 100644 --- a/QrCodeGeneratorTest/KanjiTest.cs +++ b/QrCodeGeneratorTest/KanjiTest.cs @@ -28,6 +28,8 @@ using System.Collections.Generic; using Xunit; +// ReSharper disable StringLiteralTypo + namespace Net.Codecrete.QrCodeGenerator.Test { public class KanjiTest diff --git a/QrCodeGeneratorTest/OptimalSegmentTest.cs b/QrCodeGeneratorTest/OptimalSegmentTest.cs index d972674..c7981ab 100644 --- a/QrCodeGeneratorTest/OptimalSegmentTest.cs +++ b/QrCodeGeneratorTest/OptimalSegmentTest.cs @@ -27,6 +27,8 @@ using Xunit; +// ReSharper disable StringLiteralTypo + namespace Net.Codecrete.QrCodeGenerator.Test { public class OptimalSegmentTest diff --git a/QrCodeGeneratorTest/QrCodeTest.cs b/QrCodeGeneratorTest/QrCodeTest.cs index eba9af2..5792a81 100644 --- a/QrCodeGeneratorTest/QrCodeTest.cs +++ b/QrCodeGeneratorTest/QrCodeTest.cs @@ -29,6 +29,8 @@ using Xunit; using static Net.Codecrete.QrCodeGenerator.QrCode; +// ReSharper disable StringLiteralTypo + namespace Net.Codecrete.QrCodeGenerator.Test { public class QrCodeTest diff --git a/QrCodeGeneratorTest/QrSegmentEncodingTest.cs b/QrCodeGeneratorTest/QrSegmentEncodingTest.cs index c0997e3..1f16e4a 100644 --- a/QrCodeGeneratorTest/QrSegmentEncodingTest.cs +++ b/QrCodeGeneratorTest/QrSegmentEncodingTest.cs @@ -27,7 +27,6 @@ using System; using System.Collections; -using System.Collections.Generic; using System.Text; using Xunit; @@ -35,16 +34,15 @@ namespace Net.Codecrete.QrCodeGenerator.Test { public class QrSegmentEncodingTest { + private const string TextNumeric = "83930"; - private static readonly string TextNumeric = "83930"; - - private static readonly int BitLengthNumeric = 17; + private const int BitLengthNumeric = 17; private static readonly byte[] BitsNumeric = { 139, 243, 0 }; - private static readonly string TextAlphanumeric = "$%*+-./ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private const string TextAlphanumeric = "$%*+-./ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - private static readonly int BitLengthAlphanumeric = 242; + private const int BitLengthAlphanumeric = 242; private static readonly byte[] BitsAlphanumeric = { 43, 63,240, 245, 223, 12, 64, 232, @@ -53,20 +51,20 @@ public class QrSegmentEncodingTest 109, 33, 107, 218, 193, 225, 2 }; - private static readonly string TextUtf8 = "😐ö€"; + private const string TextUtf8 = "😐ö€"; - private static readonly int BitLengthUtf8 = 72; + private const int BitLengthUtf8 = 72; private static readonly byte[] BitsUtf8 = { 15, 249, 25, 9, 195, 109, 71, 65, 53 }; [Fact] public void NumericEncoding() { - QrSegment segment = QrSegment.MakeNumeric(TextNumeric); + var segment = QrSegment.MakeNumeric(TextNumeric); Assert.Equal(segment.EncodingMode, QrSegment.Mode.Numeric); Assert.Equal(TextNumeric.Length, segment.NumChars); - BitArray data = segment.GetData(); + var data = segment.GetData(); Assert.Equal(BitLengthNumeric, data.Length); Assert.Equal(BitsNumeric, BitArrayToByteArray(data)); @@ -81,11 +79,11 @@ public void RejectNonNumeric() [Fact] public void AlphanumericEncoding() { - QrSegment segment = QrSegment.MakeAlphanumeric(TextAlphanumeric); + var segment = QrSegment.MakeAlphanumeric(TextAlphanumeric); Assert.Equal(segment.EncodingMode, QrSegment.Mode.Alphanumeric); Assert.Equal(TextAlphanumeric.Length, segment.NumChars); - BitArray data = segment.GetData(); + var data = segment.GetData(); Assert.Equal(BitLengthAlphanumeric, data.Length); Assert.Equal(BitsAlphanumeric, BitArrayToByteArray(data)); @@ -100,14 +98,14 @@ public void RejectNonAlphanumeric() [Fact] public void AutoNumericEncoding() { - List segments = QrSegment.MakeSegments(TextNumeric); + var segments = QrSegment.MakeSegments(TextNumeric); Assert.Single(segments); - QrSegment segment = segments[0]; + var segment = segments[0]; Assert.Equal(segment.EncodingMode, QrSegment.Mode.Numeric); Assert.Equal(TextNumeric.Length, segment.NumChars); - BitArray data = segment.GetData(); + var data = segment.GetData(); Assert.Equal(BitLengthNumeric, data.Length); Assert.Equal(BitsNumeric, BitArrayToByteArray(data)); @@ -116,14 +114,14 @@ public void AutoNumericEncoding() [Fact] public void AutoAlphanumericEncoding() { - List segments = QrSegment.MakeSegments(TextAlphanumeric); + var segments = QrSegment.MakeSegments(TextAlphanumeric); Assert.Single(segments); - QrSegment segment = segments[0]; + var segment = segments[0]; Assert.Equal(segment.EncodingMode, QrSegment.Mode.Alphanumeric); Assert.Equal(TextAlphanumeric.Length, segment.NumChars); - BitArray data = segment.GetData(); + var data = segment.GetData(); Assert.Equal(BitLengthAlphanumeric, data.Length); Assert.Equal(BitsAlphanumeric, BitArrayToByteArray(data)); @@ -132,13 +130,13 @@ public void AutoAlphanumericEncoding() [Fact] public void Utf8Encoding() { - List segments = QrSegment.MakeSegments(TextUtf8); + var segments = QrSegment.MakeSegments(TextUtf8); Assert.Single(segments); - QrSegment segment = segments[0]; + var segment = segments[0]; Assert.Equal(segment.EncodingMode, QrSegment.Mode.Byte); Assert.Equal(Encoding.UTF8.GetBytes(TextUtf8).Length, segment.NumChars); - BitArray data = segment.GetData(); + var data = segment.GetData(); Assert.Equal(BitLengthUtf8, data.Length); Assert.Equal(BitsUtf8, BitArrayToByteArray(data)); @@ -147,14 +145,14 @@ public void Utf8Encoding() [Fact] public void EmptyTest() { - List segments = QrSegment.MakeSegments(""); + var segments = QrSegment.MakeSegments(""); Assert.Empty(segments); } private static byte[] BitArrayToByteArray(BitArray buffer) { - int len = buffer.Length; - byte[] result = new byte[(len + 7) / 8]; + var len = buffer.Length; + var result = new byte[(len + 7) / 8]; buffer.CopyTo(result, 0); return result; } diff --git a/QrCodeGeneratorTest/SvgTest.cs b/QrCodeGeneratorTest/SvgTest.cs index ba14298..7d2eb88 100644 --- a/QrCodeGeneratorTest/SvgTest.cs +++ b/QrCodeGeneratorTest/SvgTest.cs @@ -34,13 +34,13 @@ namespace Net.Codecrete.QrCodeGenerator.Test { public class SvgTest { - private static readonly string CODE_TEXT = "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga."; + private const string CodeText = "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga."; [Fact] public void SvgImage() { - var qrCode = EncodeText(CODE_TEXT, Ecc.Medium); - string svg = qrCode.ToSvgString(0); + var qrCode = EncodeText(CodeText, Ecc.Medium); + var svg = qrCode.ToSvgString(0); Assert.StartsWith("