aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/string_utils/base64/base64.cpp
diff options
context:
space:
mode:
authorconterouz <conterouz@yandex-team.com>2022-12-16 10:04:06 +0300
committerconterouz <conterouz@yandex-team.com>2022-12-16 10:04:06 +0300
commit64fdfff412a1c555a909da6fd654cba5628e61e8 (patch)
tree93f211a4cfb841fef1595737a37233d9860c09a0 /library/cpp/string_utils/base64/base64.cpp
parentfa371e5210e9cdda3fd6fc33af87a2458b69ab84 (diff)
downloadydb-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.cpp36
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) {