Files
react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp
T
Chiara Mooney 42b391775f Fix ReactCommon Break for Windows (#33047)
Summary:
Changes to MapBuffer code in https://github.com/facebook/react-native/compare/aaff15c...d287598 broke build for Windows. Errors included incompatible type conversions, the use of `__attribute__(__packed__)` which is only supported by GCC and Clang, and the usage of designated initializers which are only supported on C++20.

Changes here restore build on Windows.

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[General] [Fixed] - Fix build break on Windows with ReactCommon

Pull Request resolved: https://github.com/facebook/react-native/pull/33047

Test Plan: React Native project built on Windows and passes react-native-windows repository pipeline. These edits are currently merged into the main branch of react-native-windows.

Reviewed By: ShikaSD

Differential Revision: D34101367

Pulled By: philIip

fbshipit-source-id: 1596365c2e92f377c6375805b33de5e1c7b78e66
2022-02-09 13:03:10 -08:00

150 lines
4.0 KiB
C++

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "MapBufferBuilder.h"
#include <algorithm>
using namespace facebook::react;
namespace facebook {
namespace react {
constexpr uint32_t INT_SIZE = sizeof(uint32_t);
constexpr uint32_t DOUBLE_SIZE = sizeof(double);
constexpr uint32_t MAX_BUCKET_VALUE_SIZE = sizeof(uint64_t);
MapBuffer MapBufferBuilder::EMPTY() {
return MapBufferBuilder(0).build();
}
MapBufferBuilder::MapBufferBuilder(uint32_t initialSize) {
buckets_.reserve(initialSize);
header_.count = 0;
header_.bufferSize = 0;
}
void MapBufferBuilder::storeKeyValue(
MapBuffer::Key key,
MapBuffer::DataType type,
uint8_t const *value,
uint32_t valueSize) {
if (valueSize > MAX_BUCKET_VALUE_SIZE) {
LOG(ERROR) << "Error: size of value must be <= MAX_VALUE_SIZE. ValueSize: "
<< valueSize;
abort();
}
uint64_t data = 0;
auto *dataPtr = reinterpret_cast<uint8_t *>(&data);
memcpy(dataPtr, value, valueSize);
buckets_.emplace_back(key, static_cast<uint16_t>(type), data);
header_.count++;
if (lastKey_ > key) {
needsSort_ = true;
}
lastKey_ = key;
}
void MapBufferBuilder::putBool(MapBuffer::Key key, bool value) {
int intValue = (int)value;
storeKeyValue(
key,
MapBuffer::DataType::Boolean,
reinterpret_cast<uint8_t const *>(&intValue),
INT_SIZE);
}
void MapBufferBuilder::putDouble(MapBuffer::Key key, double value) {
storeKeyValue(
key,
MapBuffer::DataType::Double,
reinterpret_cast<uint8_t const *>(&value),
DOUBLE_SIZE);
}
void MapBufferBuilder::putInt(MapBuffer::Key key, int32_t value) {
storeKeyValue(
key,
MapBuffer::DataType::Int,
reinterpret_cast<uint8_t const *>(&value),
INT_SIZE);
}
void MapBufferBuilder::putString(MapBuffer::Key key, std::string const &value) {
auto strSize = value.size();
const char *strData = value.data();
// format [length of string (int)] + [Array of Characters in the string]
auto offset = dynamicData_.size();
dynamicData_.resize(offset + INT_SIZE + strSize, 0);
memcpy(dynamicData_.data() + offset, &strSize, INT_SIZE);
memcpy(dynamicData_.data() + offset + INT_SIZE, strData, strSize);
// Store Key and pointer to the string
storeKeyValue(
key,
MapBuffer::DataType::String,
reinterpret_cast<uint8_t const *>(&offset),
INT_SIZE);
}
void MapBufferBuilder::putMapBuffer(MapBuffer::Key key, MapBuffer const &map) {
auto mapBufferSize = map.size();
auto offset = dynamicData_.size();
// format [length of buffer (int)] + [bytes of MapBuffer]
dynamicData_.resize(offset + INT_SIZE + mapBufferSize, 0);
memcpy(dynamicData_.data() + offset, &mapBufferSize, INT_SIZE);
// Copy the content of the map into dynamicData_
memcpy(dynamicData_.data() + offset + INT_SIZE, map.data(), mapBufferSize);
// Store Key and pointer to the string
storeKeyValue(
key,
MapBuffer::DataType::Map,
reinterpret_cast<uint8_t const *>(&offset),
INT_SIZE);
}
static inline bool compareBuckets(
MapBuffer::Bucket const &a,
MapBuffer::Bucket const &b) {
return a.key < b.key;
}
MapBuffer MapBufferBuilder::build() {
// Create buffer: [header] + [key, values] + [dynamic data]
auto bucketSize = buckets_.size() * sizeof(MapBuffer::Bucket);
auto headerSize = sizeof(MapBuffer::Header);
auto bufferSize = headerSize + bucketSize + dynamicData_.size();
header_.bufferSize = static_cast<uint32_t>(bufferSize);
if (needsSort_) {
std::sort(buckets_.begin(), buckets_.end(), compareBuckets);
}
// TODO(T83483191): add pass to check for duplicates
std::vector<uint8_t> buffer(bufferSize);
memcpy(buffer.data(), &header_, headerSize);
memcpy(buffer.data() + headerSize, buckets_.data(), bucketSize);
memcpy(
buffer.data() + headerSize + bucketSize,
dynamicData_.data(),
dynamicData_.size());
return MapBuffer(std::move(buffer));
}
} // namespace react
} // namespace facebook