Doesn't build or work at all on MSVC
mlfarrell opened this issue · 3 comments
mlfarrell commented
I thought this was supposed to be a portable library.
mlfarrell commented
I took a sledgehammer to this problem today. I have no idea if I broke anything yet. But at least it builds.
Patch attached below. Paths won't be correct so I didn't make a PR
You may want to stop using " or " "and " and " not " in place of && || and !. Honestly, I have absolutely no idea how that ever compiled correctly in the first place.
From 70faf0f7843efa50b08e6bbbdfb7e0bf1d89a2a3 Mon Sep 17 00:00:00 2001
From: Mike Farrell <@gmail.com>
Date: Wed, 18 Jul 2018 17:53:09 -0700
Subject: [PATCH] - get the UbjsonCpp lib to build on MSVC (regression risks,
here, will need to test again on iOS)
---
.../UbjsonCpp/include/Ubjson/portable_endian.h | 38 +-
.../UbjsonCpp/include/Ubjson/stream_helpers.hpp | 2 +-
.../UbjsonCpp/include/Ubjson/stream_reader.hpp | 18 +-
.../UbjsonCpp/include/Ubjson/stream_writer.hpp | 16 +-
.../3rd Party/UbjsonCpp/include/Ubjson/types.hpp | 9 +-
.../3rd Party/UbjsonCpp/include/Ubjson/value.cpp | 936 +++++++++++++++++++++
.../3rd Party/UbjsonCpp/include/Ubjson/value.hpp | 2 +-
7 files changed, 998 insertions(+), 23 deletions(-)
create mode 100644 BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/value.cpp
diff --git a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/portable_endian.h b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/portable_endian.h
index 05f8861..3364d75 100644
--- a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/portable_endian.h
+++ b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/portable_endian.h
@@ -74,8 +74,11 @@
#elif defined(__WINDOWS__)
-# include <winsock2.h>
+# include <Winsock2.h>
+#ifndef _MSC_VER
# include <sys/param.h>
+#else
+#endif
# if BYTE_ORDER == LITTLE_ENDIAN
@@ -89,10 +92,43 @@
# define be32toh(x) ntohl(x)
# define le32toh(x) (x)
+//these simply will...not...work..
+#ifdef _MSC_VER
+uint64_t ___ntohll(uint64_t x)
+{
+ uint32_t x0, x1, y0, y1;
+
+ if(ntohl(1) == 1)
+ {
+ return x;
+ }
+
+ x0 = x & 0xffffffff;
+ y0 = ntohl(x0);
+ x1 = x >> 32;
+ y1 = ntohl(x1);
+ return ((uint64_t)y0 << 32) | y1;
+}
+
+uint64_t ___htonll(uint64_t n)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+ return n;
+#else
+ return (((uint64_t)htonl(n)) << 32) + htonl(n >> 32);
+#endif
+}
+
+# define htobe64(x) ___htonll(x)
+# define htole64(x) (x)
+# define be64toh(x) ___ntohll(x)
+# define le64toh(x) (x)
+#else
# define htobe64(x) htonll(x)
# define htole64(x) (x)
# define be64toh(x) ntohll(x)
# define le64toh(x) (x)
+#endif
# elif BYTE_ORDER == BIG_ENDIAN
diff --git a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_helpers.hpp b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_helpers.hpp
index 6e0be52..74e61d5 100755
--- a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_helpers.hpp
+++ b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_helpers.hpp
@@ -37,7 +37,7 @@ namespace ubjson {
}
inline bool in_range(double value, double min, double max)
- { return (min <= value and value <= max); }
+ { return (min <= value && value <= max); }
inline
uint16_t toBigEndian16(uint16_t val)
diff --git a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_reader.hpp b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_reader.hpp
index b8e3ab5..3a06a94 100755
--- a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_reader.hpp
+++ b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_reader.hpp
@@ -89,7 +89,7 @@ namespace ubjson {
std::enable_if_t<std::is_base_of<std::istream, U>::value, bool> read_from_stream(byte*, std::size_t, bool peek = false);
template<typename U = StreamType>
- std::enable_if_t<not std::is_base_of<std::istream, U>::value, bool> read_from_stream(byte*, std::size_t, bool peek = false);
+ std::enable_if_t<! std::is_base_of<std::istream, U>::value, bool> read_from_stream(byte*, std::size_t, bool peek = false);
//decltype(std::declval<U>().peek(), std::true_type()()) read_from_stream(byte*, std::size_t);
std::pair<byte, bool> peeked_byte;
@@ -179,7 +179,7 @@ namespace ubjson {
template<typename StreamType>
- template<typename U> std::enable_if_t<not std::is_base_of<std::istream, U>::value, bool>
+ template<typename U> std::enable_if_t<! std::is_base_of<std::istream, U>::value, bool>
StreamReader<StreamType>::read_from_stream(byte* b, std::size_t sz, bool peek)
{
using std::to_string;
@@ -190,7 +190,7 @@ namespace ubjson {
if(bytes_so_far + sz > vsz.max_object_size)
throw policy_violation("Maximum Object size read at: " + to_string(bytes_so_far));
- if(peek and peeked_byte.second)
+ if(peek && peeked_byte.second)
{
b[0] = peeked_byte.first;
b = b + 1;
@@ -223,9 +223,9 @@ namespace ubjson {
decltype(KeyMarker::marker) marker;
KeyMarker km;
- while ( (not header.is_valid) or (header.is_valid and header.item_count > 0)) {
+ while ( (! header.is_valid) || (header.is_valid && header.item_count > 0)) {
- if(not header.is_valid and is_container_end(type, peekNextByte()))
+ if(! header.is_valid && is_container_end(type, peekNextByte()))
{
readNextByte(); //peel it off the stream
break;
@@ -246,7 +246,7 @@ namespace ubjson {
break;
}
- if(header.marker != Marker::Invalid and header.is_valid)
+ if(header.marker != Marker::Invalid && header.is_valid)
marker = km.marker;
else
marker = readNextByte();
@@ -428,7 +428,7 @@ namespace ubjson {
{
byte b = readNextByte();
- if(isUint8(b) and read_uint8)
+ if(isUint8(b) && read_uint8)
{
auto rtn = extract_Uint8();
return std::make_pair(rtn.first, rtn.second);
@@ -491,7 +491,7 @@ namespace ubjson {
std::pair<std::string, bool> StreamReader<StreamType>::extract_String()
{
auto icount = extract_itemCount();
- if(not icount.second)
+ if(!icount.second)
return std::make_pair(std::string(), false);
std::unique_ptr<byte[]> b(new byte[icount.first]);
@@ -505,7 +505,7 @@ namespace ubjson {
std::pair<Value::BinaryType, bool> StreamReader<StreamType>::extract_Binary()
{
auto icount = extract_itemCount();
- if(not icount.second)
+ if(!icount.second)
throw parsing_exception("Invalid count token encounted!");
std::unique_ptr<byte[]> b(new byte[icount.first]);
diff --git a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_writer.hpp b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_writer.hpp
index a20596c..3f3a0b3 100755
--- a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_writer.hpp
+++ b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/stream_writer.hpp
@@ -240,8 +240,8 @@ namespace ubjson {
else if(in_range(val, Int16::lowest(), Int16::max()))
{
const uint16_t tit = static_cast<uint16_t>(val);
- const uint16_t val = toBigEndian16(tit);
- std::memcpy(b, &val, 2);
+ const uint16_t temp = toBigEndian16(tit);
+ std::memcpy(b, &temp, 2);
write(Marker::Int16);
write(b, 2);
rtn = std::make_pair(3, true);
@@ -249,8 +249,8 @@ namespace ubjson {
else if(in_range(val, Int32::lowest(), Int32::max()))
{
const uint32_t tit = static_cast<uint32_t>(val);
- const uint32_t val = toBigEndian32(tit);
- std::memcpy(b, &val, 4);
+ const uint32_t temp = toBigEndian32(tit);
+ std::memcpy(b, &temp, 4);
write(Marker::Int32);
write(b, 4);
rtn = std::make_pair(5, true);
@@ -258,8 +258,8 @@ namespace ubjson {
else if(in_range(val, Int64::lowest(), Int64::max()))
{
const uint64_t tit = static_cast<uint64_t>(val);
- const uint64_t val = toBigEndian64(tit);
- std::memcpy(b, &val, 8);
+ const uint64_t temp = toBigEndian64(tit);
+ std::memcpy(b, &temp, 8);
write(Marker::Int64);
write(b, 8);
rtn = std::make_pair(9, true);
@@ -282,8 +282,8 @@ namespace ubjson {
//const uint32_t val = toBigEndianFloat32(static_cast<float>(val));
float temp = static_cast<float>(val); //Walkaround
- const uint32_t val = toBigEndianFloat32(temp); //Walkaround
- std::memcpy(b, &val, 4);
+ const uint32_t temp2 = toBigEndianFloat32(temp); //Walkaround
+ std::memcpy(b, &temp2, 4);
write(Marker::Float32);
write(b, 4);
rtn = std::make_pair(5, true);
diff --git a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/types.hpp b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/types.hpp
index 2fbc57e..42b8db0 100755
--- a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/types.hpp
+++ b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/types.hpp
@@ -101,7 +101,8 @@ namespace ubjson {
constexpr bool isSignedNumber(byte b)
- { return isInt16(b) or isInt32(b) or isInt64(b); }
+ { return isInt16(b) || isInt32(b) || isInt64(b); }
+ //{ return isInt16(b) or isInt32(b) or isInt64(b); }
constexpr bool isNumber(byte b)
{ return isSignedNumber(b); }
@@ -128,10 +129,12 @@ namespace ubjson {
{ return b == Marker::Optimized_Count; }
constexpr bool isOptimizedMarker(byte b)
- { return isOptimized_Count(b) or isOptimized_Type(b); }
+ { return isOptimized_Count(b) || isOptimized_Type(b); }
+ //{ return isOptimized_Count(b) or isOptimized_Type(b); }
constexpr bool requiresPayload(byte b)
- { return isObjectStart(b) or isString(b) or isBinary(b) or isArrayStart(b); }
+ { return isObjectStart(b) || isString(b) || isBinary(b) || isArrayStart(b); }
+ //{ return isObjectStart(b) or isString(b) or isBinary(b) or isArrayStart(b); }
static_assert(sizeof(byte) == 1, "a byte must be exactly one byte(8 bits)");
diff --git a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/value.cpp b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/value.cpp
new file mode 100644
index 0000000..992b71c
--- /dev/null
+++ b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/value.cpp
@@ -0,0 +1,936 @@
+#include "pch.h"
+
+/*
+ * Copyright(C): WhiZTiM, 2015
+ *
+ * This file is part of the TIML::UBJSON C++14 library
+ *
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Author: Ibrahim Timothy Onogu
+ * Email: ionogu@acm.org
+ */
+
+
+#include "value.hpp"
+#include <cmath>
+#include <limits>
+#include <cstring>
+#include <algorithm>
+#include <iostream>
+
+using namespace ubjson;
+
+///////////////// FREE FUNCTIONS
+template<typename T>
+T unique_ptr_copy(const T& src);
+
+template<>
+inline Value::ArrayType unique_ptr_copy(const Value::ArrayType& src)
+{
+ Value::ArrayType rtn;
+ for(auto& v : src)
+ rtn.emplace_back( std::make_unique<Value>(*v) );
+ rtn.shrink_to_fit();
+ return rtn;
+}
+
+template<>
+inline Value::MapType unique_ptr_copy(const Value::MapType& src)
+{
+ Value::MapType rtn;
+ for(auto& v : src)
+ rtn.emplace( std::make_pair(v.first, std::make_unique<Value>(*(v.second)) ));
+ return rtn;
+}
+
+inline bool in_range(double value, double min, double max)
+{ return (min <= value && value <= max); }
+
+inline bool is_equal(const Value::MapType& lhs, const Value::MapType& rhs)
+{
+ if(lhs.size() != rhs.size()) //edge case
+ return false;
+
+ for(const auto& val : lhs)
+ {
+ if(rhs.find(val.first) == rhs.end())
+ return false;
+ if(! (*(lhs.at(val.first)) == *(rhs.at(val.first))))
+ return false;
+ }
+ return true;
+}
+
+inline bool is_equal(const Value::ArrayType& lhs, const Value::ArrayType& rhs)
+{
+ return std::equal(lhs.begin(), lhs.end(),
+ rhs.begin(), rhs.end(),
+ []( const Value::Uptr& lhss, const Value::Uptr& rhss )
+ { return *lhss == *rhss; }
+ );
+}
+
+//////////////// VALUE IMpl
+
+
+Value::Value()
+ : vtype(Type::Null)
+{ }
+
+Value::Value(char c)
+ : vtype(Type::Char)
+{ value.Char = c; }
+
+Value::Value(bool b)
+ : vtype(Type::Bool)
+{ value.Bool = b; }
+
+Value::Value(long long ll)
+ : vtype(Type::SignedInt)
+{ value.SignedInt = ll; }
+
+Value::Value(int i)
+ : Value(static_cast<long long>(i))
+{ /**/ }
+
+Value::Value(unsigned long long ull)
+ : vtype(Type::UnsignedInt)
+{ value.UnsignedInt = ull; }
+
+Value::Value(double d)
+ : vtype(Type::Float)
+{ value.Float = d; }
+
+Value::Value(BinaryType b)
+ : vtype(Type::Binary)
+{ construct_fromBinary(std::move(b)); }
+
+Value::Value(std::string s)
+ : vtype(Type::String)
+{ construct_fromString(std::move(s)); }
+
+Value::Value(const char* c)
+ : Value(std::string(c))
+{ /**/ }
+
+Value::Value(std::initializer_list<Value> v)
+ : Value() //I suffered a setback here... explanation below
+{
+ if(v.size() == 1)
+ {
+ copy_from(*v.begin());
+ return;
+ }
+ for(auto a : v)
+ push_back( std::move(a) );
+// The bug was the fact that I didn't call the default constructor( basically initializes vtype=Type::Null)
+// Thus, the move was failing in optimized builds
+// Lesson: learn to use in-class default construction to maintain a first-class construction invariant
+}
+
+Value::Value(const std::string& key, Value val)
+ : Value()
+{
+ operator[](key) = val;
+}
+
+
+Value::Value(Value&& v)
+ : Value()
+{ move_from(std::move(v)); }
+
+Value::Value(const Value& v)
+ : Value()
+{ copy_from(v); }
+
+
+Value& Value::operator = (const Value& v)
+{
+ if(this == &v)
+ return *this;
+ copy_from(v);
+ return *this;
+}
+
+Value& Value::operator = (Value&& v)
+{
+ move_from(std::move(v));
+ return *this;
+}
+
+
+Value::~Value()
+{
+ destruct();
+}
+
+size_t Value::size() const noexcept
+{
+ switch (vtype) {
+ case Type::Null:
+ return 0;
+ case Type::Array:
+ return value.Array.size();
+ case Type::Map:
+ return value.Map.size();
+ default:
+ return 1;
+ }
+}
+
+Type Value::type() const noexcept
+{ return vtype; }
+
+Value& Value::operator [] (int i)
+{
+ if(vtype == Type::Array)
+ return *(value.Array[i]);
+ throw value_exception("Attempt to index 'Value'; 'Value' is not an Array!");
+}
+
+Value const& Value::operator [] (int i) const
+{
+ if(vtype == Type::Array)
+ return *(value.Array[i]);
+ throw value_exception("Attempt to index 'Value const&'; 'Value const&' is not an Array!");
+}
+
+Value& Value::operator [] (const std::string& s)
+{
+ if(vtype == Type::Map)
+ {
+ if(value.Map.find(s) == value.Map.end())
+ value.Map.emplace( std::make_pair(s, std::make_unique<Value>(Value())));
+ return *(value.Map[s]);
+ }
+ if(vtype == Type::Null)
+ {
+ // convert to Map
+ destruct();
+ construct_fromMap(MapType());
+ vtype = Type::Map;
+ value.Map.emplace( std::make_pair(s, std::make_unique<Value>(Value())));
+ return *(value.Map[s]);
+ }
+ throw value_exception("Attempt to index 'Value'; 'Value' is not a Key-Value pair (aka Object) !");
+}
+
+Value const& Value::operator [] (const std::string& s) const
+{
+ if(vtype == Type::Map)
+ return *(const_cast<const MapType&>(value.Map).at(s));
+ throw value_exception("Attempt to index 'Value const&'; 'Value const&' is not a Key-Value pair (aka Object) !");
+}
+
+Value& Value::operator [] (const char* c)
+{ return operator [] (std::string(c)); }
+
+Value const& Value::operator [] (const char* c) const
+{ return operator [] (std::string(c)); }
+
+void Value::push_back(Value&& v)
+{
+ switch (vtype) {
+ case Type::Null:
+ construct_fromArray(ArrayType());
+ vtype = Type::Array;
+ case Type::Array:
+ value.Array.emplace_back( std::make_unique<Value>( std::move(v) ) );
+ break;
+ default:
+ {
+ Value tmp(std::move(*this));
+ construct_fromArray(ArrayType());
+ value.Array.emplace_back(std::make_unique<Value>( std::move(tmp) ));
+ value.Array.emplace_back(std::make_unique<Value>( std::move(v) ));
+ vtype = Type::Array;
+ break;
+ }
+
+ }
+}
+
+void Value::push_back(const Value& v)
+{
+ switch (vtype) {
+ case Type::Null:
+ construct_fromArray(ArrayType());
+ vtype = Type::Array;
+ case Type::Array:
+ value.Array.emplace_back( std::make_unique<Value>(v) );
+ break;
+ default:
+ {
+ Value tmp(std::move(*this));
+ construct_fromArray(ArrayType());
+ value.Array.emplace_back(std::make_unique<Value>( std::move(tmp) ));
+ value.Array.emplace_back(std::make_unique<Value>( v ));
+ vtype = Type::Array;
+ break;
+ }
+
+ }
+}
+
+void Value::remove(const Value& v)
+{
+ switch (vtype) {
+ case Type::Array:
+ {
+ auto it = std::find_if(value.Array.begin(), value.Array.end(),
+ [&v](const auto& m){ return v == *m; } );
+ if(it != value.Array.end() )
+ value.Array.erase(it);
+ break;
+ }
+ case Type::Map:
+ value.Map.erase(v.asString());
+ default:
+ break;
+ }
+}
+
+Value::iterator Value::find(const Value& v)
+{
+ switch (vtype) {
+ case Type::Array:
+ {
+ auto it = std::find_if(value.Array.begin(), value.Array.end(),
+ [&v](const auto& m){ return v == *m; } );
+ if(it == value.Array.end() )
+ return end();
+ return iterator(this, it);
+ }
+ case Type::Map:
+ {
+ auto it = value.Map.find(v.asString());
+ if(it == value.Map.end())
+ return end();
+ return iterator(this, it);
+ }
+ default:
+ break;
+ }
+ return end();
+}
+
+
+Value::const_iterator Value::find(const Value& v) const
+{
+ switch (vtype) {
+ case Type::Array:
+ {
+ auto it = std::find_if(value.Array.begin(), value.Array.end(),
+ [&v](const auto& m){ return v == *m; } );
+ if(it == value.Array.end() )
+ return end();
+ return const_iterator(this, it);
+ }
+ case Type::Map:
+ {
+ auto it = value.Map.find(v);
+ if(it == value.Map.end())
+ return end();
+ return const_iterator(this, it);
+ }
+ default:
+ break;
+ }
+ return end();
+}
+
+bool Value::contains(const Value& v) const
+{ return find(v) != end(); }
+
+Value::Keys Value::keys() const
+{
+ if(! isMap())
+ return Keys();
+
+ Keys rtn;
+ for(const auto& k : value.Map)
+ rtn.push_back( k.first );
+ return rtn;
+}
+
+bool Value::isNull() const noexcept { return vtype == Type::Null; }
+bool Value::isArray() const noexcept { return vtype == Type::Array; }
+bool Value::isBinary() const noexcept { return vtype == Type::Binary; }
+bool Value::isBool() const noexcept { return vtype == Type::Bool; }
+bool Value::isChar() const noexcept { return vtype == Type::Char; }
+bool Value::isFloat() const noexcept { return vtype == Type::Float; }
+bool Value::isMap() const noexcept { return vtype == Type::Map; }
+bool Value::isString() const noexcept { return vtype == Type::String; }
+bool Value::isSignedInteger() const noexcept { return vtype == Type::SignedInt; }
+bool Value::isUnsignedInteger() const noexcept { return vtype == Type::UnsignedInt; }
+bool Value::isObject() const noexcept { return isMap(); }
+bool Value::isNumeric() const noexcept { return isInteger() || isFloat(); }
+bool Value::isInteger() const noexcept { return isSignedInteger() || isUnsignedInteger(); }
+
+bool Value::isComparableWith(const Value &rhs) const noexcept
+{
+ if(type() == rhs.type())
+ return true;
+ return (isNumeric() && rhs.isNumeric());
+}
+
+
+//////////////// as<...> functions //////
+///
+///
+//////////////////////////
+
+long long Value::asInt64() const noexcept
+{
+ using limit = std::numeric_limits<long long>;
+
+ if(isSignedInteger())
+ return value.SignedInt;
+ if(isUnsignedInteger())
+ return in_range(value.UnsignedInt, limit::lowest(), limit::max()) ? value.UnsignedInt : 0;
+ if(isFloat())
+ return in_range(value.Float, limit::lowest(), limit::max()) ? value.Float : 0;
+
+ if(isChar())
+ return static_cast<long long>(value.Char);
+ if(isBool())
+ return value.Bool ? 1 : 0;
+ if(isString())
+ {
+ try { return std::stoll(value.String); }
+ catch (std::invalid_argument&) {}
+ catch (std::out_of_range&) {}
+ return 0;
+ }
+ return size();
+}
+
+
+unsigned long long Value::asUint64() const noexcept
+{
+ using limit = std::numeric_limits<unsigned long long>;
+
+ if(isUnsignedInteger())
+ return value.UnsignedInt;
+ if(isSignedInteger())
+ return in_range(value.SignedInt, limit::lowest(), limit::max()) ? value.SignedInt : 0;
+ if(isFloat())
+ return in_range(value.Float, limit::lowest(), limit::max()) ? value.Float : 0;
+ if(isChar())
+ return static_cast<unsigned long long>(value.Char);
+ if(isBool())
+ return value.Bool ? 1 : 0;
+ if(isString())
+ {
+ try { return std::stoull(value.String); }
+ catch (std::invalid_argument&) {}
+ catch (std::out_of_range&) {}
+ return 0;
+ }
+
+ return size();
+}
+
+double Value::asFloat() const noexcept
+{
+
+ if(isFloat())
+ return value.Float;
+ if(isString())
+ {
+ try { return std::stod(value.String); }
+ catch (std::invalid_argument&) {}
+ catch (std::out_of_range&) {}
+ return 0;
+ }
+
+ double k1 = asUint64();
+ double k2 = asInt64();
+
+ return k1 > k2 ? k1 : k2;
+}
+
+bool Value::asBool() const noexcept
+{
+ if(isBool())
+ return value.Bool;
+ if(isUnsignedInteger())
+ return value.UnsignedInt != 0;
+ if(isSignedInteger())
+ return value.SignedInt != 0;
+ if(isFloat())
+ return value.Float != 0;
+ if(isChar())
+ return value.Char != '\0';
+ return size() != 0;
+}
+
+int Value::asInt() const noexcept
+{
+ using limit = std::numeric_limits<int>;
+ return in_range(asInt64(), limit::lowest(), limit::max()) ? (int)asInt64() : 0;
+}
+
+unsigned int Value::asUint() const noexcept
+{
+ using limit = std::numeric_limits<unsigned int>;
+ return in_range(asUint64(), limit::lowest(), limit::max()) ? (unsigned int)asUint64() : 0;
+}
+
+std::string Value::asString() const noexcept
+{
+ if(isString())
+ return value.String;
+ if(isBool())
+ return value.Bool ? "true" : "false";
+ // if(isBinary())
+ //What should we do for Binary? Base64? or what?
+ if(isChar())
+ return {value.Char};
+ if(isSignedInteger())
+ return std::to_string(value.SignedInt);
+ if(isUnsignedInteger())
+ return std::to_string(value.UnsignedInt);
+ if(isFloat())
+ return std::to_string(value.Float);
+ return "";
+}
+
+inline Value::BinaryType as_binary(const void* src, size_t size)
+{
+ Value::BinaryType rtn(size);
+ std::memcpy(&rtn[0], src, size);
+ return rtn;
+}
+
+Value::BinaryType Value::asBinary() const noexcept
+{
+ if(isBinary())
+ return value.Binary;
+ switch (vtype) {
+ case Type::Char:
+ return as_binary(&value.Char, sizeof(value.Char));
+ case Type::Bool:
+ return as_binary(&value.Bool, sizeof(value.Bool));
+ case Type::SignedInt:
+ return as_binary(&value.SignedInt, sizeof(value.SignedInt));
+ case Type::UnsignedInt:
+ return as_binary(&value.UnsignedInt, sizeof(value.UnsignedInt));
+ case Type::Float:
+ return as_binary(&value.Float, sizeof(value.Float));
+ case Type::String:
+ //return as_binary(reinterpret_cast<byte*>(value.String), sizeof(value.Char));
+ case Type::Array:
+ //return as_binary(reinterpret_cast<byte*>(value.Array), sizeof(value.Array));
+ case Type::Map:
+ //return as_binary(reinterpret_cast<byte*>(value.Map), sizeof(value.Map));
+ case Type::Binary:
+ default:
+ break;
+ }
+ return Value::BinaryType();
+}
+
+//////////////// PRIVATE ////////////////
+/////////////////////////////////////////
+///
+///
+///
+/////////////////////////////////////////
+
+
+void Value::construct_fromString(std::string&& s)
+{
+ new( &(value.String)) std::string(std::move(s));
+}
+
+void Value::construct_fromBinary(BinaryType&& b)
+{
+ new( &(value.Binary)) BinaryType(std::move(b));
+}
+
+void Value::construct_fromArray(ArrayType&& a)
+{
+ new( &(value.Array)) ArrayType(std::move(a));
+}
+
+void Value::construct_fromMap(MapType&& m)
+{
+ new( &(value.Map)) MapType(std::move(m));
+}
+
+void Value::move_from(Value&& v)
+{
+ destruct();
+
+ switch (v.vtype) {
+ case Type::Char:
+ value.Char = v.value.Char;
+ break;
+ case Type::Bool:
+ value.Bool = v.value.Bool;
+ break;
+ case Type::SignedInt:
+ value.SignedInt = v.value.SignedInt;
+ break;
+ case Type::UnsignedInt:
+ value.UnsignedInt = v.value.UnsignedInt;
+ break;
+ case Type::Float:
+ value.Float = v.value.Float;
+ break;
+ case Type::String:
+ construct_fromString( std::move(v.value.String) );
+ break;
+ case Type::Binary:
+ construct_fromBinary( std::move(v.value.Binary) );
+ break;
+ case Type::Array:
+ construct_fromArray( std::move(v.value.Array) );
+ break;
+ case Type::Map:
+ construct_fromMap( std::move(v.value.Map) );
+ break;
+ default:
+ break;
+ }
+
+ vtype = v.vtype;
+ v.destruct();
+}
+
+void Value::copy_from(const Value& v)
+{
+ destruct();
+
+ switch (v.vtype) {
+ case Type::Char:
+ value.Char = v.value.Char;
+ break;
+ case Type::Bool:
+ value.Bool = v.value.Bool;
+ break;
+ case Type::SignedInt:
+ value.SignedInt = v.value.SignedInt;
+ break;
+ case Type::UnsignedInt:
+ value.UnsignedInt = v.value.UnsignedInt;
+ break;
+ case Type::Float:
+ value.Float = v.value.Float;
+ break;
+ case Type::String:
+ construct_fromString( std::string( v.value.String ));
+ break;
+ case Type::Binary:
+ construct_fromBinary( BinaryType( v.value.Binary ));
+ break;
+ case Type::Array:
+ construct_fromArray( ArrayType(unique_ptr_copy(v.value.Array)));
+ break;
+ case Type::Map:
+ construct_fromMap( MapType(unique_ptr_copy(v.value.Map)));
+ break;
+ default:
+ break;
+ }
+ vtype = v.vtype;
+}
+
+inline void Value::destruct() noexcept
+{
+ using std::string;
+ using std::vector;
+
+
+ switch (vtype) {
+ case Type::Null:
+ return;
+ case Type::String:
+ value.String.~string();
+ break;
+ case Type::Array:
+ value.Array.~vector();
+ break;
+ case Type::Binary:
+ value.Binary.~vector();
+ break;
+ case Type::Map:
+ value.Map.~unordered_map();
+ break;
+ default:
+ break;
+ }
+
+ vtype = Type::Null;
+ //std::cout << "d " << std::flush;
+}
+
+
+////////////////////////// CONVERSION OPERATOR ///////////////////////////
+///// I currently don't know a better way to avoid code duplication here
+///// C++ forbids a const function to call a none const function
+
+
+///simple int
+Value::operator int ()
+{ return int( operator long long& () ); }
+Value::operator int () const
+{ return int( operator long long const& () ); }
+
+
+///// long long
+Value::operator long long& () &
+{
+ if(vtype == Type::SignedInt)
+ return value.SignedInt;
+ throw bad_value_cast("'Value&' cannot be casted to 'long long'");
+}
+
+Value::operator long long const& () const&
+{
+ if(vtype == Type::SignedInt)
+ return value.SignedInt;
+ throw bad_value_cast("'Value const&' cannot casted to 'long long'");
+}
+
+
+///// unsigned long long
+Value::operator unsigned long long& () &
+{
+ if(vtype == Type::UnsignedInt)
+ return value.UnsignedInt;
+ throw bad_value_cast("'Value&' cannot be casted to 'unsigned long long'");
+}
+
+Value::operator unsigned long long const& () const&
+{
+ if(vtype == Type::UnsignedInt)
+ return value.UnsignedInt;
+ throw bad_value_cast("'Value const&' cannot be casted to 'unsigned long long'");
+}
+
+
+///// bool
+Value::operator bool & () &
+{
+ if(vtype == Type::Bool)
+ return value.Bool;
+ throw bad_value_cast("'Value&' cannot be casted to 'bool'");
+}
+
+Value::operator bool const& () const&
+{
+ if(vtype == Type::Bool)
+ return value.Bool;
+ throw bad_value_cast("'Value const&' cannot be casted to 'bool'");
+}
+
+
+///// char
+Value::operator char & () &
+{
+ if(vtype == Type::Char)
+ return value.Char;
+ throw bad_value_cast("'Value&' cannot be casted to 'char'");
+}
+
+Value::operator char const& () const&
+{
+ if(vtype == Type::Char)
+ return value.Char;
+ throw bad_value_cast("'Value const&' cannot be casted to 'char'");
+}
+
+
+///// double
+Value::operator double & () &
+{
+ if(vtype == Type::Float)
+ return value.Float;
+ throw bad_value_cast("'Value&' cannot be casted to 'double'");
+}
+
+Value::operator double const& () const&
+{
+ if(vtype == Type::Float)
+ return value.Float;
+ throw bad_value_cast("'Value&' cannot be casted to 'double'");
+}
+
+
+///// std::string
+Value::operator std::string&& () &&
+{
+ if(vtype == Type::String)
+ return std::move(value.String);
+ throw bad_value_cast("'Value&&' cannot be casted to 'std::string&&'");
+}
+
+Value::operator std::string& () &
+{
+ if(vtype == Type::String)
+ return value.String;
+ throw bad_value_cast("'Value&' cannot be casted to 'std::string&'");
+}
+
+Value::operator std::string const& () const&
+{
+ if(vtype == Type::String)
+ return value.String;
+ throw bad_value_cast("'Value const&' cannot be casted to 'std::string const&'");
+}
+
+
+///// BinaryType
+Value::operator BinaryType&& () &&
+{
+ if(vtype == Type::Binary)
+ return std::move(value.Binary);
+ throw bad_value_cast("'Value&&' cannot be casted to 'BinaryType&&'");
+}
+
+Value::operator BinaryType& () &
+{
+ if(vtype == Type::Binary)
+ return value.Binary;
+ throw bad_value_cast("'Value&' cannot be casted to 'BinaryType&'");
+}
+
+Value::operator BinaryType const& () const&
+{
+ if(vtype == Type::Binary)
+ return value.Binary;
+ throw bad_value_cast("'Value const&' cannot be casted to 'BinaryType const&'");
+}
+
+
+//////////////////////// FRIEND FUNCTION ///////////
+
+void ubjson::swap(Value& v1, Value& v2)
+{
+ Value vt;
+ vt.move_from( std::move( v2 ));
+ v2.move_from( std::move( v1 ));
+ v1.move_from( std::move( vt ));
+}
+
+/////////////////////// FREE OPERATORS ////////////
+
+bool ubjson::operator == (const Value& lhs, const Value& rhs)
+{
+ using limit = std::numeric_limits<double>;
+
+ if(lhs.isNumeric() && rhs.isNumeric())
+ return std::abs(lhs.asFloat() - rhs.asFloat()) <= limit::epsilon();
+
+ if(lhs.type() != rhs.type())
+ return false;
+
+ switch (rhs.type()) {
+ case Type::Null:
+ return true;
+ case Type::Char:
+ return lhs.value.Char == rhs.value.Char;
+ case Type::Bool:
+ return lhs.value.Bool == rhs.value.Bool;
+ case Type::String:
+ return lhs.value.String == rhs.value.String;
+ case Type::Binary:
+ return lhs.value.Binary == rhs.value.Binary;
+ case Type::Array:
+ return is_equal(lhs.value.Array, rhs.value.Array);
+ case Type::Map:
+ return is_equal(lhs.value.Map, rhs.value.Map);
+ default:
+ break;
+ }
+ return false;
+}
+
+bool ubjson::operator != (const Value& lhs, const Value& rhs)
+{
+ return ! ubjson::operator == (lhs, rhs);
+}
+
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+///
+
+///////////////////////////////////////////////////////////
+
+
+std::ostream& ubjson::operator << (std::ostream& os, to_ostream&& tos)
+{
+ tos.print_value(os, tos.value);
+ return os;
+}
+
+void to_ostream::print_object(std::ostream &os, const Value &v)
+{
+ os << '{' << (ppretty ? "\n" : "");
+ if(ppretty)
+ push_addendum('\t');
+
+ const auto keys = v.keys();
+
+ size_t idx = 0, idxEnd = keys.size();
+ for(const auto& key : keys)
+ {
+ os << addendum << "\"" << key << "\"" << (ppretty ? " : " : ":");;
+ print_value(os, v[key]);
+
+ if(++idx < idxEnd)
+ os << ',';
+ os << (ppretty ? "\n" : "");
+ }
+
+ pop_addendum();
+ os << addendum << '}';
+}
+
+void to_ostream::print_array(std::ostream &os, const Value &v)
+{
+ if(ppretty)
+ push_addendum('\t');
+ os << '[';
+
+ for(size_t i=0; i < v.size(); i++)
+ {
+ print_value(os, v[(int)i]);
+
+ if(i + 1 < v.size())
+ os << (ppretty ? ", " : ",");
+ }
+
+ pop_addendum();
+ os << ']';
+}
+
+void to_ostream::print_value(std::ostream &os, const Value &v)
+{
+ if(v.isNull())
+ os << "null";
+ else if(v.isBool())
+ os << (v ? "true" : "false");
+ else if(v.isChar())
+ os << "\"" << static_cast<char>(v) << "\"";
+ else if(v.isSignedInteger())
+ os << static_cast<long long>(v);
+ else if(v.isUnsignedInteger())
+ os << static_cast<unsigned long long>(v);
+ else if(v.isFloat())
+ os << static_cast<double>(v);
+ else if(v.isString())
+ os << "\"" << static_cast<std::string>(v) << "\"";
+ else if(v.isBinary())
+ os << "BINARY DATA (" << static_cast<const Value::BinaryType&>(v).size() << " bytes)";
+ else if(v.isArray())
+ print_array(os, v);
+ else if(v.isObject())
+ print_object(os, v);
+}
diff --git a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/value.hpp b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/value.hpp
index 39a236f..5553b34 100755
--- a/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/value.hpp
+++ b/BGModeler/BGModeler/src/3rd Party/UbjsonCpp/include/Ubjson/value.hpp
@@ -552,7 +552,7 @@ namespace ubjson {
{ addendum.push_back(c); }
inline void pop_addendum() {
- if(not addendum.empty())
+ if(! addendum.empty())
addendum.pop_back();
}
--
2.9.0.windows.1
WhiZTiM commented
Thanks for this observation @mlfarrell , I honestly didn't test it on MSVC as of the time of release and wrongly assumed MSVC will support alternative operators;
Thanks for the patch, I'll use it to fix up the library this weekend.