Click here to Skip to main content
15,888,175 members
Articles / Programming Languages / C#

Windows Development in C++, COM API Clients

Rate me:
Please Sign up or sign in to vote.
4.98/5 (31 votes)
3 Jan 2015CPOL7 min read 62.9K   1.6K   106  
Using the Facade Pattern to simplify development with COM based APIs
#pragma once
#ifndef __HWINBINARYREADER_H__
#define __HWINBINARYREADER_H__

#include "hwinDef.h"
#include "hwinException.h"
#include "hwinString.h"
#include "hwinDateTime.h"
#include "hwinGuid.h"
#include "hwinIO.h"
#include "hwinNullable.h"

#ifdef _MANAGED
#pragma managed(push,off)
#endif

#pragma pack(push,8)

namespace harlinn
{
    namespace windows
    {

        class BinaryReader : public std::enable_shared_from_this<BinaryReader>
        {
        protected:
            std::shared_ptr<StreamBase> InStream;
        private:
            std::array<byte, 256> buffer_;
        public:
            BinaryReader( const std::shared_ptr<StreamBase>& stream )
                : InStream( stream )
            {
            }


            virtual std::shared_ptr<StreamBase> BaseStream( )
            {
                return InStream;
            }

        protected:
            virtual void FillBuffer( size_t numBytes )
            {
                if ( numBytes > buffer_.size( ) )
                {
                    throw ArgumentOutOfRangeException( "numBytes" );
                }
                auto ptr = buffer_.data( );
                auto numberOfBytesRead = InStream->Read( ptr, numBytes );
                if ( numberOfBytesRead < static_cast<long long>( numBytes ) )
                {
                    throw IO::EndOfStreamException( );
                }
            }

            int Read7BitEncodedInt( )
            {
                // Read out an Int32 7 bits at a time.  The high bit
                // of the byte when on means to continue reading more bytes. 
                int count = 0;
                int shift = 0;
                byte b;
                do
                {
                    // Check for a corrupted stream.  Read a max of 5 bytes.
                    // In a future version, add a DataFormatException. 
                    if ( shift == 5 * 7 )  // 5 bytes max per Int32, shift += 7 
                    {
                        throw Exception( "Bad 7-Bit Int32 format" );
                    }
                    // ReadByte handles end of stream cases for us.
                    b = ReadByte( );
                    count |= ( b & 0x7F ) << shift;
                    shift += 7;
                } while ( ( b & 0x80 ) != 0 );
                return count;
            }

        public:
            virtual int PeekChar( )
            {
                if ( !InStream->CanSeek( ) )
                {
                    return -1;
                }
                long long origPos = InStream->Position( );
                int ch = ReadSByte( );
                InStream->SetPosition( origPos );
                return ch;
            }

            virtual int Read( )
            {
                return ReadSByte( );
            }

            virtual bool ReadBoolean( )
            {
                FillBuffer( 1 );
                return ( buffer_[0] != 0 );
            }

            virtual Nullable<bool> ReadNullableBoolean( )
            {
                FillBuffer( 1 );
                if ( buffer_[0] != 0 )
                {
                    FillBuffer( 1 );
                    Nullable<bool> result( buffer_[0] != 0 );
                    return result;
                }
                return Nullable<bool>( );
            }

            virtual byte ReadByte( )
            {
                byte result = 0;
                auto bytesRead = InStream->Read( &result, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                return result;
            }

            virtual Nullable<byte> ReadNullableByte( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    byte value;
                    auto bytesRead = InStream->Read( &value, 1 );
                    if ( bytesRead == 0 )
                    {
                        throw IO::EndOfStreamException( );
                    }
                    Nullable<byte> result( value );
                    return result;
                }
                return Nullable<byte>( );
            }

            virtual char ReadSByte( )
            {
                char result = 0;
                auto bytesRead = InStream->Read( &result, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                return result;
            }

            virtual Nullable<char> ReadNullableSByte( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    char value;
                    auto bytesRead = InStream->Read( &value, 1 );
                    if ( bytesRead == 0 )
                    {
                        throw IO::EndOfStreamException( );
                    }
                    Nullable<char> result( value );
                    return result;
                }
                return Nullable<char>( );
            }

            virtual char ReadChar( )
            {
                char result = 0;
                auto bytesRead = InStream->Read( &result, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                return result;
            }

            virtual Nullable<char> ReadNullableChar( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    char value;
                    auto bytesRead = InStream->Read( &value, 1 );
                    if ( bytesRead == 0 )
                    {
                        throw IO::EndOfStreamException( );
                    }
                    Nullable<char> result( value );
                    return result;
                }
                return Nullable<char>( );
            }


            virtual wchar_t ReadWideChar( )
            {
                FillBuffer( 2 );
                auto result = ( wchar_t )( buffer_[0] | buffer_[1] << 8 );
                return result;
            }


            virtual Nullable<wchar_t> ReadNullableWideChar( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    FillBuffer( 2 );
                    auto value = ( wchar_t )( buffer_[0] | buffer_[1] << 8 );
                    Nullable<wchar_t> result( value );
                    return result;
                }
                return Nullable<wchar_t>( );
            }

            virtual short ReadInt16( )
            {
                FillBuffer( 2 );
                auto result = ( short )( buffer_[0] | buffer_[1] << 8 );
                return result;
            }

            virtual Nullable<short> ReadNullableInt16( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    FillBuffer( 2 );
                    auto value = ( short )( buffer_[0] | buffer_[1] << 8 );
                    Nullable<short> result( value );
                    return result;
                }
                return Nullable<short>( );
            }


            virtual unsigned short ReadUInt16( )
            {
                FillBuffer( 2 );
                auto result = ( unsigned short )( buffer_[0] | buffer_[1] << 8 );
                return result;
            }

            virtual Nullable<unsigned short> ReadNullableUInt16( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    FillBuffer( 2 );
                    auto value = ( unsigned short )( buffer_[0] | buffer_[1] << 8 );
                    Nullable<unsigned short> result( value );
                    return result;
                }
                return Nullable<unsigned short>( );
            }

            virtual int ReadInt32( )
            {
                FillBuffer( 4 );
                auto result = ( int )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                return result;
            }

            virtual Nullable<int> ReadNullableInt32( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    FillBuffer( 4 );
                    auto value = ( int )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    Nullable<int> result( value );
                    return result;
                }
                return Nullable<int>( );
            }

            virtual uint ReadUInt32( )
            {
                FillBuffer( 4 );
                return ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
            }

            virtual Nullable<uint> ReadNullableUInt32( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    FillBuffer( 4 );
                    auto value = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    Nullable<uint> result( value );
                    return result;
                }
                return Nullable<uint>( );
            }


            virtual long long ReadInt64( )
            {
                FillBuffer( 8 );
                uint lo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                uint hi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );
                return ( long long )( ( unsigned long long ) hi ) << 32 | lo;
            }

            virtual Nullable<long long> ReadNullableInt64( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    FillBuffer( 8 );
                    uint lo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    uint hi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );
                    auto value = ( long long )( ( unsigned long long ) hi ) << 32 | lo;
                    Nullable<long long> result( value );
                    return result;
                }
                return Nullable<long long>( );
            }

            virtual unsigned long long ReadUInt64( )
            {
                FillBuffer( 8 );
                uint lo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                uint hi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );
                return ( ( unsigned long long ) hi ) << 32 | lo;
            }

            virtual Nullable<unsigned long long> ReadNullableUInt64( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    FillBuffer( 8 );
                    uint lo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    uint hi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );
                    auto value = ( ( unsigned long long ) hi ) << 32 | lo;
                    Nullable<unsigned long long> result( value );
                    return result;
                }
                return Nullable<unsigned long long>( );
            }


            virtual float ReadSingle( )
            {
                FillBuffer( 4 );
                uint tmpBuffer = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                return *( ( float* )&tmpBuffer );
            }

            virtual Nullable<float> ReadNullableSingle( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    FillBuffer( 4 );
                    uint tmpBuffer = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    auto value = *( ( float* )&tmpBuffer );
                    Nullable<float> result( value );
                    return result;
                }
                return Nullable<float>( );
            }

            virtual std::complex<float> ReadComplexSingle( )
            {
                float real = ReadSingle( );
                float imag = ReadSingle( );
                std::complex<float> result( real, imag );
                return result;
            }

            virtual Nullable< std::complex<float> > ReadNullableComplexSingle( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    float real = ReadSingle( );
                    float imag = ReadSingle( );
                    std::complex<float> value( real, imag );
                    Nullable< std::complex<float> > result( value );
                    return result;
                }
                return Nullable< std::complex<float> >( );
            }

            virtual double ReadDouble( )
            {
                FillBuffer( 8 );
                uint lo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                uint hi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );

                unsigned long long tmpBuffer = ( ( unsigned long long ) hi ) << 32 | lo;
                return *( ( double* )&tmpBuffer );
            }


            virtual Nullable<double> ReadNullableDouble( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    FillBuffer( 8 );
                    uint lo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    uint hi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );
                    unsigned long long tmpBuffer = ( ( unsigned long long ) hi ) << 32 | lo;
                    auto value = *( ( double* )&tmpBuffer );
                    Nullable<double> result( value );
                    return result;
                }
                return Nullable<double>( );
            }

            virtual std::complex<double> ReadComplexDouble( )
            {
                auto real = ReadDouble( );
                auto imag = ReadDouble( );
                std::complex<double> result( real, imag );
                return result;
            }

            virtual Nullable< std::complex<double> > ReadNullableComplexDouble( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    auto real = ReadDouble( );
                    auto imag = ReadDouble( );
                    std::complex<double> value( real, imag );
                    Nullable< std::complex<double> > result( value );
                    return result;
                }
                return Nullable< std::complex<double> >( );
            }


            virtual Guid ReadGuid( )
            {
                std::array<Byte, 16> bytes;
                auto bytesRead = InStream->Read( bytes.data( ), 16 );
                if ( bytesRead < 16 )
                {
                    throw IO::EndOfStreamException( );
                }
                Guid result( bytes );
                return result;
            }

            virtual Nullable< Guid > ReadNullableGuid( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    auto value = ReadGuid( );

                    Nullable< Guid > result( value );
                    return result;
                }
                return Nullable< Guid >( );
            }


            virtual DateTime ReadDateTime( )
            {
                auto ticks = this->ReadInt64( );
                DateTime result( ticks );
                return result;
            }

            virtual Nullable< DateTime > ReadNullableDateTime( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    auto value = ReadDateTime( );

                    Nullable< DateTime > result( value );
                    return result;
                }
                return Nullable< DateTime >( );
            }


            virtual TimeSpan ReadTimeSpan( )
            {
                auto ticks = this->ReadInt64( );
                TimeSpan result( ticks );
                return result;
            }

            virtual Nullable< TimeSpan > ReadNullableTimeSpan( )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    auto value = ReadTimeSpan( );

                    Nullable< TimeSpan > result( value );
                    return result;
                }
                return Nullable< TimeSpan >( );
            }


            virtual AnsiString ReadAnsiString( )
            {
                // Length of the string in bytes, not chars 
                int stringLength = Read7BitEncodedInt( );
                if ( stringLength < 0 )
                {
                    throw new IO::IOException( "Invalid string length" );
                }

                if ( stringLength == 0 )
                {
                    return AnsiString( );
                }

                AnsiString result;
                result.SetLength( stringLength );
                auto bytesRead = InStream->Read( result.c_str( ), static_cast<size_t>( stringLength ) );
                if ( bytesRead < static_cast<long long>( stringLength ) )
                {
                    throw IO::EndOfStreamException( );
                }
                return result;
            }


            virtual WideString ReadWideString( )
            {
                auto s = ReadAnsiString( );
                auto result = WideString::From( s );
                return result;
            }

#ifdef HWIN_STRING_IS_WIDE
            String ReadString( )
            {
                return this->ReadWideString( );
            }
#else
            String ReadString( )
            {
                return this->ReadAnsiString( );
            }
#endif

            virtual long long Read( char* buffer, size_t bufferLength, size_t index, size_t count )
            {
                if ( buffer == nullptr )
                {
                    throw ArgumentNullException( "buffer" );
                }
                if ( bufferLength - index < count )
                {
                    throw new ArgumentException( "bufferLength" );
                }

                auto result = InStream->Read( &buffer[index], count );
                return result;
            }

            virtual long long Read( char* buffer, size_t index, size_t count )
            {
                if ( buffer == nullptr )
                {
                    throw ArgumentNullException( "buffer" );
                }

                auto result = InStream->Read( &buffer[index], count );
                return result;
            }


            void ReadBooleanArray( std::vector<bool>& destination )
            {
                FillBuffer( 8 );
                uint lo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                uint hi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );
                auto size = ( ( unsigned long long ) hi ) << 32 | lo;

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 1 );
                    destination.push_back( buffer_[0] != 0 );
                }

            }

            void ReadNullableBooleanArray( Nullable< std::vector<bool> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<bool> values;
                    ReadBooleanArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }

            size_t ReadSize( )
            {
                auto size = static_cast<size_t>( ReadInt32( ) );
                return size;
            }


            std::vector< bool > ReadBooleanArray( )
            {
                std::vector< bool > result;
                ReadBooleanArray( result );
                return result;
            }

            void ReadByteArray( std::vector<byte>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 1 );
                    destination.push_back( buffer_[0] != 0 );
                }
            }

            void ReadNullableByteArray( Nullable< std::vector<byte> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<byte> values;
                    ReadByteArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }

            std::vector< byte > ReadByteArray( )
            {
                std::vector< byte > result;
                ReadByteArray( result );
                return result;
            }

            void ReadSByteArray( std::vector<char>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 1 );
                    destination.push_back( buffer_[0] != 0 );
                }

            }


            void ReadNullableSByteArray( Nullable< std::vector<char> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<char> values;
                    ReadSByteArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }
            std::vector< char > ReadSByteArray( )
            {
                std::vector< char > result;
                ReadSByteArray( result );
                return result;
            }


            void ReadInt16Array( std::vector<short>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 2 );
                    destination.push_back( ( short )( buffer_[0] | buffer_[1] << 8 ) );
                }

            }

            void ReadNullableInt16Array( Nullable< std::vector<short> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<short> values;
                    ReadInt16Array( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }


            std::vector< short > ReadInt16Array( )
            {
                std::vector< short > result;
                ReadInt16Array( result );
                return result;
            }

            void ReadUInt16Array( std::vector<unsigned short>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 2 );
                    destination.push_back( ( unsigned short )( buffer_[0] | buffer_[1] << 8 ) );
                }
            }

            void ReadNullableUInt16Array( Nullable< std::vector<unsigned short> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<unsigned short> values;
                    ReadUInt16Array( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }

            std::vector< unsigned short > ReadUInt16Array( )
            {
                std::vector< unsigned short > result;
                ReadUInt16Array( result );
                return result;
            }

            void ReadInt32Array( std::vector<int>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 4 );
                    destination.push_back( ( int )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 ) );
                }
            }

            void ReadNullableInt32Array( Nullable< std::vector<int> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<int> values;
                    ReadInt32Array( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }

            std::vector< int > ReadInt32Array( )
            {
                std::vector< int > result;
                ReadInt32Array( result );
                return result;
            }


            void ReadUInt32Array( std::vector<unsigned int>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 4 );
                    destination.push_back( ( unsigned int )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 ) );
                }

            }

            void ReadNullableUInt32Array( Nullable< std::vector<unsigned int> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<unsigned int> values;
                    ReadUInt32Array( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }

            std::vector< unsigned int > ReadUInt32Array( )
            {
                std::vector< unsigned int > result;
                ReadUInt32Array( result );
                return result;
            }

            void ReadInt64Array( std::vector<long long>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 8 );
                    uint vlo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    uint vhi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );

                    destination.push_back( ( long long )( ( unsigned long long ) vhi ) << 32 | vlo );
                }
            }

            void ReadNullableInt64Array( Nullable< std::vector<long long> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<long long> values;
                    ReadInt64Array( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }

            std::vector< long long > ReadInt64Array( )
            {
                std::vector< long long > result;
                ReadInt64Array( result );
                return result;
            }



            void ReadUInt64Array( std::vector<unsigned long long>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 8 );
                    uint vlo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    uint vhi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );

                    destination.push_back( ( ( unsigned long long ) vhi ) << 32 | vlo );
                }

            }

            void ReadNullableUInt64Array( Nullable< std::vector<unsigned long long> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<unsigned long long> values;
                    ReadUInt64Array( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }

            std::vector< unsigned long long > ReadUInt64Array( )
            {
                std::vector< unsigned long long > result;
                ReadUInt64Array( result );
                return result;
            }


            void ReadSingleArray( std::vector<float>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 4 );
                    uint tmpBuffer = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    destination.push_back( *( ( float* )&tmpBuffer ) );
                }
            }

            void ReadNullableSingleArray( Nullable< std::vector<float> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<float> values;
                    ReadSingleArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }


            std::vector< float > ReadSingleArray( )
            {
                std::vector< float > result;
                ReadSingleArray( result );
                return result;
            }


            void ReadComplexSingleArray( std::vector< std::complex< float > >& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 4 );
                    uint realTmpBuffer = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );

                    FillBuffer( 4 );
                    uint imagTmpBuffer = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );

                    destination.emplace_back( *( ( float* )&realTmpBuffer ), *( ( float* )&imagTmpBuffer ) );
                }

            }

            void ReadNullableComplexSingleArray( Nullable< std::vector< std::complex< float > > >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<std::complex< float >> values;
                    ReadComplexSingleArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }


            std::vector< std::complex< float > > ReadComplexSingleArray( )
            {
                std::vector< std::complex< float > > result;
                ReadComplexSingleArray( result );
                return result;
            }

            void ReadDoubleArray( std::vector<double>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 8 );
                    uint lo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    uint hi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );

                    unsigned long long tmpBuffer = ( ( unsigned long long ) hi ) << 32 | lo;

                    destination.push_back( *( ( float* )&tmpBuffer ) );
                }
            }

            void ReadNullableDoubleArray( Nullable< std::vector<double> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<double> values;
                    ReadDoubleArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }


            std::vector< double > ReadDoubleArray( )
            {
                std::vector< double > result;
                ReadDoubleArray( result );
                return result;
            }


            void ReadComplexDoubleArray( std::vector< std::complex< double > >& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 8 );
                    uint vlo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    uint vhi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );

                    unsigned long long tmpBufferReal = ( ( unsigned long long ) vhi ) << 32 | vlo;

                    vlo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    vhi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );

                    unsigned long long tmpBufferImag = ( ( unsigned long long ) vhi ) << 32 | vlo;

                    destination.emplace_back( *( ( double* )&tmpBufferReal ), *( ( double* )&tmpBufferImag ) );
                }
            }

            void ReadNullableComplexDoubleArray( Nullable< std::vector< std::complex< double > > >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<std::complex< double >> values;
                    ReadComplexDoubleArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }


            std::vector< std::complex< double > > ReadComplexDoubleArray( )
            {
                std::vector< std::complex< double > > result;
                ReadComplexDoubleArray( result );
                return result;
            }


            void ReadDateTimeArray( std::vector<DateTime>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 8 );
                    uint vlo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    uint vhi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );

                    destination.emplace_back( ( long long )( ( unsigned long long ) vhi ) << 32 | vlo );
                }
            }


            void ReadNullableDateTimeArray( Nullable< std::vector<DateTime> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<DateTime> values;
                    ReadDateTimeArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }

            std::vector< DateTime > ReadDateTimeArray( )
            {
                std::vector< DateTime > result;
                ReadDateTimeArray( result );
                return result;
            }




            void ReadTimeSpanArray( std::vector<TimeSpan>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    FillBuffer( 8 );
                    uint vlo = ( uint )( buffer_[0] | buffer_[1] << 8 | buffer_[2] << 16 | buffer_[3] << 24 );
                    uint vhi = ( uint )( buffer_[4] | buffer_[5] << 8 | buffer_[6] << 16 | buffer_[7] << 24 );

                    destination.emplace_back( ( long long )( ( unsigned long long ) vhi ) << 32 | vlo );
                }

            }

            void ReadNullableTimeSpanArray( Nullable< std::vector<TimeSpan> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<TimeSpan> values;
                    ReadTimeSpanArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }


            std::vector< TimeSpan > ReadTimeSpanArray( )
            {
                std::vector< TimeSpan > result;
                ReadTimeSpanArray( result );
                return result;
            }


            void ReadAnsiStringArray( std::vector<AnsiString>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    int stringLength = Read7BitEncodedInt( );
                    if ( stringLength < 0 )
                    {
                        throw new IO::IOException( "Invalid string length" );
                    }

                    if ( stringLength == 0 )
                    {
                        destination.emplace_back( AnsiString( ) );
                    }
                    else
                    {
                        AnsiString result;
                        result.SetLength( stringLength );
                        auto bytesRead = InStream->Read( result.c_str( ), static_cast<size_t>( stringLength ) );
                        if ( bytesRead < static_cast<long long>( stringLength ) )
                        {
                            throw IO::EndOfStreamException( );
                        }
                        destination.push_back( result );
                    }
                }
            }

            void ReadNullableAnsiStringArray( Nullable< std::vector<AnsiString> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<AnsiString> values;
                    ReadAnsiStringArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }


            void ReadStringArray( std::vector<String>& destination )
            {
        #ifdef HWIN_STRING_IS_WIDE
                ReadWideStringArray( destination );
        #else
                ReadAnsiStringArray( destination );
        #endif
            }

            std::vector<AnsiString> ReadAnsiStringArray( )
            {
                std::vector<AnsiString> result;
                ReadAnsiStringArray( result );
                return result;
            }

            void ReadWideStringArray( std::vector<WideString>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                for ( size_t i = 0; i < size; i++ )
                {
                    int stringLength = Read7BitEncodedInt( );
                    if ( stringLength < 0 )
                    {
                        throw new IO::IOException( "Invalid string length" );
                    }

                    if ( stringLength == 0 )
                    {
                        destination.emplace_back( WideString( ) );
                    }
                    else
                    {
                        AnsiString result;
                        result.SetLength( stringLength );
                        auto bytesRead = InStream->Read( result.c_str( ), static_cast<size_t>( stringLength ) );
                        if ( bytesRead < static_cast<long long>( stringLength ) )
                        {
                            throw IO::EndOfStreamException( );
                        }
                        destination.push_back( WideString::From( result ) );
                    }
                }
            }

            void ReadNullableWideStringArray( Nullable< std::vector<WideString> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<WideString> values;
                    ReadWideStringArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }

            std::vector<WideString> ReadWideStringArray( )
            {
                std::vector<WideString> result;
                ReadWideStringArray( result );
                return result;
            }


        #ifdef HWIN_STRING_IS_WIDE
            std::vector<String> ReadStringArray( )
            {
                return this->ReadWideStringArray( );
            }
        #else
            std::vector<String> ReadStringArray( )
            {
                return this->ReadAnsiStringArray( );
            }
        #endif


            void ReadGuidArray( std::vector<Guid>& destination )
            {
                auto size = ReadSize( );

                destination.resize( 0 );
                destination.reserve( size );

                std::array<Byte, 16> bytes;
                for ( size_t i = 0; i < size; i++ )
                {
                    auto bytesRead = InStream->Read( bytes.data( ), 16 );
                    if ( bytesRead < 16 )
                    {
                        throw IO::EndOfStreamException( );
                    }
                    destination.emplace_back( bytes );
                }
            }

            void ReadNullableGuidArray( Nullable< std::vector<Guid> >& destination )
            {
                byte isNotNull = 0;
                auto bytesRead = InStream->Read( &isNotNull, 1 );
                if ( bytesRead == 0 )
                {
                    throw IO::EndOfStreamException( );
                }
                if ( isNotNull )
                {
                    std::vector<Guid> values;
                    ReadGuidArray( values );
                    destination.SetValue( values );
                }
                else
                {
                    destination.SetValue( nullptr );
                }
            }


            std::vector< Guid > ReadGuidArray( )
            {
                std::vector< Guid > result;
                ReadGuidArray( result );
                return result;
            }


        };

}
}

#pragma pack(pop)

#ifdef _MANAGED
#pragma managed(pop)
#endif

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Sea Surveillance AS
Norway Norway
Chief Architect - Sea Surveillance AS.

Specializing in integrated operations and high performance computing solutions.

I’ve been fooling around with computers since the early eighties, I’ve even done work on CP/M and MP/M.

Wrote my first “real” program on a BBC micro model B based on a series in a magazine at that time. It was fun and I got hooked on this thing called programming ...

A few Highlights:

  • High performance application server development
  • Model Driven Architecture and Code generators
  • Real-Time Distributed Solutions
  • C, C++, C#, Java, TSQL, PL/SQL, Delphi, ActionScript, Perl, Rexx
  • Microsoft SQL Server, Oracle RDBMS, IBM DB2, PostGreSQL
  • AMQP, Apache qpid, RabbitMQ, Microsoft Message Queuing, IBM WebSphereMQ, Oracle TuxidoMQ
  • Oracle WebLogic, IBM WebSphere
  • Corba, COM, DCE, WCF
  • AspenTech InfoPlus.21(IP21), OsiSoft PI


More information about what I do for a living can be found at: harlinn.com or LinkedIn

You can contact me at espen@harlinn.no

Comments and Discussions