| /* |
| * 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 "begin_native.hpp" |
| #include "CacheRegionHelper.hpp" |
| #include "CacheImpl.hpp" |
| #include "DataOutputInternal.hpp" |
| #include "end_native.hpp" |
| |
| |
| #include "DataOutput.hpp" |
| #include "IDataSerializable.hpp" |
| #include "ISerializable.hpp" |
| #include "CacheableObjectArray.hpp" |
| #include "impl/PdxHelper.hpp" |
| #include "impl/PdxWrapper.hpp" |
| #include "Cache.hpp" |
| |
| using namespace System; |
| using namespace System::Runtime::InteropServices; |
| using namespace apache::geode::client; |
| |
| namespace Apache |
| { |
| namespace Geode |
| { |
| namespace Client |
| { |
| using namespace msclr::interop; |
| |
| DataOutput::DataOutput(Apache::Geode::Client::Cache^ cache) |
| { |
| m_cache = cache; |
| m_nativeptr = gcnew native_conditional_unique_ptr<native::DataOutput>( |
| std::make_unique<native::DataOutput>(cache->GetNative()->createDataOutput())); |
| m_isManagedObject = true; |
| 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); |
| } |
| m_ispdxSerialization = false; |
| } |
| |
| void DataOutput::WriteByte(Byte value) |
| { |
| EnsureCapacity(1); |
| m_bytes[m_cursor++] = value; |
| } |
| |
| void DataOutput::WriteSByte(SByte value) |
| { |
| EnsureCapacity(1); |
| m_bytes[m_cursor++] = value; |
| } |
| |
| void DataOutput::WriteBoolean(bool value) |
| { |
| EnsureCapacity(1); |
| if (value) |
| m_bytes[m_cursor++] = 0x01; |
| else |
| m_bytes[m_cursor++] = 0x00; |
| } |
| |
| void DataOutput::WriteChar(Char value) |
| { |
| EnsureCapacity(2); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 8); |
| m_bytes[m_cursor++] = (System::Byte)value; |
| } |
| |
| void DataOutput::WriteBytes(array<Byte>^ bytes, System::Int32 len) |
| { |
| if (bytes != nullptr && bytes->Length >= 0) |
| { |
| if (len >= 0 && len <= bytes->Length) |
| { |
| WriteArrayLen(len); |
| EnsureCapacity(len); |
| for (int i = 0; i < len; i++) |
| m_bytes[m_cursor++] = bytes[i]; |
| } |
| else |
| { |
| throw gcnew IllegalArgumentException("DataOutput::WriteBytes argument len is not in byte array range."); |
| } |
| } |
| else |
| { |
| WriteByte(0xFF); |
| } |
| } |
| |
| void DataOutput::WriteArrayLen(System::Int32 len) |
| { |
| if (len == -1) {//0xff |
| WriteByte(0xFF); |
| } |
| else if (len <= 252) { // 252 is java's ((byte)-4 && 0xFF) or 0xfc |
| WriteByte((Byte)(len)); |
| } |
| else if (len <= 0xFFFF) { |
| WriteByte(0xFE);//0xfe |
| WriteUInt16((len)); |
| } |
| else { |
| WriteByte((0xFD));//0xfd |
| WriteUInt32(len); |
| } |
| } |
| |
| void DataOutput::WriteSBytes(array<SByte>^ bytes, System::Int32 len) |
| { |
| if (bytes != nullptr && bytes->Length >= 0) |
| { |
| if (len >= 0 && len <= bytes->Length) |
| { |
| WriteArrayLen(len); |
| EnsureCapacity(len); |
| for (int i = 0; i < len; i++) |
| m_bytes[m_cursor++] = bytes[i]; |
| } |
| else |
| { |
| throw gcnew IllegalArgumentException("DataOutput::WriteSBytes argument len is not in SByte array range."); |
| } |
| } |
| else |
| { |
| WriteByte(0xFF); |
| } |
| } |
| |
| void DataOutput::WriteBytesOnly(array<Byte>^ bytes, System::UInt32 len) |
| { |
| WriteBytesOnly(bytes, len, 0); |
| } |
| |
| void DataOutput::WriteBytesOnly(array<Byte>^ bytes, System::UInt32 len, System::UInt32 offset) |
| { |
| if (bytes != nullptr) |
| { |
| if (len >= 0 && len <= ((System::UInt32)bytes->Length - offset)) |
| { |
| EnsureCapacity(len); |
| for (System::UInt32 i = 0; i < len; i++) |
| m_bytes[m_cursor++] = bytes[offset + i]; |
| } |
| else |
| { |
| throw gcnew IllegalArgumentException("DataOutput::WriteBytesOnly argument len is not in Byte array range."); |
| } |
| } |
| } |
| |
| void DataOutput::WriteSBytesOnly(array<SByte>^ bytes, System::UInt32 len) |
| { |
| if (bytes != nullptr) |
| { |
| if (len >= 0 && len <= (System::UInt32)bytes->Length) |
| { |
| EnsureCapacity(len); |
| for (System::UInt32 i = 0; i < len; i++) |
| m_bytes[m_cursor++] = bytes[i]; |
| } |
| else |
| { |
| throw gcnew IllegalArgumentException("DataOutput::WriteSBytesOnly argument len is not in SByte array range."); |
| } |
| } |
| } |
| |
| void DataOutput::WriteUInt16(System::UInt16 value) |
| { |
| EnsureCapacity(2); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 8); |
| m_bytes[m_cursor++] = (System::Byte)value; |
| } |
| |
| void DataOutput::WriteUInt32(System::UInt32 value) |
| { |
| EnsureCapacity(4); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 24); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 16); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 8); |
| m_bytes[m_cursor++] = (System::Byte)value; |
| } |
| |
| void DataOutput::WriteUInt64(System::UInt64 value) |
| { |
| EnsureCapacity(8); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 56); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 48); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 40); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 32); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 24); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 16); |
| m_bytes[m_cursor++] = (System::Byte)(value >> 8); |
| m_bytes[m_cursor++] = (System::Byte)value; |
| } |
| |
| void DataOutput::WriteInt16(System::Int16 value) |
| { |
| WriteUInt16(value); |
| } |
| |
| void DataOutput::WriteInt32(System::Int32 value) |
| { |
| WriteUInt32(value); |
| } |
| |
| void DataOutput::WriteInt64(System::Int64 value) |
| { |
| WriteUInt64(value); |
| } |
| |
| void DataOutput::WriteFloat(float value) |
| { |
| array<Byte>^ bytes = BitConverter::GetBytes(value); |
| EnsureCapacity(4); |
| for (int i = 4 - 1; i >= 0; i--) |
| m_bytes[m_cursor++] = bytes[i]; |
| } |
| |
| void DataOutput::WriteDouble(double value) |
| { |
| array<Byte>^ bytes = BitConverter::GetBytes(value); |
| EnsureCapacity(8); |
| for (int i = 8 - 1; i >= 0; i--) |
| m_bytes[m_cursor++] = bytes[i]; |
| } |
| |
| void DataOutput::WriteDictionary(System::Collections::IDictionary^ dict) |
| { |
| if (dict != nullptr) |
| { |
| this->WriteArrayLen(dict->Count); |
| for each(System::Collections::DictionaryEntry^ entry in dict) |
| { |
| this->WriteObject(entry->Key); |
| this->WriteObject(entry->Value); |
| } |
| } |
| else |
| { |
| WriteByte((int8_t)-1); |
| } |
| } |
| |
| void DataOutput::WriteCollection(System::Collections::IList^ collection) |
| { |
| if (collection != nullptr) |
| { |
| this->WriteArrayLen(collection->Count); |
| for each (Object^ obj in collection) { |
| this->WriteObject(obj); |
| } |
| } |
| else |
| this->WriteByte((int8_t)-1); |
| } |
| |
| void DataOutput::WriteDate(System::DateTime date) |
| { |
| if (date.Ticks != 0L) |
| { |
| CacheableDate^ cd = gcnew CacheableDate(date); |
| cd->ToData(this); |
| } |
| else |
| this->WriteInt64(-1L); |
| } |
| |
| void DataOutput::WriteCharArray(array<Char>^ charArray) |
| { |
| if (charArray != nullptr) |
| { |
| this->WriteArrayLen(charArray->Length); |
| for (int i = 0; i < charArray->Length; i++) { |
| this->WriteObject(charArray[i]); |
| } |
| } |
| else |
| this->WriteByte((int8_t)-1); |
| } |
| |
| void DataOutput::WriteObjectArray(List<Object^>^ objectArray) |
| { |
| if (objectArray != nullptr) |
| { |
| CacheableObjectArray^ coa = CacheableObjectArray::Create(objectArray); |
| coa->ToData(this); |
| } |
| else |
| this->WriteByte((int8_t)-1); |
| } |
| |
| void DataOutput::WriteDotNetObjectArray(Object^ objectArray) |
| { |
| System::Collections::IList^ list = (System::Collections::IList^)objectArray; |
| this->WriteArrayLen(list->Count); |
| WriteByte((int8_t)apache::geode::client::internal::DSCode::Class); |
| String^ pdxDomainClassname = m_cache->TypeRegistry->GetPdxTypeName(objectArray->GetType()->GetElementType()->FullName); |
| WriteByte((int8_t)DSCode::CacheableASCIIString); |
| WriteUTF(pdxDomainClassname); |
| for each(Object^ o in list) |
| WriteObject(o); |
| } |
| |
| void DataOutput::WriteArrayOfByteArrays(array<array<Byte>^>^ byteArrays) |
| { |
| if (byteArrays != nullptr) |
| { |
| int fdLen = byteArrays->Length; |
| this->WriteArrayLen(byteArrays->Length); |
| for (int i = 0; i < fdLen; i++) { |
| this->WriteBytes(byteArrays[i]); |
| } |
| } |
| else |
| this->WriteByte((int8_t)-1); |
| } |
| |
| void DataOutput::WriteUTF(String^ value) |
| { |
| if (value != nullptr) { |
| int len = getEncodedLength(value); |
| |
| if (len > 0xffff) |
| len = 0xffff; |
| |
| WriteUInt16(len); |
| EnsureCapacity(len); |
| EncodeUTF8String(value, len); |
| } |
| else { |
| WriteUInt16(0); |
| } |
| } |
| |
| void DataOutput::WriteStringWithType(String^ value) |
| { |
| //value will not be null |
| int len = getEncodedLength(value); |
| |
| if (len > 0xffff) |
| { |
| if (len == value->Length)//huge ascii |
| { |
| WriteByte(static_cast<unsigned char>(DSCode::CacheableASCIIStringHuge)); |
| WriteASCIIHuge(value); |
| } |
| else//huge utf |
| { |
| WriteByte(static_cast<unsigned char>(DSCode::CacheableStringHuge)); |
| WriteUTFHuge(value); |
| } |
| return; |
| } |
| |
| if (len == value->Length) |
| { |
| WriteByte(static_cast<unsigned char>(DSCode::CacheableASCIIString));//ascii string |
| } |
| else |
| { |
| WriteByte(static_cast<unsigned char>(DSCode::CacheableString));//utf string |
| } |
| WriteUInt16(len); |
| EnsureCapacity(len); |
| EncodeUTF8String(value, len); |
| |
| } |
| |
| void DataOutput::WriteASCIIHuge(String^ value) |
| { |
| if (value != nullptr) { |
| const int strLength = value->Length; |
| WriteUInt32(strLength); |
| EnsureCapacity(strLength); |
| for (int i = 0; i < strLength; i++) { |
| m_bytes[m_cursor++] = (System::Byte)value[i]; |
| } |
| } |
| else { |
| WriteUInt32(0); |
| } |
| } |
| |
| /* Write UTF-16 */ |
| void DataOutput::WriteUTFHuge(String^ value) |
| { |
| if (value != nullptr) { |
| WriteUInt32(value->Length); |
| EnsureCapacity(value->Length * 2); |
| for (int i = 0; i < value->Length; i++) |
| { |
| Char ch = value[i]; |
| m_bytes[m_cursor++] = (Byte)((ch & 0xff00) >> 8); |
| m_bytes[m_cursor++] = (Byte)(ch & 0xff); |
| } |
| } |
| else { |
| WriteUInt32(0); |
| } |
| } |
| |
| /*void DataOutput::WriteObject( Object^ obj ) |
| { |
| WriteObjectInternal((ISerializable^)obj); |
| }*/ |
| |
| /*void DataOutput::WriteObject( Object^ obj ) |
| { |
| WriteObject( (ISerializable^)obj ); |
| }*/ |
| |
| int8_t DataOutput::GetTypeId(System::UInt32 classId) |
| { |
| if (classId >= 0x80000000) { |
| return (int8_t)((classId - 0x80000000) % 0x20000000); |
| } |
| else if (classId <= 0x7F) { |
| return (int8_t)DSCode::CacheableUserData; |
| } |
| else if (classId <= 0x7FFF) { |
| return (int8_t)DSCode::CacheableUserData2; |
| } |
| else { |
| return (int8_t)DSCode::CacheableUserData4; |
| } |
| } |
| |
| int8_t DataOutput::DSFID(System::UInt32 classId) |
| { |
| // convention that [0x8000000, 0xa0000000) is for FixedIDDefault, |
| // [0xa000000, 0xc0000000) is for FixedIDByte, |
| // [0xc0000000, 0xe0000000) is for FixedIDShort |
| // and [0xe0000000, 0xffffffff] is for FixedIDInt |
| // Note: depends on fact that FixedIDByte is 1, FixedIDShort is 2 |
| // and FixedIDInt is 3; if this changes then correct this accordingly |
| if (classId >= 0x80000000) { |
| return (int8_t)((classId - 0x80000000) / 0x20000000); |
| } |
| return 0; |
| } |
| |
| void DataOutput::WriteObject(Object^ obj) |
| { |
| |
| if (obj == nullptr) |
| { |
| WriteByte((int8_t)DSCode::NullObj); |
| return; |
| } |
| |
| if (m_ispdxSerialization && obj->GetType()->IsEnum) |
| { |
| //need to set |
| int enumVal = Internal::PdxHelper::GetEnumValue(obj->GetType()->FullName, Enum::GetName(obj->GetType(), obj), obj->GetHashCode(), m_cache); |
| WriteByte(static_cast<int8_t>(DSCode::PDX_ENUM)); |
| WriteByte(enumVal >> 24); |
| WriteArrayLen(enumVal & 0xFFFFFF); |
| return; |
| } |
| |
| DSCode typeId = static_cast<DSCode>(m_cache->TypeRegistry->GetDsCodeForManagedType(obj->GetType())); |
| |
| switch (typeId) |
| { |
| case DSCode::CacheableByte: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteByte((Byte)obj); |
| return; |
| } |
| case DSCode::CacheableBoolean: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteBoolean((bool)obj); |
| return; |
| } |
| case DSCode::CacheableCharacter: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteObject((Char)obj); |
| return; |
| } |
| case DSCode::CacheableDouble: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteDouble((Double)obj); |
| return; |
| } |
| case DSCode::CacheableASCIIString: |
| { |
| //CacheableString^ cStr = CacheableString::Create((String^)obj); |
| //// TODO: igfser mapping between generic and non generic |
| //WriteObjectInternal(cStr); |
| WriteStringWithType((String^)obj); |
| return; |
| } |
| case DSCode::CacheableFloat: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteFloat((float)obj); |
| return; |
| } |
| case DSCode::CacheableInt16: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteInt16((Int16)obj); |
| return; |
| } |
| case DSCode::CacheableInt32: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteInt32((Int32)obj); |
| return; |
| } |
| case DSCode::CacheableInt64: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteInt64((Int64)obj); |
| return; |
| } |
| case DSCode::CacheableDate: |
| { |
| //CacheableDate^ cd = gcnew CacheableDate((DateTime)obj); |
| // TODO: igfser mapping between generic and non generic |
| //WriteObjectInternal(cd); |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteDate((DateTime)obj); |
| return; |
| } |
| case DSCode::CacheableBytes: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteBytes((array<Byte>^)obj); |
| return; |
| } |
| case DSCode::CacheableDoubleArray: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteObject((array<Double>^)obj); |
| return; |
| } |
| case DSCode::CacheableFloatArray: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteObject((array<float>^)obj); |
| return; |
| } |
| case DSCode::CacheableInt16Array: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteObject((array<Int16>^)obj); |
| return; |
| } |
| case DSCode::CacheableInt32Array: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteObject((array<Int32>^)obj); |
| return; |
| } |
| case DSCode::CacheableInt64Array: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteObject((array<Int64>^)obj); |
| return; |
| } |
| case DSCode::BooleanArray: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteObject((array<bool>^)obj); |
| return; |
| } |
| case DSCode::CharArray: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteObject((array<char>^)obj); |
| return; |
| } |
| case DSCode::CacheableStringArray: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteObject((array<String^>^)obj); |
| return; |
| } |
| case DSCode::CacheableHashTable: |
| case DSCode::CacheableHashMap: |
| case DSCode::CacheableIdentityHashMap: |
| { |
| WriteByte(static_cast<unsigned char>(typeId)); |
| WriteDictionary((System::Collections::IDictionary^)obj); |
| return; |
| } |
| case DSCode::CacheableVector: |
| { |
| //CacheableVector^ cv = gcnew CacheableVector((System::Collections::IList^)obj); |
| //// TODO: igfser mapping between generic and non generic |
| //WriteObjectInternal(cv); |
| WriteByte(static_cast<unsigned char>(DSCode::CacheableVector)); |
| WriteList((System::Collections::IList^)obj); |
| return; |
| } |
| case DSCode::CacheableLinkedList: |
| { |
| //CacheableArrayList^ cal = gcnew CacheableArrayList((System::Collections::IList^)obj); |
| //// TODO: igfser mapping between generic and non generic |
| //WriteObjectInternal(cal); |
| WriteByte(static_cast<unsigned char>(DSCode::CacheableLinkedList)); |
| System::Collections::ICollection^ linkedList = (System::Collections::ICollection^)obj; |
| this->WriteArrayLen(linkedList->Count); |
| for each (Object^ o in linkedList) |
| this->WriteObject(o); |
| return; |
| } |
| case DSCode::CacheableArrayList: |
| { |
| //CacheableArrayList^ cal = gcnew CacheableArrayList((System::Collections::IList^)obj); |
| //// TODO: igfser mapping between generic and non generic |
| //WriteObjectInternal(cal); |
| WriteByte(static_cast<unsigned char>(DSCode::CacheableArrayList)); |
| WriteList((System::Collections::IList^)obj); |
| return; |
| } |
| case DSCode::CacheableStack: |
| { |
| CacheableStack^ cs = gcnew CacheableStack((System::Collections::ICollection^)obj); |
| // TODO: igfser mapping between generic and non generic |
| WriteObjectInternal(cs); |
| return; |
| } |
| default: |
| { |
| if (auto pdxObj = dynamic_cast<IPdxSerializable^>(obj)) |
| { |
| WriteByte(static_cast<int8_t>(DSCode::PDX)); |
| Internal::PdxHelper::SerializePdx(this, pdxObj); |
| return; |
| } |
| else |
| { |
| //pdx serialization and is array of object |
| if (m_ispdxSerialization && obj->GetType()->IsArray) |
| { |
| WriteByte(static_cast<unsigned char>(DSCode::CacheableObjectArray)); |
| WriteDotNetObjectArray(obj); |
| return; |
| } |
| |
| if (auto ct = dynamic_cast<ISerializable^>(obj)) { |
| WriteObjectInternal(ct); |
| return; |
| } |
| |
| if (m_cache->TypeRegistry->PdxSerializer) |
| { |
| auto pdxObj = gcnew PdxWrapper(obj); |
| WriteByte(static_cast<int8_t>(DSCode::PDX)); |
| Internal::PdxHelper::SerializePdx(this, pdxObj); |
| return; |
| } |
| } |
| |
| throw gcnew System::Exception("DataOutput not found appropriate type to write it for object: " + obj->GetType()); |
| } |
| } |
| } |
| |
| void DataOutput::WriteStringArray(array<String^>^ strArray) |
| { |
| if (strArray != nullptr) |
| { |
| this->WriteArrayLen(strArray->Length); |
| for (int i = 0; i < strArray->Length; i++) |
| { |
| // this->WriteUTF(strArray[i]); |
| WriteObject(strArray[i]); |
| } |
| } |
| else |
| WriteByte(-1); |
| } |
| |
| void DataOutput::WriteObjectInternal(ISerializable^ obj) |
| { |
| //CacheableKey^ key = gcnew CacheableKey(); |
| if (obj == nullptr) { |
| WriteByte((int8_t)DSCode::NullObj); |
| } |
| else if (auto dataSerializablePrimitive = dynamic_cast<IDataSerializablePrimitive^>(obj)) |
| { |
| auto dsCode = dataSerializablePrimitive->DsCode; |
| WriteByte(dsCode); |
| dataSerializablePrimitive->ToData(this); |
| } |
| else if (auto dataSerializable = dynamic_cast<IDataSerializable^>(obj)) |
| { |
| auto id = m_cache->TypeRegistry->GetIdForManagedType(dataSerializable->GetType()); |
| |
| auto dsCode = getDataSerializableDsCode(id); |
| WriteByte(static_cast<int8_t>(dsCode)); |
| switch (dsCode) { |
| case DSCode::CacheableUserData: |
| WriteByte(static_cast<int8_t>(id)); |
| break; |
| case DSCode::CacheableUserData2: |
| WriteInt16(static_cast<int16_t>(id)); |
| break; |
| case DSCode::CacheableUserData4: |
| WriteInt32(static_cast<int32_t>(id)); |
| break; |
| default: |
| IllegalStateException("Invalid DS Code."); |
| } |
| dataSerializable->ToData(this); |
| } |
| else if (auto dataSerializableFixedId = dynamic_cast<IDataSerializableFixedId^>(obj)) |
| { |
| auto id = dataSerializableFixedId->DSFID; |
| auto dsCode = getDataSerializableFixedIdDsCode(id); |
| WriteByte(dsCode); |
| switch (static_cast<DSCode>(dsCode)) { |
| case DSCode::FixedIDByte: |
| WriteByte(static_cast<int8_t>(id)); |
| break; |
| case DSCode::FixedIDShort: |
| WriteInt16(static_cast<int16_t>(id)); |
| break; |
| case DSCode::FixedIDInt: |
| WriteInt32(static_cast<int32_t>(id)); |
| break; |
| default: |
| IllegalStateException("Invalid DS Code."); |
| } |
| dataSerializable->ToData(this); |
| } |
| else |
| { |
| throw gcnew IllegalStateException("Unknown serializable type."); |
| } |
| } |
| |
| void DataOutput::AdvanceCursor(System::UInt32 offset) |
| { |
| EnsureCapacity(offset); |
| m_cursor += offset; |
| } |
| |
| void DataOutput::RewindCursor(System::UInt32 offset) |
| { |
| //first set native one |
| WriteBytesToUMDataOutput(); |
| try |
| { |
| m_nativeptr->get()->rewindCursor(offset); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| SetBuffer(); |
| } |
| |
| array<Byte>^ DataOutput::GetBuffer() |
| { |
| try |
| { |
| WriteBytesToUMDataOutput(); |
| SetBuffer(); |
| auto buffLen = static_cast<int>(m_nativeptr->get()->getBufferLength()); |
| array<Byte>^ buffer = gcnew array<Byte>(buffLen); |
| |
| if (buffLen > 0) { |
| pin_ptr<Byte> pin_buffer = &buffer[0]; |
| memcpy((void*)pin_buffer, m_nativeptr->get()->getBuffer(), buffLen); |
| } |
| return buffer; |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| } |
| |
| size_t DataOutput::BufferLength::get() |
| { |
| //first set native one |
| WriteBytesToUMDataOutput(); |
| SetBuffer(); |
| |
| try |
| { |
| return m_nativeptr->get()->getBufferLength(); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| } |
| |
| void DataOutput::Reset() |
| { |
| WriteBytesToUMDataOutput(); |
| try |
| { |
| m_nativeptr->get()->reset(); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| SetBuffer(); |
| } |
| |
| void DataOutput::WriteString(String^ value) |
| { |
| if (value == nullptr) |
| { |
| this->WriteByte(static_cast<unsigned char>(DSCode::CacheableNullString)); |
| } |
| else |
| { |
| WriteObject(value); |
| /*CacheableString^ cs = gcnew CacheableString(value); |
| |
| this->WriteByte( (Byte)(cs->ClassId - 0x80000000)); |
| cs->ToData(this);*/ |
| } |
| } |
| |
| void DataOutput::WriteBytesToUMDataOutput() |
| { |
| try |
| { |
| m_nativeptr->get()->advanceCursor(m_cursor); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| m_cursor = 0; |
| m_remainingBufferLength = 0; |
| m_bytes = nullptr; |
| } |
| |
| void DataOutput::WriteObject(bool% obj) |
| { |
| WriteBoolean(obj); |
| } |
| |
| void DataOutput::WriteObject(Byte% obj) |
| { |
| WriteByte(obj); |
| } |
| |
| void DataOutput::WriteObject(Char% obj) |
| { |
| unsigned short us = (unsigned short)obj; |
| EnsureCapacity(2); |
| m_bytes[m_cursor++] = us >> 8; |
| m_bytes[m_cursor++] = (Byte)us; |
| } |
| |
| void DataOutput::WriteObject(Double% obj) |
| { |
| WriteDouble(obj); |
| } |
| |
| void DataOutput::WriteObject(Single% obj) |
| { |
| WriteFloat(obj); |
| } |
| |
| void DataOutput::WriteObject(System::Int16% obj) |
| { |
| WriteInt16(obj); |
| } |
| |
| void DataOutput::WriteObject(System::Int32% obj) |
| { |
| WriteInt32(obj); |
| } |
| |
| void DataOutput::WriteObject(System::Int64% obj) |
| { |
| WriteInt64(obj); |
| } |
| |
| void DataOutput::WriteObject(UInt16% obj) |
| { |
| WriteUInt16(obj); |
| } |
| |
| void DataOutput::WriteObject(UInt32% obj) |
| { |
| WriteUInt32(obj); |
| } |
| |
| void DataOutput::WriteObject(UInt64% obj) |
| { |
| WriteUInt64(obj); |
| } |
| |
| void DataOutput::WriteBooleanArray(array<bool>^ boolArray) |
| { |
| WriteObject<bool>(boolArray); |
| } |
| |
| void DataOutput::WriteShortArray(array<Int16>^ shortArray) |
| { |
| WriteObject<Int16>(shortArray); |
| } |
| |
| void DataOutput::WriteIntArray(array<Int32>^ intArray) |
| { |
| WriteObject<Int32>(intArray); |
| } |
| |
| void DataOutput::WriteLongArray(array<Int64>^ longArray) |
| { |
| WriteObject<Int64>(longArray); |
| } |
| |
| void DataOutput::WriteFloatArray(array<float>^ floatArray) |
| { |
| WriteObject<float>(floatArray); |
| } |
| |
| void DataOutput::WriteDoubleArray(array<double>^ doubleArray) |
| { |
| WriteObject<double>(doubleArray); |
| } |
| |
| native::Pool* DataOutput::GetPool() |
| { |
| try |
| { |
| return native::DataOutputInternal::getPool(*m_nativeptr); |
| } |
| finally |
| { |
| GC::KeepAlive(m_nativeptr); |
| } |
| } |
| |
| } // namespace Client |
| } // namespace Geode |
| } // namespace Apache |