blob: f15517d11a17e37303b21f50518ed92529d72c82 [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.
*=========================================================================
*/
#ifndef _GFAS_ASCLIBUILTINS_HPP_
#define _GFAS_ASCLIBUILTINS_HPP_
#ifdef GEMFIRE_CLR
#include "ASBuiltins.hpp"
#include <vcclr.h>
using namespace System;
using namespace System::Collections::Generic;
namespace GemStone
{
namespace GemFire
{
namespace Cache
{
namespace Serializer
{
/**
* @brief Helper type traits and other structs/classes do determine type
* information at compile time using typename.
* Useful for templates in particular.
*/
namespace TypeHelper
{
typedef uint8_t yes_type;
typedef uint32_t no_type;
template <typename TBase, typename TDerived>
struct BDHelper
{
template <typename T>
static yes_type check_sig( TDerived const volatile^, T );
static no_type check_sig( TBase const volatile^, int );
};
/**
* @brief This struct helps us determine whether or not a class is a
* subclass of another at compile time, so that it can be used
* in templates. Adapted and extended from
* {@link http://groups.google.com/group/comp.lang.c++.moderated/msg/dd6c4e4d5160bd83}
*/
template <typename TBase, typename TDerived>
struct SuperSubclass
{
private:
struct Host
{
operator TBase const volatile^ ( ) const;
operator TDerived const volatile^ ( );
};
public:
static const bool result = sizeof( BDHelper<TBase, TDerived>::
check_sig( Host( ), 0 ) ) == sizeof( yes_type );
};
template <typename TBase>
struct SuperSubclass<TBase, TBase>
{
static const bool result = true;
};
template <bool getType=true>
struct YesNoType
{
static const yes_type value = 0;
};
template <>
struct YesNoType<false>
{
static const no_type value = 0;
};
}
#define TYPE_IS_IGFSERIALIZABLE( T ) \
TypeHelper::SuperSubclass<IGFSerializable, T>::result
#define TYPE_IS_IGFSERIALIZABLE_TYPE( T ) \
TypeHelper::YesNoType<TYPE_IS_SERIALIZABLE( T )>::value
inline void WriteObject( gemfire::DataOutput& output, Byte value )
{
output.write( ( uint8_t )value );
}
inline void ReadObject( gemfire::DataInput& input, Byte% value )
{
uint8_t val;
input.read( &val );
value = val;
}
inline void WriteObject( gemfire::DataOutput& output, SByte value )
{
output.write( ( int8_t )value );
}
inline void ReadObject( gemfire::DataInput& input, SByte% value )
{
int8_t val;
input.read( &val );
value = val;
}
inline void WriteObject( gemfire::DataOutput& output,
array<Byte>^ bytes )
{
if ( bytes != nullptr )
{
// We can safely use the pinning technique here since the pointer
// is not required after the end of native 'writeBytes' function.
pin_ptr<Byte> pin_bytes = &bytes[0];
output.writeBytes( ( uint8_t* )pin_bytes, bytes->Length );
}
else
{
output.writeBytes( ( uint8_t* )NULL, 0 );
}
}
inline void ReadObject( gemfire::DataInput& input,
array<Byte>^% bytes )
{
int32_t length;
input.readInt( &length );
if ( length > 0 )
{
bytes = gcnew array<Byte>( length );
pin_ptr<Byte> pin_bytes = &bytes[0];
input.readBytes( ( uint8_t* )pin_bytes, length );
}
else
{
bytes = nullptr;
}
}
inline void WriteObject( gemfire::DataOutput& output,
array<SByte>^ bytes )
{
if ( bytes != nullptr )
{
pin_ptr<SByte> pin_bytes = &bytes[0];
output.writeBytes( ( int8_t* )pin_bytes, bytes->Length );
}
else
{
output.writeBytes( ( int8_t* )NULL, 0 );
}
}
inline void ReadObject( gemfire::DataInput& input,
array<SByte>^% bytes )
{
int32_t length;
input.readInt( &length );
if ( length > 0 )
{
bytes = gcnew array<SByte>( length );
pin_ptr<SByte> pin_bytes = &bytes[0];
input.readBytes( ( int8_t* )pin_bytes, length );
}
else
{
bytes = nullptr;
}
}
inline void WriteObject( gemfire::DataOutput& output, Int16 value )
{
output.writeInt( ( int16_t )value );
}
inline void ReadObject( gemfire::DataInput& input, Int16% value )
{
int16_t val;
input.readInt( &val );
value = val;
}
inline void WriteObject( gemfire::DataOutput& output, Int32 value )
{
output.writeInt( value );
}
inline void ReadObject( gemfire::DataInput& input, Int32% value )
{
int32_t val;
input.readInt( &val );
value = val;
}
inline void WriteObject( gemfire::DataOutput& output, Int64 value )
{
output.writeInt( value );
}
inline void ReadObject( gemfire::DataInput& input, Int64% value )
{
int64_t val;
input.readInt( &val );
value = val;
}
inline void WriteObject( gemfire::DataOutput& output, UInt16 value )
{
output.writeInt( value );
}
inline void ReadObject( gemfire::DataInput& input, UInt16% value )
{
uint16_t val;
input.readInt( &val );
value = val;
}
inline void WriteObject( gemfire::DataOutput& output, UInt32 value )
{
output.writeInt( value );
}
inline void ReadObject( gemfire::DataInput& input, UInt32% value )
{
uint32_t val;
input.readInt( &val );
value = val;
}
inline void WriteObject( gemfire::DataOutput& output, UInt64 value )
{
output.writeInt( value );
}
inline void ReadObject( gemfire::DataInput& input, UInt64% value )
{
uint64_t val;
input.readInt( &val );
value = val;
}
inline void WriteObject( gemfire::DataOutput& output, Boolean value )
{
output.write( ( uint8_t )( value ? 1 : 0 ) );
}
inline void ReadObject( gemfire::DataInput& input, Boolean% value )
{
uint8_t byte;
input.read( &byte );
value = ( byte == 1 ? true : false );
}
inline void WriteObject( gemfire::DataOutput& output, Double value )
{
output.writeDouble( value );
}
inline void ReadObject( gemfire::DataInput& input, Double% value )
{
double val;
input.readDouble( &val );
value = val;
}
inline void WriteObject( gemfire::DataOutput& output, Single value )
{
output.writeFloat( value );
}
inline void ReadObject( gemfire::DataInput& input, Single% value )
{
float val;
input.readFloat( &val );
value = val;
}
inline void WriteObject( gemfire::DataOutput& output, String^ str )
{
if ( str != nullptr )
{
pin_ptr<const wchar_t> pin_str = PtrToStringChars( str );
output.writeUTF( ( wchar_t* )pin_str, str->Length );
}
else
{
output.writeUTF( ( wchar_t* )NULL, 0 );
}
}
inline void ReadObject( gemfire::DataInput& input, String^% str )
{
wchar_t* n_buffer = nullptr;
uint16_t len;
input.readUTF( &n_buffer, &len );
if ( len > 0 )
{
str = gcnew String( n_buffer, 0, len );
input.freeUTFMemory( n_buffer );
}
else
{
str = nullptr;
}
}
template <typename TObj>
inline void WriteObject( gemfire::DataOutput& output,
DataOutput^ mg_output, TObj^ value,
TypeHelper::yes_type isSerializable )
{
mg_output->WriteObject( value );
}
template <typename TObj>
inline void WriteObject( gemfire::DataOutput& output,
DataOutput^ mg_output, TObj^ value,
TypeHelper::no_type isNotSerializable )
{
WriteObject( output, value );
}
template <typename TObj>
inline void WriteObject( gemfire::DataOutput& output,
DataOutput^ mg_output, TObj^ value )
{
WriteObject( output, mg_output, value,
TYPE_IS_IGFSERIALIZABLE_TYPE( TObj ) );
}
template <typename TObj>
inline void WriteObject( gemfire::DataOutput& output,
DataOutput^ mg_output, TObj value )
{
WriteObject( output, value );
}
template <typename TObj>
inline void ReadObject( gemfire::DataInput& input,
DataInput^ mg_input, TObj^% value,
TypeHelper::yes_type isSerializable )
{
value = static_cast<TObj^>( mg_input->ReadObject( ) );
}
template <typename TObj>
inline void ReadObject( gemfire::DataInput& input,
DataInput^ mg_input, TObj^% value,
TypeHelper::no_type isNotSerializable )
{
ReadObject( input, value );
}
template <typename TObj>
inline void ReadObject( gemfire::DataInput& input,
DataInput^ mg_input, TObj^% value )
{
ReadObject( input, mg_input, value,
TYPE_IS_IGFSERIALIZABLE_TYPE( TObj ) );
}
template <typename TObj>
inline void ReadObject( gemfire::DataInput& input,
DataInput^ mg_input, TObj% value )
{
ReadObject( input, value );
}
template <typename TObj>
inline void WriteObject( gemfire::DataOutput& output,
array<TObj>^ arr )
{
if ( arr != nullptr )
{
pin_ptr<TObj> pin_arr = &arr[0];
gemfire::serializer::writeObject( output, ( TObj* )pin_arr,
arr->Length );
}
else
{
output.writeInt( 0 );
}
}
template <typename TObj>
inline void ReadObject( gemfire::DataInput& input,
array<TObj>^% arr )
{
int32_t size;
input.readInt( &size );
if ( size > 0 )
{
arr = gcnew array<TObj>( size );
pin_ptr<TObj> pin_arr = &arr[0];
gemfire::serializer::readArray( input, ( TObj* )pin_arr, size );
}
else
{
arr = nullptr;
}
}
template <typename TObj>
inline void WriteObject( gemfire::DataOutput& output,
DataOutput^ mg_output, array<TObj^>^ arr )
{
if ( arr != nullptr )
{
output.writeInt( arr->Length );
for each ( TObj^ obj in arr )
{
WriteObject( output, mg_output, obj );
}
}
else
{
output.writeInt( -1 );
}
}
template <typename TObj>
inline void ReadObject( gemfire::DataInput& input,
DataInput^ mg_input, array<TObj^>^% arr )
{
int32_t size;
input.readInt( &size );
if ( size > 0 )
{
arr = gcnew array<TObj^>( size );
for each ( TObj^ obj in arr )
{
ReadObject( input, mg_input, obj );
}
}
else
{
arr = nullptr;
}
}
template <typename TObj>
inline void WriteObject( gemfire::DataOutput& output,
DataOutput^ mg_output, List<TObj>^ value )
{
if ( value != nullptr ) {
output.writeInt( value->Count );
for each ( TObj obj in value ) {
WriteObject( output, mg_output, obj );
}
} else {
output.writeInt( -1 );
}
}
template <typename TObj>
inline void ReadObject( gemfire::DataInput& input,
DataInput^ mg_input, List<TObj>^% value )
{
int32_t len;
input.readInt( &len );
if ( len > 0 ) {
value = gcnew List<TObj>( len );
for ( int32_t listIndex = 0; listIndex < len; listIndex++ ) {
ReadObject( input, mg_input, value[ listIndex ] );
}
} else {
value = nullptr;
}
}
template <typename TKey, typename TVal>
inline void WriteObject( gemfire::DataOutput& output,
DataOutput^ mg_output,
Dictionary<TKey, TVal>^ value )
{
if ( value != nullptr ) {
output.writeInt( value->Count );
for each ( KeyValuePair<TKey, TVal>^ pair in value ) {
WriteObject( output, mg_output, pair->Key );
WriteObject( output, mg_output, pair->Value );
}
} else {
output.writeInt( -1 );
}
}
template <typename TKey, typename TVal>
inline void ReadObject( gemfire::DataInput& input,
DataInput^ mg_input,
Dictionary<TKey, TVal>^% value )
{
int32_t len;
input.readInt( &len );
if ( len > 0 ) {
TKey^ key;
TVal^ val;
value = gcnew Dictionary<TKey, TVal>( len );
for ( int32_t listIndex = 0; listIndex < len; listIndex++ ) {
ReadObject( input, mg_input, key );
ReadObject( input, mg_input, val );
value[ key ] = val;
}
} else {
value = nullptr;
}
}
}
}
}
}
#endif // GEMFIRE_CLR
#endif // _GFAS_ASCLIBUILTINS_HPP_