namespace Gma.QrCodeNet.Encoding.Terminate; internal static class Terminator { private const int NumBitsForByte = 8; /// /// This method will create BitList that contains /// terminator, padding and pad codewords for given datacodewords. /// Use it to full fill the data codewords capacity. Thus avoid massive empty bits. /// /// ISO/IEC 18004:2006 P. 32 33. /// Terminator / Bit stream to codeword conversion /// Method will add terminator bits (Terminator, padding and padcodewords) at end of baseList /// Num of bits for datacodewords without terminator /// Total number of datacodewords for specific version. /// Receive it under Version/VersionTable internal static void TerminateBites(this BitList baseList, int dataCount, int numTotalDataCodewords) { int numTotalDataBits = numTotalDataCodewords << 3; int numDataBits = dataCount; int numFillerBits = numTotalDataBits - numDataBits; int numBitsNeedForLastByte = numFillerBits & 0x7; int numFillerBytes = numFillerBits >> 3; // BitList result = new BitList(); if (numBitsNeedForLastByte >= QRCodeConstantVariable.TerminatorLength) { baseList.TerminatorPadding(numBitsNeedForLastByte); baseList.PadeCodewords(numFillerBytes); } else if (numFillerBytes == 0) { baseList.TerminatorPadding(numBitsNeedForLastByte); } else if (numFillerBytes > 0) { baseList.TerminatorPadding(numBitsNeedForLastByte + NumBitsForByte); baseList.PadeCodewords(numFillerBytes - 1); } if (baseList.Count != numTotalDataBits) { throw new ArgumentException( $"Generate terminator and Padding fail. Num of bits need: {numFillerBytes}. Actual length: {baseList.Count - numDataBits}"); } } private static void PadeCodewords(this BitList mainList, int numOfPadeCodewords) { if (numOfPadeCodewords < 0) { throw new ArgumentException("Num of pade codewords is less than Zero"); } for (int numOfP = 1; numOfP <= numOfPadeCodewords; numOfP++) { if (numOfP % 2 == 1) { mainList.Add(QRCodeConstantVariable.PadeCodewordsOdd, NumBitsForByte); } else { mainList.Add(QRCodeConstantVariable.PadeCodewordsEven, NumBitsForByte); } } } private static void TerminatorPadding(this BitList mainList, int numBits) => mainList.Add(QRCodeConstantVariable.TerminatorNPaddingBit, numBits); }