Skip to content

Commit aaff15c

Browse files
Andrei Shikovfacebook-github-bot
authored andcommitted
Use std::vector to manage MapBuffer storage
Summary: Replaces raw array pointer inside `MapBuffer` with `std::vector`, which is more conventional "safer" way of storing dynamically sized arrays. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D33512115 fbshipit-source-id: d875a2240f7938fd35c4c3ae0e7e91dc7456ff32
1 parent efc56b2 commit aaff15c

File tree

4 files changed

+47
-47
lines changed

4 files changed

+47
-47
lines changed

ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,24 @@ namespace react {
1414

1515
// TODO T83483191: Extend MapBuffer C++ implementation to support basic random
1616
// access
17-
MapBuffer::MapBuffer(uint8_t *const data, int32_t dataSize) {
18-
react_native_assert(
19-
(data != nullptr) && "Error trying to build an invalid MapBuffer");
20-
21-
// Should we move the memory here or document it?
22-
data_ = data;
23-
17+
MapBuffer::MapBuffer(std::vector<uint8_t> data) : bytes_(std::move(data)) {
2418
count_ = 0;
2519
memcpy(
2620
reinterpret_cast<uint8_t *>(&count_),
27-
reinterpret_cast<const uint8_t *>(data_ + HEADER_COUNT_OFFSET),
21+
bytes_.data() + HEADER_COUNT_OFFSET,
2822
UINT16_SIZE);
2923

3024
// TODO T83483191: extract memcpy calls into an inline function to simplify
3125
// the code
32-
dataSize_ = 0;
26+
int32_t dataSize;
3327
memcpy(
34-
reinterpret_cast<uint8_t *>(&dataSize_),
35-
reinterpret_cast<const uint8_t *>(data_ + HEADER_BUFFER_SIZE_OFFSET),
28+
reinterpret_cast<uint8_t *>(&dataSize),
29+
bytes_.data() + HEADER_BUFFER_SIZE_OFFSET,
3630
INT_SIZE);
3731

38-
if (dataSize != dataSize_) {
32+
if (dataSize != bytes_.size()) {
3933
LOG(ERROR) << "Error: Data size does not match, expected " << dataSize
40-
<< " found: " << dataSize_;
34+
<< " found: " << bytes_.size();
4135
abort();
4236
}
4337
}
@@ -46,7 +40,7 @@ int32_t MapBuffer::getInt(Key key) const {
4640
int32_t value = 0;
4741
memcpy(
4842
reinterpret_cast<uint8_t *>(&value),
49-
reinterpret_cast<const uint8_t *>(data_ + getValueOffset(key)),
43+
bytes_.data() + getValueOffset(key),
5044
INT_SIZE);
5145
return value;
5246
}
@@ -61,7 +55,7 @@ double MapBuffer::getDouble(Key key) const {
6155
double value = 0;
6256
memcpy(
6357
reinterpret_cast<uint8_t *>(&value),
64-
reinterpret_cast<const uint8_t *>(data_ + getValueOffset(key)),
58+
bytes_.data() + getValueOffset(key),
6559
DOUBLE_SIZE);
6660
return value;
6761
}
@@ -80,15 +74,14 @@ std::string MapBuffer::getString(Key key) const {
8074
int32_t offset = getInt(key);
8175
memcpy(
8276
reinterpret_cast<uint8_t *>(&stringLength),
83-
reinterpret_cast<const uint8_t *>(data_ + dynamicDataOffset + offset),
77+
bytes_.data() + dynamicDataOffset + offset,
8478
INT_SIZE);
8579

8680
char *value = new char[stringLength];
8781

8882
memcpy(
8983
reinterpret_cast<char *>(value),
90-
reinterpret_cast<const char *>(
91-
data_ + dynamicDataOffset + offset + INT_SIZE),
84+
bytes_.data() + dynamicDataOffset + offset + INT_SIZE,
9285
stringLength);
9386

9487
return std::string(value, 0, stringLength);
@@ -103,47 +96,41 @@ MapBuffer MapBuffer::getMapBuffer(Key key) const {
10396
int32_t offset = getInt(key);
10497
memcpy(
10598
reinterpret_cast<uint8_t *>(&mapBufferLength),
106-
reinterpret_cast<const uint8_t *>(data_ + dynamicDataOffset + offset),
99+
bytes_.data() + dynamicDataOffset + offset,
107100
INT_SIZE);
108101

109-
uint8_t *value = new Byte[mapBufferLength];
102+
std::vector<uint8_t> value(mapBufferLength);
110103

111104
memcpy(
112-
reinterpret_cast<uint8_t *>(value),
113-
reinterpret_cast<const uint8_t *>(
114-
data_ + dynamicDataOffset + offset + INT_SIZE),
105+
value.data(),
106+
bytes_.data() + dynamicDataOffset + offset + INT_SIZE,
115107
mapBufferLength);
116108

117-
return MapBuffer(value, mapBufferLength);
109+
return MapBuffer(std::move(value));
118110
}
119111

120112
bool MapBuffer::isNull(Key key) const {
121113
return getInt(key) == NULL_VALUE;
122114
}
123115

124116
int32_t MapBuffer::getBufferSize() const {
125-
return dataSize_;
117+
return bytes_.size();
126118
}
127119

128120
void MapBuffer::copy(uint8_t *output) const {
129-
memcpy(output, data_, dataSize_);
121+
memcpy(output, bytes_.data(), bytes_.size());
130122
}
131123

132124
uint16_t MapBuffer::getCount() const {
133125
uint16_t size = 0;
134126

135127
memcpy(
136-
reinterpret_cast<uint16_t *>(&size),
137-
reinterpret_cast<const uint16_t *>(data_ + HEADER_COUNT_OFFSET),
138-
128+
reinterpret_cast<uint8_t *>(&size),
129+
bytes_.data() + HEADER_COUNT_OFFSET,
139130
UINT16_SIZE);
140131

141132
return size;
142133
}
143134

144-
MapBuffer::~MapBuffer() {
145-
delete[] data_;
146-
}
147-
148135
} // namespace react
149136
} // namespace facebook

ReactCommon/react/renderer/mapbuffer/MapBuffer.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <react/debug/react_native_assert.h>
1111
#include <react/renderer/mapbuffer/primitives.h>
1212

13-
#include <stdlib.h>
1413
#include <limits>
1514

1615
namespace facebook {
@@ -34,10 +33,7 @@ namespace react {
3433
class MapBuffer {
3534
private:
3635
// Buffer and its size
37-
const uint8_t *data_ = nullptr;
38-
39-
// amount of bytes in the MapBuffer
40-
int32_t dataSize_ = 0;
36+
std::vector<uint8_t> const bytes_;
4137

4238
// amount of items in the MapBuffer
4339
uint16_t count_ = 0;
@@ -46,9 +42,13 @@ class MapBuffer {
4642
int32_t getDynamicDataOffset() const;
4743

4844
public:
49-
MapBuffer(uint8_t *const data, int32_t dataSize);
45+
explicit MapBuffer(std::vector<uint8_t> data);
46+
47+
MapBuffer(MapBuffer const &buffer) = delete;
48+
49+
MapBuffer &operator=(MapBuffer other) = delete;
5050

51-
~MapBuffer();
51+
MapBuffer(MapBuffer &&buffer) = default;
5252

5353
int32_t getInt(Key key) const;
5454

ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ MapBufferBuilder::MapBufferBuilder()
1717
: MapBufferBuilder::MapBufferBuilder(INITIAL_KEY_VALUE_SIZE) {}
1818

1919
MapBuffer MapBufferBuilder::EMPTY() {
20-
static auto emptyMap = MapBufferBuilder().build();
21-
return emptyMap;
20+
return MapBufferBuilder().build();
2221
}
2322

2423
MapBufferBuilder::MapBufferBuilder(uint16_t initialSize) {
@@ -181,16 +180,18 @@ MapBuffer MapBufferBuilder::build() {
181180
// Copy header at the beginning of "keyValues_"
182181
memcpy(keyValues_, &_header, HEADER_SIZE);
183182

184-
uint8_t *buffer = new Byte[bufferSize];
183+
std::vector<uint8_t> buffer(bufferSize);
185184

186-
memcpy(buffer, keyValues_, keyValuesOffset_);
185+
memcpy(buffer.data(), keyValues_, keyValuesOffset_);
187186

188187
if (dynamicDataValues_ != nullptr) {
189-
memcpy(buffer + keyValuesOffset_, dynamicDataValues_, dynamicDataOffset_);
188+
memcpy(
189+
buffer.data() + keyValuesOffset_,
190+
dynamicDataValues_,
191+
dynamicDataOffset_);
190192
}
191193

192-
// TODO T83483191: should we use std::move here?
193-
auto map = MapBuffer(buffer, bufferSize);
194+
auto map = MapBuffer(std::move(buffer));
194195

195196
// TODO T83483191: we should invalidate the class once the build() method is
196197
// called.

ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,18 @@ TEST(MapBufferTest, testUTFStringEntry) {
108108
EXPECT_EQ(map.getString(0), "Let's count: 的, 一, 是");
109109
}
110110

111+
TEST(MapBufferTest, testEmojiStringEntry) {
112+
auto builder = MapBufferBuilder();
113+
114+
builder.putString(
115+
0, "Let's count: 1️⃣, 2️⃣, 3️⃣, 🤦🏿‍♀️");
116+
auto map = builder.build();
117+
118+
EXPECT_EQ(
119+
map.getString(0),
120+
"Let's count: 1️⃣, 2️⃣, 3️⃣, 🤦🏿‍♀️");
121+
}
122+
111123
TEST(MapBufferTest, testUTFStringEntries) {
112124
auto builder = MapBufferBuilder();
113125

0 commit comments

Comments
 (0)