aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/string_utils/base64/base64.h
blob: 22e6b4b5424ee3b0bde3cc4f7db66c331d13a6f7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#pragma once

#include <util/system/defaults.h>
#include <util/generic/strbuf.h>
#include <util/generic/string.h>

/* @return Size of the buffer required to decode Base64 encoded data of size `len`.
 */
constexpr size_t Base64DecodeBufSize(const size_t len) noexcept {
    return (len + 3) / 4 * 3;
}

/* Decode Base64 encoded data. Can decode both regular Base64 and Base64URL encoded data. Can decode
 * only valid Base64[URL] data, behaviour for invalid data is unspecified.
 *
 * @throws Throws exception in case of incorrect padding.
 *
 * @param dst memory for writing output.
 * @param b pointer to the beginning of base64 encoded string.
 * @param a pointer to the end of base64 encoded string
 *
 * @return Return number of bytes decoded.
 */
size_t Base64Decode(void* dst, const char* b, const char* e);

inline TStringBuf Base64Decode(const TStringBuf src, void* dst) {
    return TStringBuf(static_cast<const char*>(dst), Base64Decode(dst, src.begin(), src.end()));
}

inline void Base64Decode(const TStringBuf src, TString& dst) {
    dst.ReserveAndResize(Base64DecodeBufSize(src.size()));
    dst.resize(Base64Decode(src, dst.begin()).size());
}

//WARNING: can process not whole input silently, use Base64StrictDecode instead of this function
inline TString Base64Decode(const TStringBuf s) {
    TString ret;
    Base64Decode(s, ret);
    return ret;
}

///
/// @brief Decodes Base64 string with strict verification
///        of invalid symbols, also tries to decode Base64 string with padding
///        inside.
//
/// @throws Throws exceptions on inputs which contain invalid symbols
///         or incorrect padding.
/// @{
///
/// @param b a pointer to the beginning of base64 encoded string.
/// @param e a pointer to the end of base64 encoded string.
/// @param dst memory for writing output.
///
/// @return Returns number of bytes decoded.
///
size_t Base64StrictDecode(void* dst, const char* b, const char* e);

///
/// @param src a base64 encoded string.
/// @param dst an pointer to allocated memory
///            for writing result.
///
/// @return Returns dst wrapped into TStringBuf.
///
inline TStringBuf Base64StrictDecode(const TStringBuf src, void* dst) {
    return TStringBuf(static_cast<const char*>(dst), Base64StrictDecode(dst, src.begin(), src.end()));
}

///
/// @param src a base64 encoded string.
/// @param dst a decoded string.
///
inline void Base64StrictDecode(const TStringBuf src, TString& dst) {
    dst.ReserveAndResize(Base64DecodeBufSize(src.size()));
    dst.resize(Base64StrictDecode(src, dst.begin()).size());
}

///
/// @param src a base64 encoded string.
///
/// @returns a decoded string.
///
inline TString Base64StrictDecode(const TStringBuf src) {
    TString ret;
    Base64StrictDecode(src, ret);
    return ret;
}
/// @}

/// Works with strings which length is not divisible by 4.
TString Base64DecodeUneven(const TStringBuf s);
size_t Base64DecodeUneven(void* dst, const TStringBuf s);

//encode
constexpr size_t Base64EncodeBufSize(const size_t len) noexcept {
    return (len + 2) / 3 * 4 + 1;
}

char* Base64Encode(char* outstr, const unsigned char* instr, size_t len);
char* Base64EncodeUrl(char* outstr, const unsigned char* instr, size_t len);

/// Make base64 string which stay unchaged after applying 'urlencode' function
/// as it doesn't contain character, which cannot be used in urls
/// @param outstr a pointer to allocated memory for writing result.
/// @param instr a to buffer to encode
/// @param len size of instr buffer
///
/// @return Returns pointer to last symbol in outstr buffer.
///
char* Base64EncodeUrlNoPadding(char* outstr, const unsigned char* instr, size_t len);

inline TStringBuf Base64Encode(const TStringBuf src, void* output) {
    return TStringBuf(static_cast<const char*>(output), Base64Encode(static_cast<char*>(output), reinterpret_cast<const unsigned char*>(src.data()), src.size()));
}

inline TStringBuf Base64EncodeUrl(const TStringBuf src, void* output) {
    return TStringBuf(static_cast<const char*>(output), Base64EncodeUrl(static_cast<char*>(output), reinterpret_cast<const unsigned char*>(src.data()), src.size()));
}

inline TStringBuf Base64EncodeUrlNoPadding(const TStringBuf src, void* output) {
    return TStringBuf(static_cast<const char*>(output), Base64EncodeUrlNoPadding(static_cast<char*>(output), reinterpret_cast<const unsigned char*>(src.data()), src.size()));
}

inline void Base64Encode(const TStringBuf src, TString& dst) {
    dst.ReserveAndResize(Base64EncodeBufSize(src.size()));
    dst.resize(Base64Encode(src, dst.begin()).size());
}

inline void Base64EncodeUrl(const TStringBuf src, TString& dst) {
    dst.ReserveAndResize(Base64EncodeBufSize(src.size()));
    dst.resize(Base64EncodeUrl(src, dst.begin()).size());
}

inline void Base64EncodeUrlNoPadding(const TStringBuf src, TString& dst) {
    dst.ReserveAndResize(Base64EncodeBufSize(src.size()));
    dst.resize(Base64EncodeUrlNoPadding(src, dst.begin()).size());
}

inline TString Base64Encode(const TStringBuf s) {
    TString ret;
    Base64Encode(s, ret);
    return ret;
}

inline TString Base64EncodeUrl(const TStringBuf s) {
    TString ret;
    Base64EncodeUrl(s, ret);
    return ret;
}

inline TString Base64EncodeUrlNoPadding(const TStringBuf s) {
    TString ret;
    Base64EncodeUrlNoPadding(s, ret);
    return ret;
}