Skip to content

Visual Studio 2013 support and related fixes #8539

New issue

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

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

Already on GitHub? # to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion include/flatbuffers/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ const Array<E, length> &CastToArrayOfEnum(const T (&arr)[length]) {

template<typename T, uint16_t length>
bool operator==(const Array<T, length> &lhs,
const Array<T, length> &rhs) noexcept {
const Array<T, length> &rhs) FLATBUFFERS_NOEXCEPT {
return std::addressof(lhs) == std::addressof(rhs) ||
(lhs.size() == rhs.size() &&
std::memcmp(lhs.Data(), rhs.Data(), rhs.size() * sizeof(T)) == 0);
Expand Down
9 changes: 9 additions & 0 deletions include/flatbuffers/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,15 @@ namespace flatbuffers {
#else
#define FLATBUFFERS_CONSTEXPR const
#define FLATBUFFERS_CONSTEXPR_CPP11
#if defined _MSC_VER && _MSC_VER == 1800
// disable VS2013 warning when if() condition is a constant expression
#pragma warning (disable: 4127)
#endif
#endif

#if defined _MSC_VER && _MSC_VER == 1800
// disabled the warning about behavior change that now conforms to the standard
#pragma warning (disable: 4351)
#endif

#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
Expand Down
4 changes: 2 additions & 2 deletions include/flatbuffers/detached_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class DetachedBuffer {
cur_(cur),
size_(sz) {}

DetachedBuffer(DetachedBuffer &&other) noexcept
DetachedBuffer(DetachedBuffer &&other) FLATBUFFERS_NOEXCEPT
: allocator_(other.allocator_),
own_allocator_(other.own_allocator_),
buf_(other.buf_),
Expand All @@ -55,7 +55,7 @@ class DetachedBuffer {
other.reset();
}

DetachedBuffer &operator=(DetachedBuffer &&other) noexcept {
DetachedBuffer &operator=(DetachedBuffer &&other) FLATBUFFERS_NOEXCEPT {
if (this == &other) return *this;

destroy();
Expand Down
111 changes: 91 additions & 20 deletions include/flatbuffers/flatbuffer_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {
}

/// @brief Move constructor for FlatBufferBuilder.
FlatBufferBuilderImpl(FlatBufferBuilderImpl &&other) noexcept
FlatBufferBuilderImpl(FlatBufferBuilderImpl &&other) FLATBUFFERS_NOEXCEPT
: buf_(1024, nullptr, false, AlignOf<largest_scalar_t>(),
static_cast<SizeT>(Is64Aware ? FLATBUFFERS_MAX_64_BUFFER_SIZE
: FLATBUFFERS_MAX_BUFFER_SIZE)),
Expand All @@ -133,7 +133,7 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {
}

/// @brief Move assignment operator for FlatBufferBuilder.
FlatBufferBuilderImpl &operator=(FlatBufferBuilderImpl &&other) noexcept {
FlatBufferBuilderImpl &operator=(FlatBufferBuilderImpl &&other) FLATBUFFERS_NOEXCEPT {
// Move construct a temporary and swap idiom
FlatBufferBuilderImpl temp(std::move(other));
Swap(temp);
Expand Down Expand Up @@ -726,19 +726,21 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {

/// @brief Serialize an array into a FlatBuffer `vector`.
/// @tparam T The data type of the array elements.
/// @tparam OffsetT the type of offset to return
/// @tparam OffsetT the type of offset to return.
/// @tparam VectorT the type of vector to cast to.
/// @tparam SizeT the size type to use in the VectorT vector.
/// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `TOffset` into the serialized data indicating
/// where the vector is stored.
template<typename T, template<typename...> class OffsetT = Offset,
template<typename...> class VectorT = Vector>
OffsetT<VectorT<T>> CreateVector(const T *v, size_t len) {
template<typename T, template<typename...> class OffsetT,
template<typename...> class VectorT,
typename SizeT = typename VectorT<T>::size_type>
OffsetT<VectorT<T, SizeT>> CreateVector(const T *v, size_t len) {
// The type of the length field in the vector.
typedef typename VectorT<T>::size_type LenT;
typedef typename OffsetT<VectorT<T>>::offset_type offset_type;
typedef typename VectorT<T, SizeT>::size_type LenT;
typedef typename OffsetT<VectorT<T, SizeT>>::offset_type offset_type;
// If this assert hits, you're specifying a template argument that is
// causing the wrong overload to be selected, remove it.
AssertScalarT<T>();
Expand All @@ -758,7 +760,20 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {
#endif
// clang-format on
}
return OffsetT<VectorT<T>>(EndVector<LenT, offset_type>(len));
return OffsetT<VectorT<T, SizeT>>(EndVector<LenT, offset_type>(len));
}

/// @brief Serialize an array into a FlatBuffer `vector`.
/// @tparam T The data type of the array elements.
/// @tparam OffsetT the type of offset to return
/// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `TOffset` into the serialized data indicating
/// where the vector is stored.
template<typename T, template<typename...> class OffsetT = Offset>
OffsetT<Vector<T>> CreateVector(const T *v, size_t len) {
return CreateVector<T, OffsetT, Vector, typename Vector<T>::size_type>(v, len);
}

/// @brief Serialize an array like object into a FlatBuffer `vector`.
Expand Down Expand Up @@ -800,10 +815,22 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {
return CreateVector(data(v), v.size());
}

template<template<typename...> class VectorT = Vector64,
template<template<typename...> class VectorT,
typename SizeT,
int &...ExplicitArgumentBarrier, typename T>
Offset64<VectorT<T, SizeT>> CreateVector64(const std::vector<T> &v) {
return CreateVector<T, Offset64, VectorT, SizeT>(data(v), v.size());
}

template<template<typename...> class VectorT,
int &...ExplicitArgumentBarrier, typename T>
Offset64<VectorT<T>> CreateVector64(const std::vector<T> &v) {
return CreateVector<T, Offset64, VectorT>(data(v), v.size());
return CreateVector64<VectorT, typename VectorT<T>::size_type>(v);
}

template<typename T>
Offset64<Vector64<T>> CreateVector64(const std::vector<T> &v) {
return CreateVector64<Vector, typename Vector64<T>::size_type>(v);
}

// vector<bool> may be implemented using a bit-set, so we can't access it as
Expand Down Expand Up @@ -899,23 +926,38 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {

/// @brief Serialize an array of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements.
/// @tparam OffsetT the type of offset to return.
/// @tparam VectorT the type of vector to cast to.
/// @tparam SizeT the size type to use in the VectorT vector.
/// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, template<typename...> class OffsetT = Offset,
template<typename...> class VectorT = Vector>
OffsetT<VectorT<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
template<typename...> class VectorT, typename SizeT = typename VectorT<T>::size_type>
OffsetT<VectorT<const T *, SizeT>> CreateVectorOfStructs(const T *v, size_t len) {
// The type of the length field in the vector.
typedef typename VectorT<T>::size_type LenT;
typedef typename OffsetT<VectorT<const T *>>::offset_type offset_type;
typedef typename VectorT<T, SizeT>::size_type LenT;
typedef typename OffsetT<VectorT<const T *, SizeT>>::offset_type offset_type;

StartVector<OffsetT, LenT>(len, sizeof(T), AlignOf<T>());
if (len > 0) {
PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
}
return OffsetT<VectorT<const T *>>(EndVector<LenT, offset_type>(len));
return OffsetT<VectorT<const T *, SizeT>>(EndVector<LenT, offset_type>(len));
}

/// @brief Serialize an array of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements.
/// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T>
Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
return CreateVectorOfStructs<T, Offset, Vector, typename Vector<T>::size_type>(v, len);
}

/// @brief Serialize an array of structs into a FlatBuffer `vector`.
Expand Down Expand Up @@ -959,22 +1001,51 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {

/// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the `std::vector` struct elements.
/// @tparam OffsetT the type of offset to return.
/// @tparam VectorT the type of vector to cast to.
/// @tparam Alloc the allocator used by the parameter.
/// @tparam SizeT the size type to use in the VectorT vector.
/// @param[in] v A const reference to the `std::vector` of structs to
/// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, template<typename...> class OffsetT = Offset,
template<typename...> class VectorT = Vector,
typename Alloc = std::allocator<T>>
typename Alloc = std::allocator<T>, typename SizeT = typename VectorT<T>::size_type>
OffsetT<VectorT<const T *>> CreateVectorOfStructs(
const std::vector<T, Alloc> &v) {
return CreateVectorOfStructs<T, OffsetT, VectorT>(data(v), v.size());
}

template<template<typename...> class VectorT = Vector64, int &..., typename T>
/// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the `std::vector` struct elements.
/// @param[in] v A const reference to the `std::vector` of structs to
/// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T>
Offset<Vector<const T *>> CreateVectorOfStructs(
const std::vector<T, std::allocator<T>> &v) {
return CreateVectorOfStructs<T, Offset, Vector, typename Vector<T>::size_type>(data(v), v.size());
}

template<template<typename...> class VectorT, typename SizeT,
int &..., typename T>
Offset64<VectorT<const T *, SizeT>> CreateVectorOfStructs64(
const std::vector<T> &v) {
return CreateVectorOfStructs<T, Offset64, VectorT, SizeT>(data(v), v.size());
}

template<int &..., typename T>
Offset64<Vector64<const T *>> CreateVectorOfStructs64(
const std::vector<T> &v) {
return CreateVectorOfStructs<T, Offset64, Vector, typename Vector64<T>::size_type>(data(v), v.size());
}

template<template<typename...> class VectorT, int &..., typename T>
Offset64<VectorT<const T *>> CreateVectorOfStructs64(
const std::vector<T> &v) {
return CreateVectorOfStructs<T, Offset64, VectorT>(data(v), v.size());
return CreateVectorOfStructs64<VectorT, typename VectorT<T>::size_type>(data(v), v.size());
}

/// @brief Serialize an array of native structs into a FlatBuffer `vector`.
Expand Down Expand Up @@ -1087,7 +1158,7 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl {
template<typename T>
Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
std::stable_sort(v, v + len, StructKeyComparator<T>());
return CreateVectorOfStructs(v, len);
return CreateVectorOfStructs<T, Offset, Vector, uoffset_t>(v, len);
}

/// @brief Serialize an array of native structs into a FlatBuffer `vector` in
Expand Down
13 changes: 11 additions & 2 deletions include/flatbuffers/flatc.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ extern void LogCompilerWarn(const std::string &warn);
extern void LogCompilerError(const std::string &err);

struct FlatCOptions {
FlatCOptions() = default;
FlatCOptions(const FlatCOptions&) = delete;
FlatCOptions(FlatCOptions&&) = delete;

~FlatCOptions() = default;

FlatCOptions& operator=(const FlatCOptions&) = delete;
FlatCOptions& operator=(FlatCOptions&&) = delete;

IDLOptions opts;

std::string program_name;
Expand Down Expand Up @@ -95,7 +104,7 @@ class FlatCompiler {
std::string GetUsageString(const std::string &program_name) const;

// Parse the FlatC options from command line arguments.
FlatCOptions ParseFromCommandLineArguments(int argc, const char **argv);
void ParseFromCommandLineArguments(int argc, const char **argv, FlatCOptions& options);

private:
void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
Expand All @@ -116,7 +125,7 @@ class FlatCompiler {

void ValidateOptions(const FlatCOptions &options);

Parser GetConformParser(const FlatCOptions &options);
void GetConformParser(const FlatCOptions &options, Parser &conform_parser);

std::unique_ptr<Parser> GenerateCode(const FlatCOptions &options,
Parser &conform_parser);
Expand Down
2 changes: 2 additions & 0 deletions include/flatbuffers/idl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1009,8 +1009,10 @@ class Parser : public ParserState {
Parser(const Parser &) = delete;
Parser &operator=(const Parser &) = delete;

#ifdef FLATBUFFERS_DEFAULT_DECLARATION
Parser(Parser &&) = default;
Parser &operator=(Parser &&) = default;
#endif

~Parser() {
for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
Expand Down
63 changes: 63 additions & 0 deletions include/flatbuffers/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,45 @@ template<> inline std::string NumToString<char>(char t) {
return NumToString(static_cast<int>(t));
}

#if defined _MSC_VER && _MSC_VER <= 1800
#define FLATBUFFERS_EXPLICIT_INF_NAN_CONVERSION
#endif

template <typename T>
bool ExplicitlyConvertSpecialValues(T value, std::string &result, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr) {
#ifdef FLATBUFFERS_EXPLICIT_INF_NAN_CONVERSION
if (value == std::numeric_limits<T>::infinity()) {
result = "inf";
return true;
}
if (value == -std::numeric_limits<T>::infinity()) {
result = "-inf";
return true;
}
if (std::isnan(value)) {
result = std::signbit(value) ? "-nan" : "nan";
return true;
}
#else
(void)value;
(void)result;
#endif
return false;
}

template <typename T>
bool ExplicitlyConvertSpecialValues(T value, std::string &result, typename std::enable_if<!std::is_floating_point<T>::value>::type* = nullptr) {
(void)value;
(void)result;
return false;
}
// Special versions for floats/doubles.
template<typename T> std::string FloatToString(T t, int precision) {
// clang-format off
std::string res;
if (ExplicitlyConvertSpecialValues(t, res)) {
return res;
}

#ifndef FLATBUFFERS_PREFER_PRINTF
// to_string() prints different numbers of digits for floats depending on
Expand Down Expand Up @@ -306,12 +342,39 @@ inline bool StringToIntegerImpl(T *val, const char *const str,
}
}

inline bool MatchFloatToString(const char *const str, const char *const constant_str, const char *& end) {
if (strcmp(str, constant_str) == 0) {
end = const_cast<char*>(str + strlen(constant_str));
return true;
}
return false;
}

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;
#ifdef FLATBUFFERS_EXPLICIT_INF_NAN_CONVERSION
if (MatchFloatToString(str, "inf", end) ||
MatchFloatToString(str, "+inf", end) ||
MatchFloatToString(str, "infinity", end) ||
MatchFloatToString(str, "+infinity", end)) {
*val = std::numeric_limits<T>::infinity();
} else if (MatchFloatToString(str, "-inf", end) ||
MatchFloatToString(str, "-infinity", end)) {
*val = -std::numeric_limits<T>::infinity();
} else if (MatchFloatToString(str, "nan", end) ||
MatchFloatToString(str, "+nan", end)) {
*val = std::numeric_limits<T>::quiet_NaN();
} else if (MatchFloatToString(str, "-nan", end)) {
*val = -std::numeric_limits<T>::quiet_NaN();
} else {
strtoval_impl(val, str, const_cast<char **>(&end));
}
#else
strtoval_impl(val, str, const_cast<char **>(&end));
#endif
auto done = (end != str) && (*end == '\0');
if (!done) *val = 0; // erase partial result
if (done && std::isnan(*val)) { *val = std::numeric_limits<T>::quiet_NaN(); }
Expand Down
4 changes: 2 additions & 2 deletions include/flatbuffers/vector_downward.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ template<typename SizeT = uoffset_t> class vector_downward {
cur_(nullptr),
scratch_(nullptr) {}

vector_downward(vector_downward &&other) noexcept
vector_downward(vector_downward &&other) FLATBUFFERS_NOEXCEPT
// clang-format on
: allocator_(other.allocator_),
own_allocator_(other.own_allocator_),
Expand All @@ -70,7 +70,7 @@ template<typename SizeT = uoffset_t> class vector_downward {
other.scratch_ = nullptr;
}

vector_downward &operator=(vector_downward &&other) noexcept {
vector_downward &operator=(vector_downward &&other) FLATBUFFERS_NOEXCEPT {
// Move construct a temporary and swap idiom
vector_downward temp(std::move(other));
swap(temp);
Expand Down
Loading