//2007.12.22 修正

//CFile.h

#ifndef __C_FILE_H__
#define __C_FILE_H__

#include <f32file.h>
#include <badesca.h>

class CFile:public CBase
{

public:
  static CFile *NewL(const TDesC &p_fileName);
  static CFile *NewLC(const TDesC &p_fileName);
  CFile(const TDesC& p_fileName);
  ~CFile();

public:
  void ConstructL(TUint p_shareMode);
  TInt FPuts(const TDesC8 &aDes);
  TInt FGets(TDes8 &aDes) const;
  TInt FSeek(TSeek aMode, TInt &aPos) const;
  TInt FSetSize(TInt aSize);
  TInt FileSize() const;
  void DostroyL();
 
public:
  static void GetDirFiles(const TDesC &path, CDesCArray& files);
  static void LogToFile(const TDesC& filename,TDesC8&  pdu);
  //static void LogToFile(const TDesC& filename,TDesC&  pdu);
  static void GetLinesFromFile(const TDesC& filename,CDesCArray&  lines);
  static void GetLinesFromFile(const TDesC& filename,CDesC8Array&  lines);
  static bool MakeCbmDir(const TDesC& aPath);
protected:
  TBuf<128> mFileName;
  RFs fs;
  RFile file;
  TInt mFileSize;
 
};

#endif //__C_FILE_H__

//CFile.cpp

#include "CFile.h"

#include <bautils.h>
#include <utf.h>

_LIT8(KCRLF, "/r/n");

CFile *CFile::NewL(const TDesC &p_fileName)
{
  CFile *self = CFile::NewLC(p_fileName);
  CleanupStack::Pop(self);
  return self;
}

CFile *CFile::NewLC(const TDesC &p_fileName)
{
  CFile *self = new(ELeave) CFile(p_fileName);
  CleanupStack::PushL(self);
  return self;
}

CFile::CFile(const TDesC &p_fileName)
{
  mFileName.Copy(p_fileName);
  mFileSize = 0;
}

CFile::~CFile()
{
   
}

void CFile::ConstructL(TUint p_shareMode)
{
  User::LeaveIfError(fs.Connect() );
  TInt err = file.Open( fs, mFileName, p_shareMode);
 
  if(err==KErrNotFound) // file does not exist - create it
    err=file.Create(fs, mFileName, p_shareMode);
 
  file.Size(mFileSize);
}

TInt CFile::FileSize() const
{
    return mFileSize;
}

TInt CFile::FPuts(const TDesC8 &aDes)
{
  return file.Write(aDes);
}

TInt CFile::FGets(TDes8 &aDes) const
{
  return file.Read(aDes);
}

TInt CFile::FSeek(TSeek aMode, TInt &aPos) const
{
  return file.Seek(aMode, aPos);
}

TInt CFile::FSetSize(TInt aSize)
{
  return file.SetSize(aSize);
}

void CFile::DostroyL()
{
  file.Close();
  fs.Close();
}

bool  CFile::MakeCbmDir(const TDesC& aPath){
    RFs fs;
    User::LeaveIfError(fs.Connect() );
 
    if( BaflUtils::FolderExists(fs,aPath)  ){
        fs.Close();
        return true;
    }
    if(KErrNone==fs.MkDirAll(aPath) ){
        fs.Close();
        return  true;
    }
   
    fs.Close();
    return false;
}

void CFile::GetDirFiles(const TDesC& path,CDesCArray&  files)
{
  RFs fs;
  User::LeaveIfError(fs.Connect() );

  if( BaflUtils::FolderExists(fs,path)  ){
    CDir* dir=NULL;
    User::LeaveIfError( fs.GetDir(path, KEntryAttNormal|KEntryAttMatchMask, ESortByName, dir) );
    TInt ii=dir->Count();
    for(TInt i=0;i<ii;i++){
      TEntry aEntry=(*dir)[i];
      TBuf<256> filePath(path);
      filePath.Append(aEntry.iName);
      files.AppendL(filePath);
    }
  }
  fs.Close();
}

void CFile::LogToFile(const TDesC& filename,TDesC8&  pdu)
{
  //_LIT(name, "C://log.txt");
  //TBuf<32> filename(name);
  RFs fs;
  RFile file;

  User::LeaveIfError(fs.Connect() );
  //CleanupClosePushL(fs); 
  //CleanupClosePushL(file); 

  TUint shareMode=EFileRead | EFileWrite ;
  TInt err= file.Open( fs, filename,shareMode ) ;

  if(err==KErrNotFound) // file does not exist - create it
    err=file.Create(fs,filename,shareMode);
  TInt pos;
  file.Seek(ESeekEnd,pos);

  if(err!=KErrNotFound)
    file.Write(pos,_L8("/r/n"));

  file.Seek(ESeekEnd,pos);
  file.Write(pos,pdu);
  //CleanupStack::PopAndDestroy(2,&fs);

  file.Close();
  fs.Close();
}

void CFile::GetLinesFromFile(const TDesC& filename,CDesCArray&  lines){
  RFs fs;
  User::LeaveIfError(fs.Connect() );
  if( BaflUtils::FileExists(fs,filename)  ){
    //open file
    RFile file;
    TUint shareMode=EFileRead | EFileWrite ;
    file.Open( fs, filename,shareMode ) ;

    TInt fileSize=0;
    file.Size(fileSize);  //取得文件大小

    CnvUtfConverter *cutf=new (ELeave) CnvUtfConverter;

    HBufC8 *bufc = HBufC8::NewL(fileSize+1);

    file.Read( (TDes8&) (bufc->Des()) ) ;

    //LogToFile(_L("c://cbm//rsadebug.txt"), bufc->Des());//

    TInt res;
    TPtrC8 iCursor(bufc->Des());
    TBuf<256>  buf16;
       
    //TBuf8<2> bufPage;
    //bufPage.Format(_L8("%02d"), res);
    //LogToFile(_L("c://cbm//rsadebug.txt"), bufPage);

    while( ( res = iCursor.FindF(KCRLF) ) >= 0 ) {
      res = iCursor.FindF(KCRLF);
      TPtrC8 result = iCursor.Left(res);
      iCursor.Set(iCursor.Right(iCursor.Length() - (res +2)));
           
      buf16.Zero();
      buf16=cutf->ConvertToUnicodeFromUtf8L(result)->Des();
           
      lines.AppendL(buf16);
    }

    if(iCursor.Size()>0) {
      buf16.Zero();
      buf16=cutf->ConvertToUnicodeFromUtf8L(iCursor)->Des();
      lines.AppendL(buf16);
    }

    delete cutf;
    delete  bufc;
    file.Close();
  }
  fs.Close();
}

void CFile::GetLinesFromFile(const TDesC& filename,CDesC8Array&  lines){
  RFs fs;
  User::LeaveIfError(fs.Connect() );
  if( BaflUtils::FileExists(fs,filename)  ){
    //open file
    RFile file;
    TUint shareMode=EFileRead | EFileWrite ;
    file.Open( fs, filename,shareMode ) ;   
    TInt fileSize=0;
    file.Size(fileSize);

    CnvUtfConverter *cutf=new (ELeave) CnvUtfConverter;

    HBufC8 *bufc = HBufC8::NewL(fileSize+1);
    file.Read( (TDes8&) (bufc->Des()) );

    //LogToFile(_L("c://cbm//rsadebug.txt"), bufc->Des());//

    TInt res;
    TPtrC8 iCursor(bufc->Des());

    while( ( res = iCursor.FindF(KCRLF) ) >= 0 ){  //有可能位置是从0开始的 如果有问题.再改成 >0
      TPtrC8 result = iCursor.Left(res);
      iCursor.Set(iCursor.Right(iCursor.Length() - (res +2)));

      lines.AppendL(result);
    }
       
    if(iCursor.Size()>0) {
      lines.AppendL(iCursor);
    }

    delete cutf;

    delete  bufc;
    file.Close();
  }
  fs.Close();
}

//file end

//CIniFile.h

#ifndef __C_INI_FILE_H__
#define __C_INI_FILE_H__

#include <e32base.h>  //CArrayPtrFlat

#include "util/CFile.h"

typedef struct tagINIElement
{
    TBuf8<40>   _Section;
    TBuf8<40>   _Key;
    TBuf8<512>  _Value;
}IniElement;

class CIniFile :public  CFile
{
public:
  static CIniFile* NewL(const TDesC &p_fileName);
  static CIniFile* NewLC(const TDesC &p_fileName);
  CIniFile(const TDesC &p_fileName);
  ~CIniFile();
 
 
  TInt OpenIni();
  TInt GetValue(const TDesC8 &p_Section, const TDesC8 &p_Key, TDes8 &p_Value );
  TInt PutValue(const TDesC8 &p_Section, const TDesC8 &p_Key, const TDesC8 &p_Value ); 
  void WriteIni();
  void CloseIni();

  void DostroyL();
private:
  CArrayPtrFlat<IniElement> *m_pIniElements;
};

#endif //__C_INI_FILE_H__

//CIniFile.cpp

#include "CIniFile.h"

CIniFile *CIniFile::NewL(const TDesC &p_fileName)
{
  CIniFile *self = CIniFile::NewLC(p_fileName);
  CleanupStack::Pop(self);
  return self;
}

CIniFile *CIniFile::NewLC(const TDesC &p_fileName)
{
  CIniFile *self = new(ELeave) CIniFile(p_fileName);
  CleanupStack::PushL(self);
  return self;
}

CIniFile::CIniFile(const TDesC &p_fileName):CFile(p_fileName)
{
  m_pIniElements = NULL;
}

void CIniFile::DostroyL()
{
   for(int i = 0; i<m_pIniElements->Count(); i++)
     delete m_pIniElements->At(i);
    
   delete m_pIniElements;
}

CIniFile::~CIniFile()
{
  DostroyL();
}

TInt CIniFile::OpenIni()
{
  ConstructL(EFileRead | EFileWrite) ;
  TInt pos=0;
  FSeek(ESeekStart,pos);
 
  HBufC8 *bufc = HBufC8::NewL(mFileSize + 3); //包含最末尾添加的/r/n
 
  FGets( (TDes8&)(bufc->Des()) );       //读出所有文件内容
  bufc->Des().Append(_L8("/r/n"));
 
  TPtrC8 iCursor(bufc->Des()); //指向文件内容的指针
 
  TInt iPos = 0;
 
  m_pIniElements = new(ELeave) CArrayPtrFlat<IniElement>(20);
 
  TBuf8<40>   szCurSection(_L8(""));
  TBuf8<40>   szSection(_L8(""));

  while( ( iPos = iCursor.FindF(_L8("/r/n")) ) >= 0 ) {
    iPos = iCursor.FindF(_L8("/r/n"));
    TPtrC8 result = iCursor.Left(iPos); //取出一行内容
   
    HBufC8 *pTmp = HBufC8::NewL(result.Length());
    pTmp->Des().Copy(result);
    pTmp->Des().Trim();

   
    if((pTmp->Des().Length() > 0) && pTmp->Des()[0] == '[') //查找section
    {
       
      pTmp->Des().Delete(0, 1);

      if( pTmp->Des()[pTmp->Des().Length() -1 ] == ']')
        pTmp->Des().Delete(pTmp->Des().Length()-1, 1);
   
      szSection.Copy(pTmp->Des());
   
      if (szCurSection != szSection)
        szCurSection = szSection;
    } else if( KErrNotFound != pTmp->Des().Find(_L8("=")) )  //key=value
    {
      if (szCurSection.Compare(_L8("")) != 0)
      {
        IniElement *element = new(ELeave) IniElement;
        element->_Section.Copy(szCurSection) ;
       
        TPtrC8 ptrKey(pTmp->Des());
        TInt iKeyPos=0;
        iKeyPos = ptrKey.FindF(_L8("="));
        TPtrC8 ptrTmpKey = ptrKey.Left(iKeyPos);
       
        element->_Key.Copy(ptrTmpKey);
        element->_Key.Trim();
       
        ptrKey.Set( ptrKey.Right(ptrKey.Length() - iKeyPos -1) );
        element->_Value.Copy(ptrKey);
        element->_Value.Trim();
       
        m_pIniElements->AppendL(element);
      }
    } else   //注释,,空行等无用数据
    {
      if (szCurSection.Compare(_L8("")) ==0 ) //没有section的注释空行..在文件开头
      {
        IniElement *element = new(ELeave) IniElement;
        element->_Section.Copy(_L8("###"));
        element->_Key.Copy(_L8("##"));
        element->_Value.Copy(pTmp->Des());
        m_pIniElements->AppendL(element);
      } else   //section中的注释空行
      {
          IniElement *element = new(ELeave) IniElement;
          element->_Section.Copy(szCurSection);
          element->_Key.Copy(_L8("##"));
        element->_Value.Copy(pTmp->Des());
        m_pIniElements->AppendL(element);
      }
    }
   
    delete pTmp;
    iCursor.Set( iCursor.Right(iCursor.Length() - (iPos +2)) );//
  }
  delete bufc;
  CloseIni();  //关闭文件句柄
  return 1;
}

TInt CIniFile::GetValue(const TDesC8 &p_Section, const TDesC8 &p_Key, TDes8 &p_Value )
{
  for(int i=0; i<m_pIniElements->Count(); i++)
  {
      if(  (m_pIniElements->At(i)->_Section.Compare( (TDesC8&)p_Section ) ==0 ) &&
          (m_pIniElements->At(i)->_Key.Compare( (TDesC8&)p_Key ) ==0 ) )
     
      {
        p_Value.Copy(m_pIniElements->At(i)->_Value);
      return 1;
      }
  }
  return 0;
}
 
 
 
 
TInt CIniFile::PutValue(const TDesC8 &p_Section, const TDesC8 &p_Key, const TDesC8 &p_Value )
{
  IniElement *element = new(ELeave) IniElement;
  element->_Section.Copy(p_Section);
  element->_Key.Copy(p_Key);
  element->_Value.Copy(p_Value);
 
 
  TInt b_KeyFind = 0;
  for(int i = 0; i<m_pIniElements->Count(); i++)
  { 
    //IniElement *tmp = m_pIniElements->At(i);
    if( (m_pIniElements->At(i)->_Section.Compare( (TDesC8&)p_Section ) ==0 ) &&
          (m_pIniElements->At(i)->_Key.Compare( (TDesC8&)p_Key ) ==0 ))
    {
      m_pIniElements->At(i)->_Value.Copy(p_Value);
      b_KeyFind = 1;
      break;
    }
  }
 
  if(0 == b_KeyFind)
  {
    TInt b_secFind = 0;
    for(int i=0; i<m_pIniElements->Count(); i++)
    {
      if( (m_pIniElements->At(i)->_Section.Compare( (TDesC8&)p_Section ) ==0) &&
            (m_pIniElements->At(i)->_Key.Compare( _L8("##")) != 0) ) 
        {
          m_pIniElements->InsertL(i+1, element);
          b_secFind  = 1;
        break;
        }
    }
   
    if(b_secFind  != 1) //如果是新增的section
      m_pIniElements->AppendL(element);
  }
//输出调试
  /*for(int i=0; i<m_pIniElements->Count(); i++)
  {
    TBuf8<512> dd;
    dd.Format(_L8("%S %S %S/r/n"), &(m_pIniElements->At(i)->_Section), &(m_pIniElements->At(i)->_Key), &(m_pIniElements->At(i)->_Value));
    CFile::LogToFile(_L("c://stock//debugini.txt"), dd);
  }
  */

 
  //将内存中的ini覆写回文件
  ConstructL(EFileRead | EFileWrite);
  TInt pos;
  FSeek(ESeekStart,pos);
  FSetSize(0);
 
  WriteIni();
 
  CloseIni();  //关闭文件句柄
  return 1;
}

void CIniFile::WriteIni()
{
  if(m_pIniElements->Count()>0)
  {
    TBuf8<40>   szCurSection(_L8(""));
   
    HBufC8 *strm = HBufC8::NewL(255);
    strm->Des().Zero();
 
    szCurSection.Copy(m_pIniElements->At(0)->_Section);
    if(szCurSection.Compare( _L8("###")) != 0)//文件开头的注释和空行
    {
      strm->Des().Format(_L8("[%S]/r/n"), &szCurSection);
      FPuts(strm->Des());
    }

    for(int i=0; i<m_pIniElements->Count(); i++)
    {
      IniElement *etmp = m_pIniElements->At(i);
      if(etmp->_Section.Compare(szCurSection) == 0) //如果查到当前块的子项
      {
        if( (etmp->_Key.Compare(_L8("##")) == 0 ) && (etmp->_Value.Compare(_L8("")) == 0 ))
          {
            FPuts( _L8("/r/n"));
          } else if( (etmp->_Key.Compare(_L8("##")) == 0 ) && (etmp->_Value.Compare(_L8("")) != 0 ))
          {
            strm->Des().Format(_L8("%S/r/n"), &(etmp->_Value));
          FPuts(strm->Des());
          } else
          {
            strm->Des().Format(_L8("%S = %S/r/n"), &(etmp->_Key), &(etmp->_Value));
          FPuts(strm->Des());
          }
      } else
      {
        szCurSection.Copy(etmp->_Section);
        if(szCurSection.Compare( _L8("###")) != 0)
        {
          strm->Des().Format(_L8("[%S]/r/n"), &szCurSection);
          FPuts(strm->Des());
        }
       
          if( (etmp->_Key.Compare(_L8("##")) == 0 ) && (etmp->_Value.Compare(_L8("")) == 0 ))
          {
            FPuts( _L8("/r/n"));
          } else if( (etmp->_Key.Compare(_L8("##")) == 0 ) && (etmp->_Value.Compare(_L8("")) != 0 ))
          {
            strm->Des().Format(_L8("%S/r/n"), &(etmp->_Value));
          FPuts(strm->Des());
          } else
          {
            strm->Des().Format(_L8("%S = %S/r/n"), &(etmp->_Key), &(etmp->_Value));
          FPuts(strm->Des());
          }
       
      }
     
    }
    delete strm;
  }

}

void CIniFile::CloseIni()
{
  CFile::DostroyL();
}