@@ -90,3 +90,180 @@ llvm::Error llvm::decodeBase64(llvm::StringRef Input,
9090 }
9191 return Error::success ();
9292}
93+
94+ using namespace llvm ;
95+
96+ namespace {
97+
98+ using byte = std::byte;
99+
100+ ::llvm::Error makeError (const Twine &Msg) {
101+ return createStringError (std::error_code{}, Msg);
102+ }
103+
104+ class Base64Impl {
105+ private:
106+ static constexpr char EncodingTable[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"
107+ " abcdefghijklmnopqrstuvwxyz"
108+ " 0123456789+/" ;
109+
110+ static_assert (sizeof (EncodingTable) == 65 , " " );
111+
112+ // Compose an index into the encoder table from two bytes and the number of
113+ // significant bits in the lower byte until the byte boundary.
114+ static inline int composeInd (byte ByteLo, byte ByteHi, int BitsLo) {
115+ int Res = (int )((ByteHi << BitsLo) | (ByteLo >> (8 - BitsLo))) & 0x3F ;
116+ return Res;
117+ }
118+
119+ // Decode a single character.
120+ static inline int decode (char Ch) {
121+ if (Ch >= ' A' && Ch <= ' Z' ) // 0..25
122+ return Ch - ' A' ;
123+ else if (Ch >= ' a' && Ch <= ' z' ) // 26..51
124+ return Ch - ' a' + 26 ;
125+ else if (Ch >= ' 0' && Ch <= ' 9' ) // 52..61
126+ return Ch - ' 0' + 52 ;
127+ else if (Ch == ' +' ) // 62
128+ return 62 ;
129+ else if (Ch == ' /' ) // 63
130+ return 63 ;
131+ return -1 ;
132+ }
133+
134+ // Decode a quadruple of characters.
135+ static inline Expected<bool > decode4 (const char *Src, byte *Dst) {
136+ int BadCh = -1 ;
137+
138+ for (auto I = 0 ; I < 4 ; ++I) {
139+ char Ch = Src[I];
140+ int Byte = decode (Ch);
141+
142+ if (Byte < 0 ) {
143+ BadCh = Ch;
144+ break ;
145+ }
146+ Dst[I] = (byte)Byte;
147+ }
148+ if (BadCh == -1 )
149+ return true ;
150+ return makeError (" invalid char in Base64Impl encoding: 0x" + Twine (BadCh));
151+ }
152+
153+ public:
154+ static size_t getEncodedSize (size_t SrcSize) {
155+ constexpr int ByteSizeInBits = 8 ;
156+ constexpr int EncBitsPerChar = 6 ;
157+ return (SrcSize * ByteSizeInBits + (EncBitsPerChar - 1 )) / EncBitsPerChar;
158+ }
159+
160+ static size_t encode (const byte *Src, raw_ostream &Out, size_t SrcSize) {
161+ size_t Off = 0 ;
162+
163+ // encode full byte triples
164+ for (size_t TriB = 0 ; TriB < SrcSize / 3 ; ++TriB) {
165+ Off = TriB * 3 ;
166+ byte Byte0 = Src[Off++];
167+ byte Byte1 = Src[Off++];
168+ byte Byte2 = Src[Off++];
169+
170+ Out << EncodingTable[(int )Byte0 & 0x3F ];
171+ Out << EncodingTable[composeInd (Byte0, Byte1, 2 )];
172+ Out << EncodingTable[composeInd (Byte1, Byte2, 4 )];
173+ Out << EncodingTable[(int )(Byte2 >> 2 ) & 0x3F ];
174+ }
175+ // encode the remainder
176+ int RemBytes = SrcSize - Off;
177+
178+ if (RemBytes > 0 ) {
179+ byte Byte0 = Src[Off + 0 ];
180+ Out << EncodingTable[(int )Byte0 & 0x3F ];
181+
182+ if (RemBytes > 1 ) {
183+ byte Byte1 = Src[Off + 1 ];
184+ Out << EncodingTable[composeInd (Byte0, Byte1, 2 )];
185+ Out << EncodingTable[(int )(Byte1 >> 4 ) & 0x3F ];
186+ } else {
187+ Out << EncodingTable[(int )(Byte0 >> 6 ) & 0x3F ];
188+ }
189+ }
190+ return getEncodedSize (SrcSize);
191+ }
192+
193+ static size_t getDecodedSize (size_t SrcSize) { return (SrcSize * 3 + 3 ) / 4 ; }
194+
195+ static Expected<size_t > decode (const char *Src, byte *Dst, size_t SrcSize) {
196+ size_t SrcOff = 0 ;
197+ size_t DstOff = 0 ;
198+
199+ // decode full quads
200+ for (size_t Qch = 0 ; Qch < SrcSize / 4 ; ++Qch, SrcOff += 4 , DstOff += 3 ) {
201+ byte Ch[4 ];
202+ Expected<bool > TrRes = decode4 (Src + SrcOff, Ch);
203+
204+ if (!TrRes)
205+ return TrRes.takeError ();
206+ // each quad of chars produces three bytes of output
207+ Dst[DstOff + 0 ] = Ch[0 ] | (Ch[1 ] << 6 );
208+ Dst[DstOff + 1 ] = (Ch[1 ] >> 2 ) | (Ch[2 ] << 4 );
209+ Dst[DstOff + 2 ] = (Ch[2 ] >> 4 ) | (Ch[3 ] << 2 );
210+ }
211+ auto RemChars = SrcSize - SrcOff;
212+
213+ if (RemChars == 0 )
214+ return DstOff;
215+ // decode the remainder; variants:
216+ // 2 chars remain - produces single byte
217+ // 3 chars remain - produces two bytes
218+
219+ if (RemChars != 2 && RemChars != 3 )
220+ return makeError (" invalid encoded sequence length" );
221+
222+ int Ch0 = decode (Src[SrcOff++]);
223+ int Ch1 = decode (Src[SrcOff++]);
224+ int Ch2 = RemChars == 3 ? decode (Src[SrcOff]) : 0 ;
225+
226+ if (Ch0 < 0 || Ch1 < 0 || Ch2 < 0 )
227+ return makeError (" invalid characters in the encoded sequence remainder" );
228+ Dst[DstOff++] = (byte)Ch0 | (byte)((Ch1 << 6 ));
229+
230+ if (RemChars == 3 )
231+ Dst[DstOff++] = (byte)(Ch1 >> 2 ) | (byte)(Ch2 << 4 );
232+ return DstOff;
233+ }
234+
235+ static Expected<std::unique_ptr<byte[]>> decode (const char *Src,
236+ size_t SrcSize) {
237+ size_t DstSize = getDecodedSize (SrcSize);
238+ std::unique_ptr<byte[]> Dst (new byte[DstSize]);
239+ Expected<size_t > Res = decode (Src, Dst.get (), SrcSize);
240+ if (!Res)
241+ return Res.takeError ();
242+ return Expected<std::unique_ptr<byte[]>>(std::move (Dst));
243+ }
244+ };
245+
246+ constexpr char Base64Impl::EncodingTable[];
247+
248+ } // anonymous namespace
249+
250+ size_t Base64::getEncodedSize (size_t SrcSize) {
251+ return Base64Impl::getEncodedSize (SrcSize);
252+ }
253+
254+ size_t Base64::encode (const byte *Src, raw_ostream &Out, size_t SrcSize) {
255+ return Base64Impl::encode (Src, Out, SrcSize);
256+ }
257+
258+ size_t Base64::getDecodedSize (size_t SrcSize) {
259+ return Base64Impl::getDecodedSize (SrcSize);
260+ }
261+
262+ Expected<size_t > Base64::decode (const char *Src, byte *Dst, size_t SrcSize) {
263+ return Base64Impl::decode (Src, Dst, SrcSize);
264+ }
265+
266+ Expected<std::unique_ptr<byte[]>> Base64::decode (const char *Src,
267+ size_t SrcSize) {
268+ return Base64Impl::decode (Src, SrcSize);
269+ }
0 commit comments