cpp.Encoding.h Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sbe-all Show documentation
Show all versions of sbe-all Show documentation
FIX/SBE - OSI layer 6 presentation for encoding and decoding application messages in binary format for low-latency applications.
/*
* Copyright 2013-2024 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_ENCODING_H
#define _OTF_ENCODING_H
#include
#include
#if defined(WIN32) || defined(_WIN32)
# define SBE_OTF_BSWAP_16(v) _byteswap_ushort(v)
# define SBE_OTF_BSWAP_32(v) _byteswap_ulong(v)
# define SBE_OTF_BSWAP_64(v) _byteswap_uint64(v)
#else // assuming gcc/clang
# define SBE_OTF_BSWAP_16(v) __builtin_bswap16(v)
# define SBE_OTF_BSWAP_32(v) __builtin_bswap32(v)
# define SBE_OTF_BSWAP_64(v) __builtin_bswap64(v)
#endif
#if defined(WIN32) || defined(_WIN32)
# define SBE_OTF_BYTE_ORDER_16(o,v) ((o == ByteOrder::SBE_LITTLE_ENDIAN) ? (v) : SBE_OTF_BSWAP_16(v))
# define SBE_OTF_BYTE_ORDER_32(o,v) ((o == ByteOrder::SBE_LITTLE_ENDIAN) ? (v) : SBE_OTF_BSWAP_32(v))
# define SBE_OTF_BYTE_ORDER_64(o,v) ((o == ByteOrder::SBE_LITTLE_ENDIAN) ? (v) : SBE_OTF_BSWAP_64(v))
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_OTF_BYTE_ORDER_16(o,v) ((o == ByteOrder::SBE_LITTLE_ENDIAN) ? (v) : SBE_OTF_BSWAP_16(v))
# define SBE_OTF_BYTE_ORDER_32(o,v) ((o == ByteOrder::SBE_LITTLE_ENDIAN) ? (v) : SBE_OTF_BSWAP_32(v))
# define SBE_OTF_BYTE_ORDER_64(o,v) ((o == ByteOrder::SBE_LITTLE_ENDIAN) ? (v) : SBE_OTF_BSWAP_64(v))
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_OTF_BYTE_ORDER_16(o,v) ((o == ByteOrder::SBE_BIG_ENDIAN) ? (v) : SBE_OTF_BSWAP_16(v))
# define SBE_OTF_BYTE_ORDER_32(o,v) ((o == ByteOrder::SBE_BIG_ENDIAN) ? (v) : SBE_OTF_BSWAP_32(v))
# define SBE_OTF_BYTE_ORDER_64(o,v) ((o == ByteOrder::SBE_BIG_ENDIAN) ? (v) : SBE_OTF_BSWAP_64(v))
#else
#error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
namespace sbe {
namespace otf {
/// Constants used for representing byte order
enum class ByteOrder : int
{
/// little endian byte order
SBE_LITTLE_ENDIAN = 0,
/// big endian byte order
SBE_BIG_ENDIAN = 1
};
typedef union sbe_float_as_uint_u
{
float fp_value;
std::uint32_t uint_value;
}
sbe_float_as_uint_t;
typedef union sbe_double_as_uint_u
{
double fp_value;
std::uint64_t uint_value;
}
sbe_double_as_uint_t;
/// Constants used for representing primitive types
enum class PrimitiveType : int
{
/// Type is undefined or unknown
NONE = 0,
/// Type is a signed character
CHAR = 1,
/// Type is a signed 8-bit value
INT8 = 2,
/// Type is a signed 16-bit value
INT16 = 3,
/// Type is a signed 32-bit value
INT32 = 4,
/// Type is a signed 64-bit value
INT64 = 5,
/// Type is a unsigned 8-bit value
UINT8 = 6,
/// Type is a unsigned 16-bit value
UINT16 = 7,
/// Type is a unsigned 32-bit value
UINT32 = 8,
/// Type is a unsigned 64-bit value
UINT64 = 9,
/// Type is a 32-bit floating point value
FLOAT = 10,
/// Type is a 64-bit double floating point value
DOUBLE = 11
};
/// Constants used for representing Presence
enum class Presence : int
{
/// Field or encoding presence is required
SBE_REQUIRED = 0,
/// Field or encoding presence is optional
SBE_OPTIONAL = 1,
/// Field or encoding presence is constant and not encoded
SBE_CONSTANT = 2
};
inline std::size_t lengthOfType(PrimitiveType type)
{
switch (type)
{
case PrimitiveType::CHAR:
return 1;
case PrimitiveType::INT8:
return 1;
case PrimitiveType::INT16:
return 2;
case PrimitiveType::INT32:
return 4;
case PrimitiveType::INT64:
return 8;
case PrimitiveType::UINT8:
return 1;
case PrimitiveType::UINT16:
return 2;
case PrimitiveType::UINT32:
return 4;
case PrimitiveType::UINT64:
return 8;
case PrimitiveType::FLOAT:
return 4;
case PrimitiveType::DOUBLE:
return 8;
default:
return 0;
}
}
class PrimitiveValue
{
public:
PrimitiveValue(PrimitiveType type, std::size_t valueLength, const char *value) :
m_type(type)
{
if (0 == valueLength)
{
m_type = PrimitiveType::NONE;
m_size = 0;
return;
}
switch (type)
{
case PrimitiveType::CHAR:
{
if (valueLength > 1)
{
m_arrayValue = std::string(value, valueLength);
m_size = valueLength;
}
else
{
m_value.asInt = *(char *) value;
m_size = 1;
}
break;
}
case PrimitiveType::INT8:
{
std::int8_t temp;
std::memcpy(&temp, value, sizeof(std::int8_t));
m_value.asInt = temp;
m_size = sizeof(std::int8_t);
break;
}
case PrimitiveType::INT16:
{
std::int16_t temp;
std::memcpy(&temp, value, sizeof(std::int16_t));
m_value.asInt = temp;
m_size = sizeof(std::int16_t);
break;
}
case PrimitiveType::INT32:
{
std::int32_t temp;
std::memcpy(&temp, value, sizeof(std::int32_t));
m_value.asInt = temp;
m_size = sizeof(std::int32_t);
break;
}
case PrimitiveType::INT64:
{
std::int64_t temp;
std::memcpy(&temp, value, sizeof(std::int64_t));
m_value.asInt = temp;
m_size = sizeof(std::int64_t);
break;
}
case PrimitiveType::UINT8:
{
std::uint8_t temp;
std::memcpy(&temp, value, sizeof(std::uint8_t));
m_value.asInt = temp;
m_size = sizeof(std::uint8_t);
break;
}
case PrimitiveType::UINT16:
{
std::uint16_t temp;
std::memcpy(&temp, value, sizeof(std::uint16_t));
m_value.asInt = temp;
m_size = sizeof(std::uint16_t);
break;
}
case PrimitiveType::UINT32:
{
std::uint32_t temp;
std::memcpy(&temp, value, sizeof(std::uint32_t));
m_value.asInt = temp;
m_size = sizeof(std::uint32_t);
break;
}
case PrimitiveType::UINT64:
{
std::uint64_t temp;
std::memcpy(&temp, value, sizeof(std::uint64_t));
m_value.asInt = temp;
m_size = sizeof(std::uint64_t);
break;
}
case PrimitiveType::FLOAT:
{
float temp;
std::memcpy(&temp, value, sizeof(float));
m_value.asDouble = temp;
m_size = sizeof(float);
break;
}
case PrimitiveType::DOUBLE:
{
double temp;
std::memcpy(&temp, value, sizeof(double));
m_value.asDouble = temp;
m_size = sizeof(double);
break;
}
default:
{
m_type = PrimitiveType::NONE;
m_size = 0;
break;
}
}
}
inline std::int64_t getAsInt() const
{
return m_value.asInt;
}
inline std::uint64_t getAsUInt() const
{
return m_value.asUInt;
}
inline double getAsDouble() const
{
return m_value.asDouble;
}
inline const char *getArray() const
{
return m_arrayValue.c_str(); // in C++11 data() and c_str() are equivalent and are null terminated after length
}
inline std::size_t size() const
{
return m_size;
}
inline PrimitiveType primitiveType() const
{
return m_type;
}
private:
PrimitiveType m_type;
std::size_t m_size;
union
{
std::int64_t asInt;
std::uint64_t asUInt;
double asDouble;
} m_value;
std::string m_arrayValue; // use this to store all the types, not just char arrays
};
class Encoding
{
public:
Encoding(
PrimitiveType type,
Presence presence,
ByteOrder byteOrder,
PrimitiveValue minValue,
PrimitiveValue maxValue,
PrimitiveValue nullValue,
PrimitiveValue constValue,
std::string characterEncoding,
std::string epoch,
std::string timeUnit,
std::string semanticType) :
m_presence(presence),
m_primitiveType(type),
m_byteOrder(byteOrder),
m_minValue(std::move(minValue)),
m_maxValue(std::move(maxValue)),
m_nullValue(std::move(nullValue)),
m_constValue(std::move(constValue)),
m_characterEncoding(std::move(characterEncoding)),
m_epoch(std::move(epoch)),
m_timeUnit(std::move(timeUnit)),
m_semanticType(std::move(semanticType))
{
}
static inline char getChar(const char *buffer)
{
return *(char *)buffer;
}
static inline std::int8_t getInt8(const char *buffer)
{
std::int8_t value;
std::memcpy(&value, buffer, sizeof(std::int8_t));
return value;
}
static inline std::int16_t getInt16(const char *buffer, const ByteOrder byteOrder)
{
std::int16_t value;
std::memcpy(&value, buffer, sizeof(std::int16_t));
return SBE_OTF_BYTE_ORDER_16(byteOrder, value);
}
static inline std::int32_t getInt32(const char *buffer, const ByteOrder byteOrder)
{
std::int32_t value;
std::memcpy(&value, buffer, sizeof(std::int32_t));
return SBE_OTF_BYTE_ORDER_32(byteOrder, value);
}
static inline std::int64_t getInt64(const char *buffer, const ByteOrder byteOrder)
{
std::int64_t value;
std::memcpy(&value, buffer, sizeof(std::int64_t));
return SBE_OTF_BYTE_ORDER_64(byteOrder, value);
}
static inline std::uint8_t getUInt8(const char *buffer)
{
std::uint8_t value;
std::memcpy(&value, buffer, sizeof(std::uint8_t));
return value;
}
static inline std::uint16_t getUInt16(const char *buffer, const ByteOrder byteOrder)
{
std::uint16_t value;
std::memcpy(&value, buffer, sizeof(std::uint16_t));
return SBE_OTF_BYTE_ORDER_16(byteOrder, value);
}
static inline std::uint32_t getUInt32(const char *buffer, const ByteOrder byteOrder)
{
std::uint32_t value;
std::memcpy(&value, buffer, sizeof(std::uint32_t));
return SBE_OTF_BYTE_ORDER_32(byteOrder, value);
}
static inline std::uint64_t getUInt64(const char *buffer, const ByteOrder byteOrder)
{
std::uint64_t value;
std::memcpy(&value, buffer, sizeof(std::uint64_t));
return SBE_OTF_BYTE_ORDER_64(byteOrder, value);
}
static inline float getFloat(const char *buffer, const ByteOrder byteOrder)
{
sbe_float_as_uint_t value;
std::memcpy(&value, buffer, sizeof(float));
value.uint_value = SBE_OTF_BYTE_ORDER_32(byteOrder, value.uint_value);
return value.fp_value;
}
static inline double getDouble(const char *buffer, const ByteOrder byteOrder)
{
sbe_double_as_uint_t value;
std::memcpy(&value, buffer, sizeof(double));
value.uint_value = SBE_OTF_BYTE_ORDER_64(byteOrder, value.uint_value);
return value.fp_value;
}
static inline std::int64_t getInt(const PrimitiveType type, const ByteOrder byteOrder, const char *buffer)
{
switch (type)
{
case PrimitiveType::CHAR:
return getChar(buffer);
case PrimitiveType::INT8:
return getInt8(buffer);
case PrimitiveType::INT16:
return getInt16(buffer, byteOrder);
case PrimitiveType::INT32:
return getInt32(buffer, byteOrder);
case PrimitiveType::INT64:
return getInt64(buffer, byteOrder);
default:
throw std::runtime_error("incorrect type for Encoding::getInt");
}
}
static inline std::uint64_t getUInt(const PrimitiveType type, const ByteOrder byteOrder, const char *buffer)
{
switch (type)
{
case PrimitiveType::UINT8:
return getUInt8(buffer);
case PrimitiveType::UINT16:
return getUInt16(buffer, byteOrder);
case PrimitiveType::UINT32:
return getUInt32(buffer, byteOrder);
case PrimitiveType::UINT64:
return getUInt64(buffer, byteOrder);
default:
throw std::runtime_error("incorrect type for Encoding::getUInt");
}
}
static inline double getDouble(const PrimitiveType type, const ByteOrder byteOrder, const char *buffer)
{
if (type == PrimitiveType::FLOAT)
{
return getFloat(buffer, byteOrder);
}
else if (type == PrimitiveType::DOUBLE)
{
return getDouble(buffer, byteOrder);
}
else
{
throw std::runtime_error("incorrect type for Encoding::getDouble");
}
}
inline Presence presence() const
{
return m_presence;
}
inline ByteOrder byteOrder() const
{
return m_byteOrder;
}
inline PrimitiveType primitiveType() const
{
return m_primitiveType;
}
inline std::int64_t getAsInt(const char *buffer) const
{
return getInt(m_primitiveType, m_byteOrder, buffer);
}
inline std::uint64_t getAsUInt(const char *buffer) const
{
return getUInt(m_primitiveType, m_byteOrder, buffer);
}
inline double getAsDouble(const char *buffer) const
{
return getDouble(m_primitiveType, m_byteOrder, buffer);
}
inline const PrimitiveValue &minValue() const
{
return m_minValue;
}
inline const PrimitiveValue &maxValue() const
{
return m_maxValue;
}
inline const PrimitiveValue &nullValue() const
{
return m_nullValue;
}
inline const PrimitiveValue &constValue() const
{
return m_constValue;
}
inline const std::string &characterEncoding() const
{
return m_characterEncoding;
}
inline const std::string &epoch() const
{
return m_epoch;
}
inline const std::string &timeUnit() const
{
return m_timeUnit;
}
inline const std::string &semanticType() const
{
return m_semanticType;
}
private:
const Presence m_presence;
const PrimitiveType m_primitiveType;
const ByteOrder m_byteOrder;
const PrimitiveValue m_minValue;
const PrimitiveValue m_maxValue;
const PrimitiveValue m_nullValue;
const PrimitiveValue m_constValue;
const std::string m_characterEncoding;
const std::string m_epoch;
const std::string m_timeUnit;
const std::string m_semanticType;
};
}}
#endif