using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Codecrete")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) Manuel Bleichenbacher and Project Nayuki (MIT License)")]
[assembly: AssemblyDescription("QR Code Generator for .NET – simple, compact and with many examples.\r\n\r\nCore features:\r\n- Supports encoding all 40 versions (sizes) and all 4 error correction levels, as per the QR Code Model 2 standard\r\n- Output formats: Raw modules/pixels of the QR symbol, SVG, XAML path, PNG and BMP files. For other raster bitmap formats, see project home page.\r\n- Encodes numeric and special-alphanumeric text in less space than general text\r\n- Open source code under the permissive MIT License\r\n- Built for .NET Standard 2.0 and therefore runs on most modern .NET platforms (.NET Core, .NET Framework, Mono etc.).\r\n- Example code for WinForms, WPF, ASP.NET, ImageSharp, SkiaSharp and many more\r\n\r\nManual parameters:\r\n- You can specify the minimum and maximum version number allowed, and the library will automatically choose the smallest version in the range that fits the data.\r\n- You can specify the mask pattern manually, otherwise library will automatically evaluate all 8 masks and select the optimal one.\r\n- You can specify an error correction level, or optionally allow the library to boost it if it doesn't increase the version number.\r\n- You can create a list of data segments manually and add ECI segments.\r\n\r\nOptional advanced features:\r\n- Long text can be split into multiple linked QR codes (aka Structured Append)\r\n- Encodes Japanese Unicode text in Kanji mode to save a lot of space compared to UTF-8 bytes\r\n- Computes optimal segment mode switching for text with mixed numeric/alphanumeric/general/kanji parts\r\n")]
[assembly: AssemblyFileVersion("2.0.1.0")]
[assembly: AssemblyInformationalVersion("2.1.0+d75ad20b2f2c04a41120c3e7c7326842fc837fcc")]
[assembly: AssemblyProduct("QR Code Generator for .NET")]
[assembly: AssemblyTitle("QrCodeGenerator")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/manuelbl/QrCodeGenerator")]
[assembly: AssemblyVersion("1.6.0.0")]
namespace Net.Codecrete.QrCodeGenerator;
public static class BitArrayExtensions
{
public static void AppendBits(this BitArray bitArray, uint val, int len)
{
if (len < 0 || len > 31)
{
throw new ArgumentOutOfRangeException("len", "'len' out of range");
}
if (val >> len != 0)
{
throw new ArgumentOutOfRangeException("val", "'val' out of range");
}
int length = bitArray.Length;
bitArray.Length = length + len;
uint num = (uint)(1 << len - 1);
for (int i = length; i < length + len; i++)
{
if ((val & num) != 0)
{
bitArray.Set(i, value: true);
}
num >>= 1;
}
}
public static void AppendData(this BitArray bitArray, BitArray otherArray)
{
Objects.RequireNonNull(otherArray);
int num = bitArray.Length;
bitArray.Length = num + otherArray.Length;
int num2 = 0;
while (num2 < otherArray.Length)
{
if (otherArray[num2])
{
bitArray.Set(num, value: true);
}
num2++;
num++;
}
}
public static uint ExtractBits(this BitArray bitArray, int index, int len)
{
if (len < 0 || len > 31)
{
throw new ArgumentOutOfRangeException("len", "'len' out of range");
}
if (index < 0 || index + len > bitArray.Length)
{
throw new ArgumentOutOfRangeException("index", "'index' out of range");
}
uint num = 0u;
for (int i = 0; i < len; i++)
{
num <<= 1;
if (bitArray.Get(index + i))
{
num |= 1u;
}
}
return num;
}
}
public class DataTooLongException : ArgumentException
{
public DataTooLongException(string message)
: base(message)
{
}
}
internal class Graphics
{
private readonly int _size;
private readonly bool[,] _modules;
internal Graphics(int size, bool[,] modules)
{
_size = size;
_modules = modules;
}
internal string ToSvgString(int border, string foreground, string background)
{
if (border < 0)
{
throw new ArgumentOutOfRangeException("border", "Border must be non-negative");
}
int num = _size + border * 2;
StringBuilder stringBuilder = new StringBuilder().Append("\n").Append("\n").Append($"\n").ToString();
}
internal string ToGraphicsPath(int border)
{
if (border < 0)
{
throw new ArgumentOutOfRangeException("border", "Border must be non-negative");
}
bool[,] modules = CopyModules();
StringBuilder stringBuilder = new StringBuilder();
CreatePath(stringBuilder, modules, border);
return stringBuilder.ToString();
}
internal byte[] ToBmpBitmap(int border, int scale, int foreground, int background)
{
if (scale < 1)
{
throw new ArgumentOutOfRangeException("scale", scale, "Scale must be greater than 0.");
}
if (border < 0)
{
throw new ArgumentOutOfRangeException("border", border, "Border must be non-negative.");
}
int num = (_size + 2 * border) * scale;
if (num > 32767)
{
throw new ArgumentOutOfRangeException("scale", "Scale or border too large.");
}
int num2 = (num - 1 >> 3) + 1;
int num3 = (num2 + 3) & -4;
int num4 = 62 + num * num3;
byte[] array = new byte[num4];
array[0] = 66;
array[1] = 77;
array[2] = (byte)num4;
array[3] = (byte)(num4 >> 8);
array[4] = (byte)(num4 >> 16);
array[5] = (byte)(num4 >> 24);
array[10] = 62;
array[14] = 40;
array[18] = (byte)num;
array[19] = (byte)(num >> 8);
array[20] = (byte)(num >> 16);
array[21] = (byte)(num >> 24);
array[22] = array[18];
array[23] = array[19];
array[24] = array[20];
array[25] = array[21];
array[26] = 1;
array[28] = 1;
array[38] = 196;
array[39] = 14;
array[42] = array[38];
array[43] = array[39];
array[54] = (byte)foreground;
array[55] = (byte)(foreground >> 8);
array[56] = (byte)(foreground >> 16);
array[58] = (byte)background;
array[59] = (byte)(background >> 8);
array[60] = (byte)(background >> 16);
int num5 = border * scale;
if (border > 0)
{
int num6 = _size * scale;
for (int i = 0; i < num3; i++)
{
byte b = byte.MaxValue;
if (i == num2 - 1)
{
b = (byte)(255 << (num2 << 3) - num);
}
else if (i >= num2)
{
b = 0;
}
for (int j = 0; j < num5; j++)
{
array[62 + i + j * num3] = b;
array[62 + i + (j + num6 + num5) * num3] = b;
}
}
}
for (int j = 0; j < _size; j++)
{
int num7 = j * scale + num5;
for (int i = 0; i < num3; i++)
{
byte b = 0;
for (int k = 0; k < 8; k++)
{
int num8 = ((i << 3) + k) / scale;
if (num8 < num)
{
b = ((num8 >= border && num8 < _size + border) ? ((byte)(b | (byte)((!_modules[_size - j - 1, num8 - border]) ? ((uint)(1 << 7 - k)) : 0u))) : ((byte)(b | (byte)(1 << 7 - k))));
}
}
array[62 + i + num7 * num3] = b;
}
for (int i = 1; i <= scale - 1; i++)
{
for (int k = 0; k < num3; k++)
{
array[62 + k + (num7 + i) * num3] = array[62 + k + num7 * num3];
}
}
}
return array;
}
private static void CreatePath(StringBuilder path, bool[,] modules, int border)
{
int length = modules.GetLength(0);
for (int i = 0; i < length; i++)
{
for (int j = 0; j < length; j++)
{
if (modules[i, j])
{
DrawLargestRectangle(path, modules, j, i, border);
}
}
}
}
private static void DrawLargestRectangle(StringBuilder path, bool[,] modules, int x, int y, int border)
{
int length = modules.GetLength(0);
int num = 1;
int num2 = 1;
int num3 = 1;
int num4 = length;
for (int i = y; i < length && modules[i, x]; i++)
{
int j;
for (j = 0; x + j < num4 && modules[i, x + j]; j++)
{
}
int num5 = j * (i - y + 1);
if (num5 > num3)
{
num3 = num5;
num = j;
num2 = i - y + 1;
}
num4 = x + j;
}
if (x != 0 || y != 0)
{
path.Append(' ');
}
FormattableString formattableString = $"M{x + border},{y + border}h{num}v{num2}h{-num}z";
path.Append(formattableString.ToString(CultureInfo.InvariantCulture));
ClearRectangle(modules, x, y, num, num2);
}
private static void ClearRectangle(bool[,] modules, int x, int y, int width, int height)
{
for (int i = y; i < y + height; i++)
{
for (int j = x; j < x + width; j++)
{
modules[i, j] = false;
}
}
}
private bool[,] CopyModules()
{
bool[,] array = new bool[_size, _size];
for (int i = 0; i < _size; i++)
{
for (int j = 0; j < _size; j++)
{
array[i, j] = _modules[i, j];
}
}
return array;
}
}
internal static class Objects
{
internal static T RequireNonNull(T arg)
{
if (arg == null)
{
throw new ArgumentNullException();
}
return arg;
}
}
internal sealed class PngBuilder
{
private static readonly byte[] Signature = new byte[8] { 137, 80, 78, 71, 13, 10, 26, 10 };
private static readonly uint[] CrcTable = new uint[256]
{
0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u, 249268274u, 2044508324u,
3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u, 498536548u, 1789927666u, 4089016648u, 2227061214u,
450548861u, 1843258603u, 4107580753u, 2211677639u, 325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u,
4195302755u, 2366115317u, 997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u,
901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u, 651767980u, 1373503546u,
3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u, 671266974u, 1594198024u, 3322730930u, 2970347812u,
795835527u, 1483230225u, 3244367275u, 3060149565u, 1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u,
2680153253u, 3904427059u, 2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u,
1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u, 1706088902u, 314042704u,
2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u, 1303535960u, 984961486u, 2747007092u, 3569037538u,
1256170817u, 1037604311u, 2765210733u, 3554079995u, 1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u,
2852801631u, 3708648649u, 1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u,
1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u, 3988292384u, 2596254646u,
62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u, 3814918930u, 2489596804u, 225274430u, 2053790376u,
3826175755u, 2466906013u, 167816743u, 2097651377u, 4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u,
426522225u, 1852507879u, 4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u,
3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u, 3624741850u, 2936675148u,
906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u, 3412177804u, 3160834842u, 628085408u, 1382605366u,
3423369109u, 3138078467u, 570562233u, 1426400815u, 3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u,
752459403u, 1541320221u, 2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u,
2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u, 2262029012u, 4057260610u,
1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u, 2282248934u, 4279200368u, 1711684554u, 285281116u,
2405801727u, 4167216745u, 1634467795u, 376229701u, 2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u,
1231636301u, 1047427035u, 2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u,
3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u, 3009837614u, 3294710456u,
1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u
};
private static readonly byte[] IHDR = new byte[4] { 73, 72, 68, 82 };
private static readonly byte[] PLTE = new byte[4] { 80, 76, 84, 69 };
private static readonly byte[] IDAT = new byte[4] { 73, 68, 65, 84 };
private static readonly byte[] IEND = new byte[4] { 73, 69, 78, 68 };
private readonly MemoryStream stream = new MemoryStream();
internal static byte[] ToImage(QrCode qrCode, int scale, int border, int foreground, int background)
{
int num = (qrCode.Size + border * 2) * scale;
PngBuilder pngBuilder = new PngBuilder();
pngBuilder.WriteHeader(num, num, 1, 3);
pngBuilder.WritePalette(new int[2] { background, foreground });
pngBuilder.WriteData(CreateBitmap(qrCode, border, scale));
pngBuilder.WriteEnd();
return pngBuilder.GetBytes();
}
private static byte[] CreateBitmap(QrCode qrCode, int border, int scale)
{
int size = qrCode.Size;
int num = (size + border * 2) * scale;
int num2 = (num + 7) / 8 + 1;
byte[] array = new byte[num2 * num];
for (int i = 0; i < size; i++)
{
int num3 = (border + i) * scale * num2;
for (int j = 0; j < size; j++)
{
if (qrCode.GetModule(j, i))
{
int k = (border + j) * scale;
for (int num4 = k + scale; k < num4; k++)
{
int num5 = num3 + k / 8 + 1;
array[num5] |= (byte)(128 >>> k % 8);
}
}
}
for (int l = 1; l < scale; l++)
{
Array.Copy(array, num3, array, num3 + l * num2, num2);
}
}
return array;
}
private byte[] GetBytes()
{
byte[] array = stream.ToArray();
SetCRC(array);
return array;
}
private void WriteHeader(int width, int height, byte bitDepth, byte colorType)
{
stream.Write(Signature, 0, Signature.Length);
WriteChunkStart(IHDR, 13);
WriteIntBigEndian((uint)width);
WriteIntBigEndian((uint)height);
stream.WriteByte(bitDepth);
stream.WriteByte(colorType);
stream.WriteByte(0);
stream.WriteByte(0);
stream.WriteByte(0);
WriteChunkEnd();
}
private void WritePalette(int[] palette)
{
WriteChunkStart(PLTE, palette.Length * 3);
foreach (int num in palette)
{
stream.WriteByte((byte)((uint)(num >> 16) & 0xFFu));
stream.WriteByte((byte)((uint)(num >> 8) & 0xFFu));
stream.WriteByte((byte)((uint)num & 0xFFu));
}
WriteChunkEnd();
}
private void WriteData(byte[] data)
{
byte[] array = Deflate(data);
WriteChunkStart(IDAT, array.Length + 6);
stream.WriteByte(120);
stream.WriteByte(156);
stream.Write(array, 0, array.Length);
uint value = CalcAdler32(data, 0, data.Length);
WriteIntBigEndian(value);
WriteChunkEnd();
}
private void WriteEnd()
{
WriteChunkStart(IEND, 0);
WriteChunkEnd();
}
private static void SetCRC(byte[] bytes)
{
int num = Signature.Length;
while (num < bytes.Length)
{
int num2 = (bytes[num] << 24) | (bytes[num + 1] << 16) | (bytes[num + 2] << 8) | bytes[num + 3];
uint num3 = CalcCrc32(bytes, num + 4, num2 + 4);
int num4 = num + 8 + num2;
bytes[num4] = (byte)(num3 >> 24);
bytes[num4 + 1] = (byte)(num3 >> 16);
bytes[num4 + 2] = (byte)(num3 >> 8);
bytes[num4 + 3] = (byte)num3;
num = num4 + 4;
}
}
private void WriteChunkStart(byte[] type, int length)
{
WriteIntBigEndian((uint)length);
stream.Write(type, 0, 4);
}
private void WriteChunkEnd()
{
stream.SetLength(stream.Length + 4);
stream.Position += 4L;
}
private void WriteIntBigEndian(uint value)
{
stream.WriteByte((byte)(value >> 24));
stream.WriteByte((byte)(value >> 16));
stream.WriteByte((byte)(value >> 8));
stream.WriteByte((byte)value);
}
private static byte[] Deflate(byte[] data)
{
MemoryStream memoryStream = new MemoryStream();
using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionLevel.Optimal))
{
deflateStream.Write(data, 0, data.Length);
}
return memoryStream.ToArray();
}
private static uint CalcAdler32(byte[] data, int index, int length)
{
uint num = 1u;
uint num2 = 0u;
int num3 = index + length;
for (int i = index; i < num3; i++)
{
num = (num + data[i]) % 65521;
num2 = (num2 + num) % 65521;
}
return (num2 << 16) + num;
}
private static uint CalcCrc32(byte[] data, int index, int length)
{
uint num = uint.MaxValue;
int num2 = index + length;
for (int i = index; i < num2; i++)
{
num = CrcTable[(num ^ data[i]) & 0xFF] ^ (num >> 8);
}
return num ^ 0xFFFFFFFFu;
}
}
public class QrCode
{
private struct FinderPenalty
{
private readonly short[] _runHistory;
private readonly int _size;
public FinderPenalty(int size)
{
_size = size;
_runHistory = new short[7];
}
internal int CountPatterns()
{
int num = _runHistory[1];
bool flag = num > 0 && _runHistory[2] == num && _runHistory[3] == num * 3 && _runHistory[4] == num && _runHistory[5] == num;
return ((flag && _runHistory[0] >= num * 4 && _runHistory[6] >= num) ? 1 : 0) + ((flag && _runHistory[6] >= num * 4 && _runHistory[0] >= num) ? 1 : 0);
}
internal int TerminateAndCount(bool currentRunColor, int currentRunLength)
{
if (currentRunColor)
{
AddHistory(currentRunLength);
currentRunLength = 0;
}
currentRunLength += _size;
AddHistory(currentRunLength);
return CountPatterns();
}
internal void AddHistory(int currentRunLength)
{
if (_runHistory[0] == 0)
{
currentRunLength += _size;
}
Array.Copy(_runHistory, 0, _runHistory, 1, 6);
_runHistory[0] = (short)currentRunLength;
}
}
public sealed class Ecc
{
public static readonly Ecc Low = new Ecc(0, 1u);
public static readonly Ecc Medium = new Ecc(1, 0u);
public static readonly Ecc Quartile = new Ecc(2, 3u);
public static readonly Ecc High = new Ecc(3, 2u);
internal static readonly Ecc[] AllValues = new Ecc[4] { Low, Medium, Quartile, High };
public int Ordinal { get; }
internal uint FormatBits { get; }
private Ecc(int ordinal, uint fb)
{
Ordinal = ordinal;
FormatBits = fb;
}
}
private readonly bool[,] _modules;
private readonly bool[,] _isFunction;
public const int MinVersion = 1;
public const int MaxVersion = 40;
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 = new byte[4, 41]
{
{
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
},
{
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
},
{
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
},
{
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
}
};
private static readonly byte[,] NumErrorCorrectionBlocks = new byte[4, 41]
{
{
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
},
{
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
},
{
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
},
{
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
}
};
public int Version { get; }
public int Size { get; }
public Ecc ErrorCorrectionLevel { get; }
public int Mask { get; }
public static QrCode EncodeText(string text, Ecc ecl)
{
Objects.RequireNonNull(text);
Objects.RequireNonNull(ecl);
return EncodeSegments(QrSegment.MakeSegments(text), ecl);
}
public static List EncodeTextInMultipleCodes(string text, Ecc ecl, int version = 29, bool boostEcl = true)
{
Objects.RequireNonNull(text);
Objects.RequireNonNull(ecl);
try
{
QrCode item = EncodeSegments(QrSegmentAdvanced.MakeSegmentsOptimally(text, ecl, version, version), ecl, version, version, -1, boostEcl);
return new List { item };
}
catch (DataTooLongException)
{
}
return (from segmentList in QrSegmentAdvanced.MakeSegmentsForMultipleCodes(text, ecl, version)
select EncodeSegments(segmentList, ecl, version, version, -1, boostEcl)).ToList();
}
public static QrCode EncodeBinary(byte[] data, Ecc ecl)
{
Objects.RequireNonNull(data);
Objects.RequireNonNull(ecl);
QrSegment item = QrSegment.MakeBytes(data);
return EncodeSegments(new List { item }, ecl);
}
public static QrCode EncodeSegments(List segments, Ecc ecl, int minVersion = 1, int maxVersion = 40, int mask = -1, bool boostEcl = true)
{
Objects.RequireNonNull(segments);
Objects.RequireNonNull(ecl);
if (minVersion < 1 || minVersion > maxVersion)
{
throw new ArgumentOutOfRangeException("minVersion", "Invalid value");
}
if (maxVersion > 40)
{
throw new ArgumentOutOfRangeException("maxVersion", "Invalid value");
}
if (mask < -1 || mask > 7)
{
throw new ArgumentOutOfRangeException("mask", "Invalid value");
}
int num = minVersion;
int totalBits;
while (true)
{
int num2 = GetNumDataCodewords(num, ecl) * 8;
totalBits = QrSegment.GetTotalBits(segments, num);
if (totalBits != -1 && totalBits <= num2)
{
break;
}
if (num >= maxVersion)
{
string message = "Segment too long";
if (totalBits != -1)
{
message = $"Data length = {totalBits} bits, Max capacity = {num2} bits";
}
throw new DataTooLongException(message);
}
num++;
}
Ecc[] allValues = Ecc.AllValues;
foreach (Ecc ecc in allValues)
{
if (boostEcl && totalBits <= GetNumDataCodewords(num, ecc) * 8)
{
ecl = ecc;
}
}
BitArray bitArray = new BitArray(0);
foreach (QrSegment segment in segments)
{
bitArray.AppendBits(segment.EncodingMode.ModeBits, 4);
bitArray.AppendBits((uint)segment.NumChars, segment.EncodingMode.NumCharCountBits(num));
bitArray.AppendData(segment.GetData());
}
int num3 = GetNumDataCodewords(num, ecl) * 8;
bitArray.AppendBits(0u, Math.Min(4, num3 - bitArray.Length));
bitArray.AppendBits(0u, (8 - bitArray.Length % 8) % 8);
uint num4 = 236u;
while (bitArray.Length < num3)
{
bitArray.AppendBits(num4, 8);
num4 ^= 0xFDu;
}
byte[] array = new byte[bitArray.Length / 8];
for (int j = 0; j < bitArray.Length; j++)
{
if (bitArray.Get(j))
{
array[j >> 3] |= (byte)(1 << 7 - (j & 7));
}
}
return new QrCode(num, ecl, array, mask);
}
public QrCode(int version, Ecc ecl, byte[] dataCodewords, int mask = -1)
{
if (version < 1 || version > 40)
{
throw new ArgumentOutOfRangeException("version", "Version value out of range");
}
if (mask < -1 || mask > 7)
{
throw new ArgumentOutOfRangeException("mask", "Mask value out of range");
}
Version = version;
Size = version * 4 + 17;
Objects.RequireNonNull(ecl);
ErrorCorrectionLevel = ecl;
Objects.RequireNonNull(dataCodewords);
_modules = new bool[Size, Size];
_isFunction = new bool[Size, Size];
DrawFunctionPatterns();
byte[] data = AddEccAndInterleave(dataCodewords);
DrawCodewords(data);
if (mask == -1)
{
int num = int.MaxValue;
for (uint num2 = 0u; num2 < 8; num2++)
{
ApplyMask(num2);
DrawFormatBits(num2);
int penaltyScore = GetPenaltyScore();
if (penaltyScore < num)
{
mask = (int)num2;
num = penaltyScore;
}
ApplyMask(num2);
}
}
Mask = mask;
ApplyMask((uint)mask);
DrawFormatBits((uint)mask);
_isFunction = null;
}
public bool GetModule(int x, int y)
{
if (0 <= x && x < Size && 0 <= y && y < Size)
{
return _modules[y, x];
}
return false;
}
public string ToSvgString(int border)
{
return ToSvgString(border, "#000000", "#ffffff");
}
public string ToSvgString(int border, string foreground, string background)
{
return AsGraphics().ToSvgString(border, foreground, background);
}
public string ToGraphicsPath(int border = 0)
{
return AsGraphics().ToGraphicsPath(border);
}
public byte[] ToBmpBitmap(int border, int scale, int foreground, int background)
{
return AsGraphics().ToBmpBitmap(border, scale, foreground, background);
}
public byte[] ToBmpBitmap(int border = 0, int scale = 1)
{
return ToBmpBitmap(border, scale, 0, 16777215);
}
public byte[] ToPngBitmap(int border, int scale, int foreground, int background)
{
return PngBuilder.ToImage(this, scale, border, foreground, background);
}
public byte[] ToPngBitmap(int border = 0, int scale = 1)
{
return PngBuilder.ToImage(this, scale, border, 0, 16777215);
}
public int RgbColor(byte red, byte green, byte blue)
{
return (red << 16) | (green << 8) | blue;
}
private void DrawFunctionPatterns()
{
for (int i = 0; i < Size; i++)
{
SetFunctionModule(6, i, i % 2 == 0);
SetFunctionModule(i, 6, i % 2 == 0);
}
DrawFinderPattern(3, 3);
DrawFinderPattern(Size - 4, 3);
DrawFinderPattern(3, Size - 4);
int[] alignmentPatternPositions = GetAlignmentPatternPositions();
int num = alignmentPatternPositions.Length;
for (int j = 0; j < num; j++)
{
for (int k = 0; k < num; k++)
{
if ((j != 0 || k != 0) && (j != 0 || k != num - 1) && (j != num - 1 || k != 0))
{
DrawAlignmentPattern(alignmentPatternPositions[j], alignmentPatternPositions[k]);
}
}
}
DrawFormatBits(0u);
DrawVersion();
}
private void DrawFormatBits(uint mask)
{
uint num = (ErrorCorrectionLevel.FormatBits << 3) | mask;
uint num2 = num;
for (int i = 0; i < 10; i++)
{
num2 = (num2 << 1) ^ ((num2 >> 9) * 1335);
}
uint x = ((num << 10) | num2) ^ 0x5412u;
for (int j = 0; j <= 5; j++)
{
SetFunctionModule(8, j, GetBit(x, j));
}
SetFunctionModule(8, 7, GetBit(x, 6));
SetFunctionModule(8, 8, GetBit(x, 7));
SetFunctionModule(7, 8, GetBit(x, 8));
for (int k = 9; k < 15; k++)
{
SetFunctionModule(14 - k, 8, GetBit(x, k));
}
for (int l = 0; l < 8; l++)
{
SetFunctionModule(Size - 1 - l, 8, GetBit(x, l));
}
for (int m = 8; m < 15; m++)
{
SetFunctionModule(8, Size - 15 + m, GetBit(x, m));
}
SetFunctionModule(8, Size - 8, isDark: true);
}
private void DrawVersion()
{
if (Version >= 7)
{
uint num = (uint)Version;
for (int i = 0; i < 12; i++)
{
num = (num << 1) ^ ((num >> 11) * 7973);
}
uint x = (uint)(Version << 12) | num;
for (int j = 0; j < 18; j++)
{
bool bit = GetBit(x, j);
int num2 = Size - 11 + j % 3;
int num3 = j / 3;
SetFunctionModule(num2, num3, bit);
SetFunctionModule(num3, num2, bit);
}
}
}
private void DrawFinderPattern(int x, int y)
{
for (int i = -4; i <= 4; i++)
{
for (int j = -4; j <= 4; j++)
{
int num = Math.Max(Math.Abs(j), Math.Abs(i));
int num2 = x + j;
int num3 = y + i;
if (0 <= num2 && num2 < Size && 0 <= num3 && num3 < Size)
{
SetFunctionModule(num2, num3, num != 2 && num != 4);
}
}
}
}
private void DrawAlignmentPattern(int x, int y)
{
for (int i = -2; i <= 2; i++)
{
for (int j = -2; j <= 2; j++)
{
SetFunctionModule(x + j, y + i, Math.Max(Math.Abs(j), Math.Abs(i)) != 1);
}
}
}
private void SetFunctionModule(int x, int y, bool isDark)
{
_modules[y, x] = isDark;
_isFunction[y, x] = true;
}
private Graphics AsGraphics()
{
return new Graphics(Size, _modules);
}
private byte[] AddEccAndInterleave(byte[] data)
{
Objects.RequireNonNull(data);
if (data.Length != GetNumDataCodewords(Version, ErrorCorrectionLevel))
{
throw new ArgumentOutOfRangeException("data", "Length of data does not match version and ecl");
}
int num = NumErrorCorrectionBlocks[ErrorCorrectionLevel.Ordinal, Version];
int num2 = EccCodewordsPerBlock[ErrorCorrectionLevel.Ordinal, Version];
int num3 = GetNumRawDataModules(Version) / 8;
int num4 = num - num3 % num;
int num5 = num3 / num;
byte[][] array = new byte[num][];
ReedSolomonGenerator reedSolomonGenerator = new ReedSolomonGenerator(num2);
int i = 0;
int num6 = 0;
for (; i < num; i++)
{
byte[] array2 = CopyOfRange(data, num6, num6 + num5 - num2 + ((i >= num4) ? 1 : 0));
num6 += array2.Length;
byte[] array3 = CopyOf(array2, num5 + 1);
byte[] remainder = reedSolomonGenerator.GetRemainder(array2);
Array.Copy(remainder, 0, array3, array3.Length - num2, remainder.Length);
array[i] = array3;
}
byte[] array4 = new byte[num3];
int j = 0;
int num7 = 0;
for (; j < array[0].Length; j++)
{
for (int k = 0; k < array.Length; k++)
{
if (j != num5 - num2 || k >= num4)
{
array4[num7] = array[k][j];
num7++;
}
}
}
return array4;
}
private void DrawCodewords(byte[] data)
{
Objects.RequireNonNull(data);
if (data.Length != GetNumRawDataModules(Version) / 8)
{
throw new ArgumentOutOfRangeException("data", "data length does not match version");
}
int num = 0;
for (int num2 = Size - 1; num2 >= 1; num2 -= 2)
{
if (num2 == 6)
{
num2 = 5;
}
for (int i = 0; i < Size; i++)
{
for (int j = 0; j < 2; j++)
{
int num3 = num2 - j;
int num4 = ((((num2 + 1) & 2) == 0) ? (Size - 1 - i) : i);
if (!_isFunction[num4, num3] && num < data.Length * 8)
{
_modules[num4, num3] = GetBit(data[num >>> 3], 7 - (num & 7));
num++;
}
}
}
}
}
private void ApplyMask(uint mask)
{
if (mask < 0 || mask > 7)
{
throw new ArgumentOutOfRangeException("mask", "Mask value out of range");
}
for (int i = 0; i < Size; i++)
{
for (int j = 0; j < Size; j++)
{
bool flag = false;
switch (mask)
{
case 0u:
flag = (j + i) % 2 == 0;
break;
case 1u:
flag = i % 2 == 0;
break;
case 2u:
flag = j % 3 == 0;
break;
case 3u:
flag = (j + i) % 3 == 0;
break;
case 4u:
flag = (j / 3 + i / 2) % 2 == 0;
break;
case 5u:
flag = j * i % 2 + j * i % 3 == 0;
break;
case 6u:
flag = (j * i % 2 + j * i % 3) % 2 == 0;
break;
case 7u:
flag = ((j + i) % 2 + j * i % 3) % 2 == 0;
break;
}
_modules[i, j] ^= flag && !_isFunction[i, j];
}
}
}
private int GetPenaltyScore()
{
int num = 0;
for (int i = 0; i < Size; i++)
{
bool flag = false;
int num2 = 0;
FinderPenalty finderPenalty = new FinderPenalty(Size);
for (int j = 0; j < Size; j++)
{
if (_modules[i, j] == flag)
{
num2++;
if (num2 == 5)
{
num += 3;
}
else if (num2 > 5)
{
num++;
}
}
else
{
finderPenalty.AddHistory(num2);
if (!flag)
{
num += finderPenalty.CountPatterns() * 40;
}
flag = _modules[i, j];
num2 = 1;
}
}
num += finderPenalty.TerminateAndCount(flag, num2) * 40;
}
for (int k = 0; k < Size; k++)
{
bool flag2 = false;
int num3 = 0;
FinderPenalty finderPenalty2 = new FinderPenalty(Size);
for (int l = 0; l < Size; l++)
{
if (_modules[l, k] == flag2)
{
num3++;
if (num3 == 5)
{
num += 3;
}
else if (num3 > 5)
{
num++;
}
}
else
{
finderPenalty2.AddHistory(num3);
if (!flag2)
{
num += finderPenalty2.CountPatterns() * 40;
}
flag2 = _modules[l, k];
num3 = 1;
}
}
num += finderPenalty2.TerminateAndCount(flag2, num3) * 40;
}
for (int m = 0; m < Size - 1; m++)
{
for (int n = 0; n < Size - 1; n++)
{
bool flag3 = _modules[m, n];
if (flag3 == _modules[m, n + 1] && flag3 == _modules[m + 1, n] && flag3 == _modules[m + 1, n + 1])
{
num += 3;
}
}
}
int num4 = 0;
for (int num5 = 0; num5 < Size; num5++)
{
for (int num6 = 0; num6 < Size; num6++)
{
if (_modules[num5, num6])
{
num4++;
}
}
}
int num7 = Size * Size;
int num8 = (Math.Abs(num4 * 20 - num7 * 10) + num7 - 1) / num7 - 1;
return num + num8 * 10;
}
private int[] GetAlignmentPatternPositions()
{
if (Version == 1)
{
return Array.Empty();
}
int num = Version / 7 + 2;
int num2 = (Version * 8 + num * 3 + 5) / (num * 4 - 4) * 2;
int[] array = new int[num];
array[0] = 6;
int num3 = array.Length - 1;
int num4 = Size - 7;
while (num3 >= 1)
{
array[num3] = num4;
num3--;
num4 -= num2;
}
return array;
}
private static int GetNumRawDataModules(int ver)
{
if (ver < 1 || ver > 40)
{
throw new ArgumentOutOfRangeException("ver", "Version number out of range");
}
int num = ver * 4 + 17;
int num2 = num * num;
num2 -= 192;
num2 -= 31;
num2 -= (num - 16) * 2;
if (ver >= 2)
{
int num3 = ver / 7 + 2;
num2 -= (num3 - 1) * (num3 - 1) * 25;
num2 -= (num3 - 2) * 2 * 20;
if (ver >= 7)
{
num2 -= 36;
}
}
return num2;
}
public static int GetNumDataCodewords(int ver, Ecc ecl)
{
return GetNumRawDataModules(ver) / 8 - EccCodewordsPerBlock[ecl.Ordinal, ver] * NumErrorCorrectionBlocks[ecl.Ordinal, ver];
}
private static byte[] CopyOfRange(byte[] original, int from, int to)
{
byte[] array = new byte[to - from];
Array.Copy(original, from, array, 0, to - from);
return array;
}
private static byte[] CopyOf(byte[] original, int newLength)
{
byte[] array = new byte[newLength];
Array.Copy(original, array, Math.Min(original.Length, newLength));
return array;
}
private static bool GetBit(uint x, int i)
{
return ((x >> i) & 1) != 0;
}
}
public class QrSegment
{
public sealed class Mode
{
public static readonly Mode Numeric = new Mode(1u, 10, 12, 14);
public static readonly Mode Alphanumeric = new Mode(2u, 9, 11, 13);
public static readonly Mode Byte = new Mode(4u, 8, 16, 16);
public static readonly Mode Kanji = new Mode(8u, 8, 10, 12);
public static readonly Mode Eci = new Mode(7u, default(int), default(int), default(int));
public static readonly Mode StructuredAppend = new Mode(3u, default(int), default(int), default(int));
internal uint ModeBits { get; }
private int[] NumBitsCharCount { get; }
internal int NumCharCountBits(int ver)
{
return NumBitsCharCount[(ver + 7) / 17];
}
private Mode(uint modeBits, params int[] numBitsCharCount)
{
ModeBits = modeBits;
NumBitsCharCount = numBitsCharCount;
}
}
private readonly BitArray _data;
private static readonly Regex NumericRegex = new Regex("^[0-9]*$", RegexOptions.Compiled);
private static readonly Regex AlphanumericRegex = new Regex("^[A-Z0-9 $%*+./:-]*$", RegexOptions.Compiled);
internal const string AlphanumericCharset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
public Mode EncodingMode { get; }
public int NumChars { get; }
public static QrSegment MakeBytes(byte[] data)
{
Objects.RequireNonNull(data);
BitArray bitArray = new BitArray(0);
foreach (byte val in data)
{
bitArray.AppendBits(val, 8);
}
return new QrSegment(Mode.Byte, data.Length, bitArray);
}
public static QrSegment MakeBytes(ArraySegment data)
{
Objects.RequireNonNull(data);
BitArray bitArray = new BitArray(0);
foreach (byte item in (IEnumerable)data)
{
bitArray.AppendBits(item, 8);
}
return new QrSegment(Mode.Byte, data.Count, bitArray);
}
public static QrSegment MakeNumeric(string digits)
{
Objects.RequireNonNull(digits);
if (!IsNumeric(digits))
{
throw new ArgumentOutOfRangeException("digits", "String contains non-numeric characters");
}
BitArray bitArray = new BitArray(0);
int num;
for (int i = 0; i < digits.Length; i += num)
{
num = Math.Min(digits.Length - i, 3);
bitArray.AppendBits(uint.Parse(digits.Substring(i, num)), num * 3 + 1);
}
return new QrSegment(Mode.Numeric, digits.Length, bitArray);
}
public static QrSegment MakeAlphanumeric(string text)
{
Objects.RequireNonNull(text);
if (!IsAlphanumeric(text))
{
throw new ArgumentOutOfRangeException("text", "String contains unencodable characters in alphanumeric mode");
}
BitArray bitArray = new BitArray(0);
int i;
for (i = 0; i <= text.Length - 2; i += 2)
{
uint num = (uint)("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".IndexOf(text[i]) * 45);
num += (uint)"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".IndexOf(text[i + 1]);
bitArray.AppendBits(num, 11);
}
if (i < text.Length)
{
bitArray.AppendBits((uint)"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".IndexOf(text[i]), 6);
}
return new QrSegment(Mode.Alphanumeric, text.Length, bitArray);
}
internal static QrSegment MakeStructuredAppend(byte parity, int position, int total)
{
BitArray bitArray = new BitArray(0);
bitArray.AppendBits((uint)(position - 1), 4);
bitArray.AppendBits((uint)(total - 1), 4);
bitArray.AppendBits(parity, 8);
return new QrSegment(Mode.StructuredAppend, 0, bitArray);
}
public static List MakeSegments(string text)
{
Objects.RequireNonNull(text);
List list = new List();
if (!(text == ""))
{
if (IsNumeric(text))
{
list.Add(MakeNumeric(text));
}
else if (IsAlphanumeric(text))
{
list.Add(MakeAlphanumeric(text));
}
else
{
list.Add(MakeBytes(Encoding.UTF8.GetBytes(text)));
}
}
return list;
}
public static QrSegment MakeEci(int assignVal)
{
BitArray bitArray = new BitArray(0);
if (assignVal < 0)
{
throw new ArgumentOutOfRangeException("assignVal", "ECI assignment value out of range");
}
if (assignVal < 128)
{
bitArray.AppendBits((uint)assignVal, 8);
}
else if (assignVal < 16384)
{
bitArray.AppendBits(2u, 2);
bitArray.AppendBits((uint)assignVal, 14);
}
else
{
if (assignVal >= 1000000)
{
throw new ArgumentOutOfRangeException("assignVal", "ECI assignment value out of range");
}
bitArray.AppendBits(6u, 3);
bitArray.AppendBits((uint)assignVal, 21);
}
return new QrSegment(Mode.Eci, 0, bitArray);
}
public static bool IsNumeric(string text)
{
return NumericRegex.IsMatch(text);
}
public static bool IsAlphanumeric(string text)
{
return AlphanumericRegex.IsMatch(text);
}
public QrSegment(Mode mode, int numChars, BitArray data)
{
EncodingMode = Objects.RequireNonNull(mode);
Objects.RequireNonNull(data);
if (numChars < 0)
{
throw new ArgumentOutOfRangeException("numChars", "Invalid value");
}
NumChars = numChars;
_data = (BitArray)data.Clone();
}
public BitArray GetData()
{
return (BitArray)_data.Clone();
}
public string GetText()
{
StringBuilder stringBuilder = new StringBuilder();
AppendText(stringBuilder);
return stringBuilder.ToString();
}
public static string GetJoinedText(List segments)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (QrSegment segment in segments)
{
segment.AppendText(stringBuilder);
}
return stringBuilder.ToString();
}
public static string GetJoinedText(List> segments)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (List segment in segments)
{
foreach (QrSegment item in segment)
{
item.AppendText(stringBuilder);
}
}
return stringBuilder.ToString();
}
private void AppendText(StringBuilder builder)
{
if (EncodingMode == Mode.Numeric)
{
for (int i = 0; i < NumChars; i += 3)
{
int num = Math.Min(NumChars - i, 3);
int index = i / 3 * 10;
switch (num)
{
case 3:
{
uint num4 = _data.ExtractBits(index, 10);
builder.Append((char)(48 + num4 / 100));
builder.Append((char)(48 + num4 / 10 % 10));
builder.Append((char)(48 + num4 % 10));
break;
}
case 2:
{
uint num3 = _data.ExtractBits(index, 7);
builder.Append((char)(48 + num3 / 10));
builder.Append((char)(48 + num3 % 10));
break;
}
case 1:
{
uint num2 = _data.ExtractBits(index, 4);
builder.Append((char)(48 + num2));
break;
}
}
}
}
else if (EncodingMode == Mode.Alphanumeric)
{
for (int j = 0; j < NumChars; j += 2)
{
int num5 = Math.Min(NumChars - j, 2);
int index2 = j / 2 * 11;
if (num5 == 2)
{
int num6 = (int)_data.ExtractBits(index2, 11);
builder.Append("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"[num6 / 45]);
builder.Append("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"[num6 % 45]);
}
else
{
int index3 = (int)_data.ExtractBits(index2, 6);
builder.Append("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"[index3]);
}
}
}
else if (EncodingMode == Mode.Byte)
{
byte[] array = new byte[NumChars];
for (int k = 0; k < NumChars; k++)
{
array[k] = (byte)_data.ExtractBits(k * 8, 8);
}
builder.Append(Encoding.UTF8.GetString(array));
}
}
internal static int GetTotalBits(List segments, int version)
{
Objects.RequireNonNull(segments);
long num = 0L;
foreach (QrSegment segment in segments)
{
Objects.RequireNonNull(segment);
int num2 = segment.EncodingMode.NumCharCountBits(version);
if (segment.NumChars >= 1 << num2)
{
return -1;
}
num += 4L + (long)num2 + segment._data.Length;
if (num > int.MaxValue)
{
return -1;
}
}
return (int)num;
}
internal static int GetTotalBits(int numChars, Mode mode, int version)
{
int num = mode.NumCharCountBits(version);
if (numChars >= 1 << num)
{
return -1;
}
int num2 = 0;
if (mode == Mode.Numeric)
{
num2 = numChars / 3 * 10 + ((numChars % 3 != 0) ? (numChars % 3 * 3 + 1) : 0);
}
else if (mode == Mode.Alphanumeric)
{
num2 = numChars / 2 * 11 + ((numChars % 2 != 0) ? 6 : 0);
}
else if (mode == Mode.Byte)
{
num2 = numChars * 8;
}
else
{
if (mode != Mode.Kanji)
{
throw new ArgumentOutOfRangeException("mode", "Unsupported mode for this calculation");
}
num2 = numChars * 13;
}
return 4 + num + num2;
}
}
public static class QrSegmentAdvanced
{
private const string PackedQrKanjiToUnicode = "MAAwATAC/wz/DjD7/xr/G/8f/wEwmzCcALT/QACo/z7/4/8/MP0w/jCdMJ4wA07dMAUwBjAHMPwgFSAQ/w8AXDAcIBb/XCAmICUgGCAZIBwgHf8I/wkwFDAV/zv/Pf9b/10wCDAJMAowCzAMMA0wDjAPMBAwEf8LIhIAsQDX//8A9/8dImD/HP8eImYiZyIeIjQmQiZAALAgMiAzIQP/5f8EAKIAo/8F/wP/Bv8K/yAApyYGJgUlyyXPJc4lxyXGJaEloCWzJbIlvSW8IDswEiGSIZAhkSGTMBP/////////////////////////////IggiCyKGIocigiKDIioiKf////////////////////8iJyIoAKwh0iHUIgAiA/////////////////////////////8iICKlIxIiAiIHImEiUiJqImsiGiI9Ih0iNSIrIiz//////////////////yErIDAmbyZtJmogICAhALb//////////yXv/////////////////////////////////////////////////xD/Ef8S/xP/FP8V/xb/F/8Y/xn///////////////////8h/yL/I/8k/yX/Jv8n/yj/Kf8q/yv/LP8t/y7/L/8w/zH/Mv8z/zT/Nf82/zf/OP85/zr///////////////////9B/0L/Q/9E/0X/Rv9H/0j/Sf9K/0v/TP9N/07/T/9Q/1H/Uv9T/1T/Vf9W/1f/WP9Z/1r//////////zBBMEIwQzBEMEUwRjBHMEgwSTBKMEswTDBNME4wTzBQMFEwUjBTMFQwVTBWMFcwWDBZMFowWzBcMF0wXjBfMGAwYTBiMGMwZDBlMGYwZzBoMGkwajBrMGwwbTBuMG8wcDBxMHIwczB0MHUwdjB3MHgweTB6MHswfDB9MH4wfzCAMIEwgjCDMIQwhTCGMIcwiDCJMIowizCMMI0wjjCPMJAwkTCSMJP/////////////////////////////////////MKEwojCjMKQwpTCmMKcwqDCpMKowqzCsMK0wrjCvMLAwsTCyMLMwtDC1MLYwtzC4MLkwujC7MLwwvTC+ML8wwDDBMMIwwzDEMMUwxjDHMMgwyTDKMMswzDDNMM4wzzDQMNEw0jDTMNQw1TDWMNcw2DDZMNow2zDcMN0w3jDf//8w4DDhMOIw4zDkMOUw5jDnMOgw6TDqMOsw7DDtMO4w7zDwMPEw8jDzMPQw9TD2/////////////////////wORA5IDkwOUA5UDlgOXA5gDmQOaA5sDnAOdA54DnwOgA6EDowOkA6UDpgOnA6gDqf////////////////////8DsQOyA7MDtAO1A7YDtwO4A7kDugO7A7wDvQO+A78DwAPBA8MDxAPFA8YDxwPIA8n/////////////////////////////////////////////////////////////////////////////////////////////////////////////BBAEEQQSBBMEFAQVBAEEFgQXBBgEGQQaBBsEHAQdBB4EHwQgBCEEIgQjBCQEJQQmBCcEKAQpBCoEKwQsBC0ELgQv////////////////////////////////////////BDAEMQQyBDMENAQ1BFEENgQ3BDgEOQQ6BDsEPAQ9//8EPgQ/BEAEQQRCBEMERARFBEYERwRIBEkESgRLBEwETQROBE///////////////////////////////////yUAJQIlDCUQJRglFCUcJSwlJCU0JTwlASUDJQ8lEyUbJRclIyUzJSslOyVLJSAlLyUoJTclPyUdJTAlJSU4JUL//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////06cVRZaA5Y/VMBhG2MoWfaQIoR1gxx6UGCqY+FuJWXthGaCppv1aJNXJ2WhYnFbm1nQhnuY9H1ifb6bjmIWfJ+It1uJXrVjCWaXaEiVx5eNZ09O5U8KT01PnVBJVvJZN1nUWgFcCWDfYQ9hcGYTaQVwunVPdXB5+32tfe+Aw4QOiGOLApBVkHpTO06VTqVX34CykMF4704AWPFuopA4ejKDKIKLnC9RQVNwVL1U4VbgWftfFZjybeuA5IUt////////lmKWcJagl/tUC1PzW4dwz3+9j8KW6FNvnVx6uk4ReJOB/G4mVhhVBGsdhRqcO1nlU6ltZnTclY9WQk6RkEuW8oNPmQxT4VW2WzBfcWYgZvNoBGw4bPNtKXRbdsh6Tpg0gvGIW4pgku1tsnWrdsqZxWCmiwGNipWyaY5TrVGG//9XElgwWURbtF72YChjqWP0bL9vFHCOcRRxWXHVcz9+AYJ2gtGFl5BgkludG1hpZbxsWnUlUflZLlllX4Bf3GK8ZfpqKmsna7Rzi3/BiVadLJ0OnsRcoWyWg3tRBFxLYbaBxmh2cmFOWU/6U3hgaW4pek+X804LUxZO7k9VTz1PoU9zUqBT71YJWQ9awVu2W+F50WaHZ5xntmtMbLNwa3PCeY15vno8e4eCsYLbgwSDd4Pvg9OHZoqyVimMqI/mkE6XHoaKT8Rc6GIRcll1O4Hlgr2G/ozAlsWZE5nVTstPGonjVt5YSljKXvtf62AqYJRgYmHQYhJi0GU5////////m0FmZmiwbXdwcHVMdoZ9dYKlh/mVi5aOjJ1R8VK+WRZUs1uzXRZhaGmCba94jYTLiFeKcpOnmrhtbJmohtlXo2f/hs6SDlKDVodUBF7TYuFkuWg8aDhru3NyeLp6a4maidKNa48DkO2Vo5aUl2lbZlyzaX2YTZhOY5t7IGor//9qf2i2nA1vX1JyVZ1gcGLsbTtuB27RhFuJEI9EThScOVP2aRtqOpeEaCpRXHrDhLKR3JOMVludKGgigwWEMXylUgiCxXTmTn5Pg1GgW9JSClLYUudd+1WaWCpZ5luMW5hb215yXnlgo2EfYWNhvmPbZWJn0WhTaPprPmtTbFdvIm+Xb0V0sHUYduN3C3r/e6F8IX3pfzZ/8ICdgmaDnomzisyMq5CElFGVk5WRlaKWZZfTmSiCGE44VCtcuF3Mc6l2THc8XKl/640LlsGYEZhUmFhPAU8OU3FVnFZoV/pZR1sJW8RckF4MXn5fzGPuZzpl12XiZx9oy2jE////////al9eMGvFbBdsfXV/eUhbY3oAfQBfvYmPihiMtI13jsyPHZjimg6bPE6AUH1RAFmTW5xiL2KAZOxrOnKgdZF5R3+ph/uKvItwY6yDypegVAlUA1WraFRqWIpweCdndZ7NU3RbooEahlCQBk4YTkVOx08RU8pUOFuuXxNgJWVR//9nPWxCbHJs43B4dAN6dnquewh9Gnz+fWZl53JbU7tcRV3oYtJi4GMZbiCGWooxjd2S+G8BeaabWk6oTqtOrE+bT6BQ0VFHevZRcVH2U1RTIVN/U+tVrFiDXOFfN19KYC9gUGBtYx9lWWpLbMFywnLtd++A+IEFggiFTpD3k+GX/5lXmlpO8FHdXC1mgWltXEBm8ml1c4loUHyBUMVS5FdHXf6TJmWkayNrPXQ0eYF5vXtLfcqCuYPMiH+JX4s5j9GR0VQfkoBOXVA2U+VTOnLXc5Z36YLmjq+ZxpnImdJRd2Eahl5VsHp6UHZb05BHloVOMmrbkedcUVxI////////Y5h6n2yTl3SPYXqqcYqWiHyCaBd+cGhRk2xS8lQbhauKE3+kjs2Q4VNmiIh5QU/CUL5SEVFEVVNXLXPqV4tZUV9iX4RgdWF2YWdhqWOyZDplbGZvaEJuE3Vmej18+31MfZl+S39rgw6DSobNigiKY4tmjv2YGp2PgriPzpvo//9Sh2IfZINvwJaZaEFQkWsgbHpvVHp0fVCIQIojZwhO9lA5UCZQZVF8UjhSY1WnVw9YBVrMXvphsmH4YvNjcmkcailyfXKscy54FHhvfXl3DICpiYuLGYzijtKQY5N1lnqYVZoTnnhRQ1OfU7Nee18mbhtukHOEc/59Q4I3igCK+pZQTk5QC1PkVHxW+lnRW2Rd8V6rXydiOGVFZ69uVnLQfMqItIChgOGD8IZOioeN6JI3lseYZ58TTpROkk8NU0hUSVQ+Wi9fjF+hYJ9op2qOdFp4gYqeiqSLd5GQTl6byU6kT3xPr1AZUBZRSVFsUp9SuVL+U5pT41QR////////VA5ViVdRV6JZfVtUW11bj13lXedd9154XoNeml63XxhgUmFMYpdi2GOnZTtmAmZDZvRnbWghaJdpy2xfbSptaW4vbp11MnaHeGx6P3zgfQV9GH1efbGAFYADgK+AsYFUgY+CKoNSiEyIYYsbjKKM/JDKkXWScXg/kvyVpJZN//+YBZmZmtidO1JbUqtT91QIWNVi92/gjGqPX565UUtSO1RKVv16QJF3nWCe0nNEbwmBcHURX/1g2pqoctuPvGtkmANOylbwV2RYvlpaYGhhx2YPZgZoOWixbfd11X06gm6bQk6bT1BTyVUGXW9d5l3uZ/tsmXRzeAKKUJOWiN9XUF6nYytQtVCsUY1nAFTJWF5Zu1uwX2liTWOhaD1rc24IcH2Rx3KAeBV4JnltZY59MIPciMGPCZabUmRXKGdQf2qMoVG0V0KWKlg6aYqAtFSyXQ5X/HiVnfpPXFJKVItkPmYoZxRn9XqEe1Z9IpMvaFybrXs5UxlRilI3////////W99i9mSuZOZnLWu6hamW0XaQm9ZjTJMGm6t2v2ZSTglQmFPCXHFg6GSSZWNoX3Hmc8p1I3uXfoKGlYuDjNuReJkQZaxmq2uLTtVO1E86T39SOlP4U/JV41bbWOtZy1nJWf9bUFxNXgJeK1/XYB1jB2UvW1xlr2W9ZehnnWti//9re2wPc0V5SXnBfPh9GX0rgKKBAoHziZaKXoppimaKjIrujMeM3JbMmPxrb06LTzxPjVFQW1db+mFIYwFmQmshbstsu3I+dL111HjBeTqADIAzgeqElI+ebFCef18Pi1idK3r6jvhbjZbrTgNT8Vf3WTFayVukYIluf28Gdb6M6lufhQB74FByZ/SCnVxhhUp+HoIOUZlcBGNojWZlnHFueT59F4AFix2OypBuhseQqlAfUvpcOmdTcHxyNZFMkciTK4LlW8JfMWD5TjtT1luIYktnMWuKculz4HougWuNo5FSmZZRElPXVGpb/2OIajl9rJcAVtpTzlRo////////W5dcMV3eT+5hAWL+bTJ5wHnLfUJ+TX/Sge2CH4SQiEaJcouQjnSPL5AxkUuRbJbGkZxOwE9PUUVTQV+TYg5n1GxBbgtzY34mkc2Sg1PUWRlbv23ReV1+LnybWH5xn1H6iFOP8E/KXPtmJXeseuOCHJn/UcZfqmXsaW9riW3z//9ulm9kdv59FF3hkHWRh5gGUeZSHWJAZpFm2W4aXrZ90n9yZviFr4X3ivhSqVPZWXNej1+QYFWS5JZkULdRH1LdUyBTR1PsVOhVRlUxVhdZaFm+WjxbtVwGXA9cEVwaXoReil7gX3Bif2KEYttjjGN3ZgdmDGYtZnZnfmiiah9qNWy8bYhuCW5YcTxxJnFndcd3AXhdeQF5ZXnweuB7EXynfTmAloPWhIuFSYhdiPOKH4o8ilSKc4xhjN6RpJJmk36UGJacl5hOCk4ITh5OV1GXUnBXzlg0WMxbIl44YMVk/mdhZ1ZtRHK2dXN6Y4S4i3KRuJMgVjFX9Jj+////////Yu1pDWuWce1+VIB3gnKJ5pjfh1WPsVw7TzhP4U+1VQdaIFvdW+lfw2FOYy9lsGZLaO5pm214bfF1M3W5dx95XnnmfTOB44KvhaqJqoo6jquPm5Aykd2XB066TsFSA1h1WOxcC3UaXD2BTooKj8WWY5dteyWKz5gIkWJW81Oo//+QF1Q5V4JeJWOobDRwindhfIt/4IhwkEKRVJMQkxiWj3RemsRdB11pZXBnoo2olttjbmdJaRmDxZgXlsCI/m+EZHpb+E4WcCx1XWYvUcRSNlLiWdNfgWAnYhBlP2V0Zh9mdGjyaBZrY24FcnJ1H3bbfL6AVljwiP2Jf4qgipOKy5AdkZKXUpdZZYl6DoEGlrteLWDcYhplpWYUZ5B383pNfE1+PoEKjKyNZI3hjl94qVIHYtljpWRCYpiKLXqDe8CKrJbqfXaCDIdJTtlRSFNDU2Bbo1wCXBZd3WImYkdksGgTaDRsyW1FbRdn029ccU5xfWXLen97rX3a////////fkp/qIF6ghuCOYWmim6Mzo31kHiQd5KtkpGVg5uuUk1VhG84cTZRaHmFflWBs3zOVkxYUVyoY6pm/mb9aVpy2XWPdY55DnlWed98l30gfUSGB4o0ljuQYZ8gUOdSdVPMU+JQCVWqWO5ZT3I9W4tcZFMdYONg82NcY4NjP2O7//9kzWXpZvld42nNaf1vFXHlTol16Xb4epN8333PfZyAYYNJg1iEbIS8hfuIxY1wkAGQbZOXlxyaElDPWJdhjoHThTWNCJAgT8NQdFJHU3Ngb2NJZ19uLI2zkB9P11xejMplz32aU1KIllF2Y8NbWFtrXApkDWdRkFxO1lkaWSpscIpRVT5YFVmlYPBiU2fBgjVpVZZAmcSaKE9TWAZb/oAQXLFeL1+FYCBhS2I0Zv9s8G7egM6Bf4LUiIuMuJAAkC6Wip7bm9tO41PwWSd7LJGNmEyd+W7dcCdTU1VEW4ViWGKeYtNsom/vdCKKF5Q4b8GK/oM4UeeG+FPq////////U+lPRpBUj7BZaoExXf166o+/aNqMN3L4nEhqPYqwTjlTWFYGV2ZixWOiZeZrTm3hbltwrXfteu97qn27gD2AxobLipWTW1bjWMdfPmWtZpZqgGu1dTeKx1Akd+VXMF8bYGVmemxgdfR6Gn9ugfSHGJBFmbN7yXVcevl7UYTE//+QEHnpepKDNlrhd0BOLU7yW5lf4GK9Zjxn8WzohmuId4o7kU6S85nQahdwJnMqgueEV4yvTgFRRlHLVYtb9V4WXjNegV8UXzVfa1+0YfJjEWaiZx1vbnJSdTp3OoB0gTmBeId2ir+K3I2FjfOSmpV3mAKc5VLFY1d29GcVbIhzzYzDk66Wc20lWJxpDmnMj/2TmnXbkBpYWmgCY7Rp+09Dbyxn2I+7hSZ9tJNUaT9vcFdqWPdbLH0scipUCpHjnbROrU9OUFxQdVJDjJ5USFgkW5peHV6VXq1e918fYIxitWM6Y9Bor2xAeId5jnoLfeCCR4oCiuaORJAT////////kLiRLZHYnw5s5WRYZOJldW70doR7G5Bpk9FuulTyX7lkpI9Nj+2SRFF4WGtZKVxVXpdt+36PdRyMvI7imFtwuU8da79vsXUwlvtRTlQQWDVYV1msXGBfkmWXZ1xuIXZ7g9+M7ZAUkP2TTXgleDpSql6mVx9ZdGASUBJRWlGs//9RzVIAVRBYVFhYWVdblVz2XYtgvGKVZC1ncWhDaLxo33bXbdhub22bcG9xyF9Tddh5d3tJe1R7UnzWfXFSMIRjhWmF5IoOiwSMRo4PkAOQD5QZlnaYLZowldhQzVLVVAxYAlwOYadknm0ed7N65YD0hASQU5KFXOCdB1M/X5dfs22ccnl3Y3m/e+Rr0nLsiq1oA2phUfh6gWk0XEqc9oLrW8WRSXAeVnhcb2DHZWZsjIxakEGYE1RRZseSDVlIkKNRhU5NUeqFmYsOcFhjepNLaWKZtH4EdXdTV2lgjt+W42xdToxcPF8Qj+lTAozRgImGeV7/ZeVOc1Fl////////WYJcP5fuTvtZil/Nio1v4XmweWJb54RxcytxsV50X/Vje2SaccN8mE5DXvxOS1fcVqJgqW/DfQ2A/YEzgb+PsomXhqRd9GKKZK2Jh2d3bOJtPnQ2eDRaRn91gq2ZrE/zXsNi3WOSZVdnb3bDckyAzIC6jymRTVANV/lakmiF//9pc3Fkcv2Mt1jyjOCWapAZh3955HfnhClPL1JlU1pizWfPbMp2fXuUfJWCNoWEj+tm3W8gcgZ+G4OrmcGeplH9e7F4cnu4gId7SGroXmGAjHVRdWBRa5Jibox2epGXmupPEH9wYpx7T5WlnOlWelhZhuSWvE80UiRTSlPNU9teBmQsZZFnf2w+bE5ySHKvc+11VH5BgiyF6Yype8SRxnFpmBKY72M9Zml1anbkeNCFQ4buUypTUVQmWYNeh198YLJiSWJ5YqtlkGvUbMx1snaueJF52H3Lf3eApYirirmMu5B/l16Y22oLfDhQmVw+X65nh2vYdDV3CX+O////////nztnynoXUzl1i5rtX2aBnYPxgJhfPF/FdWJ7RpA8aGdZ61qbfRB2fossT/VfamoZbDdvAnTieWiIaIpVjHle32PPdcV50oLXkyiS8oSchu2cLVTBX2xljG1ccBWMp4zTmDtlT3T2Tg1O2FfgWStaZlvMUaheA16cYBZidmV3//9lp2ZubW5yNnsmgVCBmoKZi1yMoIzmjXSWHJZET65kq2tmgh6EYYVqkOhcAWlTmKiEeoVXTw9Sb1+pXkVnDXmPgXmJB4mGbfVfF2JVbLhOz3Jpm5JSBlQ7VnRYs2GkYm5xGllufIl83n0blvBlh4BeThlPdVF1WEBeY15zXwpnxE4mhT2ViZZbfHOYAVD7WMF2VninUiV3pYURe4ZQT1kJckd7x33oj7qP1JBNT79SyVopXwGXrU/dgheS6lcDY1VraXUriNyPFHpCUt9Yk2FVYgpmrmvNfD+D6VAjT/hTBVRGWDFZSVudXPBc710pXpZisWNnZT5luWcL////////bNVs4XD5eDJ+K4DegrOEDITshwKJEooqjEqQppLSmP2c851sTk9OoVCNUlZXSlmoXj1f2F/ZYj9mtGcbZ9Bo0lGSfSGAqoGoiwCMjIy/kn6WMlQgmCxTF1DVU1xYqGSyZzRyZ3dmekaR5lLDbKFrhlgAXkxZVGcsf/tR4XbG//9kaXjom1Seu1fLWblmJ2eaa85U6WnZXlWBnGeVm6pn/pxSaF1Opk/jU8hiuWcrbKuPxE+tfm2ev04HYWJugG8rhRNUc2cqm0Vd83uVXKxbxoccbkqE0XoUgQhZmXyNbBF3IFLZWSJxIXJfd9uXJ51haQtaf1oYUaVUDVR9Zg5234/3kpic9Fnqcl1uxVFNaMl9v33sl2KeumR4aiGDAlmEW19r23MbdvJ9soAXhJlRMmcontl27mdiUv+ZBVwkYjt8foywVU9gtn0LlYBTAU5fUbZZHHI6gDaRzl8ld+JThF95fQSFrIozjo2XVmfzha6UU2EJYQhsuXZS////////iu2POFUvT1FRKlLHU8tbpV59YKBhgmPWZwln2m5nbYxzNnM3dTF5UIjVipiQSpCRkPWWxIeNWRVOiE9ZTg6KiY8/mBBQrV58WZZbuV64Y9pj+mTBZtxpSmnYbQtutnGUdSh6r3+KgACESYTJiYGLIY4KkGWWfZkKYX5ikWsy//9sg210f8x//G3Af4WHuoj4Z2WDsZg8lvdtG31hhD2Rak5xU3VdUGsEb+uFzYYtiadSKVQPXGVnTmiodAZ0g3XiiM+I4ZHMluKWeF+Lc4d6y4ROY6B1ZVKJbUFunHQJdVl4a3ySloZ63J+NT7ZhbmXFhlxOhk6uUNpOIVHMW+5lmWiBbbxzH3ZCd616HHzngm+K0pB8kc+WdZgYUpt90VArU5hnl23LcdB0M4HojyqWo5xXnp90YFhBbZl9L5heTuRPNk+LUbdSsV26YBxzsnk8gtOSNJa3lvaXCp6Xn2Jmpmt0UhdSo3DIiMJeyWBLYZBvI3FJfD599IBv////////hO6QI5MsVEKbb2rTcImMwo3vlzJStFpBXspfBGcXaXxplG1qbw9yYnL8e+2AAYB+h0uQzlFtnpN5hICLkzKK1lAtVIyKcWtqjMSBB2DRZ6Cd8k6ZTpicEIprhcGFaGkAbn54l4FV/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////18MThBOFU4qTjFONk48Tj9OQk5WTlhOgk6FjGtOioISXw1Ojk6eTp9OoE6iTrBOs062Ts5OzU7ETsZOwk7XTt5O7U7fTvdPCU9aTzBPW09dT1dPR092T4hPj0+YT3tPaU9wT5FPb0+GT5ZRGE/UT99Pzk/YT9tP0U/aT9BP5E/lUBpQKFAUUCpQJVAFTxxP9lAhUClQLE/+T+9QEVAGUENQR2cDUFVQUFBIUFpQVlBsUHhQgFCaUIVQtFCy////////UMlQylCzUMJQ1lDeUOVQ7VDjUO5Q+VD1UQlRAVECURZRFVEUURpRIVE6UTdRPFE7UT9RQFFSUUxRVFFievhRaVFqUW5RgFGCVthRjFGJUY9RkVGTUZVRllGkUaZRolGpUapRq1GzUbFRslGwUbVRvVHFUclR21HghlVR6VHt//9R8FH1Uf5SBFILUhRSDlInUipSLlIzUjlST1JEUktSTFJeUlRSalJ0UmlSc1J/Un1SjVKUUpJScVKIUpGPqI+nUqxSrVK8UrVSwVLNUtdS3lLjUuaY7VLgUvNS9VL4UvlTBlMIdThTDVMQUw9TFVMaUyNTL1MxUzNTOFNAU0ZTRU4XU0lTTVHWU15TaVNuWRhTe1N3U4JTllOgU6ZTpVOuU7BTtlPDfBKW2VPfZvxx7lPuU+hT7VP6VAFUPVRAVCxULVQ8VC5UNlQpVB1UTlSPVHVUjlRfVHFUd1RwVJJUe1SAVHZUhFSQVIZUx1SiVLhUpVSsVMRUyFSo////////VKtUwlSkVL5UvFTYVOVU5lUPVRRU/VTuVO1U+lTiVTlVQFVjVUxVLlVcVUVVVlVXVThVM1VdVZlVgFSvVYpVn1V7VX5VmFWeVa5VfFWDValVh1WoVdpVxVXfVcRV3FXkVdRWFFX3VhZV/lX9VhtV+VZOVlBx31Y0VjZWMlY4//9Wa1ZkVi9WbFZqVoZWgFaKVqBWlFaPVqVWrla2VrRWwla8VsFWw1bAVshWzlbRVtNW11buVvlXAFb/VwRXCVcIVwtXDVcTVxhXFlXHVxxXJlc3VzhXTlc7V0BXT1dpV8BXiFdhV39XiVeTV6BXs1ekV6pXsFfDV8ZX1FfSV9NYClfWV+NYC1gZWB1YclghWGJYS1hwa8BYUlg9WHlYhVi5WJ9Yq1i6WN5Yu1i4WK5YxVjTWNFY11jZWNhY5VjcWORY31jvWPpY+Vj7WPxY/VkCWQpZEFkbaKZZJVksWS1ZMlk4WT560llVWVBZTllaWVhZYllgWWdZbFlp////////WXhZgVmdT15Pq1mjWbJZxlnoWdxZjVnZWdpaJVofWhFaHFoJWhpaQFpsWklaNVo2WmJaalqaWrxavlrLWsJavVrjWtda5lrpWtZa+lr7WwxbC1sWWzJa0FsqWzZbPltDW0VbQFtRW1VbWltbW2VbaVtwW3NbdVt4ZYhbeluA//9bg1umW7hbw1vHW8lb1FvQW+Rb5lviW95b5VvrW/Bb9lvzXAVcB1wIXA1cE1wgXCJcKFw4XDlcQVxGXE5cU1xQXE9bcVxsXG5OYlx2XHlcjFyRXJRZm1yrXLtctly8XLdcxVy+XMdc2VzpXP1c+lztXYxc6l0LXRVdF11cXR9dG10RXRRdIl0aXRldGF1MXVJdTl1LXWxdc112XYddhF2CXaJdnV2sXa5dvV2QXbddvF3JXc1d013SXdZd213rXfJd9V4LXhpeGV4RXhteNl43XkReQ15AXk5eV15UXl9eYl5kXkdedV52XnqevF5/XqBewV7CXshe0F7P////////XtZe417dXtpe217iXuFe6F7pXuxe8V7zXvBe9F74Xv5fA18JX11fXF8LXxFfFl8pXy1fOF9BX0hfTF9OXy9fUV9WX1dfWV9hX21fc193X4Nfgl9/X4pfiF+RX4dfnl+ZX5hfoF+oX61fvF/WX/tf5F/4X/Ff3WCzX/9gIWBg//9gGWAQYClgDmAxYBtgFWArYCZgD2A6YFpgQWBqYHdgX2BKYEZgTWBjYENgZGBCYGxga2BZYIFgjWDnYINgmmCEYJtglmCXYJJgp2CLYOFguGDgYNNgtF/wYL1gxmC1YNhhTWEVYQZg9mD3YQBg9GD6YQNhIWD7YPFhDWEOYUdhPmEoYSdhSmE/YTxhLGE0YT1hQmFEYXNhd2FYYVlhWmFrYXRhb2FlYXFhX2FdYVNhdWGZYZZhh2GsYZRhmmGKYZFhq2GuYcxhymHJYfdhyGHDYcZhumHLf3lhzWHmYeNh9mH6YfRh/2H9Yfxh/mIAYghiCWINYgxiFGIb////////Yh5iIWIqYi5iMGIyYjNiQWJOYl5iY2JbYmBiaGJ8YoJiiWJ+YpJik2KWYtRig2KUYtdi0WK7Ys9i/2LGZNRiyGLcYsxiymLCYsdim2LJYwxi7mLxYydjAmMIYu9i9WNQYz5jTWQcY09jlmOOY4Bjq2N2Y6Njj2OJY59jtWNr//9jaWO+Y+ljwGPGY+NjyWPSY/ZjxGQWZDRkBmQTZCZkNmUdZBdkKGQPZGdkb2R2ZE5lKmSVZJNkpWSpZIhkvGTaZNJkxWTHZLtk2GTCZPFk54IJZOBk4WKsZONk72UsZPZk9GTyZPplAGT9ZRhlHGUFZSRlI2UrZTRlNWU3ZTZlOHVLZUhlVmVVZU1lWGVeZV1lcmV4ZYJlg4uKZZtln2WrZbdlw2XGZcFlxGXMZdJl22XZZeBl4WXxZ3JmCmYDZftnc2Y1ZjZmNGYcZk9mRGZJZkFmXmZdZmRmZ2ZoZl9mYmZwZoNmiGaOZolmhGaYZp1mwWa5Zslmvma8////////ZsRmuGbWZtpm4GY/ZuZm6WbwZvVm92cPZxZnHmcmZyeXOGcuZz9nNmdBZzhnN2dGZ15nYGdZZ2NnZGeJZ3BnqWd8Z2pnjGeLZ6ZnoWeFZ7dn72e0Z+xns2fpZ7hn5GfeZ91n4mfuZ7lnzmfGZ+dqnGgeaEZoKWhAaE1oMmhO//9os2graFloY2h3aH9on2iPaK1olGidaJtog2quaLlodGi1aKBoumkPaI1ofmkBaMppCGjYaSJpJmjhaQxozWjUaOdo1Wk2aRJpBGjXaONpJWj5aOBo72koaSppGmkjaSFoxml5aXdpXGl4aWtpVGl+aW5pOWl0aT1pWWkwaWFpXmldaYFpammyaa5p0Gm/acFp02m+ac5b6GnKad1pu2nDaadqLmmRaaBpnGmVabRp3mnoagJqG2n/awpp+WnyaedqBWmxah5p7WoUaetqCmoSasFqI2oTakRqDGpyajZqeGpHamJqWWpmakhqOGoiapBqjWqgaoRqomqj////////apeGF2q7asNqwmq4arNqrGreatFq32qqatpq6mr7awWGFmr6axJrFpsxax9rOGs3dtxrOZjua0drQ2tJa1BrWWtUa1trX2tha3hreWt/a4BrhGuDa41rmGuVa55rpGuqa6trr2uya7Frs2u3a7xrxmvLa9Nr32vsa+tr82vv//+evmwIbBNsFGwbbCRsI2xebFVsYmxqbIJsjWyabIFsm2x+bGhsc2ySbJBsxGzxbNNsvWzXbMVs3WyubLFsvmy6bNts72zZbOptH4hNbTZtK209bThtGW01bTNtEm0MbWNtk21kbVpteW1ZbY5tlW/kbYVt+W4VbgpttW3HbeZtuG3Gbext3m3Mbeht0m3Fbfpt2W3kbdVt6m3ubi1ubm4ubhlucm5fbj5uI25rbitudm5Nbh9uQ246bk5uJG7/bh1uOG6CbqpumG7Jbrdu0269bq9uxG6ybtRu1W6PbqVuwm6fb0FvEXBMbuxu+G7+bz9u8m8xbu9vMm7M////////bz5vE273b4Zvem94b4FvgG9vb1tv829tb4JvfG9Yb45vkW/Cb2Zvs2+jb6FvpG+5b8Zvqm/fb9Vv7G/Ub9hv8W/ub9twCXALb/pwEXABcA9v/nAbcBpvdHAdcBhwH3AwcD5wMnBRcGNwmXCScK9w8XCscLhws3CucN9wy3Dd//9w2XEJcP1xHHEZcWVxVXGIcWZxYnFMcVZxbHGPcftxhHGVcahxrHHXcblxvnHScclx1HHOceBx7HHncfVx/HH5cf9yDXIQchtyKHItcixyMHIycjtyPHI/ckByRnJLclhydHJ+coJygXKHcpJylnKicqdyuXKycsNyxnLEcs5y0nLicuBy4XL5cvdQD3MXcwpzHHMWcx1zNHMvcylzJXM+c05zT57Yc1dzanNoc3BzeHN1c3tzenPIc7NzznO7c8Bz5XPuc950onQFdG90JXP4dDJ0OnRVdD90X3RZdEF0XHRpdHB0Y3RqdHZ0fnSLdJ50p3TKdM901HPx////////dOB043TndOl07nTydPB08XT4dPd1BHUDdQV1DHUOdQ11FXUTdR51JnUsdTx1RHVNdUp1SXVbdUZ1WnVpdWR1Z3VrdW11eHV2dYZ1h3V0dYp1iXWCdZR1mnWddaV1o3XCdbN1w3W1db11uHW8dbF1zXXKddJ12XXjdd51/nX///91/HYBdfB1+nXydfN2C3YNdgl2H3YndiB2IXYidiR2NHYwdjt2R3ZIdkZ2XHZYdmF2YnZodml2anZndmx2cHZydnZ2eHZ8doB2g3aIdot2jnaWdpN2mXaadrB2tHa4drl2unbCds121nbSdt524Xbldud26oYvdvt3CHcHdwR3KXckdx53JXcmdxt3N3c4d0d3Wndod2t3W3dld393fnd5d453i3eRd6B3nnewd7Z3uXe/d7x3vXe7d8d3zXfXd9p33Hfjd+53/HgMeBJ5JnggeSp4RXiOeHR4hnh8eJp4jHijeLV4qniveNF4xnjLeNR4vni8eMV4ynjs////////eOd42nj9ePR5B3kSeRF5GXkseSt5QHlgeVd5X3laeVV5U3l6eX95inmdeaefS3mqea55s3m5ebp5yXnVeed57HnheeN6CHoNehh6GXogeh95gHoxejt6Pno3ekN6V3pJemF6Ynppn516cHp5en16iHqXepV6mHqWeql6yHqw//96tnrFesR6v5CDesd6ynrNes961XrTetl62nrdeuF64nrmeu168HsCew97CnsGezN7GHsZex57NXsoezZ7UHt6ewR7TXsLe0x7RXt1e2V7dHtne3B7cXtse257nXuYe597jXuce5p7i3uSe497XXuZe8t7wXvMe897tHvGe9176XwRfBR75nvlfGB8AHwHfBN783v3fBd8DXv2fCN8J3wqfB98N3wrfD18THxDfFR8T3xAfFB8WHxffGR8VnxlfGx8dXyDfJB8pHytfKJ8q3yhfKh8s3yyfLF8rny5fL18wHzFfMJ82HzSfNx84ps7fO988nz0fPZ8+n0G////////fQJ9HH0VfQp9RX1LfS59Mn0/fTV9Rn1zfVZ9Tn1yfWh9bn1PfWN9k32JfVt9j319fZt9un2ufaN9tX3Hfb19q349faJ9r33cfbh9n32wfdh93X3kfd59+33yfeF+BX4KfiN+IX4SfjF+H34Jfgt+In5GfmZ+O341fjl+Q343//9+Mn46fmd+XX5Wfl5+WX5afnl+an5pfnx+e36DfdV+fY+ufn9+iH6Jfox+kn6QfpN+lH6Wfo5+m36cfzh/On9Ff0x/TX9Of1B/UX9Vf1R/WH9ff2B/aH9pf2d/eH+Cf4Z/g3+If4d/jH+Uf55/nX+af6N/r3+yf7l/rn+2f7iLcX/Ff8Z/yn/Vf9R/4X/mf+l/83/5mNyABoAEgAuAEoAYgBmAHIAhgCiAP4A7gEqARoBSgFiAWoBfgGKAaIBzgHKAcIB2gHmAfYB/gISAhoCFgJuAk4CagK1RkICsgNuA5YDZgN2AxIDagNaBCYDvgPGBG4EpgSOBL4FL////////louBRoE+gVOBUYD8gXGBboFlgWaBdIGDgYiBioGAgYKBoIGVgaSBo4FfgZOBqYGwgbWBvoG4gb2BwIHCgbqByYHNgdGB2YHYgciB2oHfgeCB54H6gfuB/oIBggKCBYIHggqCDYIQghaCKYIrgjiCM4JAglmCWIJdglqCX4Jk//+CYoJogmqCa4IugnGCd4J4gn6CjYKSgquCn4K7gqyC4YLjgt+C0oL0gvOC+oOTgwOC+4L5gt6DBoLcgwmC2YM1gzSDFoMygzGDQIM5g1CDRYMvgyuDF4MYg4WDmoOqg5+DooOWgyODjoOHg4qDfIO1g3ODdYOgg4mDqIP0hBOD64POg/2EA4PYhAuDwYP3hAeD4IPyhA2EIoQgg72EOIUGg/uEbYQqhDyFWoSEhHeEa4SthG6EgoRphEaELIRvhHmENYTKhGKEuYS/hJ+E2YTNhLuE2oTQhMGExoTWhKGFIYT/hPSFF4UYhSyFH4UVhRSE/IVAhWOFWIVI////////hUGGAoVLhVWFgIWkhYiFkYWKhaiFbYWUhZuF6oWHhZyFd4V+hZCFyYW6hc+FuYXQhdWF3YXlhdyF+YYKhhOGC4X+hfqGBoYihhqGMIY/hk1OVYZUhl+GZ4ZxhpOGo4aphqqGi4aMhraGr4bEhsaGsIbJiCOGq4bUht6G6Ybs//+G34bbhu+HEocGhwiHAIcDhvuHEYcJhw2G+YcKhzSHP4c3hzuHJYcphxqHYIdfh3iHTIdOh3SHV4doh26HWYdTh2OHaogFh6KHn4eCh6+Hy4e9h8CH0JbWh6uHxIezh8eHxoe7h++H8ofgiA+IDYf+h/aH94gOh9KIEYgWiBWIIoghiDGINog5iCeIO4hEiEKIUohZiF6IYohriIGIfoieiHWIfYi1iHKIgoiXiJKIroiZiKKIjYikiLCIv4ixiMOIxIjUiNiI2YjdiPmJAoj8iPSI6IjyiQSJDIkKiROJQ4keiSWJKokriUGJRIk7iTaJOIlMiR2JYIle////////iWaJZIltiWqJb4l0iXeJfomDiYiJiomTiZiJoYmpiaaJrImvibKJuom9ib+JwInaidyJ3YnnifSJ+IoDihaKEIoMihuKHYolijaKQYpbilKKRopIinyKbYpsimKKhYqCioSKqIqhipGKpYqmipqKo4rEis2KworaiuuK84rn//+K5IrxixSK4IriiveK3orbiwyLB4saiuGLFosQixeLIIszl6uLJosriz6LKItBi0yLT4tOi0mLVotbi1qLa4tfi2yLb4t0i32LgIuMi46LkouTi5aLmYuajDqMQYw/jEiMTIxOjFCMVYxijGyMeIx6jIKMiYyFjIqMjYyOjJSMfIyYYh2MrYyqjL2MsoyzjK6MtozIjMGM5IzjjNqM/Yz6jPuNBI0FjQqNB40PjQ2NEJ9OjROMzY0UjRaNZ41tjXGNc42BjZmNwo2+jbqNz43ajdaNzI3bjcuN6o3rjd+N4438jgiOCY3/jh2OHo4Qjh+OQo41jjCONI5K////////jkeOSY5MjlCOSI5ZjmSOYI4qjmOOVY52jnKOfI6BjoeOhY6EjouOio6TjpGOlI6ZjqqOoY6sjrCOxo6xjr6OxY7IjsuO247jjvyO+47rjv6PCo8FjxWPEo8ZjxOPHI8fjxuPDI8mjzOPO485j0WPQo8+j0yPSY9Gj06PV49c//+PYo9jj2SPnI+fj6OPrY+vj7eP2o/lj+KP6o/vkIeP9JAFj/mP+pARkBWQIZANkB6QFpALkCeQNpA1kDmP+JBPkFCQUZBSkA6QSZA+kFaQWJBekGiQb5B2lqiQcpCCkH2QgZCAkIqQiZCPkKiQr5CxkLWQ4pDkYkiQ25ECkRKRGZEykTCRSpFWkViRY5FlkWmRc5FykYuRiZGCkaKRq5GvkaqRtZG0kbqRwJHBkcmRy5HQkdaR35HhkduR/JH1kfaSHpH/khSSLJIVkhGSXpJXkkWSSZJkkkiSlZI/kkuSUJKckpaSk5KbklqSz5K5kreS6ZMPkvqTRJMu////////kxmTIpMakyOTOpM1kzuTXJNgk3yTbpNWk7CTrJOtk5STuZPWk9eT6JPlk9iTw5Pdk9CTyJPklBqUFJQTlAOUB5QQlDaUK5Q1lCGUOpRBlFKURJRblGCUYpRelGqSKZRwlHWUd5R9lFqUfJR+lIGUf5WClYeVipWUlZaVmJWZ//+VoJWolaeVrZW8lbuVuZW+lcpv9pXDlc2VzJXVldSV1pXcleGV5ZXiliGWKJYuli+WQpZMlk+WS5Z3llyWXpZdll+WZpZylmyWjZaYlpWWl5aqlqeWsZaylrCWtJa2lriWuZbOlsuWyZbNiU2W3JcNltWW+ZcElwaXCJcTlw6XEZcPlxaXGZcklyqXMJc5lz2XPpdEl0aXSJdCl0mXXJdgl2SXZpdoUtKXa5dxl3mXhZd8l4GXepeGl4uXj5eQl5yXqJeml6OXs5e0l8OXxpfIl8uX3Jftn0+X8nrfl/aX9ZgPmAyYOJgkmCGYN5g9mEaYT5hLmGuYb5hw////////mHGYdJhzmKqYr5ixmLaYxJjDmMaY6ZjrmQOZCZkSmRSZGJkhmR2ZHpkkmSCZLJkumT2ZPplCmUmZRZlQmUuZUZlSmUyZVZmXmZiZpZmtma6ZvJnfmduZ3ZnYmdGZ7ZnumfGZ8pn7mfiaAZoPmgWZ4poZmiuaN5pFmkKaQJpD//+aPppVmk2aW5pXml+aYpplmmSaaZprmmqarZqwmryawJrPmtGa05rUmt6a35rimuOa5prvmuua7pr0mvGa95r7mwabGJsamx+bIpsjmyWbJ5somymbKpsumy+bMptEm0ObT5tNm06bUZtYm3Sbk5uDm5GblpuXm5+boJuom7SbwJvKm7mbxpvPm9Gb0pvjm+Kb5JvUm+GcOpvym/Gb8JwVnBScCZwTnAycBpwInBKcCpwEnC6cG5wlnCScIZwwnEecMpxGnD6cWpxgnGecdpx4nOec7JzwnQmdCJzrnQOdBp0qnSadr50jnR+dRJ0VnRKdQZ0/nT6dRp1I////////nV2dXp1knVGdUJ1ZnXKdiZ2Hnaudb516nZqdpJ2pnbKdxJ3BnbuduJ26ncadz53Cndmd0534nead7Z3vnf2eGp4bnh6edZ55nn2egZ6InouejJ6SnpWekZ6dnqWeqZ64nqqerZdhnsyezp7PntCe1J7cnt6e3Z7gnuWe6J7v//+e9J72nvee+Z77nvye/Z8Hnwh2t58VnyGfLJ8+n0qfUp9Un2OfX59gn2GfZp9nn2yfap93n3Kfdp+Vn5yfoFgvaceQWXRkUdxxmf///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////w==";
private static readonly ushort[] UnicodeToQrKanji;
public static List MakeSegmentsOptimally(string text, QrCode.Ecc ecl, int minVersion = 1, int maxVersion = 40)
{
Objects.RequireNonNull(text);
Objects.RequireNonNull(ecl);
if (minVersion < 1 || minVersion > maxVersion)
{
throw new ArgumentOutOfRangeException("minVersion", "Invalid value");
}
if (maxVersion > 40)
{
throw new ArgumentOutOfRangeException("maxVersion", "Invalid value");
}
List list = null;
int[] codePoints = ToCodePoints(text);
int num = 0;
int num2 = 0;
for (int i = minVersion; i <= maxVersion; i++)
{
if (i == minVersion || i == 10 || i == 27)
{
list = MakeSegmentsOptimally(codePoints, i);
}
num = QrCode.GetNumDataCodewords(i, ecl) * 8;
num2 = QrSegment.GetTotalBits(list, i);
if (num2 != -1 && num2 <= num)
{
return list;
}
}
string message = "Segment too long";
if (num2 != -1)
{
message = $"Data length = {num2} bits, Max capacity = {num} bits";
}
throw new DataTooLongException(message);
}
private static List MakeSegmentsOptimally(IReadOnlyList codePoints, int version)
{
if (codePoints.Count == 0)
{
return new List();
}
QrSegment.Mode[] charModes = ComputeCharacterModes(codePoints, version);
return SplitIntoSegments(codePoints, charModes);
}
private static int MeasureSegmentsOptimally(IReadOnlyList codePoints, int version)
{
if (codePoints.Count == 0)
{
return 0;
}
QrSegment.Mode[] charModes = ComputeCharacterModes(codePoints, version);
return MeasureSegments(codePoints, charModes, version);
}
private static QrSegment.Mode[] ComputeCharacterModes(IReadOnlyList codePoints, int version)
{
if (codePoints.Count == 0)
{
throw new ArgumentOutOfRangeException("codePoints");
}
QrSegment.Mode[] array = new QrSegment.Mode[4]
{
QrSegment.Mode.Byte,
QrSegment.Mode.Alphanumeric,
QrSegment.Mode.Numeric,
QrSegment.Mode.Kanji
};
int num = array.Length;
int[] array2 = new int[num];
for (int i = 0; i < num; i++)
{
array2[i] = (4 + array[i].NumCharCountBits(version)) * 6;
}
QrSegment.Mode[,] array3 = new QrSegment.Mode[codePoints.Count, num];
int[] array4 = (int[])array2.Clone();
for (int j = 0; j < codePoints.Count; j++)
{
int num2 = codePoints[j];
int[] array5 = new int[num];
array5[0] = array4[0] + CountUtf8Bytes(num2) * 8 * 6;
array3[j, 0] = array[0];
if (Enumerable.Contains("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:", (char)num2))
{
array5[1] = array4[1] + 33;
array3[j, 1] = array[1];
}
if (48 <= num2 && num2 <= 57)
{
array5[2] = array4[2] + 20;
array3[j, 2] = array[2];
}
if (IsKanji(num2))
{
array5[3] = array4[3] + 78;
array3[j, 3] = array[3];
}
for (int k = 0; k < num; k++)
{
for (int l = 0; l < num; l++)
{
int num3 = (array5[l] + 5) / 6 * 6 + array2[k];
if (array3[j, l] != null && (array3[j, k] == null || num3 < array5[k]))
{
array5[k] = num3;
array3[j, k] = array[l];
}
}
}
array4 = array5;
}
QrSegment.Mode mode = null;
int m = 0;
int num4 = 0;
for (; m < num; m++)
{
if (mode == null || array4[m] < num4)
{
num4 = array4[m];
mode = array[m];
}
}
QrSegment.Mode[] array6 = new QrSegment.Mode[codePoints.Count];
for (int num5 = array6.Length - 1; num5 >= 0; num5--)
{
for (int n = 0; n < num; n++)
{
if (array[n] == mode)
{
mode = (array6[num5] = array3[num5, n]);
break;
}
}
}
return array6;
}
private static List SplitIntoSegments(IReadOnlyList codePoints, IReadOnlyList charModes)
{
if (codePoints.Count == 0)
{
throw new ArgumentOutOfRangeException("codePoints");
}
List result = new List();
GroupConsecutiveModes(charModes, delegate(int startIndex, int endIndex, QrSegment.Mode mode)
{
string text = FromCodePoints(codePoints, startIndex, endIndex - startIndex);
if (mode == QrSegment.Mode.Byte)
{
result.Add(QrSegment.MakeBytes(Encoding.UTF8.GetBytes(text)));
}
else if (mode == QrSegment.Mode.Numeric)
{
result.Add(QrSegment.MakeNumeric(text));
}
else if (mode == QrSegment.Mode.Alphanumeric)
{
result.Add(QrSegment.MakeAlphanumeric(text));
}
else if (mode == QrSegment.Mode.Kanji)
{
result.Add(MakeKanji(text));
}
});
return result;
}
private static int MeasureSegments(IReadOnlyList codePoints, IReadOnlyList charModes, int version)
{
if (codePoints.Count == 0)
{
throw new ArgumentOutOfRangeException("codePoints");
}
int result = 0;
GroupConsecutiveModes(charModes, delegate(int startIndex, int endIndex, QrSegment.Mode mode)
{
int num;
if (mode == QrSegment.Mode.Byte)
{
num = 0;
for (int i = startIndex; i < endIndex; i++)
{
num += CountUtf8Bytes(codePoints[i]);
}
}
else
{
num = endIndex - startIndex;
}
result += QrSegment.GetTotalBits(num, mode, version);
});
return result;
}
private static string FromCodePoints(IReadOnlyList codepoints, int startIndex, int count)
{
Encoding encoding = new UTF32Encoding(!BitConverter.IsLittleEndian, byteOrderMark: false, throwOnInvalidCharacters: true);
byte[] array = new byte[count * 4];
int num = startIndex;
int num2 = 0;
while (num < startIndex + count)
{
byte[] bytes = BitConverter.GetBytes(codepoints[num]);
array[num2] = bytes[0];
array[num2 + 1] = bytes[1];
array[num2 + 2] = bytes[2];
array[num2 + 3] = bytes[3];
num++;
num2 += 4;
}
return encoding.GetString(array);
}
private static int[] ToCodePoints(string s)
{
byte[] bytes = new UTF32Encoding(!BitConverter.IsLittleEndian, byteOrderMark: false, throwOnInvalidCharacters: true).GetBytes(s);
int[] array = new int[bytes.Length / 4];
int num = 0;
int num2 = 0;
while (num < bytes.Length)
{
array[num2] = BitConverter.ToInt32(bytes, num);
num += 4;
num2++;
}
return array;
}
private static int CountUtf8Bytes(int cp)
{
if (cp < 0)
{
throw new ArgumentOutOfRangeException("cp", "Invalid code point");
}
if (cp < 128)
{
return 1;
}
if (cp < 2048)
{
return 2;
}
if (cp < 65536)
{
return 3;
}
if (cp < 1114112)
{
return 4;
}
throw new ArgumentOutOfRangeException("cp", "Invalid code point");
}
public static QrSegment MakeKanji(string text)
{
Objects.RequireNonNull(text);
BitArray bitArray = new BitArray(0);
foreach (ushort item in text.Select((char t) => UnicodeToQrKanji[(uint)t]))
{
if (item == ushort.MaxValue)
{
throw new ArgumentOutOfRangeException("text", "String contains non-kanji-mode characters");
}
bitArray.AppendBits(item, 13);
}
return new QrSegment(QrSegment.Mode.Kanji, text.Length, bitArray);
}
public static bool IsEncodableAsKanji(string text)
{
Objects.RequireNonNull(text);
return text.All((char t) => IsKanji(t));
}
private static bool IsKanji(int c)
{
if (c < UnicodeToQrKanji.Length)
{
return UnicodeToQrKanji[c] != ushort.MaxValue;
}
return false;
}
static QrSegmentAdvanced()
{
UnicodeToQrKanji = new ushort[65536];
for (int i = 0; i < UnicodeToQrKanji.Length; i++)
{
UnicodeToQrKanji[i] = ushort.MaxValue;
}
byte[] array = Convert.FromBase64String("MAAwATAC/wz/DjD7/xr/G/8f/wEwmzCcALT/QACo/z7/4/8/MP0w/jCdMJ4wA07dMAUwBjAHMPwgFSAQ/w8AXDAcIBb/XCAmICUgGCAZIBwgHf8I/wkwFDAV/zv/Pf9b/10wCDAJMAowCzAMMA0wDjAPMBAwEf8LIhIAsQDX//8A9/8dImD/HP8eImYiZyIeIjQmQiZAALAgMiAzIQP/5f8EAKIAo/8F/wP/Bv8K/yAApyYGJgUlyyXPJc4lxyXGJaEloCWzJbIlvSW8IDswEiGSIZAhkSGTMBP/////////////////////////////IggiCyKGIocigiKDIioiKf////////////////////8iJyIoAKwh0iHUIgAiA/////////////////////////////8iICKlIxIiAiIHImEiUiJqImsiGiI9Ih0iNSIrIiz//////////////////yErIDAmbyZtJmogICAhALb//////////yXv/////////////////////////////////////////////////xD/Ef8S/xP/FP8V/xb/F/8Y/xn///////////////////8h/yL/I/8k/yX/Jv8n/yj/Kf8q/yv/LP8t/y7/L/8w/zH/Mv8z/zT/Nf82/zf/OP85/zr///////////////////9B/0L/Q/9E/0X/Rv9H/0j/Sf9K/0v/TP9N/07/T/9Q/1H/Uv9T/1T/Vf9W/1f/WP9Z/1r//////////zBBMEIwQzBEMEUwRjBHMEgwSTBKMEswTDBNME4wTzBQMFEwUjBTMFQwVTBWMFcwWDBZMFowWzBcMF0wXjBfMGAwYTBiMGMwZDBlMGYwZzBoMGkwajBrMGwwbTBuMG8wcDBxMHIwczB0MHUwdjB3MHgweTB6MHswfDB9MH4wfzCAMIEwgjCDMIQwhTCGMIcwiDCJMIowizCMMI0wjjCPMJAwkTCSMJP/////////////////////////////////////MKEwojCjMKQwpTCmMKcwqDCpMKowqzCsMK0wrjCvMLAwsTCyMLMwtDC1MLYwtzC4MLkwujC7MLwwvTC+ML8wwDDBMMIwwzDEMMUwxjDHMMgwyTDKMMswzDDNMM4wzzDQMNEw0jDTMNQw1TDWMNcw2DDZMNow2zDcMN0w3jDf//8w4DDhMOIw4zDkMOUw5jDnMOgw6TDqMOsw7DDtMO4w7zDwMPEw8jDzMPQw9TD2/////////////////////wORA5IDkwOUA5UDlgOXA5gDmQOaA5sDnAOdA54DnwOgA6EDowOkA6UDpgOnA6gDqf////////////////////8DsQOyA7MDtAO1A7YDtwO4A7kDugO7A7wDvQO+A78DwAPBA8MDxAPFA8YDxwPIA8n/////////////////////////////////////////////////////////////////////////////////////////////////////////////BBAEEQQSBBMEFAQVBAEEFgQXBBgEGQQaBBsEHAQdBB4EHwQgBCEEIgQjBCQEJQQmBCcEKAQpBCoEKwQsBC0ELgQv////////////////////////////////////////BDAEMQQyBDMENAQ1BFEENgQ3BDgEOQQ6BDsEPAQ9//8EPgQ/BEAEQQRCBEMERARFBEYERwRIBEkESgRLBEwETQROBE///////////////////////////////////yUAJQIlDCUQJRglFCUcJSwlJCU0JTwlASUDJQ8lEyUbJRclIyUzJSslOyVLJSAlLyUoJTclPyUdJTAlJSU4JUL//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////06cVRZaA5Y/VMBhG2MoWfaQIoR1gxx6UGCqY+FuJWXthGaCppv1aJNXJ2WhYnFbm1nQhnuY9H1ifb6bjmIWfJ+It1uJXrVjCWaXaEiVx5eNZ09O5U8KT01PnVBJVvJZN1nUWgFcCWDfYQ9hcGYTaQVwunVPdXB5+32tfe+Aw4QOiGOLApBVkHpTO06VTqVX34CykMF4704AWPFuopA4ejKDKIKLnC9RQVNwVL1U4VbgWftfFZjybeuA5IUt////////lmKWcJagl/tUC1PzW4dwz3+9j8KW6FNvnVx6uk4ReJOB/G4mVhhVBGsdhRqcO1nlU6ltZnTclY9WQk6RkEuW8oNPmQxT4VW2WzBfcWYgZvNoBGw4bPNtKXRbdsh6Tpg0gvGIW4pgku1tsnWrdsqZxWCmiwGNipWyaY5TrVGG//9XElgwWURbtF72YChjqWP0bL9vFHCOcRRxWXHVcz9+AYJ2gtGFl5BgkludG1hpZbxsWnUlUflZLlllX4Bf3GK8ZfpqKmsna7Rzi3/BiVadLJ0OnsRcoWyWg3tRBFxLYbaBxmh2cmFOWU/6U3hgaW4pek+X804LUxZO7k9VTz1PoU9zUqBT71YJWQ9awVu2W+F50WaHZ5xntmtMbLNwa3PCeY15vno8e4eCsYLbgwSDd4Pvg9OHZoqyVimMqI/mkE6XHoaKT8Rc6GIRcll1O4Hlgr2G/ozAlsWZE5nVTstPGonjVt5YSljKXvtf62AqYJRgYmHQYhJi0GU5////////m0FmZmiwbXdwcHVMdoZ9dYKlh/mVi5aOjJ1R8VK+WRZUs1uzXRZhaGmCba94jYTLiFeKcpOnmrhtbJmohtlXo2f/hs6SDlKDVodUBF7TYuFkuWg8aDhru3NyeLp6a4maidKNa48DkO2Vo5aUl2lbZlyzaX2YTZhOY5t7IGor//9qf2i2nA1vX1JyVZ1gcGLsbTtuB27RhFuJEI9EThScOVP2aRtqOpeEaCpRXHrDhLKR3JOMVludKGgigwWEMXylUgiCxXTmTn5Pg1GgW9JSClLYUudd+1WaWCpZ5luMW5hb215yXnlgo2EfYWNhvmPbZWJn0WhTaPprPmtTbFdvIm+Xb0V0sHUYduN3C3r/e6F8IX3pfzZ/8ICdgmaDnomzisyMq5CElFGVk5WRlaKWZZfTmSiCGE44VCtcuF3Mc6l2THc8XKl/640LlsGYEZhUmFhPAU8OU3FVnFZoV/pZR1sJW8RckF4MXn5fzGPuZzpl12XiZx9oy2jE////////al9eMGvFbBdsfXV/eUhbY3oAfQBfvYmPihiMtI13jsyPHZjimg6bPE6AUH1RAFmTW5xiL2KAZOxrOnKgdZF5R3+ph/uKvItwY6yDypegVAlUA1WraFRqWIpweCdndZ7NU3RbooEahlCQBk4YTkVOx08RU8pUOFuuXxNgJWVR//9nPWxCbHJs43B4dAN6dnquewh9Gnz+fWZl53JbU7tcRV3oYtJi4GMZbiCGWooxjd2S+G8BeaabWk6oTqtOrE+bT6BQ0VFHevZRcVH2U1RTIVN/U+tVrFiDXOFfN19KYC9gUGBtYx9lWWpLbMFywnLtd++A+IEFggiFTpD3k+GX/5lXmlpO8FHdXC1mgWltXEBm8ml1c4loUHyBUMVS5FdHXf6TJmWkayNrPXQ0eYF5vXtLfcqCuYPMiH+JX4s5j9GR0VQfkoBOXVA2U+VTOnLXc5Z36YLmjq+ZxpnImdJRd2Eahl5VsHp6UHZb05BHloVOMmrbkedcUVxI////////Y5h6n2yTl3SPYXqqcYqWiHyCaBd+cGhRk2xS8lQbhauKE3+kjs2Q4VNmiIh5QU/CUL5SEVFEVVNXLXPqV4tZUV9iX4RgdWF2YWdhqWOyZDplbGZvaEJuE3Vmej18+31MfZl+S39rgw6DSobNigiKY4tmjv2YGp2PgriPzpvo//9Sh2IfZINvwJaZaEFQkWsgbHpvVHp0fVCIQIojZwhO9lA5UCZQZVF8UjhSY1WnVw9YBVrMXvphsmH4YvNjcmkcailyfXKscy54FHhvfXl3DICpiYuLGYzijtKQY5N1lnqYVZoTnnhRQ1OfU7Nee18mbhtukHOEc/59Q4I3igCK+pZQTk5QC1PkVHxW+lnRW2Rd8V6rXydiOGVFZ69uVnLQfMqItIChgOGD8IZOioeN6JI3lseYZ58TTpROkk8NU0hUSVQ+Wi9fjF+hYJ9op2qOdFp4gYqeiqSLd5GQTl6byU6kT3xPr1AZUBZRSVFsUp9SuVL+U5pT41QR////////VA5ViVdRV6JZfVtUW11bj13lXedd9154XoNeml63XxhgUmFMYpdi2GOnZTtmAmZDZvRnbWghaJdpy2xfbSptaW4vbp11MnaHeGx6P3zgfQV9GH1efbGAFYADgK+AsYFUgY+CKoNSiEyIYYsbjKKM/JDKkXWScXg/kvyVpJZN//+YBZmZmtidO1JbUqtT91QIWNVi92/gjGqPX565UUtSO1RKVv16QJF3nWCe0nNEbwmBcHURX/1g2pqoctuPvGtkmANOylbwV2RYvlpaYGhhx2YPZgZoOWixbfd11X06gm6bQk6bT1BTyVUGXW9d5l3uZ/tsmXRzeAKKUJOWiN9XUF6nYytQtVCsUY1nAFTJWF5Zu1uwX2liTWOhaD1rc24IcH2Rx3KAeBV4JnltZY59MIPciMGPCZabUmRXKGdQf2qMoVG0V0KWKlg6aYqAtFSyXQ5X/HiVnfpPXFJKVItkPmYoZxRn9XqEe1Z9IpMvaFybrXs5UxlRilI3////////W99i9mSuZOZnLWu6hamW0XaQm9ZjTJMGm6t2v2ZSTglQmFPCXHFg6GSSZWNoX3Hmc8p1I3uXfoKGlYuDjNuReJkQZaxmq2uLTtVO1E86T39SOlP4U/JV41bbWOtZy1nJWf9bUFxNXgJeK1/XYB1jB2UvW1xlr2W9ZehnnWti//9re2wPc0V5SXnBfPh9GX0rgKKBAoHziZaKXoppimaKjIrujMeM3JbMmPxrb06LTzxPjVFQW1db+mFIYwFmQmshbstsu3I+dL111HjBeTqADIAzgeqElI+ebFCef18Pi1idK3r6jvhbjZbrTgNT8Vf3WTFayVukYIluf28Gdb6M6lufhQB74FByZ/SCnVxhhUp+HoIOUZlcBGNojWZlnHFueT59F4AFix2OypBuhseQqlAfUvpcOmdTcHxyNZFMkciTK4LlW8JfMWD5TjtT1luIYktnMWuKculz4HougWuNo5FSmZZRElPXVGpb/2OIajl9rJcAVtpTzlRo////////W5dcMV3eT+5hAWL+bTJ5wHnLfUJ+TX/Sge2CH4SQiEaJcouQjnSPL5AxkUuRbJbGkZxOwE9PUUVTQV+TYg5n1GxBbgtzY34mkc2Sg1PUWRlbv23ReV1+LnybWH5xn1H6iFOP8E/KXPtmJXeseuOCHJn/UcZfqmXsaW9riW3z//9ulm9kdv59FF3hkHWRh5gGUeZSHWJAZpFm2W4aXrZ90n9yZviFr4X3ivhSqVPZWXNej1+QYFWS5JZkULdRH1LdUyBTR1PsVOhVRlUxVhdZaFm+WjxbtVwGXA9cEVwaXoReil7gX3Bif2KEYttjjGN3ZgdmDGYtZnZnfmiiah9qNWy8bYhuCW5YcTxxJnFndcd3AXhdeQF5ZXnweuB7EXynfTmAloPWhIuFSYhdiPOKH4o8ilSKc4xhjN6RpJJmk36UGJacl5hOCk4ITh5OV1GXUnBXzlg0WMxbIl44YMVk/mdhZ1ZtRHK2dXN6Y4S4i3KRuJMgVjFX9Jj+////////Yu1pDWuWce1+VIB3gnKJ5pjfh1WPsVw7TzhP4U+1VQdaIFvdW+lfw2FOYy9lsGZLaO5pm214bfF1M3W5dx95XnnmfTOB44KvhaqJqoo6jquPm5Aykd2XB066TsFSA1h1WOxcC3UaXD2BTooKj8WWY5dteyWKz5gIkWJW81Oo//+QF1Q5V4JeJWOobDRwindhfIt/4IhwkEKRVJMQkxiWj3RemsRdB11pZXBnoo2olttjbmdJaRmDxZgXlsCI/m+EZHpb+E4WcCx1XWYvUcRSNlLiWdNfgWAnYhBlP2V0Zh9mdGjyaBZrY24FcnJ1H3bbfL6AVljwiP2Jf4qgipOKy5AdkZKXUpdZZYl6DoEGlrteLWDcYhplpWYUZ5B383pNfE1+PoEKjKyNZI3hjl94qVIHYtljpWRCYpiKLXqDe8CKrJbqfXaCDIdJTtlRSFNDU2Bbo1wCXBZd3WImYkdksGgTaDRsyW1FbRdn029ccU5xfWXLen97rX3a////////fkp/qIF6ghuCOYWmim6Mzo31kHiQd5KtkpGVg5uuUk1VhG84cTZRaHmFflWBs3zOVkxYUVyoY6pm/mb9aVpy2XWPdY55DnlWed98l30gfUSGB4o0ljuQYZ8gUOdSdVPMU+JQCVWqWO5ZT3I9W4tcZFMdYONg82NcY4NjP2O7//9kzWXpZvld42nNaf1vFXHlTol16Xb4epN8333PfZyAYYNJg1iEbIS8hfuIxY1wkAGQbZOXlxyaElDPWJdhjoHThTWNCJAgT8NQdFJHU3Ngb2NJZ19uLI2zkB9P11xejMplz32aU1KIllF2Y8NbWFtrXApkDWdRkFxO1lkaWSpscIpRVT5YFVmlYPBiU2fBgjVpVZZAmcSaKE9TWAZb/oAQXLFeL1+FYCBhS2I0Zv9s8G7egM6Bf4LUiIuMuJAAkC6Wip7bm9tO41PwWSd7LJGNmEyd+W7dcCdTU1VEW4ViWGKeYtNsom/vdCKKF5Q4b8GK/oM4UeeG+FPq////////U+lPRpBUj7BZaoExXf166o+/aNqMN3L4nEhqPYqwTjlTWFYGV2ZixWOiZeZrTm3hbltwrXfteu97qn27gD2AxobLipWTW1bjWMdfPmWtZpZqgGu1dTeKx1Akd+VXMF8bYGVmemxgdfR6Gn9ugfSHGJBFmbN7yXVcevl7UYTE//+QEHnpepKDNlrhd0BOLU7yW5lf4GK9Zjxn8WzohmuId4o7kU6S85nQahdwJnMqgueEV4yvTgFRRlHLVYtb9V4WXjNegV8UXzVfa1+0YfJjEWaiZx1vbnJSdTp3OoB0gTmBeId2ir+K3I2FjfOSmpV3mAKc5VLFY1d29GcVbIhzzYzDk66Wc20lWJxpDmnMj/2TmnXbkBpYWmgCY7Rp+09Dbyxn2I+7hSZ9tJNUaT9vcFdqWPdbLH0scipUCpHjnbROrU9OUFxQdVJDjJ5USFgkW5peHV6VXq1e918fYIxitWM6Y9Bor2xAeId5jnoLfeCCR4oCiuaORJAT////////kLiRLZHYnw5s5WRYZOJldW70doR7G5Bpk9FuulTyX7lkpI9Nj+2SRFF4WGtZKVxVXpdt+36PdRyMvI7imFtwuU8da79vsXUwlvtRTlQQWDVYV1msXGBfkmWXZ1xuIXZ7g9+M7ZAUkP2TTXgleDpSql6mVx9ZdGASUBJRWlGs//9RzVIAVRBYVFhYWVdblVz2XYtgvGKVZC1ncWhDaLxo33bXbdhub22bcG9xyF9Tddh5d3tJe1R7UnzWfXFSMIRjhWmF5IoOiwSMRo4PkAOQD5QZlnaYLZowldhQzVLVVAxYAlwOYadknm0ed7N65YD0hASQU5KFXOCdB1M/X5dfs22ccnl3Y3m/e+Rr0nLsiq1oA2phUfh6gWk0XEqc9oLrW8WRSXAeVnhcb2DHZWZsjIxakEGYE1RRZseSDVlIkKNRhU5NUeqFmYsOcFhjepNLaWKZtH4EdXdTV2lgjt+W42xdToxcPF8Qj+lTAozRgImGeV7/ZeVOc1Fl////////WYJcP5fuTvtZil/Nio1v4XmweWJb54RxcytxsV50X/Vje2SaccN8mE5DXvxOS1fcVqJgqW/DfQ2A/YEzgb+PsomXhqRd9GKKZK2Jh2d3bOJtPnQ2eDRaRn91gq2ZrE/zXsNi3WOSZVdnb3bDckyAzIC6jymRTVANV/lakmiF//9pc3Fkcv2Mt1jyjOCWapAZh3955HfnhClPL1JlU1pizWfPbMp2fXuUfJWCNoWEj+tm3W8gcgZ+G4OrmcGeplH9e7F4cnu4gId7SGroXmGAjHVRdWBRa5Jibox2epGXmupPEH9wYpx7T5WlnOlWelhZhuSWvE80UiRTSlPNU9teBmQsZZFnf2w+bE5ySHKvc+11VH5BgiyF6Yype8SRxnFpmBKY72M9Zml1anbkeNCFQ4buUypTUVQmWYNeh198YLJiSWJ5YqtlkGvUbMx1snaueJF52H3Lf3eApYirirmMu5B/l16Y22oLfDhQmVw+X65nh2vYdDV3CX+O////////nztnynoXUzl1i5rtX2aBnYPxgJhfPF/FdWJ7RpA8aGdZ61qbfRB2fossT/VfamoZbDdvAnTieWiIaIpVjHle32PPdcV50oLXkyiS8oSchu2cLVTBX2xljG1ccBWMp4zTmDtlT3T2Tg1O2FfgWStaZlvMUaheA16cYBZidmV3//9lp2ZubW5yNnsmgVCBmoKZi1yMoIzmjXSWHJZET65kq2tmgh6EYYVqkOhcAWlTmKiEeoVXTw9Sb1+pXkVnDXmPgXmJB4mGbfVfF2JVbLhOz3Jpm5JSBlQ7VnRYs2GkYm5xGllufIl83n0blvBlh4BeThlPdVF1WEBeY15zXwpnxE4mhT2ViZZbfHOYAVD7WMF2VninUiV3pYURe4ZQT1kJckd7x33oj7qP1JBNT79SyVopXwGXrU/dgheS6lcDY1VraXUriNyPFHpCUt9Yk2FVYgpmrmvNfD+D6VAjT/hTBVRGWDFZSVudXPBc710pXpZisWNnZT5luWcL////////bNVs4XD5eDJ+K4DegrOEDITshwKJEooqjEqQppLSmP2c851sTk9OoVCNUlZXSlmoXj1f2F/ZYj9mtGcbZ9Bo0lGSfSGAqoGoiwCMjIy/kn6WMlQgmCxTF1DVU1xYqGSyZzRyZ3dmekaR5lLDbKFrhlgAXkxZVGcsf/tR4XbG//9kaXjom1Seu1fLWblmJ2eaa85U6WnZXlWBnGeVm6pn/pxSaF1Opk/jU8hiuWcrbKuPxE+tfm2ev04HYWJugG8rhRNUc2cqm0Vd83uVXKxbxoccbkqE0XoUgQhZmXyNbBF3IFLZWSJxIXJfd9uXJ51haQtaf1oYUaVUDVR9Zg5234/3kpic9Fnqcl1uxVFNaMl9v33sl2KeumR4aiGDAlmEW19r23MbdvJ9soAXhJlRMmcontl27mdiUv+ZBVwkYjt8foywVU9gtn0LlYBTAU5fUbZZHHI6gDaRzl8ld+JThF95fQSFrIozjo2XVmfzha6UU2EJYQhsuXZS////////iu2POFUvT1FRKlLHU8tbpV59YKBhgmPWZwln2m5nbYxzNnM3dTF5UIjVipiQSpCRkPWWxIeNWRVOiE9ZTg6KiY8/mBBQrV58WZZbuV64Y9pj+mTBZtxpSmnYbQtutnGUdSh6r3+KgACESYTJiYGLIY4KkGWWfZkKYX5ikWsy//9sg210f8x//G3Af4WHuoj4Z2WDsZg8lvdtG31hhD2Rak5xU3VdUGsEb+uFzYYtiadSKVQPXGVnTmiodAZ0g3XiiM+I4ZHMluKWeF+Lc4d6y4ROY6B1ZVKJbUFunHQJdVl4a3ySloZ63J+NT7ZhbmXFhlxOhk6uUNpOIVHMW+5lmWiBbbxzH3ZCd616HHzngm+K0pB8kc+WdZgYUpt90VArU5hnl23LcdB0M4HojyqWo5xXnp90YFhBbZl9L5heTuRPNk+LUbdSsV26YBxzsnk8gtOSNJa3lvaXCp6Xn2Jmpmt0UhdSo3DIiMJeyWBLYZBvI3FJfD599IBv////////hO6QI5MsVEKbb2rTcImMwo3vlzJStFpBXspfBGcXaXxplG1qbw9yYnL8e+2AAYB+h0uQzlFtnpN5hICLkzKK1lAtVIyKcWtqjMSBB2DRZ6Cd8k6ZTpicEIprhcGFaGkAbn54l4FV/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////18MThBOFU4qTjFONk48Tj9OQk5WTlhOgk6FjGtOioISXw1Ojk6eTp9OoE6iTrBOs062Ts5OzU7ETsZOwk7XTt5O7U7fTvdPCU9aTzBPW09dT1dPR092T4hPj0+YT3tPaU9wT5FPb0+GT5ZRGE/UT99Pzk/YT9tP0U/aT9BP5E/lUBpQKFAUUCpQJVAFTxxP9lAhUClQLE/+T+9QEVAGUENQR2cDUFVQUFBIUFpQVlBsUHhQgFCaUIVQtFCy////////UMlQylCzUMJQ1lDeUOVQ7VDjUO5Q+VD1UQlRAVECURZRFVEUURpRIVE6UTdRPFE7UT9RQFFSUUxRVFFievhRaVFqUW5RgFGCVthRjFGJUY9RkVGTUZVRllGkUaZRolGpUapRq1GzUbFRslGwUbVRvVHFUclR21HghlVR6VHt//9R8FH1Uf5SBFILUhRSDlInUipSLlIzUjlST1JEUktSTFJeUlRSalJ0UmlSc1J/Un1SjVKUUpJScVKIUpGPqI+nUqxSrVK8UrVSwVLNUtdS3lLjUuaY7VLgUvNS9VL4UvlTBlMIdThTDVMQUw9TFVMaUyNTL1MxUzNTOFNAU0ZTRU4XU0lTTVHWU15TaVNuWRhTe1N3U4JTllOgU6ZTpVOuU7BTtlPDfBKW2VPfZvxx7lPuU+hT7VP6VAFUPVRAVCxULVQ8VC5UNlQpVB1UTlSPVHVUjlRfVHFUd1RwVJJUe1SAVHZUhFSQVIZUx1SiVLhUpVSsVMRUyFSo////////VKtUwlSkVL5UvFTYVOVU5lUPVRRU/VTuVO1U+lTiVTlVQFVjVUxVLlVcVUVVVlVXVThVM1VdVZlVgFSvVYpVn1V7VX5VmFWeVa5VfFWDValVh1WoVdpVxVXfVcRV3FXkVdRWFFX3VhZV/lX9VhtV+VZOVlBx31Y0VjZWMlY4//9Wa1ZkVi9WbFZqVoZWgFaKVqBWlFaPVqVWrla2VrRWwla8VsFWw1bAVshWzlbRVtNW11buVvlXAFb/VwRXCVcIVwtXDVcTVxhXFlXHVxxXJlc3VzhXTlc7V0BXT1dpV8BXiFdhV39XiVeTV6BXs1ekV6pXsFfDV8ZX1FfSV9NYClfWV+NYC1gZWB1YclghWGJYS1hwa8BYUlg9WHlYhVi5WJ9Yq1i6WN5Yu1i4WK5YxVjTWNFY11jZWNhY5VjcWORY31jvWPpY+Vj7WPxY/VkCWQpZEFkbaKZZJVksWS1ZMlk4WT560llVWVBZTllaWVhZYllgWWdZbFlp////////WXhZgVmdT15Pq1mjWbJZxlnoWdxZjVnZWdpaJVofWhFaHFoJWhpaQFpsWklaNVo2WmJaalqaWrxavlrLWsJavVrjWtda5lrpWtZa+lr7WwxbC1sWWzJa0FsqWzZbPltDW0VbQFtRW1VbWltbW2VbaVtwW3NbdVt4ZYhbeluA//9bg1umW7hbw1vHW8lb1FvQW+Rb5lviW95b5VvrW/Bb9lvzXAVcB1wIXA1cE1wgXCJcKFw4XDlcQVxGXE5cU1xQXE9bcVxsXG5OYlx2XHlcjFyRXJRZm1yrXLtctly8XLdcxVy+XMdc2VzpXP1c+lztXYxc6l0LXRVdF11cXR9dG10RXRRdIl0aXRldGF1MXVJdTl1LXWxdc112XYddhF2CXaJdnV2sXa5dvV2QXbddvF3JXc1d013SXdZd213rXfJd9V4LXhpeGV4RXhteNl43XkReQ15AXk5eV15UXl9eYl5kXkdedV52XnqevF5/XqBewV7CXshe0F7P////////XtZe417dXtpe217iXuFe6F7pXuxe8V7zXvBe9F74Xv5fA18JX11fXF8LXxFfFl8pXy1fOF9BX0hfTF9OXy9fUV9WX1dfWV9hX21fc193X4Nfgl9/X4pfiF+RX4dfnl+ZX5hfoF+oX61fvF/WX/tf5F/4X/Ff3WCzX/9gIWBg//9gGWAQYClgDmAxYBtgFWArYCZgD2A6YFpgQWBqYHdgX2BKYEZgTWBjYENgZGBCYGxga2BZYIFgjWDnYINgmmCEYJtglmCXYJJgp2CLYOFguGDgYNNgtF/wYL1gxmC1YNhhTWEVYQZg9mD3YQBg9GD6YQNhIWD7YPFhDWEOYUdhPmEoYSdhSmE/YTxhLGE0YT1hQmFEYXNhd2FYYVlhWmFrYXRhb2FlYXFhX2FdYVNhdWGZYZZhh2GsYZRhmmGKYZFhq2GuYcxhymHJYfdhyGHDYcZhumHLf3lhzWHmYeNh9mH6YfRh/2H9Yfxh/mIAYghiCWINYgxiFGIb////////Yh5iIWIqYi5iMGIyYjNiQWJOYl5iY2JbYmBiaGJ8YoJiiWJ+YpJik2KWYtRig2KUYtdi0WK7Ys9i/2LGZNRiyGLcYsxiymLCYsdim2LJYwxi7mLxYydjAmMIYu9i9WNQYz5jTWQcY09jlmOOY4Bjq2N2Y6Njj2OJY59jtWNr//9jaWO+Y+ljwGPGY+NjyWPSY/ZjxGQWZDRkBmQTZCZkNmUdZBdkKGQPZGdkb2R2ZE5lKmSVZJNkpWSpZIhkvGTaZNJkxWTHZLtk2GTCZPFk54IJZOBk4WKsZONk72UsZPZk9GTyZPplAGT9ZRhlHGUFZSRlI2UrZTRlNWU3ZTZlOHVLZUhlVmVVZU1lWGVeZV1lcmV4ZYJlg4uKZZtln2WrZbdlw2XGZcFlxGXMZdJl22XZZeBl4WXxZ3JmCmYDZftnc2Y1ZjZmNGYcZk9mRGZJZkFmXmZdZmRmZ2ZoZl9mYmZwZoNmiGaOZolmhGaYZp1mwWa5Zslmvma8////////ZsRmuGbWZtpm4GY/ZuZm6WbwZvVm92cPZxZnHmcmZyeXOGcuZz9nNmdBZzhnN2dGZ15nYGdZZ2NnZGeJZ3BnqWd8Z2pnjGeLZ6ZnoWeFZ7dn72e0Z+xns2fpZ7hn5GfeZ91n4mfuZ7lnzmfGZ+dqnGgeaEZoKWhAaE1oMmhO//9os2graFloY2h3aH9on2iPaK1olGidaJtog2quaLlodGi1aKBoumkPaI1ofmkBaMppCGjYaSJpJmjhaQxozWjUaOdo1Wk2aRJpBGjXaONpJWj5aOBo72koaSppGmkjaSFoxml5aXdpXGl4aWtpVGl+aW5pOWl0aT1pWWkwaWFpXmldaYFpammyaa5p0Gm/acFp02m+ac5b6GnKad1pu2nDaadqLmmRaaBpnGmVabRp3mnoagJqG2n/awpp+WnyaedqBWmxah5p7WoUaetqCmoSasFqI2oTakRqDGpyajZqeGpHamJqWWpmakhqOGoiapBqjWqgaoRqomqj////////apeGF2q7asNqwmq4arNqrGreatFq32qqatpq6mr7awWGFmr6axJrFpsxax9rOGs3dtxrOZjua0drQ2tJa1BrWWtUa1trX2tha3hreWt/a4BrhGuDa41rmGuVa55rpGuqa6trr2uya7Frs2u3a7xrxmvLa9Nr32vsa+tr82vv//+evmwIbBNsFGwbbCRsI2xebFVsYmxqbIJsjWyabIFsm2x+bGhsc2ySbJBsxGzxbNNsvWzXbMVs3WyubLFsvmy6bNts72zZbOptH4hNbTZtK209bThtGW01bTNtEm0MbWNtk21kbVpteW1ZbY5tlW/kbYVt+W4VbgpttW3HbeZtuG3Gbext3m3Mbeht0m3Fbfpt2W3kbdVt6m3ubi1ubm4ubhlucm5fbj5uI25rbitudm5Nbh9uQ246bk5uJG7/bh1uOG6CbqpumG7Jbrdu0269bq9uxG6ybtRu1W6PbqVuwm6fb0FvEXBMbuxu+G7+bz9u8m8xbu9vMm7M////////bz5vE273b4Zvem94b4FvgG9vb1tv829tb4JvfG9Yb45vkW/Cb2Zvs2+jb6FvpG+5b8Zvqm/fb9Vv7G/Ub9hv8W/ub9twCXALb/pwEXABcA9v/nAbcBpvdHAdcBhwH3AwcD5wMnBRcGNwmXCScK9w8XCscLhws3CucN9wy3Dd//9w2XEJcP1xHHEZcWVxVXGIcWZxYnFMcVZxbHGPcftxhHGVcahxrHHXcblxvnHScclx1HHOceBx7HHncfVx/HH5cf9yDXIQchtyKHItcixyMHIycjtyPHI/ckByRnJLclhydHJ+coJygXKHcpJylnKicqdyuXKycsNyxnLEcs5y0nLicuBy4XL5cvdQD3MXcwpzHHMWcx1zNHMvcylzJXM+c05zT57Yc1dzanNoc3BzeHN1c3tzenPIc7NzznO7c8Bz5XPuc950onQFdG90JXP4dDJ0OnRVdD90X3RZdEF0XHRpdHB0Y3RqdHZ0fnSLdJ50p3TKdM901HPx////////dOB043TndOl07nTydPB08XT4dPd1BHUDdQV1DHUOdQ11FXUTdR51JnUsdTx1RHVNdUp1SXVbdUZ1WnVpdWR1Z3VrdW11eHV2dYZ1h3V0dYp1iXWCdZR1mnWddaV1o3XCdbN1w3W1db11uHW8dbF1zXXKddJ12XXjdd51/nX///91/HYBdfB1+nXydfN2C3YNdgl2H3YndiB2IXYidiR2NHYwdjt2R3ZIdkZ2XHZYdmF2YnZodml2anZndmx2cHZydnZ2eHZ8doB2g3aIdot2jnaWdpN2mXaadrB2tHa4drl2unbCds121nbSdt524Xbldud26oYvdvt3CHcHdwR3KXckdx53JXcmdxt3N3c4d0d3Wndod2t3W3dld393fnd5d453i3eRd6B3nnewd7Z3uXe/d7x3vXe7d8d3zXfXd9p33Hfjd+53/HgMeBJ5JnggeSp4RXiOeHR4hnh8eJp4jHijeLV4qniveNF4xnjLeNR4vni8eMV4ynjs////////eOd42nj9ePR5B3kSeRF5GXkseSt5QHlgeVd5X3laeVV5U3l6eX95inmdeaefS3mqea55s3m5ebp5yXnVeed57HnheeN6CHoNehh6GXogeh95gHoxejt6Pno3ekN6V3pJemF6Ynppn516cHp5en16iHqXepV6mHqWeql6yHqw//96tnrFesR6v5CDesd6ynrNes961XrTetl62nrdeuF64nrmeu168HsCew97CnsGezN7GHsZex57NXsoezZ7UHt6ewR7TXsLe0x7RXt1e2V7dHtne3B7cXtse257nXuYe597jXuce5p7i3uSe497XXuZe8t7wXvMe897tHvGe9176XwRfBR75nvlfGB8AHwHfBN783v3fBd8DXv2fCN8J3wqfB98N3wrfD18THxDfFR8T3xAfFB8WHxffGR8VnxlfGx8dXyDfJB8pHytfKJ8q3yhfKh8s3yyfLF8rny5fL18wHzFfMJ82HzSfNx84ps7fO988nz0fPZ8+n0G////////fQJ9HH0VfQp9RX1LfS59Mn0/fTV9Rn1zfVZ9Tn1yfWh9bn1PfWN9k32JfVt9j319fZt9un2ufaN9tX3Hfb19q349faJ9r33cfbh9n32wfdh93X3kfd59+33yfeF+BX4KfiN+IX4SfjF+H34Jfgt+In5GfmZ+O341fjl+Q343//9+Mn46fmd+XX5Wfl5+WX5afnl+an5pfnx+e36DfdV+fY+ufn9+iH6Jfox+kn6QfpN+lH6Wfo5+m36cfzh/On9Ff0x/TX9Of1B/UX9Vf1R/WH9ff2B/aH9pf2d/eH+Cf4Z/g3+If4d/jH+Uf55/nX+af6N/r3+yf7l/rn+2f7iLcX/Ff8Z/yn/Vf9R/4X/mf+l/83/5mNyABoAEgAuAEoAYgBmAHIAhgCiAP4A7gEqARoBSgFiAWoBfgGKAaIBzgHKAcIB2gHmAfYB/gISAhoCFgJuAk4CagK1RkICsgNuA5YDZgN2AxIDagNaBCYDvgPGBG4EpgSOBL4FL////////louBRoE+gVOBUYD8gXGBboFlgWaBdIGDgYiBioGAgYKBoIGVgaSBo4FfgZOBqYGwgbWBvoG4gb2BwIHCgbqByYHNgdGB2YHYgciB2oHfgeCB54H6gfuB/oIBggKCBYIHggqCDYIQghaCKYIrgjiCM4JAglmCWIJdglqCX4Jk//+CYoJogmqCa4IugnGCd4J4gn6CjYKSgquCn4K7gqyC4YLjgt+C0oL0gvOC+oOTgwOC+4L5gt6DBoLcgwmC2YM1gzSDFoMygzGDQIM5g1CDRYMvgyuDF4MYg4WDmoOqg5+DooOWgyODjoOHg4qDfIO1g3ODdYOgg4mDqIP0hBOD64POg/2EA4PYhAuDwYP3hAeD4IPyhA2EIoQgg72EOIUGg/uEbYQqhDyFWoSEhHeEa4SthG6EgoRphEaELIRvhHmENYTKhGKEuYS/hJ+E2YTNhLuE2oTQhMGExoTWhKGFIYT/hPSFF4UYhSyFH4UVhRSE/IVAhWOFWIVI////////hUGGAoVLhVWFgIWkhYiFkYWKhaiFbYWUhZuF6oWHhZyFd4V+hZCFyYW6hc+FuYXQhdWF3YXlhdyF+YYKhhOGC4X+hfqGBoYihhqGMIY/hk1OVYZUhl+GZ4ZxhpOGo4aphqqGi4aMhraGr4bEhsaGsIbJiCOGq4bUht6G6Ybs//+G34bbhu+HEocGhwiHAIcDhvuHEYcJhw2G+YcKhzSHP4c3hzuHJYcphxqHYIdfh3iHTIdOh3SHV4doh26HWYdTh2OHaogFh6KHn4eCh6+Hy4e9h8CH0JbWh6uHxIezh8eHxoe7h++H8ofgiA+IDYf+h/aH94gOh9KIEYgWiBWIIoghiDGINog5iCeIO4hEiEKIUohZiF6IYohriIGIfoieiHWIfYi1iHKIgoiXiJKIroiZiKKIjYikiLCIv4ixiMOIxIjUiNiI2YjdiPmJAoj8iPSI6IjyiQSJDIkKiROJQ4keiSWJKokriUGJRIk7iTaJOIlMiR2JYIle////////iWaJZIltiWqJb4l0iXeJfomDiYiJiomTiZiJoYmpiaaJrImvibKJuom9ib+JwInaidyJ3YnnifSJ+IoDihaKEIoMihuKHYolijaKQYpbilKKRopIinyKbYpsimKKhYqCioSKqIqhipGKpYqmipqKo4rEis2KworaiuuK84rn//+K5IrxixSK4IriiveK3orbiwyLB4saiuGLFosQixeLIIszl6uLJosriz6LKItBi0yLT4tOi0mLVotbi1qLa4tfi2yLb4t0i32LgIuMi46LkouTi5aLmYuajDqMQYw/jEiMTIxOjFCMVYxijGyMeIx6jIKMiYyFjIqMjYyOjJSMfIyYYh2MrYyqjL2MsoyzjK6MtozIjMGM5IzjjNqM/Yz6jPuNBI0FjQqNB40PjQ2NEJ9OjROMzY0UjRaNZ41tjXGNc42BjZmNwo2+jbqNz43ajdaNzI3bjcuN6o3rjd+N4438jgiOCY3/jh2OHo4Qjh+OQo41jjCONI5K////////jkeOSY5MjlCOSI5ZjmSOYI4qjmOOVY52jnKOfI6BjoeOhY6EjouOio6TjpGOlI6ZjqqOoY6sjrCOxo6xjr6OxY7IjsuO247jjvyO+47rjv6PCo8FjxWPEo8ZjxOPHI8fjxuPDI8mjzOPO485j0WPQo8+j0yPSY9Gj06PV49c//+PYo9jj2SPnI+fj6OPrY+vj7eP2o/lj+KP6o/vkIeP9JAFj/mP+pARkBWQIZANkB6QFpALkCeQNpA1kDmP+JBPkFCQUZBSkA6QSZA+kFaQWJBekGiQb5B2lqiQcpCCkH2QgZCAkIqQiZCPkKiQr5CxkLWQ4pDkYkiQ25ECkRKRGZEykTCRSpFWkViRY5FlkWmRc5FykYuRiZGCkaKRq5GvkaqRtZG0kbqRwJHBkcmRy5HQkdaR35HhkduR/JH1kfaSHpH/khSSLJIVkhGSXpJXkkWSSZJkkkiSlZI/kkuSUJKckpaSk5KbklqSz5K5kreS6ZMPkvqTRJMu////////kxmTIpMakyOTOpM1kzuTXJNgk3yTbpNWk7CTrJOtk5STuZPWk9eT6JPlk9iTw5Pdk9CTyJPklBqUFJQTlAOUB5QQlDaUK5Q1lCGUOpRBlFKURJRblGCUYpRelGqSKZRwlHWUd5R9lFqUfJR+lIGUf5WClYeVipWUlZaVmJWZ//+VoJWolaeVrZW8lbuVuZW+lcpv9pXDlc2VzJXVldSV1pXcleGV5ZXiliGWKJYuli+WQpZMlk+WS5Z3llyWXpZdll+WZpZylmyWjZaYlpWWl5aqlqeWsZaylrCWtJa2lriWuZbOlsuWyZbNiU2W3JcNltWW+ZcElwaXCJcTlw6XEZcPlxaXGZcklyqXMJc5lz2XPpdEl0aXSJdCl0mXXJdgl2SXZpdoUtKXa5dxl3mXhZd8l4GXepeGl4uXj5eQl5yXqJeml6OXs5e0l8OXxpfIl8uX3Jftn0+X8nrfl/aX9ZgPmAyYOJgkmCGYN5g9mEaYT5hLmGuYb5hw////////mHGYdJhzmKqYr5ixmLaYxJjDmMaY6ZjrmQOZCZkSmRSZGJkhmR2ZHpkkmSCZLJkumT2ZPplCmUmZRZlQmUuZUZlSmUyZVZmXmZiZpZmtma6ZvJnfmduZ3ZnYmdGZ7ZnumfGZ8pn7mfiaAZoPmgWZ4poZmiuaN5pFmkKaQJpD//+aPppVmk2aW5pXml+aYpplmmSaaZprmmqarZqwmryawJrPmtGa05rUmt6a35rimuOa5prvmuua7pr0mvGa95r7mwabGJsamx+bIpsjmyWbJ5somymbKpsumy+bMptEm0ObT5tNm06bUZtYm3Sbk5uDm5GblpuXm5+boJuom7SbwJvKm7mbxpvPm9Gb0pvjm+Kb5JvUm+GcOpvym/Gb8JwVnBScCZwTnAycBpwInBKcCpwEnC6cG5wlnCScIZwwnEecMpxGnD6cWpxgnGecdpx4nOec7JzwnQmdCJzrnQOdBp0qnSadr50jnR+dRJ0VnRKdQZ0/nT6dRp1I////////nV2dXp1knVGdUJ1ZnXKdiZ2Hnaudb516nZqdpJ2pnbKdxJ3BnbuduJ26ncadz53Cndmd0534nead7Z3vnf2eGp4bnh6edZ55nn2egZ6InouejJ6SnpWekZ6dnqWeqZ64nqqerZdhnsyezp7PntCe1J7cnt6e3Z7gnuWe6J7v//+e9J72nvee+Z77nvye/Z8Hnwh2t58VnyGfLJ8+n0qfUp9Un2OfX59gn2GfZp9nn2yfap93n3Kfdp+Vn5yfoFgvaceQWXRkUdxxmf///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////w==");
for (int j = 0; j < array.Length; j += 2)
{
int num = (array[j] << 8) | array[j + 1];
if (num != 65535)
{
UnicodeToQrKanji[num] = (ushort)(j / 2);
}
}
}
public static List> MakeSegmentsForMultipleCodes(string text, QrCode.Ecc ecl, int version = 29)
{
Objects.RequireNonNull(text);
Objects.RequireNonNull(ecl);
if (version < 1 || version > 40)
{
throw new ArgumentOutOfRangeException("version", "Invalid value");
}
List> list = SplitTextIntoMultipleCodes(text, ecl, version);
byte parity = CalculateParity(text);
for (int i = 0; i < list.Count; i++)
{
list[i].Insert(0, QrSegment.MakeStructuredAppend(parity, i + 1, list.Count));
}
return list;
}
private static List> SplitTextIntoMultipleCodes(string text, QrCode.Ecc ecl, int version)
{
int[] array = ToCodePoints(text);
int num = QrCode.GetNumDataCodewords(version, ecl) * 8 - 20;
List> list = new List>();
int num2 = 0;
while (num2 < array.Length)
{
if (list.Count >= 16)
{
throw new DataTooLongException("The text is too long to fit into 16 QR codes");
}
int num3 = num2;
int num4 = array.Length;
while (num3 < num4)
{
int num5 = (num3 + num4 + 1) / 2;
if (MeasureSegmentsOptimally(new ArraySegment(array, num2, num5 - num2), version) <= num)
{
num3 = num5;
}
else
{
num4 = num5 - 1;
}
}
if (num4 == num2)
{
throw new InvalidOperationException("QR code splitting: should not reach");
}
list.Add(MakeSegmentsOptimally(new ArraySegment(array, num2, num4 - num2), version));
num2 = num4;
}
return list;
}
private static byte CalculateParity(string text)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
byte b = 0;
byte[] array = bytes;
foreach (byte b2 in array)
{
b ^= (byte)(b2 >> 8);
}
return b;
}
private static void GroupConsecutiveModes(IReadOnlyList elements, Action action)
{
int arg = 0;
QrSegment.Mode mode = elements[0];
int num = 0;
while (true)
{
if (num == elements.Count || elements[num] != mode)
{
action(arg, num, mode);
if (num == elements.Count)
{
break;
}
arg = num;
mode = elements[num];
}
num++;
}
}
}
internal class ReedSolomonGenerator
{
private readonly byte[] _coefficients;
internal ReedSolomonGenerator(int degree)
{
if (degree < 1 || degree > 255)
{
throw new ArgumentOutOfRangeException("degree", "Degree out of range");
}
_coefficients = new byte[degree];
_coefficients[degree - 1] = 1;
uint num = 1u;
for (int i = 0; i < degree; i++)
{
for (int j = 0; j < _coefficients.Length; j++)
{
_coefficients[j] = Multiply(_coefficients[j], num);
if (j + 1 < _coefficients.Length)
{
_coefficients[j] ^= _coefficients[j + 1];
}
}
num = Multiply(num, 2u);
}
}
internal byte[] GetRemainder(byte[] data)
{
Objects.RequireNonNull(data);
byte[] array = new byte[_coefficients.Length];
for (int i = 0; i < data.Length; i++)
{
uint y = (uint)(data[i] ^ array[0]);
Array.Copy(array, 1, array, 0, array.Length - 1);
array[^1] = 0;
for (int j = 0; j < array.Length; j++)
{
array[j] ^= Multiply(_coefficients[j], y);
}
}
return array;
}
private static byte Multiply(uint x, uint y)
{
uint num = 0u;
for (int num2 = 7; num2 >= 0; num2--)
{
num = (num << 1) ^ ((num >> 7) * 285);
num ^= ((y >> num2) & 1) * x;
}
return (byte)num;
}
}