#include <s32mem.h>        // RDesWriteStream / RDesReadStream

class CSamochod : public CBase
{
    public:        // Konstruktory dwufazowe i destruktor
        static CSamochod* NewL();
        static CSamochod* NewLC();
        
        virtual ~CSamochod();
    
    public:        // Metody publiczne
    
        TPtrC Marka() const { return *iMarka; }
        TPtrC Model() const { return *iModel; }
        TUint RokProdukcji() const { return iRokProdukcji; }
        TUint Przebieg() const { return iPrzebieg; }
        
        void UstawMarkeL( const TDesC& aMarka );
        void UstawModelL( const TDesC& aModel );
        void UstawRokProdukcji( TUint aRokProdukcji ){ iRokProdukcji = aRokProdukcji; }
        void UstawPrzebieg( TUint aPrzebieg ) { iPrzebieg = aPrzebieg; }
        
    public:        // Eksternalizacja/Internalizacja
        // Metody odpowiedzialne za eksternalizacj oraz internalizacj
        // obiektw zawsze posiadaj deklaracje w nastpujcej postaci:
        void ExternalizeL( RWriteStream& aStream ) const;
        void InternalizeL( RReadStream& aStream );
    
    private:    // Konstruktory
        CSamochod() {}
        void ConstructL();
        
    private:    // Pola
        HBufC* iMarka;
        HBufC* iModel;
        TUint iRokProdukcji;
        TUint iPrzebieg;
};

CSamochod* CSamochod::NewL()
{
    CSamochod* self = CSamochod::NewLC();
    CleanupStack::Pop( self );
    return self;
}

CSamochod* CSamochod::NewLC()
{
    CSamochod* self = new( ELeave ) CSamochod();
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
}

CSamochod::~CSamochod()
{
    delete iMarka;
    delete iModel;
}

void CSamochod::ConstructL()
{
    iMarka = KNullDesC().AllocL();
    iModel = KNullDesC().AllocL();
}

void CSamochod::UstawMarkeL( const TDesC& aMarka )
{
    delete iMarka;
    iMarka = NULL;
    iMarka = aMarka.AllocL();
}

void CSamochod::UstawModelL( const TDesC& aModel )
{
    delete iModel;
    iModel = NULL;
    iModel = aModel.AllocL();
}

void CSamochod::ExternalizeL( RWriteStream& aStream ) const
{
    // Zapisujemy obiekt do strumienia w nastpujcej formie:
    // -----------------------------------------------------------------------
    // |iMarka->Length()|iMarka|iModel->Length|iModel|iRokProdukcji|iPrzebieg|
    // -----------------------------------------------------------------------
    
    aStream.WriteInt32L( iMarka->Length() );
    aStream.WriteL( *iMarka );
    aStream.WriteInt32L( iModel->Length() );
    aStream.WriteL( *iModel );
    aStream.WriteUint32L( iRokProdukcji );
    aStream.WriteUint32L( iPrzebieg );
} 

void CSamochod::InternalizeL( RReadStream& aStream )
{
    delete iMarka;
    iMarka = iMarka;
    delete iModel;
    iModel = NULL;

    TInt dlugosc = aStream.ReadInt32L();
    iMarka = HBufC::NewL( dlugosc );
    TPtr markaWsk = iMarka->Des();
    aStream.ReadL( markaWsk, dlugosc );
    
    dlugosc = aStream.ReadInt32L();
    iModel = HBufC::NewL( dlugosc );
    TPtr modelWsk = iModel->Des();
    aStream.ReadL( modelWsk, dlugosc );
    
    iRokProdukcji = aStream.ReadUint32L();
    iPrzebieg = aStream.ReadUint32L();
}

// -------------------------

CSamochod* s = CSamochod::NewLC();
s->UstawMarkeL( _L("BMW") );
s->UstawModelL( _L("320d") );
s->UstawRokProdukcji( 2002 );
s->UstawPrzebieg( 120000 );

const TInt KMaksRozmiarObiektu = 256;    // bajtw
TBuf8< KMaksRozmiarObiektu > desk;

RDesWriteStream strumienZap( desk );
strumienZap.PushL();
strumienZap << *s;
strumienZap.CommitL();
CleanupStack::PopAndDestroy( &strumienZap );
// "desk" zawiera zdeskryptoryzowany obiekt "s".
// ...
CSamochod* s2 = CSamochod::NewLC();
RDesReadStream strumienCzyt( desk );
strumienCzyt.PushL();
strumienCzyt >> *s2;
CleanupStack::PopAndDestroy( &strumienCzyt );
// s2.Marka() = "BMW"
// s2.Model() = "320d"
// s2.RokProdukcji() = 2002
// s2.Przebieg() = 120000

CleanupStack::PopAndDestroy( s2 );
CleanupStack::PopAndDestroy( s );
