diff options
author | conterouz <conterouz@yandex-team.com> | 2022-12-16 10:04:06 +0300 |
---|---|---|
committer | conterouz <conterouz@yandex-team.com> | 2022-12-16 10:04:06 +0300 |
commit | 64fdfff412a1c555a909da6fd654cba5628e61e8 (patch) | |
tree | 93f211a4cfb841fef1595737a37233d9860c09a0 /library/cpp/string_utils/base64/base64.cpp | |
parent | fa371e5210e9cdda3fd6fc33af87a2458b69ab84 (diff) | |
download | ydb-64fdfff412a1c555a909da6fd654cba5628e61e8.tar.gz |
Добавил в библиотеку метод для создания Base64 строки url-friendly
Diffstat (limited to 'library/cpp/string_utils/base64/base64.cpp')
-rw-r--r-- | library/cpp/string_utils/base64/base64.cpp | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/library/cpp/string_utils/base64/base64.cpp b/library/cpp/string_utils/base64/base64.cpp index 05c201f0de..610136fd1a 100644 --- a/library/cpp/string_utils/base64/base64.cpp +++ b/library/cpp/string_utils/base64/base64.cpp @@ -111,7 +111,7 @@ static inline unsigned char GetBase64EncodedIndex3(unsigned char octet2) { return (octet2 & 0x3f); } -template <bool urlVersion> +template <bool urlVersion, bool usePadding = true> static inline char* Base64EncodeImpl(char* outstr, const unsigned char* instr, size_t len) { const char* const base64_etab = (urlVersion ? base64_etab_url : base64_etab_std); const char pad = (urlVersion ? ',' : '='); @@ -132,9 +132,13 @@ static inline char* Base64EncodeImpl(char* outstr, const unsigned char* instr, s *outstr++ = base64_etab[GetBase64EncodedIndex2(instr[idx + 1], '\0')]; } else { *outstr++ = base64_etab[GetBase64EncodedIndex1(instr[idx], '\0')]; + if (usePadding) { + *outstr++ = pad; + } + } + if (usePadding) { *outstr++ = pad; } - *outstr++ = pad; } *outstr = 0; @@ -149,6 +153,10 @@ char* Base64EncodeUrl(char* outstr, const unsigned char* instr, size_t len) { return Base64EncodeImpl<true>(outstr, instr, len); } +char* Base64EncodeUrlNoPadding(char* outstr, const unsigned char* instr, size_t len) { + return Base64EncodeImpl<true, false>(outstr, instr, len); +} + inline void uudecode_1(char* dst, unsigned char* src) { dst[0] = char((base64_bkw[src[0]] << 2) | (base64_bkw[src[1]] >> 4)); dst[1] = char((base64_bkw[src[1]] << 4) | (base64_bkw[src[2]] >> 2)); @@ -245,13 +253,27 @@ size_t Base64Decode(void* dst, const char* b, const char* e) { return outLen; } -TString Base64DecodeUneven(const TStringBuf s) { - if (s.length() % 4 == 0) { - return Base64Decode(s); +size_t Base64DecodeUneven(void* dst, const TStringBuf s) { + const size_t tailSize = s.length() % 4; + if (tailSize == 0) { + return Base64Decode(dst, s.begin(), s.end()); } - // padding to 4 - return Base64Decode(TString(s) + TString(4 - (s.length() % 4), '=')); + // divide s into even part and tail and decode in two step, to avoid memory allocation + char tail[4] = {'=', '=', '=', '='}; + memcpy(tail, s.end() - tailSize, tailSize); + size_t decodedEven = s.length() > 4 ? Base64Decode(dst, s.begin(), s.end() - tailSize) : 0; + // there should not be tail of size 1 it's incorrect for 8-bit bytes + size_t decodedTail = tailSize != 1 ? Base64Decode(static_cast<char*>(dst) + decodedEven, tail, tail + 4) : 0; + return decodedEven + decodedTail; +} + +TString Base64DecodeUneven(const TStringBuf s) { + TString ret; + ret.ReserveAndResize(Base64DecodeBufSize(s.size())); + size_t size = Base64DecodeUneven(const_cast<char*>(ret.data()), s); + ret.resize(size); + return ret; } char* Base64Encode(char* outstr, const unsigned char* instr, size_t len) { |