OpenShot Audio Library | OpenShotAudio  0.6.0
juce_Base64.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 bool Base64::convertToBase64 (OutputStream& base64Result, const void* sourceData, size_t sourceDataSize)
27 {
28  static const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
29  auto* source = static_cast<const uint8*> (sourceData);
30 
31  while (sourceDataSize > 0)
32  {
33  char frame[4];
34  auto byte0 = *source++;
35  frame[0] = lookup [(byte0 & 0xfcu) >> 2];
36  uint32 bits = (byte0 & 0x03u) << 4;
37 
38  if (sourceDataSize > 1)
39  {
40  auto byte1 = *source++;
41  frame[1] = lookup[bits | ((byte1 & 0xf0u) >> 4)];
42  bits = (byte1 & 0x0fu) << 2;
43 
44  if (sourceDataSize > 2)
45  {
46  auto byte2 = *source++;
47  frame[2] = lookup[bits | ((byte2 & 0xc0u) >> 6)];
48  frame[3] = lookup[byte2 & 0x3fu];
49  sourceDataSize -= 3;
50  }
51  else
52  {
53  frame[2] = lookup[bits];
54  frame[3] = '=';
55  sourceDataSize = 0;
56  }
57  }
58  else
59  {
60  frame[1] = lookup[bits];
61  frame[2] = '=';
62  frame[3] = '=';
63  sourceDataSize = 0;
64  }
65 
66  if (! base64Result.write (frame, 4))
67  return false;
68  }
69 
70  return true;
71 }
72 
73 bool Base64::convertFromBase64 (OutputStream& binaryOutput, StringRef base64TextInput)
74 {
75  for (auto s = base64TextInput.text; ! s.isEmpty();)
76  {
77  uint8 data[4];
78 
79  for (int i = 0; i < 4; ++i)
80  {
81  auto c = (uint32) s.getAndAdvance();
82 
83  if (c >= 'A' && c <= 'Z') c -= 'A';
84  else if (c >= 'a' && c <= 'z') c -= 'a' - 26;
85  else if (c >= '0' && c <= '9') c += 52 - '0';
86  else if (c == '+') c = 62;
87  else if (c == '/') c = 63;
88  else if (c == '=') { c = 64; if (i <= 1) return false; }
89  else return false;
90 
91  data[i] = (uint8) c;
92  }
93 
94  binaryOutput.writeByte ((char) ((data[0] << 2) | (data[1] >> 4)));
95 
96  if (data[2] < 64)
97  {
98  binaryOutput.writeByte ((char) ((data[1] << 4) | (data[2] >> 2)));
99 
100  if (data[3] < 64)
101  binaryOutput.writeByte ((char) ((data[2] << 6) | data[3]));
102  }
103  }
104 
105  return true;
106 }
107 
108 String Base64::toBase64 (const void* sourceData, size_t sourceDataSize)
109 {
110  MemoryOutputStream m ((sourceDataSize * 4) / 3 + 3);
111  [[maybe_unused]] bool ok = convertToBase64 (m, sourceData, sourceDataSize);
112  jassert (ok); // should always succeed for this simple case
113  return m.toString();
114 }
115 
117 {
118  return toBase64 (text.toRawUTF8(), strlen (text.toRawUTF8()));
119 }
120 
121 
122 //==============================================================================
123 //==============================================================================
124 #if JUCE_UNIT_TESTS
125 
126 class Base64Tests final : public UnitTest
127 {
128 public:
129  Base64Tests()
130  : UnitTest ("Base64 class", UnitTestCategories::text)
131  {}
132 
133  static MemoryBlock createRandomData (Random& r)
134  {
135  MemoryOutputStream m;
136 
137  for (int i = r.nextInt (400); --i >= 0;)
138  m.writeByte ((char) r.nextInt (256));
139 
140  return m.getMemoryBlock();
141  }
142 
143  void runTest() override
144  {
145  beginTest ("Base64");
146 
147  auto r = getRandom();
148 
149  for (int i = 1000; --i >= 0;)
150  {
151  auto original = createRandomData (r);
152  auto asBase64 = Base64::toBase64 (original.getData(), original.getSize());
153  MemoryOutputStream out;
154  expect (Base64::convertFromBase64 (out, asBase64));
155  auto result = out.getMemoryBlock();
156  expect (result == original);
157  }
158  }
159 };
160 
161 static Base64Tests base64Tests;
162 
163 #endif
164 
165 } // namespace juce
virtual bool write(const void *dataToWrite, size_t numberOfBytes)=0
virtual bool writeByte(char byte)
String::CharPointerType text
const char * toRawUTF8() const
static bool convertToBase64(OutputStream &base64Result, const void *sourceData, size_t sourceDataSize)
Definition: juce_Base64.cpp:26
static String toBase64(const void *sourceData, size_t sourceDataSize)
static bool convertFromBase64(OutputStream &binaryOutput, StringRef base64TextInput)
Definition: juce_Base64.cpp:73