public static bool TryDecode(IList <byte> pBytes, out cByteList rBytes, out string rError) { if (pBytes.Count == 0) { rBytes = new cByteList(); rError = null; return(true); } if (pBytes.Count % 4 != 0) { rBytes = null; rError = "base64 bytes must be in multiples of 4"; return(false); } int lCount; if (pBytes[pBytes.Count - 2] == cASCII.EQUALS) { if (pBytes[pBytes.Count - 1] != cASCII.EQUALS) { rBytes = null; rError = "invalid termination"; return(false); } lCount = pBytes.Count - 2; } else if (pBytes[pBytes.Count - 1] == cASCII.EQUALS) { lCount = pBytes.Count - 1; } else { lCount = pBytes.Count; } rBytes = new cByteList((lCount + 2) / 4 * 3); var lBuffer = new cFromBase64Buffer(rBytes); for (int i = 0; i < lCount; i++) { if (!lBuffer.TryAdd(pBytes[i], out rError)) { rBytes = null; return(false); } } if (!lBuffer.TryFlush(out rError)) { rBytes = null; return(false); } return(true); }
public static bool TryDecode(IList <byte> pBytes, out string rString, out string rError) { if (pBytes.Count == 0) { rString = string.Empty; rError = null; return(true); } var lBuilder = new StringBuilder(); var lBuffer = new cFromBase64Buffer(lBuilder); int lByteNumber = 1; byte lByte = pBytes[0]; while (true) { if (lByte == cASCII.AMPERSAND) { if (lByteNumber == pBytes.Count) { rString = null; rError = "ends with an ampersand"; return(false); } lByte = pBytes[lByteNumber++]; if (lByte == cASCII.HYPEN) { lBuilder.Append('&'); } else { // base64 loop while (true) { if (lByteNumber + 2 > pBytes.Count) { rString = null; rError = "invalid base64 character sequence"; return(false); } if (!ZTryDecodeBase64Byte(lByte, out int l61) || !ZTryDecodeBase64Byte(pBytes[lByteNumber++], out int l62) ) { rString = null; rError = "invalid base64 character"; return(false); } lBuffer.Add((l61 << 2) | (l62 >> 4)); lByte = pBytes[lByteNumber++]; if (lByte == cASCII.HYPEN) { if (lBuffer.ContainsAByte) { rString = null; rError = "odd number of encoded bytes"; return(false); } break; } if (lByteNumber + 1 > pBytes.Count) { rString = null; rError = "invalid base64 character sequence"; return(false); } if (!ZTryDecodeBase64Byte(lByte, out int l63)) { rString = null; rError = "invalid base64 character"; return(false); } lBuffer.Add(((l62 & 15) << 4) | (l63 >> 2)); lByte = pBytes[lByteNumber++]; if (lByte == cASCII.HYPEN) { if (lBuffer.ContainsAByte) { rString = null; rError = "odd number of encoded bytes"; return(false); } break; } if (lByteNumber + 1 > pBytes.Count) { rString = null; rError = "invalid base64 character sequence"; return(false); } if (!ZTryDecodeBase64Byte(lByte, out int l64)) { rString = null; rError = "invalid base64 character"; return(false); } lBuffer.Add(((l63 & 3) << 6) | l64); lByte = pBytes[lByteNumber++]; if (lByte == cASCII.HYPEN) { if (lBuffer.ContainsAByte) { rString = null; rError = "odd number of encoded bytes"; return(false); } break; } } } } else { if (lByte < cASCII.SPACE || lByte > cASCII.TILDA) { rString = null; rError = "invalid unencoded byte"; return(false); } lBuilder.Append((char)lByte); } if (lByteNumber == pBytes.Count) { rString = lBuilder.ToString(); rError = null; return(true); } lByte = pBytes[lByteNumber++]; } }