/*
 * PlikTymczasowy.h
 *
 * Autor: Pawe Gala
 */

#ifndef PLIKTYMCZASOWY_H_
#define PLIKTYMCZASOWY_H_

#include <e32base.h>    // CBase
#include <f32file.h>    // RFs, RFile

class CPlikTymczasowy : public CActive
{
    public:        // Enumeratory
        enum TStanOperacjiZapisu
        {
            EBlad = -1,
            EWykonano,
            EWTrakcie
        };
    
    public:        // Konstruktory dwufazowe
        static CPlikTymczasowy* NewL( TDes& aNazwaPliku );
        static CPlikTymczasowy* NewLC( TDes& aNazwaPliku );
        ~CPlikTymczasowy();
        
    public:
        void ZapiszDane( const TDesC8& aDane );
        TStanOperacjiZapisu Stan() const;
        TInt Blad() const;
        
    private:    // Odziedziczone z CActive
        void DoCancel();
        void RunL();
        // Przecienie metody RunError() nie jest wymagane
        // w tej klasie.
        // TInt RunError( TInt aError );
        
    private:    // Konstruktory
        // - pierwsza faza
        CPlikTymczasowy();
        // - druga faza
        void ConstructL( TDes& aNazwaPliku );
        
    private:    // Pola
        RFs iSystemPlikow;
        // Klasa RFile peni rol Dostawcy Usug Asynchronicznych.
        RFile iPlik;
        
        // Stan obiektu
        TStanOperacjiZapisu iStan;
        TInt iBlad;
};

#endif /* PLIKTYMCZASOWY_H_ */

/*
 * PlikTymczasowy.cpp
 *
 * Autor: Pawe Gala
 */

#include "PlikTymczasowy.h"

CPlikTymczasowy* CPlikTymczasowy::NewL( TDes& aNazwaPliku )
{
    CPlikTymczasowy* self = CPlikTymczasowy::NewLC( aNazwaPliku );
    CleanupStack::Pop( self );
    return self;
}

CPlikTymczasowy* CPlikTymczasowy::NewLC( TDes& aNazwaPliku )
{
    CPlikTymczasowy* self = new( ELeave ) CPlikTymczasowy();
    CleanupStack::PushL( self );
    self->ConstructL( aNazwaPliku );
    return self;
}

CPlikTymczasowy::CPlikTymczasowy() : CActive( EPriorityStandard )
{
    CActiveScheduler::Add( this );
}

CPlikTymczasowy::~CPlikTymczasowy()
{
    Cancel();
    
    iPlik.Close();
    iSystemPlikow.Close();
}

void CPlikTymczasowy::ConstructL( TDes& aNazwaPliku )
{
    User::LeaveIfError( iSystemPlikow.Connect() );
    // Jeeli klasa CPlikTymczasowy jest czci standardowej aplikacji
    // GUI, referencj do otwartej sesji do systemu plikw mona uzyska
    // w sposb podany poniej.
    // #include <coemain.h>        // CCoeEnv
    // iSystemPlikow = CCoeEnv::Static()->FsSession();
    // W takim przypadku nie moemy wywoa w  metody Close() 
    // na obiekcie iSystemPlikow w destruktorze ~CPlikTymczasowy().
    
    if( aNazwaPliku.Length() == 0 )
    {    
        // Standardowy katalog na dane uytkownika
        _LIT( KSciezka, "c:\\Data\\" );
        // Tworzymy i otwieramy plik tymczasowy o unikatowej nazwie.
        TFileName utworzonyPlik;
        User::LeaveIfError( iPlik.Temp( iSystemPlikow, 
            KSciezka,        // Katalog, w ktrym plik zostanie utworzony.
            utworzonyPlik,        // cieka + nazwa utworzonego pliku
            EFileWrite ) );    // Otwieramy plik do zapisu.
        
        if( utworzonyPlik.Length() <= aNazwaPliku.MaxLength() )
        {
            aNazwaPliku.Copy( utworzonyPlik );
        }
        else
        {
            User::Leave( KErrArgument );
        }
    }
    else
    {
        // Utwrz plik o nazwie i lokalizacji podanej w parametrze aNazwaPliku.
        // Jeeli plik istnieje, to go zastp.
        User::LeaveIfError( iPlik.Replace( iSystemPlikow, aNazwaPliku, EFileWrite ) );
    }
}

void CPlikTymczasowy::ZapiszDane( const TDesC8& aDane )
{
    Cancel();
    iBlad = KErrNone;
    
    if( aDane.Length() == 0 )
    {
        iStan = EBlad;
        iBlad = KErrArgument;
    }
    else
    {
        iPlik.Write( aDane, iStatus );
        SetActive();
        
        iStan = EWTrakcie;
    }
}

CPlikTymczasowy::TStanOperacjiZapisu CPlikTymczasowy::Stan() const
{
    return iStan;
}

TInt CPlikTymczasowy::Blad() const
{
    return iBlad;
}

void CPlikTymczasowy::DoCancel()
{
    // Klasa RFile nie oferuje metody do anulowania asynchronicznej
    // operacji zapisu.
}

void CPlikTymczasowy::RunL()
{
    iBlad = iStatus.Int();
    if( iBlad )
    {
        iStan = EBlad;
    }
    else
    {
        iStan = EWykonano;
    }
}

// ----------------
// Uycie klasy CPlikTymczasowy
// ----------------
TBuf<64> plikTymcz;
iPlikTymczasowy = CPlikTymczasowy::NewL( plikTymcz );
// Przykadowa cieka bezwzgldna do pliku tymczasowego, wygenerowanego 
// podczas tworzenia obiektu iPlikTymczasowy.
// plikTymcz = "c:\\Data\\TMP00fe7.$$$"

TBuf8<32> dane( _L8("przykadowe dane...") );
iPlikTymczasowy->ZapiszDane( dane );
