ipa: rpi: Add support for the Sony IMX500 camera sensor
Add a Sony IMX500 camera helper to the IPA. This also includes support for the on-chip CNN hardware accelerator and parsing of the neural network data stream returned in the metadata buffer. Add tuning files for both VC4 and PiSP platforms. Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
This commit is contained in:
330
src/ipa/rpi/cam_helper/cam_helper_imx500.cpp
Normal file
330
src/ipa/rpi/cam_helper/cam_helper_imx500.cpp
Normal file
@@ -0,0 +1,330 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024, Raspberry Pi Ltd
|
||||
*
|
||||
* cam_helper_imx500.cpp - camera helper for imx500 sensor
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libcamera/base/log.h>
|
||||
#include <libcamera/base/span.h>
|
||||
|
||||
#include <libcamera/control_ids.h>
|
||||
|
||||
#include "imx500_tensor_parser/imx500_tensor_parser.h"
|
||||
|
||||
#include "cam_helper.h"
|
||||
#include "md_parser.h"
|
||||
|
||||
using namespace RPiController;
|
||||
using namespace libcamera;
|
||||
using libcamera::utils::Duration;
|
||||
|
||||
namespace libcamera {
|
||||
LOG_DECLARE_CATEGORY(IPARPI)
|
||||
}
|
||||
|
||||
/*
|
||||
* We care about two gain registers and a pair of exposure registers. Their
|
||||
* I2C addresses from the Sony IMX500 datasheet:
|
||||
*/
|
||||
constexpr uint32_t expHiReg = 0x0202;
|
||||
constexpr uint32_t expLoReg = 0x0203;
|
||||
constexpr uint32_t gainHiReg = 0x0204;
|
||||
constexpr uint32_t gainLoReg = 0x0205;
|
||||
constexpr uint32_t frameLengthHiReg = 0x0340;
|
||||
constexpr uint32_t frameLengthLoReg = 0x0341;
|
||||
constexpr uint32_t lineLengthHiReg = 0x0342;
|
||||
constexpr uint32_t lineLengthLoReg = 0x0343;
|
||||
constexpr uint32_t temperatureReg = 0x013a;
|
||||
constexpr std::initializer_list<uint32_t> registerList = { expHiReg, expLoReg, gainHiReg, gainLoReg, frameLengthHiReg, frameLengthLoReg,
|
||||
lineLengthHiReg, lineLengthLoReg, temperatureReg };
|
||||
|
||||
class CamHelperImx500 : public CamHelper
|
||||
{
|
||||
public:
|
||||
CamHelperImx500();
|
||||
uint32_t gainCode(double gain) const override;
|
||||
double gain(uint32_t gainCode) const override;
|
||||
void prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata) override;
|
||||
std::pair<uint32_t, uint32_t> getBlanking(Duration &exposure, Duration minFrameDuration,
|
||||
Duration maxFrameDuration) const override;
|
||||
bool sensorEmbeddedDataPresent() const override;
|
||||
|
||||
private:
|
||||
/*
|
||||
* Smallest difference between the frame length and integration time,
|
||||
* in units of lines.
|
||||
*/
|
||||
static constexpr int frameIntegrationDiff = 22;
|
||||
/* Maximum frame length allowable for long exposure calculations. */
|
||||
static constexpr int frameLengthMax = 0xffdc;
|
||||
/* Largest long exposure scale factor given as a left shift on the frame length. */
|
||||
static constexpr int longExposureShiftMax = 7;
|
||||
|
||||
void parseInferenceData(libcamera::Span<const uint8_t> buffer, Metadata &metadata);
|
||||
void populateMetadata(const MdParser::RegisterMap ®isters,
|
||||
Metadata &metadata) const override;
|
||||
|
||||
std::unique_ptr<uint8_t[]> savedInputTensor_;
|
||||
};
|
||||
|
||||
CamHelperImx500::CamHelperImx500()
|
||||
: CamHelper(std::make_unique<MdParserSmia>(registerList), frameIntegrationDiff)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t CamHelperImx500::gainCode(double gain) const
|
||||
{
|
||||
return static_cast<uint32_t>(1024 - 1024 / gain);
|
||||
}
|
||||
|
||||
double CamHelperImx500::gain(uint32_t gainCode) const
|
||||
{
|
||||
return 1024.0 / (1024 - gainCode);
|
||||
}
|
||||
|
||||
void CamHelperImx500::prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata)
|
||||
{
|
||||
MdParser::RegisterMap registers;
|
||||
DeviceStatus deviceStatus;
|
||||
|
||||
if (metadata.get("device.status", deviceStatus)) {
|
||||
LOG(IPARPI, Error) << "DeviceStatus not found from DelayedControls";
|
||||
return;
|
||||
}
|
||||
|
||||
parseEmbeddedData(buffer, metadata);
|
||||
|
||||
/*
|
||||
* The DeviceStatus struct is first populated with values obtained from
|
||||
* DelayedControls. If this reports frame length is > frameLengthMax,
|
||||
* it means we are using a long exposure mode. Since the long exposure
|
||||
* scale factor is not returned back through embedded data, we must rely
|
||||
* on the existing exposure lines and frame length values returned by
|
||||
* DelayedControls.
|
||||
*
|
||||
* Otherwise, all values are updated with what is reported in the
|
||||
* embedded data.
|
||||
*/
|
||||
if (deviceStatus.frameLength > frameLengthMax) {
|
||||
DeviceStatus parsedDeviceStatus;
|
||||
|
||||
metadata.get("device.status", parsedDeviceStatus);
|
||||
parsedDeviceStatus.exposureTime = deviceStatus.exposureTime;
|
||||
parsedDeviceStatus.frameLength = deviceStatus.frameLength;
|
||||
metadata.set("device.status", parsedDeviceStatus);
|
||||
|
||||
LOG(IPARPI, Debug) << "Metadata updated for long exposure: "
|
||||
<< parsedDeviceStatus;
|
||||
}
|
||||
|
||||
parseInferenceData(buffer, metadata);
|
||||
}
|
||||
|
||||
std::pair<uint32_t, uint32_t> CamHelperImx500::getBlanking(Duration &exposure,
|
||||
Duration minFrameDuration,
|
||||
Duration maxFrameDuration) const
|
||||
{
|
||||
uint32_t frameLength, exposureLines;
|
||||
unsigned int shift = 0;
|
||||
|
||||
auto [vblank, hblank] = CamHelper::getBlanking(exposure, minFrameDuration,
|
||||
maxFrameDuration);
|
||||
|
||||
frameLength = mode_.height + vblank;
|
||||
Duration lineLength = hblankToLineLength(hblank);
|
||||
|
||||
/*
|
||||
* Check if the frame length calculated needs to be setup for long
|
||||
* exposure mode. This will require us to use a long exposure scale
|
||||
* factor provided by a shift operation in the sensor.
|
||||
*/
|
||||
while (frameLength > frameLengthMax) {
|
||||
if (++shift > longExposureShiftMax) {
|
||||
shift = longExposureShiftMax;
|
||||
frameLength = frameLengthMax;
|
||||
break;
|
||||
}
|
||||
frameLength >>= 1;
|
||||
}
|
||||
|
||||
if (shift) {
|
||||
/* Account for any rounding in the scaled frame length value. */
|
||||
frameLength <<= shift;
|
||||
exposureLines = CamHelperImx500::exposureLines(exposure, lineLength);
|
||||
exposureLines = std::min(exposureLines, frameLength - frameIntegrationDiff);
|
||||
exposure = CamHelperImx500::exposure(exposureLines, lineLength);
|
||||
}
|
||||
|
||||
return { frameLength - mode_.height, hblank };
|
||||
}
|
||||
|
||||
bool CamHelperImx500::sensorEmbeddedDataPresent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void CamHelperImx500::parseInferenceData(libcamera::Span<const uint8_t> buffer,
|
||||
Metadata &metadata)
|
||||
{
|
||||
/* Inference data comes after 2 lines of embedded data. */
|
||||
constexpr unsigned int StartLine = 2;
|
||||
size_t bytesPerLine = (mode_.width * mode_.bitdepth) >> 3;
|
||||
if (hwConfig_.dataBufferStrided)
|
||||
bytesPerLine = (bytesPerLine + 15) & ~15;
|
||||
|
||||
if (buffer.size() <= StartLine * bytesPerLine)
|
||||
return;
|
||||
|
||||
/* Check if an input tensor is needed - this is sticky! */
|
||||
bool enableInputTensor = false;
|
||||
metadata.get("cnn.enable_input_tensor", enableInputTensor);
|
||||
|
||||
/* Cache the DNN metadata for fast parsing. */
|
||||
unsigned int tensorBufferSize = buffer.size() - (StartLine * bytesPerLine);
|
||||
std::unique_ptr<uint8_t[]> cache = std::make_unique<uint8_t[]>(tensorBufferSize);
|
||||
memcpy(cache.get(), buffer.data() + StartLine * bytesPerLine, tensorBufferSize);
|
||||
Span<const uint8_t> tensors(cache.get(), tensorBufferSize);
|
||||
|
||||
std::unordered_map<TensorType, IMX500Tensors> offsets = RPiController::imx500SplitTensors(tensors);
|
||||
auto itIn = offsets.find(TensorType::InputTensor);
|
||||
auto itOut = offsets.find(TensorType::OutputTensor);
|
||||
|
||||
if (itIn != offsets.end() && itOut != offsets.end()) {
|
||||
const unsigned int inputTensorOffset = itIn->second.offset;
|
||||
const unsigned int outputTensorOffset = itOut->second.offset;
|
||||
const unsigned int inputTensorSize = outputTensorOffset - inputTensorOffset;
|
||||
Span<const uint8_t> inputTensor;
|
||||
|
||||
if (itIn->second.valid) {
|
||||
if (itOut->second.valid) {
|
||||
/* Valid input and output tensor, get the span directly from the current cache. */
|
||||
inputTensor = Span<const uint8_t>(cache.get() + inputTensorOffset,
|
||||
inputTensorSize);
|
||||
} else {
|
||||
/*
|
||||
* Invalid output tensor with valid input tensor.
|
||||
* This is likely because the DNN takes longer than
|
||||
* a frame time to generate the output tensor.
|
||||
*
|
||||
* In such cases, we don't process the input tensor,
|
||||
* but simply save it for when the next output
|
||||
* tensor is valid. This way, we ensure that both
|
||||
* valid input and output tensors are in lock-step.
|
||||
*/
|
||||
savedInputTensor_ = std::make_unique<uint8_t[]>(inputTensorSize);
|
||||
memcpy(savedInputTensor_.get(), cache.get() + inputTensorOffset,
|
||||
inputTensorSize);
|
||||
}
|
||||
} else if (itOut->second.valid && savedInputTensor_) {
|
||||
/*
|
||||
* Invalid input tensor with valid output tensor. This is
|
||||
* likely because the DNN takes longer than a frame time
|
||||
* to generate the output tensor.
|
||||
*
|
||||
* In such cases, use the previously saved input tensor
|
||||
* if possible.
|
||||
*/
|
||||
inputTensor = Span<const uint8_t>(savedInputTensor_.get(), inputTensorSize);
|
||||
}
|
||||
|
||||
if (inputTensor.size()) {
|
||||
IMX500InputTensorInfo inputTensorInfo;
|
||||
if (!imx500ParseInputTensor(inputTensorInfo, inputTensor)) {
|
||||
CnnInputTensorInfo exported{};
|
||||
exported.width = inputTensorInfo.width;
|
||||
exported.height = inputTensorInfo.height;
|
||||
exported.numChannels = inputTensorInfo.channels;
|
||||
strncpy(exported.networkName, inputTensorInfo.networkName.c_str(),
|
||||
sizeof(exported.networkName));
|
||||
exported.networkName[sizeof(exported.networkName) - 1] = '\0';
|
||||
metadata.set("cnn.input_tensor_info", exported);
|
||||
metadata.set("cnn.input_tensor", std::move(inputTensorInfo.data));
|
||||
metadata.set("cnn.input_tensor_size", inputTensorInfo.size);
|
||||
}
|
||||
|
||||
/* We can now safely clear the saved input tensor. */
|
||||
savedInputTensor_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (itOut != offsets.end() && itOut->second.valid) {
|
||||
unsigned int outputTensorOffset = itOut->second.offset;
|
||||
Span<const uint8_t> outputTensor(cache.get() + outputTensorOffset,
|
||||
tensorBufferSize - outputTensorOffset);
|
||||
|
||||
IMX500OutputTensorInfo outputTensorInfo;
|
||||
if (!imx500ParseOutputTensor(outputTensorInfo, outputTensor)) {
|
||||
CnnOutputTensorInfo exported{};
|
||||
if (outputTensorInfo.numTensors < MaxNumTensors) {
|
||||
exported.numTensors = outputTensorInfo.numTensors;
|
||||
for (unsigned int i = 0; i < exported.numTensors; i++) {
|
||||
exported.info[i].tensorDataNum = outputTensorInfo.tensorDataNum[i];
|
||||
exported.info[i].numDimensions = outputTensorInfo.numDimensions[i];
|
||||
for (unsigned int j = 0; j < exported.info[i].numDimensions; j++)
|
||||
exported.info[i].size[j] = outputTensorInfo.vecDim[i][j].size;
|
||||
}
|
||||
} else {
|
||||
LOG(IPARPI, Debug)
|
||||
<< "IMX500 output tensor info export failed, numTensors > MaxNumTensors";
|
||||
}
|
||||
strncpy(exported.networkName, outputTensorInfo.networkName.c_str(),
|
||||
sizeof(exported.networkName));
|
||||
exported.networkName[sizeof(exported.networkName) - 1] = '\0';
|
||||
metadata.set("cnn.output_tensor_info", exported);
|
||||
metadata.set("cnn.output_tensor", std::move(outputTensorInfo.data));
|
||||
metadata.set("cnn.output_tensor_size", outputTensorInfo.totalSize);
|
||||
|
||||
auto itKpi = offsets.find(TensorType::Kpi);
|
||||
if (itKpi != offsets.end()) {
|
||||
constexpr unsigned int DnnRuntimeOffset = 9;
|
||||
constexpr unsigned int DspRuntimeOffset = 10;
|
||||
CnnKpiInfo kpi;
|
||||
|
||||
uint8_t *k = cache.get() + itKpi->second.offset;
|
||||
kpi.dnnRuntime = k[4 * DnnRuntimeOffset + 3] << 24 |
|
||||
k[4 * DnnRuntimeOffset + 2] << 16 |
|
||||
k[4 * DnnRuntimeOffset + 1] << 8 |
|
||||
k[4 * DnnRuntimeOffset];
|
||||
kpi.dspRuntime = k[4 * DspRuntimeOffset + 3] << 24 |
|
||||
k[4 * DspRuntimeOffset + 2] << 16 |
|
||||
k[4 * DspRuntimeOffset + 1] << 8 |
|
||||
k[4 * DspRuntimeOffset];
|
||||
metadata.set("cnn.kpi_info", kpi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CamHelperImx500::populateMetadata(const MdParser::RegisterMap ®isters,
|
||||
Metadata &metadata) const
|
||||
{
|
||||
DeviceStatus deviceStatus;
|
||||
|
||||
deviceStatus.lineLength = lineLengthPckToDuration(registers.at(lineLengthHiReg) * 256 +
|
||||
registers.at(lineLengthLoReg));
|
||||
deviceStatus.exposureTime = exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg),
|
||||
deviceStatus.lineLength);
|
||||
deviceStatus.analogueGain = gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg));
|
||||
deviceStatus.frameLength = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg);
|
||||
deviceStatus.sensorTemperature = std::clamp<int8_t>(registers.at(temperatureReg), -20, 80);
|
||||
|
||||
metadata.set("device.status", deviceStatus);
|
||||
}
|
||||
|
||||
static CamHelper *create()
|
||||
{
|
||||
return new CamHelperImx500();
|
||||
}
|
||||
|
||||
static RegisterCamHelper reg_imx500("imx500", &create);
|
||||
@@ -0,0 +1,544 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_APPARAMSFLATBUFFERS_APPARAMS_FB_H_
|
||||
#define FLATBUFFERS_GENERATED_APPARAMSFLATBUFFERS_APPARAMS_FB_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
namespace apParams {
|
||||
namespace fb {
|
||||
|
||||
struct FBDimension;
|
||||
|
||||
struct FBInputTensor;
|
||||
|
||||
struct FBOutputTensor;
|
||||
|
||||
struct FBNetwork;
|
||||
|
||||
struct FBApParams;
|
||||
|
||||
struct FBDimension FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_ID = 4,
|
||||
VT_SIZE = 6,
|
||||
VT_SERIALIZATIONINDEX = 8,
|
||||
VT_PADDING = 10
|
||||
};
|
||||
uint8_t id() const {
|
||||
return GetField<uint8_t>(VT_ID, 0);
|
||||
}
|
||||
uint16_t size() const {
|
||||
return GetField<uint16_t>(VT_SIZE, 0);
|
||||
}
|
||||
uint8_t serializationIndex() const {
|
||||
return GetField<uint8_t>(VT_SERIALIZATIONINDEX, 0);
|
||||
}
|
||||
uint8_t padding() const {
|
||||
return GetField<uint8_t>(VT_PADDING, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint8_t>(verifier, VT_ID) &&
|
||||
VerifyField<uint16_t>(verifier, VT_SIZE) &&
|
||||
VerifyField<uint8_t>(verifier, VT_SERIALIZATIONINDEX) &&
|
||||
VerifyField<uint8_t>(verifier, VT_PADDING) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct FBDimensionBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_id(uint8_t id) {
|
||||
fbb_.AddElement<uint8_t>(FBDimension::VT_ID, id, 0);
|
||||
}
|
||||
void add_size(uint16_t size) {
|
||||
fbb_.AddElement<uint16_t>(FBDimension::VT_SIZE, size, 0);
|
||||
}
|
||||
void add_serializationIndex(uint8_t serializationIndex) {
|
||||
fbb_.AddElement<uint8_t>(FBDimension::VT_SERIALIZATIONINDEX, serializationIndex, 0);
|
||||
}
|
||||
void add_padding(uint8_t padding) {
|
||||
fbb_.AddElement<uint8_t>(FBDimension::VT_PADDING, padding, 0);
|
||||
}
|
||||
explicit FBDimensionBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
FBDimensionBuilder &operator=(const FBDimensionBuilder &);
|
||||
flatbuffers::Offset<FBDimension> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<FBDimension>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<FBDimension> CreateFBDimension(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint8_t id = 0,
|
||||
uint16_t size = 0,
|
||||
uint8_t serializationIndex = 0,
|
||||
uint8_t padding = 0) {
|
||||
FBDimensionBuilder builder_(_fbb);
|
||||
builder_.add_size(size);
|
||||
builder_.add_padding(padding);
|
||||
builder_.add_serializationIndex(serializationIndex);
|
||||
builder_.add_id(id);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct FBInputTensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_ID = 4,
|
||||
VT_NAME = 6,
|
||||
VT_NUMOFDIMENSIONS = 8,
|
||||
VT_DIMENSIONS = 10,
|
||||
VT_SHIFT = 12,
|
||||
VT_SCALE = 14,
|
||||
VT_FORMAT = 16
|
||||
};
|
||||
uint8_t id() const {
|
||||
return GetField<uint8_t>(VT_ID, 0);
|
||||
}
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
uint8_t numOfDimensions() const {
|
||||
return GetField<uint8_t>(VT_NUMOFDIMENSIONS, 0);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<FBDimension>> *dimensions() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<FBDimension>> *>(VT_DIMENSIONS);
|
||||
}
|
||||
uint16_t shift() const {
|
||||
return GetField<uint16_t>(VT_SHIFT, 0);
|
||||
}
|
||||
float scale() const {
|
||||
return GetField<float>(VT_SCALE, 0.0f);
|
||||
}
|
||||
uint8_t format() const {
|
||||
return GetField<uint8_t>(VT_FORMAT, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint8_t>(verifier, VT_ID) &&
|
||||
VerifyOffset(verifier, VT_NAME) &&
|
||||
verifier.VerifyString(name()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_NUMOFDIMENSIONS) &&
|
||||
VerifyOffset(verifier, VT_DIMENSIONS) &&
|
||||
verifier.VerifyVector(dimensions()) &&
|
||||
verifier.VerifyVectorOfTables(dimensions()) &&
|
||||
VerifyField<uint16_t>(verifier, VT_SHIFT) &&
|
||||
VerifyField<float>(verifier, VT_SCALE) &&
|
||||
VerifyField<uint8_t>(verifier, VT_FORMAT) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct FBInputTensorBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_id(uint8_t id) {
|
||||
fbb_.AddElement<uint8_t>(FBInputTensor::VT_ID, id, 0);
|
||||
}
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(FBInputTensor::VT_NAME, name);
|
||||
}
|
||||
void add_numOfDimensions(uint8_t numOfDimensions) {
|
||||
fbb_.AddElement<uint8_t>(FBInputTensor::VT_NUMOFDIMENSIONS, numOfDimensions, 0);
|
||||
}
|
||||
void add_dimensions(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FBDimension>>> dimensions) {
|
||||
fbb_.AddOffset(FBInputTensor::VT_DIMENSIONS, dimensions);
|
||||
}
|
||||
void add_shift(uint16_t shift) {
|
||||
fbb_.AddElement<uint16_t>(FBInputTensor::VT_SHIFT, shift, 0);
|
||||
}
|
||||
void add_scale(float scale) {
|
||||
fbb_.AddElement<float>(FBInputTensor::VT_SCALE, scale, 0.0f);
|
||||
}
|
||||
void add_format(uint8_t format) {
|
||||
fbb_.AddElement<uint8_t>(FBInputTensor::VT_FORMAT, format, 0);
|
||||
}
|
||||
explicit FBInputTensorBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
FBInputTensorBuilder &operator=(const FBInputTensorBuilder &);
|
||||
flatbuffers::Offset<FBInputTensor> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<FBInputTensor>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<FBInputTensor> CreateFBInputTensor(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint8_t id = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
uint8_t numOfDimensions = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FBDimension>>> dimensions = 0,
|
||||
uint16_t shift = 0,
|
||||
float scale = 0.0f,
|
||||
uint8_t format = 0) {
|
||||
FBInputTensorBuilder builder_(_fbb);
|
||||
builder_.add_scale(scale);
|
||||
builder_.add_dimensions(dimensions);
|
||||
builder_.add_name(name);
|
||||
builder_.add_shift(shift);
|
||||
builder_.add_format(format);
|
||||
builder_.add_numOfDimensions(numOfDimensions);
|
||||
builder_.add_id(id);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<FBInputTensor> CreateFBInputTensorDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint8_t id = 0,
|
||||
const char *name = nullptr,
|
||||
uint8_t numOfDimensions = 0,
|
||||
const std::vector<flatbuffers::Offset<FBDimension>> *dimensions = nullptr,
|
||||
uint16_t shift = 0,
|
||||
float scale = 0.0f,
|
||||
uint8_t format = 0) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto dimensions__ = dimensions ? _fbb.CreateVector<flatbuffers::Offset<FBDimension>>(*dimensions) : 0;
|
||||
return apParams::fb::CreateFBInputTensor(
|
||||
_fbb,
|
||||
id,
|
||||
name__,
|
||||
numOfDimensions,
|
||||
dimensions__,
|
||||
shift,
|
||||
scale,
|
||||
format);
|
||||
}
|
||||
|
||||
struct FBOutputTensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_ID = 4,
|
||||
VT_NAME = 6,
|
||||
VT_NUMOFDIMENSIONS = 8,
|
||||
VT_DIMENSIONS = 10,
|
||||
VT_BITSPERELEMENT = 12,
|
||||
VT_SHIFT = 14,
|
||||
VT_SCALE = 16,
|
||||
VT_FORMAT = 18
|
||||
};
|
||||
uint8_t id() const {
|
||||
return GetField<uint8_t>(VT_ID, 0);
|
||||
}
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
uint8_t numOfDimensions() const {
|
||||
return GetField<uint8_t>(VT_NUMOFDIMENSIONS, 0);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<FBDimension>> *dimensions() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<FBDimension>> *>(VT_DIMENSIONS);
|
||||
}
|
||||
uint8_t bitsPerElement() const {
|
||||
return GetField<uint8_t>(VT_BITSPERELEMENT, 0);
|
||||
}
|
||||
uint16_t shift() const {
|
||||
return GetField<uint16_t>(VT_SHIFT, 0);
|
||||
}
|
||||
float scale() const {
|
||||
return GetField<float>(VT_SCALE, 0.0f);
|
||||
}
|
||||
uint8_t format() const {
|
||||
return GetField<uint8_t>(VT_FORMAT, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint8_t>(verifier, VT_ID) &&
|
||||
VerifyOffset(verifier, VT_NAME) &&
|
||||
verifier.VerifyString(name()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_NUMOFDIMENSIONS) &&
|
||||
VerifyOffset(verifier, VT_DIMENSIONS) &&
|
||||
verifier.VerifyVector(dimensions()) &&
|
||||
verifier.VerifyVectorOfTables(dimensions()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_BITSPERELEMENT) &&
|
||||
VerifyField<uint16_t>(verifier, VT_SHIFT) &&
|
||||
VerifyField<float>(verifier, VT_SCALE) &&
|
||||
VerifyField<uint8_t>(verifier, VT_FORMAT) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct FBOutputTensorBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_id(uint8_t id) {
|
||||
fbb_.AddElement<uint8_t>(FBOutputTensor::VT_ID, id, 0);
|
||||
}
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(FBOutputTensor::VT_NAME, name);
|
||||
}
|
||||
void add_numOfDimensions(uint8_t numOfDimensions) {
|
||||
fbb_.AddElement<uint8_t>(FBOutputTensor::VT_NUMOFDIMENSIONS, numOfDimensions, 0);
|
||||
}
|
||||
void add_dimensions(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FBDimension>>> dimensions) {
|
||||
fbb_.AddOffset(FBOutputTensor::VT_DIMENSIONS, dimensions);
|
||||
}
|
||||
void add_bitsPerElement(uint8_t bitsPerElement) {
|
||||
fbb_.AddElement<uint8_t>(FBOutputTensor::VT_BITSPERELEMENT, bitsPerElement, 0);
|
||||
}
|
||||
void add_shift(uint16_t shift) {
|
||||
fbb_.AddElement<uint16_t>(FBOutputTensor::VT_SHIFT, shift, 0);
|
||||
}
|
||||
void add_scale(float scale) {
|
||||
fbb_.AddElement<float>(FBOutputTensor::VT_SCALE, scale, 0.0f);
|
||||
}
|
||||
void add_format(uint8_t format) {
|
||||
fbb_.AddElement<uint8_t>(FBOutputTensor::VT_FORMAT, format, 0);
|
||||
}
|
||||
explicit FBOutputTensorBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
FBOutputTensorBuilder &operator=(const FBOutputTensorBuilder &);
|
||||
flatbuffers::Offset<FBOutputTensor> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<FBOutputTensor>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<FBOutputTensor> CreateFBOutputTensor(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint8_t id = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
uint8_t numOfDimensions = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FBDimension>>> dimensions = 0,
|
||||
uint8_t bitsPerElement = 0,
|
||||
uint16_t shift = 0,
|
||||
float scale = 0.0f,
|
||||
uint8_t format = 0) {
|
||||
FBOutputTensorBuilder builder_(_fbb);
|
||||
builder_.add_scale(scale);
|
||||
builder_.add_dimensions(dimensions);
|
||||
builder_.add_name(name);
|
||||
builder_.add_shift(shift);
|
||||
builder_.add_format(format);
|
||||
builder_.add_bitsPerElement(bitsPerElement);
|
||||
builder_.add_numOfDimensions(numOfDimensions);
|
||||
builder_.add_id(id);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<FBOutputTensor> CreateFBOutputTensorDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint8_t id = 0,
|
||||
const char *name = nullptr,
|
||||
uint8_t numOfDimensions = 0,
|
||||
const std::vector<flatbuffers::Offset<FBDimension>> *dimensions = nullptr,
|
||||
uint8_t bitsPerElement = 0,
|
||||
uint16_t shift = 0,
|
||||
float scale = 0.0f,
|
||||
uint8_t format = 0) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto dimensions__ = dimensions ? _fbb.CreateVector<flatbuffers::Offset<FBDimension>>(*dimensions) : 0;
|
||||
return apParams::fb::CreateFBOutputTensor(
|
||||
_fbb,
|
||||
id,
|
||||
name__,
|
||||
numOfDimensions,
|
||||
dimensions__,
|
||||
bitsPerElement,
|
||||
shift,
|
||||
scale,
|
||||
format);
|
||||
}
|
||||
|
||||
struct FBNetwork FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_ID = 4,
|
||||
VT_NAME = 6,
|
||||
VT_TYPE = 8,
|
||||
VT_INPUTTENSORS = 10,
|
||||
VT_OUTPUTTENSORS = 12
|
||||
};
|
||||
uint16_t id() const {
|
||||
return GetField<uint16_t>(VT_ID, 0);
|
||||
}
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
const flatbuffers::String *type() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_TYPE);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<FBInputTensor>> *inputTensors() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<FBInputTensor>> *>(VT_INPUTTENSORS);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<FBOutputTensor>> *outputTensors() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<FBOutputTensor>> *>(VT_OUTPUTTENSORS);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint16_t>(verifier, VT_ID) &&
|
||||
VerifyOffset(verifier, VT_NAME) &&
|
||||
verifier.VerifyString(name()) &&
|
||||
VerifyOffset(verifier, VT_TYPE) &&
|
||||
verifier.VerifyString(type()) &&
|
||||
VerifyOffset(verifier, VT_INPUTTENSORS) &&
|
||||
verifier.VerifyVector(inputTensors()) &&
|
||||
verifier.VerifyVectorOfTables(inputTensors()) &&
|
||||
VerifyOffset(verifier, VT_OUTPUTTENSORS) &&
|
||||
verifier.VerifyVector(outputTensors()) &&
|
||||
verifier.VerifyVectorOfTables(outputTensors()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct FBNetworkBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_id(uint16_t id) {
|
||||
fbb_.AddElement<uint16_t>(FBNetwork::VT_ID, id, 0);
|
||||
}
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(FBNetwork::VT_NAME, name);
|
||||
}
|
||||
void add_type(flatbuffers::Offset<flatbuffers::String> type) {
|
||||
fbb_.AddOffset(FBNetwork::VT_TYPE, type);
|
||||
}
|
||||
void add_inputTensors(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FBInputTensor>>> inputTensors) {
|
||||
fbb_.AddOffset(FBNetwork::VT_INPUTTENSORS, inputTensors);
|
||||
}
|
||||
void add_outputTensors(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FBOutputTensor>>> outputTensors) {
|
||||
fbb_.AddOffset(FBNetwork::VT_OUTPUTTENSORS, outputTensors);
|
||||
}
|
||||
explicit FBNetworkBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
FBNetworkBuilder &operator=(const FBNetworkBuilder &);
|
||||
flatbuffers::Offset<FBNetwork> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<FBNetwork>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<FBNetwork> CreateFBNetwork(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint16_t id = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> type = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FBInputTensor>>> inputTensors = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FBOutputTensor>>> outputTensors = 0) {
|
||||
FBNetworkBuilder builder_(_fbb);
|
||||
builder_.add_outputTensors(outputTensors);
|
||||
builder_.add_inputTensors(inputTensors);
|
||||
builder_.add_type(type);
|
||||
builder_.add_name(name);
|
||||
builder_.add_id(id);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<FBNetwork> CreateFBNetworkDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint16_t id = 0,
|
||||
const char *name = nullptr,
|
||||
const char *type = nullptr,
|
||||
const std::vector<flatbuffers::Offset<FBInputTensor>> *inputTensors = nullptr,
|
||||
const std::vector<flatbuffers::Offset<FBOutputTensor>> *outputTensors = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto type__ = type ? _fbb.CreateString(type) : 0;
|
||||
auto inputTensors__ = inputTensors ? _fbb.CreateVector<flatbuffers::Offset<FBInputTensor>>(*inputTensors) : 0;
|
||||
auto outputTensors__ = outputTensors ? _fbb.CreateVector<flatbuffers::Offset<FBOutputTensor>>(*outputTensors) : 0;
|
||||
return apParams::fb::CreateFBNetwork(
|
||||
_fbb,
|
||||
id,
|
||||
name__,
|
||||
type__,
|
||||
inputTensors__,
|
||||
outputTensors__);
|
||||
}
|
||||
|
||||
struct FBApParams FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NETWORKS = 4
|
||||
};
|
||||
const flatbuffers::Vector<flatbuffers::Offset<FBNetwork>> *networks() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<FBNetwork>> *>(VT_NETWORKS);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_NETWORKS) &&
|
||||
verifier.VerifyVector(networks()) &&
|
||||
verifier.VerifyVectorOfTables(networks()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct FBApParamsBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_networks(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FBNetwork>>> networks) {
|
||||
fbb_.AddOffset(FBApParams::VT_NETWORKS, networks);
|
||||
}
|
||||
explicit FBApParamsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
FBApParamsBuilder &operator=(const FBApParamsBuilder &);
|
||||
flatbuffers::Offset<FBApParams> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<FBApParams>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<FBApParams> CreateFBApParams(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FBNetwork>>> networks = 0) {
|
||||
FBApParamsBuilder builder_(_fbb);
|
||||
builder_.add_networks(networks);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<FBApParams> CreateFBApParamsDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const std::vector<flatbuffers::Offset<FBNetwork>> *networks = nullptr) {
|
||||
auto networks__ = networks ? _fbb.CreateVector<flatbuffers::Offset<FBNetwork>>(*networks) : 0;
|
||||
return apParams::fb::CreateFBApParams(
|
||||
_fbb,
|
||||
networks__);
|
||||
}
|
||||
|
||||
inline const apParams::fb::FBApParams *GetFBApParams(const void *buf) {
|
||||
return flatbuffers::GetRoot<apParams::fb::FBApParams>(buf);
|
||||
}
|
||||
|
||||
inline const apParams::fb::FBApParams *GetSizePrefixedFBApParams(const void *buf) {
|
||||
return flatbuffers::GetSizePrefixedRoot<apParams::fb::FBApParams>(buf);
|
||||
}
|
||||
|
||||
inline bool VerifyFBApParamsBuffer(
|
||||
flatbuffers::Verifier &verifier) {
|
||||
return verifier.VerifyBuffer<apParams::fb::FBApParams>(nullptr);
|
||||
}
|
||||
|
||||
inline bool VerifySizePrefixedFBApParamsBuffer(
|
||||
flatbuffers::Verifier &verifier) {
|
||||
return verifier.VerifySizePrefixedBuffer<apParams::fb::FBApParams>(nullptr);
|
||||
}
|
||||
|
||||
inline void FinishFBApParamsBuffer(
|
||||
flatbuffers::FlatBufferBuilder &fbb,
|
||||
flatbuffers::Offset<apParams::fb::FBApParams> root) {
|
||||
fbb.Finish(root);
|
||||
}
|
||||
|
||||
inline void FinishSizePrefixedFBApParamsBuffer(
|
||||
flatbuffers::FlatBufferBuilder &fbb,
|
||||
flatbuffers::Offset<apParams::fb::FBApParams> root) {
|
||||
fbb.FinishSizePrefixed(root);
|
||||
}
|
||||
|
||||
} // namespace fb
|
||||
} // namespace apParams
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_APPARAMSFLATBUFFERS_APPARAMS_FB_H_
|
||||
379
src/ipa/rpi/cam_helper/imx500_tensor_parser/flatbuffers/base.h
Normal file
379
src/ipa/rpi/cam_helper/imx500_tensor_parser/flatbuffers/base.h
Normal file
@@ -0,0 +1,379 @@
|
||||
#ifndef FLATBUFFERS_BASE_H_
|
||||
#define FLATBUFFERS_BASE_H_
|
||||
|
||||
// clang-format off
|
||||
|
||||
// If activate should be declared and included first.
|
||||
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
||||
defined(_MSC_VER) && defined(_DEBUG)
|
||||
// The _CRTDBG_MAP_ALLOC inside <crtdbg.h> will replace
|
||||
// calloc/free (etc) to its debug version using #define directives.
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
// Replace operator new by trace-enabled version.
|
||||
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
#if !defined(FLATBUFFERS_ASSERT)
|
||||
#include <assert.h>
|
||||
#define FLATBUFFERS_ASSERT assert
|
||||
#elif defined(FLATBUFFERS_ASSERT_INCLUDE)
|
||||
// Include file with forward declaration
|
||||
#include FLATBUFFERS_ASSERT_INCLUDE
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO
|
||||
#include <cstdint>
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
|
||||
#include <utility.h>
|
||||
#else
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
#ifdef _STLPORT_VERSION
|
||||
#define FLATBUFFERS_CPP98_STL
|
||||
#endif
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
#include "stl_emulation.h"
|
||||
|
||||
// Note the __clang__ check is needed, because clang presents itself
|
||||
// as an older GNUC compiler (4.2).
|
||||
// Clang 3.3 and later implement all of the ISO C++ 2011 standard.
|
||||
// Clang 3.4 and later implement all of the ISO C++ 2014 standard.
|
||||
// http://clang.llvm.org/cxx_status.html
|
||||
|
||||
// Note the MSVC value '__cplusplus' may be incorrect:
|
||||
// The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L,
|
||||
// indicating (erroneously!) that the compiler conformed to the C++98 Standard.
|
||||
// This value should be correct starting from MSVC2017-15.7-Preview-3.
|
||||
// The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set.
|
||||
// Workaround (for details see MSDN):
|
||||
// Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus for compatibility.
|
||||
// The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch.
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#else
|
||||
#define FLATBUFFERS_GCC 0
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
#define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
|
||||
#else
|
||||
#define FLATBUFFERS_CLANG 0
|
||||
#endif
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
#if __cplusplus <= 199711L && \
|
||||
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
||||
(!defined(__GNUC__) || \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
|
||||
#error A C++11 compatible compiler with support for the auto typing is \
|
||||
required for FlatBuffers.
|
||||
#error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
|
||||
#endif
|
||||
|
||||
#if !defined(__clang__) && \
|
||||
defined(__GNUC__) && \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
|
||||
// Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr
|
||||
// and constexpr keywords. Note the __clang__ check is needed, because clang
|
||||
// presents itself as an older GNUC compiler.
|
||||
#ifndef nullptr_t
|
||||
const class nullptr_t {
|
||||
public:
|
||||
template<class T> inline operator T*() const { return 0; }
|
||||
private:
|
||||
void operator&() const;
|
||||
} nullptr = {};
|
||||
#endif
|
||||
#ifndef constexpr
|
||||
#define constexpr const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// The wire format uses a little endian encoding (since that's efficient for
|
||||
// the common platforms).
|
||||
#if defined(__s390x__)
|
||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||
#endif // __s390x__
|
||||
#if !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#if (defined(__BIG_ENDIAN__) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||
#else
|
||||
#define FLATBUFFERS_LITTLEENDIAN 1
|
||||
#endif // __BIG_ENDIAN__
|
||||
#elif defined(_MSC_VER)
|
||||
#if defined(_M_PPC)
|
||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||
#else
|
||||
#define FLATBUFFERS_LITTLEENDIAN 1
|
||||
#endif
|
||||
#else
|
||||
#error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
|
||||
#endif
|
||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
|
||||
#define FLATBUFFERS_VERSION_MAJOR 1
|
||||
#define FLATBUFFERS_VERSION_MINOR 11
|
||||
#define FLATBUFFERS_VERSION_REVISION 0
|
||||
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
||||
|
||||
#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
|
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \
|
||||
defined(__clang__)
|
||||
#define FLATBUFFERS_FINAL_CLASS final
|
||||
#define FLATBUFFERS_OVERRIDE override
|
||||
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t
|
||||
#else
|
||||
#define FLATBUFFERS_FINAL_CLASS
|
||||
#define FLATBUFFERS_OVERRIDE
|
||||
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE
|
||||
#endif
|
||||
|
||||
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
|
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
|
||||
(defined(__cpp_constexpr) && __cpp_constexpr >= 200704)
|
||||
#define FLATBUFFERS_CONSTEXPR constexpr
|
||||
#else
|
||||
#define FLATBUFFERS_CONSTEXPR const
|
||||
#endif
|
||||
|
||||
#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
|
||||
(defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
|
||||
#define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR
|
||||
#else
|
||||
#define FLATBUFFERS_CONSTEXPR_CPP14
|
||||
#endif
|
||||
|
||||
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
|
||||
(defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \
|
||||
defined(__clang__)
|
||||
#define FLATBUFFERS_NOEXCEPT noexcept
|
||||
#else
|
||||
#define FLATBUFFERS_NOEXCEPT
|
||||
#endif
|
||||
|
||||
// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
|
||||
// private, so be sure to put it at the end or reset access mode explicitly.
|
||||
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
|
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
|
||||
defined(__clang__)
|
||||
#define FLATBUFFERS_DELETE_FUNC(func) func = delete;
|
||||
#else
|
||||
#define FLATBUFFERS_DELETE_FUNC(func) private: func;
|
||||
#endif
|
||||
|
||||
#ifndef FLATBUFFERS_HAS_STRING_VIEW
|
||||
// Only provide flatbuffers::string_view if __has_include can be used
|
||||
// to detect a header that provides an implementation
|
||||
#if defined(__has_include)
|
||||
// Check for std::string_view (in c++17)
|
||||
#if __has_include(<string_view>) && (__cplusplus >= 201606 || _HAS_CXX17)
|
||||
#include <string_view>
|
||||
namespace flatbuffers {
|
||||
typedef std::string_view string_view;
|
||||
}
|
||||
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
||||
// Check for std::experimental::string_view (in c++14, compiler-dependent)
|
||||
#elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411)
|
||||
#include <experimental/string_view>
|
||||
namespace flatbuffers {
|
||||
typedef std::experimental::string_view string_view;
|
||||
}
|
||||
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
||||
#endif
|
||||
#endif // __has_include
|
||||
#endif // !FLATBUFFERS_HAS_STRING_VIEW
|
||||
|
||||
#ifndef FLATBUFFERS_HAS_NEW_STRTOD
|
||||
// Modern (C++11) strtod and strtof functions are available for use.
|
||||
// 1) nan/inf strings as argument of strtod;
|
||||
// 2) hex-float as argument of strtod/strtof.
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
|
||||
(defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
|
||||
(defined(__clang__))
|
||||
#define FLATBUFFERS_HAS_NEW_STRTOD 1
|
||||
#endif
|
||||
#endif // !FLATBUFFERS_HAS_NEW_STRTOD
|
||||
|
||||
#ifndef FLATBUFFERS_LOCALE_INDEPENDENT
|
||||
// Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}.
|
||||
// They are part of the POSIX-2008 but not part of the C/C++ standard.
|
||||
// GCC/Clang have definition (_XOPEN_SOURCE>=700) if POSIX-2008.
|
||||
#if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \
|
||||
(defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE>=700)))
|
||||
#define FLATBUFFERS_LOCALE_INDEPENDENT 1
|
||||
#else
|
||||
#define FLATBUFFERS_LOCALE_INDEPENDENT 0
|
||||
#endif
|
||||
#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
|
||||
|
||||
// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
|
||||
// - __supress_ubsan__("undefined")
|
||||
// - __supress_ubsan__("signed-integer-overflow")
|
||||
#if defined(__clang__)
|
||||
#define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
|
||||
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
|
||||
#define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
|
||||
#else
|
||||
#define __supress_ubsan__(type)
|
||||
#endif
|
||||
|
||||
// This is constexpr function used for checking compile-time constants.
|
||||
// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
|
||||
template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
|
||||
return !!t;
|
||||
}
|
||||
|
||||
// Enable C++ attribute [[]] if std:c++17 or higher.
|
||||
#if ((__cplusplus >= 201703L) \
|
||||
|| (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
|
||||
// All attributes unknown to an implementation are ignored without causing an error.
|
||||
#define FLATBUFFERS_ATTRIBUTE(attr) [[attr]]
|
||||
|
||||
#define FLATBUFFERS_FALLTHROUGH() [[fallthrough]]
|
||||
#else
|
||||
#define FLATBUFFERS_ATTRIBUTE(attr)
|
||||
|
||||
#if FLATBUFFERS_CLANG >= 30800
|
||||
#define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]]
|
||||
#elif FLATBUFFERS_GCC >= 70300
|
||||
#define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]]
|
||||
#else
|
||||
#define FLATBUFFERS_FALLTHROUGH()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// @endcond
|
||||
|
||||
/// @file
|
||||
namespace flatbuffers {
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
// Our default offset / size type, 32bit on purpose on 64bit systems.
|
||||
// Also, using a consistent offset type maintains compatibility of serialized
|
||||
// offset values between 32bit and 64bit systems.
|
||||
typedef uint32_t uoffset_t;
|
||||
|
||||
// Signed offsets for references that can go in both directions.
|
||||
typedef int32_t soffset_t;
|
||||
|
||||
// Offset/index used in v-tables, can be changed to uint8_t in
|
||||
// format forks to save a bit of space if desired.
|
||||
typedef uint16_t voffset_t;
|
||||
|
||||
typedef uintmax_t largest_scalar_t;
|
||||
|
||||
// In 32bits, this evaluates to 2GB - 1
|
||||
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
|
||||
|
||||
// We support aligning the contents of buffers up to this size.
|
||||
#define FLATBUFFERS_MAX_ALIGNMENT 16
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
||||
#endif
|
||||
|
||||
template<typename T> T EndianSwap(T t) {
|
||||
#if defined(_MSC_VER)
|
||||
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
|
||||
#define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
|
||||
#define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
|
||||
#else
|
||||
#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
|
||||
// __builtin_bswap16 was missing prior to GCC 4.8.
|
||||
#define FLATBUFFERS_BYTESWAP16(x) \
|
||||
static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
|
||||
#else
|
||||
#define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
|
||||
#endif
|
||||
#define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
|
||||
#define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
|
||||
#endif
|
||||
if (sizeof(T) == 1) { // Compile-time if-then's.
|
||||
return t;
|
||||
} else if (sizeof(T) == 2) {
|
||||
union { T t; uint16_t i; } u;
|
||||
u.t = t;
|
||||
u.i = FLATBUFFERS_BYTESWAP16(u.i);
|
||||
return u.t;
|
||||
} else if (sizeof(T) == 4) {
|
||||
union { T t; uint32_t i; } u;
|
||||
u.t = t;
|
||||
u.i = FLATBUFFERS_BYTESWAP32(u.i);
|
||||
return u.t;
|
||||
} else if (sizeof(T) == 8) {
|
||||
union { T t; uint64_t i; } u;
|
||||
u.t = t;
|
||||
u.i = FLATBUFFERS_BYTESWAP64(u.i);
|
||||
return u.t;
|
||||
} else {
|
||||
FLATBUFFERS_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T> T EndianScalar(T t) {
|
||||
#if FLATBUFFERS_LITTLEENDIAN
|
||||
return t;
|
||||
#else
|
||||
return EndianSwap(t);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
|
||||
__supress_ubsan__("alignment")
|
||||
T ReadScalar(const void *p) {
|
||||
return EndianScalar(*reinterpret_cast<const T *>(p));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
|
||||
__supress_ubsan__("alignment")
|
||||
void WriteScalar(void *p, T t) {
|
||||
*reinterpret_cast<T *>(p) = EndianScalar(t);
|
||||
}
|
||||
|
||||
template<typename T> struct Offset;
|
||||
template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
|
||||
*reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
|
||||
}
|
||||
|
||||
// Computes how many bytes you'd have to pad to be able to write an
|
||||
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
|
||||
// memory).
|
||||
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
|
||||
return ((~buf_size) + 1) & (scalar_size - 1);
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
#endif // FLATBUFFERS_BASE_H_
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_CODE_GENERATORS_H_
|
||||
#define FLATBUFFERS_CODE_GENERATORS_H_
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include "flatbuffers/idl.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Utility class to assist in generating code through use of text templates.
|
||||
//
|
||||
// Example code:
|
||||
// CodeWriter code;
|
||||
// code.SetValue("NAME", "Foo");
|
||||
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
|
||||
// code.SetValue("NAME", "Bar");
|
||||
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
|
||||
// std::cout << code.ToString() << std::endl;
|
||||
//
|
||||
// Output:
|
||||
// void Foo() { printf("%s", "Foo"); }
|
||||
// void Bar() { printf("%s", "Bar"); }
|
||||
class CodeWriter {
|
||||
public:
|
||||
CodeWriter() {}
|
||||
|
||||
// Clears the current "written" code.
|
||||
void Clear() {
|
||||
stream_.str("");
|
||||
stream_.clear();
|
||||
}
|
||||
|
||||
// Associates a key with a value. All subsequent calls to operator+=, where
|
||||
// the specified key is contained in {{ and }} delimiters will be replaced by
|
||||
// the given value.
|
||||
void SetValue(const std::string &key, const std::string &value) {
|
||||
value_map_[key] = value;
|
||||
}
|
||||
|
||||
// Appends the given text to the generated code as well as a newline
|
||||
// character. Any text within {{ and }} delimeters is replaced by values
|
||||
// previously stored in the CodeWriter by calling SetValue above. The newline
|
||||
// will be suppressed if the text ends with the \\ character.
|
||||
void operator+=(std::string text);
|
||||
|
||||
// Returns the current contents of the CodeWriter as a std::string.
|
||||
std::string ToString() const { return stream_.str(); }
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> value_map_;
|
||||
std::stringstream stream_;
|
||||
};
|
||||
|
||||
class BaseGenerator {
|
||||
public:
|
||||
virtual bool generate() = 0;
|
||||
|
||||
static std::string NamespaceDir(const Parser &parser, const std::string &path,
|
||||
const Namespace &ns);
|
||||
|
||||
protected:
|
||||
BaseGenerator(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name,
|
||||
const std::string qualifying_start,
|
||||
const std::string qualifying_separator)
|
||||
: parser_(parser),
|
||||
path_(path),
|
||||
file_name_(file_name),
|
||||
qualifying_start_(qualifying_start),
|
||||
qualifying_separator_(qualifying_separator) {}
|
||||
virtual ~BaseGenerator() {}
|
||||
|
||||
// No copy/assign.
|
||||
BaseGenerator &operator=(const BaseGenerator &);
|
||||
BaseGenerator(const BaseGenerator &);
|
||||
|
||||
std::string NamespaceDir(const Namespace &ns) const;
|
||||
|
||||
static const char *FlatBuffersGeneratedWarning();
|
||||
|
||||
static std::string FullNamespace(const char *separator, const Namespace &ns);
|
||||
|
||||
static std::string LastNamespacePart(const Namespace &ns);
|
||||
|
||||
// tracks the current namespace for early exit in WrapInNameSpace
|
||||
// c++, java and csharp returns a different namespace from
|
||||
// the following default (no early exit, always fully qualify),
|
||||
// which works for js and php
|
||||
virtual const Namespace *CurrentNameSpace() const { return nullptr; }
|
||||
|
||||
// Ensure that a type is prefixed with its namespace whenever it is used
|
||||
// outside of its namespace.
|
||||
std::string WrapInNameSpace(const Namespace *ns,
|
||||
const std::string &name) const;
|
||||
|
||||
std::string WrapInNameSpace(const Definition &def) const;
|
||||
|
||||
std::string GetNameSpace(const Definition &def) const;
|
||||
|
||||
const Parser &parser_;
|
||||
const std::string &path_;
|
||||
const std::string &file_name_;
|
||||
const std::string qualifying_start_;
|
||||
const std::string qualifying_separator_;
|
||||
};
|
||||
|
||||
struct CommentConfig {
|
||||
const char *first_line;
|
||||
const char *content_line_prefix;
|
||||
const char *last_line;
|
||||
};
|
||||
|
||||
extern void GenComment(const std::vector<std::string> &dc,
|
||||
std::string *code_ptr, const CommentConfig *config,
|
||||
const char *prefix = "");
|
||||
|
||||
class FloatConstantGenerator {
|
||||
public:
|
||||
virtual ~FloatConstantGenerator() {}
|
||||
std::string GenFloatConstant(const FieldDef &field) const;
|
||||
|
||||
private:
|
||||
virtual std::string Value(double v, const std::string &src) const = 0;
|
||||
virtual std::string Inf(double v) const = 0;
|
||||
virtual std::string NaN(double v) const = 0;
|
||||
|
||||
virtual std::string Value(float v, const std::string &src) const = 0;
|
||||
virtual std::string Inf(float v) const = 0;
|
||||
virtual std::string NaN(float v) const = 0;
|
||||
|
||||
template<typename T>
|
||||
std::string GenFloatConstantImpl(const FieldDef &field) const;
|
||||
};
|
||||
|
||||
class SimpleFloatConstantGenerator : public FloatConstantGenerator {
|
||||
public:
|
||||
SimpleFloatConstantGenerator(const char *nan_number,
|
||||
const char *pos_inf_number,
|
||||
const char *neg_inf_number);
|
||||
|
||||
private:
|
||||
std::string Value(double v,
|
||||
const std::string &src) const FLATBUFFERS_OVERRIDE;
|
||||
std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
|
||||
std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
|
||||
|
||||
std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE;
|
||||
std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
|
||||
std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
|
||||
|
||||
const std::string nan_number_;
|
||||
const std::string pos_inf_number_;
|
||||
const std::string neg_inf_number_;
|
||||
};
|
||||
|
||||
// C++, C#, Java like generator.
|
||||
class TypedFloatConstantGenerator : public FloatConstantGenerator {
|
||||
public:
|
||||
TypedFloatConstantGenerator(const char *double_prefix,
|
||||
const char *single_prefix, const char *nan_number,
|
||||
const char *pos_inf_number,
|
||||
const char *neg_inf_number = "");
|
||||
|
||||
private:
|
||||
std::string Value(double v,
|
||||
const std::string &src) const FLATBUFFERS_OVERRIDE;
|
||||
std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
|
||||
|
||||
std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
|
||||
|
||||
std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE;
|
||||
std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
|
||||
std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
|
||||
|
||||
std::string MakeNaN(const std::string &prefix) const;
|
||||
std::string MakeInf(bool neg, const std::string &prefix) const;
|
||||
|
||||
const std::string double_prefix_;
|
||||
const std::string single_prefix_;
|
||||
const std::string nan_number_;
|
||||
const std::string pos_inf_number_;
|
||||
const std::string neg_inf_number_;
|
||||
};
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_CODE_GENERATORS_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
#include "flatbuffers/util.h"
|
||||
|
||||
#ifndef FLATC_H_
|
||||
# define FLATC_H_
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
class FlatCompiler {
|
||||
public:
|
||||
// Output generator for the various programming languages and formats we
|
||||
// support.
|
||||
struct Generator {
|
||||
typedef bool (*GenerateFn)(const flatbuffers::Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
typedef std::string (*MakeRuleFn)(const flatbuffers::Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
GenerateFn generate;
|
||||
const char *generator_opt_short;
|
||||
const char *generator_opt_long;
|
||||
const char *lang_name;
|
||||
bool schema_only;
|
||||
GenerateFn generateGRPC;
|
||||
flatbuffers::IDLOptions::Language lang;
|
||||
const char *generator_help;
|
||||
MakeRuleFn make_rule;
|
||||
};
|
||||
|
||||
typedef void (*WarnFn)(const FlatCompiler *flatc, const std::string &warn,
|
||||
bool show_exe_name);
|
||||
|
||||
typedef void (*ErrorFn)(const FlatCompiler *flatc, const std::string &err,
|
||||
bool usage, bool show_exe_name);
|
||||
|
||||
// Parameters required to initialize the FlatCompiler.
|
||||
struct InitParams {
|
||||
InitParams()
|
||||
: generators(nullptr),
|
||||
num_generators(0),
|
||||
warn_fn(nullptr),
|
||||
error_fn(nullptr) {}
|
||||
|
||||
const Generator *generators;
|
||||
size_t num_generators;
|
||||
WarnFn warn_fn;
|
||||
ErrorFn error_fn;
|
||||
};
|
||||
|
||||
explicit FlatCompiler(const InitParams ¶ms) : params_(params) {}
|
||||
|
||||
int Compile(int argc, const char **argv);
|
||||
|
||||
std::string GetUsageString(const char *program_name) const;
|
||||
|
||||
private:
|
||||
void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
|
||||
const std::string &contents,
|
||||
std::vector<const char *> &include_directories) const;
|
||||
|
||||
void LoadBinarySchema(Parser &parser, const std::string &filename,
|
||||
const std::string &contents);
|
||||
|
||||
void Warn(const std::string &warn, bool show_exe_name = true) const;
|
||||
|
||||
void Error(const std::string &err, bool usage = true,
|
||||
bool show_exe_name = true) const;
|
||||
|
||||
InitParams params_;
|
||||
};
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATC_H_
|
||||
File diff suppressed because it is too large
Load Diff
328
src/ipa/rpi/cam_helper/imx500_tensor_parser/flatbuffers/grpc.h
Normal file
328
src/ipa/rpi/cam_helper/imx500_tensor_parser/flatbuffers/grpc.h
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_GRPC_H_
|
||||
#define FLATBUFFERS_GRPC_H_
|
||||
|
||||
// Helper functionality to glue FlatBuffers and GRPC.
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "grpc++/support/byte_buffer.h"
|
||||
#include "grpc/byte_buffer_reader.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
namespace grpc {
|
||||
|
||||
// Message is a typed wrapper around a buffer that manages the underlying
|
||||
// `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify`
|
||||
// and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer
|
||||
// is refcounted and ownership is be managed automatically.
|
||||
template<class T> class Message {
|
||||
public:
|
||||
Message() : slice_(grpc_empty_slice()) {}
|
||||
|
||||
Message(grpc_slice slice, bool add_ref)
|
||||
: slice_(add_ref ? grpc_slice_ref(slice) : slice) {}
|
||||
|
||||
Message &operator=(const Message &other) = delete;
|
||||
|
||||
Message(Message &&other) : slice_(other.slice_) {
|
||||
other.slice_ = grpc_empty_slice();
|
||||
}
|
||||
|
||||
Message(const Message &other) = delete;
|
||||
|
||||
Message &operator=(Message &&other) {
|
||||
grpc_slice_unref(slice_);
|
||||
slice_ = other.slice_;
|
||||
other.slice_ = grpc_empty_slice();
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Message() { grpc_slice_unref(slice_); }
|
||||
|
||||
const uint8_t *mutable_data() const { return GRPC_SLICE_START_PTR(slice_); }
|
||||
|
||||
const uint8_t *data() const { return GRPC_SLICE_START_PTR(slice_); }
|
||||
|
||||
size_t size() const { return GRPC_SLICE_LENGTH(slice_); }
|
||||
|
||||
bool Verify() const {
|
||||
Verifier verifier(data(), size());
|
||||
return verifier.VerifyBuffer<T>(nullptr);
|
||||
}
|
||||
|
||||
T *GetMutableRoot() { return flatbuffers::GetMutableRoot<T>(mutable_data()); }
|
||||
|
||||
const T *GetRoot() const { return flatbuffers::GetRoot<T>(data()); }
|
||||
|
||||
// This is only intended for serializer use, or if you know what you're doing
|
||||
const grpc_slice &BorrowSlice() const { return slice_; }
|
||||
|
||||
private:
|
||||
grpc_slice slice_;
|
||||
};
|
||||
|
||||
class MessageBuilder;
|
||||
|
||||
// SliceAllocator is a gRPC-specific allocator that uses the `grpc_slice`
|
||||
// refcounted slices to manage memory ownership. This makes it easy and
|
||||
// efficient to transfer buffers to gRPC.
|
||||
class SliceAllocator : public Allocator {
|
||||
public:
|
||||
SliceAllocator() : slice_(grpc_empty_slice()) {}
|
||||
|
||||
SliceAllocator(const SliceAllocator &other) = delete;
|
||||
SliceAllocator &operator=(const SliceAllocator &other) = delete;
|
||||
|
||||
SliceAllocator(SliceAllocator &&other)
|
||||
: slice_(grpc_empty_slice()) {
|
||||
// default-construct and swap idiom
|
||||
swap(other);
|
||||
}
|
||||
|
||||
SliceAllocator &operator=(SliceAllocator &&other) {
|
||||
// move-construct and swap idiom
|
||||
SliceAllocator temp(std::move(other));
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(SliceAllocator &other) {
|
||||
using std::swap;
|
||||
swap(slice_, other.slice_);
|
||||
}
|
||||
|
||||
virtual ~SliceAllocator() { grpc_slice_unref(slice_); }
|
||||
|
||||
virtual uint8_t *allocate(size_t size) override {
|
||||
FLATBUFFERS_ASSERT(GRPC_SLICE_IS_EMPTY(slice_));
|
||||
slice_ = grpc_slice_malloc(size);
|
||||
return GRPC_SLICE_START_PTR(slice_);
|
||||
}
|
||||
|
||||
virtual void deallocate(uint8_t *p, size_t size) override {
|
||||
FLATBUFFERS_ASSERT(p == GRPC_SLICE_START_PTR(slice_));
|
||||
FLATBUFFERS_ASSERT(size == GRPC_SLICE_LENGTH(slice_));
|
||||
grpc_slice_unref(slice_);
|
||||
slice_ = grpc_empty_slice();
|
||||
}
|
||||
|
||||
virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
|
||||
size_t new_size, size_t in_use_back,
|
||||
size_t in_use_front) override {
|
||||
FLATBUFFERS_ASSERT(old_p == GRPC_SLICE_START_PTR(slice_));
|
||||
FLATBUFFERS_ASSERT(old_size == GRPC_SLICE_LENGTH(slice_));
|
||||
FLATBUFFERS_ASSERT(new_size > old_size);
|
||||
grpc_slice old_slice = slice_;
|
||||
grpc_slice new_slice = grpc_slice_malloc(new_size);
|
||||
uint8_t *new_p = GRPC_SLICE_START_PTR(new_slice);
|
||||
memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
|
||||
in_use_front);
|
||||
slice_ = new_slice;
|
||||
grpc_slice_unref(old_slice);
|
||||
return new_p;
|
||||
}
|
||||
|
||||
private:
|
||||
grpc_slice &get_slice(uint8_t *p, size_t size) {
|
||||
FLATBUFFERS_ASSERT(p == GRPC_SLICE_START_PTR(slice_));
|
||||
FLATBUFFERS_ASSERT(size == GRPC_SLICE_LENGTH(slice_));
|
||||
return slice_;
|
||||
}
|
||||
|
||||
grpc_slice slice_;
|
||||
|
||||
friend class MessageBuilder;
|
||||
};
|
||||
|
||||
// SliceAllocatorMember is a hack to ensure that the MessageBuilder's
|
||||
// slice_allocator_ member is constructed before the FlatBufferBuilder, since
|
||||
// the allocator is used in the FlatBufferBuilder ctor.
|
||||
namespace detail {
|
||||
struct SliceAllocatorMember {
|
||||
SliceAllocator slice_allocator_;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
|
||||
// to allocate gRPC buffers.
|
||||
class MessageBuilder : private detail::SliceAllocatorMember,
|
||||
public FlatBufferBuilder {
|
||||
public:
|
||||
explicit MessageBuilder(uoffset_t initial_size = 1024)
|
||||
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
|
||||
|
||||
MessageBuilder(const MessageBuilder &other) = delete;
|
||||
MessageBuilder &operator=(const MessageBuilder &other) = delete;
|
||||
|
||||
MessageBuilder(MessageBuilder &&other)
|
||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||
// Default construct and swap idiom.
|
||||
Swap(other);
|
||||
}
|
||||
|
||||
/// Create a MessageBuilder from a FlatBufferBuilder.
|
||||
explicit MessageBuilder(FlatBufferBuilder &&src, void (*dealloc)(void*, size_t) = &DefaultAllocator::dealloc)
|
||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||
src.Swap(*this);
|
||||
src.SwapBufAllocator(*this);
|
||||
if (buf_.capacity()) {
|
||||
uint8_t *buf = buf_.scratch_data(); // pointer to memory
|
||||
size_t capacity = buf_.capacity(); // size of memory
|
||||
slice_allocator_.slice_ = grpc_slice_new_with_len(buf, capacity, dealloc);
|
||||
}
|
||||
else {
|
||||
slice_allocator_.slice_ = grpc_empty_slice();
|
||||
}
|
||||
}
|
||||
|
||||
/// Move-assign a FlatBufferBuilder to a MessageBuilder.
|
||||
/// Only FlatBufferBuilder with default allocator (basically, nullptr) is supported.
|
||||
MessageBuilder &operator=(FlatBufferBuilder &&src) {
|
||||
// Move construct a temporary and swap
|
||||
MessageBuilder temp(std::move(src));
|
||||
Swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MessageBuilder &operator=(MessageBuilder &&other) {
|
||||
// Move construct a temporary and swap
|
||||
MessageBuilder temp(std::move(other));
|
||||
Swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Swap(MessageBuilder &other) {
|
||||
slice_allocator_.swap(other.slice_allocator_);
|
||||
FlatBufferBuilder::Swap(other);
|
||||
// After swapping the FlatBufferBuilder, we swap back the allocator, which restores
|
||||
// the original allocator back in place. This is necessary because MessageBuilder's
|
||||
// allocator is its own member (SliceAllocatorMember). The allocator passed to
|
||||
// FlatBufferBuilder::vector_downward must point to this member.
|
||||
buf_.swap_allocator(other.buf_);
|
||||
}
|
||||
|
||||
// Releases the ownership of the buffer pointer.
|
||||
// Returns the size, offset, and the original grpc_slice that
|
||||
// allocated the buffer. Also see grpc_slice_unref().
|
||||
uint8_t *ReleaseRaw(size_t &size, size_t &offset, grpc_slice &slice) {
|
||||
uint8_t *buf = FlatBufferBuilder::ReleaseRaw(size, offset);
|
||||
slice = slice_allocator_.slice_;
|
||||
slice_allocator_.slice_ = grpc_empty_slice();
|
||||
return buf;
|
||||
}
|
||||
|
||||
~MessageBuilder() {}
|
||||
|
||||
// GetMessage extracts the subslice of the buffer corresponding to the
|
||||
// flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
|
||||
// ownership.
|
||||
template<class T> Message<T> GetMessage() {
|
||||
auto buf_data = buf_.scratch_data(); // pointer to memory
|
||||
auto buf_size = buf_.capacity(); // size of memory
|
||||
auto msg_data = buf_.data(); // pointer to msg
|
||||
auto msg_size = buf_.size(); // size of msg
|
||||
// Do some sanity checks on data/size
|
||||
FLATBUFFERS_ASSERT(msg_data);
|
||||
FLATBUFFERS_ASSERT(msg_size);
|
||||
FLATBUFFERS_ASSERT(msg_data >= buf_data);
|
||||
FLATBUFFERS_ASSERT(msg_data + msg_size <= buf_data + buf_size);
|
||||
// Calculate offsets from the buffer start
|
||||
auto begin = msg_data - buf_data;
|
||||
auto end = begin + msg_size;
|
||||
// Get the slice we are working with (no refcount change)
|
||||
grpc_slice slice = slice_allocator_.get_slice(buf_data, buf_size);
|
||||
// Extract a subslice of the existing slice (increment refcount)
|
||||
grpc_slice subslice = grpc_slice_sub(slice, begin, end);
|
||||
// Wrap the subslice in a `Message<T>`, but don't increment refcount
|
||||
Message<T> msg(subslice, false);
|
||||
return msg;
|
||||
}
|
||||
|
||||
template<class T> Message<T> ReleaseMessage() {
|
||||
Message<T> msg = GetMessage<T>();
|
||||
Reset();
|
||||
return msg;
|
||||
}
|
||||
|
||||
private:
|
||||
// SliceAllocator slice_allocator_; // part of SliceAllocatorMember
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
} // namespace flatbuffers
|
||||
|
||||
namespace grpc {
|
||||
|
||||
template<class T> class SerializationTraits<flatbuffers::grpc::Message<T>> {
|
||||
public:
|
||||
static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg,
|
||||
grpc_byte_buffer **buffer, bool *own_buffer) {
|
||||
// We are passed in a `Message<T>`, which is a wrapper around a
|
||||
// `grpc_slice`. We extract it here using `BorrowSlice()`. The const cast
|
||||
// is necesary because the `grpc_raw_byte_buffer_create` func expects
|
||||
// non-const slices in order to increment their refcounts.
|
||||
grpc_slice *slice = const_cast<grpc_slice *>(&msg.BorrowSlice());
|
||||
// Now use `grpc_raw_byte_buffer_create` to package the single slice into a
|
||||
// `grpc_byte_buffer`, incrementing the refcount in the process.
|
||||
*buffer = grpc_raw_byte_buffer_create(slice, 1);
|
||||
*own_buffer = true;
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
// Deserialize by pulling the
|
||||
static grpc::Status Deserialize(grpc_byte_buffer *buffer,
|
||||
flatbuffers::grpc::Message<T> *msg) {
|
||||
if (!buffer) {
|
||||
return ::grpc::Status(::grpc::StatusCode::INTERNAL, "No payload");
|
||||
}
|
||||
// Check if this is a single uncompressed slice.
|
||||
if ((buffer->type == GRPC_BB_RAW) &&
|
||||
(buffer->data.raw.compression == GRPC_COMPRESS_NONE) &&
|
||||
(buffer->data.raw.slice_buffer.count == 1)) {
|
||||
// If it is, then we can reference the `grpc_slice` directly.
|
||||
grpc_slice slice = buffer->data.raw.slice_buffer.slices[0];
|
||||
// We wrap a `Message<T>` around the slice, incrementing the refcount.
|
||||
*msg = flatbuffers::grpc::Message<T>(slice, true);
|
||||
} else {
|
||||
// Otherwise, we need to use `grpc_byte_buffer_reader_readall` to read
|
||||
// `buffer` into a single contiguous `grpc_slice`. The gRPC reader gives
|
||||
// us back a new slice with the refcount already incremented.
|
||||
grpc_byte_buffer_reader reader;
|
||||
grpc_byte_buffer_reader_init(&reader, buffer);
|
||||
grpc_slice slice = grpc_byte_buffer_reader_readall(&reader);
|
||||
grpc_byte_buffer_reader_destroy(&reader);
|
||||
// We wrap a `Message<T>` around the slice, but dont increment refcount
|
||||
*msg = flatbuffers::grpc::Message<T>(slice, false);
|
||||
}
|
||||
grpc_byte_buffer_destroy(buffer);
|
||||
#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
||||
return ::grpc::Status::OK;
|
||||
#else
|
||||
if (msg->Verify()) {
|
||||
return ::grpc::Status::OK;
|
||||
} else {
|
||||
return ::grpc::Status(::grpc::StatusCode::INTERNAL,
|
||||
"Message verification failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // FLATBUFFERS_GRPC_H_
|
||||
127
src/ipa/rpi/cam_helper/imx500_tensor_parser/flatbuffers/hash.h
Normal file
127
src/ipa/rpi/cam_helper/imx500_tensor_parser/flatbuffers/hash.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_HASH_H_
|
||||
#define FLATBUFFERS_HASH_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
template<typename T> struct FnvTraits {
|
||||
static const T kFnvPrime;
|
||||
static const T kOffsetBasis;
|
||||
};
|
||||
|
||||
template<> struct FnvTraits<uint32_t> {
|
||||
static const uint32_t kFnvPrime = 0x01000193;
|
||||
static const uint32_t kOffsetBasis = 0x811C9DC5;
|
||||
};
|
||||
|
||||
template<> struct FnvTraits<uint64_t> {
|
||||
static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
|
||||
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
|
||||
};
|
||||
|
||||
template<typename T> T HashFnv1(const char *input) {
|
||||
T hash = FnvTraits<T>::kOffsetBasis;
|
||||
for (const char *c = input; *c; ++c) {
|
||||
hash *= FnvTraits<T>::kFnvPrime;
|
||||
hash ^= static_cast<unsigned char>(*c);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
template<typename T> T HashFnv1a(const char *input) {
|
||||
T hash = FnvTraits<T>::kOffsetBasis;
|
||||
for (const char *c = input; *c; ++c) {
|
||||
hash ^= static_cast<unsigned char>(*c);
|
||||
hash *= FnvTraits<T>::kFnvPrime;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
template <> inline uint16_t HashFnv1<uint16_t>(const char *input) {
|
||||
uint32_t hash = HashFnv1<uint32_t>(input);
|
||||
return (hash >> 16) ^ (hash & 0xffff);
|
||||
}
|
||||
|
||||
template <> inline uint16_t HashFnv1a<uint16_t>(const char *input) {
|
||||
uint32_t hash = HashFnv1a<uint32_t>(input);
|
||||
return (hash >> 16) ^ (hash & 0xffff);
|
||||
}
|
||||
|
||||
template <typename T> struct NamedHashFunction {
|
||||
const char *name;
|
||||
|
||||
typedef T (*HashFunction)(const char *);
|
||||
HashFunction function;
|
||||
};
|
||||
|
||||
const NamedHashFunction<uint16_t> kHashFunctions16[] = {
|
||||
{ "fnv1_16", HashFnv1<uint16_t> },
|
||||
{ "fnv1a_16", HashFnv1a<uint16_t> },
|
||||
};
|
||||
|
||||
const NamedHashFunction<uint32_t> kHashFunctions32[] = {
|
||||
{ "fnv1_32", HashFnv1<uint32_t> },
|
||||
{ "fnv1a_32", HashFnv1a<uint32_t> },
|
||||
};
|
||||
|
||||
const NamedHashFunction<uint64_t> kHashFunctions64[] = {
|
||||
{ "fnv1_64", HashFnv1<uint64_t> },
|
||||
{ "fnv1a_64", HashFnv1a<uint64_t> },
|
||||
};
|
||||
|
||||
inline NamedHashFunction<uint16_t>::HashFunction FindHashFunction16(
|
||||
const char *name) {
|
||||
std::size_t size = sizeof(kHashFunctions16) / sizeof(kHashFunctions16[0]);
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
if (std::strcmp(name, kHashFunctions16[i].name) == 0) {
|
||||
return kHashFunctions16[i].function;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32(
|
||||
const char *name) {
|
||||
std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]);
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
if (std::strcmp(name, kHashFunctions32[i].name) == 0) {
|
||||
return kHashFunctions32[i].function;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline NamedHashFunction<uint64_t>::HashFunction FindHashFunction64(
|
||||
const char *name) {
|
||||
std::size_t size = sizeof(kHashFunctions64) / sizeof(kHashFunctions64[0]);
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
if (std::strcmp(name, kHashFunctions64[i].name) == 0) {
|
||||
return kHashFunctions64[i].function;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_HASH_H_
|
||||
995
src/ipa/rpi/cam_helper/imx500_tensor_parser/flatbuffers/idl.h
Normal file
995
src/ipa/rpi/cam_helper/imx500_tensor_parser/flatbuffers/idl.h
Normal file
@@ -0,0 +1,995 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_IDL_H_
|
||||
#define FLATBUFFERS_IDL_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/flexbuffers.h"
|
||||
#include "flatbuffers/hash.h"
|
||||
#include "flatbuffers/reflection.h"
|
||||
|
||||
#if !defined(FLATBUFFERS_CPP98_STL)
|
||||
# include <functional>
|
||||
#endif // !defined(FLATBUFFERS_CPP98_STL)
|
||||
|
||||
// This file defines the data types representing a parsed IDL (Interface
|
||||
// Definition Language) / schema file.
|
||||
|
||||
// Limits maximum depth of nested objects.
|
||||
// Prevents stack overflow while parse flatbuffers or json.
|
||||
#if !defined(FLATBUFFERS_MAX_PARSING_DEPTH)
|
||||
# define FLATBUFFERS_MAX_PARSING_DEPTH 64
|
||||
#endif
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// The order of these matters for Is*() functions below.
|
||||
// Additionally, Parser::ParseType assumes bool..string is a contiguous range
|
||||
// of type tokens.
|
||||
// clang-format off
|
||||
#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
|
||||
TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8) \
|
||||
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8) /* begin scalar/int */ \
|
||||
TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool) \
|
||||
TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8) \
|
||||
TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8) \
|
||||
TD(SHORT, "short", int16_t, short, int16, short, int16, i16) \
|
||||
TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16) \
|
||||
TD(INT, "int", int32_t, int, int32, int, int32, i32) \
|
||||
TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32) \
|
||||
TD(LONG, "long", int64_t, long, int64, long, int64, i64) \
|
||||
TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64) /* end int */ \
|
||||
TD(FLOAT, "float", float, float, float32, float, float32, f32) /* begin float */ \
|
||||
TD(DOUBLE, "double", double, double, float64, double, float64, f64) /* end float/scalar */
|
||||
#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
|
||||
TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused) \
|
||||
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused) \
|
||||
TD(STRUCT, "", Offset<void>, int, int, int, int, unused) \
|
||||
TD(UNION, "", Offset<void>, int, int, int, int, unused)
|
||||
|
||||
// The fields are:
|
||||
// - enum
|
||||
// - FlatBuffers schema type.
|
||||
// - C++ type.
|
||||
// - Java type.
|
||||
// - Go type.
|
||||
// - C# / .Net type.
|
||||
// - Python type.
|
||||
// - Rust type.
|
||||
|
||||
// using these macros, we can now write code dealing with types just once, e.g.
|
||||
|
||||
/*
|
||||
switch (type) {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||
RTYPE) \
|
||||
case BASE_TYPE_ ## ENUM: \
|
||||
// do something specific to CTYPE here
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
}
|
||||
*/
|
||||
|
||||
#define FLATBUFFERS_GEN_TYPES(TD) \
|
||||
FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(TD)
|
||||
|
||||
// Create an enum for all the types above.
|
||||
#ifdef __GNUC__
|
||||
__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
|
||||
#endif
|
||||
enum BaseType {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||
RTYPE) \
|
||||
BASE_TYPE_ ## ENUM,
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
};
|
||||
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||
RTYPE) \
|
||||
static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
|
||||
"define largest_scalar_t as " #CTYPE);
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
|
||||
inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
|
||||
t <= BASE_TYPE_DOUBLE; }
|
||||
inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
|
||||
t <= BASE_TYPE_ULONG; }
|
||||
inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
|
||||
t == BASE_TYPE_DOUBLE; }
|
||||
inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
|
||||
t == BASE_TYPE_ULONG; }
|
||||
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
|
||||
inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
|
||||
t <= BASE_TYPE_UCHAR; }
|
||||
// clang-format on
|
||||
|
||||
extern const char *const kTypeNames[];
|
||||
extern const char kTypeSizes[];
|
||||
|
||||
inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
|
||||
|
||||
struct StructDef;
|
||||
struct EnumDef;
|
||||
class Parser;
|
||||
|
||||
// Represents any type in the IDL, which is a combination of the BaseType
|
||||
// and additional information for vectors/structs_.
|
||||
struct Type {
|
||||
explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
|
||||
EnumDef *_ed = nullptr)
|
||||
: base_type(_base_type),
|
||||
element(BASE_TYPE_NONE),
|
||||
struct_def(_sd),
|
||||
enum_def(_ed) {}
|
||||
|
||||
bool operator==(const Type &o) {
|
||||
return base_type == o.base_type && element == o.element &&
|
||||
struct_def == o.struct_def && enum_def == o.enum_def;
|
||||
}
|
||||
|
||||
Type VectorType() const { return Type(element, struct_def, enum_def); }
|
||||
|
||||
Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
|
||||
|
||||
bool Deserialize(const Parser &parser, const reflection::Type *type);
|
||||
|
||||
BaseType base_type;
|
||||
BaseType element; // only set if t == BASE_TYPE_VECTOR
|
||||
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
|
||||
EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
|
||||
// or for an integral type derived from an enum.
|
||||
};
|
||||
|
||||
// Represents a parsed scalar value, it's type, and field offset.
|
||||
struct Value {
|
||||
Value()
|
||||
: constant("0"),
|
||||
offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
|
||||
Type type;
|
||||
std::string constant;
|
||||
voffset_t offset;
|
||||
};
|
||||
|
||||
// Helper class that retains the original order of a set of identifiers and
|
||||
// also provides quick lookup.
|
||||
template<typename T> class SymbolTable {
|
||||
public:
|
||||
~SymbolTable() {
|
||||
for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
|
||||
}
|
||||
|
||||
bool Add(const std::string &name, T *e) {
|
||||
vector_emplace_back(&vec, e);
|
||||
auto it = dict.find(name);
|
||||
if (it != dict.end()) return true;
|
||||
dict[name] = e;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Move(const std::string &oldname, const std::string &newname) {
|
||||
auto it = dict.find(oldname);
|
||||
if (it != dict.end()) {
|
||||
auto obj = it->second;
|
||||
dict.erase(it);
|
||||
dict[newname] = obj;
|
||||
} else {
|
||||
FLATBUFFERS_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
T *Lookup(const std::string &name) const {
|
||||
auto it = dict.find(name);
|
||||
return it == dict.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
public:
|
||||
std::map<std::string, T *> dict; // quick lookup
|
||||
std::vector<T *> vec; // Used to iterate in order of insertion
|
||||
};
|
||||
|
||||
// A name space, as set in the schema.
|
||||
struct Namespace {
|
||||
Namespace() : from_table(0) {}
|
||||
|
||||
// Given a (potentally unqualified) name, return the "fully qualified" name
|
||||
// which has a full namespaced descriptor.
|
||||
// With max_components you can request less than the number of components
|
||||
// the current namespace has.
|
||||
std::string GetFullyQualifiedName(const std::string &name,
|
||||
size_t max_components = 1000) const;
|
||||
|
||||
std::vector<std::string> components;
|
||||
size_t from_table; // Part of the namespace corresponds to a message/table.
|
||||
};
|
||||
|
||||
// Base class for all definition types (fields, structs_, enums_).
|
||||
struct Definition {
|
||||
Definition()
|
||||
: generated(false),
|
||||
defined_namespace(nullptr),
|
||||
serialized_location(0),
|
||||
index(-1),
|
||||
refcount(1) {}
|
||||
|
||||
flatbuffers::Offset<
|
||||
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
||||
SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
|
||||
bool DeserializeAttributes(Parser &parser,
|
||||
const Vector<Offset<reflection::KeyValue>> *attrs);
|
||||
|
||||
std::string name;
|
||||
std::string file;
|
||||
std::vector<std::string> doc_comment;
|
||||
SymbolTable<Value> attributes;
|
||||
bool generated; // did we already output code for this definition?
|
||||
Namespace *defined_namespace; // Where it was defined.
|
||||
|
||||
// For use with Serialize()
|
||||
uoffset_t serialized_location;
|
||||
int index; // Inside the vector it is stored.
|
||||
int refcount;
|
||||
};
|
||||
|
||||
struct FieldDef : public Definition {
|
||||
FieldDef()
|
||||
: deprecated(false),
|
||||
required(false),
|
||||
key(false),
|
||||
shared(false),
|
||||
native_inline(false),
|
||||
flexbuffer(false),
|
||||
nested_flatbuffer(NULL),
|
||||
padding(0) {}
|
||||
|
||||
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(Parser &parser, const reflection::Field *field);
|
||||
|
||||
Value value;
|
||||
bool deprecated; // Field is allowed to be present in old data, but can't be.
|
||||
// written in new data nor accessed in new code.
|
||||
bool required; // Field must always be present.
|
||||
bool key; // Field functions as a key for creating sorted vectors.
|
||||
bool shared; // Field will be using string pooling (i.e. CreateSharedString)
|
||||
// as default serialization behavior if field is a string.
|
||||
bool native_inline; // Field will be defined inline (instead of as a pointer)
|
||||
// for native tables if field is a struct.
|
||||
bool flexbuffer; // This field contains FlexBuffer data.
|
||||
StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
|
||||
size_t padding; // Bytes to always pad after this field.
|
||||
};
|
||||
|
||||
struct StructDef : public Definition {
|
||||
StructDef()
|
||||
: fixed(false),
|
||||
predecl(true),
|
||||
sortbysize(true),
|
||||
has_key(false),
|
||||
minalign(1),
|
||||
bytesize(0) {}
|
||||
|
||||
void PadLastField(size_t min_align) {
|
||||
auto padding = PaddingBytes(bytesize, min_align);
|
||||
bytesize += padding;
|
||||
if (fields.vec.size()) fields.vec.back()->padding = padding;
|
||||
}
|
||||
|
||||
Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(Parser &parser, const reflection::Object *object);
|
||||
|
||||
SymbolTable<FieldDef> fields;
|
||||
|
||||
bool fixed; // If it's struct, not a table.
|
||||
bool predecl; // If it's used before it was defined.
|
||||
bool sortbysize; // Whether fields come in the declaration or size order.
|
||||
bool has_key; // It has a key field.
|
||||
size_t minalign; // What the whole object needs to be aligned to.
|
||||
size_t bytesize; // Size if fixed.
|
||||
|
||||
flatbuffers::unique_ptr<std::string> original_location;
|
||||
};
|
||||
|
||||
inline bool IsStruct(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
|
||||
}
|
||||
|
||||
inline size_t InlineSize(const Type &type) {
|
||||
return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type);
|
||||
}
|
||||
|
||||
inline size_t InlineAlignment(const Type &type) {
|
||||
return IsStruct(type) ? type.struct_def->minalign : SizeOf(type.base_type);
|
||||
}
|
||||
|
||||
struct EnumVal {
|
||||
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
|
||||
EnumVal() : value(0) {}
|
||||
|
||||
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
|
||||
bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
|
||||
bool IsZero() const { return 0 == value; }
|
||||
bool IsNonZero() const { return !IsZero(); }
|
||||
|
||||
std::string name;
|
||||
std::vector<std::string> doc_comment;
|
||||
int64_t value;
|
||||
Type union_type;
|
||||
};
|
||||
|
||||
struct EnumDef : public Definition {
|
||||
EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
|
||||
|
||||
EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
|
||||
for (auto it = Vals().begin() +
|
||||
static_cast<int>(is_union && skip_union_default);
|
||||
it != Vals().end(); ++it) {
|
||||
if ((*it)->value == enum_idx) { return *it; }
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
|
||||
bool Deserialize(Parser &parser, const reflection::Enum *values);
|
||||
|
||||
size_t size() const { return vals.vec.size(); }
|
||||
|
||||
const std::vector<EnumVal *> &Vals() const {
|
||||
return vals.vec;
|
||||
}
|
||||
|
||||
SymbolTable<EnumVal> vals;
|
||||
bool is_union;
|
||||
// Type is a union which uses type aliases where at least one type is
|
||||
// available under two different names.
|
||||
bool uses_multiple_type_instances;
|
||||
Type underlying_type;
|
||||
};
|
||||
|
||||
inline bool EqualByName(const Type &a, const Type &b) {
|
||||
return a.base_type == b.base_type && a.element == b.element &&
|
||||
(a.struct_def == b.struct_def ||
|
||||
a.struct_def->name == b.struct_def->name) &&
|
||||
(a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
|
||||
}
|
||||
|
||||
struct RPCCall : public Definition {
|
||||
Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
|
||||
bool Deserialize(Parser &parser, const reflection::RPCCall *call);
|
||||
|
||||
StructDef *request, *response;
|
||||
};
|
||||
|
||||
struct ServiceDef : public Definition {
|
||||
Offset<reflection::Service> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
bool Deserialize(Parser &parser, const reflection::Service *service);
|
||||
|
||||
SymbolTable<RPCCall> calls;
|
||||
};
|
||||
|
||||
// Container of options that may apply to any of the source/text generators.
|
||||
struct IDLOptions {
|
||||
bool strict_json;
|
||||
bool skip_js_exports;
|
||||
bool use_goog_js_export_format;
|
||||
bool use_ES6_js_export_format;
|
||||
bool output_default_scalars_in_json;
|
||||
int indent_step;
|
||||
bool output_enum_identifiers;
|
||||
bool prefixed_enums;
|
||||
bool scoped_enums;
|
||||
bool include_dependence_headers;
|
||||
bool mutable_buffer;
|
||||
bool one_file;
|
||||
bool proto_mode;
|
||||
bool proto_oneof_union;
|
||||
bool generate_all;
|
||||
bool skip_unexpected_fields_in_json;
|
||||
bool generate_name_strings;
|
||||
bool generate_object_based_api;
|
||||
bool gen_compare;
|
||||
std::string cpp_object_api_pointer_type;
|
||||
std::string cpp_object_api_string_type;
|
||||
bool cpp_object_api_string_flexible_constructor;
|
||||
bool gen_nullable;
|
||||
bool gen_generated;
|
||||
std::string object_prefix;
|
||||
std::string object_suffix;
|
||||
bool union_value_namespacing;
|
||||
bool allow_non_utf8;
|
||||
bool natural_utf8;
|
||||
std::string include_prefix;
|
||||
bool keep_include_path;
|
||||
bool binary_schema_comments;
|
||||
bool binary_schema_builtins;
|
||||
bool skip_flatbuffers_import;
|
||||
std::string go_import;
|
||||
std::string go_namespace;
|
||||
bool reexport_ts_modules;
|
||||
bool js_ts_short_names;
|
||||
bool protobuf_ascii_alike;
|
||||
bool size_prefixed;
|
||||
std::string root_type;
|
||||
bool force_defaults;
|
||||
|
||||
// Possible options for the more general generator below.
|
||||
enum Language {
|
||||
kJava = 1 << 0,
|
||||
kCSharp = 1 << 1,
|
||||
kGo = 1 << 2,
|
||||
kCpp = 1 << 3,
|
||||
kJs = 1 << 4,
|
||||
kPython = 1 << 5,
|
||||
kPhp = 1 << 6,
|
||||
kJson = 1 << 7,
|
||||
kBinary = 1 << 8,
|
||||
kTs = 1 << 9,
|
||||
kJsonSchema = 1 << 10,
|
||||
kDart = 1 << 11,
|
||||
kLua = 1 << 12,
|
||||
kLobster = 1 << 13,
|
||||
kRust = 1 << 14,
|
||||
kMAX
|
||||
};
|
||||
|
||||
Language lang;
|
||||
|
||||
enum MiniReflect { kNone, kTypes, kTypesAndNames };
|
||||
|
||||
MiniReflect mini_reflect;
|
||||
|
||||
// The corresponding language bit will be set if a language is included
|
||||
// for code generation.
|
||||
unsigned long lang_to_generate;
|
||||
|
||||
// If set (default behavior), empty string and vector fields will be set to
|
||||
// nullptr to make the flatbuffer more compact.
|
||||
bool set_empty_to_null;
|
||||
|
||||
IDLOptions()
|
||||
: strict_json(false),
|
||||
skip_js_exports(false),
|
||||
use_goog_js_export_format(false),
|
||||
use_ES6_js_export_format(false),
|
||||
output_default_scalars_in_json(false),
|
||||
indent_step(2),
|
||||
output_enum_identifiers(true),
|
||||
prefixed_enums(true),
|
||||
scoped_enums(false),
|
||||
include_dependence_headers(true),
|
||||
mutable_buffer(false),
|
||||
one_file(false),
|
||||
proto_mode(false),
|
||||
proto_oneof_union(false),
|
||||
generate_all(false),
|
||||
skip_unexpected_fields_in_json(false),
|
||||
generate_name_strings(false),
|
||||
generate_object_based_api(false),
|
||||
gen_compare(false),
|
||||
cpp_object_api_pointer_type("std::unique_ptr"),
|
||||
cpp_object_api_string_flexible_constructor(false),
|
||||
gen_nullable(false),
|
||||
gen_generated(false),
|
||||
object_suffix("T"),
|
||||
union_value_namespacing(true),
|
||||
allow_non_utf8(false),
|
||||
natural_utf8(false),
|
||||
keep_include_path(false),
|
||||
binary_schema_comments(false),
|
||||
binary_schema_builtins(false),
|
||||
skip_flatbuffers_import(false),
|
||||
reexport_ts_modules(true),
|
||||
js_ts_short_names(false),
|
||||
protobuf_ascii_alike(false),
|
||||
size_prefixed(false),
|
||||
force_defaults(false),
|
||||
lang(IDLOptions::kJava),
|
||||
mini_reflect(IDLOptions::kNone),
|
||||
lang_to_generate(0),
|
||||
set_empty_to_null(true) {}
|
||||
};
|
||||
|
||||
// This encapsulates where the parser is in the current source file.
|
||||
struct ParserState {
|
||||
ParserState()
|
||||
: cursor_(nullptr),
|
||||
line_start_(nullptr),
|
||||
line_(0),
|
||||
token_(-1),
|
||||
attr_is_trivial_ascii_string_(true) {}
|
||||
|
||||
protected:
|
||||
void ResetState(const char *source) {
|
||||
cursor_ = source;
|
||||
line_ = 0;
|
||||
MarkNewLine();
|
||||
}
|
||||
|
||||
void MarkNewLine() {
|
||||
line_start_ = cursor_;
|
||||
line_ += 1;
|
||||
}
|
||||
|
||||
int64_t CursorPosition() const {
|
||||
FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
|
||||
return static_cast<int64_t>(cursor_ - line_start_);
|
||||
}
|
||||
|
||||
const char *cursor_;
|
||||
const char *line_start_;
|
||||
int line_; // the current line being parsed
|
||||
int token_;
|
||||
|
||||
// Flag: text in attribute_ is true ASCII string without escape
|
||||
// sequences. Only printable ASCII (without [\t\r\n]).
|
||||
// Used for number-in-string (and base64 string in future).
|
||||
bool attr_is_trivial_ascii_string_;
|
||||
std::string attribute_;
|
||||
std::vector<std::string> doc_comment_;
|
||||
};
|
||||
|
||||
// A way to make error propagation less error prone by requiring values to be
|
||||
// checked.
|
||||
// Once you create a value of this type you must either:
|
||||
// - Call Check() on it.
|
||||
// - Copy or assign it to another value.
|
||||
// Failure to do so leads to an assert.
|
||||
// This guarantees that this as return value cannot be ignored.
|
||||
class CheckedError {
|
||||
public:
|
||||
explicit CheckedError(bool error)
|
||||
: is_error_(error), has_been_checked_(false) {}
|
||||
|
||||
CheckedError &operator=(const CheckedError &other) {
|
||||
is_error_ = other.is_error_;
|
||||
has_been_checked_ = false;
|
||||
other.has_been_checked_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CheckedError(const CheckedError &other) {
|
||||
*this = other; // Use assignment operator.
|
||||
}
|
||||
|
||||
~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
|
||||
|
||||
bool Check() {
|
||||
has_been_checked_ = true;
|
||||
return is_error_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool is_error_;
|
||||
mutable bool has_been_checked_;
|
||||
};
|
||||
|
||||
// Additionally, in GCC we can get these errors statically, for additional
|
||||
// assurance:
|
||||
// clang-format off
|
||||
#ifdef __GNUC__
|
||||
#define FLATBUFFERS_CHECKED_ERROR CheckedError \
|
||||
__attribute__((warn_unused_result))
|
||||
#else
|
||||
#define FLATBUFFERS_CHECKED_ERROR CheckedError
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
class Parser : public ParserState {
|
||||
public:
|
||||
explicit Parser(const IDLOptions &options = IDLOptions())
|
||||
: current_namespace_(nullptr),
|
||||
empty_namespace_(nullptr),
|
||||
root_struct_def_(nullptr),
|
||||
opts(options),
|
||||
uses_flexbuffers_(false),
|
||||
source_(nullptr),
|
||||
anonymous_counter(0),
|
||||
recurse_protection_counter(0) {
|
||||
if (opts.force_defaults) {
|
||||
builder_.ForceDefaults(true);
|
||||
}
|
||||
// Start out with the empty namespace being current.
|
||||
empty_namespace_ = new Namespace();
|
||||
namespaces_.push_back(empty_namespace_);
|
||||
current_namespace_ = empty_namespace_;
|
||||
known_attributes_["deprecated"] = true;
|
||||
known_attributes_["required"] = true;
|
||||
known_attributes_["key"] = true;
|
||||
known_attributes_["shared"] = true;
|
||||
known_attributes_["hash"] = true;
|
||||
known_attributes_["id"] = true;
|
||||
known_attributes_["force_align"] = true;
|
||||
known_attributes_["bit_flags"] = true;
|
||||
known_attributes_["original_order"] = true;
|
||||
known_attributes_["nested_flatbuffer"] = true;
|
||||
known_attributes_["csharp_partial"] = true;
|
||||
known_attributes_["streaming"] = true;
|
||||
known_attributes_["idempotent"] = true;
|
||||
known_attributes_["cpp_type"] = true;
|
||||
known_attributes_["cpp_ptr_type"] = true;
|
||||
known_attributes_["cpp_ptr_type_get"] = true;
|
||||
known_attributes_["cpp_str_type"] = true;
|
||||
known_attributes_["cpp_str_flex_ctor"] = true;
|
||||
known_attributes_["native_inline"] = true;
|
||||
known_attributes_["native_custom_alloc"] = true;
|
||||
known_attributes_["native_type"] = true;
|
||||
known_attributes_["native_default"] = true;
|
||||
known_attributes_["flexbuffer"] = true;
|
||||
known_attributes_["private"] = true;
|
||||
}
|
||||
|
||||
~Parser() {
|
||||
for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the string containing either schema or JSON data, which will
|
||||
// populate the SymbolTable's or the FlatBufferBuilder above.
|
||||
// include_paths is used to resolve any include statements, and typically
|
||||
// should at least include the project path (where you loaded source_ from).
|
||||
// include_paths must be nullptr terminated if specified.
|
||||
// If include_paths is nullptr, it will attempt to load from the current
|
||||
// directory.
|
||||
// If the source was loaded from a file and isn't an include file,
|
||||
// supply its name in source_filename.
|
||||
// All paths specified in this call must be in posix format, if you accept
|
||||
// paths from user input, please call PosixPath on them first.
|
||||
bool Parse(const char *_source, const char **include_paths = nullptr,
|
||||
const char *source_filename = nullptr);
|
||||
|
||||
// Set the root type. May override the one set in the schema.
|
||||
bool SetRootType(const char *name);
|
||||
|
||||
// Mark all definitions as already having code generated.
|
||||
void MarkGenerated();
|
||||
|
||||
// Get the files recursively included by the given file. The returned
|
||||
// container will have at least the given file.
|
||||
std::set<std::string> GetIncludedFilesRecursive(
|
||||
const std::string &file_name) const;
|
||||
|
||||
// Fills builder_ with a binary version of the schema parsed.
|
||||
// See reflection/reflection.fbs
|
||||
void Serialize();
|
||||
|
||||
// Deserialize a schema buffer
|
||||
bool Deserialize(const uint8_t *buf, const size_t size);
|
||||
|
||||
// Fills internal structure as if the schema passed had been loaded by parsing
|
||||
// with Parse except that included filenames will not be populated.
|
||||
bool Deserialize(const reflection::Schema* schema);
|
||||
|
||||
Type* DeserializeType(const reflection::Type* type);
|
||||
|
||||
// Checks that the schema represented by this parser is a safe evolution
|
||||
// of the schema provided. Returns non-empty error on any problems.
|
||||
std::string ConformTo(const Parser &base);
|
||||
|
||||
// Similar to Parse(), but now only accepts JSON to be parsed into a
|
||||
// FlexBuffer.
|
||||
bool ParseFlexBuffer(const char *source, const char *source_filename,
|
||||
flexbuffers::Builder *builder);
|
||||
|
||||
StructDef *LookupStruct(const std::string &id) const;
|
||||
|
||||
std::string UnqualifiedName(std::string fullQualifiedName);
|
||||
|
||||
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
||||
|
||||
private:
|
||||
void Message(const std::string &msg);
|
||||
void Warning(const std::string &msg);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
|
||||
FLATBUFFERS_CHECKED_ERROR Next();
|
||||
FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
|
||||
bool Is(int t) const;
|
||||
bool IsIdent(const char *id) const;
|
||||
FLATBUFFERS_CHECKED_ERROR Expect(int t);
|
||||
std::string TokenToStringId(int t) const;
|
||||
EnumDef *LookupEnum(const std::string &id);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
|
||||
std::string *last);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
|
||||
FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
|
||||
const std::string &name, const Type &type,
|
||||
FieldDef **dest);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseString(Value &val);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseComma();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
|
||||
size_t parent_fieldn,
|
||||
const StructDef *parent_struct_def,
|
||||
uoffset_t count,
|
||||
bool inside_vector = false);
|
||||
template<typename F>
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
|
||||
const StructDef *struct_def,
|
||||
F body);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
|
||||
std::string *value, uoffset_t *ovalue);
|
||||
void SerializeStruct(const StructDef &struct_def, const Value &val);
|
||||
template<typename F>
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
|
||||
FieldDef *field, size_t fieldn);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
||||
size_t fieldn,
|
||||
const StructDef *parent_struct_def);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
|
||||
FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e,
|
||||
BaseType req, bool *destmatch);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
|
||||
FLATBUFFERS_CHECKED_ERROR TokenError();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, bool check_now);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, std::string *result);
|
||||
StructDef *LookupCreateStruct(const std::string &name,
|
||||
bool create_if_new = true,
|
||||
bool definition = false);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseNamespace();
|
||||
FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
|
||||
StructDef **dest);
|
||||
FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name,
|
||||
bool is_union,
|
||||
EnumDef **dest);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseDecl();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseService();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
|
||||
bool isextend, bool inside_oneof);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
|
||||
FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
|
||||
FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
|
||||
const char *source_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
|
||||
const char **include_paths,
|
||||
const char *source_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
|
||||
const char **include_paths,
|
||||
const char *source_filename,
|
||||
const char *include_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
|
||||
StructDef *struct_def,
|
||||
const char *suffix,
|
||||
BaseType baseType);
|
||||
|
||||
bool SupportsAdvancedUnionFeatures() const;
|
||||
Namespace *UniqueNamespace(Namespace *ns);
|
||||
|
||||
FLATBUFFERS_CHECKED_ERROR RecurseError();
|
||||
template<typename F> CheckedError Recurse(F f);
|
||||
|
||||
public:
|
||||
SymbolTable<Type> types_;
|
||||
SymbolTable<StructDef> structs_;
|
||||
SymbolTable<EnumDef> enums_;
|
||||
SymbolTable<ServiceDef> services_;
|
||||
std::vector<Namespace *> namespaces_;
|
||||
Namespace *current_namespace_;
|
||||
Namespace *empty_namespace_;
|
||||
std::string error_; // User readable error_ if Parse() == false
|
||||
|
||||
FlatBufferBuilder builder_; // any data contained in the file
|
||||
StructDef *root_struct_def_;
|
||||
std::string file_identifier_;
|
||||
std::string file_extension_;
|
||||
|
||||
std::map<std::string, std::string> included_files_;
|
||||
std::map<std::string, std::set<std::string>> files_included_per_file_;
|
||||
std::vector<std::string> native_included_files_;
|
||||
|
||||
std::map<std::string, bool> known_attributes_;
|
||||
|
||||
IDLOptions opts;
|
||||
bool uses_flexbuffers_;
|
||||
|
||||
private:
|
||||
const char *source_;
|
||||
|
||||
std::string file_being_parsed_;
|
||||
|
||||
std::vector<std::pair<Value, FieldDef *>> field_stack_;
|
||||
|
||||
int anonymous_counter;
|
||||
int recurse_protection_counter;
|
||||
};
|
||||
|
||||
// Utility functions for multiple generators:
|
||||
|
||||
extern std::string MakeCamel(const std::string &in, bool first = true);
|
||||
|
||||
// Generate text (JSON) from a given FlatBuffer, and a given Parser
|
||||
// object that has been populated with the corresponding schema.
|
||||
// If ident_step is 0, no indentation will be generated. Additionally,
|
||||
// if it is less than 0, no linefeeds will be generated either.
|
||||
// See idl_gen_text.cpp.
|
||||
// strict_json adds "quotes" around field names if true.
|
||||
// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
|
||||
// byte arrays in String values), returns false.
|
||||
extern bool GenerateTextFromTable(const Parser &parser,
|
||||
const void *table,
|
||||
const std::string &tablename,
|
||||
std::string *text);
|
||||
extern bool GenerateText(const Parser &parser,
|
||||
const void *flatbuffer,
|
||||
std::string *text);
|
||||
extern bool GenerateTextFile(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate binary files from a given FlatBuffer, and a given Parser
|
||||
// object that has been populated with the corresponding schema.
|
||||
// See idl_gen_general.cpp.
|
||||
extern bool GenerateBinary(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a C++ header from the definitions in the Parser object.
|
||||
// See idl_gen_cpp.
|
||||
extern bool GenerateCPP(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
extern bool GenerateDart(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
|
||||
// See idl_gen_js.
|
||||
extern bool GenerateJSTS(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Go files from the definitions in the Parser object.
|
||||
// See idl_gen_go.cpp.
|
||||
extern bool GenerateGo(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Php code from the definitions in the Parser object.
|
||||
// See idl_gen_php.
|
||||
extern bool GeneratePhp(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Python files from the definitions in the Parser object.
|
||||
// See idl_gen_python.cpp.
|
||||
extern bool GeneratePython(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Lobster files from the definitions in the Parser object.
|
||||
// See idl_gen_lobster.cpp.
|
||||
extern bool GenerateLobster(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Lua files from the definitions in the Parser object.
|
||||
// See idl_gen_lua.cpp.
|
||||
extern bool GenerateLua(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Rust files from the definitions in the Parser object.
|
||||
// See idl_gen_rust.cpp.
|
||||
extern bool GenerateRust(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Json schema file
|
||||
// See idl_gen_json_schema.cpp.
|
||||
extern bool GenerateJsonSchema(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Java/C#/.. files from the definitions in the Parser object.
|
||||
// See idl_gen_general.cpp.
|
||||
extern bool GenerateGeneral(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a schema file from the internal representation, useful after
|
||||
// parsing a .proto schema.
|
||||
extern std::string GenerateFBS(const Parser &parser,
|
||||
const std::string &file_name);
|
||||
extern bool GenerateFBS(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated JavaScript or TypeScript code.
|
||||
// See idl_gen_js.cpp.
|
||||
extern std::string JSTSMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated C++ header.
|
||||
// See idl_gen_cpp.cpp.
|
||||
extern std::string CPPMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated Dart code
|
||||
// see idl_gen_dart.cpp
|
||||
extern std::string DartMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated Rust code.
|
||||
// See idl_gen_rust.cpp.
|
||||
extern std::string RustMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated Java/C#/... files.
|
||||
// See idl_gen_general.cpp.
|
||||
extern std::string GeneralMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated text (JSON) files.
|
||||
// See idl_gen_text.cpp.
|
||||
extern std::string TextMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_names);
|
||||
|
||||
// Generate a make rule for the generated binary files.
|
||||
// See idl_gen_general.cpp.
|
||||
extern std::string BinaryMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Cpp interfaces.
|
||||
// See idl_gen_grpc.cpp.
|
||||
bool GenerateCppGRPC(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Go interfaces.
|
||||
// See idl_gen_grpc.cpp.
|
||||
bool GenerateGoGRPC(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Java classes.
|
||||
// See idl_gen_grpc.cpp
|
||||
bool GenerateJavaGRPC(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_IDL_H_
|
||||
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_MINIREFLECT_H_
|
||||
#define FLATBUFFERS_MINIREFLECT_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/util.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Utilities that can be used with the "mini reflection" tables present
|
||||
// in generated code with --reflect-types (only types) or --reflect-names
|
||||
// (also names).
|
||||
// This allows basic reflection functionality such as pretty-printing
|
||||
// that does not require the use of the schema parser or loading of binary
|
||||
// schema files at runtime (reflection.h).
|
||||
|
||||
// For any of the functions below that take `const TypeTable *`, you pass
|
||||
// `FooTypeTable()` if the type of the root is `Foo`.
|
||||
|
||||
// First, a generic iterator that can be used by multiple algorithms.
|
||||
|
||||
struct IterationVisitor {
|
||||
// These mark the scope of a table or struct.
|
||||
virtual void StartSequence() {}
|
||||
virtual void EndSequence() {}
|
||||
// Called for each field regardless of wether it is present or not.
|
||||
// If not present, val == nullptr. set_idx is the index of all set fields.
|
||||
virtual void Field(size_t /*field_idx*/, size_t /*set_idx*/,
|
||||
ElementaryType /*type*/, bool /*is_vector*/,
|
||||
const TypeTable * /*type_table*/, const char * /*name*/,
|
||||
const uint8_t * /*val*/) {}
|
||||
// Called for a value that is actually present, after a field, or as part
|
||||
// of a vector.
|
||||
virtual void UType(uint8_t, const char *) {}
|
||||
virtual void Bool(bool) {}
|
||||
virtual void Char(int8_t, const char *) {}
|
||||
virtual void UChar(uint8_t, const char *) {}
|
||||
virtual void Short(int16_t, const char *) {}
|
||||
virtual void UShort(uint16_t, const char *) {}
|
||||
virtual void Int(int32_t, const char *) {}
|
||||
virtual void UInt(uint32_t, const char *) {}
|
||||
virtual void Long(int64_t) {}
|
||||
virtual void ULong(uint64_t) {}
|
||||
virtual void Float(float) {}
|
||||
virtual void Double(double) {}
|
||||
virtual void String(const String *) {}
|
||||
virtual void Unknown(const uint8_t *) {} // From a future version.
|
||||
// These mark the scope of a vector.
|
||||
virtual void StartVector() {}
|
||||
virtual void EndVector() {}
|
||||
virtual void Element(size_t /*i*/, ElementaryType /*type*/,
|
||||
const TypeTable * /*type_table*/,
|
||||
const uint8_t * /*val*/) {}
|
||||
virtual ~IterationVisitor() {}
|
||||
};
|
||||
|
||||
inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
|
||||
switch (type) {
|
||||
case ET_UTYPE:
|
||||
case ET_BOOL:
|
||||
case ET_CHAR:
|
||||
case ET_UCHAR: return 1;
|
||||
case ET_SHORT:
|
||||
case ET_USHORT: return 2;
|
||||
case ET_INT:
|
||||
case ET_UINT:
|
||||
case ET_FLOAT:
|
||||
case ET_STRING: return 4;
|
||||
case ET_LONG:
|
||||
case ET_ULONG:
|
||||
case ET_DOUBLE: return 8;
|
||||
case ET_SEQUENCE:
|
||||
switch (type_table->st) {
|
||||
case ST_TABLE:
|
||||
case ST_UNION: return 4;
|
||||
case ST_STRUCT: return static_cast<size_t>(type_table->values[type_table->num_elems]);
|
||||
default: FLATBUFFERS_ASSERT(false); return 1;
|
||||
}
|
||||
default: FLATBUFFERS_ASSERT(false); return 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline int64_t LookupEnum(int64_t enum_val, const int64_t *values,
|
||||
size_t num_values) {
|
||||
if (!values) return enum_val;
|
||||
for (size_t i = 0; i < num_values; i++) {
|
||||
if (enum_val == values[i]) return static_cast<int64_t>(i);
|
||||
}
|
||||
return -1; // Unknown enum value.
|
||||
}
|
||||
|
||||
template<typename T> const char *EnumName(T tval, const TypeTable *type_table) {
|
||||
if (!type_table || !type_table->names) return nullptr;
|
||||
auto i = LookupEnum(static_cast<int64_t>(tval), type_table->values,
|
||||
type_table->num_elems);
|
||||
if (i >= 0 && i < static_cast<int64_t>(type_table->num_elems)) {
|
||||
return type_table->names[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void IterateObject(const uint8_t *obj, const TypeTable *type_table,
|
||||
IterationVisitor *visitor);
|
||||
|
||||
inline void IterateValue(ElementaryType type, const uint8_t *val,
|
||||
const TypeTable *type_table, const uint8_t *prev_val,
|
||||
soffset_t vector_index, IterationVisitor *visitor) {
|
||||
switch (type) {
|
||||
case ET_UTYPE: {
|
||||
auto tval = ReadScalar<uint8_t>(val);
|
||||
visitor->UType(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_BOOL: {
|
||||
visitor->Bool(ReadScalar<uint8_t>(val) != 0);
|
||||
break;
|
||||
}
|
||||
case ET_CHAR: {
|
||||
auto tval = ReadScalar<int8_t>(val);
|
||||
visitor->Char(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_UCHAR: {
|
||||
auto tval = ReadScalar<uint8_t>(val);
|
||||
visitor->UChar(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_SHORT: {
|
||||
auto tval = ReadScalar<int16_t>(val);
|
||||
visitor->Short(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_USHORT: {
|
||||
auto tval = ReadScalar<uint16_t>(val);
|
||||
visitor->UShort(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_INT: {
|
||||
auto tval = ReadScalar<int32_t>(val);
|
||||
visitor->Int(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_UINT: {
|
||||
auto tval = ReadScalar<uint32_t>(val);
|
||||
visitor->UInt(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_LONG: {
|
||||
visitor->Long(ReadScalar<int64_t>(val));
|
||||
break;
|
||||
}
|
||||
case ET_ULONG: {
|
||||
visitor->ULong(ReadScalar<uint64_t>(val));
|
||||
break;
|
||||
}
|
||||
case ET_FLOAT: {
|
||||
visitor->Float(ReadScalar<float>(val));
|
||||
break;
|
||||
}
|
||||
case ET_DOUBLE: {
|
||||
visitor->Double(ReadScalar<double>(val));
|
||||
break;
|
||||
}
|
||||
case ET_STRING: {
|
||||
val += ReadScalar<uoffset_t>(val);
|
||||
visitor->String(reinterpret_cast<const String *>(val));
|
||||
break;
|
||||
}
|
||||
case ET_SEQUENCE: {
|
||||
switch (type_table->st) {
|
||||
case ST_TABLE:
|
||||
val += ReadScalar<uoffset_t>(val);
|
||||
IterateObject(val, type_table, visitor);
|
||||
break;
|
||||
case ST_STRUCT: IterateObject(val, type_table, visitor); break;
|
||||
case ST_UNION: {
|
||||
val += ReadScalar<uoffset_t>(val);
|
||||
FLATBUFFERS_ASSERT(prev_val);
|
||||
auto union_type = *prev_val; // Always a uint8_t.
|
||||
if (vector_index >= 0) {
|
||||
auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
|
||||
union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
|
||||
}
|
||||
auto type_code_idx =
|
||||
LookupEnum(union_type, type_table->values, type_table->num_elems);
|
||||
if (type_code_idx >= 0 &&
|
||||
type_code_idx < static_cast<int32_t>(type_table->num_elems)) {
|
||||
auto type_code = type_table->type_codes[type_code_idx];
|
||||
switch (type_code.base_type) {
|
||||
case ET_SEQUENCE: {
|
||||
auto ref = type_table->type_refs[type_code.sequence_ref]();
|
||||
IterateObject(val, ref, visitor);
|
||||
break;
|
||||
}
|
||||
case ET_STRING:
|
||||
visitor->String(reinterpret_cast<const String *>(val));
|
||||
break;
|
||||
default: visitor->Unknown(val);
|
||||
}
|
||||
} else {
|
||||
visitor->Unknown(val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ST_ENUM: FLATBUFFERS_ASSERT(false); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
visitor->Unknown(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void IterateObject(const uint8_t *obj, const TypeTable *type_table,
|
||||
IterationVisitor *visitor) {
|
||||
visitor->StartSequence();
|
||||
const uint8_t *prev_val = nullptr;
|
||||
size_t set_idx = 0;
|
||||
for (size_t i = 0; i < type_table->num_elems; i++) {
|
||||
auto type_code = type_table->type_codes[i];
|
||||
auto type = static_cast<ElementaryType>(type_code.base_type);
|
||||
auto is_vector = type_code.is_vector != 0;
|
||||
auto ref_idx = type_code.sequence_ref;
|
||||
const TypeTable *ref = nullptr;
|
||||
if (ref_idx >= 0) { ref = type_table->type_refs[ref_idx](); }
|
||||
auto name = type_table->names ? type_table->names[i] : nullptr;
|
||||
const uint8_t *val = nullptr;
|
||||
if (type_table->st == ST_TABLE) {
|
||||
val = reinterpret_cast<const Table *>(obj)->GetAddressOf(
|
||||
FieldIndexToOffset(static_cast<voffset_t>(i)));
|
||||
} else {
|
||||
val = obj + type_table->values[i];
|
||||
}
|
||||
visitor->Field(i, set_idx, type, is_vector, ref, name, val);
|
||||
if (val) {
|
||||
set_idx++;
|
||||
if (is_vector) {
|
||||
val += ReadScalar<uoffset_t>(val);
|
||||
auto vec = reinterpret_cast<const Vector<uint8_t> *>(val);
|
||||
visitor->StartVector();
|
||||
auto elem_ptr = vec->Data();
|
||||
for (size_t j = 0; j < vec->size(); j++) {
|
||||
visitor->Element(j, type, ref, elem_ptr);
|
||||
IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j),
|
||||
visitor);
|
||||
elem_ptr += InlineSize(type, ref);
|
||||
}
|
||||
visitor->EndVector();
|
||||
} else {
|
||||
IterateValue(type, val, ref, prev_val, -1, visitor);
|
||||
}
|
||||
}
|
||||
prev_val = val;
|
||||
}
|
||||
visitor->EndSequence();
|
||||
}
|
||||
|
||||
inline void IterateFlatBuffer(const uint8_t *buffer,
|
||||
const TypeTable *type_table,
|
||||
IterationVisitor *callback) {
|
||||
IterateObject(GetRoot<uint8_t>(buffer), type_table, callback);
|
||||
}
|
||||
|
||||
// Outputting a Flatbuffer to a string. Tries to conform as close to JSON /
|
||||
// the output generated by idl_gen_text.cpp.
|
||||
|
||||
struct ToStringVisitor : public IterationVisitor {
|
||||
std::string s;
|
||||
std::string d;
|
||||
bool q;
|
||||
std::string in;
|
||||
size_t indent_level;
|
||||
bool vector_delimited;
|
||||
ToStringVisitor(std::string delimiter, bool quotes, std::string indent,
|
||||
bool vdelimited = true)
|
||||
: d(delimiter),
|
||||
q(quotes),
|
||||
in(indent),
|
||||
indent_level(0),
|
||||
vector_delimited(vdelimited) {}
|
||||
ToStringVisitor(std::string delimiter)
|
||||
: d(delimiter),
|
||||
q(false),
|
||||
in(""),
|
||||
indent_level(0),
|
||||
vector_delimited(true) {}
|
||||
|
||||
void append_indent() {
|
||||
for (size_t i = 0; i < indent_level; i++) { s += in; }
|
||||
}
|
||||
|
||||
void StartSequence() {
|
||||
s += "{";
|
||||
s += d;
|
||||
indent_level++;
|
||||
}
|
||||
void EndSequence() {
|
||||
s += d;
|
||||
indent_level--;
|
||||
append_indent();
|
||||
s += "}";
|
||||
}
|
||||
void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/,
|
||||
bool /*is_vector*/, const TypeTable * /*type_table*/,
|
||||
const char *name, const uint8_t *val) {
|
||||
if (!val) return;
|
||||
if (set_idx) {
|
||||
s += ",";
|
||||
s += d;
|
||||
}
|
||||
append_indent();
|
||||
if (name) {
|
||||
if (q) s += "\"";
|
||||
s += name;
|
||||
if (q) s += "\"";
|
||||
s += ": ";
|
||||
}
|
||||
}
|
||||
template<typename T> void Named(T x, const char *name) {
|
||||
if (name) {
|
||||
if (q) s += "\"";
|
||||
s += name;
|
||||
if (q) s += "\"";
|
||||
} else {
|
||||
s += NumToString(x);
|
||||
}
|
||||
}
|
||||
void UType(uint8_t x, const char *name) { Named(x, name); }
|
||||
void Bool(bool x) { s += x ? "true" : "false"; }
|
||||
void Char(int8_t x, const char *name) { Named(x, name); }
|
||||
void UChar(uint8_t x, const char *name) { Named(x, name); }
|
||||
void Short(int16_t x, const char *name) { Named(x, name); }
|
||||
void UShort(uint16_t x, const char *name) { Named(x, name); }
|
||||
void Int(int32_t x, const char *name) { Named(x, name); }
|
||||
void UInt(uint32_t x, const char *name) { Named(x, name); }
|
||||
void Long(int64_t x) { s += NumToString(x); }
|
||||
void ULong(uint64_t x) { s += NumToString(x); }
|
||||
void Float(float x) { s += NumToString(x); }
|
||||
void Double(double x) { s += NumToString(x); }
|
||||
void String(const struct String *str) {
|
||||
EscapeString(str->c_str(), str->size(), &s, true, false);
|
||||
}
|
||||
void Unknown(const uint8_t *) { s += "(?)"; }
|
||||
void StartVector() {
|
||||
s += "[";
|
||||
if (vector_delimited) {
|
||||
s += d;
|
||||
indent_level++;
|
||||
append_indent();
|
||||
} else {
|
||||
s += " ";
|
||||
}
|
||||
}
|
||||
void EndVector() {
|
||||
if (vector_delimited) {
|
||||
s += d;
|
||||
indent_level--;
|
||||
append_indent();
|
||||
} else {
|
||||
s += " ";
|
||||
}
|
||||
s += "]";
|
||||
}
|
||||
void Element(size_t i, ElementaryType /*type*/,
|
||||
const TypeTable * /*type_table*/, const uint8_t * /*val*/) {
|
||||
if (i) {
|
||||
s += ",";
|
||||
if (vector_delimited) {
|
||||
s += d;
|
||||
append_indent();
|
||||
} else {
|
||||
s += " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline std::string FlatBufferToString(const uint8_t *buffer,
|
||||
const TypeTable *type_table,
|
||||
bool multi_line = false,
|
||||
bool vector_delimited = true) {
|
||||
ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, "",
|
||||
vector_delimited);
|
||||
IterateFlatBuffer(buffer, type_table, &tostring_visitor);
|
||||
return tostring_visitor.s;
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_MINIREFLECT_H_
|
||||
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_REFLECTION_H_
|
||||
#define FLATBUFFERS_REFLECTION_H_
|
||||
|
||||
// This is somewhat of a circular dependency because flatc (and thus this
|
||||
// file) is needed to generate this header in the first place.
|
||||
// Should normally not be a problem since it can be generated by the
|
||||
// previous version of flatc whenever this code needs to change.
|
||||
// See reflection/generate_code.sh
|
||||
#include "flatbuffers/reflection_generated.h"
|
||||
|
||||
// Helper functionality for reflection.
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// ------------------------- GETTERS -------------------------
|
||||
|
||||
inline bool IsScalar(reflection::BaseType t) {
|
||||
return t >= reflection::UType && t <= reflection::Double;
|
||||
}
|
||||
inline bool IsInteger(reflection::BaseType t) {
|
||||
return t >= reflection::UType && t <= reflection::ULong;
|
||||
}
|
||||
inline bool IsFloat(reflection::BaseType t) {
|
||||
return t == reflection::Float || t == reflection::Double;
|
||||
}
|
||||
inline bool IsLong(reflection::BaseType t) {
|
||||
return t == reflection::Long || t == reflection::ULong;
|
||||
}
|
||||
|
||||
// Size of a basic type, don't use with structs.
|
||||
inline size_t GetTypeSize(reflection::BaseType base_type) {
|
||||
// This needs to correspond to the BaseType enum.
|
||||
static size_t sizes[] = { 0, 1, 1, 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 4, 4, 4, 4 };
|
||||
return sizes[base_type];
|
||||
}
|
||||
|
||||
// Same as above, but now correctly returns the size of a struct if
|
||||
// the field (or vector element) is a struct.
|
||||
inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index,
|
||||
const reflection::Schema &schema) {
|
||||
if (base_type == reflection::Obj &&
|
||||
schema.objects()->Get(type_index)->is_struct()) {
|
||||
return schema.objects()->Get(type_index)->bytesize();
|
||||
} else {
|
||||
return GetTypeSize(base_type);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the root, regardless of what type it is.
|
||||
inline Table *GetAnyRoot(uint8_t *flatbuf) {
|
||||
return GetMutableRoot<Table>(flatbuf);
|
||||
}
|
||||
inline const Table *GetAnyRoot(const uint8_t *flatbuf) {
|
||||
return GetRoot<Table>(flatbuf);
|
||||
}
|
||||
|
||||
// Get a field's default, if you know it's an integer, and its exact type.
|
||||
template<typename T> T GetFieldDefaultI(const reflection::Field &field) {
|
||||
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||
return static_cast<T>(field.default_integer());
|
||||
}
|
||||
|
||||
// Get a field's default, if you know it's floating point and its exact type.
|
||||
template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
|
||||
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||
return static_cast<T>(field.default_real());
|
||||
}
|
||||
|
||||
// Get a field, if you know it's an integer, and its exact type.
|
||||
template<typename T>
|
||||
T GetFieldI(const Table &table, const reflection::Field &field) {
|
||||
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||
return table.GetField<T>(field.offset(),
|
||||
static_cast<T>(field.default_integer()));
|
||||
}
|
||||
|
||||
// Get a field, if you know it's floating point and its exact type.
|
||||
template<typename T>
|
||||
T GetFieldF(const Table &table, const reflection::Field &field) {
|
||||
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||
return table.GetField<T>(field.offset(),
|
||||
static_cast<T>(field.default_real()));
|
||||
}
|
||||
|
||||
// Get a field, if you know it's a string.
|
||||
inline const String *GetFieldS(const Table &table,
|
||||
const reflection::Field &field) {
|
||||
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::String);
|
||||
return table.GetPointer<const String *>(field.offset());
|
||||
}
|
||||
|
||||
// Get a field, if you know it's a vector.
|
||||
template<typename T>
|
||||
Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) {
|
||||
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Vector &&
|
||||
sizeof(T) == GetTypeSize(field.type()->element()));
|
||||
return table.GetPointer<Vector<T> *>(field.offset());
|
||||
}
|
||||
|
||||
// Get a field, if you know it's a vector, generically.
|
||||
// To actually access elements, use the return value together with
|
||||
// field.type()->element() in any of GetAnyVectorElemI below etc.
|
||||
inline VectorOfAny *GetFieldAnyV(const Table &table,
|
||||
const reflection::Field &field) {
|
||||
return table.GetPointer<VectorOfAny *>(field.offset());
|
||||
}
|
||||
|
||||
// Get a field, if you know it's a table.
|
||||
inline Table *GetFieldT(const Table &table, const reflection::Field &field) {
|
||||
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj ||
|
||||
field.type()->base_type() == reflection::Union);
|
||||
return table.GetPointer<Table *>(field.offset());
|
||||
}
|
||||
|
||||
// Get a field, if you know it's a struct.
|
||||
inline const Struct *GetFieldStruct(const Table &table,
|
||||
const reflection::Field &field) {
|
||||
// TODO: This does NOT check if the field is a table or struct, but we'd need
|
||||
// access to the schema to check the is_struct flag.
|
||||
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
|
||||
return table.GetStruct<const Struct *>(field.offset());
|
||||
}
|
||||
|
||||
// Get a structure's field, if you know it's a struct.
|
||||
inline const Struct *GetFieldStruct(const Struct &structure,
|
||||
const reflection::Field &field) {
|
||||
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
|
||||
return structure.GetStruct<const Struct *>(field.offset());
|
||||
}
|
||||
|
||||
// Raw helper functions used below: get any value in memory as a 64bit int, a
|
||||
// double or a string.
|
||||
// All scalars get static_cast to an int64_t, strings use strtoull, every other
|
||||
// data type returns 0.
|
||||
int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data);
|
||||
// All scalars static cast to double, strings use strtod, every other data
|
||||
// type is 0.0.
|
||||
double GetAnyValueF(reflection::BaseType type, const uint8_t *data);
|
||||
// All scalars converted using stringstream, strings as-is, and all other
|
||||
// data types provide some level of debug-pretty-printing.
|
||||
std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
|
||||
const reflection::Schema *schema, int type_index);
|
||||
|
||||
// Get any table field as a 64bit int, regardless of what type it is.
|
||||
inline int64_t GetAnyFieldI(const Table &table,
|
||||
const reflection::Field &field) {
|
||||
auto field_ptr = table.GetAddressOf(field.offset());
|
||||
return field_ptr ? GetAnyValueI(field.type()->base_type(), field_ptr)
|
||||
: field.default_integer();
|
||||
}
|
||||
|
||||
// Get any table field as a double, regardless of what type it is.
|
||||
inline double GetAnyFieldF(const Table &table, const reflection::Field &field) {
|
||||
auto field_ptr = table.GetAddressOf(field.offset());
|
||||
return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr)
|
||||
: field.default_real();
|
||||
}
|
||||
|
||||
// Get any table field as a string, regardless of what type it is.
|
||||
// You may pass nullptr for the schema if you don't care to have fields that
|
||||
// are of table type pretty-printed.
|
||||
inline std::string GetAnyFieldS(const Table &table,
|
||||
const reflection::Field &field,
|
||||
const reflection::Schema *schema) {
|
||||
auto field_ptr = table.GetAddressOf(field.offset());
|
||||
return field_ptr ? GetAnyValueS(field.type()->base_type(), field_ptr, schema,
|
||||
field.type()->index())
|
||||
: "";
|
||||
}
|
||||
|
||||
// Get any struct field as a 64bit int, regardless of what type it is.
|
||||
inline int64_t GetAnyFieldI(const Struct &st, const reflection::Field &field) {
|
||||
return GetAnyValueI(field.type()->base_type(),
|
||||
st.GetAddressOf(field.offset()));
|
||||
}
|
||||
|
||||
// Get any struct field as a double, regardless of what type it is.
|
||||
inline double GetAnyFieldF(const Struct &st, const reflection::Field &field) {
|
||||
return GetAnyValueF(field.type()->base_type(),
|
||||
st.GetAddressOf(field.offset()));
|
||||
}
|
||||
|
||||
// Get any struct field as a string, regardless of what type it is.
|
||||
inline std::string GetAnyFieldS(const Struct &st,
|
||||
const reflection::Field &field) {
|
||||
return GetAnyValueS(field.type()->base_type(),
|
||||
st.GetAddressOf(field.offset()), nullptr, -1);
|
||||
}
|
||||
|
||||
// Get any vector element as a 64bit int, regardless of what type it is.
|
||||
inline int64_t GetAnyVectorElemI(const VectorOfAny *vec,
|
||||
reflection::BaseType elem_type, size_t i) {
|
||||
return GetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
|
||||
}
|
||||
|
||||
// Get any vector element as a double, regardless of what type it is.
|
||||
inline double GetAnyVectorElemF(const VectorOfAny *vec,
|
||||
reflection::BaseType elem_type, size_t i) {
|
||||
return GetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
|
||||
}
|
||||
|
||||
// Get any vector element as a string, regardless of what type it is.
|
||||
inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
|
||||
reflection::BaseType elem_type, size_t i) {
|
||||
return GetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i,
|
||||
nullptr, -1);
|
||||
}
|
||||
|
||||
// Get a vector element that's a table/string/vector from a generic vector.
|
||||
// Pass Table/String/VectorOfAny as template parameter.
|
||||
// Warning: does no typechecking.
|
||||
template<typename T>
|
||||
T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
|
||||
auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
|
||||
return reinterpret_cast<T*>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
|
||||
}
|
||||
|
||||
// Get the inline-address of a vector element. Useful for Structs (pass Struct
|
||||
// as template arg), or being able to address a range of scalars in-line.
|
||||
// Get elem_size from GetTypeSizeInline().
|
||||
// Note: little-endian data on all platforms, use EndianScalar() instead of
|
||||
// raw pointer access with scalars).
|
||||
template<typename T>
|
||||
T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i,
|
||||
size_t elem_size) {
|
||||
return reinterpret_cast<T *>(vec->Data() + elem_size * i);
|
||||
}
|
||||
|
||||
// Similarly, for elements of tables.
|
||||
template<typename T>
|
||||
T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) {
|
||||
return reinterpret_cast<T *>(table.GetAddressOf(field.offset()));
|
||||
}
|
||||
|
||||
// Similarly, for elements of structs.
|
||||
template<typename T>
|
||||
T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
|
||||
return reinterpret_cast<T *>(st.GetAddressOf(field.offset()));
|
||||
}
|
||||
|
||||
// ------------------------- SETTERS -------------------------
|
||||
|
||||
// Set any scalar field, if you know its exact type.
|
||||
template<typename T>
|
||||
bool SetField(Table *table, const reflection::Field &field, T val) {
|
||||
reflection::BaseType type = field.type()->base_type();
|
||||
if (!IsScalar(type)) { return false; }
|
||||
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(type));
|
||||
T def;
|
||||
if (IsInteger(type)) {
|
||||
def = GetFieldDefaultI<T>(field);
|
||||
} else {
|
||||
FLATBUFFERS_ASSERT(IsFloat(type));
|
||||
def = GetFieldDefaultF<T>(field);
|
||||
}
|
||||
return table->SetField(field.offset(), val, def);
|
||||
}
|
||||
|
||||
// Raw helper functions used below: set any value in memory as a 64bit int, a
|
||||
// double or a string.
|
||||
// These work for all scalar values, but do nothing for other data types.
|
||||
// To set a string, see SetString below.
|
||||
void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val);
|
||||
void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val);
|
||||
void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val);
|
||||
|
||||
// Set any table field as a 64bit int, regardless of type what it is.
|
||||
inline bool SetAnyFieldI(Table *table, const reflection::Field &field,
|
||||
int64_t val) {
|
||||
auto field_ptr = table->GetAddressOf(field.offset());
|
||||
if (!field_ptr) return val == GetFieldDefaultI<int64_t>(field);
|
||||
SetAnyValueI(field.type()->base_type(), field_ptr, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set any table field as a double, regardless of what type it is.
|
||||
inline bool SetAnyFieldF(Table *table, const reflection::Field &field,
|
||||
double val) {
|
||||
auto field_ptr = table->GetAddressOf(field.offset());
|
||||
if (!field_ptr) return val == GetFieldDefaultF<double>(field);
|
||||
SetAnyValueF(field.type()->base_type(), field_ptr, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set any table field as a string, regardless of what type it is.
|
||||
inline bool SetAnyFieldS(Table *table, const reflection::Field &field,
|
||||
const char *val) {
|
||||
auto field_ptr = table->GetAddressOf(field.offset());
|
||||
if (!field_ptr) return false;
|
||||
SetAnyValueS(field.type()->base_type(), field_ptr, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set any struct field as a 64bit int, regardless of type what it is.
|
||||
inline void SetAnyFieldI(Struct *st, const reflection::Field &field,
|
||||
int64_t val) {
|
||||
SetAnyValueI(field.type()->base_type(), st->GetAddressOf(field.offset()),
|
||||
val);
|
||||
}
|
||||
|
||||
// Set any struct field as a double, regardless of type what it is.
|
||||
inline void SetAnyFieldF(Struct *st, const reflection::Field &field,
|
||||
double val) {
|
||||
SetAnyValueF(field.type()->base_type(), st->GetAddressOf(field.offset()),
|
||||
val);
|
||||
}
|
||||
|
||||
// Set any struct field as a string, regardless of type what it is.
|
||||
inline void SetAnyFieldS(Struct *st, const reflection::Field &field,
|
||||
const char *val) {
|
||||
SetAnyValueS(field.type()->base_type(), st->GetAddressOf(field.offset()),
|
||||
val);
|
||||
}
|
||||
|
||||
// Set any vector element as a 64bit int, regardless of type what it is.
|
||||
inline void SetAnyVectorElemI(VectorOfAny *vec, reflection::BaseType elem_type,
|
||||
size_t i, int64_t val) {
|
||||
SetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
|
||||
}
|
||||
|
||||
// Set any vector element as a double, regardless of type what it is.
|
||||
inline void SetAnyVectorElemF(VectorOfAny *vec, reflection::BaseType elem_type,
|
||||
size_t i, double val) {
|
||||
SetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
|
||||
}
|
||||
|
||||
// Set any vector element as a string, regardless of type what it is.
|
||||
inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type,
|
||||
size_t i, const char *val) {
|
||||
SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
|
||||
}
|
||||
|
||||
// ------------------------- RESIZING SETTERS -------------------------
|
||||
|
||||
// "smart" pointer for use with resizing vectors: turns a pointer inside
|
||||
// a vector into a relative offset, such that it is not affected by resizes.
|
||||
template<typename T, typename U> class pointer_inside_vector {
|
||||
public:
|
||||
pointer_inside_vector(T *ptr, std::vector<U> &vec)
|
||||
: offset_(reinterpret_cast<uint8_t *>(ptr) -
|
||||
reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))),
|
||||
vec_(vec) {}
|
||||
|
||||
T *operator*() const {
|
||||
return reinterpret_cast<T *>(
|
||||
reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec_)) + offset_);
|
||||
}
|
||||
T *operator->() const { return operator*(); }
|
||||
void operator=(const pointer_inside_vector &piv);
|
||||
|
||||
private:
|
||||
size_t offset_;
|
||||
std::vector<U> &vec_;
|
||||
};
|
||||
|
||||
// Helper to create the above easily without specifying template args.
|
||||
template<typename T, typename U>
|
||||
pointer_inside_vector<T, U> piv(T *ptr, std::vector<U> &vec) {
|
||||
return pointer_inside_vector<T, U>(ptr, vec);
|
||||
}
|
||||
|
||||
inline const char *UnionTypeFieldSuffix() { return "_type"; }
|
||||
|
||||
// Helper to figure out the actual table type a union refers to.
|
||||
inline const reflection::Object &GetUnionType(
|
||||
const reflection::Schema &schema, const reflection::Object &parent,
|
||||
const reflection::Field &unionfield, const Table &table) {
|
||||
auto enumdef = schema.enums()->Get(unionfield.type()->index());
|
||||
// TODO: this is clumsy and slow, but no other way to find it?
|
||||
auto type_field = parent.fields()->LookupByKey(
|
||||
(unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
|
||||
FLATBUFFERS_ASSERT(type_field);
|
||||
auto union_type = GetFieldI<uint8_t>(table, *type_field);
|
||||
auto enumval = enumdef->values()->LookupByKey(union_type);
|
||||
return *enumval->object();
|
||||
}
|
||||
|
||||
// Changes the contents of a string inside a FlatBuffer. FlatBuffer must
|
||||
// live inside a std::vector so we can resize the buffer if needed.
|
||||
// "str" must live inside "flatbuf" and may be invalidated after this call.
|
||||
// If your FlatBuffer's root table is not the schema's root table, you should
|
||||
// pass in your root_table type as well.
|
||||
void SetString(const reflection::Schema &schema, const std::string &val,
|
||||
const String *str, std::vector<uint8_t> *flatbuf,
|
||||
const reflection::Object *root_table = nullptr);
|
||||
|
||||
// Resizes a flatbuffers::Vector inside a FlatBuffer. FlatBuffer must
|
||||
// live inside a std::vector so we can resize the buffer if needed.
|
||||
// "vec" must live inside "flatbuf" and may be invalidated after this call.
|
||||
// If your FlatBuffer's root table is not the schema's root table, you should
|
||||
// pass in your root_table type as well.
|
||||
uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
|
||||
const VectorOfAny *vec, uoffset_t num_elems,
|
||||
uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
|
||||
const reflection::Object *root_table = nullptr);
|
||||
|
||||
template<typename T>
|
||||
void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
|
||||
const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
|
||||
const reflection::Object *root_table = nullptr) {
|
||||
auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
|
||||
auto newelems = ResizeAnyVector(
|
||||
schema, newsize, reinterpret_cast<const VectorOfAny *>(vec), vec->size(),
|
||||
static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table);
|
||||
// Set new elements to "val".
|
||||
for (int i = 0; i < delta_elem; i++) {
|
||||
auto loc = newelems + i * sizeof(T);
|
||||
auto is_scalar = flatbuffers::is_scalar<T>::value;
|
||||
if (is_scalar) {
|
||||
WriteScalar(loc, val);
|
||||
} else { // struct
|
||||
*reinterpret_cast<T *>(loc) = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adds any new data (in the form of a new FlatBuffer) to an existing
|
||||
// FlatBuffer. This can be used when any of the above methods are not
|
||||
// sufficient, in particular for adding new tables and new fields.
|
||||
// This is potentially slightly less efficient than a FlatBuffer constructed
|
||||
// in one piece, since the new FlatBuffer doesn't share any vtables with the
|
||||
// existing one.
|
||||
// The return value can now be set using Vector::MutateOffset or SetFieldT
|
||||
// below.
|
||||
const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
|
||||
const uint8_t *newbuf, size_t newlen);
|
||||
|
||||
inline bool SetFieldT(Table *table, const reflection::Field &field,
|
||||
const uint8_t *val) {
|
||||
FLATBUFFERS_ASSERT(sizeof(uoffset_t) ==
|
||||
GetTypeSize(field.type()->base_type()));
|
||||
return table->SetPointer(field.offset(), val);
|
||||
}
|
||||
|
||||
// ------------------------- COPYING -------------------------
|
||||
|
||||
// Generic copying of tables from a FlatBuffer into a FlatBuffer builder.
|
||||
// Can be used to do any kind of merging/selecting you may want to do out
|
||||
// of existing buffers. Also useful to reconstruct a whole buffer if the
|
||||
// above resizing functionality has introduced garbage in a buffer you want
|
||||
// to remove.
|
||||
// Note: this does not deal with DAGs correctly. If the table passed forms a
|
||||
// DAG, the copy will be a tree instead (with duplicates). Strings can be
|
||||
// shared however, by passing true for use_string_pooling.
|
||||
|
||||
Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
|
||||
const reflection::Schema &schema,
|
||||
const reflection::Object &objectdef,
|
||||
const Table &table,
|
||||
bool use_string_pooling = false);
|
||||
|
||||
// Verifies the provided flatbuffer using reflection.
|
||||
// root should point to the root type for this flatbuffer.
|
||||
// buf should point to the start of flatbuffer data.
|
||||
// length specifies the size of the flatbuffer data.
|
||||
bool Verify(const reflection::Schema &schema, const reflection::Object &root,
|
||||
const uint8_t *buf, size_t length);
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_REFLECTION_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_REGISTRY_H_
|
||||
#define FLATBUFFERS_REGISTRY_H_
|
||||
|
||||
#include "flatbuffers/idl.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Convenience class to easily parse or generate text for arbitrary FlatBuffers.
|
||||
// Simply pre-populate it with all schema filenames that may be in use, and
|
||||
// This class will look them up using the file_identifier declared in the
|
||||
// schema.
|
||||
class Registry {
|
||||
public:
|
||||
// Call this for all schemas that may be in use. The identifier has
|
||||
// a function in the generated code, e.g. MonsterIdentifier().
|
||||
void Register(const char *file_identifier, const char *schema_path) {
|
||||
Schema schema;
|
||||
schema.path_ = schema_path;
|
||||
schemas_[file_identifier] = schema;
|
||||
}
|
||||
|
||||
// Generate text from an arbitrary FlatBuffer by looking up its
|
||||
// file_identifier in the registry.
|
||||
bool FlatBufferToText(const uint8_t *flatbuf, size_t len, std::string *dest) {
|
||||
// Get the identifier out of the buffer.
|
||||
// If the buffer is truncated, exit.
|
||||
if (len < sizeof(uoffset_t) + FlatBufferBuilder::kFileIdentifierLength) {
|
||||
lasterror_ = "buffer truncated";
|
||||
return false;
|
||||
}
|
||||
std::string ident(
|
||||
reinterpret_cast<const char *>(flatbuf) + sizeof(uoffset_t),
|
||||
FlatBufferBuilder::kFileIdentifierLength);
|
||||
// Load and parse the schema.
|
||||
Parser parser;
|
||||
if (!LoadSchema(ident, &parser)) return false;
|
||||
// Now we're ready to generate text.
|
||||
if (!GenerateText(parser, flatbuf, dest)) {
|
||||
lasterror_ = "unable to generate text for FlatBuffer binary";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Converts a binary buffer to text using one of the schemas in the registry,
|
||||
// use the file_identifier to indicate which.
|
||||
// If DetachedBuffer::data() is null then parsing failed.
|
||||
DetachedBuffer TextToFlatBuffer(const char *text,
|
||||
const char *file_identifier) {
|
||||
// Load and parse the schema.
|
||||
Parser parser;
|
||||
if (!LoadSchema(file_identifier, &parser)) return DetachedBuffer();
|
||||
// Parse the text.
|
||||
if (!parser.Parse(text)) {
|
||||
lasterror_ = parser.error_;
|
||||
return DetachedBuffer();
|
||||
}
|
||||
// We have a valid FlatBuffer. Detach it from the builder and return.
|
||||
return parser.builder_.Release();
|
||||
}
|
||||
|
||||
// Modify any parsing / output options used by the other functions.
|
||||
void SetOptions(const IDLOptions &opts) { opts_ = opts; }
|
||||
|
||||
// If schemas used contain include statements, call this function for every
|
||||
// directory the parser should search them for.
|
||||
void AddIncludeDirectory(const char *path) { include_paths_.push_back(path); }
|
||||
|
||||
// Returns a human readable error if any of the above functions fail.
|
||||
const std::string &GetLastError() { return lasterror_; }
|
||||
|
||||
private:
|
||||
bool LoadSchema(const std::string &ident, Parser *parser) {
|
||||
// Find the schema, if not, exit.
|
||||
auto it = schemas_.find(ident);
|
||||
if (it == schemas_.end()) {
|
||||
// Don't attach the identifier, since it may not be human readable.
|
||||
lasterror_ = "identifier for this buffer not in the registry";
|
||||
return false;
|
||||
}
|
||||
auto &schema = it->second;
|
||||
// Load the schema from disk. If not, exit.
|
||||
std::string schematext;
|
||||
if (!LoadFile(schema.path_.c_str(), false, &schematext)) {
|
||||
lasterror_ = "could not load schema: " + schema.path_;
|
||||
return false;
|
||||
}
|
||||
// Parse schema.
|
||||
parser->opts = opts_;
|
||||
if (!parser->Parse(schematext.c_str(), vector_data(include_paths_),
|
||||
schema.path_.c_str())) {
|
||||
lasterror_ = parser->error_;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Schema {
|
||||
std::string path_;
|
||||
// TODO(wvo) optionally cache schema file or parsed schema here.
|
||||
};
|
||||
|
||||
std::string lasterror_;
|
||||
IDLOptions opts_;
|
||||
std::vector<const char *> include_paths_;
|
||||
std::map<std::string, Schema> schemas_;
|
||||
};
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_REGISTRY_H_
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_STL_EMULATION_H_
|
||||
#define FLATBUFFERS_STL_EMULATION_H_
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
|
||||
#if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
|
||||
#define FLATBUFFERS_CPP98_STL
|
||||
#endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
|
||||
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
#include <cctype>
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
|
||||
// Check if we can use template aliases
|
||||
// Not possible if Microsoft Compiler before 2012
|
||||
// Possible is the language feature __cpp_alias_templates is defined well
|
||||
// Or possible if the C++ std is C+11 or newer
|
||||
#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \
|
||||
|| (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \
|
||||
|| (defined(__cplusplus) && __cplusplus >= 201103L)
|
||||
#define FLATBUFFERS_TEMPLATES_ALIASES
|
||||
#endif
|
||||
|
||||
// This header provides backwards compatibility for C++98 STLs like stlport.
|
||||
namespace flatbuffers {
|
||||
|
||||
// Retrieve ::back() from a string in a way that is compatible with pre C++11
|
||||
// STLs (e.g stlport).
|
||||
inline char& string_back(std::string &value) {
|
||||
return value[value.length() - 1];
|
||||
}
|
||||
|
||||
inline char string_back(const std::string &value) {
|
||||
return value[value.length() - 1];
|
||||
}
|
||||
|
||||
// Helper method that retrieves ::data() from a vector in a way that is
|
||||
// compatible with pre C++11 STLs (e.g stlport).
|
||||
template <typename T> inline T *vector_data(std::vector<T> &vector) {
|
||||
// In some debug environments, operator[] does bounds checking, so &vector[0]
|
||||
// can't be used.
|
||||
return vector.empty() ? nullptr : &vector[0];
|
||||
}
|
||||
|
||||
template <typename T> inline const T *vector_data(
|
||||
const std::vector<T> &vector) {
|
||||
return vector.empty() ? nullptr : &vector[0];
|
||||
}
|
||||
|
||||
template <typename T, typename V>
|
||||
inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
vector->push_back(data);
|
||||
#else
|
||||
vector->emplace_back(std::forward<V>(data));
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
}
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
template <typename T>
|
||||
using numeric_limits = std::numeric_limits<T>;
|
||||
#else
|
||||
template <typename T> class numeric_limits :
|
||||
public std::numeric_limits<T> {};
|
||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
#else
|
||||
template <typename T> class numeric_limits :
|
||||
public std::numeric_limits<T> {
|
||||
public:
|
||||
// Android NDK fix.
|
||||
static T lowest() {
|
||||
return std::numeric_limits<T>::min();
|
||||
}
|
||||
};
|
||||
|
||||
template <> class numeric_limits<float> :
|
||||
public std::numeric_limits<float> {
|
||||
public:
|
||||
static float lowest() { return -FLT_MAX; }
|
||||
};
|
||||
|
||||
template <> class numeric_limits<double> :
|
||||
public std::numeric_limits<double> {
|
||||
public:
|
||||
static double lowest() { return -DBL_MAX; }
|
||||
};
|
||||
|
||||
template <> class numeric_limits<unsigned long long> {
|
||||
public:
|
||||
static unsigned long long min() { return 0ULL; }
|
||||
static unsigned long long max() { return ~0ULL; }
|
||||
static unsigned long long lowest() {
|
||||
return numeric_limits<unsigned long long>::min();
|
||||
}
|
||||
};
|
||||
|
||||
template <> class numeric_limits<long long> {
|
||||
public:
|
||||
static long long min() {
|
||||
return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
|
||||
}
|
||||
static long long max() {
|
||||
return static_cast<long long>(
|
||||
(1ULL << ((sizeof(long long) << 3) - 1)) - 1);
|
||||
}
|
||||
static long long lowest() {
|
||||
return numeric_limits<long long>::min();
|
||||
}
|
||||
};
|
||||
#endif // FLATBUFFERS_CPP98_STL
|
||||
|
||||
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
template <typename T> using is_scalar = std::is_scalar<T>;
|
||||
template <typename T, typename U> using is_same = std::is_same<T,U>;
|
||||
template <typename T> using is_floating_point = std::is_floating_point<T>;
|
||||
template <typename T> using is_unsigned = std::is_unsigned<T>;
|
||||
template <typename T> using make_unsigned = std::make_unsigned<T>;
|
||||
#else
|
||||
// Map C++ TR1 templates defined by stlport.
|
||||
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
|
||||
template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
|
||||
template <typename T> using is_floating_point =
|
||||
std::tr1::is_floating_point<T>;
|
||||
template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
|
||||
// Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
|
||||
template<typename T> struct make_unsigned {
|
||||
static_assert(is_unsigned<T>::value, "Specialization not implemented!");
|
||||
using type = T;
|
||||
};
|
||||
template<> struct make_unsigned<char> { using type = unsigned char; };
|
||||
template<> struct make_unsigned<short> { using type = unsigned short; };
|
||||
template<> struct make_unsigned<int> { using type = unsigned int; };
|
||||
template<> struct make_unsigned<long> { using type = unsigned long; };
|
||||
template<>
|
||||
struct make_unsigned<long long> { using type = unsigned long long; };
|
||||
#endif // !FLATBUFFERS_CPP98_STL
|
||||
#else
|
||||
// MSVC 2010 doesn't support C++11 aliases.
|
||||
template <typename T> struct is_scalar : public std::is_scalar<T> {};
|
||||
template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
|
||||
template <typename T> struct is_floating_point :
|
||||
public std::is_floating_point<T> {};
|
||||
template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
|
||||
template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
|
||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
template <class T> using unique_ptr = std::unique_ptr<T>;
|
||||
#else
|
||||
// MSVC 2010 doesn't support C++11 aliases.
|
||||
// We're manually "aliasing" the class here as we want to bring unique_ptr
|
||||
// into the flatbuffers namespace. We have unique_ptr in the flatbuffers
|
||||
// namespace we have a completely independent implemenation (see below)
|
||||
// for C++98 STL implementations.
|
||||
template <class T> class unique_ptr : public std::unique_ptr<T> {
|
||||
public:
|
||||
unique_ptr() {}
|
||||
explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
|
||||
unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
|
||||
unique_ptr(unique_ptr&& u) { *this = std::move(u); }
|
||||
unique_ptr& operator=(std::unique_ptr<T>&& u) {
|
||||
std::unique_ptr<T>::reset(u.release());
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(unique_ptr&& u) {
|
||||
std::unique_ptr<T>::reset(u.release());
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(T* p) {
|
||||
return std::unique_ptr<T>::operator=(p);
|
||||
}
|
||||
};
|
||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
#else
|
||||
// Very limited implementation of unique_ptr.
|
||||
// This is provided simply to allow the C++ code generated from the default
|
||||
// settings to function in C++98 environments with no modifications.
|
||||
template <class T> class unique_ptr {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
unique_ptr() : ptr_(nullptr) {}
|
||||
explicit unique_ptr(T* p) : ptr_(p) {}
|
||||
unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
|
||||
unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
|
||||
reset(const_cast<unique_ptr*>(&u)->release());
|
||||
}
|
||||
~unique_ptr() { reset(); }
|
||||
|
||||
unique_ptr& operator=(const unique_ptr& u) {
|
||||
reset(const_cast<unique_ptr*>(&u)->release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_ptr& operator=(unique_ptr&& u) {
|
||||
reset(u.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_ptr& operator=(T* p) {
|
||||
reset(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const T& operator*() const { return *ptr_; }
|
||||
T* operator->() const { return ptr_; }
|
||||
T* get() const noexcept { return ptr_; }
|
||||
explicit operator bool() const { return ptr_ != nullptr; }
|
||||
|
||||
// modifiers
|
||||
T* release() {
|
||||
T* value = ptr_;
|
||||
ptr_ = nullptr;
|
||||
return value;
|
||||
}
|
||||
|
||||
void reset(T* p = nullptr) {
|
||||
T* value = ptr_;
|
||||
ptr_ = p;
|
||||
if (value) delete value;
|
||||
}
|
||||
|
||||
void swap(unique_ptr& u) {
|
||||
T* temp_ptr = ptr_;
|
||||
ptr_ = u.ptr_;
|
||||
u.ptr_ = temp_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
T* ptr_;
|
||||
};
|
||||
|
||||
template <class T> bool operator==(const unique_ptr<T>& x,
|
||||
const unique_ptr<T>& y) {
|
||||
return x.get() == y.get();
|
||||
}
|
||||
|
||||
template <class T, class D> bool operator==(const unique_ptr<T>& x,
|
||||
const D* y) {
|
||||
return static_cast<D*>(x.get()) == y;
|
||||
}
|
||||
|
||||
template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
|
||||
return reinterpret_cast<intptr_t>(x.get()) == y;
|
||||
}
|
||||
#endif // !FLATBUFFERS_CPP98_STL
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_STL_EMULATION_H_
|
||||
654
src/ipa/rpi/cam_helper/imx500_tensor_parser/flatbuffers/util.h
Normal file
654
src/ipa/rpi/cam_helper/imx500_tensor_parser/flatbuffers/util.h
Normal file
@@ -0,0 +1,654 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_UTIL_H_
|
||||
#define FLATBUFFERS_UTIL_H_
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||
# include <sstream>
|
||||
#else // FLATBUFFERS_PREFER_PRINTF
|
||||
# include <float.h>
|
||||
# include <stdio.h>
|
||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// @locale-independent functions for ASCII characters set.
|
||||
|
||||
// Fast checking that character lies in closed range: [a <= x <= b]
|
||||
// using one compare (conditional branch) operator.
|
||||
inline bool check_ascii_range(char x, char a, char b) {
|
||||
FLATBUFFERS_ASSERT(a <= b);
|
||||
// (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`.
|
||||
// The x, a, b will be promoted to int and subtracted without overflow.
|
||||
return static_cast<unsigned int>(x - a) <= static_cast<unsigned int>(b - a);
|
||||
}
|
||||
|
||||
// Case-insensitive isalpha
|
||||
inline bool is_alpha(char c) {
|
||||
// ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
|
||||
return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF);
|
||||
}
|
||||
|
||||
// Check (case-insensitive) that `c` is equal to alpha.
|
||||
inline bool is_alpha_char(char c, char alpha) {
|
||||
FLATBUFFERS_ASSERT(is_alpha(alpha));
|
||||
// ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
|
||||
return ((c & 0xDF) == (alpha & 0xDF));
|
||||
}
|
||||
|
||||
// https://en.cppreference.com/w/cpp/string/byte/isxdigit
|
||||
// isdigit and isxdigit are the only standard narrow character classification
|
||||
// functions that are not affected by the currently installed C locale. although
|
||||
// some implementations (e.g. Microsoft in 1252 codepage) may classify
|
||||
// additional single-byte characters as digits.
|
||||
inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); }
|
||||
|
||||
inline bool is_xdigit(char c) {
|
||||
// Replace by look-up table.
|
||||
return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF);
|
||||
}
|
||||
|
||||
// Case-insensitive isalnum
|
||||
inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); }
|
||||
|
||||
// @end-locale-independent functions for ASCII character set
|
||||
|
||||
#ifdef FLATBUFFERS_PREFER_PRINTF
|
||||
template<typename T> size_t IntToDigitCount(T t) {
|
||||
size_t digit_count = 0;
|
||||
// Count the sign for negative numbers
|
||||
if (t < 0) digit_count++;
|
||||
// Count a single 0 left of the dot for fractional numbers
|
||||
if (-1 < t && t < 1) digit_count++;
|
||||
// Count digits until fractional part
|
||||
T eps = std::numeric_limits<float>::epsilon();
|
||||
while (t <= (-1 + eps) || (1 - eps) <= t) {
|
||||
t /= 10;
|
||||
digit_count++;
|
||||
}
|
||||
return digit_count;
|
||||
}
|
||||
|
||||
template<typename T> size_t NumToStringWidth(T t, int precision = 0) {
|
||||
size_t string_width = IntToDigitCount(t);
|
||||
// Count the dot for floating point numbers
|
||||
if (precision) string_width += (precision + 1);
|
||||
return string_width;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string NumToStringImplWrapper(T t, const char *fmt, int precision = 0) {
|
||||
size_t string_width = NumToStringWidth(t, precision);
|
||||
std::string s(string_width, 0x00);
|
||||
// Allow snprintf to use std::string trailing null to detect buffer overflow
|
||||
snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, precision, t);
|
||||
return s;
|
||||
}
|
||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||
|
||||
// Convert an integer or floating point value to a string.
|
||||
// In contrast to std::stringstream, "char" values are
|
||||
// converted to a string of digits, and we don't use scientific notation.
|
||||
template<typename T> std::string NumToString(T t) {
|
||||
// clang-format off
|
||||
|
||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||
std::stringstream ss;
|
||||
ss << t;
|
||||
return ss.str();
|
||||
#else // FLATBUFFERS_PREFER_PRINTF
|
||||
auto v = static_cast<long long>(t);
|
||||
return NumToStringImplWrapper(v, "%.*lld");
|
||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||
// clang-format on
|
||||
}
|
||||
// Avoid char types used as character data.
|
||||
template<> inline std::string NumToString<signed char>(signed char t) {
|
||||
return NumToString(static_cast<int>(t));
|
||||
}
|
||||
template<> inline std::string NumToString<unsigned char>(unsigned char t) {
|
||||
return NumToString(static_cast<int>(t));
|
||||
}
|
||||
template<> inline std::string NumToString<char>(char t) {
|
||||
return NumToString(static_cast<int>(t));
|
||||
}
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
template<> inline std::string NumToString<long long>(long long t) {
|
||||
char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2
|
||||
snprintf(buf, sizeof(buf), "%lld", t);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline std::string NumToString<unsigned long long>(unsigned long long t) {
|
||||
char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1
|
||||
snprintf(buf, sizeof(buf), "%llu", t);
|
||||
return std::string(buf);
|
||||
}
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
|
||||
// Special versions for floats/doubles.
|
||||
template<typename T> std::string FloatToString(T t, int precision) {
|
||||
// clang-format off
|
||||
|
||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||
// to_string() prints different numbers of digits for floats depending on
|
||||
// platform and isn't available on Android, so we use stringstream
|
||||
std::stringstream ss;
|
||||
// Use std::fixed to suppress scientific notation.
|
||||
ss << std::fixed;
|
||||
// Default precision is 6, we want that to be higher for doubles.
|
||||
ss << std::setprecision(precision);
|
||||
ss << t;
|
||||
auto s = ss.str();
|
||||
#else // FLATBUFFERS_PREFER_PRINTF
|
||||
auto v = static_cast<double>(t);
|
||||
auto s = NumToStringImplWrapper(v, "%0.*f", precision);
|
||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||
// clang-format on
|
||||
// Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
|
||||
auto p = s.find_last_not_of('0');
|
||||
if (p != std::string::npos) {
|
||||
// Strip trailing zeroes. If it is a whole number, keep one zero.
|
||||
s.resize(p + (s[p] == '.' ? 2 : 1));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
template<> inline std::string NumToString<double>(double t) {
|
||||
return FloatToString(t, 12);
|
||||
}
|
||||
template<> inline std::string NumToString<float>(float t) {
|
||||
return FloatToString(t, 6);
|
||||
}
|
||||
|
||||
// Convert an integer value to a hexadecimal string.
|
||||
// The returned string length is always xdigits long, prefixed by 0 digits.
|
||||
// For example, IntToStringHex(0x23, 8) returns the string "00000023".
|
||||
inline std::string IntToStringHex(int i, int xdigits) {
|
||||
FLATBUFFERS_ASSERT(i >= 0);
|
||||
// clang-format off
|
||||
|
||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||
std::stringstream ss;
|
||||
ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
|
||||
<< i;
|
||||
return ss.str();
|
||||
#else // FLATBUFFERS_PREFER_PRINTF
|
||||
return NumToStringImplWrapper(i, "%.*X", xdigits);
|
||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}.
|
||||
#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
|
||||
class ClassicLocale {
|
||||
#ifdef _MSC_VER
|
||||
typedef _locale_t locale_type;
|
||||
#else
|
||||
typedef locale_t locale_type; // POSIX.1-2008 locale_t type
|
||||
#endif
|
||||
ClassicLocale();
|
||||
~ClassicLocale();
|
||||
locale_type locale_;
|
||||
static ClassicLocale instance_;
|
||||
public:
|
||||
static locale_type Get() { return instance_.locale_; }
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get())
|
||||
#define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get())
|
||||
#define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get())
|
||||
#define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get())
|
||||
#else
|
||||
#define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get())
|
||||
#define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get())
|
||||
#define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get())
|
||||
#define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get())
|
||||
#endif
|
||||
#else
|
||||
#define __strtod_impl(s, pe) strtod(s, pe)
|
||||
#define __strtof_impl(s, pe) static_cast<float>(strtod(s, pe))
|
||||
#ifdef _MSC_VER
|
||||
#define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b)
|
||||
#define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b)
|
||||
#else
|
||||
#define __strtoull_impl(s, pe, b) strtoull(s, pe, b)
|
||||
#define __strtoll_impl(s, pe, b) strtoll(s, pe, b)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
inline void strtoval_impl(int64_t *val, const char *str, char **endptr,
|
||||
int base) {
|
||||
*val = __strtoll_impl(str, endptr, base);
|
||||
}
|
||||
|
||||
inline void strtoval_impl(uint64_t *val, const char *str, char **endptr,
|
||||
int base) {
|
||||
*val = __strtoull_impl(str, endptr, base);
|
||||
}
|
||||
|
||||
inline void strtoval_impl(double *val, const char *str, char **endptr) {
|
||||
*val = __strtod_impl(str, endptr);
|
||||
}
|
||||
|
||||
// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true.
|
||||
__supress_ubsan__("float-cast-overflow")
|
||||
inline void strtoval_impl(float *val, const char *str, char **endptr) {
|
||||
*val = __strtof_impl(str, endptr);
|
||||
}
|
||||
#undef __strtoull_impl
|
||||
#undef __strtoll_impl
|
||||
#undef __strtod_impl
|
||||
#undef __strtof_impl
|
||||
// clang-format on
|
||||
|
||||
// Adaptor for strtoull()/strtoll().
|
||||
// Flatbuffers accepts numbers with any count of leading zeros (-009 is -9),
|
||||
// while strtoll with base=0 interprets first leading zero as octal prefix.
|
||||
// In future, it is possible to add prefixed 0b0101.
|
||||
// 1) Checks errno code for overflow condition (out of range).
|
||||
// 2) If base <= 0, function try to detect base of number by prefix.
|
||||
//
|
||||
// Return value (like strtoull and strtoll, but reject partial result):
|
||||
// - If successful, an integer value corresponding to the str is returned.
|
||||
// - If full string conversion can't be performed, 0 is returned.
|
||||
// - If the converted value falls out of range of corresponding return type, a
|
||||
// range error occurs. In this case value MAX(T)/MIN(T) is returned.
|
||||
template<typename T>
|
||||
inline bool StringToIntegerImpl(T *val, const char *const str,
|
||||
const int base = 0,
|
||||
const bool check_errno = true) {
|
||||
// T is int64_t or uint64_T
|
||||
FLATBUFFERS_ASSERT(str);
|
||||
if (base <= 0) {
|
||||
auto s = str;
|
||||
while (*s && !is_digit(*s)) s++;
|
||||
if (s[0] == '0' && is_alpha_char(s[1], 'X'))
|
||||
return StringToIntegerImpl(val, str, 16, check_errno);
|
||||
// if a prefix not match, try base=10
|
||||
return StringToIntegerImpl(val, str, 10, check_errno);
|
||||
} else {
|
||||
if (check_errno) errno = 0; // clear thread-local errno
|
||||
auto endptr = str;
|
||||
strtoval_impl(val, str, const_cast<char **>(&endptr), base);
|
||||
if ((*endptr != '\0') || (endptr == str)) {
|
||||
*val = 0; // erase partial result
|
||||
return false; // invalid string
|
||||
}
|
||||
// errno is out-of-range, return MAX/MIN
|
||||
if (check_errno && errno) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool StringToFloatImpl(T *val, const char *const str) {
|
||||
// Type T must be either float or double.
|
||||
FLATBUFFERS_ASSERT(str && val);
|
||||
auto end = str;
|
||||
strtoval_impl(val, str, const_cast<char **>(&end));
|
||||
auto done = (end != str) && (*end == '\0');
|
||||
if (!done) *val = 0; // erase partial result
|
||||
return done;
|
||||
}
|
||||
|
||||
// Convert a string to an instance of T.
|
||||
// Return value (matched with StringToInteger64Impl and strtod):
|
||||
// - If successful, a numeric value corresponding to the str is returned.
|
||||
// - If full string conversion can't be performed, 0 is returned.
|
||||
// - If the converted value falls out of range of corresponding return type, a
|
||||
// range error occurs. In this case value MAX(T)/MIN(T) is returned.
|
||||
template<typename T> inline bool StringToNumber(const char *s, T *val) {
|
||||
FLATBUFFERS_ASSERT(s && val);
|
||||
int64_t i64;
|
||||
// The errno check isn't needed, will return MAX/MIN on overflow.
|
||||
if (StringToIntegerImpl(&i64, s, 0, false)) {
|
||||
const int64_t max = flatbuffers::numeric_limits<T>::max();
|
||||
const int64_t min = flatbuffers::numeric_limits<T>::lowest();
|
||||
if (i64 > max) {
|
||||
*val = static_cast<T>(max);
|
||||
return false;
|
||||
}
|
||||
if (i64 < min) {
|
||||
// For unsigned types return max to distinguish from
|
||||
// "no conversion can be performed" when 0 is returned.
|
||||
*val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
|
||||
return false;
|
||||
}
|
||||
*val = static_cast<T>(i64);
|
||||
return true;
|
||||
}
|
||||
*val = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<> inline bool StringToNumber<int64_t>(const char *str, int64_t *val) {
|
||||
return StringToIntegerImpl(val, str);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool StringToNumber<uint64_t>(const char *str, uint64_t *val) {
|
||||
if (!StringToIntegerImpl(val, str)) return false;
|
||||
// The strtoull accepts negative numbers:
|
||||
// If the minus sign was part of the input sequence, the numeric value
|
||||
// calculated from the sequence of digits is negated as if by unary minus
|
||||
// in the result type, which applies unsigned integer wraparound rules.
|
||||
// Fix this behaviour (except -0).
|
||||
if (*val) {
|
||||
auto s = str;
|
||||
while (*s && !is_digit(*s)) s++;
|
||||
s = (s > str) ? (s - 1) : s; // step back to one symbol
|
||||
if (*s == '-') {
|
||||
// For unsigned types return the max to distinguish from
|
||||
// "no conversion can be performed".
|
||||
*val = flatbuffers::numeric_limits<uint64_t>::max();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<> inline bool StringToNumber(const char *s, float *val) {
|
||||
return StringToFloatImpl(val, s);
|
||||
}
|
||||
|
||||
template<> inline bool StringToNumber(const char *s, double *val) {
|
||||
return StringToFloatImpl(val, s);
|
||||
}
|
||||
|
||||
inline int64_t StringToInt(const char *s, int base = 10) {
|
||||
int64_t val;
|
||||
return StringToIntegerImpl(&val, s, base) ? val : 0;
|
||||
}
|
||||
|
||||
inline uint64_t StringToUInt(const char *s, int base = 10) {
|
||||
uint64_t val;
|
||||
return StringToIntegerImpl(&val, s, base) ? val : 0;
|
||||
}
|
||||
|
||||
typedef bool (*LoadFileFunction)(const char *filename, bool binary,
|
||||
std::string *dest);
|
||||
typedef bool (*FileExistsFunction)(const char *filename);
|
||||
|
||||
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
|
||||
|
||||
FileExistsFunction SetFileExistsFunction(
|
||||
FileExistsFunction file_exists_function);
|
||||
|
||||
// Check if file "name" exists.
|
||||
bool FileExists(const char *name);
|
||||
|
||||
// Check if "name" exists and it is also a directory.
|
||||
bool DirExists(const char *name);
|
||||
|
||||
// Load file "name" into "buf" returning true if successful
|
||||
// false otherwise. If "binary" is false data is read
|
||||
// using ifstream's text mode, otherwise data is read with
|
||||
// no transcoding.
|
||||
bool LoadFile(const char *name, bool binary, std::string *buf);
|
||||
|
||||
// Save data "buf" of length "len" bytes into a file
|
||||
// "name" returning true if successful, false otherwise.
|
||||
// If "binary" is false data is written using ifstream's
|
||||
// text mode, otherwise data is written with no
|
||||
// transcoding.
|
||||
bool SaveFile(const char *name, const char *buf, size_t len, bool binary);
|
||||
|
||||
// Save data "buf" into file "name" returning true if
|
||||
// successful, false otherwise. If "binary" is false
|
||||
// data is written using ifstream's text mode, otherwise
|
||||
// data is written with no transcoding.
|
||||
inline bool SaveFile(const char *name, const std::string &buf, bool binary) {
|
||||
return SaveFile(name, buf.c_str(), buf.size(), binary);
|
||||
}
|
||||
|
||||
// Functionality for minimalistic portable path handling.
|
||||
|
||||
// The functions below behave correctly regardless of whether posix ('/') or
|
||||
// Windows ('/' or '\\') separators are used.
|
||||
|
||||
// Any new separators inserted are always posix.
|
||||
FLATBUFFERS_CONSTEXPR char kPathSeparator = '/';
|
||||
|
||||
// Returns the path with the extension, if any, removed.
|
||||
std::string StripExtension(const std::string &filepath);
|
||||
|
||||
// Returns the extension, if any.
|
||||
std::string GetExtension(const std::string &filepath);
|
||||
|
||||
// Return the last component of the path, after the last separator.
|
||||
std::string StripPath(const std::string &filepath);
|
||||
|
||||
// Strip the last component of the path + separator.
|
||||
std::string StripFileName(const std::string &filepath);
|
||||
|
||||
// Concatenates a path with a filename, regardless of wether the path
|
||||
// ends in a separator or not.
|
||||
std::string ConCatPathFileName(const std::string &path,
|
||||
const std::string &filename);
|
||||
|
||||
// Replaces any '\\' separators with '/'
|
||||
std::string PosixPath(const char *path);
|
||||
|
||||
// This function ensure a directory exists, by recursively
|
||||
// creating dirs for any parts of the path that don't exist yet.
|
||||
void EnsureDirExists(const std::string &filepath);
|
||||
|
||||
// Obtains the absolute path from any other path.
|
||||
// Returns the input path if the absolute path couldn't be resolved.
|
||||
std::string AbsolutePath(const std::string &filepath);
|
||||
|
||||
// To and from UTF-8 unicode conversion functions
|
||||
|
||||
// Convert a unicode code point into a UTF-8 representation by appending it
|
||||
// to a string. Returns the number of bytes generated.
|
||||
inline int ToUTF8(uint32_t ucc, std::string *out) {
|
||||
FLATBUFFERS_ASSERT(!(ucc & 0x80000000)); // Top bit can't be set.
|
||||
// 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8
|
||||
for (int i = 0; i < 6; i++) {
|
||||
// Max bits this encoding can represent.
|
||||
uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i);
|
||||
if (ucc < (1u << max_bits)) { // does it fit?
|
||||
// Remaining bits not encoded in the first byte, store 6 bits each
|
||||
uint32_t remain_bits = i * 6;
|
||||
// Store first byte:
|
||||
(*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
|
||||
(ucc >> remain_bits));
|
||||
// Store remaining bytes:
|
||||
for (int j = i - 1; j >= 0; j--) {
|
||||
(*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
|
||||
}
|
||||
return i + 1; // Return the number of bytes added.
|
||||
}
|
||||
}
|
||||
FLATBUFFERS_ASSERT(0); // Impossible to arrive here.
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Converts whatever prefix of the incoming string corresponds to a valid
|
||||
// UTF-8 sequence into a unicode code. The incoming pointer will have been
|
||||
// advanced past all bytes parsed.
|
||||
// returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in
|
||||
// this case).
|
||||
inline int FromUTF8(const char **in) {
|
||||
int len = 0;
|
||||
// Count leading 1 bits.
|
||||
for (int mask = 0x80; mask >= 0x04; mask >>= 1) {
|
||||
if (**in & mask) {
|
||||
len++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((static_cast<unsigned char>(**in) << len) & 0x80)
|
||||
return -1; // Bit after leading 1's must be 0.
|
||||
if (!len) return *(*in)++;
|
||||
// UTF-8 encoded values with a length are between 2 and 4 bytes.
|
||||
if (len < 2 || len > 4) { return -1; }
|
||||
// Grab initial bits of the code.
|
||||
int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
|
||||
for (int i = 0; i < len - 1; i++) {
|
||||
if ((**in & 0xC0) != 0x80) return -1; // Upper bits must 1 0.
|
||||
ucc <<= 6;
|
||||
ucc |= *(*in)++ & 0x3F; // Grab 6 more bits of the code.
|
||||
}
|
||||
// UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
|
||||
// UTF-16 surrogate pairs).
|
||||
if (ucc >= 0xD800 && ucc <= 0xDFFF) { return -1; }
|
||||
// UTF-8 must represent code points in their shortest possible encoding.
|
||||
switch (len) {
|
||||
case 2:
|
||||
// Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
|
||||
if (ucc < 0x0080 || ucc > 0x07FF) { return -1; }
|
||||
break;
|
||||
case 3:
|
||||
// Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
|
||||
if (ucc < 0x0800 || ucc > 0xFFFF) { return -1; }
|
||||
break;
|
||||
case 4:
|
||||
// Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
|
||||
if (ucc < 0x10000 || ucc > 0x10FFFF) { return -1; }
|
||||
break;
|
||||
}
|
||||
return ucc;
|
||||
}
|
||||
|
||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||
// Wraps a string to a maximum length, inserting new lines where necessary. Any
|
||||
// existing whitespace will be collapsed down to a single space. A prefix or
|
||||
// suffix can be provided, which will be inserted before or after a wrapped
|
||||
// line, respectively.
|
||||
inline std::string WordWrap(const std::string in, size_t max_length,
|
||||
const std::string wrapped_line_prefix,
|
||||
const std::string wrapped_line_suffix) {
|
||||
std::istringstream in_stream(in);
|
||||
std::string wrapped, line, word;
|
||||
|
||||
in_stream >> word;
|
||||
line = word;
|
||||
|
||||
while (in_stream >> word) {
|
||||
if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) <
|
||||
max_length) {
|
||||
line += " " + word;
|
||||
} else {
|
||||
wrapped += line + wrapped_line_suffix + "\n";
|
||||
line = wrapped_line_prefix + word;
|
||||
}
|
||||
}
|
||||
wrapped += line;
|
||||
|
||||
return wrapped;
|
||||
}
|
||||
#endif // !FLATBUFFERS_PREFER_PRINTF
|
||||
|
||||
inline bool EscapeString(const char *s, size_t length, std::string *_text,
|
||||
bool allow_non_utf8, bool natural_utf8) {
|
||||
std::string &text = *_text;
|
||||
text += "\"";
|
||||
for (uoffset_t i = 0; i < length; i++) {
|
||||
char c = s[i];
|
||||
switch (c) {
|
||||
case '\n': text += "\\n"; break;
|
||||
case '\t': text += "\\t"; break;
|
||||
case '\r': text += "\\r"; break;
|
||||
case '\b': text += "\\b"; break;
|
||||
case '\f': text += "\\f"; break;
|
||||
case '\"': text += "\\\""; break;
|
||||
case '\\': text += "\\\\"; break;
|
||||
default:
|
||||
if (c >= ' ' && c <= '~') {
|
||||
text += c;
|
||||
} else {
|
||||
// Not printable ASCII data. Let's see if it's valid UTF-8 first:
|
||||
const char *utf8 = s + i;
|
||||
int ucc = FromUTF8(&utf8);
|
||||
if (ucc < 0) {
|
||||
if (allow_non_utf8) {
|
||||
text += "\\x";
|
||||
text += IntToStringHex(static_cast<uint8_t>(c), 2);
|
||||
} else {
|
||||
// There are two cases here:
|
||||
//
|
||||
// 1) We reached here by parsing an IDL file. In that case,
|
||||
// we previously checked for non-UTF-8, so we shouldn't reach
|
||||
// here.
|
||||
//
|
||||
// 2) We reached here by someone calling GenerateText()
|
||||
// on a previously-serialized flatbuffer. The data might have
|
||||
// non-UTF-8 Strings, or might be corrupt.
|
||||
//
|
||||
// In both cases, we have to give up and inform the caller
|
||||
// they have no JSON.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (natural_utf8) {
|
||||
// utf8 points to past all utf-8 bytes parsed
|
||||
text.append(s + i, static_cast<size_t>(utf8 - s - i));
|
||||
} else if (ucc <= 0xFFFF) {
|
||||
// Parses as Unicode within JSON's \uXXXX range, so use that.
|
||||
text += "\\u";
|
||||
text += IntToStringHex(ucc, 4);
|
||||
} else if (ucc <= 0x10FFFF) {
|
||||
// Encode Unicode SMP values to a surrogate pair using two \u
|
||||
// escapes.
|
||||
uint32_t base = ucc - 0x10000;
|
||||
auto high_surrogate = (base >> 10) + 0xD800;
|
||||
auto low_surrogate = (base & 0x03FF) + 0xDC00;
|
||||
text += "\\u";
|
||||
text += IntToStringHex(high_surrogate, 4);
|
||||
text += "\\u";
|
||||
text += IntToStringHex(low_surrogate, 4);
|
||||
}
|
||||
// Skip past characters recognized.
|
||||
i = static_cast<uoffset_t>(utf8 - s - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
text += "\"";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove paired quotes in a string: "text"|'text' -> text.
|
||||
std::string RemoveStringQuotes(const std::string &s);
|
||||
|
||||
// Change th global C-locale to locale with name <locale_name>.
|
||||
// Returns an actual locale name in <_value>, useful if locale_name is "" or
|
||||
// null.
|
||||
bool SetGlobalTestLocale(const char *locale_name,
|
||||
std::string *_value = nullptr);
|
||||
|
||||
// Read (or test) a value of environment variable.
|
||||
bool ReadEnvironmentVariable(const char *var_name,
|
||||
std::string *_value = nullptr);
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_UTIL_H_
|
||||
@@ -0,0 +1,753 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024, Raspberry Pi Ltd
|
||||
*
|
||||
* imx500_tensor_parser.cpp - Parser for imx500 tensors
|
||||
*/
|
||||
|
||||
#include "imx500_tensor_parser.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <future>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <libcamera/base/log.h>
|
||||
#include <libcamera/base/span.h>
|
||||
|
||||
#include "apParams.flatbuffers_generated.h"
|
||||
|
||||
using namespace libcamera;
|
||||
using namespace RPiController;
|
||||
|
||||
LOG_DEFINE_CATEGORY(IMX500)
|
||||
|
||||
namespace {
|
||||
|
||||
/* Setup in the IMX500 driver */
|
||||
constexpr unsigned int TensorStride = 2560;
|
||||
|
||||
constexpr unsigned int DnnHeaderSize = 12;
|
||||
constexpr unsigned int MipiPhSize = 0;
|
||||
constexpr unsigned int InputSensorMaxWidth = 1280;
|
||||
constexpr unsigned int InputSensorMaxHeight = 960;
|
||||
|
||||
enum TensorDataType {
|
||||
Signed = 0,
|
||||
Unsigned
|
||||
};
|
||||
|
||||
struct DnnHeader {
|
||||
uint8_t frameValid;
|
||||
uint8_t frameCount;
|
||||
uint16_t maxLineLen;
|
||||
uint16_t apParamSize;
|
||||
uint16_t networkId;
|
||||
uint8_t tensorType;
|
||||
};
|
||||
|
||||
struct OutputTensorApParams {
|
||||
uint8_t id;
|
||||
std::string name;
|
||||
std::string networkName;
|
||||
uint16_t numDimensions;
|
||||
uint8_t bitsPerElement;
|
||||
std::vector<Dimensions> vecDim;
|
||||
uint16_t shift;
|
||||
float scale;
|
||||
uint8_t format;
|
||||
};
|
||||
|
||||
struct InputTensorApParams {
|
||||
uint8_t networkId;
|
||||
std::string networkName;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint16_t channel;
|
||||
uint16_t widthStride;
|
||||
uint16_t heightStride;
|
||||
uint8_t format;
|
||||
};
|
||||
|
||||
int parseHeader(DnnHeader &dnnHeader, std::vector<uint8_t> &apParams, const uint8_t *src)
|
||||
{
|
||||
dnnHeader = *reinterpret_cast<const DnnHeader *>(src);
|
||||
|
||||
LOG(IMX500, Debug)
|
||||
<< "Header: valid " << static_cast<bool>(dnnHeader.frameValid)
|
||||
<< " count " << static_cast<int>(dnnHeader.frameCount)
|
||||
<< " max len " << dnnHeader.maxLineLen
|
||||
<< " ap param size " << dnnHeader.apParamSize
|
||||
<< " network id " << dnnHeader.networkId
|
||||
<< " tensor type " << static_cast<int>(dnnHeader.tensorType);
|
||||
|
||||
if (!dnnHeader.frameValid)
|
||||
return -1;
|
||||
|
||||
apParams.resize(dnnHeader.apParamSize, 0);
|
||||
|
||||
uint32_t i = DnnHeaderSize;
|
||||
for (unsigned int j = 0; j < dnnHeader.apParamSize; j++) {
|
||||
if (i >= TensorStride) {
|
||||
i = 0;
|
||||
src += TensorStride + MipiPhSize;
|
||||
}
|
||||
apParams[j] = src[i++];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parseOutputApParams(std::vector<OutputTensorApParams> &outputApParams, const std::vector<uint8_t> &apParams,
|
||||
const DnnHeader &dnnHeader)
|
||||
{
|
||||
const apParams::fb::FBApParams *fbApParams;
|
||||
const apParams::fb::FBNetwork *fbNetwork;
|
||||
const apParams::fb::FBOutputTensor *fbOutputTensor;
|
||||
|
||||
fbApParams = apParams::fb::GetFBApParams(apParams.data());
|
||||
LOG(IMX500, Debug) << "Networks size: " << fbApParams->networks()->size();
|
||||
|
||||
outputApParams.clear();
|
||||
|
||||
for (unsigned int i = 0; i < fbApParams->networks()->size(); i++) {
|
||||
fbNetwork = (apParams::fb::FBNetwork *)(fbApParams->networks()->Get(i));
|
||||
if (fbNetwork->id() != dnnHeader.networkId)
|
||||
continue;
|
||||
|
||||
LOG(IMX500, Debug)
|
||||
<< "Network: " << fbNetwork->type()->c_str()
|
||||
<< ", i/p size: " << fbNetwork->inputTensors()->size()
|
||||
<< ", o/p size: " << fbNetwork->outputTensors()->size();
|
||||
|
||||
for (unsigned int j = 0; j < fbNetwork->outputTensors()->size(); j++) {
|
||||
OutputTensorApParams outApParam;
|
||||
|
||||
fbOutputTensor = (apParams::fb::FBOutputTensor *)fbNetwork->outputTensors()->Get(j);
|
||||
|
||||
outApParam.id = fbOutputTensor->id();
|
||||
outApParam.name = fbOutputTensor->name()->str();
|
||||
outApParam.networkName = fbNetwork->type()->str();
|
||||
outApParam.numDimensions = fbOutputTensor->numOfDimensions();
|
||||
|
||||
for (unsigned int k = 0; k < fbOutputTensor->numOfDimensions(); k++) {
|
||||
Dimensions dim;
|
||||
dim.ordinal = fbOutputTensor->dimensions()->Get(k)->id();
|
||||
dim.size = fbOutputTensor->dimensions()->Get(k)->size();
|
||||
dim.serializationIndex = fbOutputTensor->dimensions()->Get(k)->serializationIndex();
|
||||
dim.padding = fbOutputTensor->dimensions()->Get(k)->padding();
|
||||
if (dim.padding != 0) {
|
||||
LOG(IMX500, Error)
|
||||
<< "Error in AP Params, Non-Zero padding for Dimension " << k;
|
||||
return -1;
|
||||
}
|
||||
|
||||
outApParam.vecDim.push_back(dim);
|
||||
}
|
||||
|
||||
outApParam.bitsPerElement = fbOutputTensor->bitsPerElement();
|
||||
outApParam.shift = fbOutputTensor->shift();
|
||||
outApParam.scale = fbOutputTensor->scale();
|
||||
outApParam.format = fbOutputTensor->format();
|
||||
|
||||
/* Add the element to vector */
|
||||
outputApParams.push_back(outApParam);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int populateOutputTensorInfo(IMX500OutputTensorInfo &outputTensorInfo,
|
||||
const std::vector<OutputTensorApParams> &outputApParams)
|
||||
{
|
||||
/* Calculate total output size. */
|
||||
unsigned int totalOutSize = 0;
|
||||
for (auto const &ap : outputApParams) {
|
||||
unsigned int totalDimensionSize = 1;
|
||||
for (auto &dim : ap.vecDim) {
|
||||
if (totalDimensionSize >= std::numeric_limits<uint32_t>::max() / dim.size) {
|
||||
LOG(IMX500, Error) << "Invalid totalDimensionSize";
|
||||
return -1;
|
||||
}
|
||||
|
||||
totalDimensionSize *= dim.size;
|
||||
}
|
||||
|
||||
if (totalOutSize >= std::numeric_limits<uint32_t>::max() - totalDimensionSize) {
|
||||
LOG(IMX500, Error) << "Invalid totalOutSize";
|
||||
return -1;
|
||||
}
|
||||
|
||||
totalOutSize += totalDimensionSize;
|
||||
}
|
||||
|
||||
if (totalOutSize == 0) {
|
||||
LOG(IMX500, Error) << "Invalid output tensor info (totalOutSize is 0)";
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG(IMX500, Debug) << "Final output size: " << totalOutSize;
|
||||
|
||||
if (totalOutSize >= std::numeric_limits<uint32_t>::max() / sizeof(float)) {
|
||||
LOG(IMX500, Error) << "Invalid output tensor info";
|
||||
return -1;
|
||||
}
|
||||
|
||||
outputTensorInfo.data = std::shared_ptr<float[]>(new float[totalOutSize]);
|
||||
unsigned int numOutputTensors = outputApParams.size();
|
||||
|
||||
if (!numOutputTensors) {
|
||||
LOG(IMX500, Error) << "Invalid numOutputTensors (0)";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (numOutputTensors >= std::numeric_limits<uint32_t>::max() / sizeof(uint32_t)) {
|
||||
LOG(IMX500, Error) << "Invalid numOutputTensors";
|
||||
return -1;
|
||||
}
|
||||
|
||||
outputTensorInfo.totalSize = totalOutSize;
|
||||
outputTensorInfo.numTensors = numOutputTensors;
|
||||
outputTensorInfo.networkName = outputApParams[0].networkName;
|
||||
outputTensorInfo.tensorDataNum.resize(numOutputTensors, 0);
|
||||
for (auto const &p : outputApParams) {
|
||||
outputTensorInfo.vecDim.push_back(p.vecDim);
|
||||
outputTensorInfo.numDimensions.push_back(p.vecDim.size());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
float getVal8(const uint8_t *src, const OutputTensorApParams ¶m)
|
||||
{
|
||||
T temp = (T)*src;
|
||||
float value = (temp - param.shift) * param.scale;
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
float getVal16(const uint8_t *src, const OutputTensorApParams ¶m)
|
||||
{
|
||||
T temp = (((T) * (src + 1)) & 0xff) << 8 | (*src & 0xff);
|
||||
float value = (temp - param.shift) * param.scale;
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
float getVal32(const uint8_t *src, const OutputTensorApParams ¶m)
|
||||
{
|
||||
T temp = (((T) * (src + 3)) & 0xff) << 24 | (((T) * (src + 2)) & 0xff) << 16 |
|
||||
(((T) * (src + 1)) & 0xff) << 8 | (*src & 0xff);
|
||||
float value = (temp - param.shift) * param.scale;
|
||||
return value;
|
||||
}
|
||||
|
||||
int parseOutputTensorBody(IMX500OutputTensorInfo &outputTensorInfo, const uint8_t *src,
|
||||
const std::vector<OutputTensorApParams> &outputApParams,
|
||||
const DnnHeader &dnnHeader)
|
||||
{
|
||||
float *dst = outputTensorInfo.data.get();
|
||||
int ret = 0;
|
||||
|
||||
if (outputTensorInfo.totalSize > (std::numeric_limits<uint32_t>::max() / sizeof(float))) {
|
||||
LOG(IMX500, Error) << "totalSize is greater than maximum size";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::unique_ptr<float[]> tmpDst = std::make_unique<float[]>(outputTensorInfo.totalSize);
|
||||
std::vector<uint16_t> numLinesVec(outputApParams.size());
|
||||
std::vector<uint32_t> outSizes(outputApParams.size());
|
||||
std::vector<uint32_t> offsets(outputApParams.size());
|
||||
std::vector<const uint8_t *> srcArr(outputApParams.size());
|
||||
std::vector<std::vector<Dimensions>> serializedDims;
|
||||
std::vector<std::vector<Dimensions>> actualDims;
|
||||
|
||||
const uint8_t *src1 = src;
|
||||
uint32_t offset = 0;
|
||||
std::vector<Dimensions> serializedDimT;
|
||||
std::vector<Dimensions> actualDimT;
|
||||
|
||||
for (unsigned int tensorIdx = 0; tensorIdx < outputApParams.size(); tensorIdx++) {
|
||||
offsets[tensorIdx] = offset;
|
||||
srcArr[tensorIdx] = src1;
|
||||
uint32_t tensorDataNum = 0;
|
||||
|
||||
const OutputTensorApParams ¶m = outputApParams.at(tensorIdx);
|
||||
uint32_t outputTensorSize = 0;
|
||||
uint32_t tensorOutSize = (param.bitsPerElement / 8);
|
||||
|
||||
serializedDimT.resize(param.numDimensions);
|
||||
actualDimT.resize(param.numDimensions);
|
||||
|
||||
for (int idx = 0; idx < param.numDimensions; idx++) {
|
||||
actualDimT[idx].size = param.vecDim.at(idx).size;
|
||||
serializedDimT[param.vecDim.at(idx).serializationIndex].size = param.vecDim.at(idx).size;
|
||||
|
||||
tensorOutSize *= param.vecDim.at(idx).size;
|
||||
if (tensorOutSize >= std::numeric_limits<uint32_t>::max() / param.bitsPerElement / 8) {
|
||||
LOG(IMX500, Error) << "Invalid output tensor info";
|
||||
return -1;
|
||||
}
|
||||
|
||||
actualDimT[idx].serializationIndex = param.vecDim.at(idx).serializationIndex;
|
||||
serializedDimT[param.vecDim.at(idx).serializationIndex].serializationIndex =
|
||||
static_cast<uint8_t>(idx);
|
||||
}
|
||||
|
||||
uint16_t numLines = std::ceil(tensorOutSize / static_cast<float>(dnnHeader.maxLineLen));
|
||||
outputTensorSize = tensorOutSize;
|
||||
numLinesVec[tensorIdx] = numLines;
|
||||
outSizes[tensorIdx] = tensorOutSize;
|
||||
|
||||
serializedDims.push_back(serializedDimT);
|
||||
actualDims.push_back(actualDimT);
|
||||
|
||||
src1 += numLines * TensorStride;
|
||||
tensorDataNum = (outputTensorSize / (param.bitsPerElement / 8));
|
||||
offset += tensorDataNum;
|
||||
outputTensorInfo.tensorDataNum[tensorIdx] = tensorDataNum;
|
||||
if (offset > outputTensorInfo.totalSize) {
|
||||
LOG(IMX500, Error)
|
||||
<< "Error in parsing output tensor offset " << offset << " > output_size";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint32_t> idxs(outputApParams.size());
|
||||
for (unsigned int i = 0; i < idxs.size(); i++)
|
||||
idxs[i] = i;
|
||||
|
||||
for (unsigned int i = 0; i < idxs.size(); i++) {
|
||||
for (unsigned int j = 0; j < idxs.size(); j++) {
|
||||
if (numLinesVec[idxs[i]] > numLinesVec[idxs[j]])
|
||||
std::swap(idxs[i], idxs[j]);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::future<int>> futures;
|
||||
for (unsigned int ii = 0; ii < idxs.size(); ii++) {
|
||||
uint32_t idx = idxs[ii];
|
||||
futures.emplace_back(std::async(
|
||||
std::launch::async,
|
||||
[&tmpDst, &outSizes, &numLinesVec, &actualDims, &serializedDims,
|
||||
&outputApParams, &dnnHeader, dst](int tensorIdx, const uint8_t *tsrc, int toffset) -> int {
|
||||
uint32_t outputTensorSize = outSizes[tensorIdx];
|
||||
uint16_t numLines = numLinesVec[tensorIdx];
|
||||
bool sortingRequired = false;
|
||||
|
||||
const OutputTensorApParams ¶m = outputApParams[tensorIdx];
|
||||
const std::vector<Dimensions> &serializedDim = serializedDims[tensorIdx];
|
||||
const std::vector<Dimensions> &actualDim = actualDims[tensorIdx];
|
||||
|
||||
for (unsigned i = 0; i < param.numDimensions; i++) {
|
||||
if (param.vecDim.at(i).serializationIndex != param.vecDim.at(i).ordinal)
|
||||
sortingRequired = true;
|
||||
}
|
||||
|
||||
if (!outputTensorSize) {
|
||||
LOG(IMX500, Error) << "Invalid output tensorsize (0)";
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Extract output tensor data */
|
||||
uint32_t elementIndex = 0;
|
||||
if (param.bitsPerElement == 8) {
|
||||
for (unsigned int i = 0; i < numLines; i++) {
|
||||
int lineIndex = 0;
|
||||
while (lineIndex < dnnHeader.maxLineLen) {
|
||||
if (param.format == TensorDataType::Signed)
|
||||
tmpDst[toffset + elementIndex] =
|
||||
getVal8<int8_t>(tsrc + lineIndex, param);
|
||||
else
|
||||
tmpDst[toffset + elementIndex] =
|
||||
getVal8<uint8_t>(tsrc + lineIndex, param);
|
||||
elementIndex++;
|
||||
lineIndex++;
|
||||
if (elementIndex == outputTensorSize)
|
||||
break;
|
||||
}
|
||||
tsrc += TensorStride;
|
||||
if (elementIndex == outputTensorSize)
|
||||
break;
|
||||
}
|
||||
} else if (param.bitsPerElement == 16) {
|
||||
for (unsigned int i = 0; i < numLines; i++) {
|
||||
int lineIndex = 0;
|
||||
while (lineIndex < dnnHeader.maxLineLen) {
|
||||
if (param.format == TensorDataType::Signed)
|
||||
tmpDst[toffset + elementIndex] =
|
||||
getVal16<int16_t>(tsrc + lineIndex, param);
|
||||
else
|
||||
tmpDst[toffset + elementIndex] =
|
||||
getVal16<uint16_t>(tsrc + lineIndex, param);
|
||||
elementIndex++;
|
||||
lineIndex += 2;
|
||||
if (elementIndex >= (outputTensorSize >> 1))
|
||||
break;
|
||||
}
|
||||
tsrc += TensorStride;
|
||||
if (elementIndex >= (outputTensorSize >> 1))
|
||||
break;
|
||||
}
|
||||
} else if (param.bitsPerElement == 32) {
|
||||
for (unsigned int i = 0; i < numLines; i++) {
|
||||
int lineIndex = 0;
|
||||
while (lineIndex < dnnHeader.maxLineLen) {
|
||||
if (param.format == TensorDataType::Signed)
|
||||
tmpDst[toffset + elementIndex] =
|
||||
getVal32<int32_t>(tsrc + lineIndex, param);
|
||||
else
|
||||
tmpDst[toffset + elementIndex] =
|
||||
getVal32<uint32_t>(tsrc + lineIndex, param);
|
||||
elementIndex++;
|
||||
lineIndex += 4;
|
||||
if (elementIndex >= (outputTensorSize >> 2))
|
||||
break;
|
||||
}
|
||||
tsrc += TensorStride;
|
||||
if (elementIndex >= (outputTensorSize >> 2))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sorting in order according to AP Params. Not supported if larger than 3D
|
||||
* Preparation:
|
||||
*/
|
||||
if (sortingRequired) {
|
||||
constexpr unsigned int DimensionMax = 3;
|
||||
|
||||
std::array<uint32_t, DimensionMax> loopCnt{ 1, 1, 1 };
|
||||
std::array<uint32_t, DimensionMax> coef{ 1, 1, 1 };
|
||||
for (unsigned int i = 0; i < param.numDimensions; i++) {
|
||||
if (i >= DimensionMax) {
|
||||
LOG(IMX500, Error) << "numDimensions value is 3 or higher";
|
||||
break;
|
||||
}
|
||||
|
||||
loopCnt[i] = serializedDim.at(i).size;
|
||||
|
||||
for (unsigned int j = serializedDim.at(i).serializationIndex; j > 0; j--)
|
||||
coef[i] *= actualDim.at(j - 1).size;
|
||||
}
|
||||
/* Sort execution */
|
||||
unsigned int srcIndex = 0;
|
||||
unsigned int dstIndex;
|
||||
for (unsigned int i = 0; i < loopCnt[DimensionMax - 1]; i++) {
|
||||
for (unsigned int j = 0; j < loopCnt[DimensionMax - 2]; j++) {
|
||||
for (unsigned int k = 0; k < loopCnt[DimensionMax - 3]; k++) {
|
||||
dstIndex = (coef[DimensionMax - 1] * i) +
|
||||
(coef[DimensionMax - 2] * j) +
|
||||
(coef[DimensionMax - 3] * k);
|
||||
dst[toffset + dstIndex] = tmpDst[toffset + srcIndex++];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (param.bitsPerElement == 8)
|
||||
memcpy(dst + toffset, tmpDst.get() + toffset,
|
||||
outputTensorSize * sizeof(float));
|
||||
else if (param.bitsPerElement == 16)
|
||||
memcpy(dst + toffset, tmpDst.get() + toffset,
|
||||
(outputTensorSize >> 1) * sizeof(float));
|
||||
else if (param.bitsPerElement == 32)
|
||||
memcpy(dst + toffset, tmpDst.get() + toffset,
|
||||
(outputTensorSize >> 2) * sizeof(float));
|
||||
else {
|
||||
LOG(IMX500, Error)
|
||||
<< "Invalid bitsPerElement value =" << param.bitsPerElement;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
idx, srcArr[idx], offsets[idx]));
|
||||
}
|
||||
|
||||
for (auto &f : futures)
|
||||
ret += f.get();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int parseInputApParams(InputTensorApParams &inputApParams, const std::vector<uint8_t> &apParams,
|
||||
const DnnHeader &dnnHeader)
|
||||
{
|
||||
const apParams::fb::FBApParams *fbApParams;
|
||||
const apParams::fb::FBNetwork *fbNetwork;
|
||||
const apParams::fb::FBInputTensor *fbInputTensor;
|
||||
|
||||
fbApParams = apParams::fb::GetFBApParams(apParams.data());
|
||||
LOG(IMX500, Debug) << "Networks size: " << fbApParams->networks()->size();
|
||||
|
||||
for (unsigned int i = 0; i < fbApParams->networks()->size(); i++) {
|
||||
fbNetwork = reinterpret_cast<const apParams::fb::FBNetwork *>(fbApParams->networks()->Get(i));
|
||||
if (fbNetwork->id() != dnnHeader.networkId)
|
||||
continue;
|
||||
|
||||
LOG(IMX500, Debug)
|
||||
<< "Network: " << fbNetwork->type()->c_str()
|
||||
<< ", i/p size: " << fbNetwork->inputTensors()->size()
|
||||
<< ", o/p size: " << fbNetwork->outputTensors()->size();
|
||||
|
||||
inputApParams.networkName = fbNetwork->type()->str();
|
||||
fbInputTensor =
|
||||
reinterpret_cast<const apParams::fb::FBInputTensor *>(fbNetwork->inputTensors()->Get(0));
|
||||
|
||||
LOG(IMX500, Debug)
|
||||
<< "Input Tensor shift: " << fbInputTensor->shift()
|
||||
<< ", Scale: scale: " << fbInputTensor->scale()
|
||||
<< ", Format: " << static_cast<int>(fbInputTensor->format());
|
||||
|
||||
if (fbInputTensor->dimensions()->size() != 3) {
|
||||
LOG(IMX500, Error) << "Invalid number of dimensions in InputTensor";
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < fbInputTensor->dimensions()->size(); j++) {
|
||||
switch (fbInputTensor->dimensions()->Get(j)->serializationIndex()) {
|
||||
case 0:
|
||||
inputApParams.width = fbInputTensor->dimensions()->Get(j)->size();
|
||||
inputApParams.widthStride =
|
||||
inputApParams.width + fbInputTensor->dimensions()->Get(j)->padding();
|
||||
break;
|
||||
case 1:
|
||||
inputApParams.height = fbInputTensor->dimensions()->Get(j)->size();
|
||||
inputApParams.heightStride =
|
||||
inputApParams.height + fbInputTensor->dimensions()->Get(j)->padding();
|
||||
break;
|
||||
case 2:
|
||||
inputApParams.channel = fbInputTensor->dimensions()->Get(j)->size();
|
||||
break;
|
||||
default:
|
||||
LOG(IMX500, Error) << "Invalid dimension in InputTensor " << j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parseInputTensorBody(IMX500InputTensorInfo &inputTensorInfo, const uint8_t *src,
|
||||
const InputTensorApParams &inputApParams, const DnnHeader &dnnHeader)
|
||||
{
|
||||
if ((inputApParams.width > InputSensorMaxWidth) || (inputApParams.height > InputSensorMaxHeight) ||
|
||||
((inputApParams.channel != 1) && (inputApParams.channel != 3) && (inputApParams.channel != 4))) {
|
||||
LOG(IMX500, Error)
|
||||
<< "Invalid input tensor size w: " << inputApParams.width
|
||||
<< " h: " << inputApParams.height
|
||||
<< " c: " << inputApParams.channel;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int outSize = inputApParams.width * inputApParams.height * inputApParams.channel;
|
||||
unsigned int outSizePadded = inputApParams.widthStride * inputApParams.heightStride * inputApParams.channel;
|
||||
unsigned int numLines = std::ceil(outSizePadded / static_cast<float>(dnnHeader.maxLineLen));
|
||||
inputTensorInfo.data = std::shared_ptr<uint8_t[]>(new uint8_t[outSize]);
|
||||
|
||||
unsigned int diff = 0, outLineIndex = 0, pixelIndex = 0, heightIndex = 0, size = 0, left = 0;
|
||||
unsigned int wPad = inputApParams.widthStride - inputApParams.width;
|
||||
unsigned int hPad = inputApParams.heightStride - inputApParams.height;
|
||||
|
||||
for (unsigned int line = 0; line < numLines; line++) {
|
||||
for (unsigned int lineIndex = diff; lineIndex < dnnHeader.maxLineLen; lineIndex += size) {
|
||||
if (outLineIndex == inputApParams.width) { /* Skip width padding pixels */
|
||||
outLineIndex = 0;
|
||||
heightIndex++;
|
||||
lineIndex += wPad;
|
||||
if (lineIndex >= dnnHeader.maxLineLen) {
|
||||
diff = lineIndex - dnnHeader.maxLineLen;
|
||||
break;
|
||||
} else
|
||||
diff = 0;
|
||||
}
|
||||
|
||||
if (heightIndex == inputApParams.height) { /* Skip height padding pixels */
|
||||
lineIndex += hPad * inputApParams.widthStride;
|
||||
heightIndex = 0;
|
||||
if (lineIndex >= dnnHeader.maxLineLen) {
|
||||
diff = lineIndex - dnnHeader.maxLineLen;
|
||||
while (diff >= dnnHeader.maxLineLen) {
|
||||
diff -= dnnHeader.maxLineLen;
|
||||
src += TensorStride;
|
||||
line++;
|
||||
}
|
||||
break;
|
||||
} else
|
||||
diff = 0;
|
||||
}
|
||||
|
||||
if (((pixelIndex == inputApParams.width * inputApParams.height) ||
|
||||
(pixelIndex == inputApParams.width * inputApParams.height * 2) ||
|
||||
(pixelIndex == inputApParams.width * inputApParams.height * 3))) {
|
||||
if (pixelIndex == outSize)
|
||||
break;
|
||||
}
|
||||
|
||||
if (left > 0) {
|
||||
size = left;
|
||||
left = 0;
|
||||
} else if (pixelIndex + inputApParams.width >= outSize) {
|
||||
size = outSize - pixelIndex;
|
||||
} else if (lineIndex + inputApParams.width >= dnnHeader.maxLineLen) {
|
||||
size = dnnHeader.maxLineLen - lineIndex;
|
||||
left = inputApParams.width - size;
|
||||
} else {
|
||||
size = inputApParams.width;
|
||||
}
|
||||
|
||||
memcpy(&inputTensorInfo.data[pixelIndex], src + lineIndex, size);
|
||||
pixelIndex += size;
|
||||
outLineIndex += size;
|
||||
}
|
||||
|
||||
if (pixelIndex == outSize)
|
||||
break;
|
||||
|
||||
src += TensorStride;
|
||||
}
|
||||
|
||||
inputTensorInfo.size = outSize;
|
||||
inputTensorInfo.width = inputApParams.width;
|
||||
inputTensorInfo.height = inputApParams.height;
|
||||
inputTensorInfo.channels = inputApParams.channel;
|
||||
inputTensorInfo.widthStride = inputApParams.widthStride;
|
||||
inputTensorInfo.heightStride = inputApParams.heightStride;
|
||||
inputTensorInfo.networkName = inputApParams.networkName;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} /* namespace */
|
||||
|
||||
int RPiController::imx500ParseInputTensor(IMX500InputTensorInfo &inputTensorInfo,
|
||||
libcamera::Span<const uint8_t> inputTensor)
|
||||
{
|
||||
DnnHeader dnnHeader;
|
||||
std::vector<uint8_t> apParams;
|
||||
InputTensorApParams inputApParams{};
|
||||
|
||||
const uint8_t *src = inputTensor.data();
|
||||
int ret = parseHeader(dnnHeader, apParams, src);
|
||||
if (ret) {
|
||||
LOG(IMX500, Error) << "Header param parsing failed!";
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dnnHeader.tensorType != TensorType::InputTensor) {
|
||||
LOG(IMX500, Error) << "Invalid input tensor type in AP params!";
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = parseInputApParams(inputApParams, apParams, dnnHeader);
|
||||
if (ret) {
|
||||
LOG(IMX500, Error) << "AP param parsing failed!";
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = parseInputTensorBody(inputTensorInfo, src + TensorStride, inputApParams, dnnHeader);
|
||||
if (ret) {
|
||||
LOG(IMX500, Error) << "Input tensor body parsing failed!";
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RPiController::imx500ParseOutputTensor(IMX500OutputTensorInfo &outputTensorInfo,
|
||||
Span<const uint8_t> outputTensor)
|
||||
{
|
||||
DnnHeader dnnHeader;
|
||||
std::vector<uint8_t> apParams;
|
||||
std::vector<OutputTensorApParams> outputApParams;
|
||||
|
||||
const uint8_t *src = outputTensor.data();
|
||||
int ret = parseHeader(dnnHeader, apParams, src);
|
||||
if (ret) {
|
||||
LOG(IMX500, Error) << "Header param parsing failed!";
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dnnHeader.tensorType != TensorType::OutputTensor) {
|
||||
LOG(IMX500, Error) << "Invalid output tensor type in AP params!";
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = parseOutputApParams(outputApParams, apParams, dnnHeader);
|
||||
if (ret) {
|
||||
LOG(IMX500, Error) << "AP param parsing failed!";
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = populateOutputTensorInfo(outputTensorInfo, outputApParams);
|
||||
if (ret) {
|
||||
LOG(IMX500, Error) << "Failed to populate OutputTensorInfo!";
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = parseOutputTensorBody(outputTensorInfo, src + TensorStride, outputApParams, dnnHeader);
|
||||
if (ret) {
|
||||
LOG(IMX500, Error) << "Output tensor body parsing failed!";
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unordered_map<TensorType, IMX500Tensors> RPiController::imx500SplitTensors(Span<const uint8_t> tensors)
|
||||
{
|
||||
const DnnHeader *outputHeader;
|
||||
DnnHeader inputHeader;
|
||||
std::unordered_map<TensorType, IMX500Tensors> offsets;
|
||||
|
||||
/*
|
||||
* Structure of the IMX500 DNN output:
|
||||
* Line 0: KPI params
|
||||
* Line [1, x): Input tensor
|
||||
* Line [x, N-1): Output tensor
|
||||
* Line N-1: PQ params
|
||||
*/
|
||||
offsets[TensorType::Kpi].offset = 0;
|
||||
|
||||
const uint8_t *src = tensors.data() + TensorStride;
|
||||
inputHeader = *reinterpret_cast<const DnnHeader *>(src);
|
||||
if (inputHeader.tensorType != TensorType::InputTensor) {
|
||||
LOG(IMX500, Debug) << "Input tensor is invalid, arborting.";
|
||||
return {};
|
||||
}
|
||||
|
||||
offsets[TensorType::InputTensor].offset = TensorStride;
|
||||
offsets[TensorType::InputTensor].valid = inputHeader.frameValid;
|
||||
LOG(IMX500, Debug)
|
||||
<< "Found input tensor at offset: " << offsets[TensorType::InputTensor].offset
|
||||
<< ", valid: " << static_cast<unsigned int>(offsets[TensorType::InputTensor].valid);
|
||||
|
||||
src += TensorStride;
|
||||
|
||||
while (src < tensors.data() + tensors.size()) {
|
||||
outputHeader = reinterpret_cast<const DnnHeader *>(src);
|
||||
if (outputHeader->frameCount == inputHeader.frameCount &&
|
||||
outputHeader->apParamSize == inputHeader.apParamSize &&
|
||||
outputHeader->maxLineLen == inputHeader.maxLineLen &&
|
||||
outputHeader->tensorType == TensorType::OutputTensor) {
|
||||
offsets[TensorType::OutputTensor].offset = src - tensors.data();
|
||||
offsets[TensorType::OutputTensor].valid = outputHeader->frameValid;
|
||||
LOG(IMX500, Debug)
|
||||
<< "Found output tensor at offset: " << offsets[TensorType::OutputTensor].offset
|
||||
<< ", valid: " << static_cast<unsigned int>(offsets[TensorType::OutputTensor].valid);
|
||||
break;
|
||||
}
|
||||
src += TensorStride;
|
||||
}
|
||||
|
||||
return offsets;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024, Raspberry Pi Ltd
|
||||
*
|
||||
* imx500_tensor_parser.h - Parser for imx500 tensors
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <libcamera/base/span.h>
|
||||
|
||||
namespace RPiController {
|
||||
|
||||
enum TensorType {
|
||||
InputTensor = 0,
|
||||
OutputTensor,
|
||||
Kpi,
|
||||
};
|
||||
|
||||
struct Dimensions {
|
||||
uint8_t ordinal;
|
||||
uint16_t size;
|
||||
uint8_t serializationIndex;
|
||||
uint8_t padding;
|
||||
};
|
||||
|
||||
struct IMX500OutputTensorInfo {
|
||||
uint32_t totalSize;
|
||||
uint32_t numTensors;
|
||||
std::string networkName;
|
||||
std::shared_ptr<float[]> data;
|
||||
std::vector<uint32_t> tensorDataNum;
|
||||
std::vector<std::vector<Dimensions>> vecDim;
|
||||
std::vector<uint32_t> numDimensions;
|
||||
};
|
||||
|
||||
struct IMX500InputTensorInfo {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int widthStride;
|
||||
unsigned int heightStride;
|
||||
unsigned int channels;
|
||||
unsigned int size;
|
||||
std::string networkName;
|
||||
std::shared_ptr<uint8_t[]> data;
|
||||
};
|
||||
|
||||
struct IMX500Tensors {
|
||||
bool valid;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
int imx500ParseOutputTensor(IMX500OutputTensorInfo &outputTensorInfo,
|
||||
libcamera::Span<const uint8_t> outputTensor);
|
||||
int imx500ParseInputTensor(IMX500InputTensorInfo &inputTensorInfo,
|
||||
libcamera::Span<const uint8_t> inputTensor);
|
||||
std::unordered_map<TensorType, IMX500Tensors> imx500SplitTensors(libcamera::Span<const uint8_t> tensors);
|
||||
|
||||
} /* namespace RPiController */
|
||||
5
src/ipa/rpi/cam_helper/imx500_tensor_parser/meson.build
Normal file
5
src/ipa/rpi/cam_helper/imx500_tensor_parser/meson.build
Normal file
@@ -0,0 +1,5 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
rpi_ipa_cam_helper_sources += files([
|
||||
'imx500_tensor_parser.cpp',
|
||||
])
|
||||
@@ -9,6 +9,7 @@ rpi_ipa_cam_helper_sources = files([
|
||||
'cam_helper_imx296.cpp',
|
||||
'cam_helper_imx415.cpp',
|
||||
'cam_helper_imx477.cpp',
|
||||
'cam_helper_imx500.cpp',
|
||||
'cam_helper_imx519.cpp',
|
||||
'cam_helper_imx708.cpp',
|
||||
'cam_helper_ov64a40.cpp',
|
||||
@@ -23,6 +24,8 @@ rpi_ipa_cam_helper_includes = [
|
||||
include_directories('..'),
|
||||
]
|
||||
|
||||
subdir('imx500_tensor_parser')
|
||||
|
||||
rpi_ipa_cam_helper_deps = [
|
||||
libcamera_private,
|
||||
]
|
||||
|
||||
1209
src/ipa/rpi/pisp/data/imx500.json
Normal file
1209
src/ipa/rpi/pisp/data/imx500.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,7 @@ conf_files = files([
|
||||
'imx477.json',
|
||||
'imx477_noir.json',
|
||||
'imx477_scientific.json',
|
||||
'imx500.json',
|
||||
'imx519.json',
|
||||
'imx708.json',
|
||||
'imx708_noir.json',
|
||||
|
||||
463
src/ipa/rpi/vc4/data/imx500.json
Normal file
463
src/ipa/rpi/vc4/data/imx500.json
Normal file
@@ -0,0 +1,463 @@
|
||||
{
|
||||
"version": 2.0,
|
||||
"target": "bcm2835",
|
||||
"algorithms": [
|
||||
{
|
||||
"rpi.black_level":
|
||||
{
|
||||
"black_level": 4096
|
||||
}
|
||||
},
|
||||
{
|
||||
"rpi.dpc": { }
|
||||
},
|
||||
{
|
||||
"rpi.lux":
|
||||
{
|
||||
"reference_shutter_speed": 10369,
|
||||
"reference_gain": 2.0,
|
||||
"reference_aperture": 1.0,
|
||||
"reference_lux": 950,
|
||||
"reference_Y": 12457
|
||||
}
|
||||
},
|
||||
{
|
||||
"rpi.noise":
|
||||
{
|
||||
"reference_constant": 0,
|
||||
"reference_slope": 2.747
|
||||
}
|
||||
},
|
||||
{
|
||||
"rpi.geq":
|
||||
{
|
||||
"offset": 223,
|
||||
"slope": 0.00933
|
||||
}
|
||||
},
|
||||
{
|
||||
"rpi.sdn": { }
|
||||
},
|
||||
{
|
||||
"rpi.awb":
|
||||
{
|
||||
"priors": [
|
||||
{
|
||||
"lux": 0,
|
||||
"prior":
|
||||
[
|
||||
2000, 1.0,
|
||||
3000, 0.0,
|
||||
13000, 0.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"lux": 800,
|
||||
"prior":
|
||||
[
|
||||
2000, 0.0,
|
||||
6000, 2.0,
|
||||
13000, 2.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"lux": 1500,
|
||||
"prior":
|
||||
[
|
||||
2000, 0.0,
|
||||
4000, 1.0,
|
||||
6000, 6.0,
|
||||
6500, 7.0,
|
||||
7000, 1.0,
|
||||
13000, 1.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"modes":
|
||||
{
|
||||
"auto":
|
||||
{
|
||||
"lo": 2800,
|
||||
"hi": 8000
|
||||
},
|
||||
"incandescent":
|
||||
{
|
||||
"lo": 2800,
|
||||
"hi": 3000
|
||||
},
|
||||
"tungsten":
|
||||
{
|
||||
"lo": 3000,
|
||||
"hi": 3500
|
||||
},
|
||||
"fluorescent":
|
||||
{
|
||||
"lo": 4000,
|
||||
"hi": 4700
|
||||
},
|
||||
"indoor":
|
||||
{
|
||||
"lo": 3000,
|
||||
"hi": 5000
|
||||
},
|
||||
"daylight":
|
||||
{
|
||||
"lo": 5500,
|
||||
"hi": 6500
|
||||
},
|
||||
"cloudy":
|
||||
{
|
||||
"lo": 7000,
|
||||
"hi": 7600
|
||||
}
|
||||
},
|
||||
"bayes": 1,
|
||||
"ct_curve":
|
||||
[
|
||||
2800.0, 0.7126, 0.3567,
|
||||
2860.0, 0.6681, 0.4042,
|
||||
2880.0, 0.6651, 0.4074,
|
||||
3580.0, 0.5674, 0.5091,
|
||||
3650.0, 0.5629, 0.5137,
|
||||
4500.0, 0.4792, 0.5982,
|
||||
4570.0, 0.4752, 0.6022,
|
||||
5648.0, 0.4137, 0.6628,
|
||||
5717.0, 0.4116, 0.6648,
|
||||
7600.0, 0.3609, 0.7138
|
||||
],
|
||||
"sensitivity_r": 1.0,
|
||||
"sensitivity_b": 1.0,
|
||||
"transverse_pos": 0.02798,
|
||||
"transverse_neg": 0.02626
|
||||
}
|
||||
},
|
||||
{
|
||||
"rpi.agc":
|
||||
{
|
||||
"metering_modes":
|
||||
{
|
||||
"centre-weighted":
|
||||
{
|
||||
"weights":
|
||||
[
|
||||
3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
|
||||
]
|
||||
},
|
||||
"spot":
|
||||
{
|
||||
"weights":
|
||||
[
|
||||
2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
]
|
||||
},
|
||||
"matrix":
|
||||
{
|
||||
"weights":
|
||||
[
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
||||
]
|
||||
}
|
||||
},
|
||||
"exposure_modes":
|
||||
{
|
||||
"normal":
|
||||
{
|
||||
"shutter": [ 100, 10000, 30000, 60000, 120000 ],
|
||||
"gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
|
||||
},
|
||||
"short":
|
||||
{
|
||||
"shutter": [ 100, 5000, 10000, 20000, 120000 ],
|
||||
"gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
|
||||
}
|
||||
},
|
||||
"constraint_modes":
|
||||
{
|
||||
"normal": [
|
||||
{
|
||||
"bound": "LOWER",
|
||||
"q_lo": 0.98,
|
||||
"q_hi": 1.0,
|
||||
"y_target":
|
||||
[
|
||||
0, 0.5,
|
||||
1000, 0.5
|
||||
]
|
||||
}
|
||||
],
|
||||
"highlight": [
|
||||
{
|
||||
"bound": "LOWER",
|
||||
"q_lo": 0.98,
|
||||
"q_hi": 1.0,
|
||||
"y_target":
|
||||
[
|
||||
0, 0.5,
|
||||
1000, 0.5
|
||||
]
|
||||
},
|
||||
{
|
||||
"bound": "UPPER",
|
||||
"q_lo": 0.98,
|
||||
"q_hi": 1.0,
|
||||
"y_target":
|
||||
[
|
||||
0, 0.8,
|
||||
1000, 0.8
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"y_target":
|
||||
[
|
||||
0, 0.16,
|
||||
1000, 0.165,
|
||||
10000, 0.17
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"rpi.alsc":
|
||||
{
|
||||
"omega": 1.3,
|
||||
"n_iter": 100,
|
||||
"luminance_strength": 0.8,
|
||||
"calibrations_Cr": [
|
||||
{
|
||||
"ct": 2800,
|
||||
"table":
|
||||
[
|
||||
1.613, 1.617, 1.621, 1.621, 1.615, 1.607, 1.604, 1.603, 1.603, 1.603, 1.607, 1.619, 1.626, 1.626, 1.622, 1.615,
|
||||
1.613, 1.616, 1.617, 1.615, 1.599, 1.583, 1.571, 1.564, 1.564, 1.571, 1.584, 1.603, 1.621, 1.624, 1.622, 1.618,
|
||||
1.613, 1.614, 1.614, 1.599, 1.577, 1.546, 1.529, 1.521, 1.521, 1.529, 1.548, 1.582, 1.603, 1.621, 1.621, 1.621,
|
||||
1.613, 1.613, 1.604, 1.577, 1.546, 1.521, 1.489, 1.481, 1.481, 1.491, 1.525, 1.548, 1.582, 1.612, 1.621, 1.623,
|
||||
1.614, 1.612, 1.595, 1.561, 1.521, 1.489, 1.475, 1.453, 1.453, 1.479, 1.491, 1.525, 1.567, 1.606, 1.623, 1.624,
|
||||
1.614, 1.612, 1.593, 1.555, 1.513, 1.477, 1.454, 1.452, 1.453, 1.455, 1.481, 1.519, 1.563, 1.604, 1.624, 1.626,
|
||||
1.615, 1.612, 1.593, 1.555, 1.513, 1.477, 1.458, 1.452, 1.453, 1.459, 1.481, 1.519, 1.563, 1.604, 1.625, 1.626,
|
||||
1.615, 1.614, 1.599, 1.564, 1.525, 1.496, 1.477, 1.459, 1.459, 1.481, 1.497, 1.531, 1.572, 1.609, 1.626, 1.627,
|
||||
1.614, 1.614, 1.609, 1.581, 1.552, 1.525, 1.496, 1.488, 1.488, 1.497, 1.531, 1.558, 1.591, 1.619, 1.626, 1.626,
|
||||
1.614, 1.616, 1.618, 1.607, 1.581, 1.552, 1.535, 1.529, 1.529, 1.538, 1.558, 1.591, 1.616, 1.631, 1.631, 1.625,
|
||||
1.613, 1.618, 1.619, 1.621, 1.607, 1.591, 1.579, 1.575, 1.575, 1.582, 1.597, 1.616, 1.631, 1.632, 1.631, 1.625,
|
||||
1.611, 1.616, 1.622, 1.623, 1.621, 1.615, 1.614, 1.614, 1.614, 1.615, 1.619, 1.631, 1.633, 1.633, 1.629, 1.624
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 4000,
|
||||
"table":
|
||||
[
|
||||
2.051, 2.057, 2.058, 2.058, 2.052, 2.045, 2.041, 2.041, 2.041, 2.042, 2.047, 2.062, 2.071, 2.071, 2.068, 2.061,
|
||||
2.051, 2.053, 2.055, 2.051, 2.033, 2.014, 2.001, 1.995, 1.995, 2.004, 2.019, 2.042, 2.064, 2.069, 2.068, 2.062,
|
||||
2.051, 2.051, 2.051, 2.033, 2.005, 1.971, 1.951, 1.943, 1.943, 1.953, 1.976, 2.016, 2.042, 2.064, 2.065, 2.065,
|
||||
2.049, 2.049, 2.037, 2.005, 1.971, 1.939, 1.904, 1.894, 1.894, 1.906, 1.947, 1.976, 2.016, 2.053, 2.065, 2.066,
|
||||
2.051, 2.048, 2.028, 1.987, 1.939, 1.904, 1.884, 1.858, 1.858, 1.891, 1.906, 1.947, 1.998, 2.044, 2.066, 2.068,
|
||||
2.051, 2.048, 2.025, 1.981, 1.929, 1.886, 1.858, 1.855, 1.857, 1.861, 1.892, 1.939, 1.992, 2.041, 2.068, 2.068,
|
||||
2.052, 2.048, 2.025, 1.981, 1.929, 1.886, 1.863, 1.855, 1.858, 1.864, 1.892, 1.939, 1.992, 2.041, 2.068, 2.069,
|
||||
2.053, 2.052, 2.033, 1.992, 1.944, 1.911, 1.886, 1.864, 1.864, 1.892, 1.912, 1.953, 2.003, 2.048, 2.069, 2.069,
|
||||
2.053, 2.053, 2.046, 2.013, 1.978, 1.944, 1.911, 1.901, 1.901, 1.912, 1.953, 1.985, 2.023, 2.059, 2.069, 2.069,
|
||||
2.053, 2.055, 2.058, 2.044, 2.013, 1.978, 1.959, 1.951, 1.951, 1.961, 1.985, 2.023, 2.054, 2.071, 2.071, 2.068,
|
||||
2.052, 2.058, 2.059, 2.061, 2.044, 2.025, 2.011, 2.005, 2.005, 2.014, 2.031, 2.054, 2.071, 2.075, 2.072, 2.068,
|
||||
2.051, 2.056, 2.064, 2.064, 2.061, 2.055, 2.052, 2.052, 2.052, 2.054, 2.058, 2.071, 2.077, 2.077, 2.072, 2.067
|
||||
]
|
||||
}
|
||||
],
|
||||
"calibrations_Cb": [
|
||||
{
|
||||
"ct": 2800,
|
||||
"table":
|
||||
[
|
||||
2.878, 2.876, 2.864, 2.851, 2.847, 2.847, 2.849, 2.854, 2.854, 2.854, 2.854, 2.854, 2.861, 2.873, 2.885, 2.887,
|
||||
2.876, 2.871, 2.859, 2.852, 2.849, 2.849, 2.854, 2.855, 2.855, 2.855, 2.854, 2.852, 2.854, 2.861, 2.875, 2.885,
|
||||
2.872, 2.869, 2.859, 2.856, 2.854, 2.856, 2.859, 2.863, 2.863, 2.861, 2.855, 2.852, 2.853, 2.855, 2.867, 2.875,
|
||||
2.872, 2.871, 2.865, 2.859, 2.858, 2.863, 2.869, 2.877, 2.877, 2.872, 2.861, 2.856, 2.854, 2.857, 2.863, 2.873,
|
||||
2.872, 2.871, 2.868, 2.865, 2.866, 2.872, 2.886, 2.899, 2.899, 2.879, 2.872, 2.861, 2.857, 2.859, 2.862, 2.871,
|
||||
2.872, 2.871, 2.869, 2.869, 2.872, 2.886, 2.901, 2.909, 2.903, 2.899, 2.879, 2.865, 2.859, 2.859, 2.861, 2.869,
|
||||
2.872, 2.871, 2.871, 2.871, 2.873, 2.886, 2.906, 2.909, 2.908, 2.902, 2.879, 2.865, 2.859, 2.859, 2.861, 2.868,
|
||||
2.872, 2.871, 2.871, 2.869, 2.873, 2.884, 2.892, 2.907, 2.903, 2.889, 2.875, 2.864, 2.859, 2.859, 2.861, 2.868,
|
||||
2.875, 2.872, 2.868, 2.867, 2.869, 2.874, 2.884, 2.889, 2.889, 2.877, 2.866, 2.859, 2.859, 2.861, 2.864, 2.872,
|
||||
2.877, 2.875, 2.867, 2.864, 2.865, 2.869, 2.874, 2.877, 2.877, 2.868, 2.861, 2.859, 2.859, 2.863, 2.872, 2.881,
|
||||
2.882, 2.877, 2.868, 2.863, 2.863, 2.863, 2.868, 2.869, 2.868, 2.865, 2.863, 2.861, 2.863, 2.871, 2.881, 2.883,
|
||||
2.885, 2.882, 2.872, 2.864, 2.861, 2.861, 2.865, 2.865, 2.865, 2.864, 2.863, 2.863, 2.866, 2.872, 2.882, 2.891
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 4000,
|
||||
"table":
|
||||
[
|
||||
1.919, 1.919, 1.913, 1.909, 1.909, 1.909, 1.911, 1.912, 1.912, 1.911, 1.909, 1.909, 1.911, 1.914, 1.919, 1.921,
|
||||
1.919, 1.916, 1.913, 1.911, 1.909, 1.912, 1.914, 1.915, 1.914, 1.913, 1.911, 1.909, 1.909, 1.911, 1.915, 1.919,
|
||||
1.916, 1.915, 1.915, 1.914, 1.914, 1.918, 1.921, 1.921, 1.921, 1.919, 1.915, 1.911, 1.909, 1.911, 1.913, 1.916,
|
||||
1.916, 1.916, 1.916, 1.916, 1.919, 1.924, 1.928, 1.932, 1.932, 1.928, 1.919, 1.915, 1.911, 1.911, 1.912, 1.914,
|
||||
1.916, 1.917, 1.918, 1.919, 1.924, 1.928, 1.937, 1.945, 1.945, 1.932, 1.928, 1.919, 1.915, 1.912, 1.912, 1.913,
|
||||
1.916, 1.918, 1.919, 1.923, 1.928, 1.937, 1.946, 1.949, 1.946, 1.945, 1.931, 1.922, 1.916, 1.912, 1.912, 1.913,
|
||||
1.916, 1.918, 1.919, 1.923, 1.928, 1.937, 1.948, 1.949, 1.948, 1.945, 1.931, 1.922, 1.916, 1.912, 1.912, 1.912,
|
||||
1.915, 1.917, 1.918, 1.922, 1.927, 1.933, 1.938, 1.946, 1.945, 1.935, 1.928, 1.919, 1.915, 1.912, 1.912, 1.912,
|
||||
1.916, 1.916, 1.917, 1.918, 1.922, 1.927, 1.933, 1.935, 1.935, 1.928, 1.921, 1.915, 1.913, 1.912, 1.912, 1.914,
|
||||
1.917, 1.916, 1.916, 1.915, 1.917, 1.921, 1.925, 1.926, 1.926, 1.921, 1.918, 1.913, 1.913, 1.913, 1.916, 1.919,
|
||||
1.918, 1.917, 1.915, 1.913, 1.913, 1.916, 1.919, 1.921, 1.921, 1.918, 1.914, 1.913, 1.913, 1.915, 1.918, 1.921,
|
||||
1.919, 1.919, 1.914, 1.912, 1.912, 1.913, 1.914, 1.915, 1.915, 1.915, 1.913, 1.913, 1.913, 1.915, 1.919, 1.922
|
||||
]
|
||||
}
|
||||
],
|
||||
"luminance_lut":
|
||||
[
|
||||
3.029, 2.888, 2.497, 2.201, 1.954, 1.761, 1.711, 1.711, 1.711, 1.713, 1.778, 1.975, 2.225, 2.526, 2.925, 3.069,
|
||||
2.888, 2.562, 2.203, 1.999, 1.762, 1.602, 1.495, 1.447, 1.447, 1.503, 1.616, 1.785, 2.019, 2.229, 2.594, 2.925,
|
||||
2.577, 2.319, 2.004, 1.762, 1.602, 1.391, 1.284, 1.241, 1.241, 1.294, 1.409, 1.616, 1.785, 2.031, 2.349, 2.607,
|
||||
2.451, 2.155, 1.861, 1.607, 1.391, 1.284, 1.137, 1.095, 1.095, 1.154, 1.294, 1.409, 1.631, 1.891, 2.185, 2.483,
|
||||
2.393, 2.056, 1.765, 1.501, 1.288, 1.137, 1.091, 1.004, 1.011, 1.095, 1.154, 1.309, 1.527, 1.796, 2.088, 2.425,
|
||||
2.393, 2.015, 1.722, 1.455, 1.245, 1.097, 1.004, 1.001, 1.001, 1.016, 1.115, 1.266, 1.482, 1.752, 2.046, 2.425,
|
||||
2.393, 2.015, 1.722, 1.455, 1.245, 1.097, 1.014, 1.001, 1.011, 1.017, 1.115, 1.266, 1.482, 1.752, 2.046, 2.425,
|
||||
2.399, 2.071, 1.777, 1.515, 1.301, 1.158, 1.097, 1.017, 1.017, 1.114, 1.169, 1.323, 1.543, 1.809, 2.102, 2.429,
|
||||
2.471, 2.178, 1.881, 1.628, 1.419, 1.301, 1.158, 1.117, 1.117, 1.169, 1.323, 1.439, 1.657, 1.915, 2.213, 2.501,
|
||||
2.622, 2.358, 2.034, 1.799, 1.628, 1.419, 1.315, 1.271, 1.271, 1.327, 1.439, 1.657, 1.824, 2.067, 2.394, 2.662,
|
||||
2.959, 2.622, 2.255, 2.034, 1.799, 1.644, 1.536, 1.489, 1.489, 1.548, 1.664, 1.824, 2.066, 2.284, 2.662, 3.018,
|
||||
3.099, 2.959, 2.559, 2.249, 1.994, 1.803, 1.756, 1.756, 1.756, 1.759, 1.824, 2.022, 2.281, 2.601, 3.018, 3.155
|
||||
],
|
||||
"sigma": 0.00096,
|
||||
"sigma_Cb": 0.00125
|
||||
}
|
||||
},
|
||||
{
|
||||
"rpi.contrast":
|
||||
{
|
||||
"ce_enable": 1,
|
||||
"gamma_curve":
|
||||
[
|
||||
0, 0,
|
||||
1024, 5040,
|
||||
2048, 9338,
|
||||
3072, 12356,
|
||||
4096, 15312,
|
||||
5120, 18051,
|
||||
6144, 20790,
|
||||
7168, 23193,
|
||||
8192, 25744,
|
||||
9216, 27942,
|
||||
10240, 30035,
|
||||
11264, 32005,
|
||||
12288, 33975,
|
||||
13312, 35815,
|
||||
14336, 37600,
|
||||
15360, 39168,
|
||||
16384, 40642,
|
||||
18432, 43379,
|
||||
20480, 45749,
|
||||
22528, 47753,
|
||||
24576, 49621,
|
||||
26624, 51253,
|
||||
28672, 52698,
|
||||
30720, 53796,
|
||||
32768, 54876,
|
||||
36864, 57012,
|
||||
40960, 58656,
|
||||
45056, 59954,
|
||||
49152, 61183,
|
||||
53248, 62355,
|
||||
57344, 63419,
|
||||
61440, 64476,
|
||||
65535, 65535
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"rpi.ccm":
|
||||
{
|
||||
"ccms": [
|
||||
{
|
||||
"ct": 2800,
|
||||
"ccm":
|
||||
[
|
||||
1.61505, -0.29143, -0.32361,
|
||||
-0.36502, 1.73067, -0.36565,
|
||||
0.05048, -1.11795, 2.06747
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 2860,
|
||||
"ccm":
|
||||
[
|
||||
1.61304, -0.35407, -0.25897,
|
||||
-0.49934, 1.98721, -0.48786,
|
||||
-0.03138, -0.70205, 1.73343
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 2880,
|
||||
"ccm":
|
||||
[
|
||||
1.61025, -0.33823, -0.27202,
|
||||
-0.49191, 1.99155, -0.49964,
|
||||
-0.02357, -0.74144, 1.76501
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 3580,
|
||||
"ccm":
|
||||
[
|
||||
1.67102, -0.45799, -0.21303,
|
||||
-0.43726, 1.89058, -0.45332,
|
||||
-0.04778, -0.57899, 1.62678
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 3650,
|
||||
"ccm":
|
||||
[
|
||||
1.66289, -0.44966, -0.21324,
|
||||
-0.42687, 1.86716, -0.44029,
|
||||
-0.04423, -0.55781, 1.60204
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 4500,
|
||||
"ccm":
|
||||
[
|
||||
1.59699, -0.35409, -0.24291,
|
||||
-0.38812, 1.97453, -0.58641,
|
||||
-0.05398, -0.50715, 1.56113
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 4570,
|
||||
"ccm":
|
||||
[
|
||||
1.62669, -0.38858, -0.23811,
|
||||
-0.38608, 1.97311, -0.58703,
|
||||
-0.05461, -0.52526, 1.57986
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 5648,
|
||||
"ccm":
|
||||
[
|
||||
1.77461, -0.60797, -0.16664,
|
||||
-0.33734, 1.82254, -0.48521,
|
||||
-0.06916, -0.43139, 1.50056
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 5717,
|
||||
"ccm":
|
||||
[
|
||||
1.76115, -0.59353, -0.16763,
|
||||
-0.33521, 1.82009, -0.48488,
|
||||
-0.07309, -0.42667, 1.49976
|
||||
]
|
||||
},
|
||||
{
|
||||
"ct": 7600,
|
||||
"ccm":
|
||||
[
|
||||
1.71087, -0.34863, -0.36223,
|
||||
-0.31392, 2.24605, -0.93213,
|
||||
-0.08447, -0.72208, 1.80655
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"rpi.sharpen": { }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -16,6 +16,7 @@ conf_files = files([
|
||||
'imx477.json',
|
||||
'imx477_noir.json',
|
||||
'imx477_scientific.json',
|
||||
'imx500.json',
|
||||
'imx519.json',
|
||||
'imx708.json',
|
||||
'imx708_noir.json',
|
||||
|
||||
@@ -291,6 +291,16 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen
|
||||
.hblankDelay = 3
|
||||
},
|
||||
} },
|
||||
{ "imx500", {
|
||||
.unitCellSize = { 1550, 1550 },
|
||||
.testPatternModes = {},
|
||||
.sensorDelays = {
|
||||
.exposureDelay = 2,
|
||||
.gainDelay = 2,
|
||||
.vblankDelay = 3,
|
||||
.hblankDelay = 3
|
||||
},
|
||||
} },
|
||||
{ "imx519", {
|
||||
.unitCellSize = { 1220, 1220 },
|
||||
.testPatternModes = {
|
||||
|
||||
Reference in New Issue
Block a user