1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci
9cb93a386Sopenharmony_ci#include "include/utils/SkBase64.h"
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#define DecodePad -2
12cb93a386Sopenharmony_ci#define EncodePad 64
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_cistatic const char default_encode[] =
15cb93a386Sopenharmony_ci    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
16cb93a386Sopenharmony_ci    "abcdefghijklmnopqrstuvwxyz"
17cb93a386Sopenharmony_ci    "0123456789+/=";
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_cistatic const signed char decodeData[] = {
20cb93a386Sopenharmony_ci    62, -1, -1, -1, 63,
21cb93a386Sopenharmony_ci    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, DecodePad, -1, -1,
22cb93a386Sopenharmony_ci    -1,  0,  1,  2,  3,  4,  5,  6, 7,  8,  9, 10, 11, 12, 13, 14,
23cb93a386Sopenharmony_ci    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
24cb93a386Sopenharmony_ci    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
25cb93a386Sopenharmony_ci    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
26cb93a386Sopenharmony_ci};
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ci#if defined _WIN32  // disable 'two', etc. may be used without having been initialized
29cb93a386Sopenharmony_ci#pragma warning ( push )
30cb93a386Sopenharmony_ci#pragma warning ( disable : 4701 )
31cb93a386Sopenharmony_ci#endif
32cb93a386Sopenharmony_ci
33cb93a386Sopenharmony_ciSkBase64::Error SkBase64::Decode(const void* srcv, size_t srcLength, void* dstv, size_t* dstLength){
34cb93a386Sopenharmony_ci    const unsigned char* src = static_cast<const unsigned char*>(srcv);
35cb93a386Sopenharmony_ci    unsigned char* dst = static_cast<unsigned char*>(dstv);
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci    int i = 0;
38cb93a386Sopenharmony_ci    bool padTwo = false;
39cb93a386Sopenharmony_ci    bool padThree = false;
40cb93a386Sopenharmony_ci    char unsigned const * const end = src + srcLength;
41cb93a386Sopenharmony_ci    while (src < end) {
42cb93a386Sopenharmony_ci        unsigned char bytes[4];
43cb93a386Sopenharmony_ci        int byte = 0;
44cb93a386Sopenharmony_ci        do {
45cb93a386Sopenharmony_ci            unsigned char srcByte = *src++;
46cb93a386Sopenharmony_ci            if (srcByte == 0)
47cb93a386Sopenharmony_ci                goto goHome;
48cb93a386Sopenharmony_ci            if (srcByte <= ' ')
49cb93a386Sopenharmony_ci                continue; // treat as white space
50cb93a386Sopenharmony_ci            if (srcByte < '+' || srcByte > 'z')
51cb93a386Sopenharmony_ci                return kBadCharError;
52cb93a386Sopenharmony_ci            signed char decoded = decodeData[srcByte - '+'];
53cb93a386Sopenharmony_ci            bytes[byte] = decoded;
54cb93a386Sopenharmony_ci            if (decoded < 0) {
55cb93a386Sopenharmony_ci                if (decoded == DecodePad)
56cb93a386Sopenharmony_ci                    goto handlePad;
57cb93a386Sopenharmony_ci                return kBadCharError;
58cb93a386Sopenharmony_ci            } else
59cb93a386Sopenharmony_ci                byte++;
60cb93a386Sopenharmony_ci            if (*src)
61cb93a386Sopenharmony_ci                continue;
62cb93a386Sopenharmony_ci            if (byte == 0)
63cb93a386Sopenharmony_ci                goto goHome;
64cb93a386Sopenharmony_ci            if (byte == 4)
65cb93a386Sopenharmony_ci                break;
66cb93a386Sopenharmony_cihandlePad:
67cb93a386Sopenharmony_ci            if (byte < 2)
68cb93a386Sopenharmony_ci                return kPadError;
69cb93a386Sopenharmony_ci            padThree = true;
70cb93a386Sopenharmony_ci            if (byte == 2)
71cb93a386Sopenharmony_ci                padTwo = true;
72cb93a386Sopenharmony_ci            break;
73cb93a386Sopenharmony_ci        } while (byte < 4);
74cb93a386Sopenharmony_ci        int two = 0;
75cb93a386Sopenharmony_ci        int three = 0;
76cb93a386Sopenharmony_ci        if (dst) {
77cb93a386Sopenharmony_ci            int one = (uint8_t) (bytes[0] << 2);
78cb93a386Sopenharmony_ci            two = bytes[1];
79cb93a386Sopenharmony_ci            one |= two >> 4;
80cb93a386Sopenharmony_ci            two = (uint8_t) ((two << 4) & 0xFF);
81cb93a386Sopenharmony_ci            three = bytes[2];
82cb93a386Sopenharmony_ci            two |= three >> 2;
83cb93a386Sopenharmony_ci            three = (uint8_t) ((three << 6) & 0xFF);
84cb93a386Sopenharmony_ci            three |= bytes[3];
85cb93a386Sopenharmony_ci            SkASSERT(one < 256 && two < 256 && three < 256);
86cb93a386Sopenharmony_ci            dst[i] = (unsigned char) one;
87cb93a386Sopenharmony_ci        }
88cb93a386Sopenharmony_ci        i++;
89cb93a386Sopenharmony_ci        if (padTwo)
90cb93a386Sopenharmony_ci            break;
91cb93a386Sopenharmony_ci        if (dst)
92cb93a386Sopenharmony_ci            dst[i] = (unsigned char) two;
93cb93a386Sopenharmony_ci        i++;
94cb93a386Sopenharmony_ci        if (padThree)
95cb93a386Sopenharmony_ci            break;
96cb93a386Sopenharmony_ci        if (dst)
97cb93a386Sopenharmony_ci            dst[i] = (unsigned char) three;
98cb93a386Sopenharmony_ci        i++;
99cb93a386Sopenharmony_ci    }
100cb93a386Sopenharmony_cigoHome:
101cb93a386Sopenharmony_ci    *dstLength = i;
102cb93a386Sopenharmony_ci    return kNoError;
103cb93a386Sopenharmony_ci}
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ci#if defined _WIN32
106cb93a386Sopenharmony_ci#pragma warning ( pop )
107cb93a386Sopenharmony_ci#endif
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_cisize_t SkBase64::Encode(const void* srcv, size_t length, void* dstv, const char* encodeMap) {
110cb93a386Sopenharmony_ci    const unsigned char* src = static_cast<const unsigned char*>(srcv);
111cb93a386Sopenharmony_ci    unsigned char* dst = static_cast<unsigned char*>(dstv);
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    const char* encode;
114cb93a386Sopenharmony_ci    if (nullptr == encodeMap) {
115cb93a386Sopenharmony_ci        encode = default_encode;
116cb93a386Sopenharmony_ci    } else {
117cb93a386Sopenharmony_ci        encode = encodeMap;
118cb93a386Sopenharmony_ci    }
119cb93a386Sopenharmony_ci    if (dst) {
120cb93a386Sopenharmony_ci        size_t remainder = length % 3;
121cb93a386Sopenharmony_ci        char unsigned const * const end = &src[length - remainder];
122cb93a386Sopenharmony_ci        while (src < end) {
123cb93a386Sopenharmony_ci            unsigned a = *src++;
124cb93a386Sopenharmony_ci            unsigned b = *src++;
125cb93a386Sopenharmony_ci            unsigned c = *src++;
126cb93a386Sopenharmony_ci            int      d = c & 0x3F;
127cb93a386Sopenharmony_ci            c = (c >> 6 | b << 2) & 0x3F;
128cb93a386Sopenharmony_ci            b = (b >> 4 | a << 4) & 0x3F;
129cb93a386Sopenharmony_ci            a = a >> 2;
130cb93a386Sopenharmony_ci            *dst++ = encode[a];
131cb93a386Sopenharmony_ci            *dst++ = encode[b];
132cb93a386Sopenharmony_ci            *dst++ = encode[c];
133cb93a386Sopenharmony_ci            *dst++ = encode[d];
134cb93a386Sopenharmony_ci        }
135cb93a386Sopenharmony_ci        if (remainder > 0) {
136cb93a386Sopenharmony_ci            int k1 = 0;
137cb93a386Sopenharmony_ci            int k2 = EncodePad;
138cb93a386Sopenharmony_ci            int a = (uint8_t) *src++;
139cb93a386Sopenharmony_ci            if (remainder == 2)
140cb93a386Sopenharmony_ci            {
141cb93a386Sopenharmony_ci                int b = *src++;
142cb93a386Sopenharmony_ci                k1 = b >> 4;
143cb93a386Sopenharmony_ci                k2 = (b << 2) & 0x3F;
144cb93a386Sopenharmony_ci            }
145cb93a386Sopenharmony_ci            *dst++ = encode[a >> 2];
146cb93a386Sopenharmony_ci            *dst++ = encode[(k1 | a << 4) & 0x3F];
147cb93a386Sopenharmony_ci            *dst++ = encode[k2];
148cb93a386Sopenharmony_ci            *dst++ = encode[EncodePad];
149cb93a386Sopenharmony_ci        }
150cb93a386Sopenharmony_ci    }
151cb93a386Sopenharmony_ci    return (length + 2) / 3 * 4;
152cb93a386Sopenharmony_ci}
153