You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by yz...@apache.org on 2017/01/26 14:53:12 UTC

[13/15] ignite git commit: IGNITE-1466: CPP: Added initial BinaryObject implementation. This closes #1448.

IGNITE-1466: CPP: Added initial BinaryObject implementation. This closes #1448.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/9d64a281
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/9d64a281
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/9d64a281

Branch: refs/heads/ignite-comm-balance-master
Commit: 9d64a281b89d447c92fc8181190d0554ea3f5755
Parents: 58b49b6
Author: isapego <ig...@gmail.com>
Authored: Thu Jan 26 15:02:03 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Thu Jan 26 15:02:03 2017 +0300

----------------------------------------------------------------------
 modules/platforms/cpp/binary/Makefile.am        |   2 +
 .../platforms/cpp/binary/include/Makefile.am    |   3 +
 .../cpp/binary/include/ignite/binary/binary.h   |  15 +-
 .../include/ignite/binary/binary_object.h       |  77 +++++
 .../ignite/impl/binary/binary_object_header.h   | 250 ++++++++++++++++
 .../ignite/impl/binary/binary_object_impl.h     | 102 +++++++
 .../include/ignite/impl/binary/binary_schema.h  |   2 +-
 .../include/ignite/impl/binary/binary_utils.h   |  61 ++++
 .../cpp/binary/project/vs/binary.vcxproj        |   5 +
 .../binary/project/vs/binary.vcxproj.filters    |  15 +
 .../src/impl/binary/binary_object_header.cpp    |  51 ++++
 .../src/impl/binary/binary_object_impl.cpp      |  52 ++++
 .../cpp/binary/src/impl/binary/binary_utils.cpp |  83 ++++++
 .../src/impl/binary/binary_writer_impl.cpp      |   2 +-
 modules/platforms/cpp/core-test/Makefile.am     |   1 +
 .../core-test/include/ignite/binary_test_defs.h |  25 ++
 .../cpp/core-test/include/ignite/complex_type.h | 135 +++++++++
 .../cpp/core-test/include/ignite/test_type.h    | 186 ++++++++++++
 .../cpp/core-test/project/vs/core-test.vcxproj  |   3 +
 .../project/vs/core-test.vcxproj.filters        |  16 +-
 .../cpp/core-test/src/binary_object_test.cpp    | 282 +++++++++++++++++++
 21 files changed, 1357 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/Makefile.am b/modules/platforms/cpp/binary/Makefile.am
index 5ffc4fd..cee87cd 100644
--- a/modules/platforms/cpp/binary/Makefile.am
+++ b/modules/platforms/cpp/binary/Makefile.am
@@ -60,6 +60,8 @@ libignite_binary_la_SOURCES = \
     src/impl/binary/binary_type_updater.cpp \
     src/impl/binary/binary_schema.cpp \
     src/impl/binary/binary_type_snapshot.cpp \
+    src/impl/binary/binary_object_header.cpp \
+    src/impl/binary/binary_object_impl.cpp \
     src/impl/interop/interop_memory.cpp \
     src/impl/interop/interop_output_stream.cpp \
     src/impl/interop/interop_input_stream.cpp

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/include/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/include/Makefile.am b/modules/platforms/cpp/binary/include/Makefile.am
index d3211a3..2795cbc 100644
--- a/modules/platforms/cpp/binary/include/Makefile.am
+++ b/modules/platforms/cpp/binary/include/Makefile.am
@@ -26,6 +26,7 @@ nobase_include_HEADERS = \
     ignite/binary/binary.h \
     ignite/binary/binary_consts.h \
     ignite/binary/binary_type.h \
+    ignite/binary/binary_object.h \
     ignite/impl/binary/binary_type_handler.h \
     ignite/impl/binary/binary_id_resolver.h \
     ignite/impl/binary/binary_type_manager.h \
@@ -36,6 +37,8 @@ nobase_include_HEADERS = \
     ignite/impl/binary/binary_reader_impl.h \
     ignite/impl/binary/binary_schema.h \
     ignite/impl/binary/binary_utils.h \
+    ignite/impl/binary/binary_object_header.h \
+    ignite/impl/binary/binary_object_impl.h \
     ignite/impl/interop/interop_memory.h \
     ignite/impl/interop/interop.h \
     ignite/impl/interop/interop_stream_position_guard.h \

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/include/ignite/binary/binary.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary.h b/modules/platforms/cpp/binary/include/ignite/binary/binary.h
index bfe23f4..d8c5404 100644
--- a/modules/platforms/cpp/binary/include/ignite/binary/binary.h
+++ b/modules/platforms/cpp/binary/include/ignite/binary/binary.h
@@ -23,12 +23,13 @@
 #ifndef _IGNITE_BINARY_BINARY
 #define _IGNITE_BINARY_BINARY
 
-#include "ignite/binary/binary_consts.h"
-#include "ignite/binary/binary_containers.h"
-#include "ignite/binary/binary_type.h"
-#include "ignite/binary/binary_raw_reader.h"
-#include "ignite/binary/binary_raw_writer.h"
-#include "ignite/binary/binary_reader.h"
-#include "ignite/binary/binary_writer.h"
+#include <ignite/binary/binary_consts.h>
+#include <ignite/binary/binary_containers.h>
+#include <ignite/binary/binary_type.h>
+#include <ignite/binary/binary_object.h>
+#include <ignite/binary/binary_raw_reader.h>
+#include <ignite/binary/binary_raw_writer.h>
+#include <ignite/binary/binary_reader.h>
+#include <ignite/binary/binary_writer.h>
 
 #endif //_IGNITE_BINARY_BINARY
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/include/ignite/binary/binary_object.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_object.h b/modules/platforms/cpp/binary/include/ignite/binary/binary_object.h
new file mode 100644
index 0000000..41907d0
--- /dev/null
+++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_object.h
@@ -0,0 +1,77 @@
+/*
+ * 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::BinaryObject class.
+ */
+
+#ifndef _IGNITE_BINARY_BINARY_OBJECT
+#define _IGNITE_BINARY_BINARY_OBJECT
+
+#include <stdint.h>
+
+#include <ignite/impl/interop/interop.h>
+#include <ignite/impl/binary/binary_reader_impl.h>
+#include <ignite/impl/binary/binary_object_impl.h>
+
+namespace ignite
+{
+    namespace binary
+    {
+        /**
+         * Binary object.
+         *
+         * This is a thin wrapper over the memory area that contains serialized
+         * binary object. Provides method that allows deserialize object.
+         */
+        class IGNITE_IMPORT_EXPORT BinaryObject : private impl::binary::BinaryObjectImpl
+        {
+        public:
+            /// @cond INTERNAL
+            /**
+             * Constructor.
+             *
+             * @param mem Binary object memory.
+             * @param start Object starting position in memory.
+             */
+            BinaryObject(impl::interop::InteropMemory& mem, int32_t start) : 
+                BinaryObjectImpl(mem, start)
+            {
+                // No-op.
+            };
+            /// @endcond
+
+            /**
+             * Deserialize object.
+             * @throw IgniteError if the object can not be deserialized to specified type.
+             *
+             * @return Deserialized value.
+             */
+            template<typename T>
+            T Deserialize() const
+            {
+                return impl::binary::BinaryObjectImpl::Deserialize<T>();
+            }
+
+        private:
+            IGNITE_NO_COPY_ASSIGNMENT(BinaryObject)
+        };
+    }
+}
+
+#endif //_IGNITE_BINARY_BINARY_OBJECT
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_object_header.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_object_header.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_object_header.h
new file mode 100644
index 0000000..5ba1960
--- /dev/null
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_object_header.h
@@ -0,0 +1,250 @@
+/*
+ * 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::impl::binary::BinaryObjectHeader class.
+ */
+
+#ifndef _IGNITE_IMPL_BINARY_BINARY_OBJECT_HEADER
+#define _IGNITE_IMPL_BINARY_BINARY_OBJECT_HEADER
+
+#include <stdint.h>
+
+#include <ignite/common/common.h>
+
+#include <ignite/impl/binary/binary_common.h>
+#include <ignite/impl/interop/interop_memory.h>
+
+namespace ignite
+{
+    namespace impl
+    {
+        namespace binary
+        {
+
+            // This is a packed structure - we do not want padding for our fields here.
+#pragma pack(push, 1)
+
+            /**
+             * Binary object header layout.
+             */
+            struct IGNITE_IMPORT_EXPORT BinaryObjectHeaderLayout
+            {
+                int8_t  headerType;
+                int8_t  version;
+                int16_t flags;
+                int32_t typeId;
+                int32_t hashCode;
+                int32_t length;
+                int32_t schemaId;
+                int32_t schemaOffset;
+            };
+
+#pragma pack(pop)
+
+            /**
+             * Binary object header class.
+             *
+             * @note Most methods are defined in header to encourage inlining.
+             */
+            class IGNITE_IMPORT_EXPORT BinaryObjectHeader
+            {
+            public:
+                // Header size in bytes.
+                enum { SIZE = sizeof(BinaryObjectHeaderLayout) };
+
+                /**
+                 * Create from InteropMemory instance.
+                 * @throw IgniteError if the memory at the specified offset
+                 *    is not a valid BinaryObject.
+                 *
+                 * @param mem Memory.
+                 * @param offset Offset in memory.
+                 * @return New BinaryObjectHeader instance.
+                 */
+                static BinaryObjectHeader FromMemory(interop::InteropMemory& mem, int32_t offset);
+
+                /**
+                 * Constructor.
+                 *
+                 * @param mem Pointer to header memory.
+                 */
+                BinaryObjectHeader(void* mem) :
+                    header(reinterpret_cast<BinaryObjectHeaderLayout*>(mem))
+                {
+                    // No-op. 
+                }
+
+                /**
+                 * Copy constructor.
+                 *
+                 * @param other Instance to copy.
+                 */
+                BinaryObjectHeader(const BinaryObjectHeader& other) : 
+                    header(other.header)
+                {
+                    // No-op.
+                }
+
+                /**
+                 * Assingment operator.
+                 *
+                 * @param other Other instance.
+                 * @return Reference to this.
+                 */
+                BinaryObjectHeader& operator=(const BinaryObjectHeader& other)
+                {
+                    header = other.header;
+
+                    return *this;
+                }
+
+                /**
+                 * Get header type.
+                 *
+                 * @return Header type.
+                 */
+                int8_t GetType() const
+                {
+                    return header->headerType;
+                }
+
+                /**
+                 * Get version.
+                 *
+                 * @return Binary object layout version.
+                 */
+                int8_t GetVersion() const
+                {
+                    return header->version;
+                }
+
+                /**
+                 * Get flags.
+                 *
+                 * @return Flags.
+                 */
+                int16_t GetFlags() const
+                {
+                    return header->flags;
+                }
+
+                /**
+                 * Get type ID.
+                 *
+                 * @return Type ID.
+                 */
+                int32_t GetTypeId() const
+                {
+                    return header->typeId;
+                }
+
+                /**
+                 * Get hash code.
+                 *
+                 * @return Hash code.
+                 */
+                int32_t GetHashCode() const
+                {
+                    return header->hashCode;
+                }
+
+                /**
+                 * Get object length.
+                 *
+                 * @return Object length.
+                 */
+                int32_t GetLength() const
+                {
+                    return header->length;
+                }
+
+                /**
+                 * Get schema ID.
+                 *
+                 * @return Schema ID.
+                 */
+                int32_t GetSchemaId() const
+                {
+                    return header->schemaId;
+                }
+
+                /**
+                 * Get schema offset.
+                 *
+                 * @return Schema offset.
+                 */
+                int32_t GetSchemaOffset() const
+                {
+                    return header->schemaOffset;
+                }
+
+                /**
+                 * Check if the binary object has schema.
+                 *
+                 * @return True if the binary object has schema.
+                 */
+                bool HasSchema() const
+                {
+                    return (header->flags & IGNITE_BINARY_FLAG_HAS_SCHEMA) != 0;
+                }
+
+                /**
+                 * Check if the binary object is of user-defined type.
+                 *
+                 * @return True if the binary object is of user-defined type.
+                 */
+                bool IsUserType() const
+                {
+                    return (header->flags & IGNITE_BINARY_FLAG_USER_TYPE) != 0;
+                }
+
+                /**
+                 * Get footer offset.
+                 *
+                 * @return Footer offset.
+                 */
+                int32_t GetFooterOffset() const
+                {
+                    // No schema: all we have is data. There is no offset in last 4 bytes.
+                    if (!HasSchema())
+                        return GetLength();
+
+                    // There is schema. Regardless of raw data presence, footer starts with schema.
+                    return GetSchemaOffset();
+                }
+
+                /**
+                 * Get size of data without header and footer.
+                 *
+                 * @return Data length.
+                 */
+                int32_t GetDataLength() const
+                {
+                    return GetFooterOffset() - SIZE;
+                }
+
+            private:
+                /** Header layout */
+                BinaryObjectHeaderLayout* header;
+            };
+        }
+    }
+}
+
+#endif //_IGNITE_IMPL_BINARY_BINARY_OBJECT_HEADER
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_object_impl.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_object_impl.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_object_impl.h
new file mode 100644
index 0000000..288ba26
--- /dev/null
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_object_impl.h
@@ -0,0 +1,102 @@
+/*
+ * 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::BinaryObject class.
+ */
+
+#ifndef _IGNITE_IMPL_BINARY_BINARY_OBJECT_IMPL
+#define _IGNITE_IMPL_BINARY_BINARY_OBJECT_IMPL
+
+#include <stdint.h>
+
+#include <ignite/impl/interop/interop.h>
+#include <ignite/impl/binary/binary_reader_impl.h>
+
+namespace ignite
+{
+    namespace impl
+    {
+        namespace binary
+        {
+            /**
+             * Binary object implementation.
+             *
+             * This is a thin wrapper over the memory area that contains serialized
+             * binary object. Provides some methods that allow to access object's
+             * data without deserialization. Also provides method that allows
+             * deserialize object.
+             */
+            class IGNITE_IMPORT_EXPORT BinaryObjectImpl
+            {
+            public:
+                /**
+                 * Constructor.
+                 *
+                 * @param mem Binary object memory.
+                 * @param start Object starting position in memory.
+                 */
+                BinaryObjectImpl(interop::InteropMemory& mem, int32_t start);
+
+                /**
+                 * Deserialize object.
+                 * @throw IgniteError if the object can not be deserialized to specified type.
+                 *
+                 * @return Deserialized value.
+                 */
+                template<typename T>
+                T Deserialize() const
+                {
+                    interop::InteropInputStream stream(&mem);
+
+                    stream.Position(start);
+                    BinaryReaderImpl reader(&stream);
+
+                    return reader.ReadObject<T>();
+                }
+
+                /**
+                 * Get object data.
+                 * @throw IgniteError if the object is not in a valid state.
+                 *
+                 * @return Pointer to object data.
+                 */
+                const int8_t* GetData() const;
+
+                /**
+                 * Get object length.
+                 * @throw IgniteError if the object is not in a valid state.
+                 *
+                 * @return Object length.
+                 */
+                int32_t GetLength() const;
+
+            private:
+                IGNITE_NO_COPY_ASSIGNMENT(BinaryObjectImpl)
+
+                /** Underlying object memory. */
+                interop::InteropMemory& mem;
+
+                /** Object starting position in memory. */
+                int32_t start;
+            };
+        }
+    }
+}
+
+#endif //_IGNITE_IMPL_BINARY_BINARY_OBJECT_IMPL
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_schema.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_schema.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_schema.h
index 756a3f7..cf97f8d 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_schema.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_schema.h
@@ -67,7 +67,7 @@ namespace ignite
                 /**
                  * Add another field to schema.
                  *
-                 * @param id Field id.
+                 * @param fieldId Field id.
                  * @param offset Field offset.
                  */
                 void AddField(int32_t fieldId, int32_t offset);

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_utils.h
----------------------------------------------------------------------
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 3abd651..9599fce 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
@@ -36,6 +36,7 @@ namespace ignite
         {
             class InteropInputStream;
             class InteropOutputStream;
+            class InteropMemory;
         }
 
         namespace binary
@@ -55,6 +56,26 @@ namespace ignite
                 static int8_t ReadInt8(interop::InteropInputStream* stream);
 
                 /**
+                 * Utility method to read signed 8-bit integer from memory.
+                 * @throw IgniteError if there is not enough memory.
+                 *
+                 * @param mem Memory.
+                 * @param pos Position in memory.
+                 * @return Value.
+                 */
+                static int8_t ReadInt8(interop::InteropMemory& mem, int32_t pos);
+
+                /**
+                 * Utility method to read signed 8-bit integer from memory.
+                 * @warning Does not check if there is enough data in memory to read.
+                 *
+                 * @param mem Memory.
+                 * @param pos Position in memory.
+                 * @return Value.
+                 */
+                static int8_t UnsafeReadInt8(interop::InteropMemory& mem, int32_t pos);
+
+                /**
                  * Utility method to write signed 8-bit integer to stream.
                  *
                  * @param stream Stream.
@@ -123,6 +144,26 @@ namespace ignite
                 static int16_t ReadInt16(interop::InteropInputStream* stream);
 
                 /**
+                 * Utility method to read signed 16-bit integer from memory.
+                 * @throw IgniteError if there is not enough memory.
+                 *
+                 * @param mem Memory.
+                 * @param pos Position in memory.
+                 * @return Value.
+                 */
+                static int16_t ReadInt16(interop::InteropMemory& mem, int32_t pos);
+
+                /**
+                 * Utility method to read signed 16-bit integer from memory.
+                 * @warning Does not check if there is enough data in memory to read.
+                 *
+                 * @param mem Memory.
+                 * @param pos Position in memory.
+                 * @return Value.
+                 */
+                static int16_t UnsafeReadInt16(interop::InteropMemory& mem, int32_t pos);
+
+                /**
                  * Utility method to write signed 16-bit integer to stream.
                  *
                  * @param stream Stream.
@@ -191,6 +232,26 @@ namespace ignite
                 static int32_t ReadInt32(interop::InteropInputStream* stream);
 
                 /**
+                 * Utility method to read signed 32-bit integer from memory.
+                 * @throw IgniteError if there is not enough memory.
+                 *
+                 * @param mem Memory.
+                 * @param pos Position in memory.
+                 * @return Value.
+                 */
+                static int32_t ReadInt32(interop::InteropMemory& mem, int32_t pos);
+
+                /**
+                 * Utility method to read signed 32-bit integer from memory.
+                 * @warning Does not check if there is enough data in memory to read.
+                 *
+                 * @param mem Memory.
+                 * @param pos Position in memory.
+                 * @return Value.
+                 */
+                static int32_t UnsafeReadInt32(interop::InteropMemory& mem, int32_t pos);
+
+                /**
                  * Utility method to write signed 32-bit integer to stream.
                  *
                  * @param stream Stream.

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/project/vs/binary.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/project/vs/binary.vcxproj b/modules/platforms/cpp/binary/project/vs/binary.vcxproj
index a29b361..887eb96 100644
--- a/modules/platforms/cpp/binary/project/vs/binary.vcxproj
+++ b/modules/platforms/cpp/binary/project/vs/binary.vcxproj
@@ -180,6 +180,7 @@
     <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_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" />
@@ -187,6 +188,8 @@
     <ClInclude Include="..\..\include\ignite\binary\binary_writer.h" />
     <ClInclude Include="..\..\include\ignite\impl\binary\binary_common.h" />
     <ClInclude Include="..\..\include\ignite\impl\binary\binary_id_resolver.h" />
+    <ClInclude Include="..\..\include\ignite\impl\binary\binary_object_header.h" />
+    <ClInclude Include="..\..\include\ignite\impl\binary\binary_object_impl.h" />
     <ClInclude Include="..\..\include\ignite\impl\binary\binary_reader_impl.h" />
     <ClInclude Include="..\..\include\ignite\impl\binary\binary_schema.h" />
     <ClInclude Include="..\..\include\ignite\impl\binary\binary_type_handler.h" />
@@ -208,6 +211,8 @@
     <ClCompile Include="..\..\src\binary\binary_reader.cpp" />
     <ClCompile Include="..\..\src\binary\binary_type.cpp" />
     <ClCompile Include="..\..\src\binary\binary_writer.cpp" />
+    <ClCompile Include="..\..\src\impl\binary\binary_object_header.cpp" />
+    <ClCompile Include="..\..\src\impl\binary\binary_object_impl.cpp" />
     <ClCompile Include="..\..\src\impl\binary\binary_reader_impl.cpp" />
     <ClCompile Include="..\..\src\impl\binary\binary_schema.cpp" />
     <ClCompile Include="..\..\src\impl\binary\binary_type_handler.cpp" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters b/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters
index 09aca58..a1a83ef 100644
--- a/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters
+++ b/modules/platforms/cpp/binary/project/vs/binary.vcxproj.filters
@@ -88,6 +88,15 @@
     <ClInclude Include="..\..\include\ignite\impl\interop\interop_stream_position_guard.h">
       <Filter>Code\impl\interop</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\ignite\binary\binary_object.h">
+      <Filter>Code\binary</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\impl\binary\binary_object_header.h">
+      <Filter>Code\impl\binary</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\impl\binary\binary_object_impl.h">
+      <Filter>Code\impl\binary</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\binary\binary_containers.cpp">
@@ -141,5 +150,11 @@
     <ClCompile Include="..\..\src\impl\interop\interop_output_stream.cpp">
       <Filter>Code\impl\interop</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\impl\binary\binary_object_header.cpp">
+      <Filter>Code\impl\binary</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\impl\binary\binary_object_impl.cpp">
+      <Filter>Code\impl\binary</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/src/impl/binary/binary_object_header.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_object_header.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_object_header.cpp
new file mode 100644
index 0000000..aef095f
--- /dev/null
+++ b/modules/platforms/cpp/binary/src/impl/binary/binary_object_header.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#include <ignite/ignite_error.h>
+
+#include <ignite/impl/binary/binary_object_header.h>
+
+namespace ignite
+{
+    namespace impl
+    {
+        namespace binary
+        {
+            BinaryObjectHeader BinaryObjectHeader::FromMemory(interop::InteropMemory& mem, int32_t offset)
+            {
+                if ((mem.Length() - offset) < SIZE)
+                {
+                    IGNITE_ERROR_FORMATTED_3(ignite::IgniteError::IGNITE_ERR_MEMORY,
+                        "Not enough data in the binary object", "memPtr", mem.PointerLong(),
+                        "len", mem.Length(), "headerLen", SIZE);
+                }
+
+                BinaryObjectHeader hdr(mem.Data() + offset);
+
+                int8_t type = hdr.GetType();
+                if (type != impl::binary::IGNITE_TYPE_OBJECT)
+                {
+                    IGNITE_ERROR_FORMATTED_3(ignite::IgniteError::IGNITE_ERR_MEMORY,
+                        "Not enough data in the binary object", "memPtr", mem.PointerLong(),
+                        "type", type, "expected", impl::binary::IGNITE_TYPE_OBJECT);
+                }
+
+                return hdr;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/src/impl/binary/binary_object_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_object_impl.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_object_impl.cpp
new file mode 100644
index 0000000..652d54d
--- /dev/null
+++ b/modules/platforms/cpp/binary/src/impl/binary/binary_object_impl.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#include <ignite/impl/binary/binary_object_header.h>
+#include <ignite/impl/binary/binary_object_impl.h>
+
+using namespace ignite::impl::binary;
+
+namespace ignite
+{
+    namespace impl
+    {
+        namespace binary
+        {
+            BinaryObjectImpl::BinaryObjectImpl(impl::interop::InteropMemory& mem, int32_t start) :
+                mem(mem),
+                start(start)
+            {
+                // No-op.
+            }
+
+            const int8_t* BinaryObjectImpl::GetData() const
+            {
+                // Creating header here to validate object header layout.
+                BinaryObjectHeader header = BinaryObjectHeader::FromMemory(mem, start);
+
+                return mem.Data() + start + BinaryObjectHeader::SIZE;
+            }
+
+            int32_t BinaryObjectImpl::GetLength() const
+            {
+                BinaryObjectHeader header = BinaryObjectHeader::FromMemory(mem, start);
+
+                return header.GetDataLength();
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp
----------------------------------------------------------------------
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 22738ef..bffd038 100644
--- a/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp
+++ b/modules/platforms/cpp/binary/src/impl/binary/binary_utils.cpp
@@ -17,12 +17,65 @@
 
 #include <time.h>
 
+#include "ignite/ignite_error.h"
+
 #include "ignite/impl/interop/interop.h"
 #include "ignite/impl/binary/binary_utils.h"
 
 using namespace ignite::impl::interop;
 using namespace ignite::impl::binary;
 
+namespace
+{
+    /**
+     * Check if there is enough data in memory.
+     * @throw IgniteError if there is not enough memory.
+     *
+     * @param mem Memory.
+     * @param pos Position.
+     * @param len Data to read.
+     */
+    inline void CheckEnoughData(InteropMemory& mem, int32_t pos, int32_t len)
+    {
+        if (mem.Length() < (pos + len))
+        {
+            IGNITE_ERROR_FORMATTED_4(ignite::IgniteError::IGNITE_ERR_MEMORY, "Not enough data in "
+                "the binary object", "memPtr", mem.PointerLong(), "len", mem.Length(), "pos", pos,
+                "requested", len);
+        }
+    }
+
+    /**
+     * Read primitive int type from the specific place in memory.
+     * @throw IgniteError if there is not enough memory.
+     *
+     * @param mem Memory.
+     * @param pos Position.
+     * @return Primitive.
+     */
+    template<typename T>
+    inline T ReadPrimitive(InteropMemory& mem, int32_t pos)
+    {
+        CheckEnoughData(mem, pos, sizeof(T));
+
+        return *reinterpret_cast<T*>(mem.Data() + pos);
+    }
+
+    /**
+     * Read primitive int type from the specific place in memory.
+     * @warning Does not check if there is enough data in memory to read.
+     *
+     * @param mem Memory.
+     * @param pos Position.
+     * @return Primitive.
+     */
+    template<typename T>
+    inline T UnsafeReadPrimitive(InteropMemory& mem, int32_t pos)
+    {
+        return *reinterpret_cast<T*>(mem.Data() + pos);
+    }
+}
+
 namespace ignite
 {
     namespace impl
@@ -34,6 +87,16 @@ namespace ignite
                 return stream->ReadInt8();
             }
 
+            int8_t BinaryUtils::ReadInt8(InteropMemory& mem, int32_t pos)
+            {
+                return ReadPrimitive<int8_t>(mem, pos);
+            }
+
+            int8_t BinaryUtils::UnsafeReadInt8(interop::InteropMemory& mem, int32_t pos)
+            {
+                return UnsafeReadPrimitive<int8_t>(mem, pos);
+            }
+
             void BinaryUtils::WriteInt8(InteropOutputStream* stream, int8_t val)
             {
                 stream->WriteInt8(val); 
@@ -74,6 +137,16 @@ namespace ignite
                 return stream->ReadInt16();
             }
 
+            int16_t BinaryUtils::ReadInt16(interop::InteropMemory& mem, int32_t pos)
+            {
+                return ReadPrimitive<int16_t>(mem, pos);
+            }
+
+            int16_t BinaryUtils::UnsafeReadInt16(interop::InteropMemory& mem, int32_t pos)
+            {
+                return UnsafeReadPrimitive<int16_t>(mem, pos);
+            }
+
             void BinaryUtils::WriteInt16(InteropOutputStream* stream, int16_t val)
             {
                 stream->WriteInt16(val);
@@ -114,6 +187,16 @@ namespace ignite
                 return stream->ReadInt32();
             }
 
+            int32_t BinaryUtils::ReadInt32(interop::InteropMemory& mem, int32_t pos)
+            {
+                return ReadPrimitive<int32_t>(mem, pos);
+            }
+
+            int32_t BinaryUtils::UnsafeReadInt32(interop::InteropMemory& mem, int32_t pos)
+            {
+                return UnsafeReadPrimitive<int32_t>(mem, pos);
+            }
+
             void BinaryUtils::WriteInt32(InteropOutputStream* stream, int32_t val)
             {
                 stream->WriteInt32(val);

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/binary/src/impl/binary/binary_writer_impl.cpp
----------------------------------------------------------------------
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 5df0c2a..20fb74d 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
@@ -736,7 +736,7 @@ namespace ignite
                     int32_t length = stream->Position() - start;
 
                     flags |= IGNITE_BINARY_FLAG_HAS_SCHEMA;
-                    
+
                     if (schemaType == OFFSET_TYPE_ONE_BYTE)
                         flags |= IGNITE_BINARY_FLAG_OFFSET_ONE_BYTE;
                     else if (schemaType == OFFSET_TYPE_TWO_BYTES)

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/core-test/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/Makefile.am b/modules/platforms/cpp/core-test/Makefile.am
index a5a60ed..4af2850 100644
--- a/modules/platforms/cpp/core-test/Makefile.am
+++ b/modules/platforms/cpp/core-test/Makefile.am
@@ -64,6 +64,7 @@ ignite_tests_SOURCES = \
     src/handle_registry_test.cpp \
     src/ignite_error_test.cpp \
     src/binary_test_defs.cpp \
+    src/binary_object_test.cpp \
     src/binary_reader_writer_raw_test.cpp \
     src/binary_reader_writer_test.cpp \
     src/binary_session_test.cpp \

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h
----------------------------------------------------------------------
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 00b17e2..42f4539 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
@@ -76,6 +76,31 @@ namespace ignite_test
                 {
                     // No-op.   
                 }
+
+                friend bool operator==(const BinaryFields& one, const BinaryFields& two)
+                {
+                    return one.val1 == two.val1 && one.val2 == two.val2 && 
+                        one.rawVal1 == two.rawVal1 &&one.rawVal2 == two.rawVal2;
+                }
+            };
+
+            class DummyIdResolver : public ignite::impl::binary::BinaryIdResolver
+            {
+            public:
+                virtual ~DummyIdResolver()
+                {
+                    // No-op.
+                }
+
+                virtual int32_t GetTypeId()
+                {
+                    return 0;
+                }
+
+                virtual int32_t GetFieldId(const int32_t, const char*)
+                {
+                    return 0;
+                }
             };
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/core-test/include/ignite/complex_type.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/include/ignite/complex_type.h b/modules/platforms/cpp/core-test/include/ignite/complex_type.h
new file mode 100644
index 0000000..cb4a8a1
--- /dev/null
+++ b/modules/platforms/cpp/core-test/include/ignite/complex_type.h
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+#ifndef _IGNITE_ODBC_TEST_COMPLEX_TYPE
+#define _IGNITE_ODBC_TEST_COMPLEX_TYPE
+
+#include <string>
+
+#include "ignite/ignite.h"
+#include "ignite/ignition.h"
+
+namespace ignite
+{
+    struct InnerObject
+    {
+        InnerObject() :
+            f1(412),
+            f2("Lorem ipsum")
+        {
+            // No-op.
+        }
+
+        friend bool operator==(const InnerObject& one, const InnerObject& two)
+        {
+            return one.f1 == two.f1 &&
+                one.f2 == two.f2;
+        }
+
+        int32_t f1;
+        std::string f2;
+    };
+
+    struct ComplexType
+    {
+        ComplexType() :
+            i32Field(0)
+        {
+            // No-op.
+        }
+
+        friend bool operator==(const ComplexType& one, const ComplexType& two)
+        {
+            return one.i32Field == two.i32Field &&
+                one.objField == two.objField &&
+                one.strField == two.strField;
+        }
+
+        int32_t i32Field;
+        InnerObject objField;
+        std::string strField;
+    };
+}
+
+namespace ignite
+{
+    namespace binary
+    {
+
+        IGNITE_BINARY_TYPE_START(ignite::InnerObject)
+
+            typedef ignite::InnerObject InnerObject;
+
+            IGNITE_BINARY_GET_TYPE_ID_AS_HASH(InnerObject)
+            IGNITE_BINARY_GET_TYPE_NAME_AS_IS(InnerObject)
+            IGNITE_BINARY_GET_FIELD_ID_AS_HASH
+            IGNITE_BINARY_GET_HASH_CODE_ZERO(InnerObject)
+            IGNITE_BINARY_IS_NULL_FALSE(InnerObject)
+            IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(InnerObject)
+
+            void Write(BinaryWriter& writer, InnerObject obj)
+            {
+                writer.WriteInt32("f1", obj.f1);
+                writer.WriteString("f2", obj.f2);
+            }
+
+            InnerObject Read(BinaryReader& reader)
+            {
+                InnerObject obj;
+
+                obj.f1 = reader.ReadInt32("f1");
+                obj.f2 = reader.ReadString("f2");
+
+                return obj;
+            }
+
+        IGNITE_BINARY_TYPE_END
+
+        IGNITE_BINARY_TYPE_START(ignite::ComplexType)
+
+            typedef ignite::ComplexType ComplexType;
+
+            IGNITE_BINARY_GET_TYPE_ID_AS_HASH(ComplexType)
+            IGNITE_BINARY_GET_TYPE_NAME_AS_IS(ComplexType)
+            IGNITE_BINARY_GET_FIELD_ID_AS_HASH
+            IGNITE_BINARY_GET_HASH_CODE_ZERO(ComplexType)
+            IGNITE_BINARY_IS_NULL_FALSE(ComplexType)
+            IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(ComplexType)
+
+            void Write(BinaryWriter& writer, ComplexType obj)
+            {
+                writer.WriteInt32("i32Field", obj.i32Field);
+                writer.WriteObject("objField", obj.objField);
+                writer.WriteString("strField", obj.strField);
+            }
+
+            ComplexType Read(BinaryReader& reader)
+            {
+                ComplexType obj;
+
+                obj.i32Field = reader.ReadInt32("i32Field");
+                obj.objField = reader.ReadObject<InnerObject>("objField");
+                obj.strField = reader.ReadString("strField");
+
+                return obj;
+            }
+
+        IGNITE_BINARY_TYPE_END
+    }
+};
+
+#endif // _IGNITE_ODBC_TEST_COMPLEX_TYPE

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/core-test/include/ignite/test_type.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/include/ignite/test_type.h b/modules/platforms/cpp/core-test/include/ignite/test_type.h
new file mode 100644
index 0000000..b399afe
--- /dev/null
+++ b/modules/platforms/cpp/core-test/include/ignite/test_type.h
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+#ifndef _IGNITE_ODBC_TEST_TEST_TYPE
+#define _IGNITE_ODBC_TEST_TEST_TYPE
+
+#include <string>
+
+#include "ignite/ignite.h"
+#include "ignite/ignition.h"
+
+namespace ignite
+{
+    struct TestType
+    {
+        TestType() :
+            allNulls(false),
+            i8Field(0),
+            i16Field(0),
+            i32Field(0),
+            i64Field(0),
+            floatField(0.0f),
+            doubleField(0.0),
+            boolField(false),
+            dateField(),
+            timestampField()
+        {
+            // No-op.
+        }
+
+        TestType(int8_t i8Field, int16_t i16Field, int32_t i32Field,
+            int64_t i64Field, const std::string& strField, float floatField,
+            double doubleField, bool boolField, const Guid& guidField,
+            const Date& dateField, const Timestamp& timestampField) :
+            allNulls(false),
+            i8Field(i8Field),
+            i16Field(i16Field),
+            i32Field(i32Field),
+            i64Field(i64Field),
+            strField(strField),
+            floatField(floatField),
+            doubleField(doubleField),
+            boolField(boolField),
+            guidField(guidField),
+            dateField(dateField),
+            timestampField(timestampField)
+        {
+            // No-op.
+        }
+
+        friend bool operator==(const TestType& one, const TestType& two)
+        {
+            return
+                one.allNulls == two.allNulls &&
+                one.i8Field == two.i8Field &&
+                one.i16Field == two.i16Field &&
+                one.i32Field == two.i32Field &&
+                one.i64Field == two.i64Field &&
+                one.strField == two.strField &&
+                one.floatField == two.floatField &&
+                one.doubleField == two.doubleField &&
+                one.boolField == two.boolField &&
+                one.guidField == two.guidField &&
+                one.dateField == two.dateField &&
+                one.timestampField == two.timestampField &&
+                one.i8ArrayField == two.i8ArrayField;
+        }
+
+        bool allNulls;
+        int8_t i8Field;
+        int16_t i16Field;
+        int32_t i32Field;
+        int64_t i64Field;
+        std::string strField;
+        float floatField;
+        double doubleField;
+        bool boolField;
+        Guid guidField;
+        Date dateField;
+        Timestamp timestampField;
+        std::vector<int8_t> i8ArrayField;
+    };
+}
+
+namespace ignite
+{
+    namespace binary
+    {
+        IGNITE_BINARY_TYPE_START(ignite::TestType)
+
+            typedef ignite::TestType TestType;
+
+            IGNITE_BINARY_GET_TYPE_ID_AS_HASH(TestType)
+            IGNITE_BINARY_GET_TYPE_NAME_AS_IS(TestType)
+            IGNITE_BINARY_GET_FIELD_ID_AS_HASH
+            IGNITE_BINARY_GET_HASH_CODE_ZERO(TestType)
+            IGNITE_BINARY_IS_NULL_FALSE(TestType)
+            IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(TestType)
+
+            void Write(BinaryWriter& writer, TestType obj)
+            {
+                if (!obj.allNulls)
+                {
+                    writer.WriteInt8("i8Field", obj.i8Field);
+                    writer.WriteInt16("i16Field", obj.i16Field);
+                    writer.WriteInt32("i32Field", obj.i32Field);
+                    writer.WriteInt64("i64Field", obj.i64Field);
+                    writer.WriteString("strField", obj.strField);
+                    writer.WriteFloat("floatField", obj.floatField);
+                    writer.WriteDouble("doubleField", obj.doubleField);
+                    writer.WriteBool("boolField", obj.boolField);
+                    writer.WriteGuid("guidField", obj.guidField);
+                    writer.WriteDate("dateField", obj.dateField);
+                    writer.WriteTimestamp("timestampField", obj.timestampField);
+                    if (obj.i8ArrayField.empty())
+                    {
+                        writer.WriteNull("i8ArrayField");
+                    }
+                    else
+                    {
+                        writer.WriteInt8Array("i8ArrayField", &obj.i8ArrayField[0], static_cast<int32_t>(obj.i8ArrayField.size()));
+                    }
+                }
+                else
+                {
+                    writer.WriteNull("i8Field");
+                    writer.WriteNull("i16Field");
+                    writer.WriteNull("i32Field");
+                    writer.WriteNull("i64Field");
+                    writer.WriteNull("strField");
+                    writer.WriteNull("floatField");
+                    writer.WriteNull("doubleField");
+                    writer.WriteNull("boolField");
+                    writer.WriteNull("guidField");
+                    writer.WriteNull("dateField");
+                    writer.WriteNull("timestampField");
+                    writer.WriteNull("i8ArrayField");
+                }
+            }
+
+            TestType Read(BinaryReader& reader)
+            {
+                int8_t i8Field = reader.ReadInt8("i8Field");
+                int16_t i16Field = reader.ReadInt16("i16Field");
+                int32_t i32Field = reader.ReadInt32("i32Field");
+                int64_t i64Field = reader.ReadInt64("i64Field");
+                std::string strField = reader.ReadString("strField");
+                float floatField = reader.ReadFloat("floatField");
+                double doubleField = reader.ReadDouble("doubleField");
+                bool boolField = reader.ReadBool("boolField");
+                Guid guidField = reader.ReadGuid("guidField");
+                Date dateField = reader.ReadDate("dateField");
+                Timestamp timestampField = reader.ReadTimestamp("timestampField");
+
+                TestType result(i8Field, i16Field, i32Field, i64Field, strField,
+                    floatField, doubleField, boolField, guidField, dateField,
+                    timestampField);
+
+                int32_t len = reader.ReadInt8Array("i8ArrayField", 0, 0);
+                if (len > 0)
+                {
+                    result.i8ArrayField.resize(len);
+                    reader.ReadInt8Array("i8ArrayField", &result.i8ArrayField[0], len);
+                }
+                return result;
+            }
+
+        IGNITE_BINARY_TYPE_END
+    }
+};
+
+#endif // _IGNITE_ODBC_TEST_TEST_TYPE

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
index a41d8f8..634ede2 100644
--- a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
+++ b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
@@ -38,6 +38,7 @@
     <None Include="..\..\config\invalid.xml" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\..\src\binary_object_test.cpp" />
     <ClCompile Include="..\..\src\cache_test.cpp" />
     <ClCompile Include="..\..\src\concurrent_test.cpp" />
     <ClCompile Include="..\..\src\decimal_test.cpp" />
@@ -63,6 +64,8 @@
   <ItemGroup>
     <ClInclude Include="..\..\include\ignite\binary_test_defs.h" />
     <ClInclude Include="..\..\include\ignite\binary_test_utils.h" />
+    <ClInclude Include="..\..\include\ignite\complex_type.h" />
+    <ClInclude Include="..\..\include\ignite\test_type.h" />
     <ClInclude Include="..\..\include\teamcity_messages.h" />
   </ItemGroup>
   <PropertyGroup Label="Globals">

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
index a95e3a4..906a9d4 100644
--- a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
+++ b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
@@ -64,15 +64,24 @@
     <ClCompile Include="..\..\src\reference_test.cpp">
       <Filter>Code</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\binary_object_test.cpp">
+      <Filter>Code</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\teamcity_messages.h">
       <Filter>TeamCity</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\ignite\binary_test_defs.h">
+    <ClInclude Include="..\..\include\ignite\binary_test_utils.h">
       <Filter>Code</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\ignite\binary_test_utils.h">
+    <ClInclude Include="..\..\include\ignite\complex_type.h">
+      <Filter>Code\Types</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\test_type.h">
+      <Filter>Code\Types</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\binary_test_defs.h">
       <Filter>Code</Filter>
     </ClInclude>
   </ItemGroup>
@@ -86,6 +95,9 @@
     <Filter Include="TeamCity">
       <UniqueIdentifier>{76bceab0-e251-445f-88c3-3f6f8739423b}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Code\Types">
+      <UniqueIdentifier>{fb43524e-3694-44ee-b153-770cd9cf6c7a}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\..\config\cache-test.xml">

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d64a281/modules/platforms/cpp/core-test/src/binary_object_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/src/binary_object_test.cpp b/modules/platforms/cpp/core-test/src/binary_object_test.cpp
new file mode 100644
index 0000000..0ae7136
--- /dev/null
+++ b/modules/platforms/cpp/core-test/src/binary_object_test.cpp
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ */
+
+#ifndef _MSC_VER
+#   define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include <ignite/common/fixed_size_array.h>
+#include <ignite/binary/binary_object.h>
+#include <ignite/binary/binary_writer.h>
+
+#include "ignite/binary_test_defs.h"
+#include "ignite/test_type.h"
+#include "ignite/complex_type.h"
+
+using namespace ignite;
+using namespace ignite::binary;
+using namespace ignite::impl::interop;
+using namespace ignite::impl::binary;
+using namespace ignite_test::core::binary;
+
+template<typename T>
+void FillMem(InteropMemory& mem, const T& value)
+{
+    InteropOutputStream stream(&mem);
+    BinaryWriterImpl writer(&stream, 0);
+
+    writer.WriteObject<T>(value);
+
+    stream.Synchronize();
+}
+
+template<typename T>
+void CheckSimple(const T& value)
+{
+    InteropUnpooledMemory mem(1024);
+
+    FillMem<T>(mem, value);
+
+    BinaryObject obj(mem, 0);
+
+    T actual = obj.Deserialize<T>();
+
+    BOOST_REQUIRE_EQUAL(value, actual);
+}
+
+template<typename T>
+void CheckSimpleNP(const T& value)
+{
+    InteropUnpooledMemory mem(1024);
+
+    FillMem<T>(mem, value);
+
+    BinaryObject obj(mem, 0);
+
+    T actual = obj.Deserialize<T>();
+
+    BOOST_REQUIRE(value == actual);
+}
+
+template<typename T>
+void GetObjectData(const T& obj, common::FixedSizeArray<int8_t>& data)
+{
+    DummyIdResolver idResolver;
+
+    InteropUnpooledMemory mem(1024);
+    InteropOutputStream stream(&mem);
+    BinaryWriterImpl writerImpl(&stream, &idResolver, 0, 0, 0);
+    BinaryWriter writer(&writerImpl);
+
+    BinaryType<T> bt;
+
+    bt.Write(writer, obj);
+
+    data.Assign(mem.Data(), stream.Position());
+}
+
+template<typename T>
+void CheckData(const T& obj)
+{
+    common::FixedSizeArray<int8_t> objData;
+    GetObjectData<T>(obj, objData);
+
+    InteropUnpooledMemory mem(1024);
+    FillMem<T>(mem, obj);
+
+    BinaryObjectImpl binObj(mem, 0);
+
+    BOOST_REQUIRE_EQUAL(binObj.GetLength(), objData.GetSize());
+
+    common::FixedSizeArray<int8_t> binObjData(binObj.GetData(), binObj.GetLength());
+
+    for (int32_t i = 0; i < objData.GetSize(); ++i)
+        BOOST_CHECK_EQUAL(objData[i], binObjData[i]);
+}
+
+BOOST_AUTO_TEST_SUITE(BinaryObjectTestSuite)
+
+#ifdef CHECK_BINARY_OBJECT_WITH_PRIMITIVES
+
+BOOST_AUTO_TEST_CASE(PrimitiveInt8)
+{
+    CheckSimple<int8_t>(0);
+    CheckSimple<int8_t>(INT8_MAX);
+    CheckSimple<int8_t>(INT8_MIN);
+    CheckSimple<int8_t>(42);
+    CheckSimple<int8_t>(-12);
+    CheckSimple<int8_t>(0x7D);
+}
+
+BOOST_AUTO_TEST_CASE(PrimitiveInt16)
+{
+    CheckSimple<int32_t>(0);
+    CheckSimple<int32_t>(INT16_MAX);
+    CheckSimple<int32_t>(INT16_MIN);
+    CheckSimple<int32_t>(42);
+    CheckSimple<int32_t>(12321);
+    CheckSimple<int32_t>(0x7AB0);
+}
+
+BOOST_AUTO_TEST_CASE(PrimitiveInt32)
+{
+    CheckSimple<int32_t>(0);
+    CheckSimple<int32_t>(INT32_MAX);
+    CheckSimple<int32_t>(INT32_MIN);
+    CheckSimple<int32_t>(42);
+    CheckSimple<int32_t>(1337);
+    CheckSimple<int32_t>(0xA2496BC9);
+}
+
+BOOST_AUTO_TEST_CASE(PrimitiveInt64)
+{
+    CheckSimple<int64_t>(0);
+    CheckSimple<int64_t>(INT64_MAX);
+    CheckSimple<int64_t>(INT64_MIN);
+    CheckSimple<int64_t>(42);
+    CheckSimple<int64_t>(13371337133713371337LL);
+    CheckSimple<int64_t>(0xA928673F501CC09E);
+}
+
+BOOST_AUTO_TEST_CASE(PrimitiveBool)
+{
+    CheckSimple<bool>(true);
+    CheckSimple<bool>(false);
+}
+
+BOOST_AUTO_TEST_CASE(PrimitiveFloat)
+{
+    CheckSimple<float>(0.0);
+    CheckSimple<float>(1E38f);
+    CheckSimple<float>(-1E38f);
+    CheckSimple<float>(1E-38f);
+    CheckSimple<float>(-1E-38f);
+    CheckSimple<float>(42.0f);
+    CheckSimple<float>(42.42f);
+    CheckSimple<float>(1337.1337f);
+}
+
+BOOST_AUTO_TEST_CASE(PrimitiveDouble)
+{
+    CheckSimple<double>(0);
+    CheckSimple<double>(1E127);
+    CheckSimple<double>(-1E127);
+    CheckSimple<double>(1E-127);
+    CheckSimple<double>(-1E-127);
+    CheckSimple<double>(42);
+    CheckSimple<double>(42.42);
+    CheckSimple<double>(1337.1337 * 1337.1337);
+}
+
+BOOST_AUTO_TEST_CASE(PrimitiveString)
+{
+    CheckSimple<std::string>("");
+    CheckSimple<std::string>("Lorem ipsum");
+    CheckSimple<std::string>("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
+        "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, "
+        "quis nostrud exercitation");
+
+    CheckSimple<std::string>(std::string(1000, '.'));
+}
+
+BOOST_AUTO_TEST_CASE(PrimitiveGuid)
+{
+    CheckSimple<Guid>(Guid(0, 0));
+    CheckSimple<Guid>(Guid(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF));
+    CheckSimple<Guid>(Guid(0x4F9039DEF0FB8000, 0x905AE8A2D6FD49C1));
+}
+
+BOOST_AUTO_TEST_CASE(PrimitiveDate)
+{
+    CheckSimpleNP<Date>(Date(0));
+    CheckSimpleNP<Date>(BinaryUtils::MakeDateGmt(1998, 12, 3, 18, 32, 01));
+    CheckSimpleNP<Date>(BinaryUtils::MakeDateGmt(2017, 1, 18, 20, 50, 41));
+    CheckSimpleNP<Date>(BinaryUtils::MakeDateLocal(1998, 12, 3, 18, 32, 01));
+}
+
+BOOST_AUTO_TEST_CASE(PrimitiveTimestamp)
+{
+    CheckSimpleNP<Timestamp>(Timestamp(0));
+    CheckSimpleNP<Timestamp>(BinaryUtils::MakeTimestampGmt(1998, 12, 3, 18, 32, 01, 593846589));
+    CheckSimpleNP<Timestamp>(BinaryUtils::MakeTimestampGmt(2017, 1, 18, 20, 50, 41, 920700532));
+    CheckSimpleNP<Timestamp>(BinaryUtils::MakeTimestampLocal(1998, 12, 3, 18, 32, 01, 2385));
+}
+
+#endif //CHECK_BINARY_OBJECT_WITH_PRIMITIVES
+
+BOOST_AUTO_TEST_CASE(UserTestType)
+{
+    CheckSimpleNP(TestType());
+    CheckSimpleNP(TestType(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9),
+        BinaryUtils::MakeDateGmt(1987, 6, 5),
+        BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456)));
+}
+
+BOOST_AUTO_TEST_CASE(UserComplexType)
+{
+    CheckSimpleNP(ComplexType());
+
+    ComplexType nonDefault;
+
+    nonDefault.i32Field = 589630659;
+    nonDefault.strField = "Some string value";
+    nonDefault.objField.f1 = 403685016;
+    nonDefault.objField.f2 = "Whatever";
+
+    CheckSimpleNP(nonDefault);
+}
+
+BOOST_AUTO_TEST_CASE(UserBinaryFields)
+{
+    CheckSimpleNP(BinaryFields());
+
+    BinaryFields nonDefault(423425, 961851, 18946, 180269165);
+
+    CheckSimpleNP(nonDefault);
+}
+
+BOOST_AUTO_TEST_CASE(UserComplexTypeGetData)
+{
+    CheckData(ComplexType());
+
+    ComplexType nonDefault;
+
+    nonDefault.i32Field = 589630659;
+    nonDefault.strField = "Some string value";
+    nonDefault.objField.f1 = 403685016;
+    nonDefault.objField.f2 = "Whatever";
+
+    CheckData(nonDefault);
+}
+
+BOOST_AUTO_TEST_CASE(UserTestTypeGetData)
+{
+    CheckData(TestType());
+    CheckData(TestType(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9),
+        BinaryUtils::MakeDateGmt(1987, 6, 5),
+        BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456)));
+}
+
+BOOST_AUTO_TEST_CASE(UserBinaryFieldsGetData)
+{
+    CheckData(BinaryFields());
+    CheckData(BinaryFields(423425, 961851, 18946, 180269165));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file