Coverage Report

Created: 2025-06-24 07:03

/src/moddable/modules/data/base64/modBase64.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2016-2021  Moddable Tech, Inc.
3
 *
4
 *   This file is part of the Moddable SDK Runtime.
5
 * 
6
 *   The Moddable SDK Runtime is free software: you can redistribute it and/or modify
7
 *   it under the terms of the GNU Lesser General Public License as published by
8
 *   the Free Software Foundation, either version 3 of the License, or
9
 *   (at your option) any later version.
10
 * 
11
 *   The Moddable SDK Runtime is distributed in the hope that it will be useful,
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *   GNU Lesser General Public License for more details.
15
 * 
16
 *   You should have received a copy of the GNU Lesser General Public License
17
 *   along with the Moddable SDK Runtime.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * This file incorporates work covered by the following copyright and  
20
 * permission notice:  
21
 *
22
 *       Copyright (C) 2010-2016 Marvell International Ltd.
23
 *       Copyright (C) 2002-2010 Kinoma, Inc.
24
 *
25
 *       Licensed under the Apache License, Version 2.0 (the "License");
26
 *       you may not use this file except in compliance with the License.
27
 *       You may obtain a copy of the License at
28
 *
29
 *        http://www.apache.org/licenses/LICENSE-2.0
30
 *
31
 *       Unless required by applicable law or agreed to in writing, software
32
 *       distributed under the License is distributed on an "AS IS" BASIS,
33
 *       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
 *       See the License for the specific language governing permissions and
35
 *       limitations under the License.
36
 */
37
38
/*
39
  modeled on FskStrB64Decode and FskStrB64Encode from KPR.
40
*/
41
42
#include "xsmc.h"
43
#include "xsHost.h"
44
45
void xs_base64_encode(xsMachine *the)
46
0
{
47
0
  static const char b64[] ICACHE_XS6RO2_ATTR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
48
0
  xsType    srcType;
49
0
  uint8_t   *src, *dst;
50
0
  uint32_t  srcSize, dstSize;
51
0
  uint8_t   a, b, c;
52
53
0
  srcType = xsmcTypeOf(xsArg(0));
54
0
  if (xsStringType == srcType) {
55
0
    src = (uint8_t *)xsmcToString(xsArg(0));
56
0
    srcSize = c_strlen((char *)src);
57
0
  }
58
0
  else
59
0
    xsmcGetBufferReadable(xsArg(0), (void **)&src, &srcSize);
60
0
  dstSize = (((srcSize + 2) / 3) * 4) + 1;
61
62
0
  xsResult = xsStringBuffer(NULL, dstSize);
63
0
  if (xsStringType == srcType)
64
0
    src = (uint8_t *)xsmcToString(xsArg(0));   // refresh pointer
65
0
  else
66
0
    xsmcGetBufferReadable(xsArg(0), (void **)&src, &srcSize);
67
0
  dst = (uint8_t *)xsmcToString(xsResult);
68
69
0
  while (srcSize > 2) {
70
0
    a = c_read8(src++);
71
0
    b = c_read8(src++);
72
0
    c = c_read8(src++);
73
0
    *dst++ = c_read8(b64 + ((a & 0xfc) >> 2));
74
0
    *dst++ = c_read8(b64 + (((a & 0x3) << 4) | ((b & 0xf0) >> 4)));
75
0
    *dst++ = c_read8(b64 + (((b & 0xf) << 2) | ((c & 0xc0) >> 6)));
76
0
    *dst++ = c_read8(b64 + (c & 0x3f));
77
0
    srcSize -= 3;
78
0
  }
79
80
0
  if (srcSize == 2) {
81
0
    a = c_read8(src++);
82
0
    b = c_read8(src++);
83
0
    *dst++ = c_read8(b64 + ((a & 0xfc) >> 2));
84
0
    *dst++ = c_read8(b64 + (((a & 0x3) << 4) | ((b & 0xf0) >> 4)));
85
0
    *dst++ = c_read8(b64 + ((b & 0xf) << 2));
86
0
    *dst++ = '=';
87
0
  }
88
0
  else if (srcSize == 1) {
89
0
    a = c_read8(src++);
90
0
    *dst++ = c_read8(b64 + ((a & 0xfc) >> 2));
91
0
    *dst++ = c_read8(b64 + ((a & 0x3) << 4));
92
0
    *dst++ = '=';
93
0
    *dst++ = '=';
94
0
  }
95
96
0
  *dst++ = 0;
97
0
}
98
99
void xs_base64_decode(xsMachine *the)
100
0
{
101
0
  uint8_t   *src;
102
0
  uint32_t  srcSize, dstSize, srcIndex, dstIndex;
103
0
  uint8_t   aFlag = 0;
104
0
  uint8_t   aByte;
105
0
  uint8_t   aBuffer[4];
106
0
  uint8_t   *dst, *dstStart;
107
108
0
  src = (uint8_t *)xsmcToString(xsArg(0));
109
0
  srcSize = c_strlen((char *)src);
110
111
0
  dstSize = (srcSize / 4) * 3;
112
0
  if (c_read8(src + srcSize - 1) == '=')
113
0
    dstSize--;
114
0
  if (c_read8(src + srcSize - 2) == '=')
115
0
    dstSize--;
116
0
  srcIndex = 0;
117
118
0
  xsmcSetArrayBufferResizable(xsResult, NULL, dstSize, dstSize);
119
0
  dst = dstStart = xsmcToArrayBuffer(xsResult);
120
121
0
  src = (uint8_t *)xsmcToString(xsArg(0)); // refresh pointer
122
123
0
  dstIndex = 3;
124
0
  while ((aByte = c_read8(src++))) {
125
0
    if (('A' <= aByte) && (aByte <= 'Z'))
126
0
      aByte = aByte - 'A';
127
0
    else if (('a' <= aByte) && (aByte <= 'z'))
128
0
      aByte = aByte - 'a' + 26;
129
0
    else if (('0' <= aByte) && (aByte <= '9'))
130
0
      aByte = aByte - '0' + 52;
131
0
    else if (aByte == '+')
132
0
      aByte = 62;
133
0
    else if (aByte == '/')
134
0
      aByte = 63;
135
0
    else if (aByte == '=') {
136
0
      if (srcIndex == 2) {
137
0
        if (c_read8(src) == '=') {
138
0
          aBuffer[srcIndex++] = 0;
139
0
          dstIndex = 1;
140
0
          aByte = 0;
141
0
          aFlag = 1;
142
0
        }
143
0
        else
144
0
          continue;
145
0
      }
146
0
      else if (srcIndex == 3) {
147
0
        dstIndex = 2;
148
0
        aByte = 0;
149
0
        aFlag = 1;
150
0
      }
151
0
      else
152
0
        continue;
153
0
    }
154
0
    else
155
0
      continue;
156
0
    aBuffer[srcIndex++] = aByte;
157
0
    if (srcIndex == 4) {
158
0
      *dst++ = (aBuffer[0] << 2) | ((aBuffer[1] & 0x30) >> 4);
159
0
      if (dstIndex > 1)
160
0
        *dst++ = ((aBuffer[1] & 0x0F) << 4) | ((aBuffer[2] & 0x3C) >> 2);
161
0
      if (dstIndex > 2)
162
0
        *dst++ = ((aBuffer[2] & 0x03) << 6) | (aBuffer[3] & 0x3F);
163
0
      srcIndex = 0;
164
0
    }
165
0
    if (aFlag)
166
0
      break;
167
0
  }
168
169
0
  xsmcSetArrayBufferLength(xsResult, dst - dstStart);
170
0
}
171
172
void modInstallBase64(xsMachine *the)
173
0
{
174
0
  #define kNamespace (0)
175
0
  #define kScratch (1)
176
177
0
  xsBeginHost(the);
178
0
  xsmcVars(2);
179
180
0
  xsVar(kNamespace) = xsNewObject();
181
0
  xsmcDefine(xsGlobal, xsID("Base64"), xsVar(kNamespace), xsDontEnum);
182
0
  xsVar(kScratch) = xsNewHostFunction(xs_base64_encode, 1);
183
0
  xsmcDefine(xsVar(kNamespace), xsID("encode"), xsVar(kScratch), xsDontEnum);
184
0
  xsVar(kScratch) = xsNewHostFunction(xs_base64_decode, 1);
185
0
  xsmcDefine(xsVar(kNamespace), xsID("decode"), xsVar(kScratch), xsDontEnum);
186
187
0
  xsEndHost(the);
188
0
}