1 #ifndef LIBBASE64_CPP_H
2 #define LIBBASE64_CPP_H
8 #define __LIBBASE64_MAJOR__ 1
9 #define __LIBBASE64_MINOR__ 1
10 #define __LIBBASE64_PATCH__ 0
11 #define __LIBBASE64_VERSION__ (__LIBBASE64_MAJOR__ * 10000 + __LIBBASE64_MINOR__ * 100 + __LIBBASE64_PATCH__)
15 #define LIBBASE64_ASSERT(cond, msg) (void)0
16 #define CREATEBOUNDCHECKER(type, name, ubound, lbound) (void)0
17 #define GETITEM_BOUNDCHECK(loc, name) (*(loc))
20 #define LIBBASE64_ASSERT(cond, msg) if (!(cond)){ std::cerr << msg << std::endl; throw false; }
26 T getLocation(
const T * loc){
27 LIBBASE64_ASSERT(loc < upperbound,
"Array index above bounds");
28 LIBBASE64_ASSERT(loc >= lowerbound,
"Array index below bounds");
35 #define CREATEBOUNDCHECKER(type, name, ubound, lbound) libbase64_boundChecker<type> name(ubound, lbound)
36 #define GETITEM_BOUNDCHECK(loc, name) name.getLocation(loc)
38 #ifdef LIBBASE64CODECOVERAGE
39 #define LIBBASE64CODECOVERAGEBRANCH { static bool f_codeCoverage_ = false; if (f_codeCoverage_ == false){ libbase64::getCoverageHits<STRINGTYPE, CHARTYPE, UCHARTYPE, SAFETY>(true); f_codeCoverage_ = true; } }
42 #ifndef LIBBASE64CODECOVERAGE
43 #define LIBBASE64CODECOVERAGEBRANCH (void)0
48 #define LIBBASE64_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
49 #if (LIBBASE64_GCC_VERSION >= 29600)
50 #define libbase64_likely(x) __builtin_expect((long)((bool)(x)),1)
51 #define libbase64_unlikely(x) __builtin_expect((long)((bool)(x)),0)
54 #ifndef libbase64_likely
55 #define libbase64_likely(x) x
56 #define libbase64_unlikely(x) x
61 #ifdef LIBBASE64CODECOVERAGE //Gets the number of branches that has been made
62 template<
class STRINGTYPE,
typename CHARTYPE,
typename UCHARTYPE,
bool SAFETY>
63 static size_t getCoverageHits(
bool inc){
64 static size_t hits = 0;
71 namespace libbase64_characters {
73 inline static const T * getChar64(
void){
74 static const T char64s[64] = {
75 (T)
'A', (T)
'B', (T)
'C', (T)
'D', (T)
'E', (T)
'F', (T)
'G', (T)
'H', (T)
'I', (T)
'J', (T)
'K', (T)
'L', (T)
'M',
76 (T)
'N', (T)
'O', (T)
'P', (T)
'Q', (T)
'R', (T)
'S', (T)
'T', (T)
'U', (T)
'V', (T)
'W', (T)
'X', (T)
'Y', (T)
'Z',
77 (T)
'a', (T)
'b', (T)
'c', (T)
'd', (T)
'e', (T)
'f', (T)
'g', (T)
'h', (T)
'i', (T)
'j', (T)
'k', (T)
'l', (T)
'm',
78 (T)
'n', (T)
'o', (T)
'p', (T)
'q', (T)
'r', (T)
's', (T)
't', (T)
'u', (T)
'v', (T)
'w', (T)
'x', (T)
'y', (T)
'z',
79 (T)
'0', (T)
'1', (T)
'2', (T)
'3', (T)
'4', (T)
'5', (T)
'6', (T)
'7', (T)
'8', (T)
'9', (T)
'+', (T)
'/'
85 inline static T getChar(
unsigned char bin){
86 CREATEBOUNDCHECKER(T, char64bounds, getChar64<T>(), getChar64<T>() + 64);
87 return GETITEM_BOUNDCHECK(getChar64<T>() + bin, char64bounds);
91 inline static T toBinary(T c) {
92 static T binaryConvert[80] = {62,48,49,50,63,52,53,54,55,56,57,58,59,60,61,249,250,251,252,253,254,255,0,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,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};
93 CREATEBOUNDCHECKER(T, binaryConvertsbounds, binaryConvert, binaryConvert + 80);
94 return GETITEM_BOUNDCHECK(binaryConvert + c - 43, binaryConvertsbounds);
98 static inline T & emptyString(
void){
104 namespace libbase64_Calculator {
105 inline static size_t getEncodingSize(
size_t bytes){
106 return (bytes + 2 - ((bytes + 2) % 3)) / 3 * 4;
108 inline static size_t getDecodingSize(
size_t res){
117 template<
class STRINGTYPE,
typename CHARTYPE,
typename UCHARTYPE,
bool SAFETY>
118 static STRINGTYPE encode(
const unsigned char * binary,
size_t bytes){
119 CREATEBOUNDCHECKER(
unsigned char, binarybounds, binary, binary + bytes);
123 if (libbase64_unlikely(bytes == 0)){
124 LIBBASE64CODECOVERAGEBRANCH;
125 return libbase64_characters::emptyString<STRINGTYPE>();
130 size_t misaligned = bytes % 3;
132 result.reserve(libbase64_Calculator::getEncodingSize(bytes));
135 for (
size_t i = 0, aligned((bytes - misaligned) / 3); i < aligned; ++i){
136 LIBBASE64CODECOVERAGEBRANCH;
137 result += libbase64_characters::getChar<CHARTYPE>((GETITEM_BOUNDCHECK(binary, binarybounds) & 0xFC) >> 2);
138 result += libbase64_characters::getChar<CHARTYPE>(((GETITEM_BOUNDCHECK(binary, binarybounds) & 0x03) << 4) + ((GETITEM_BOUNDCHECK(binary + 1, binarybounds) & 0xF0) >> 4));
139 result += libbase64_characters::getChar<CHARTYPE>(((GETITEM_BOUNDCHECK(binary + 1, binarybounds) & 0x0F) << 2) + ((GETITEM_BOUNDCHECK(binary + 2, binarybounds) & 0xC0) >> 6));
140 result += libbase64_characters::getChar<CHARTYPE>(GETITEM_BOUNDCHECK(binary + 2, binarybounds) & 0x3F);
145 if (libbase64_likely(misaligned != 0)){
146 LIBBASE64CODECOVERAGEBRANCH;
148 unsigned char temp[3] = {
'\0',
'\0',
'\0' };
149 for (
unsigned char i = 0; i < (
unsigned char)misaligned; ++i){
150 LIBBASE64CODECOVERAGEBRANCH;
151 temp[i] = GETITEM_BOUNDCHECK(binary++, binarybounds);
155 result += libbase64_characters::getChar<CHARTYPE>((temp[0] & 0xFC) >> 2);
156 result += libbase64_characters::getChar<CHARTYPE>(((temp[0] & 0x03) << 4) + ((temp[1] & 0xF0) >> 4));
157 if (misaligned == 2){
158 LIBBASE64CODECOVERAGEBRANCH;
159 result += libbase64_characters::getChar<CHARTYPE>(((temp[1] & 0x0F) << 2) + ((temp[2] & 0xC0) >> 6));
161 LIBBASE64CODECOVERAGEBRANCH;
162 result += (CHARTYPE)
'=';
164 result += (CHARTYPE)
'=';
166 LIBBASE64CODECOVERAGEBRANCH;
169 LIBBASE64_ASSERT(libbase64_Calculator::getEncodingSize(bytes) == result.length(),
"Reserve wasn't the correct guess");
173 template<
class STRINGTYPE,
typename CHARTYPE,
typename UCHARTYPE,
bool SAFETY>
174 static std::string decode(
const STRINGTYPE & encoded){
176 const size_t length = encoded.length();
179 if (libbase64_unlikely((length % 4) != 0)){
180 LIBBASE64CODECOVERAGEBRANCH;
181 return libbase64_characters::emptyString<std::string>();
183 if (libbase64_unlikely(length == 0)){
184 LIBBASE64CODECOVERAGEBRANCH;
185 return libbase64_characters::emptyString<std::string>();
189 size_t pos = encoded.find_first_not_of(libbase64_characters::getChar64<CHARTYPE>());
190 if (libbase64_unlikely(pos != STRINGTYPE::npos)){
191 LIBBASE64CODECOVERAGEBRANCH;
192 if (libbase64_unlikely(encoded[pos] != (CHARTYPE)
'=')){
193 LIBBASE64CODECOVERAGEBRANCH;
194 #ifdef LIBBASE64_THROW_STD_INVALID_ARGUMENT
195 throw std::invalid_argument(
"invalid character in base64");
197 return libbase64_characters::emptyString<std::string>();
200 if (pos != length - 1){
201 LIBBASE64CODECOVERAGEBRANCH;
202 if (libbase64_unlikely(pos != length - 2)){
203 LIBBASE64CODECOVERAGEBRANCH;
204 #ifdef LIBBASE64_THROW_STD_INVALID_ARGUMENT
205 throw std::invalid_argument(
"equal sign in wrong place in base64");
207 return libbase64_characters::emptyString<std::string>();
210 if (libbase64_unlikely(encoded[pos + 1] != (CHARTYPE)
'=')){
211 LIBBASE64CODECOVERAGEBRANCH;
212 #ifdef LIBBASE64_THROW_STD_INVALID_ARGUMENT
213 throw std::invalid_argument(
"invalid character in base64");
215 return libbase64_characters::emptyString<std::string>();
218 LIBBASE64CODECOVERAGEBRANCH;
220 LIBBASE64CODECOVERAGEBRANCH;
223 LIBBASE64CODECOVERAGEBRANCH;
227 const CHARTYPE * runner = encoded.data();
228 const CHARTYPE * end = runner + encoded.length();
229 CREATEBOUNDCHECKER(CHARTYPE, encodedbounds, runner, end);
230 size_t aligned = length / 4;
233 result.reserve(libbase64_Calculator::getDecodingSize(length));
236 for (
unsigned int i = 0; i < aligned; ++i){
237 const CHARTYPE second = libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner + 1, encodedbounds));
238 const CHARTYPE third = libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner + 2, encodedbounds));
239 result += (libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner, encodedbounds)) << 2) + ((second & 0x30) >> 4);
240 result += ((second & 0xf) << 4) + ((third & 0x3c) >> 2);
241 result += ((third & 0x3) << 6) + libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner + 3, encodedbounds));
246 const CHARTYPE second = libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner + 1, encodedbounds));
247 result += (libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner + 0, encodedbounds)) << 2) + ((second & 0x30) >> 4);
249 if ((runner != end) && (*runner != (CHARTYPE)
'=')){
250 LIBBASE64CODECOVERAGEBRANCH;
251 const CHARTYPE third = libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner, encodedbounds));
252 result += ((second & 0xf) << 4) + ((third & 0x3c) >> 2);
254 if ((runner != end) && (*runner != (CHARTYPE)
'=')){
255 LIBBASE64CODECOVERAGEBRANCH;
256 result += ((third & 0x3) << 6) + libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner, encodedbounds));
258 LIBBASE64CODECOVERAGEBRANCH;
261 LIBBASE64CODECOVERAGEBRANCH;
264 LIBBASE64_ASSERT(libbase64_Calculator::getDecodingSize(length) >= result.length(),
"Reserve wasn't the correct guess, too small");
265 LIBBASE64_ASSERT((result.length() <= 3) || (libbase64_Calculator::getDecodingSize(length) > result.length() - 3),
"Reserve wasn't the correct guess, too big");
Definition: libbase64++.h:23
Definition: libbase64++.h:60