001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
044:
045:
046:
047:
048:
049:
050:
051:
052:
053:
054:
055:
056:
057:
058:
059:
060:
061:
062:
063:
064:
065:
066:
067:
068:
069:
070:
071:
072:
073:
074:
075:
076:
077:
078:
079:
080:
081:
082:
083:
084:
085:
086:
087:
088:
089:
090:
091:
092:
093:
094:
095:
096:
097:
098:
099:
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:
Min/Max
































































































































/*
* Copyright (c), Zeriph Enterprises
* All rights reserved.
*
* Contributor(s):
* Zechariah Perez, omni (at) zeriph (dot) com
*
* THIS SOFTWARE IS PROVIDED BY ZERIPH AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ZERIPH AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(OMNI_CRYPTO_BASE64_HPP)
#define OMNI_CRYPTO_BASE64_HPP 1

#include <omni/defs/crypto_def.hpp>
#include <omni/types/char_t.hpp>

#define OMNI_CRYPTO_BASE64_CHARS { \
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", \
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" \
}


#define OMNI_CYRPTO_BASE64_CHAR_POS(c, p) \
switch (c) { \
    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': \
    case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': \
    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': \
    case 'V': case 'W': case 'X': case 'Y': case 'Z': \
        p = static_cast<std::size_t>(c - 'A'); break; \
    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': \
    case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': \
    case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': \
    case 'v': case 'w': case 'x': case 'y': case 'z': \
        p = static_cast<std::size_t>(c - 'a' + ('Z' - 'A') + 1); break; \
    case '0': case '1': case '2': case '3': case '4': \
    case '5': case '6': case '7': case '8': case '9': \
        p = static_cast<std::size_t>(c - '0' + ('Z' - 'A') + ('z' - 'a') + 2); break; \
    case '+': case '-': p = 62; break; \
    case '/': case '_': p = 63; break; \
    default: p = 255; OMNI_ERR_FW("An invalid character was detected in the base64 encoded data", omni::exceptions::invalid_parse("Invalid base64 encoded data")) break; \
}


namespace omni {
    namespace crypto {
        namespace base64 {
            template < template < class, class > class std_seq_t, class T, class std_allocator_t >
            inline void decode(const std::string& data, std_seq_t<T, std_allocator_t >& out_buff)
            {
                if (!data.empty()) {
                    std::size_t pos1, pos1a, pos2, pos2a;
                    for (std::size_t pos = 0; pos < data.size(); pos += 4) {
                        OMNI_CYRPTO_BASE64_CHAR_POS((data[pos+1]), pos1)
                        OMNI_CYRPTO_BASE64_CHAR_POS((data[pos+0]), pos1a)
                        out_buff.push_back(static_cast<T>((pos1a << 2) + ((pos1 & 0x30) >> 4)));
                        if (((pos + 2) < data.size()) && (data[pos+2] != '=') && (data[pos+2] != '.')) {
                            OMNI_CYRPTO_BASE64_CHAR_POS((data[pos+2]), pos2)
                            out_buff.push_back(static_cast<T>(((pos1 & 0x0F) << 4) + ((pos2 & 0x3C) >> 2)));
                            if (((pos + 3) < data.size()) && (data[pos+3] != '=') && (data[pos+3] != '.')) {
                                OMNI_CYRPTO_BASE64_CHAR_POS((data[pos+3]), pos2a)
                                out_buff.push_back(static_cast<T>(((pos2 & 0x03) << 6) + pos2a));
                            }
                        }
                    }
                }
            }

            inline omni_seq_t<uint8_t> decode(const std::string& data)
            {
                omni_seq_t<uint8_t> buff;
                omni::crypto::base64::decode(data, buff);
                return buff;
            }

            inline std::string encode(unsigned char const* data, std::size_t size, bool url)
            {
                if ((data == OMNI_NULL_PTR) || (size == 0)) {
                    return std::string();
                }
                const char *const CHARS[] = OMNI_CRYPTO_BASE64_CHARS;
                unsigned char end = url ? '.' : '=';
                std::string ret;
                ret.reserve((((size +2) / 3) * 4));
                for (std::size_t pos = 0; pos < size; pos += 3) {
                    ret.push_back(CHARS[url][(data[pos] & 0xFC) >> 2]);
                    if ((pos + 1) < size) {
                        ret.push_back(CHARS[url][(((data[pos] & 0x03) << 4) + ((data[(pos + 1)] & 0xF0) >> 4))]);
                        if ((pos + 2) < size) {
                            ret.push_back(CHARS[url][(((data[(pos + 1)] & 0x0F) << 2) + ((data[(pos + 2)] & 0xC0) >> 6))]);
                            ret.push_back(CHARS[url][(data[(pos + 2)] & 0x3F)]);
                        } else {
                            ret.push_back(CHARS[url][((data[pos + 1] & 0x0F) << 2)]);
                            ret.push_back(static_cast<char>(end));
                        }
                    } else {
                        ret.push_back(CHARS[url][((data[(pos + 0)] & 0x03) << 4)]);
                        ret.push_back(static_cast<char>(end));
                        ret.push_back(static_cast<char>(end));
                    }
                }
                return ret;
            }

            inline std::string encode(unsigned char const* data, std::size_t size)
            {
                return omni::crypto::base64::encode(data, size, false);
            }

            inline std::string encode(const std::string& data, bool url)
            {
                return omni::crypto::base64::encode(reinterpret_cast<const unsigned char*>(data.data()), data.size(), url);
            }

            inline std::string encode(const std::string& data)
            {
                return omni::crypto::base64::encode(reinterpret_cast<const unsigned char*>(data.data()), data.size(), false);
            }
        }
    }
}

#endif // OMNI_CRYPTO_BASE64_HPP