OpenShot Library | OpenShotAudio  0.2.1
juce_Base64.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
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  bool ok = convertToBase64 (m, sourceData, sourceDataSize);
112  jassert (ok); // should always succeed for this simple case
113  ignoreUnused (ok);
114  return m.toString();
115 }
116 
118 {
119  return toBase64 (text.toRawUTF8(), strlen (text.toRawUTF8()));
120 }
121 
122 
123 //==============================================================================
124 //==============================================================================
125 #if JUCE_UNIT_TESTS
126 
127 class Base64Tests : public UnitTest
128 {
129 public:
130  Base64Tests()
131  : UnitTest ("Base64 class", UnitTestCategories::text)
132  {}
133 
134  static MemoryBlock createRandomData (Random& r)
135  {
137 
138  for (int i = r.nextInt (400); --i >= 0;)
139  m.writeByte ((char) r.nextInt (256));
140 
141  return m.getMemoryBlock();
142  }
143 
144  void runTest() override
145  {
146  beginTest ("Base64");
147 
148  auto r = getRandom();
149 
150  for (int i = 1000; --i >= 0;)
151  {
152  auto original = createRandomData (r);
153  auto asBase64 = Base64::toBase64 (original.getData(), original.getSize());
154  MemoryOutputStream out;
155  expect (Base64::convertFromBase64 (out, asBase64));
156  auto result = out.getMemoryBlock();
157  expect (result == original);
158  }
159  }
160 };
161 
162 static Base64Tests base64Tests;
163 
164 #endif
165 
166 } // namespace juce
virtual bool write(const void *dataToWrite, size_t numberOfBytes)=0
Writes a block of data to the stream.
const char * toRawUTF8() const
Returns a pointer to a UTF-8 version of this string.
virtual bool writeByte(char byte)
Writes a single byte to the stream.
int nextInt() noexcept
Returns the next random 32 bit integer.
Definition: juce_Random.cpp:78
A simple class for holding temporary references to a string literal or String.
static bool convertToBase64(OutputStream &base64Result, const void *sourceData, size_t sourceDataSize)
Converts a binary block of data into a base-64 string.
Definition: juce_Base64.cpp:26
MemoryBlock getMemoryBlock() const
Returns a copy of the stream&#39;s data as a memory block.
bool isEmpty() const noexcept
Returns true if this pointer is pointing to a null character.
The JUCE String class!
Definition: juce_String.h:42
This is a base class for classes that perform a unit test.
Definition: juce_UnitTest.h:73
The base class for streams that write data to some kind of destination.
String::CharPointerType text
The text that is referenced.
static String toBase64(const void *sourceData, size_t sourceDataSize)
Converts a block of binary data to a base-64 string.
A random number generator.
Definition: juce_Random.h:38
Writes data to an internal memory buffer, which grows as required.
A class to hold a resizable block of raw data.
String toString() const
Attempts to detect the encoding of the data and convert it to a string.
static bool convertFromBase64(OutputStream &binaryOutput, StringRef base64TextInput)
Converts a base-64 string back to its binary representation.
Definition: juce_Base64.cpp:73