blob: 383ee30e40baa54fd0e5b5423bf2f2c5290e42b2 [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
#include "gf_includes.hpp"
#include "DataOutputM.hpp"
#include <cppcache/impl/GemfireTypeIdsImpl.hpp>
#include <vcclr.h>
#include "IGFSerializable.hpp"
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace gemfire;
namespace GemStone
{
namespace GemFire
{
namespace Cache
{
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::WriteBytes( array<Byte>^ bytes, int32_t len )
{
//TODO::hitesh
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 GemFire::Cache::IllegalArgumentException("DataOutput::WriteBytes argument len is not in byte array range." );
}
}
else
{
WriteByte(0xFF);
}
}
/* void DataOutput::WriteArrayLen( int32_t len )
{
if (len == -1) {
WriteByte(0xFF);
} else if (len <= 252) { // 252 is java's ((byte)-4 && 0xFF)
WriteByte(Convert::ToByte(len));
} else if (len <= 0xFFFF) {
WriteByte(0xFE);
WriteInt16(Convert::ToInt16(len));
} else {
WriteByte(Convert::ToByte(-0xFD));
WriteInt32(len);
}
}*/
void DataOutput::WriteArrayLen( int32_t len )
{
if (len == -1) {//0xff
WriteByte(0xFF);
} else if (len <= 252) { // 252 is java's ((byte)-4 && 0xFF) or 0xfc
WriteByte(Convert::ToByte(len));
} else if (len <= 0xFFFF) {
WriteByte(0xFE);//0xfe
WriteUInt16((len));
} else {
WriteByte((0xFD));//0xfd
WriteUInt32(len);
}
}
void DataOutput::WriteSBytes( array<SByte>^ bytes, int32_t len )
{
//TODO::hitesh
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 GemFire::Cache::IllegalArgumentException("DataOutput::WriteSBytes argument len is not in SByte array range." );
}
}
else
{
WriteByte(0xFF);
}
}
void DataOutput::WriteBytesOnly( array<Byte>^ bytes, uint32_t len )
{
WriteBytesOnly(bytes, len, 0);
}
void DataOutput::WriteBytesOnly( array<Byte>^ bytes, uint32_t len, uint32_t offset )
{
//TODO::hitesh
if (bytes != nullptr)
{
if ( len >= 0 && len <= ((uint32_t)bytes->Length - offset) )
{
EnsureCapacity(len);
for( uint32_t i = 0; i < len; i++ )
m_bytes[m_cursor++] = bytes[offset + i];
}
else
{
throw gcnew GemFire::Cache::IllegalArgumentException("DataOutput::WriteBytesOnly argument len is not in Byte array range." );
}
}
}
void DataOutput::WriteSBytesOnly( array<SByte>^ bytes, uint32_t len )
{
//TODO::hitesh
if (bytes != nullptr)
{
if ( len >= 0 && len <= (uint32_t)bytes->Length )
{
EnsureCapacity(len);
for( uint32_t i = 0; i < len; i++ )
m_bytes[m_cursor++] = bytes[i];
}
else
{
throw gcnew GemFire::Cache::IllegalArgumentException("DataOutput::WriteSBytesOnly argument len is not in SByte array range." );
}
}
}
void DataOutput::WriteUInt16( uint16_t value )
{
EnsureCapacity(2);
m_bytes[m_cursor++] = (uint8_t)(value >> 8);
m_bytes[m_cursor++] = (uint8_t)value;
}
void DataOutput::WriteUInt32( uint32_t value )
{
EnsureCapacity(4);
m_bytes[m_cursor++] = (uint8_t)(value >> 24);
m_bytes[m_cursor++] = (uint8_t)(value >> 16);
m_bytes[m_cursor++] = (uint8_t)(value >> 8);
m_bytes[m_cursor++] = (uint8_t)value;
}
void DataOutput::WriteUInt64( uint64_t value )
{
EnsureCapacity(8);
m_bytes[m_cursor++] = (uint8_t)(value >> 56);
m_bytes[m_cursor++] = (uint8_t)(value >> 48);
m_bytes[m_cursor++] = (uint8_t)(value >> 40);
m_bytes[m_cursor++] = (uint8_t)(value >> 32);
m_bytes[m_cursor++] = (uint8_t)(value >> 24);
m_bytes[m_cursor++] = (uint8_t)(value >> 16);
m_bytes[m_cursor++] = (uint8_t)(value >> 8);
m_bytes[m_cursor++] = (uint8_t)value;
}
void DataOutput::WriteInt16( int16_t value )
{
WriteUInt16(value);
}
void DataOutput::WriteInt32( int32_t value )
{
WriteUInt32(value);
}
void DataOutput::WriteInt64( int64_t value )
{
WriteUInt64(value);
}
void DataOutput::WriteFloat( float value )
{
array<Byte>^ bytes = BitConverter::GetBytes(value);
EnsureCapacity(4);
for(int i = bytes->Length - 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 = bytes->Length - 1; i >=0 ; i--)
m_bytes[m_cursor++] = bytes[i];
}
void DataOutput::WriteUTF( String^ value )
{
if (value != nullptr) {
int len = value->Length*3;
if (len > 8192) //approx check
len = getEncodedLength(value);
if (len > 0xffff)
len = 0xffff;
EnsureCapacity(len);
m_cursor += 2;
int strLen = EncodeString(value, len);
m_cursor -= (strLen + 2);
WriteUInt16(strLen);
m_cursor += strLen;
}
else {
WriteUInt16(0);
}
}
void DataOutput::WriteASCIIHuge( String^ value )
{
//TODO::hitesh
if (value != nullptr) {
EnsureCapacity(value->Length);
m_cursor += 4;
int strLen = EncodeString(value, value->Length);
m_cursor -= (strLen + 4);
WriteUInt32(strLen);
m_cursor += strLen;
}
else {
WriteUInt32(0);
}
}
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( IGFSerializable^ obj )
{
WriteObjectInternal(obj);
}
void DataOutput::WriteObject( Serializable^ obj )
{
WriteObject( (IGFSerializable^)obj );
}
int8_t DataOutput::GetTypeId(uint32_t classId )
{
if (classId >= 0x80000000) {
return (int8_t)((classId - 0x80000000) % 0x20000000);
}
else if (classId <= 0x7F) {
return (int8_t)GemfireTypeIdsImpl::CacheableUserData;
}
else if (classId <= 0x7FFF) {
return (int8_t)GemfireTypeIdsImpl::CacheableUserData2;
}
else {
return (int8_t)GemfireTypeIdsImpl::CacheableUserData4;
}
}
int8_t DataOutput::DSFID(uint32_t 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::WriteGenericObject(Object^ obj)
{
if ( obj == nullptr )
{
WriteByte( (int8_t) GemfireTypeIds::NullObj );
return;
}
Byte typeId = GemStone::GemFire::Cache::Generic::Serializable::GetManagedTypeMappingGeneric(obj->GetType());
switch(typeId)
{
case gemfire::GemfireTypeIds::CacheableByte:
{
WriteByte(typeId);
WriteByte((Byte)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableBoolean:
{
WriteByte(typeId);
WriteBoolean((bool)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableWideChar:
{
WriteByte(typeId);
WriteObject((Char)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableDouble:
{
WriteByte(typeId);
WriteDouble((Double)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableASCIIString:
{
GemStone::GemFire::Cache::CacheableString^ cStr = GemStone::GemFire::Cache::CacheableString::Create((String^)obj);
WriteObjectInternal(cStr);
return;
}
case gemfire::GemfireTypeIds::CacheableFloat:
{
WriteByte(typeId);
WriteFloat((float)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableInt16:
{
WriteByte(typeId);
WriteInt16((Int16)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableInt32:
{
WriteByte(typeId);
WriteInt32((Int32)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableInt64:
{
WriteByte(typeId);
WriteInt64((Int64)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableDate:
{
GemStone::GemFire::Cache::CacheableDate^ cd = gcnew GemStone::GemFire::Cache::CacheableDate((DateTime)obj);
WriteObjectInternal(cd);
return;
}
case gemfire::GemfireTypeIds::CacheableBytes:
{
WriteByte(typeId);
WriteBytes((array<Byte>^)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableDoubleArray:
{
WriteByte(typeId);
WriteObject((array<Double>^)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableFloatArray:
{
WriteByte(typeId);
WriteObject((array<float>^)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableInt16Array:
{
WriteByte(typeId);
WriteObject((array<Int16>^)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableInt32Array:
{
WriteByte(typeId);
WriteObject((array<Int32>^)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableInt64Array:
{
WriteByte(typeId);
WriteObject((array<Int64>^)obj);
return;
}
case gemfire::GemfireTypeIds::BooleanArray:
{
WriteByte(typeId);
WriteObject((array<bool>^)obj);
return;
}
case gemfire::GemfireTypeIds::CharArray:
{
WriteByte(typeId);
WriteObject((array<char>^)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableStringArray:
{
WriteByte(typeId);
WriteObject((array<String^>^)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableHashTable:
case gemfire::GemfireTypeIds::CacheableHashMap:
case gemfire::GemfireTypeIds::CacheableIdentityHashMap:
{
WriteByte(typeId);
WriteDictionary((System::Collections::IDictionary^)obj);
return;
}
case gemfire::GemfireTypeIds::CacheableVector:
{
GemStone::GemFire::Cache::CacheableVector^ cv = gcnew GemStone::GemFire::Cache::CacheableVector((System::Collections::IList^)obj);
WriteObjectInternal(cv);
return;
}
case gemfire::GemfireTypeIds::CacheableArrayList:
{
GemStone::GemFire::Cache::CacheableArrayList^ cal = gcnew GemStone::GemFire::Cache::CacheableArrayList((System::Collections::IList^)obj);
WriteObjectInternal(cal);
return;
}
case gemfire::GemfireTypeIds::CacheableStack:
{
GemStone::GemFire::Cache::CacheableStack^ cs = gcnew GemStone::GemFire::Cache::CacheableStack((System::Collections::ICollection^)obj);
WriteObjectInternal(cs);
return;
}
default:
{
IGFSerializable^ ct = safe_cast<IGFSerializable^>(obj);
if(ct != nullptr) {
WriteObjectInternal(ct);
return ;
}
throw gcnew System::Exception("DataOutput not found appropriate type to write it.");
}
}
}
*/
/*
void DataOutput::WriteStringArray(array<String^>^ strArray)
{
this->WriteArrayLen(strArray->Length);
for(int i = 0; i < strArray->Length; i++)
{
this->WriteUTF(strArray[i]);
}
}
*/
void DataOutput::WriteObjectInternal( IGFSerializable^ obj )
{
//CacheableKey^ key = gcnew CacheableKey();
if ( obj == nullptr ) {
WriteByte( (int8_t) GemfireTypeIds::NullObj );
} else {
int8_t typeId = DataOutput::GetTypeId( obj->ClassId);
switch (DataOutput::DSFID(obj->ClassId)) {
case GemfireTypeIdsImpl::FixedIDByte:
WriteByte((int8_t)GemfireTypeIdsImpl::FixedIDByte);
WriteByte( typeId ); // write the type ID.
break;
case GemfireTypeIdsImpl::FixedIDShort:
WriteByte((int8_t)GemfireTypeIdsImpl::FixedIDShort);
WriteInt16( (int16_t)typeId ); // write the type ID.
break;
case GemfireTypeIdsImpl::FixedIDInt:
WriteByte((int8_t)GemfireTypeIdsImpl::FixedIDInt);
WriteInt32( (int32_t)typeId ); // write the type ID.
break;
default:
WriteByte( typeId ); // write the type ID.
break;
}
if ( (int32_t)typeId == GemfireTypeIdsImpl::CacheableUserData ) {
WriteByte( (int8_t) obj->ClassId );
} else if ( (int32_t)typeId == GemfireTypeIdsImpl::CacheableUserData2 ) {
WriteInt16( (int16_t) obj->ClassId );
} else if ( (int32_t)typeId == GemfireTypeIdsImpl::CacheableUserData4 ) {
WriteInt32( (int32_t) obj->ClassId );
}
obj->ToData( this ); // let the obj serialize itself.
}
}
void DataOutput::AdvanceCursor( uint32_t offset )
{
m_cursor += offset;
}
void DataOutput::RewindCursor( uint32_t offset )
{
//first set native one
WriteBytesToUMDataOutput();
NativePtr->rewindCursor(offset);
SetBuffer();
//m_cursor -= offset;
}
array<Byte>^ DataOutput::GetBuffer( )
{
//TODO::hitesh
// return m_bytes;
//first set native one
WriteBytesToUMDataOutput();
SetBuffer();
int buffLen = NativePtr->getBufferLength();
array<Byte>^ buffer = gcnew array<Byte>( buffLen );
if ( buffLen > 0 ) {
pin_ptr<Byte> pin_buffer = &buffer[ 0 ];
memcpy( (void*)pin_buffer, NativePtr->getBuffer( ), buffLen );
}
return buffer;
}
uint32_t DataOutput::BufferLength::get( )
{
//first set native one
WriteBytesToUMDataOutput();
SetBuffer();
return NativePtr->getBufferLength();
}
void DataOutput::Reset( )
{
//first set native one
WriteBytesToUMDataOutput();
NativePtr->reset();
SetBuffer();
}
}
}
}