Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for long double #75

Merged
merged 9 commits into from Apr 4, 2016
2 changes: 2 additions & 0 deletions src/leapserial/Archive.cpp
Expand Up @@ -39,6 +39,8 @@ const char* leap::ToString(serial_atom atom) {
return "f32";
case serial_atom::f64:
return "f64";
case serial_atom::f80:
return "f80";
case serial_atom::reference:
return "ref";
case serial_atom::array:
Expand Down
12 changes: 8 additions & 4 deletions src/leapserial/Archive.h
Expand Up @@ -63,6 +63,7 @@ namespace leap {
ui64,
f32,
f64,
f80,
reference,
array,
string,
Expand Down Expand Up @@ -136,12 +137,14 @@ namespace leap {
virtual void WriteInteger(int64_t value) { WriteInteger(value, sizeof(value)); }
virtual void WriteInteger(uint64_t value) { WriteInteger((int64_t)value, sizeof(value)); }

virtual void WriteFloat(float value) { WriteByteArray(&value, sizeof(float)); }
virtual void WriteFloat(double value) { WriteByteArray(&value, sizeof(double)); }
virtual void WriteFloat(float value) = 0;
virtual void WriteFloat(double value) = 0;
virtual void WriteFloat(long double value) = 0;

virtual uint64_t SizeInteger(int64_t value, uint8_t ncb) const = 0;
virtual uint64_t SizeFloat(float value) const = 0;
virtual uint64_t SizeFloat(double value) const = 0;
virtual uint64_t SizeFloat(long double value) const = 0;
virtual uint64_t SizeBool(bool value) const = 0;
virtual uint64_t SizeString(const void* pBuf, uint64_t ncb, uint8_t charSize) const = 0;

Expand Down Expand Up @@ -280,8 +283,9 @@ namespace leap {
/// It is an error for (value & ~(1 << (ncb * 8))) to be nonzero.
/// </remarks>
virtual uint64_t ReadInteger(uint8_t ncb) = 0;
virtual void ReadFloat(float& value) { ReadByteArray(&value, sizeof(float)); }
virtual void ReadFloat(double& value) { ReadByteArray(&value, sizeof(double)); }
virtual void ReadFloat(float& value) = 0;
virtual void ReadFloat(double& value) = 0;
virtual void ReadFloat(long double& value) = 0;
virtual void ReadDictionary(IDictionaryInserter&& dictionary) = 0;
};

Expand Down
71 changes: 42 additions & 29 deletions src/leapserial/ArchiveFlatbuffer.cpp
Expand Up @@ -13,14 +13,14 @@ using namespace leap;
//// https://google.github.io/flatbuffers/md__internals.html
///
/// offsets are always written as 32 bit integers
///
///
/// Structs are all aligned to their size and are written in order.
///
/// Tables start with soffset_t (a int32_t) to the vtable for the object,
/// followed by all fields as aligned scalars. not all fields need to be present.
///
///
/// Vtables are constructed of voffset_ts(a uint16_t).
///
///
/// Strings are vectors of bytes, always null terminated
/// vectors are stored as contiguous aligned scalars with a uint32_t element count.
/// The standard implementation writes buffers backwards as this reduces the amount
Expand All @@ -34,7 +34,7 @@ using namespace leap;
/// uint16_t size of object in bytes (including vtable offset)
/// for N elements in the vtable
/// uint16_t offset of Nth field
///
///

struct not_implemented_exception :
public std::runtime_error
Expand Down Expand Up @@ -133,7 +133,7 @@ void OArchiveFlatbuffer::WriteByteArray(const void* pBuf, uint64_t ncb, bool wri
throw not_implemented_exception();
}

void OArchiveFlatbuffer::WriteString(const void* pBuf, uint64_t charCount, uint8_t charSize) {
void OArchiveFlatbuffer::WriteString(const void* pBuf, uint64_t charCount, uint8_t charSize) {
if (charSize != 1)
throw std::runtime_error("Flatbuffers does not support non ASCII/UTF-8 strings");

Expand All @@ -152,29 +152,34 @@ void OArchiveFlatbuffer::WriteString(const void* pBuf, uint64_t charCount, uint8
SaveOffset(m_currentFieldPtr, (uint32_t)m_builder.size());
}

void OArchiveFlatbuffer::WriteBool(bool value) {
void OArchiveFlatbuffer::WriteBool(bool value) {
WriteInteger((uint8_t)value);
}

void OArchiveFlatbuffer::WriteInteger(int64_t value, uint8_t ncb) {
Align(ncb);

uint64_t bits = *reinterpret_cast<uint64_t*>(&value);
for (int i = ncb-1; i >= 0; --i) {
const uint8_t lowerBits = (uint8_t)(bits >> (i * 8) & 0x0000000000000FF);
m_builder.push_back(lowerBits);
}
}

void OArchiveFlatbuffer::WriteFloat(float value) {
void OArchiveFlatbuffer::WriteFloat(float value) {
WriteInteger(*reinterpret_cast<uint32_t*>(&value));
}

void OArchiveFlatbuffer::WriteFloat(double value) {
void OArchiveFlatbuffer::WriteFloat(double value) {
WriteInteger(*reinterpret_cast<uint64_t*>(&value));
}

void OArchiveFlatbuffer::WriteObjectReference(const field_serializer& serializer, const void* pObj) {
void OArchiveFlatbuffer::WriteFloat(long double value) {
for (size_t i = 0; i < sizeof(value); i++)
WriteInteger(reinterpret_cast<uint8_t*>(&value)[i]);
}

void OArchiveFlatbuffer::WriteObjectReference(const field_serializer& serializer, const void* pObj) {
throw not_implemented_exception();
}

Expand All @@ -192,7 +197,7 @@ void OArchiveFlatbuffer::WriteObject(const field_serializer& serializer, const v
Finish();
}

void OArchiveFlatbuffer::WriteDescriptor(const descriptor& descriptor, const void* pObj) {
void OArchiveFlatbuffer::WriteDescriptor(const descriptor& descriptor, const void* pObj) {

const auto orderedDescriptors = SortFields(descriptor);

Expand Down Expand Up @@ -221,7 +226,7 @@ void OArchiveFlatbuffer::WriteDescriptor(const descriptor& descriptor, const voi
}
vTable.offsets.push_back(static_cast<uint16_t>((uint32_t)m_builder.size() - tableEnd));
}

//If there are no identified descriptors, then we are a struct and do not care about vtable stuff.
if (descriptor.identified_descriptors.empty())
return;
Expand All @@ -235,7 +240,7 @@ void OArchiveFlatbuffer::WriteDescriptor(const descriptor& descriptor, const voi
vTable.offset = tableStart + vTable.size;

auto insertionResult = m_vTables.insert(vTable);

//Final entry for the table
WriteInteger((int32_t)(insertionResult.first->offset - tableStart));

Expand Down Expand Up @@ -278,47 +283,50 @@ void OArchiveFlatbuffer::WriteArray(IArrayReader&& ary) {
}

void OArchiveFlatbuffer::WriteDictionary(IDictionaryReader&& dictionary)
{
{
throw not_implemented_exception();
}

uint64_t OArchiveFlatbuffer::SizeInteger(int64_t value, uint8_t ncb) const {
uint64_t OArchiveFlatbuffer::SizeInteger(int64_t value, uint8_t ncb) const {
return ncb;
}
uint64_t OArchiveFlatbuffer::SizeFloat(float value) const {
uint64_t OArchiveFlatbuffer::SizeFloat(float value) const {
return sizeof(float);
}
uint64_t OArchiveFlatbuffer::SizeFloat(double value) const {
uint64_t OArchiveFlatbuffer::SizeFloat(double value) const {
return sizeof(double);
}
uint64_t OArchiveFlatbuffer::SizeBool(bool value) const {
uint64_t OArchiveFlatbuffer::SizeFloat(long double value) const {
return sizeof(long double);
}
uint64_t OArchiveFlatbuffer::SizeBool(bool value) const {
return sizeof(bool);
}
uint64_t OArchiveFlatbuffer::SizeString(const void* pBuf, uint64_t ncb, uint8_t charSize) const {
uint64_t OArchiveFlatbuffer::SizeString(const void* pBuf, uint64_t ncb, uint8_t charSize) const {
return sizeof(uint32_t);
}
uint64_t OArchiveFlatbuffer::SizeObjectReference(const field_serializer& serializer, const void* pObj) const {
uint64_t OArchiveFlatbuffer::SizeObjectReference(const field_serializer& serializer, const void* pObj) const {
return sizeof(uint32_t);
}
uint64_t OArchiveFlatbuffer::SizeDescriptor(const descriptor& descriptor, const void* pObj) const {
uint64_t OArchiveFlatbuffer::SizeDescriptor(const descriptor& descriptor, const void* pObj) const {
// If stored as a struct, return the size of the struct
if (descriptor.identified_descriptors.empty()) {
uint64_t size = 0;
for (const auto& field_descriptor : descriptor.field_descriptors)
size += field_descriptor.serializer.size(*this, pObj);
return size;
}

// If stored as a table, return the offset size.
return sizeof(uint32_t);
}

uint64_t OArchiveFlatbuffer::SizeArray(IArrayReader&& ary) const {
uint64_t OArchiveFlatbuffer::SizeArray(IArrayReader&& ary) const {
return sizeof(uint32_t);
}

uint64_t OArchiveFlatbuffer::SizeDictionary(IDictionaryReader&& dictionary) const
{
{
throw not_implemented_exception();
}

Expand All @@ -339,7 +347,7 @@ void IArchiveFlatbuffer::ReadObject(const field_serializer& sz, void* pObj, inte
sz.deserialize(*this, pObj, 0); //The root entry is an offset to a table.
}

IArchive::ReleasedMemory IArchiveFlatbuffer::ReadObjectReferenceResponsible(IArchive::ReleasedMemory(*pfnAlloc)(), const field_serializer& sz, bool isUnique) {
IArchive::ReleasedMemory IArchiveFlatbuffer::ReadObjectReferenceResponsible(IArchive::ReleasedMemory(*pfnAlloc)(), const field_serializer& sz, bool isUnique) {
throw not_implemented_exception();
}

Expand Down Expand Up @@ -390,7 +398,7 @@ void IArchiveFlatbuffer::ReadByteArray(void* pBuf, uint64_t ncb) {
void IArchiveFlatbuffer::ReadString(std::function<void*(uint64_t)> getBufferFn, uint8_t charSize, uint64_t ncb) {
const auto baseOffset = m_offset;
const auto stringOffset = baseOffset + GetValue<uint32_t>(baseOffset);

const auto size = GetValue<uint32_t>(stringOffset);

auto* dstString = getBufferFn(size);
Expand All @@ -400,9 +408,9 @@ void IArchiveFlatbuffer::ReadString(std::function<void*(uint64_t)> getBufferFn,
m_offset = baseOffset + sizeof(uint32_t);
}

bool IArchiveFlatbuffer::ReadBool() {
bool IArchiveFlatbuffer::ReadBool() {
const auto offset = m_offset;
m_offset += sizeof(uint8_t);
m_offset += sizeof(uint8_t);
return !!GetValue<uint8_t>(offset);
}

Expand Down Expand Up @@ -430,7 +438,12 @@ void IArchiveFlatbuffer::ReadFloat(float& value) {

void IArchiveFlatbuffer::ReadFloat(double& value) {
value = GetValue<double>(m_offset);
m_offset += sizeof(float);
m_offset += sizeof(double);
}

void IArchiveFlatbuffer::ReadFloat(long double& value) {
value = GetValue<long double>(m_offset);
m_offset += sizeof(long double);
}

void IArchiveFlatbuffer::ReadArray(IArrayAppender&& ary) {
Expand Down
3 changes: 3 additions & 0 deletions src/leapserial/ArchiveFlatbuffer.h
Expand Up @@ -44,6 +44,7 @@ namespace leap {
using OArchive::WriteInteger;
void WriteFloat(float value) override;
void WriteFloat(double value) override;
void WriteFloat(long double value) override;
void WriteObjectReference(const field_serializer& serializer, const void* pObj) override;
void WriteObject(const field_serializer& serializer, const void* pObj) override;
void WriteDescriptor(const descriptor& descriptor, const void* pObj) override;
Expand All @@ -55,6 +56,7 @@ namespace leap {
uint64_t SizeInteger(int64_t value, uint8_t ncb) const override;
uint64_t SizeFloat(float value) const override;
uint64_t SizeFloat(double value) const override;
uint64_t SizeFloat(long double value) const override;
uint64_t SizeBool(bool value) const override;
uint64_t SizeString(const void* pBuf, uint64_t ncb, uint8_t charSize) const override;
uint64_t SizeObjectReference(const field_serializer& serializer, const void* pObj) const override;
Expand Down Expand Up @@ -105,6 +107,7 @@ namespace leap {
uint64_t ReadInteger(uint8_t ncb) override;
void ReadFloat(float& value) override;
void ReadFloat(double& value) override;
void ReadFloat(long double& value) override;
void ReadArray(IArrayAppender&& ary) override;
void ReadDictionary(IDictionaryInserter&& dictionary) override;

Expand Down
15 changes: 11 additions & 4 deletions src/leapserial/ArchiveJSON.cpp
Expand Up @@ -67,18 +67,22 @@ void OArchiveJSON::WriteInteger(uint64_t value) {
os << value;
}

void OArchiveJSON::WriteFloat(float value) {
void OArchiveJSON::WriteInteger(int64_t value, uint8_t) {
os << value;
}

void OArchiveJSON::WriteInteger(int64_t value, uint8_t) {
void OArchiveJSON::WriteFloat(float value) {
os << value;
}

void OArchiveJSON::WriteFloat(double value) {
os << value;
}

void OArchiveJSON::WriteFloat(long double value) {
os << value;
}

void OArchiveJSON::WriteObjectReference(const field_serializer& serializer, const void* pObj) {
throw not_implemented_exception();
}
Expand All @@ -103,7 +107,7 @@ void OArchiveJSON::WriteDescriptor(const descriptor& descriptor, const void* pOb
os << "\"" << field_descriptor.name << "\":";
if (PrettyPrint)
os << ' ';

const void* pChildObj = pBase + field_descriptor.offset;
field_descriptor.serializer.serialize(*this, pChildObj);

Expand Down Expand Up @@ -162,6 +166,9 @@ uint64_t OArchiveJSON::SizeFloat(float value) const {
uint64_t OArchiveJSON::SizeFloat(double value) const {
throw not_implemented_exception();
}
uint64_t OArchiveJSON::SizeFloat(long double value) const {
throw not_implemented_exception();
}
uint64_t OArchiveJSON::SizeBool(bool value) const {
throw not_implemented_exception();
}
Expand Down Expand Up @@ -194,7 +201,7 @@ void OArchiveJSON::TabOut(void) const {
}

IArchiveJSON::IArchiveJSON(std::istream& is) {

}

void IArchiveJSON::Skip(uint64_t ncb) {
Expand Down
4 changes: 3 additions & 1 deletion src/leapserial/ArchiveJSON.h
Expand Up @@ -38,6 +38,7 @@ namespace leap {
void WriteInteger(uint64_t value) override;
void WriteFloat(float value) override;
void WriteFloat(double value) override;
void WriteFloat(long double value) override;
void WriteObjectReference(const field_serializer& serializer, const void* pObj) override;
void WriteObject(const field_serializer& serializer, const void* pObj) override;
void WriteDescriptor(const descriptor& descriptor, const void* pObj) override;
Expand All @@ -49,6 +50,7 @@ namespace leap {
uint64_t SizeInteger(int64_t value, uint8_t ncb) const override;
uint64_t SizeFloat(float value) const override;
uint64_t SizeFloat(double value) const override;
uint64_t SizeFloat(long double value) const override;
uint64_t SizeBool(bool value) const override;
uint64_t SizeString(const void* pBuf, uint64_t ncb, uint8_t charSize) const override;
uint64_t SizeObjectReference(const field_serializer& serializer, const void* pObj) const override;
Expand All @@ -60,7 +62,7 @@ namespace leap {
// Current tab level, if pretty printing is turned on, otherwise ignored
size_t currentTabLevel = 0;
std::ostream& os;

// Prints TabLevel spaces to the output stream
void TabOut(void) const;
};
Expand Down
5 changes: 3 additions & 2 deletions src/leapserial/IArchiveImpl.h
Expand Up @@ -104,8 +104,9 @@ namespace leap {
void ReadString(std::function<void*(uint64_t)> getBufferFn, uint8_t charSize, uint64_t ncb) override;
bool ReadBool() override;
uint64_t ReadInteger(uint8_t ncb) override;
void ReadFloat(float& value) override { ReadByteArray(&value, sizeof(float)); }
void ReadFloat(double& value) override { ReadByteArray(&value, sizeof(double)); }
void ReadFloat(float& value) override { ReadByteArray(&value, sizeof(value)); }
void ReadFloat(double& value) override { ReadByteArray(&value, sizeof(value)); }
void ReadFloat(long double& value) override { ReadByteArray(&value, sizeof(value)); }
void ReadDescriptor(const descriptor& descriptor, void* pObj, uint64_t ncb) override;
void ReadArray(IArrayAppender&& ary) override;
void ReadDictionary(IDictionaryInserter&& dictionary) override;
Expand Down
14 changes: 14 additions & 0 deletions src/leapserial/IArchiveProtobuf.cpp
Expand Up @@ -114,6 +114,20 @@ uint64_t IArchiveProtobuf::ReadInteger(uint8_t) {
return leap::FromBase128(buf, ncb);
}

void IArchiveProtobuf::ReadFloat(float& value) {
is.Read(&value, sizeof(value));
}

void IArchiveProtobuf::ReadFloat(double& value) {
is.Read(&value, sizeof(value));
}

void IArchiveProtobuf::ReadFloat(long double& value) {
double temp;
ReadFloat(temp);
value = temp;
}

void IArchiveProtobuf::ReadArray(IArrayAppender&& ary) {
// Protobuf array deserialization is funny, it's just a bunch of single entries repeated
// over and over again.
Expand Down