This is an automated email from the ASF dual-hosted git repository. isapego pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push: new 43e3fee IGNITE-1472: Enum support for C++ 43e3fee is described below commit 43e3fee444c55fe12da3b9d57606f0b6b8df1886 Author: Igor Sapego <isap...@apache.org> AuthorDate: Fri Jul 12 19:23:32 2019 +0300 IGNITE-1472: Enum support for C++ This closes #6649 --- .../cpp/binary/include/ignite/binary/binary_enum.h | 204 +++++++++++++++++++++ .../include/ignite/binary/binary_enum_entry.h | 107 +++++++++++ .../include/ignite/binary/binary_raw_reader.h | 23 +++ .../include/ignite/binary/binary_raw_writer.h | 21 +++ .../binary/include/ignite/binary/binary_reader.h | 23 +++ .../cpp/binary/include/ignite/binary/binary_type.h | 8 +- .../binary/include/ignite/binary/binary_writer.h | 22 +++ .../include/ignite/impl/binary/binary_common.h | 6 + .../ignite/impl/binary/binary_reader_impl.h | 84 ++++++++- .../include/ignite/impl/binary/binary_utils.h | 82 ++++++--- .../ignite/impl/binary/binary_writer_impl.h | 69 ++++++- .../ignite/impl/interop/interop_input_stream.h | 4 +- .../platforms/cpp/binary/project/vs/binary.vcxproj | 2 + .../cpp/binary/project/vs/binary.vcxproj.filters | 6 + .../cpp/binary/src/binary/binary_raw_reader.cpp | 5 + .../cpp/binary/src/binary/binary_raw_writer.cpp | 5 + .../cpp/binary/src/binary/binary_reader.cpp | 5 + .../cpp/binary/src/binary/binary_writer.cpp | 5 + .../binary/src/impl/binary/binary_reader_impl.cpp | 85 ++++++--- .../cpp/binary/src/impl/binary/binary_utils.cpp | 43 +++-- .../binary/src/impl/binary/binary_writer_impl.cpp | 21 +++ .../core-test/include/ignite/binary_test_defs.h | 58 ++++++ .../cpp/core-test/src/binary_object_test.cpp | 117 ++++++++++++ modules/platforms/cpp/core-test/src/cache_test.cpp | 50 ++++- 24 files changed, 976 insertions(+), 79 deletions(-) diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_enum.h b/modules/platforms/cpp/binary/include/ignite/binary/binary_enum.h new file mode 100644 index 0000000..dd2f37c --- /dev/null +++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_enum.h @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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. + */ + +/** + * @file + * Declares ignite::binary::BinaryEnum class template and helping classes + * to declare enum type specialization for user types. + */ + +#ifndef _IGNITE_BINARY_BINARY_ENUM +#define _IGNITE_BINARY_BINARY_ENUM + +#include <stdint.h> + +#include <ignite/common/common.h> + +#include <ignite/binary/binary_type.h> + +namespace ignite +{ + namespace binary + { + /** + * Binary enum structure. Defines a set of functions required for enum type to be serialized and deserialized. + * + * Methods that should be defined: + * static void GetTypeName(std::string& dst) - should place type name in @c dst parameter. This method should + * always return the same value. + * static int32_t GetTypeId() - should return Type ID. + * static int32_t GetOrdinal(T) - should return ordinal value for enum value. + * static T FromOrdinal(int32_t) - should return enum value for a given ordinal value. + * static bool IsNull(const T&) - check whether passed enum object should be interpreted as NULL. + * static void GetNull(T&) - get NULL value for the given enum type. + * + * It is recommended to use BinaryEnumDefault as a base class for default implementation of GetTypeId(), + * GetOrdinal() and FromOrdinal() methods for plain enum types. In this case, only GetTypeName() should be + * implemented by a user directly. + */ + template<typename T> + struct BinaryEnum { }; + + /** + * Default implementations of BinaryEnum. + */ + template<typename T> + struct BinaryEnumDefault + { + /** + * Get type ID for the enum type. + * + * @return Type ID. + */ + static int32_t GetTypeId() + { + std::string typeName; + BinaryEnum<T>::GetTypeName(typeName); + + return GetBinaryStringHashCode(typeName.c_str()); + } + + /** + * Get enum type ordinal. + * + * @return Ordinal of the enum type. + */ + static int32_t GetOrdinal(T value) + { + return static_cast<int32_t>(value); + } + + /** + * Get enum value for the given ordinal value. + * + * @param ordinal Ordinal value of the enum. + */ + static T FromOrdinal(int32_t ordinal) + { + return static_cast<T>(ordinal); + } + }; + + /** + * Implementations of BinaryEnum nullability when INT32_MIN ordinal value used as a NULL indicator. + */ + template<typename T> + struct BinaryEnumIntMinNull + { + /** + * Check whether passed binary object should be interpreted as NULL. + * + * @return True if binary object should be interpreted as NULL. + */ + static bool IsNull(const T& val) + { + return val == BinaryEnum<T>::FromOrdinal(INT32_MIN); + } + + /** + * Get NULL value for the given binary type. + * + * @param dst Null value for the type. + */ + static void GetNull(T& dst) + { + dst = BinaryEnum<T>::FromOrdinal(INT32_MIN); + } + }; + + /** + * Default implementations of BinaryType hashing functions and non-null type behaviour. + */ + template<typename T> + struct BinaryEnumDefaultAll : + BinaryEnumDefault<T>, + BinaryEnumIntMinNull<T> { }; + + /** + * BinaryEnum template specialization for pointers. + */ + template <typename T> + struct BinaryEnum<T*> + { + /** Actual type. */ + typedef BinaryEnum<T> BinaryEnumDereferenced; + + /** + * Get binary object type ID. + * + * @return Type ID. + */ + static int32_t GetTypeId() + { + return BinaryEnumDereferenced::GetTypeId(); + } + + /** + * Get binary object type name. + * + * @param dst Output type name. + */ + static void GetTypeName(std::string& dst) + { + BinaryEnumDereferenced::GetTypeName(dst); + } + + /** + * Get enum type ordinal. + * + * @return Ordinal of the enum type. + */ + static int32_t GetOrdinal(T* value) + { + return BinaryEnumDereferenced::GetOrdinal(*value); + } + + /** + * Get enum value for the given ordinal value. + * + * @param ordinal Ordinal value of the enum. + */ + static T* FromOrdinal(int32_t ordinal) + { + return new T(BinaryEnumDereferenced::FromOrdinal(ordinal)); + } + + /** + * Check whether passed enum should be interpreted as NULL. + * + * @param obj Enum value to test. + * @return True if enum value should be interpreted as NULL. + */ + static bool IsNull(T* const& obj) + { + return !obj || BinaryEnumDereferenced::IsNull(*obj); + } + + /** + * Get NULL value for the enum type. + * + * @param dst NULL value for the enum. + */ + static void GetNull(T*& dst) + { + dst = 0; + } + }; + } +} + +#endif //_IGNITE_BINARY_BINARY_ENUM diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_enum_entry.h b/modules/platforms/cpp/binary/include/ignite/binary/binary_enum_entry.h new file mode 100644 index 0000000..8a27506 --- /dev/null +++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_enum_entry.h @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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. + */ + +/** + * @file + * Declares ignite::binary::BinaryEnumEntry class. + */ + +#ifndef _IGNITE_BINARY_BINARY_ENUM_ENTRY +#define _IGNITE_BINARY_BINARY_ENUM_ENTRY + +#include <stdint.h> + +#include <ignite/common/common.h> + +namespace ignite +{ + namespace binary + { + /** + * Binary enum entry. + * + * Represents a single entry of enum in a binary form. + */ + class IGNITE_IMPORT_EXPORT BinaryEnumEntry + { + public: + /** + * Default constructor. + */ + BinaryEnumEntry() : + typeId(0), + ordinal(0) + { + // No-op. + } + + /** + * Constructor. + * + * @param typeId Type ID of the enum. + * @param ordinal Ordinal of the enum value. + */ + BinaryEnumEntry(int32_t typeId, int32_t ordinal) : + typeId(typeId), + ordinal(ordinal) + { + // No-op. + } + + /** + * Get type ID. + * Type ID can never equal zero. If the Type ID equals zero, the instance is not valid, and could only be + * acquired by manual construction or by reading NULL value. + * + * @return Type ID. + */ + int32_t GetTypeId() const + { + return typeId; + } + + /** + * Get ordinal of the enum value. + * + * @return Ordinal. + */ + int32_t GetOrdinal() const + { + return ordinal; + } + + /** + * Check whether value was acquired by reading a NULL value. + * + * @return @c true if acquired by reading a NULL value. + */ + bool IsNull() const + { + return typeId == 0; + } + + private: + /** Type ID. */ + int32_t typeId; + + /** Ordinal value. */ + int32_t ordinal; + }; + } +} + +#endif //_IGNITE_BINARY_BINARY_ENUM_ENTRY diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h index dd7a696..a8efad9 100644 --- a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h +++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h @@ -31,6 +31,7 @@ #include "ignite/impl/binary/binary_reader_impl.h" #include "ignite/binary/binary_consts.h" #include "ignite/binary/binary_containers.h" +#include "ignite/binary/binary_enum_entry.h" #include "ignite/guid.h" #include "ignite/date.h" #include "ignite/timestamp.h" @@ -352,6 +353,13 @@ namespace ignite BinaryStringArrayReader ReadStringArray(); /** + * Read enum entry. + * + * @return Enum entry. + */ + BinaryEnumEntry ReadBinaryEnum(); + + /** * Start array read. * * Every time you get a BinaryArrayReader from BinaryRawReader you @@ -443,6 +451,8 @@ namespace ignite * Read object. * * @return Object. + * + * @trapam T Object type. BinaryType class template should be specialized for the type. */ template<typename T> T ReadObject() @@ -451,6 +461,19 @@ namespace ignite } /** + * Read enum value. + * + * @return Enum value. + * + * @trapam T Enum type. BinaryEnum class template should be specialized for the type. + */ + template<typename T> + T ReadEnum() + { + return impl->ReadEnum<T>(); + } + + /** * Try read object. * Reads value, stores it to res and returns true if the value is * not null. Otherwise just returns false. diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_writer.h b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_writer.h index 857d7f2..8150db0 100644 --- a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_writer.h +++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_writer.h @@ -283,6 +283,13 @@ namespace ignite BinaryStringArrayWriter WriteStringArray(); /** + * Write enum entry. + * + * @param entry Binary enum entry. + */ + void WriteBinaryEnum(BinaryEnumEntry entry); + + /** * Write NULL value. */ void WriteNull(); @@ -415,6 +422,20 @@ namespace ignite { impl->WriteObject<T>(val); } + + /** + * Write binary enum entry. + * + * @param val Binary enum entry. + * + * @trapam T Enum type. BinaryEnum class template should be specialized for the type. + */ + template<typename T> + void WriteEnum(T val) + { + impl->WriteEnum(val); + } + private: /** Implementation delegate. */ ignite::impl::binary::BinaryWriterImpl* impl; diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_reader.h b/modules/platforms/cpp/binary/include/ignite/binary/binary_reader.h index acd9d61..be4badc 100644 --- a/modules/platforms/cpp/binary/include/ignite/binary/binary_reader.h +++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_reader.h @@ -366,6 +366,14 @@ namespace ignite BinaryStringArrayReader ReadStringArray(const char* fieldName); /** + * Read enum entry. + * + * @param fieldName Field name. + * @return Enum entry. + */ + BinaryEnumEntry ReadBinaryEnum(const char* fieldName); + + /** * Start array read. * * Every time you get a BinaryArrayReader from BinaryReader you @@ -464,6 +472,8 @@ namespace ignite * * @param fieldName Field name. * @return Object. + * + * @trapam T Object type. BinaryType class template should be specialized for the type. */ template<typename T> T ReadObject(const char* fieldName) @@ -472,6 +482,19 @@ namespace ignite } /** + * Read enum value. + * + * @return Enum value. + * + * @trapam T Enum type. BinaryEnum class template should be specialized for the type. + */ + template<typename T> + T ReadEnum(const char* fieldName) + { + return impl->ReadEnum<T>(fieldName); + } + + /** * Get raw reader for this reader. * * @return Raw reader. diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_type.h b/modules/platforms/cpp/binary/include/ignite/binary/binary_type.h index 84de648..492de03 100644 --- a/modules/platforms/cpp/binary/include/ignite/binary/binary_type.h +++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_type.h @@ -18,7 +18,7 @@ /** * @file * Declares ignite::binary::BinaryType class template and helping macros - * to declare binary type specialisation for user types. + * to declare binary type specialization for user types. */ #ifndef _IGNITE_BINARY_BINARY_TYPE @@ -108,7 +108,7 @@ static bool IsNull(const T& obj) \ /** * @def IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(T) - * Implementation of GetNull() function which returns an instance created with defult constructor. + * Implementation of GetNull() function which returns an instance created with default constructor. */ #define IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(T) \ static void GetNull(T& dst) \ @@ -215,7 +215,7 @@ namespace ignite BinaryTypeNonNullableType<T> { }; /** - * Templated binary type specification for pointers. + * BinaryType template specialization for pointers. */ template <typename T> struct IGNITE_IMPORT_EXPORT BinaryType<T*> @@ -292,7 +292,7 @@ namespace ignite /** * Get NULL value for the given binary type. * - * @param dst Null value for the type. + * @param dst NULL value for the type. */ static void GetNull(T*& dst) { diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_writer.h b/modules/platforms/cpp/binary/include/ignite/binary/binary_writer.h index 3dc1241..c293935 100644 --- a/modules/platforms/cpp/binary/include/ignite/binary/binary_writer.h +++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_writer.h @@ -307,6 +307,14 @@ namespace ignite BinaryStringArrayWriter WriteStringArray(const char* fieldName); /** + * Write binary enum entry. + * + * @param fieldName Field name. + * @param entry Binary enum entry. + */ + void WriteBinaryEnum(const char* fieldName, BinaryEnumEntry entry); + + /** * Write NULL value. * * @param fieldName Field name. @@ -451,6 +459,20 @@ namespace ignite } /** + * Write enum entry. + * + * @param fieldName Field name. + * @param val Binary enum entry. + * + * @trapam T Enum type. BinaryEnum class template should be specialized for the type. + */ + template<typename T> + void WriteEnum(const char* fieldName, T val) + { + impl->WriteEnum(fieldName, val); + } + + /** * Get raw writer for this reader. * * @return Raw writer. diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_common.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_common.h index a4275c7..7124170 100644 --- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_common.h +++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_common.h @@ -158,6 +158,12 @@ namespace ignite /** Type: binary object. */ const int8_t IGNITE_TYPE_BINARY = 27; + /** Type: Enum. */ + const int8_t IGNITE_TYPE_ENUM = 28; + + /** Type: Binary Enum. */ + const int8_t IGNITE_TYPE_BINARY_ENUM = 38; + /** Type: timestamp. */ const int8_t IGNITE_TYPE_TIMESTAMP = 33; diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h index a3b880c..ca9f8b7 100644 --- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h +++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h @@ -30,10 +30,12 @@ #include "ignite/common/utils.h" #include "ignite/binary/binary_consts.h" #include "ignite/binary/binary_type.h" +#include "ignite/binary/binary_enum_entry.h" #include "ignite/guid.h" #include "ignite/date.h" #include "ignite/timestamp.h" #include "ignite/time.h" +#include "ignite/binary/binary_enum.h" namespace ignite { @@ -65,6 +67,7 @@ namespace ignite * @param rawOff Raw data offset. * @param footerBegin Footer beginning absolute position in stream. * @param footerEnd Footer ending absolute position in stream. + * @param schemaType Schema Type. */ BinaryReaderImpl(interop::InteropInputStream* stream, BinaryIdResolver* idRslvr, int32_t pos, bool usrType, int32_t typeId, int32_t hashCode, int32_t len, int32_t rawOff, @@ -559,10 +562,25 @@ namespace ignite int32_t ReadTimeArray(const char* fieldName, Time* res, const int32_t len); /** + * Read enum entry. + * + * @return Enum entry. + */ + ignite::binary::BinaryEnumEntry ReadBinaryEnum(); + + /** + * Read enum entry. + * + * @param fieldName Field name. + * @return Enum entry. + */ + ignite::binary::BinaryEnumEntry ReadBinaryEnum(const char* fieldName); + + /** * Read string. * * @param len Expected length of string. - * @param res Array to store data to (should be able to acocmodate null-terminator). + * @param res Array to store data to (should be able to accomodate null-terminator). * @return Actual amount of elements read. If "len" argument is less than actual * array size or resulting array is set to null, nothing will be written * to resulting array and returned value will contain required array length. @@ -862,6 +880,33 @@ namespace ignite } /** + * Read enum value. + * + * @return Enum value. + */ + template<typename T> + T ReadEnum() + { + ignite::binary::BinaryEnumEntry entry = ReadBinaryEnum(); + + return DeserializeEnumEntry<T>(entry); + } + + /** + * Read enum value. + * + * @param fieldName Field name. + * @return Enum value. + */ + template<typename T> + T ReadEnum(const char* fieldName) + { + ignite::binary::BinaryEnumEntry entry = ReadBinaryEnum(fieldName); + + return DeserializeEnumEntry<T>(entry); + } + + /** * Try read object. * Reads value, stores it to res and returns true if the value is * not null. Otherwise just returns false. @@ -1105,6 +1150,36 @@ namespace ignite BinaryOffsetType::Type schemaType; IGNITE_NO_COPY_ASSIGNMENT(BinaryReaderImpl) + + /** + * Deserialize EnumEntry into user type. + * + * @param entry Entry to deserialize. + * @return User type value. + */ + template<typename T> + T DeserializeEnumEntry(ignite::binary::BinaryEnumEntry entry) + { + typedef ignite::binary::BinaryEnum<T> TypeMeta; + + if (entry.IsNull()) + { + T res; + + TypeMeta::GetNull(res); + + return res; + } + + if (entry.GetTypeId() != TypeMeta::GetTypeId()) + { + IGNITE_ERROR_FORMATTED_2(ignite::IgniteError::IGNITE_ERR_BINARY, + "Unexpected type ID during deserialization of the enum: ", + "expected", TypeMeta::GetTypeId(), "actual", entry.GetTypeId()); + } + + return TypeMeta::FromOrdinal(entry.GetOrdinal()); + } /** * Internal routine to read Guid array. @@ -1409,6 +1484,13 @@ namespace ignite void ThrowOnInvalidHeader(int8_t expHdr, int8_t hdr) const; /** + * Read enum entry. + * + * @return Enum entry. + */ + ignite::binary::BinaryEnumEntry ReadBinaryEnumInternal(); + + /** * Internal string read routine. * * @param res Resulting array. diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_utils.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_utils.h index fda9a18..58e5819 100644 --- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_utils.h +++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_utils.h @@ -27,6 +27,7 @@ #include <ignite/timestamp.h> #include <ignite/time.h> +#include <ignite/binary/binary_enum_entry.h> #include <ignite/binary/binary_type.h> namespace ignite @@ -100,7 +101,7 @@ namespace ignite * @param res Target array. * @param len Array length. */ - static void ReadInt8Array(interop::InteropInputStream* stream, int8_t* res, const int32_t len); + static void ReadInt8Array(interop::InteropInputStream* stream, int8_t* res, int32_t len); /** * Utility method to write signed 8-bit integer array to stream. @@ -109,7 +110,7 @@ namespace ignite * @param val Value. * @param len Array length. */ - static void WriteInt8Array(interop::InteropOutputStream* stream, const int8_t* val, const int32_t len); + static void WriteInt8Array(interop::InteropOutputStream* stream, const int8_t* val, int32_t len); /** * Utility method to read boolean from stream. @@ -134,7 +135,7 @@ namespace ignite * @param res Target array. * @param len Array length. */ - static void ReadBoolArray(interop::InteropInputStream* stream, bool* res, const int32_t len); + static void ReadBoolArray(interop::InteropInputStream* stream, bool* res, int32_t len); /** * Utility method to write bool array to stream. @@ -143,7 +144,7 @@ namespace ignite * @param val Value. * @param len Array length. */ - static void WriteBoolArray(interop::InteropOutputStream* stream, const bool* val, const int32_t len); + static void WriteBoolArray(interop::InteropOutputStream* stream, const bool* val, int32_t len); /** * Utility method to read signed 16-bit integer from stream. @@ -188,7 +189,7 @@ namespace ignite * @param res Target array. * @param len Array length. */ - static void ReadInt16Array(interop::InteropInputStream* stream, int16_t* res, const int32_t len); + static void ReadInt16Array(interop::InteropInputStream* stream, int16_t* res, int32_t len); /** * Utility method to write signed 16-bit integer array to stream. @@ -197,7 +198,7 @@ namespace ignite * @param val Value. * @param len Array length. */ - static void WriteInt16Array(interop::InteropOutputStream* stream, const int16_t* val, const int32_t len); + static void WriteInt16Array(interop::InteropOutputStream* stream, const int16_t* val, int32_t len); /** * Utility method to read unsigned 16-bit integer from stream. @@ -222,7 +223,7 @@ namespace ignite * @param res Target array. * @param len Array length. */ - static void ReadUInt16Array(interop::InteropInputStream* stream, uint16_t* res, const int32_t len); + static void ReadUInt16Array(interop::InteropInputStream* stream, uint16_t* res, int32_t len); /** * Utility method to write unsigned 16-bit integer array to stream. @@ -231,7 +232,7 @@ namespace ignite * @param val Value. * @param len Array length. */ - static void WriteUInt16Array(interop::InteropOutputStream* stream, const uint16_t* val, const int32_t len); + static void WriteUInt16Array(interop::InteropOutputStream* stream, const uint16_t* val, int32_t len); /** * Utility method to read signed 32-bit integer from stream. @@ -276,7 +277,7 @@ namespace ignite * @param res Target array. * @param len Array length. */ - static void ReadInt32Array(interop::InteropInputStream* stream, int32_t* res, const int32_t len); + static void ReadInt32Array(interop::InteropInputStream* stream, int32_t* res, int32_t len); /** * Utility method to write signed 32-bit integer array to stream. @@ -285,7 +286,7 @@ namespace ignite * @param val Value. * @param len Array length. */ - static void WriteInt32Array(interop::InteropOutputStream* stream, const int32_t* val, const int32_t len); + static void WriteInt32Array(interop::InteropOutputStream* stream, const int32_t* val, int32_t len); /** * Utility method to read signed 64-bit integer from stream. @@ -310,7 +311,7 @@ namespace ignite * @param res Target array. * @param len Array length. */ - static void ReadInt64Array(interop::InteropInputStream* stream, int64_t* res, const int32_t len); + static void ReadInt64Array(interop::InteropInputStream* stream, int64_t* res, int32_t len); /** * Utility method to write signed 64-bit integer array to stream. @@ -319,7 +320,7 @@ namespace ignite * @param val Value. * @param len Array length. */ - static void WriteInt64Array(interop::InteropOutputStream* stream, const int64_t* val, const int32_t len); + static void WriteInt64Array(interop::InteropOutputStream* stream, const int64_t* val, int32_t len); /** * Utility method to read float from stream. @@ -344,7 +345,7 @@ namespace ignite * @param res Target array. * @param len Array length. */ - static void ReadFloatArray(interop::InteropInputStream* stream, float* res, const int32_t len); + static void ReadFloatArray(interop::InteropInputStream* stream, float* res, int32_t len); /** * Utility method to write float array to stream. @@ -353,7 +354,7 @@ namespace ignite * @param val Value. * @param len Array length. */ - static void WriteFloatArray(interop::InteropOutputStream* stream, const float* val, const int32_t len); + static void WriteFloatArray(interop::InteropOutputStream* stream, const float* val, int32_t len); /** * Utility method to read double from stream. @@ -378,7 +379,7 @@ namespace ignite * @param res Target array. * @param len Array length. */ - static void ReadDoubleArray(interop::InteropInputStream* stream, double* res, const int32_t len); + static void ReadDoubleArray(interop::InteropInputStream* stream, double* res, int32_t len); /** * Utility method to write double array to stream. @@ -387,13 +388,12 @@ namespace ignite * @param val Value. * @param len Array length. */ - static void WriteDoubleArray(interop::InteropOutputStream* stream, const double* val, const int32_t len); + static void WriteDoubleArray(interop::InteropOutputStream* stream, const double* val, int32_t len); /** * Utility method to read Guid from stream. * * @param stream Stream. - * @param res Value. */ static Guid ReadGuid(interop::InteropInputStream* stream); @@ -403,13 +403,12 @@ namespace ignite * @param stream Stream. * @param val Value. */ - static void WriteGuid(interop::InteropOutputStream* stream, const Guid val); + static void WriteGuid(interop::InteropOutputStream* stream, Guid val); /** * Utility method to read Date from stream. * * @param stream Stream. - * @param res Value. */ static Date ReadDate(interop::InteropInputStream* stream); @@ -419,7 +418,7 @@ namespace ignite * @param stream Stream. * @param val Value. */ - static void WriteDate(interop::InteropOutputStream* stream, const Date val); + static void WriteDate(interop::InteropOutputStream* stream, Date val); /** * Utility method to read Timestamp from stream. @@ -435,7 +434,7 @@ namespace ignite * @param stream Stream. * @param val Value. */ - static void WriteTimestamp(interop::InteropOutputStream* stream, const Timestamp val); + static void WriteTimestamp(interop::InteropOutputStream* stream, Timestamp val); /** * Utility method to read Time from stream. @@ -446,12 +445,41 @@ namespace ignite static Time ReadTime(interop::InteropInputStream* stream); /** - * Utility method to write Timestamp to stream. + * Utility method to write Time to stream. + * + * @param stream Stream. + * @param val Value. + */ + static void WriteTime(interop::InteropOutputStream* stream, Time val); + + /** + * Utility method to read BinaryEnumEntry from stream. + * + * @param stream Stream. + * @return Value. + */ + static ignite::binary::BinaryEnumEntry ReadBinaryEnumEntry(interop::InteropInputStream* stream); + + /** + * Utility method to write BinaryEnumEntry to stream. * * @param stream Stream. * @param val Value. */ - static void WriteTime(interop::InteropOutputStream* stream, const Time val); + static void WriteBinaryEnumEntry(interop::InteropOutputStream* stream, + ignite::binary::BinaryEnumEntry val) + { + WriteBinaryEnumEntry(stream, val.GetTypeId(), val.GetOrdinal()); + } + + /** + * Utility method to write Binary Enum Entry to stream. + * + * @param stream Stream. + * @param typeId Type ID. + * @param ordinal Ordinal. + */ + static void WriteBinaryEnumEntry(interop::InteropOutputStream* stream, int32_t typeId, int32_t ordinal); /** * Utility method to write string to stream. @@ -460,7 +488,7 @@ namespace ignite * @param val Value. * @param len Length. */ - static void WriteString(interop::InteropOutputStream* stream, const char* val, const int32_t len); + static void WriteString(interop::InteropOutputStream* stream, const char* val, int32_t len); /** * Get default value for the type. @@ -551,6 +579,12 @@ namespace ignite } template<> + inline ignite::binary::BinaryEnumEntry BinaryUtils::GetDefaultValue<ignite::binary::BinaryEnumEntry>() + { + return ignite::binary::BinaryEnumEntry(); + } + + template<> inline std::string BinaryUtils::GetDefaultValue<std::string>() { return std::string(); diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h index e6cd487..bc04620 100644 --- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h +++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h @@ -31,7 +31,6 @@ #include "ignite/impl/binary/binary_type_manager.h" #include "ignite/impl/binary/binary_utils.h" #include "ignite/impl/binary/binary_schema.h" -#include "ignite/impl/binary/binary_type_manager.h" #include "ignite/impl/binary/binary_object_impl.h" #include "ignite/binary/binary_consts.h" #include "ignite/binary/binary_type.h" @@ -50,6 +49,9 @@ namespace ignite { namespace binary { + // Forward declaration. + class BinaryTypeManager; + /** * Internal implementation of binary reader. */ @@ -523,6 +525,21 @@ namespace ignite void WriteStringElement(int32_t id, const char* val, int32_t len); /** + * Write binary enum entry. + * + * @param entry Binary enum entry. + */ + void WriteBinaryEnum(ignite::binary::BinaryEnumEntry entry); + + /** + * Write binary enum entry. + * + * @param fieldName Field name. + * @param entry Binary enum entry. + */ + void WriteBinaryEnum(const char* fieldName, ignite::binary::BinaryEnumEntry entry); + + /** * Write NULL value. */ void WriteNull(); @@ -542,7 +559,6 @@ namespace ignite /** * Start array write. * - * @param typ Collection type. * @return Session ID. */ int32_t WriteArray(); @@ -694,6 +710,55 @@ namespace ignite } /** + * Write enum entry. + * + * @param val Binary enum entry. + * + * @trapam T Enum type. BinaryEnum class template should be specialized for the type. + */ + template<typename T> + void WriteEnum(T val) + { + typedef ignite::binary::BinaryEnum<T> TypeMeta; + + if (TypeMeta::IsNull(val)) + { + WriteNull(); + + return; + } + + ignite::binary::BinaryEnumEntry entry(TypeMeta::GetTypeId(), TypeMeta::GetOrdinal(val)); + + WriteBinaryEnum(entry); + } + + /** + * Write enum entry. + * + * @param fieldName Field name. + * @param val Binary enum entry. + * + * @trapam T Enum type. BinaryEnum class template should be specialized for the type. + */ + template<typename T> + void WriteEnum(const char* fieldName, T val) + { + typedef ignite::binary::BinaryEnum<T> TypeMeta; + + if (TypeMeta::IsNull(val)) + { + WriteNull(fieldName); + + return; + } + + ignite::binary::BinaryEnumEntry entry(TypeMeta::GetTypeId(), TypeMeta::GetOrdinal(val)); + + WriteBinaryEnum(fieldName, entry); + } + + /** * Set raw mode. */ void SetRawMode(); diff --git a/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_input_stream.h b/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_input_stream.h index 3652516..2ba318b 100644 --- a/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_input_stream.h +++ b/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_input_stream.h @@ -199,7 +199,7 @@ namespace ignite /** * Set position. * - * @param Position. + * @param pos Position. */ void Position(int32_t pos); @@ -230,7 +230,7 @@ namespace ignite /** * Copy data from the stream shifting it along the way. * - * @param ptr Pointer to data. + * @param dest Pointer to data. * @param off Offset. * @param cnt Amount of data to copy. */ diff --git a/modules/platforms/cpp/binary/project/vs/binary.vcxproj b/modules/platforms/cpp/binary/project/vs/binary.vcxproj index 5b76f06..c973204 100644 --- a/modules/platforms/cpp/binary/project/vs/binary.vcxproj +++ b/modules/platforms/cpp/binary/project/vs/binary.vcxproj @@ -180,12 +180,14 @@ <ClInclude Include="..\..\include\ignite\binary\binary.h" /> <ClInclude Include="..\..\include\ignite\binary\binary_consts.h" /> <ClInclude Include="..\..\include\ignite\binary\binary_containers.h" /> + <ClInclude Include="..\..\include\ignite\binary\binary_enum.h" /> <ClInclude Include="..\..\include\ignite\binary\binary_object.h" /> <ClInclude Include="..\..\include\ignite\binary\binary_raw_reader.h" /> <ClInclude Include="..\..\include\ignite\binary\binary_raw_writer.h" /> <ClInclude Include="..\..\include\ignite\binary\binary_reader.h" /> <ClInclude Include="..\..\include\ignite\binary\binary_type.h" /> <ClInclude Include="..\..\include\ignite\binary\binary_writer.h" /> + <ClInclude Include="..\..\include\ignite\binary\binary_enum_entry.h" /> <ClInclude Include="..\..\include\ignite\impl\binary\binary_common.h" /> <ClInclude Include="..\..\include\ignite\impl\binary\binary_field_meta.h" /> <ClInclude Include="..\..\include\ignite\impl\binary\binary_id_resolver.h" /> diff --git a/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters b/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters index 573b5fa..e6528ea 100644 --- a/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters +++ b/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters @@ -103,6 +103,12 @@ <ClInclude Include="..\..\include\ignite\impl\binary\binary_type_impl.h"> <Filter>Code\impl\binary</Filter> </ClInclude> + <ClInclude Include="..\..\include\ignite\binary\binary_enum_entry.h"> + <Filter>Code\binary</Filter> + </ClInclude> + <ClInclude Include="..\..\include\ignite\binary\binary_enum.h"> + <Filter>Code\binary</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\src\binary\binary_containers.cpp"> diff --git a/modules/platforms/cpp/binary/src/binary/binary_raw_reader.cpp b/modules/platforms/cpp/binary/src/binary/binary_raw_reader.cpp index f751685..5f3dcc5 100644 --- a/modules/platforms/cpp/binary/src/binary/binary_raw_reader.cpp +++ b/modules/platforms/cpp/binary/src/binary/binary_raw_reader.cpp @@ -163,6 +163,11 @@ namespace ignite return BinaryStringArrayReader(impl, id, size); } + BinaryEnumEntry BinaryRawReader::ReadBinaryEnum() + { + return impl->ReadBinaryEnum(); + } + CollectionType::Type BinaryRawReader::ReadCollectionType() { return impl->ReadCollectionType(); diff --git a/modules/platforms/cpp/binary/src/binary/binary_raw_writer.cpp b/modules/platforms/cpp/binary/src/binary/binary_raw_writer.cpp index f2e94a5..703e1b4 100644 --- a/modules/platforms/cpp/binary/src/binary/binary_raw_writer.cpp +++ b/modules/platforms/cpp/binary/src/binary/binary_raw_writer.cpp @@ -169,6 +169,11 @@ namespace ignite return BinaryStringArrayWriter(impl, id); } + void BinaryRawWriter::WriteBinaryEnum(BinaryEnumEntry entry) + { + impl->WriteBinaryEnum(entry); + } + void BinaryRawWriter::WriteNull() { impl->WriteNull(); diff --git a/modules/platforms/cpp/binary/src/binary/binary_reader.cpp b/modules/platforms/cpp/binary/src/binary/binary_reader.cpp index 0ba82e6..ee4ba57 100644 --- a/modules/platforms/cpp/binary/src/binary/binary_reader.cpp +++ b/modules/platforms/cpp/binary/src/binary/binary_reader.cpp @@ -163,6 +163,11 @@ namespace ignite return BinaryStringArrayReader(impl, id, size); } + BinaryEnumEntry BinaryReader::ReadBinaryEnum(const char* fieldName) + { + return impl->ReadBinaryEnum(fieldName); + } + CollectionType::Type BinaryReader::ReadCollectionType(const char* fieldName) { return impl->ReadCollectionType(fieldName); diff --git a/modules/platforms/cpp/binary/src/binary/binary_writer.cpp b/modules/platforms/cpp/binary/src/binary/binary_writer.cpp index 6c549bb..edce91f 100644 --- a/modules/platforms/cpp/binary/src/binary/binary_writer.cpp +++ b/modules/platforms/cpp/binary/src/binary/binary_writer.cpp @@ -169,6 +169,11 @@ namespace ignite return BinaryStringArrayWriter(impl, id); } + void BinaryWriter::WriteBinaryEnum(const char* fieldName, BinaryEnumEntry entry) + { + impl->WriteBinaryEnum(fieldName, entry); + } + void BinaryWriter::WriteNull(const char* fieldName) { impl->WriteNull(fieldName); diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp index e3b57ed..7d4d4a1 100644 --- a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp +++ b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp @@ -17,7 +17,8 @@ #include <ignite/ignite_error.h> -#include "ignite/impl/interop/interop.h" +#include "ignite/impl/interop/interop_memory.h" +#include "ignite/impl/interop/interop_input_stream.h" #include "ignite/impl/interop/interop_stream_position_guard.h" #include "ignite/impl/binary/binary_common.h" #include "ignite/impl/binary/binary_id_resolver.h" @@ -375,7 +376,7 @@ namespace ignite return realLen; } - void BinaryReaderImpl::ReadTimestampArrayInternal(interop::InteropInputStream* stream, Timestamp* res, const int32_t len) + void BinaryReaderImpl::ReadTimestampArrayInternal(InteropInputStream* stream, Timestamp* res, const int32_t len) { for (int i = 0; i < len; i++) res[i] = ReadNullable<Timestamp>(stream, BinaryUtils::ReadTimestamp, IGNITE_TYPE_TIMESTAMP); @@ -389,7 +390,7 @@ namespace ignite return ReadNullable(stream, BinaryUtils::ReadTime, IGNITE_TYPE_TIME); } - int32_t BinaryReaderImpl::ReadTimeArray(Time * res, int32_t len) + int32_t BinaryReaderImpl::ReadTimeArray(Time* res, int32_t len) { CheckRawMode(true); CheckSingleMode(true); @@ -397,7 +398,7 @@ namespace ignite return ReadArrayInternal<Time>(res, len, stream, ReadTimeArrayInternal, IGNITE_TYPE_ARRAY_TIME); } - Time BinaryReaderImpl::ReadTime(const char * fieldName) + Time BinaryReaderImpl::ReadTime(const char* fieldName) { CheckRawMode(false); CheckSingleMode(true); @@ -413,7 +414,7 @@ namespace ignite return ReadNullable(stream, BinaryUtils::ReadTime, IGNITE_TYPE_TIME); } - int32_t BinaryReaderImpl::ReadTimeArray(const char * fieldName, Time * res, const int32_t len) + int32_t BinaryReaderImpl::ReadTimeArray(const char* fieldName, Time* res, const int32_t len) { CheckRawMode(false); CheckSingleMode(true); @@ -431,12 +432,49 @@ namespace ignite return realLen; } - void BinaryReaderImpl::ReadTimeArrayInternal(interop::InteropInputStream* stream, Time* res, const int32_t len) + void BinaryReaderImpl::ReadTimeArrayInternal(InteropInputStream* stream, Time* res, const int32_t len) { for (int i = 0; i < len; i++) res[i] = ReadNullable<Time>(stream, BinaryUtils::ReadTime, IGNITE_TYPE_TIME); } + BinaryEnumEntry BinaryReaderImpl::ReadBinaryEnum() + { + CheckRawMode(true); + CheckSingleMode(true); + + return ReadBinaryEnumInternal(); + } + + BinaryEnumEntry BinaryReaderImpl::ReadBinaryEnum(const char* fieldName) + { + CheckRawMode(false); + CheckSingleMode(true); + + int32_t fieldId = idRslvr->GetFieldId(typeId, fieldName); + int32_t fieldPos = FindField(fieldId); + + if (fieldPos <= 0) + return BinaryEnumEntry(); + + stream->Position(fieldPos); + + return ReadBinaryEnumInternal(); + } + + BinaryEnumEntry BinaryReaderImpl::ReadBinaryEnumInternal() + { + int8_t hdr = stream->ReadInt8(); + + if (hdr == IGNITE_TYPE_ENUM || hdr == IGNITE_TYPE_BINARY_ENUM) + return BinaryUtils::ReadBinaryEnumEntry(stream); + + if (hdr != IGNITE_HDR_NULL) + ThrowOnInvalidHeader(IGNITE_TYPE_ENUM, hdr); + + return BinaryUtils::GetDefaultValue<BinaryEnumEntry>(); + } + int32_t BinaryReaderImpl::ReadString(char* res, const int32_t len) { CheckRawMode(true); @@ -549,7 +587,8 @@ namespace ignite return realLen; } - else if (hdr != IGNITE_HDR_NULL) + + if (hdr != IGNITE_HDR_NULL) ThrowOnInvalidHeader(IGNITE_TYPE_STRING, hdr); return -1; @@ -879,21 +918,20 @@ namespace ignite } template <typename T> - T BinaryReaderImpl::ReadTopObject0(const int8_t expHdr, T(*func)(ignite::impl::interop::InteropInputStream*)) + T BinaryReaderImpl::ReadTopObject0(const int8_t expHdr, T(*func)(InteropInputStream*)) { int8_t typeId = stream->ReadInt8(); if (typeId == expHdr) return func(stream); - else if (typeId == IGNITE_HDR_NULL) + + if (typeId == IGNITE_HDR_NULL) return BinaryUtils::GetDefaultValue<T>(); - else - { - int32_t pos = stream->Position() - 1; - IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, - "Invalid header", "position", pos, "expected", (int)expHdr, "actual", (int)typeId) - } + int32_t pos = stream->Position() - 1; + + IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, + "Invalid header", "position", pos, "expected", (int)expHdr, "actual", (int)typeId) } InteropInputStream* BinaryReaderImpl::GetStream() @@ -992,23 +1030,18 @@ namespace ignite return elemId; } - else - { - *size = 0; - return ++elemIdGen; - } - } - else if (hdr == IGNITE_HDR_NULL) { - *size = -1; + *size = 0; return ++elemIdGen; } - else { + + if (hdr != IGNITE_HDR_NULL) ThrowOnInvalidHeader(expHdr, hdr); - return 0; - } + *size = -1; + + return ++elemIdGen; } void BinaryReaderImpl::CheckSession(int32_t expSes) const diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp index a583128..59b2fa1 100644 --- a/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp +++ b/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp @@ -24,6 +24,7 @@ using namespace ignite::impl::interop; using namespace ignite::impl::binary; +using namespace ignite::binary; namespace { @@ -108,7 +109,7 @@ namespace ignite return ReadPrimitive<int8_t>(mem, pos); } - int8_t BinaryUtils::UnsafeReadInt8(interop::InteropMemory& mem, int32_t pos) + int8_t BinaryUtils::UnsafeReadInt8(InteropMemory& mem, int32_t pos) { return UnsafeReadPrimitive<int8_t>(mem, pos); } @@ -153,12 +154,12 @@ namespace ignite return stream->ReadInt16(); } - int16_t BinaryUtils::ReadInt16(interop::InteropMemory& mem, int32_t pos) + int16_t BinaryUtils::ReadInt16(InteropMemory& mem, int32_t pos) { return ReadPrimitive<int16_t>(mem, pos); } - int16_t BinaryUtils::UnsafeReadInt16(interop::InteropMemory& mem, int32_t pos) + int16_t BinaryUtils::UnsafeReadInt16(InteropMemory& mem, int32_t pos) { return UnsafeReadPrimitive<int16_t>(mem, pos); } @@ -203,12 +204,12 @@ namespace ignite return stream->ReadInt32(); } - int32_t BinaryUtils::ReadInt32(interop::InteropMemory& mem, int32_t pos) + int32_t BinaryUtils::ReadInt32(InteropMemory& mem, int32_t pos) { return ReadPrimitive<int32_t>(mem, pos); } - int32_t BinaryUtils::UnsafeReadInt32(interop::InteropMemory& mem, int32_t pos) + int32_t BinaryUtils::UnsafeReadInt32(InteropMemory& mem, int32_t pos) { return UnsafeReadPrimitive<int32_t>(mem, pos); } @@ -288,7 +289,7 @@ namespace ignite stream->WriteDoubleArray(val, len); } - Guid BinaryUtils::ReadGuid(interop::InteropInputStream* stream) + Guid BinaryUtils::ReadGuid(InteropInputStream* stream) { int64_t most = stream->ReadInt64(); int64_t least = stream->ReadInt64(); @@ -296,25 +297,25 @@ namespace ignite return Guid(most, least); } - void BinaryUtils::WriteGuid(interop::InteropOutputStream* stream, const Guid val) + void BinaryUtils::WriteGuid(InteropOutputStream* stream, const Guid val) { stream->WriteInt64(val.GetMostSignificantBits()); stream->WriteInt64(val.GetLeastSignificantBits()); } - Date BinaryUtils::ReadDate(interop::InteropInputStream * stream) + Date BinaryUtils::ReadDate(InteropInputStream * stream) { int64_t milliseconds = stream->ReadInt64(); return Date(milliseconds); } - void BinaryUtils::WriteDate(interop::InteropOutputStream* stream, const Date val) + void BinaryUtils::WriteDate(InteropOutputStream* stream, const Date val) { stream->WriteInt64(val.GetMilliseconds()); } - Timestamp BinaryUtils::ReadTimestamp(interop::InteropInputStream* stream) + Timestamp BinaryUtils::ReadTimestamp(InteropInputStream* stream) { int64_t milliseconds = stream->ReadInt64(); int32_t nanoseconds = stream->ReadInt32(); @@ -322,25 +323,39 @@ namespace ignite return Timestamp(milliseconds / 1000, (milliseconds % 1000) * 1000000 + nanoseconds); } - void BinaryUtils::WriteTimestamp(interop::InteropOutputStream* stream, const Timestamp val) + void BinaryUtils::WriteTimestamp(InteropOutputStream* stream, const Timestamp val) { stream->WriteInt64(val.GetSeconds() * 1000 + val.GetSecondFraction() / 1000000); stream->WriteInt32(val.GetSecondFraction() % 1000000); } - Time BinaryUtils::ReadTime(interop::InteropInputStream* stream) + Time BinaryUtils::ReadTime(InteropInputStream* stream) { int64_t ms = stream->ReadInt64(); return Time(ms); } - void BinaryUtils::WriteTime(interop::InteropOutputStream* stream, const Time val) + void BinaryUtils::WriteTime(InteropOutputStream* stream, const Time val) { stream->WriteInt64(val.GetMilliseconds()); } - void BinaryUtils::WriteString(interop::InteropOutputStream* stream, const char* val, const int32_t len) + BinaryEnumEntry BinaryUtils::ReadBinaryEnumEntry(InteropInputStream* stream) + { + int32_t typeId = stream->ReadInt32(); + int32_t ordinal = stream->ReadInt32(); + + return BinaryEnumEntry(typeId, ordinal); + } + + void BinaryUtils::WriteBinaryEnumEntry(InteropOutputStream * stream, int32_t typeId, int32_t ordinal) + { + stream->WriteInt32(typeId); + stream->WriteInt32(ordinal); + } + + void BinaryUtils::WriteString(InteropOutputStream* stream, const char* val, const int32_t len) { stream->WriteInt32(len); stream->WriteInt8Array(reinterpret_cast<const int8_t*>(val), len); diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_writer_impl.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_writer_impl.cpp index 51be3a0..49197ec 100644 --- a/modules/platforms/cpp/binary/src/impl/binary/binary_writer_impl.cpp +++ b/modules/platforms/cpp/binary/src/impl/binary/binary_writer_impl.cpp @@ -521,6 +521,27 @@ namespace ignite elemCnt++; } + void BinaryWriterImpl::WriteBinaryEnum(BinaryEnumEntry entry) + { + CheckRawMode(true); + CheckSingleMode(true); + + stream->WriteInt8(IGNITE_TYPE_ENUM); + + BinaryUtils::WriteBinaryEnumEntry(stream, entry); + } + + void BinaryWriterImpl::WriteBinaryEnum(const char* fieldName, BinaryEnumEntry entry) + { + CheckRawMode(false); + CheckSingleMode(true); + + WriteFieldId(fieldName, IGNITE_TYPE_ENUM); + stream->WriteInt8(IGNITE_TYPE_ENUM); + + BinaryUtils::WriteBinaryEnumEntry(stream, entry); + } + void BinaryWriterImpl::WriteNull() { CheckRawMode(true); diff --git a/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h b/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h index 51aeff0..a509e22 100644 --- a/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h +++ b/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h @@ -130,6 +130,27 @@ namespace ignite_test return new DummyIdResolver(); } }; + + struct TestEnum + { + enum Type + { + TEST_ZERO, + + TEST_NON_ZERO, + + TEST_NEGATIVE_42 = -42, + + TEST_SOME_BIG = 1241267, + }; + }; + + struct TypeWithEnumField + { + int32_t i32Field; + TestEnum::Type enumField; + std::string strField; + }; } } } @@ -300,6 +321,43 @@ namespace ignite dst.val2 = rawReader.ReadInt32(); } }; + + template<> + struct BinaryEnum<gt::TestEnum::Type> : BinaryEnumDefaultAll<gt::TestEnum::Type> + { + /** + * Get binary object type name. + * + * @param dst Output type name. + */ + static void GetTypeName(std::string& dst) + { + dst = "TestEnum"; + } + }; + + template<> + struct BinaryType<gt::TypeWithEnumField> : BinaryTypeDefaultAll<gt::TypeWithEnumField> + { + static void GetTypeName(std::string& dst) + { + dst = "TypeWithEnumField"; + } + + static void Write(BinaryWriter& writer, const gt::TypeWithEnumField& obj) + { + writer.WriteInt32("i32Field", obj.i32Field); + writer.WriteEnum("enumField", obj.enumField); + writer.WriteString("strField", obj.strField); + } + + static void Read(BinaryReader& reader, gt::TypeWithEnumField& dst) + { + dst.i32Field = reader.ReadInt32("i32Field"); + dst.enumField = reader.ReadEnum<gt::TestEnum::Type>("enumField"); + dst.strField = reader.ReadString("strField"); + } + }; } } diff --git a/modules/platforms/cpp/core-test/src/binary_object_test.cpp b/modules/platforms/cpp/core-test/src/binary_object_test.cpp index 3abd26a..37a3a0d 100644 --- a/modules/platforms/cpp/core-test/src/binary_object_test.cpp +++ b/modules/platforms/cpp/core-test/src/binary_object_test.cpp @@ -21,6 +21,9 @@ #include <ignite/common/fixed_size_array.h> #include <ignite/binary/binary_object.h> #include <ignite/binary/binary_writer.h> +#include <ignite/binary/binary_enum.h> +#include <ignite/binary/binary_enum_entry.h> +#include <ignite/ignition.h> #include "ignite/binary_test_defs.h" #include "ignite/test_type.h" @@ -389,4 +392,118 @@ BOOST_AUTO_TEST_CASE(GetEnumValueInvalid) BOOST_CHECK_THROW(binObj.GetEnumValue(), IgniteError); } +void CheckBinaryEnumEntry(int32_t typeId, int32_t ordinal) +{ + InteropUnpooledMemory mem(1024); + InteropOutputStream outStream(&mem); + BinaryWriterImpl writer(&outStream, 0); + + BinaryEnumEntry original(typeId, ordinal); + + writer.WriteBinaryEnum(original); + + outStream.Synchronize(); + + InteropInputStream inStream(&mem); + BinaryReaderImpl reader(&inStream); + + BinaryEnumEntry result = reader.ReadBinaryEnum(); + + if (original.IsNull()) + { + BOOST_CHECK(result.IsNull()); + + return; + } + + BOOST_CHECK_EQUAL(original.GetTypeId(), result.GetTypeId()); + BOOST_CHECK_EQUAL(original.GetOrdinal(), result.GetOrdinal()); +} + +BOOST_AUTO_TEST_CASE(ReadWriteBinaryEnum) +{ + CheckBinaryEnumEntry(1234567, 42); + CheckBinaryEnumEntry(1234567, 1); + CheckBinaryEnumEntry(1, 1); + CheckBinaryEnumEntry(6754, 0); + CheckBinaryEnumEntry(0, 0); + CheckBinaryEnumEntry(0, 1); +} + +template<typename T> +void CheckUserEnum(T val) +{ + InteropUnpooledMemory mem(1024); + InteropOutputStream outStream(&mem); + BinaryWriterImpl writer(&outStream, 0); + + writer.WriteEnum(val); + + outStream.Synchronize(); + + InteropInputStream inStream(&mem); + BinaryReaderImpl reader(&inStream); + + T result = reader.ReadEnum<T>(); + + BOOST_CHECK_EQUAL(val, result); +} + +BOOST_AUTO_TEST_CASE(ReadWriteUserEnum) +{ + CheckUserEnum(TestEnum::TEST_ZERO); + CheckUserEnum(TestEnum::TEST_NON_ZERO); + CheckUserEnum(TestEnum::TEST_NEGATIVE_42); + CheckUserEnum(TestEnum::TEST_SOME_BIG); +} + +template<typename T> +void CheckUserEnumPtr(T val) +{ + InteropUnpooledMemory mem(1024); + InteropOutputStream outStream(&mem); + BinaryWriterImpl writer(&outStream, 0); + + writer.WriteEnum(&val); + + outStream.Synchronize(); + + InteropInputStream inStream(&mem); + BinaryReaderImpl reader(&inStream); + + T* result = reader.ReadEnum<T*>(); + + BOOST_CHECK_EQUAL(val, *result); + + delete result; +} + +BOOST_AUTO_TEST_CASE(ReadWriteUserEnumPtr) +{ + CheckUserEnumPtr(TestEnum::TEST_ZERO); + CheckUserEnumPtr(TestEnum::TEST_NON_ZERO); + CheckUserEnumPtr(TestEnum::TEST_NEGATIVE_42); + CheckUserEnumPtr(TestEnum::TEST_SOME_BIG); +} + +BOOST_AUTO_TEST_CASE(ReadWriteUserEnumNullPtr) +{ + InteropUnpooledMemory mem(1024); + InteropOutputStream outStream(&mem); + BinaryWriterImpl writer(&outStream, 0); + + writer.WriteEnum<TestEnum::Type*>(0); + + outStream.Synchronize(); + + InteropInputStream inStream(&mem); + BinaryReaderImpl reader(&inStream); + + TestEnum::Type* result = reader.ReadEnum<TestEnum::Type*>(); + + BOOST_CHECK(result == 0); + + delete result; +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/platforms/cpp/core-test/src/cache_test.cpp b/modules/platforms/cpp/core-test/src/cache_test.cpp index db09940..ff30f93 100644 --- a/modules/platforms/cpp/core-test/src/cache_test.cpp +++ b/modules/platforms/cpp/core-test/src/cache_test.cpp @@ -21,6 +21,7 @@ #include "ignite/ignite.h" #include "ignite/ignition.h" #include "ignite/test_utils.h" +#include "ignite/binary_test_defs.h" using namespace ignite; using namespace boost::unit_test; @@ -97,6 +98,29 @@ struct CacheTestSuiteFixture #endif } + void PutGetStructWithEnumField(int32_t i32Field, ignite_test::core::binary::TestEnum::Type enumField, + const std::string& strField) + { + typedef ignite_test::core::binary::TypeWithEnumField TypeWithEnumField; + + TypeWithEnumField val; + val.i32Field = i32Field; + val.enumField = enumField; + val.strField = strField; + + cache::Cache<int, TypeWithEnumField> cache = grid0.GetOrCreateCache<int, TypeWithEnumField>("PutGetStructWithEnumField"); + + BOOST_TEST_CHECKPOINT("Putting value into the cache"); + cache.Put(i32Field, val); + + BOOST_TEST_CHECKPOINT("Getting value from the cache"); + TypeWithEnumField res = cache.Get(i32Field); + + BOOST_CHECK_EQUAL(val.i32Field, res.i32Field); + BOOST_CHECK_EQUAL(val.enumField, res.enumField); + BOOST_CHECK_EQUAL(val.strField, res.strField); + } + /* * Destructor. */ @@ -203,7 +227,7 @@ BOOST_AUTO_TEST_CASE(TestPutAll) for (int i = 0; i < 100; i++) map[i] = i + 1; - + cache::Cache<int, int> cache = Cache(); cache.PutAll(map); @@ -259,7 +283,7 @@ BOOST_AUTO_TEST_CASE(TestGet) BOOST_REQUIRE(1 == cache.Get(1)); BOOST_REQUIRE(2 == cache.Get(2)); - + BOOST_REQUIRE(0 == cache.Get(3)); } @@ -268,7 +292,7 @@ BOOST_AUTO_TEST_CASE(TestGetAll) cache::Cache<int, int> cache = Cache(); int keys[] = { 1, 2, 3, 4, 5 }; - + std::set<int> keySet (keys, keys + 5); for (int i = 0; i < static_cast<int>(keySet.size()); i++) @@ -366,14 +390,14 @@ BOOST_AUTO_TEST_CASE(TestContainsKey) BOOST_REQUIRE(true == cache.ContainsKey(1)); BOOST_REQUIRE(true == cache.Remove(1)); - + BOOST_REQUIRE(false == cache.ContainsKey(1)); } BOOST_AUTO_TEST_CASE(TestContainsKeys) { cache::Cache<int, int> cache = Cache(); - + int keys[] = { 1, 2 }; std::set<int> keySet(keys, keys + 2); @@ -382,7 +406,7 @@ BOOST_AUTO_TEST_CASE(TestContainsKeys) cache.Put(1, 1); cache.Put(2, 2); - + BOOST_REQUIRE(true == cache.ContainsKeys(keySet)); cache.Remove(1); @@ -691,4 +715,18 @@ BOOST_AUTO_TEST_CASE(TestGetBigString) BOOST_REQUIRE(longStr == cache.Get(5)); } +BOOST_AUTO_TEST_CASE(TestPutGetStructWithEnumField) +{ + typedef ignite_test::core::binary::TestEnum TestEnum; + + PutGetStructWithEnumField(0, TestEnum::TEST_ZERO, ""); + PutGetStructWithEnumField(1, TestEnum::TEST_ZERO, ""); + PutGetStructWithEnumField(0, TestEnum::TEST_NON_ZERO, ""); + PutGetStructWithEnumField(0, TestEnum::TEST_ZERO, "Lorem ipsum"); + PutGetStructWithEnumField(1, TestEnum::TEST_NON_ZERO, "Lorem ipsum"); + + PutGetStructWithEnumField(13, TestEnum::TEST_NEGATIVE_42, "hishib"); + PutGetStructWithEnumField(1337, TestEnum::TEST_SOME_BIG, "Some test value"); +} + BOOST_AUTO_TEST_SUITE_END()