Beispiel #1
0
 internal LookupTable GetOrCreateLookupTable(string alphabet)
 {
     return(_lookupTable ?? (_lookupTable = BuildLookupTable(alphabet)));
 }
Beispiel #2
0
        private static unsafe bool CheckAlphabet(string encoded, int index, int length, LookupTable lookupTable)
        {
            int[] lookupValues = lookupTable.Values;
            int   lowCode      = lookupTable.LowCode;
            int   lookupSize   = lookupValues.Length;

            fixed(char *pEncodedBegin = encoded)
            fixed(int *pLookup = lookupValues)
            {
                char *pEncoded = pEncodedBegin + index;
                char *pEnd     = pEncoded + length;

                while (pEncoded < pEnd)
                {
                    int lookupIndex = *pEncoded - lowCode;
                    if (lookupIndex < 0 || lookupIndex >= lookupSize)
                    {
                        return(false);
                    }

                    int item = *(pLookup + lookupIndex);
                    if (item == LookupTableNullItem)
                    {
                        return(false);
                    }

                    pEncoded++;
                }
            }

            return(true);
        }
Beispiel #3
0
        internal static byte[] ToBytes(string encoded, int index, int length, char?padSymbol, LookupTable lookupTable)
        {
            CheckToBytesArguments(encoded, index, length, lookupTable);

            if (length == 0)
            {
                return(new byte[0]);
            }

            int remainder = GetRemainderWithChecks(encoded, index, length, padSymbol);

            int groupsCount = length / 8;

            int bytesCount = 0;

            if (remainder > 0)
            {
                if (padSymbol != null)
                {
                    // groupsCount always >= 1 here because of "length % 8 != 0" as checked before
                    groupsCount--;
                }

                bytesCount = GetBytesCount(remainder);
            }

            bytesCount += groupsCount * 5;

            var bytes = new byte[bytesCount];

            if (bytesCount > 0)
            {
                ToBytesUnsafe(encoded, index, bytes, 0, groupsCount, remainder, lookupTable);
            }

            return(bytes);
        }
Beispiel #4
0
        private static void CheckToBytesArguments(string encoded, int index, int length, LookupTable lookupTable)
        {
            if (encoded == null)
            {
                throw new ArgumentNullException(nameof(encoded));
            }

            if (index < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }

            if (length < 0 || length > encoded.Length - index)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            if (lookupTable == null)
            {
                throw new ArgumentNullException(nameof(lookupTable));
            }
        }
Beispiel #5
0
        private static unsafe void ToBytesUnsafe(string encoded, int index, byte[] output, int outputOffset,
                                                 int encodedGroupsCount, int remainder, LookupTable lookupTable)
        {
            int[] lookupValues = lookupTable.Values;
            int   lowCode      = lookupTable.LowCode;

            fixed(char *pEncodedBegin = encoded)
            fixed(byte *pOutput = &output[outputOffset])
            fixed(int *pLookup  = lookupValues)
            {
                char *pEncoded = pEncodedBegin + index;

                if (encodedGroupsCount > 0)
                {
                    ToBytesGroupsUnsafe(pEncoded, pOutput, encodedGroupsCount, pLookup,
                                        lookupValues.Length, lowCode);
                }

                if (remainder <= 1)
                {
                    return;
                }

                char *pEncodedRemainder = pEncoded + encodedGroupsCount * 8;
                byte *pOutputRemainder  = pOutput + encodedGroupsCount * 5;

                ToBytesRemainderUnsafe(pEncodedRemainder, pOutputRemainder, remainder, pLookup,
                                       lookupValues.Length, lowCode);
            }
        }
Beispiel #6
0
        internal static byte[] ToBytes(string encoded, int index, int length, char?padSymbol, LookupTable lookupTable)
        {
            if (encoded == null)
            {
                throw new ArgumentNullException(nameof(encoded));
            }

            if (index < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }

            if (length < 0 || length > encoded.Length - index)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            if (lookupTable == null)
            {
                throw new ArgumentNullException(nameof(lookupTable));
            }

            if (length == 0)
            {
                return(new byte[0]);
            }

            int remainder;

            if (padSymbol != null)
            {
                if (length % 8 != 0)
                {
                    throw new FormatException(ErrorMessageInvalidLength);
                }

                remainder = 8;
                char padChar = padSymbol.Value;
                for (int i = index + length - 1; i >= index; i--)
                {
                    if (encoded[i] != padChar)
                    {
                        break;
                    }

                    remainder--;
                }
                if (remainder <= 0)
                {
                    throw new FormatException(ErrorMessageInvalidPadding);
                }

                remainder %= 8;
            }
            else
            {
                remainder = length % 8;
            }

            int groupsCount = length / 8;

            int bytesCount = 0;

            if (remainder > 0)
            {
                if (padSymbol != null)
                {
                    // groupsCount was checked before and always >= 1 here
                    groupsCount--;
                }
                bytesCount = GetBytesCount(remainder);
            }

            bytesCount += groupsCount * 5;

            var bytes = new byte[bytesCount];

            if (bytesCount > 0)
            {
                ToBytesUnsafe(encoded, index, length, bytes, 0, groupsCount, remainder, padSymbol, lookupTable);
            }
            return(bytes);
        }