Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions sbe-tool/src/main/cpp/otf/Encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,143 @@ class Encoding
}
}

static inline void putChar(char *buffer, char value)
{
*buffer = value;
}

static inline void putInt8(char *buffer, std::int8_t value)
{
std::memcpy(buffer, &value, sizeof(std::int8_t));
}

static inline void putInt16(char *buffer, const ByteOrder byteOrder, std::int16_t value)
{
value = SBE_OTF_BYTE_ORDER_16(byteOrder, value);
std::memcpy(buffer, &value, sizeof(std::int16_t));
}

static inline void putInt32(char *buffer, const ByteOrder byteOrder, std::int32_t value)
{
value = SBE_OTF_BYTE_ORDER_32(byteOrder, value);
std::memcpy(buffer, &value, sizeof(std::int32_t));
}

static inline void putInt64(char *buffer, const ByteOrder byteOrder, std::int64_t value)
{
value = SBE_OTF_BYTE_ORDER_64(byteOrder, value);
std::memcpy(buffer, &value, sizeof(std::int64_t));
}

static inline void putUInt8(char *buffer, std::uint8_t value)
{
std::memcpy(buffer, &value, sizeof(std::uint8_t));
}

static inline void putUInt16(char *buffer, const ByteOrder byteOrder, std::uint16_t value)
{
value = SBE_OTF_BYTE_ORDER_16(byteOrder, value);
std::memcpy(buffer, &value, sizeof(std::uint16_t));
}

static inline void putUInt32(char *buffer, const ByteOrder byteOrder, std::uint32_t value)
{
value = SBE_OTF_BYTE_ORDER_32(byteOrder, value);
std::memcpy(buffer, &value, sizeof(std::uint32_t));
}

static inline void putUInt64(char *buffer, const ByteOrder byteOrder, std::uint64_t value)
{
value = SBE_OTF_BYTE_ORDER_64(byteOrder, value);
std::memcpy(buffer, &value, sizeof(std::uint64_t));
}

static inline void putFloat(char *buffer, const ByteOrder byteOrder, float value)
{
sbe_float_as_uint_t val;
val.fp_value = value;
val.uint_value = SBE_OTF_BYTE_ORDER_32(byteOrder, val.uint_value);
std::memcpy(buffer, &val, sizeof(float));
}

static inline void putDouble(char *buffer, const ByteOrder byteOrder, double value)
{
sbe_double_as_uint_t val;
val.fp_value = value;
val.uint_value = SBE_OTF_BYTE_ORDER_64(byteOrder, val.uint_value);
std::memcpy(buffer, &val, sizeof(double));
}

static inline void putInt(const PrimitiveType type, const ByteOrder byteOrder, char *buffer, const std::int64_t value)
{
switch (type)
{
case PrimitiveType::CHAR:
putChar(buffer, static_cast<char>(value));
break;

case PrimitiveType::INT8:
putInt8(buffer, static_cast<std::int8_t>(value));
break;

case PrimitiveType::INT16:
putInt16(buffer, byteOrder, static_cast<std::int16_t>(value));
break;

case PrimitiveType::INT32:
putInt32(buffer, byteOrder, static_cast<std::int32_t>(value));
break;

case PrimitiveType::INT64:
putInt64(buffer, byteOrder, value);
break;

default:
throw std::runtime_error("incorrect type for Encoding::putInt");
}
}

static inline void putUInt(const PrimitiveType type, const ByteOrder byteOrder, char *buffer, const std::uint64_t value)
{
switch (type)
{
case PrimitiveType::UINT8:
putUInt8(buffer, static_cast<std::uint8_t>(value));
break;

case PrimitiveType::UINT16:
putUInt16(buffer, byteOrder, static_cast<std::uint16_t>(value));
break;

case PrimitiveType::UINT32:
putUInt32(buffer, byteOrder, static_cast<std::uint32_t>(value));
break;

case PrimitiveType::UINT64:
putUInt64(buffer, byteOrder, value);
break;

default:
throw std::runtime_error("incorrect type for Encoding::putUInt");
}
}

static inline void putDouble(const PrimitiveType type, const ByteOrder byteOrder, char *buffer, const double value)
{
if (type == PrimitiveType::FLOAT)
{
putFloat(buffer, byteOrder, static_cast<float>(value));
}
else if (type == PrimitiveType::DOUBLE)
{
putDouble(buffer, byteOrder, value);
}
else
{
throw std::runtime_error("incorrect type for Encoding::putDouble");
}
}

inline Presence presence() const
{
return m_presence;
Expand Down Expand Up @@ -531,6 +668,21 @@ class Encoding
return getDouble(m_primitiveType, m_byteOrder, buffer);
}

inline void putAsInt(char *buffer, const std::int64_t value) const
{
putInt(m_primitiveType, m_byteOrder, buffer, value);
}

inline void putAsUInt(char *buffer, const std::uint64_t value) const
{
putUInt(m_primitiveType, m_byteOrder, buffer, value);
}

inline void putAsDouble(char *buffer, const double value) const
{
putDouble(m_primitiveType, m_byteOrder, buffer, value);
}

inline const PrimitiveValue &minValue() const
{
return m_minValue;
Expand Down
116 changes: 116 additions & 0 deletions sbe-tool/src/main/cpp/otf/OtfHeaderEncoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright 2013-2025 Real Logic Limited.
*
* 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
*
* https://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 _OTF_HEADERENCODER_H
#define _OTF_HEADERENCODER_H

#include <cstdint>
#include <memory>
#include <vector>
#include <string>

#include "Token.h"

namespace sbe {
namespace otf {

/*
* Writes an SBE message header. Inverse of OtfHeaderDecoder: it locates the same well-known
* header fields by name and writes them, rather than reading them.
*/
class OtfHeaderEncoder
{
public:
explicit OtfHeaderEncoder(const std::shared_ptr<std::vector<Token>> &tokens)
{
m_encodedLength = tokens->at(0).encodedLength();

for (Token &token : *tokens)
{
const std::string &name = token.name();

if (name == "blockLength") { m_blockLength = field(token); }
else if (name == "templateId"){ m_templateId = field(token); }
else if (name == "schemaId") { m_schemaId = field(token); }
else if (name == "version") { m_schemaVersion = field(token); }
}

require(m_blockLength, "blockLength");
require(m_templateId, "templateId");
require(m_schemaId, "schemaId");
require(m_schemaVersion, "version");
}

inline std::uint32_t encodedLength() const
{
return static_cast<std::uint32_t>(m_encodedLength);
}

/* All header elements are unsigned integers per the SBE specification. */

void setBlockLength(char *headerBuffer, std::uint64_t value) const { put(m_blockLength, headerBuffer, value); }
void setTemplateId(char *headerBuffer, std::uint64_t value) const { put(m_templateId, headerBuffer, value); }
void setSchemaId(char *headerBuffer, std::uint64_t value) const { put(m_schemaId, headerBuffer, value); }
void setSchemaVersion(char *headerBuffer, std::uint64_t value) const { put(m_schemaVersion, headerBuffer, value); }

void encode(
char *headerBuffer,
std::uint64_t blockLength,
std::uint64_t templateId,
std::uint64_t schemaId,
std::uint64_t schemaVersion) const
{
setBlockLength(headerBuffer, blockLength);
setTemplateId(headerBuffer, templateId);
setSchemaId(headerBuffer, schemaId);
setSchemaVersion(headerBuffer, schemaVersion);
}

private:
struct Field
{
std::int32_t offset = -1;
PrimitiveType type = PrimitiveType::NONE;
ByteOrder byteOrder = ByteOrder::SBE_LITTLE_ENDIAN;
};

static Field field(const Token &token)
{
return { token.offset(), token.encoding().primitiveType(), token.encoding().byteOrder() };
}

static void require(const Field &f, const char *name)
{
if (f.offset < 0)
{
throw std::runtime_error(std::string(name) + " token not found");
}
}

static void put(const Field &f, char *headerBuffer, std::uint64_t value)
{
Encoding::putUInt(f.type, f.byteOrder, headerBuffer + f.offset, value);
}

std::int32_t m_encodedLength = 0;
Field m_blockLength;
Field m_templateId;
Field m_schemaId;
Field m_schemaVersion;
};

}}

#endif
Loading
Loading