Skip to content

Commit 2e4cb9c

Browse files
authored
Merge pull request #2 from mateusz1913/fix/cpp-containers-and-base64
fix: use std::vector and implement base64 with library
2 parents 71d5a5a + 1d85223 commit 2e4cb9c

File tree

8 files changed

+731
-96
lines changed

8 files changed

+731
-96
lines changed

.changeset/eighty-eels-lose.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'react-native-encoding': 'patch'
3+
---
4+
5+
Use std::vector instead of raw pointers, use base64 implementation from https://github.com/tobiaslocker/base64

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ function YEET(inputBuffer: Uint8Array) {
4747
- ✅ You can use this library with [Development Builds](https://docs.expo.dev/development/introduction/).
4848
- ❌ This library can't be used in the "Expo Go" app because it [requires custom native code](https://docs.expo.dev/workflow/customizing/).
4949

50+
## Acknowledgements
51+
52+
Base64 is implemented using https://github.com/tobiaslocker/base64 under MIT license
53+
5054
## Contributing
5155

5256
See the [contributing guide](./CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.

cpp/ReactNativeEncodingArrayBuffer.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22

33
namespace facebook::react {
44

5-
ReactNativeEncodingArrayBuffer::ReactNativeEncodingArrayBuffer(uint8_t *data, size_t size)
6-
: jsi::MutableBuffer(), data_(data), size_(size) {}
5+
ReactNativeEncodingArrayBuffer::ReactNativeEncodingArrayBuffer(std::vector<uint8_t> data, size_t size)
6+
: jsi::MutableBuffer(), data_(std::move(data)), size_(size) {}
77

88
std::shared_ptr<ReactNativeEncodingArrayBuffer> ReactNativeEncodingArrayBuffer::fromString(const std::string &str) {
9-
auto buffer = new uint8_t[str.size()];
10-
std::copy(str.data(), str.data() + str.size(), buffer);
11-
return std::make_shared<ReactNativeEncodingArrayBuffer>(buffer, str.size());
9+
std::vector buffer(str.begin(), str.end());
10+
auto size = buffer.size();
11+
return std::make_shared<ReactNativeEncodingArrayBuffer>(std::move(buffer), size);
1212
}
1313

1414
uint8_t *ReactNativeEncodingArrayBuffer::data() {
15-
return data_;
15+
return data_.data();
1616
}
1717

1818
size_t ReactNativeEncodingArrayBuffer::size() const {

cpp/ReactNativeEncodingArrayBuffer.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
#pragma once
22

3+
#include <vector>
4+
35
#include <jsi/jsi.h>
46

57
namespace facebook::react {
68

79
class ReactNativeEncodingArrayBuffer : public jsi::MutableBuffer {
810
public:
9-
explicit ReactNativeEncodingArrayBuffer(uint8_t *data, size_t size);
11+
explicit ReactNativeEncodingArrayBuffer(std::vector<uint8_t> data, size_t size);
1012

1113
static std::shared_ptr<ReactNativeEncodingArrayBuffer> fromString(const std::string &str);
1214

1315
[[nodiscard]] size_t size() const override;
1416
uint8_t *data() override;
1517

1618
private:
17-
uint8_t *data_;
19+
std::vector<uint8_t> data_;
1820
size_t size_;
1921
};
2022

encoding-core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(CMAKE_VERBOSE_MAKEFILE on)
77
add_library(ReactNativeEncodingCore SHARED
88
${CMAKE_CURRENT_SOURCE_DIR}/ReactNativeEncodingBase64.cpp
99
${CMAKE_CURRENT_SOURCE_DIR}/ReactNativeEncodingBase64.h
10+
${CMAKE_CURRENT_SOURCE_DIR}/base64.hpp
1011
${CMAKE_CURRENT_SOURCE_DIR}/ReactNativeEncodingHex.cpp
1112
${CMAKE_CURRENT_SOURCE_DIR}/ReactNativeEncodingHex.h)
1213

Lines changed: 4 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,11 @@
11
#include "ReactNativeEncodingBase64.h"
22

3-
static const uint8_t base64DecodingTable[128] = {
4-
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, /* 0 - 15 */
5-
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, /* 16 - 31 */
6-
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 62, 99, 99, 99, 63, /* 32 - 47 */
7-
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 99, 99, 99, 64, 99, 99, /* 48 - 63 */
8-
99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 64 - 79 */
9-
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 99, 99, 99, 99, 99, /* 80 - 95 */
10-
99, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 96 - 111 */
11-
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 99, 99, 99, 99, 99 /* 112 - 127 */
12-
};
133
std::string decodeFromBase64BufferToUtf8String(const uint8_t *data, const size_t size) {
14-
bool pad = data[size - 1] == (uint8_t)'=';
15-
size_t offset;
16-
17-
if (pad) {
18-
offset = ((size / 4) - 1) * 4;
19-
} else {
20-
offset = (size / 4) * 4;
21-
}
22-
23-
bool isPad1 = data[offset + 2] != (uint8_t)'=';
24-
25-
std::string decodedStr;
26-
decodedStr.reserve(offset + (isPad1 ? 2 : 1));
27-
28-
for (auto p = (uint8_t *)data; p != data + offset; p += 4) {
29-
uint8_t b1 = base64DecodingTable[p[0]];
30-
uint8_t b2 = base64DecodingTable[p[1]];
31-
uint8_t b3 = base64DecodingTable[p[2]];
32-
uint8_t b4 = base64DecodingTable[p[3]];
33-
34-
uint32_t quartet = unsigned(b1) << 18 | unsigned(b2) << 12 | unsigned(b3) << 6 | b4;
35-
36-
decodedStr.push_back((char)(quartet >> 16));
37-
decodedStr.push_back((char)((quartet >> 8) & 0xFF));
38-
decodedStr.push_back((char)(quartet & 0xFF));
39-
}
40-
41-
if (pad) {
42-
uint8_t b1 = base64DecodingTable[data[offset]];
43-
uint8_t b2 = base64DecodingTable[data[offset + 1]];
44-
45-
uint32_t quartet = unsigned(b1) << 18 | unsigned(b2) << 12;
46-
47-
decodedStr.push_back((char)(quartet >> 16));
48-
49-
if (isPad1) {
50-
uint8_t b3 = base64DecodingTable[data[offset + 2]];
51-
52-
decodedStr.push_back((char)(((quartet | (unsigned(b3) << 6)) >> 8) & 0xFF));
53-
}
54-
}
55-
56-
return decodedStr;
4+
std::string_view str_view(reinterpret_cast<const char *>(data), size);
5+
return base64::from_base64(str_view);
576
}
587

59-
static const std::string base64EncodingTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
608
std::string encodeFromUtf8BufferToBase64String(const uint8_t *data, const size_t size) {
61-
size_t pad = size % 3;
62-
size_t last = size - pad;
63-
64-
size_t encodedStrSize = ((size + 2) / 3) * 4;
65-
std::string encodedStr(encodedStrSize, '=');
66-
67-
int i = 0;
68-
for (auto p = (uint8_t *)data; p != data + last; p += 3) {
69-
uint32_t triple = unsigned(p[0]) << 16 | unsigned(p[1]) << 8 | p[2];
70-
71-
encodedStr[i++] = base64EncodingTable[triple >> 18];
72-
encodedStr[i++] = base64EncodingTable[(triple >> 12) & 0x3F];
73-
encodedStr[i++] = base64EncodingTable[(triple >> 6) & 0x3F];
74-
encodedStr[i++] = base64EncodingTable[triple & 0x3F];
75-
}
76-
77-
if (pad) {
78-
uint8_t *p = (uint8_t *)data + last;
79-
80-
if (pad == 1) {
81-
auto triple = unsigned(p[0]);
82-
83-
encodedStr[i++] = base64EncodingTable[triple >> 2];
84-
encodedStr[i++] = base64EncodingTable[(triple << 4) & 0x3F];
85-
} else if (pad == 2) {
86-
auto triple = unsigned(p[0]) << 8 | p[1];
87-
88-
encodedStr[i++] = base64EncodingTable[triple >> 10];
89-
encodedStr[i++] = base64EncodingTable[(triple >> 4) & 0x3F];
90-
encodedStr[i++] = base64EncodingTable[(triple << 2) & 0x3F];
91-
}
92-
}
93-
94-
return encodedStr;
9+
std::string_view str_view(reinterpret_cast<const char *>(data), size);
10+
return base64::to_base64(str_view);
9511
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#pragma once
22

3+
#include <base64.hpp>
34
#include <cstdint>
45
#include <string>
6+
#include <string_view>
57

68
std::string decodeFromBase64BufferToUtf8String(const uint8_t *data, size_t size);
79
std::string encodeFromUtf8BufferToBase64String(const uint8_t *data, size_t size);

0 commit comments

Comments
 (0)