Skip to content

Visual Studio 2013 support and related fixes #8539

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

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