| /* |
| * 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. |
| */ |
| |
| #pragma once |
| |
| |
| #include "geode_defs.hpp" |
| #include "begin_native.hpp" |
| #include <geode/DataOutput.hpp> |
| #include "end_native.hpp" |
| |
| #include "native_conditional_unique_ptr.hpp" |
| #include "Log.hpp" |
| #include "ExceptionTypes.hpp" |
| #include "Serializable.hpp" |
| |
| #include "CacheableString.hpp" |
| #include "CacheableDate.hpp" |
| #include "CacheableVector.hpp" |
| #include "CacheableArrayList.hpp" |
| #include "CacheableStack.hpp" |
| |
| using namespace System; |
| using namespace System::Runtime::CompilerServices; |
| |
| namespace Apache |
| { |
| namespace Geode |
| { |
| namespace Client |
| { |
| namespace native = apache::geode::client; |
| |
| ref class Cache; |
| interface class ISerializable; |
| |
| /// <summary> |
| /// Provides operations for writing primitive data values, and |
| /// user-defined objects implementing ISerializable, to a byte stream. |
| /// This class is intentionally not thread safe. |
| /// </summary> |
| public ref class DataOutput sealed |
| { |
| private: |
| System::Int32 m_cursor; |
| bool m_isManagedObject; |
| System::Byte * m_bytes; |
| System::Int32 m_remainingBufferLength; |
| bool m_ispdxSerialization; |
| native_conditional_unique_ptr<native::DataOutput>^ m_nativeptr; |
| Apache::Geode::Client::Cache^ m_cache; |
| |
| public: |
| |
| /// <summary> |
| /// Default constructor. |
| /// </summary> |
| DataOutput(Apache::Geode::Client::Cache^ cache); |
| |
| /// <summary> |
| /// Write length of the array to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="len">Array len to write.</param> |
| void WriteArrayLen( System::Int32 len ); |
| |
| /// <summary> |
| /// Write a signed byte to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value">The signed byte to write.</param> |
| void WriteSByte( SByte value ); |
| |
| /// <summary> |
| /// Write a boolean value to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value">The boolean value to write.</param> |
| void WriteBoolean( bool value ); |
| |
| /// <summary> |
| /// Write a char value to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value">The char value to write.</param> |
| void WriteChar( Char value ); |
| |
| /// <summary> |
| /// Write a given length of bytes to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="bytes">The array of bytes to write.</param> |
| /// <param name="len"> |
| /// The number of bytes from the start of array to write. |
| /// </param> |
| void WriteBytes( array<Byte>^ bytes, System::Int32 len ); |
| |
| /// <summary> |
| /// Write an array of bytes to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="bytes">The array of bytes to write.</param> |
| inline void WriteBytes( array<Byte>^ bytes ) |
| { |
| WriteBytes( bytes, ( bytes == nullptr ? -1 : bytes->Length ) ); |
| } |
| |
| /// <summary> |
| /// Write a given length of signed bytes to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="bytes">The array of signed bytes to write.</param> |
| /// <param name="len"> |
| /// The number of bytes from the start of array to write. |
| /// </param> |
| void WriteSBytes( array<SByte>^ bytes, System::Int32 len ); |
| |
| /// <summary> |
| /// Write an array of signed bytes to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="bytes">The array of signed bytes to write.</param> |
| inline void WriteSBytes( array<SByte>^ bytes ) |
| { |
| WriteSBytes( bytes, ( bytes == nullptr ? -1 : bytes->Length ) ); |
| } |
| |
| /// <summary> |
| /// Write a given length of bytes without its length to the |
| /// <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="bytes">The array of bytes to write.</param> |
| /// <param name="len"> |
| /// The number of bytes from the start of array to write. |
| /// </param> |
| void WriteBytesOnly( array<Byte>^ bytes, System::UInt32 len ); |
| |
| void WriteBytesOnly( array<Byte>^ bytes, System::UInt32 len, System::UInt32 offset ); |
| |
| /// <summary> |
| /// Write an array of bytes without its length to the |
| /// <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="bytes">The array of bytes to write.</param> |
| inline void WriteBytesOnly( array<Byte>^ bytes ) |
| { |
| WriteBytesOnly( bytes, ( bytes == nullptr ? 0 : bytes->Length ) ); |
| } |
| |
| /// <summary> |
| /// Write a given length of signed bytes without its length |
| /// to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="bytes">The array of signed bytes to write.</param> |
| /// <param name="len"> |
| /// The number of bytes from the start of array to write. |
| /// </param> |
| void WriteSBytesOnly( array<SByte>^ bytes, System::UInt32 len ); |
| |
| /// <summary> |
| /// Write an array of signed bytes without its length |
| /// to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="bytes">The array of signed bytes to write.</param> |
| inline void WriteSBytesOnly( array<SByte>^ bytes ) |
| { |
| WriteSBytesOnly( bytes, ( bytes == nullptr ? 0 : bytes->Length ) ); |
| } |
| |
| /// <summary> |
| /// Write a 16-bit integer to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value">The 16-bit integer to write.</param> |
| void WriteInt16( System::Int16 value ); |
| |
| /// <summary> |
| /// Write a 32-bit integer to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value">The 32-bit integer to write.</param> |
| void WriteInt32( System::Int32 value ); |
| |
| /// <summary> |
| /// Write a 64-bit integer to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value">The 64-bit integer to write.</param> |
| void WriteInt64( System::Int64 value ); |
| |
| /// <summary> |
| /// Write a float to the DataOutput. |
| /// </summary> |
| /// <param name="value">The float value to write.</param> |
| void WriteFloat( float value ); |
| |
| /// <summary> |
| /// Write a double precision real number to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value"> |
| /// The double precision real number to write. |
| /// </param> |
| void WriteDouble( double value ); |
| |
| /// <summary> |
| /// Write a string using java-modified UTF-8 encoding to |
| /// <c>DataOutput</c>. |
| /// The maximum length supported is 2^16-1 beyond which the string |
| /// shall be truncated. |
| /// </summary> |
| /// <param name="value">The UTF encoded string to write.</param> |
| void WriteUTF( String^ value ); |
| |
| void WriteString(String^ value); |
| |
| /// <summary> |
| /// Write a <c>Serializable</c> object to the <c>DataOutput</c>. |
| /// This is provided to conveniently pass primitive types (like string) |
| /// that shall be implicitly converted to corresponding |
| /// <c>ISerializable</c> wrapper types. |
| /// </summary> |
| /// <param name="obj">The object to write.</param> |
| void WriteObject( Object^ obj ); |
| |
| /// <summary> |
| /// Advance the buffer cursor by the given offset. |
| /// </summary> |
| /// <param name="offset"> |
| /// The offset by which to advance the cursor. |
| /// </param> |
| void AdvanceCursor( System::UInt32 offset ); |
| |
| /// <summary> |
| /// Rewind the buffer cursor by the given offset. |
| /// </summary> |
| /// <param name="offset"> |
| /// The offset by which to rewind the cursor. |
| /// </param> |
| void RewindCursor( System::UInt32 offset ); |
| |
| /// <summary> |
| /// Get a copy of the current buffer. |
| /// </summary> |
| array<Byte>^ GetBuffer( ); |
| |
| /// <summary> |
| /// Get the length of current data in the buffer. |
| /// </summary> |
| property size_t BufferLength |
| { |
| size_t get( ); |
| } |
| |
| property Apache::Geode::Client::Cache^ Cache |
| { |
| Apache::Geode::Client::Cache^ get() { return m_cache; } |
| } |
| |
| /// <summary> |
| /// Reset the cursor to the start of the buffer. |
| /// </summary> |
| void Reset( ); |
| |
| /// <summary> |
| /// Write a Dictionary to the DataOutput. |
| /// </summary> |
| /// <param name="value">The object which implements IDictionary to write.</param> |
| void WriteDictionary(System::Collections::IDictionary^ value); |
| |
| /// <summary> |
| /// Write a date to the DataOutput. |
| /// </summary> |
| /// <param name="value">The date value to write.</param> |
| void WriteDate(System::DateTime value); |
| |
| /// <summary> |
| /// Write a collection to the DataOutput. |
| /// </summary> |
| /// <param name="value">The object which implements IList to write.</param> |
| void WriteCollection(System::Collections::IList^ value); |
| |
| /// <summary> |
| /// Write a char array to the DataOutput. |
| /// </summary> |
| /// <param name="value">The char array to write.</param> |
| void WriteCharArray(array<Char>^ value); |
| |
| /// <summary> |
| /// Write a bool array to the DataOutput. |
| /// </summary> |
| /// <param name="value">The bool array to write.</param> |
| void WriteBooleanArray(array<bool>^ value); |
| |
| /// <summary> |
| /// Write a short array to the DataOutput. |
| /// </summary> |
| /// <param name="value">The short array to write.</param> |
| void WriteShortArray(array<Int16>^ value); |
| |
| /// <summary> |
| /// Write a int array to the DataOutput. |
| /// </summary> |
| /// <param name="value">The int array to write.</param> |
| void WriteIntArray(array<Int32>^ value); |
| |
| /// <summary> |
| /// Write a long array to the DataOutput. |
| /// </summary> |
| /// <param name="value">The long array to write.</param> |
| void WriteLongArray(array<Int64>^ value); |
| |
| /// <summary> |
| /// Write a float array to the DataOutput. |
| /// </summary> |
| /// <param name="value">The float array to write.</param> |
| void WriteFloatArray(array<float>^ value); |
| |
| /// <summary> |
| /// Write a double array to the DataOutput. |
| /// </summary> |
| /// <param name="value">The double array to write.</param> |
| void WriteDoubleArray(array<double>^ value); |
| |
| /// <summary> |
| /// Write a object array to the DataOutput. |
| /// </summary> |
| /// <param name="value">The object array to write.</param> |
| void WriteObjectArray(List<Object^>^ value); |
| |
| /// <summary> |
| /// Write a array of sign byte array to the DataOutput. |
| /// </summary> |
| /// <param name="value">The array of sign byte array to write.</param> |
| void WriteArrayOfByteArrays(array<array<Byte>^>^ value); |
| |
| internal: |
| |
| native::DataOutput* GetNative() |
| { |
| return m_nativeptr->get(); |
| } |
| |
| void WriteDotNetObjectArray(Object^ objectArray); |
| |
| /// <summary> |
| /// Write a byte to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value">The byte to write.</param> |
| void WriteByte( Byte value ); |
| |
| /// <summary> |
| /// Write an unsigned short integer (System::Int16) to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value">The unsigned 16-bit integer to write.</param> |
| void WriteUInt16( System::UInt16 value ); |
| |
| /// <summary> |
| /// Write an unsigned 32-bit integer to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value">The unsigned 32-bit integer to write.</param> |
| void WriteUInt32( System::UInt32 value ); |
| |
| /// <summary> |
| /// Write an unsigned 64-bit integer to the <c>DataOutput</c>. |
| /// </summary> |
| /// <param name="value">The unsigned 64-bit integer to write.</param> |
| void WriteUInt64( System::UInt64 value ); |
| |
| /// <summary> |
| /// Write a string using java-modified UTF-8 encoding to |
| /// <c>DataOutput</c>. |
| /// Length should be more than 2^16 -1. |
| /// </summary> |
| /// <param name="value">The UTF encoded string to write.</param> |
| void WriteUTFHuge( String^ value ); |
| |
| /// <summary> |
| /// Write a string(only ASCII char) to |
| /// <c>DataOutput</c>. |
| /// Length should be more than 2^16 -1. |
| /// </summary> |
| /// <param name="value">The UTF encoded string to write.</param> |
| void WriteASCIIHuge( String^ value ); |
| |
| |
| System::Int32 GetBufferLengthPdx() |
| { |
| try |
| { |
| return (System::Int32)m_nativeptr->get()->getBufferLength(); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| } |
| |
| System::Int32 GetCursorPdx() |
| { |
| return m_cursor; |
| } |
| |
| native::Pool* GetPool(); |
| |
| void WriteStringArray(array<String^>^ strArray); |
| |
| void EncodeUTF8String( String^ input, int encLength ) |
| { |
| const int strLength = input->Length; |
| const int end = m_cursor + encLength; |
| for ( int i = 0; i < strLength && m_cursor < end; i++ ) |
| { |
| unsigned short c = (unsigned short)input[i]; |
| |
| if( c == 0 ) |
| { |
| m_bytes[m_cursor++] = 0xc0; |
| m_bytes[m_cursor++] = 0x80; |
| } |
| else if ( c < 0x80 )//ASCII character |
| { |
| // 7-bits done in one byte. |
| m_bytes[m_cursor++] = (System::Byte)c; |
| } |
| else if ( c < 0x800 ) |
| { |
| // 8-11 bits done in 2 bytes |
| m_bytes[m_cursor++] = ( 0xC0 | c >> 6 ); |
| m_bytes[m_cursor++] = ( 0x80 | c & 0x3F ); |
| } |
| else |
| { |
| // 12-16 bits done in 3 bytes |
| m_bytes[m_cursor++] = ( 0xE0 | c >> 12 ); |
| m_bytes[m_cursor++] = ( 0x80 | c >> 6 & 0x3F ); |
| m_bytes[m_cursor++] = ( 0x80 | c & 0x3F ); |
| } |
| } |
| |
| // TODO ASSERT end = m_cursor |
| } |
| |
| static int getEncodedLength(String^ input) |
| { |
| int count = 0; |
| for ( int i = 0; i < input->Length; i++ ) |
| { |
| unsigned short c = (unsigned short)input[i]; |
| |
| if( c == 0) |
| { |
| count += 2; |
| } |
| else if ( c < 0x80 )//ASCII character |
| { |
| count++; |
| } |
| else if ( c < 0x800 ) |
| { |
| count += 2; |
| } |
| else |
| { |
| count += 3; |
| } |
| }// end for |
| |
| return count; |
| } |
| |
| void setPdxSerialization(bool val) |
| { |
| m_ispdxSerialization = val; |
| } |
| |
| void WriteStringWithType( String^ value ); |
| |
| static int8_t GetTypeId(System::UInt32 classId ); |
| |
| static int8_t DSFID(System::UInt32 classId); |
| |
| static inline DSCode getDataSerializableDsCode(int32_t classId) { |
| if (classId <= std::numeric_limits<int8_t>::max() && |
| classId >= std::numeric_limits<int8_t>::min()) { |
| return DSCode::CacheableUserData; |
| } else if (classId <= std::numeric_limits<int16_t>::max() && |
| classId >= std::numeric_limits<int16_t>::min()) { |
| return DSCode::CacheableUserData2; |
| } else { |
| return DSCode::CacheableUserData4; |
| } |
| } |
| |
| static inline int8_t getDataSerializableFixedIdDsCode(int32_t fixedId) { |
| if (fixedId <= std::numeric_limits<int8_t>::max() && |
| fixedId >= std::numeric_limits<int8_t>::min()) { |
| return static_cast<int8_t>(DSCode::FixedIDByte); |
| } else if (fixedId <= std::numeric_limits<int16_t>::max() && |
| fixedId >= std::numeric_limits<int16_t>::min()) { |
| return static_cast<int8_t>(DSCode::FixedIDShort); |
| } else { |
| return static_cast<int8_t>(DSCode::FixedIDInt); |
| } |
| } |
| |
| void WriteObjectInternal( ISerializable^ obj ); |
| |
| void WriteBytesToUMDataOutput(); |
| |
| void WriteObject(bool% obj); |
| |
| void WriteObject(Byte% obj); |
| |
| void WriteObject(Char% obj); |
| |
| void WriteObject(Double% obj); |
| |
| void WriteObject(Single% obj); |
| |
| void WriteObject(System::Int16% obj); |
| |
| void WriteObject(System::Int32% obj); |
| |
| void WriteObject(System::Int64% obj); |
| |
| void WriteObject(UInt16% obj); |
| |
| void WriteObject(UInt32% obj); |
| |
| void WriteObject(UInt64% obj); |
| |
| |
| template <typename mType> |
| void WriteObject(array<mType>^ %objArray) |
| { |
| if(objArray != nullptr) { |
| int arrayLen = objArray->Length; |
| WriteArrayLen(arrayLen); |
| if(arrayLen > 0) { |
| int i = 0; |
| for( i = 0; i < arrayLen; i++ ){ |
| WriteObject(objArray[i]); |
| } |
| } |
| } |
| else { |
| WriteByte(0xff); |
| } |
| } |
| |
| bool IsManagedObject() |
| { |
| return m_isManagedObject; |
| } |
| |
| void SetBuffer() |
| { |
| m_cursor = 0; |
| try |
| { |
| m_bytes = const_cast<System::Byte *>(m_nativeptr->get()->getCursor()); |
| m_remainingBufferLength = (System::Int32)m_nativeptr->get()->getRemainingBufferLength(); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| } |
| |
| System::Byte* GetStartBufferPosition() |
| { |
| try |
| { |
| return const_cast<System::Byte *>( m_nativeptr->get()->getBuffer()); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| }; |
| } |
| |
| inline void EnsureCapacity( System::Int32 size ) |
| { |
| System::Int32 bytesLeft = m_remainingBufferLength - m_cursor; |
| if ( bytesLeft < size ) { |
| try |
| { |
| auto p = m_nativeptr->get(); |
| p->ensureCapacity(m_cursor + size); |
| m_bytes = const_cast<System::Byte *>( p->getCursor()); |
| m_remainingBufferLength = (System::Int32)p->getRemainingBufferLength(); |
| } |
| catch(apache::geode::client::OutOfMemoryException ex ) |
| { |
| throw gcnew OutOfMemoryException(ex); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| } |
| } |
| |
| //it expects list is not null |
| inline void WriteList(System::Collections::IList^ list) |
| { |
| this->WriteArrayLen(list->Count); |
| for each (Object^ obj in list) |
| this->WriteObject(obj); |
| } |
| |
| System::Byte* GetBytes(System::Byte* src, System::UInt32 size) |
| { |
| try |
| { |
| return m_nativeptr->get()->getBufferCopyFrom(src, size); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| } |
| |
| System::Int32 GetRemainingBufferLength() |
| { |
| try |
| { |
| return (System::Int32) m_nativeptr->get()->getRemainingBufferLength(); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| } |
| |
| /// <summary> |
| /// Internal constructor to wrap a native object pointer |
| /// </summary> |
| /// <param name="nativeptr">The native object pointer</param> |
| inline DataOutput(apache::geode::client::DataOutput* nativeptr, bool managedObject, Apache::Geode::Client::Cache^ cache) |
| { |
| m_cache = cache; |
| m_nativeptr = gcnew native_conditional_unique_ptr<native::DataOutput>(nativeptr); |
| m_isManagedObject = managedObject; |
| m_cursor = 0; |
| m_bytes = const_cast<System::Byte *>(nativeptr->getCursor()); |
| m_remainingBufferLength = (System::Int32)nativeptr->getRemainingBufferLength(); |
| m_ispdxSerialization = false; |
| } |
| }; |
| } // namespace Client |
| } // namespace Geode |
| } // namespace Apache |
| |