internal LookupTable GetOrCreateLookupTable(string alphabet) { return(_lookupTable ?? (_lookupTable = BuildLookupTable(alphabet))); }
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); }
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); }
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)); } }
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); } }
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); }