Coverage Report

Created: 2026-06-28 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/modules/data/base64/modBase64.c
Line
Count
Source
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
  srcIndex = 0;
113
114
0
  xsmcSetArrayBufferResizable(xsResult, NULL, dstSize, dstSize);
115
0
  dst = dstStart = xsmcToArrayBuffer(xsResult);
116
117
0
  src = (uint8_t *)xsmcToString(xsArg(0)); // refresh pointer
118
119
0
  dstIndex = 3;
120
0
  while ((aByte = c_read8(src++))) {
121
0
    if (('A' <= aByte) && (aByte <= 'Z'))
122
0
      aByte = aByte - 'A';
123
0
    else if (('a' <= aByte) && (aByte <= 'z'))
124
0
      aByte = aByte - 'a' + 26;
125
0
    else if (('0' <= aByte) && (aByte <= '9'))
126
0
      aByte = aByte - '0' + 52;
127
0
    else if (aByte == '+')
128
0
      aByte = 62;
129
0
    else if (aByte == '/')
130
0
      aByte = 63;
131
0
    else if (aByte == '=') {
132
0
      if (srcIndex == 2) {
133
0
        if (c_read8(src) == '=') {
134
0
          aBuffer[srcIndex++] = 0;
135
0
          dstIndex = 1;
136
0
          aByte = 0;
137
0
          aFlag = 1;
138
0
        }
139
0
        else
140
0
          continue;
141
0
      }
142
0
      else if (srcIndex == 3) {
143
0
        dstIndex = 2;
144
0
        aByte = 0;
145
0
        aFlag = 1;
146
0
      }
147
0
      else
148
0
        continue;
149
0
    }
150
0
    else
151
0
      continue;
152
0
    aBuffer[srcIndex++] = aByte;
153
0
    if (srcIndex == 4) {
154
0
      *dst++ = (aBuffer[0] << 2) | ((aBuffer[1] & 0x30) >> 4);
155
0
      if (dstIndex > 1)
156
0
        *dst++ = ((aBuffer[1] & 0x0F) << 4) | ((aBuffer[2] & 0x3C) >> 2);
157
0
      if (dstIndex > 2)
158
0
        *dst++ = ((aBuffer[2] & 0x03) << 6) | (aBuffer[3] & 0x3F);
159
0
      srcIndex = 0;
160
0
    }
161
0
    if (aFlag)
162
0
      break;
163
0
  }
164
165
0
  xsmcSetArrayBufferLength(xsResult, dst - dstStart);
166
0
}
167
168
void modInstallBase64(xsMachine *the)
169
0
{
170
0
  #define kNamespace (0)
171
0
  #define kScratch (1)
172
173
0
  xsBeginHost(the);
174
0
  xsmcVars(2);
175
176
0
  xsVar(kNamespace) = xsNewObject();
177
0
  xsmcDefine(xsGlobal, xsID("Base64"), xsVar(kNamespace), xsDontEnum);
178
0
  xsVar(kScratch) = xsNewHostFunction(xs_base64_encode, 1);
179
0
  xsmcDefine(xsVar(kNamespace), xsID("encode"), xsVar(kScratch), xsDontEnum);
180
0
  xsVar(kScratch) = xsNewHostFunction(xs_base64_decode, 1);
181
0
  xsmcDefine(xsVar(kNamespace), xsID("decode"), xsVar(kScratch), xsDontEnum);
182
183
  xsEndHost(the);
184
0
}