SNAP Library 2.1, Developer Reference  2013-09-25 10:47:25
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
fl.cpp
Go to the documentation of this file.
00001 #ifdef GLib_LINUX
00002 extern "C" {
00003         #include <sys/mman.h>
00004 }
00005 
00006 #endif
00007 
00009 // Check-Sum
00010 const int TCs::MxMask=0x0FFFFFFF;
00011 
00012 TCs TCs::GetCsFromBf(char* Bf, const int& BfL){
00013   TCs Cs;
00014   for (int BfC=0; BfC<BfL; BfC++){Cs+=Bf[BfC];}
00015   return Cs;
00016 }
00017 
00019 // Stream-Base
00020 TStr TSBase::GetSNm() const {
00021   return TStr(SNm.CStr());
00022 }
00023 
00025 // Input-Stream
00026 TSIn::TSIn(const TStr& Str) : TSBase(Str.CStr()), FastMode(false){}
00027 
00028 void TSIn::LoadCs(){
00029   TCs CurCs=Cs; TCs TestCs;
00030   Cs+=GetBf(&TestCs, sizeof(TestCs));
00031   EAssertR(CurCs==TestCs, "Invalid checksum reading '"+GetSNm()+"'.");
00032 }
00033 
00034 void TSIn::Load(char*& CStr){
00035   char Ch; Load(Ch);
00036   int CStrLen=int(Ch);
00037   EAssertR(CStrLen>=0, "Error reading stream '"+GetSNm()+"'.");
00038   CStr=new char[CStrLen+1];
00039   if (CStrLen>0){Cs+=GetBf(CStr, CStrLen);}
00040   CStr[CStrLen]=TCh::NullCh;
00041 }
00042 
00043 bool TSIn::GetNextLn(TStr& LnStr){
00044   TChA LnChA;
00045   const bool IsNext=GetNextLn(LnChA);
00046   LnStr=LnChA;
00047   return IsNext;
00048 }
00049 
00050 bool TSIn::GetNextLn(TChA& LnChA){
00051   LnChA.Clr();
00052   while (!Eof()){
00053     const char Ch=GetCh();
00054     if (Ch=='\n'){return true;}
00055     if (Ch=='\r' && PeekCh()=='\n'){GetCh(); return true;}
00056     LnChA.AddCh(Ch);
00057   }
00058   return !LnChA.Empty();
00059 }
00060 
00061 const PSIn TSIn::StdIn=PSIn(new TStdIn());
00062 
00063 TStdIn::TStdIn(): TSBase("Standard input"), TSIn("Standard input") {}
00064 
00066 // Output-Stream
00067 TSOut::TSOut(const TStr& Str):
00068   TSBase(Str.CStr()), MxLnLen(-1), LnLen(0){}
00069 
00070 int TSOut::UpdateLnLen(const int& StrLen, const bool& ForceInLn){
00071   int Cs=0;
00072   if (MxLnLen!=-1){
00073     if ((!ForceInLn)&&(LnLen+StrLen>MxLnLen)){Cs+=PutLn();}
00074     LnLen+=StrLen;
00075   }
00076   return Cs;
00077 }
00078 
00079 int TSOut::PutMem(const TMem& Mem){
00080   return PutBf(Mem(), Mem.Len());
00081 }
00082 
00083 int TSOut::PutCh(const char& Ch, const int& Chs){
00084   int Cs=0;
00085   for (int ChN=0; ChN<Chs; ChN++){Cs+=PutCh(Ch);}
00086   return Cs;
00087 }
00088 
00089 int TSOut::PutBool(const bool& Bool){
00090   return PutStr(TBool::GetStr(Bool));
00091 }
00092 
00093 int TSOut::PutInt(const int& Int){
00094   return PutStr(TInt::GetStr(Int));
00095 }
00096 
00097 int TSOut::PutInt(const int& Int, const char* FmtStr){
00098   return PutStr(TInt::GetStr(Int, FmtStr));
00099 }
00100 
00101 int TSOut::PutUInt(const uint& UInt){
00102   return PutStr(TUInt::GetStr(UInt));
00103 }
00104 
00105 int TSOut::PutUInt(const uint& UInt, const char* FmtStr){
00106   return PutStr(TUInt::GetStr(UInt, FmtStr));
00107 }
00108 
00109 int TSOut::PutFlt(const double& Flt){
00110   return PutStr(TFlt::GetStr(Flt));
00111 }
00112 
00113 int TSOut::PutFlt(const double& Flt, const char* FmtStr){
00114   return PutStr(TFlt::GetStr(Flt, FmtStr));
00115 }
00116 
00117 int TSOut::PutStr(const char* CStr){
00118   int Cs=UpdateLnLen(int(strlen(CStr)));
00119   return Cs+PutBf(CStr, int(strlen(CStr)));
00120 }
00121 
00122 int TSOut::PutStr(const TChA& ChA){
00123   int Cs=UpdateLnLen(ChA.Len());
00124   return Cs+PutBf(ChA.CStr(), ChA.Len());
00125 }
00126 
00127 int TSOut::PutStr(const TStr& Str, const char* FmtStr){
00128   return PutStr(TStr::GetStr(Str, FmtStr));
00129 }
00130 
00131 int TSOut::PutStr(const TStr& Str, const bool& ForceInLn){
00132   int Cs=UpdateLnLen(Str.Len(), ForceInLn);
00133   return Cs+PutBf(Str.CStr(), Str.Len());
00134 }
00135 
00136 int TSOut::PutStrFmt(const char *FmtStr, ...){
00137   char Bf[10*1024];
00138   va_list valist;
00139   va_start(valist, FmtStr);
00140   const int RetVal=vsnprintf(Bf, 10*1024-2, FmtStr, valist);
00141   va_end(valist);
00142   return RetVal!=-1 ? PutStr(TStr(Bf)) : 0;     
00143 }
00144 
00145 int TSOut::PutStrFmtLn(const char *FmtStr, ...){
00146   char Bf[10*1024];
00147   va_list valist;
00148   va_start(valist, FmtStr);
00149   const int RetVal=vsnprintf(Bf, 10*1024-2, FmtStr, valist);
00150   va_end(valist);
00151   return RetVal!=-1 ? PutStrLn(TStr(Bf)) : PutLn();     
00152 }
00153 
00154 int TSOut::PutIndent(const int& IndentLev){
00155   return PutCh(' ', IndentLev*2);
00156 }
00157 
00158 int TSOut::PutLn(const int& Lns){
00159   LnLen=0; int Cs=0;
00160   for (int LnN=0; LnN<Lns; LnN++){Cs+=PutCh('\n');}
00161   return Cs;
00162 }
00163 
00164 int TSOut::PutDosLn(const int& Lns){
00165   LnLen=0; int Cs=0;
00166   for (int LnN=0; LnN<Lns; LnN++){Cs+=PutCh(TCh::CrCh)+PutCh(TCh::LfCh);}
00167   return Cs;
00168 }
00169 
00170 int TSOut::PutSep(const int& NextStrLen){
00171   int Cs=0;
00172   if (MxLnLen==-1){
00173     Cs+=PutCh(' ');
00174   } else {
00175     if (LnLen>0){
00176       if (LnLen+1+NextStrLen>MxLnLen){Cs+=PutLn();} else {Cs+=PutCh(' ');}
00177     }
00178   }
00179   return Cs;
00180 }
00181 
00182 int TSOut::PutSepLn(const int& Lns){
00183   int Cs=0;
00184   if (LnLen>0){Cs+=PutLn();}
00185   Cs+=PutLn(Lns);
00186   return Cs;
00187 }
00188 
00189 void TSOut::Save(const char* CStr){
00190   int CStrLen=int(strlen(CStr));
00191   EAssertR(CStrLen<=127, "Error writting stream '"+GetSNm()+"'.");
00192   Save(char(CStrLen));
00193   if (CStrLen>0){Cs+=PutBf(CStr, CStrLen);}
00194 }
00195 
00196 void TSOut::Save(TSIn& SIn, const TSize& BfL){
00197   Fail;
00198   if (BfL==0){ //J: used to be ==-1
00199     while (!SIn.Eof()){Save(SIn.GetCh());}
00200   } else {
00201     for (TSize BfC=0; BfC<BfL; BfC++){Save(SIn.GetCh());}
00202   }
00203 }
00204 
00205 TSOut& TSOut::operator<<(TSIn& SIn) {
00206   while (!SIn.Eof())
00207     operator<<((char)SIn.GetCh());
00208   return *this;
00209 }
00210 
00211 const PSOut TSOut::StdOut=PSOut(new TStdOut());
00212 
00213 TStdOut::TStdOut(): TSBase(TSStr("Standard output")), TSOut("Standard output"){}
00214 
00216 // Standard-Input
00217 int TStdIn::GetBf(const void* LBf, const TSize& LBfL){
00218   int LBfS=0;
00219   for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00220     LBfS+=(((char*)LBf)[LBfC]=GetCh());}
00221   return LBfS;
00222 }
00223 
00224 bool TStdIn::GetNextLnBf(TChA& LnChA){
00225   // not implemented
00226   FailR(TStr::Fmt("TStdIn::GetNextLnBf: not implemented").CStr());
00227   return false;
00228 }
00229 
00231 // Standard-Output
00232 int TStdOut::PutBf(const void* LBf, const TSize& LBfL){
00233   int LBfS=0;
00234   for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00235     LBfS+=PutCh(((char*)LBf)[LBfC]);}
00236   return LBfS;
00237 }
00238 
00240 // Input-File
00241 const int TFIn::MxBfL=16*1024;
00242 
00243 void TFIn::SetFPos(const int& FPos) const {
00244   EAssertR(
00245    fseek(FileId, FPos, SEEK_SET)==0,
00246    "Error seeking into file '"+GetSNm()+"'.");
00247 }
00248 
00249 int TFIn::GetFPos() const {
00250   const int FPos=(int)ftell(FileId);
00251   EAssertR(FPos!=-1, "Error seeking into file '"+GetSNm()+"'.");
00252   return FPos;
00253 }
00254 
00255 int TFIn::GetFLen() const {
00256   const int FPos=GetFPos();
00257   EAssertR(
00258    fseek(FileId, 0, SEEK_END)==0,
00259    "Error seeking into file '"+GetSNm()+"'.");
00260   const int FLen=GetFPos(); SetFPos(FPos);
00261   return FLen;
00262 }
00263 
00264 void TFIn::FillBf(){
00265   EAssertR(
00266    (BfC==BfL)&&((BfL==-1)||(BfL==MxBfL)),
00267    "Error reading file '"+GetSNm()+"'.");
00268   BfL=int(fread(Bf, 1, MxBfL, FileId));
00269   EAssertR((BfC!=0)||(BfL!=0), "Error reading file '"+GetSNm()+"'.");
00270   BfC=0;
00271 }
00272 
00273 TFIn::TFIn(const TStr& FNm):
00274   TSBase(FNm.CStr()), TSIn(FNm), FileId(NULL), Bf(NULL), BfC(0), BfL(0){
00275   EAssertR(!FNm.Empty(), "Empty file-name.");
00276   FileId=fopen(FNm.CStr(), "rb");
00277   EAssertR(FileId!=NULL, "Can not open file '"+FNm+"'.");
00278   Bf=new char[MxBfL]; BfC=BfL=-1; FillBf();
00279 }
00280 
00281 TFIn::TFIn(const TStr& FNm, bool& OpenedP):
00282   TSBase(FNm.CStr()), TSIn(FNm), FileId(NULL), Bf(NULL), BfC(0), BfL(0){
00283   EAssertR(!FNm.Empty(), "Empty file-name.");
00284   FileId=fopen(FNm.CStr(), "rb");
00285   OpenedP=(FileId!=NULL);
00286   if (OpenedP){
00287     Bf=new char[MxBfL]; BfC=BfL=-1; FillBf();}
00288 }
00289 
00290 PSIn TFIn::New(const TStr& FNm){
00291   return PSIn(new TFIn(FNm));
00292 }
00293 
00294 PSIn TFIn::New(const TStr& FNm, bool& OpenedP){
00295   return PSIn(new TFIn(FNm, OpenedP));
00296 }
00297 
00298 TFIn::~TFIn(){
00299   if (FileId!=NULL){
00300     EAssertR(fclose(FileId)==0, "Can not close file '"+GetSNm()+"'.");}
00301   if (Bf!=NULL){delete[] Bf;}
00302 }
00303 
00304 int TFIn::GetBf(const void* LBf, const TSize& LBfL){
00305   int LBfS=0;
00306   if (TSize(BfC+LBfL)>TSize(BfL)){
00307     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00308       if (BfC==BfL){FillBf();}
00309       LBfS+=((char*)LBf)[LBfC]=Bf[BfC++];}
00310   } else {
00311     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00312       LBfS+=(((char*)LBf)[LBfC]=Bf[BfC++]);}
00313   }
00314   return LBfS;
00315 }
00316 
00317 // Gets the next line to LnChA.
00318 // Returns true, if LnChA contains a valid line.
00319 // Returns false, if LnChA is empty, such as end of file was encountered.
00320 
00321 bool TFIn::GetNextLnBf(TChA& LnChA) {
00322   int Status;
00323   int BfN;        // new pointer to the end of line
00324   int BfP;        // previous pointer to the line start
00325   bool CrEnd;     // last character in previous buffer was CR
00326 
00327   LnChA.Clr();
00328 
00329   CrEnd = false;
00330   do {
00331     if (BfC >= BfL) {
00332       // reset the current pointer, FindEol() will read a new buffer
00333       BfP = 0;
00334     } else {
00335       BfP = BfC;
00336     }
00337     Status = FindEol(BfN,CrEnd);
00338     if (Status >= 0) {
00339       if (BfN-BfP > 0) {
00340         LnChA.AddBf(&Bf[BfP],BfN-BfP);
00341       }
00342       if (Status == 1) {
00343         // got a complete line
00344         return true;
00345       }
00346     }
00347     // get more data, if the line is incomplete
00348   } while (Status == 0);
00349 
00350   // eof or the last line has no newline
00351   return !LnChA.Empty();
00352 }
00353     
00354 // Sets BfN to the end of line or end of buffer. Reads more data, if needed.
00355 // Returns 1, when an end of line was found, BfN is end of line.
00356 // Returns 0, when an end of line was not found and more data is required,
00357 //    BfN is end of buffer.
00358 // Returns -1, when an end of file was found, BfN is not defined.
00359 
00360 int TFIn::FindEol(int& BfN, bool& CrEnd) {
00361   char Ch;
00362 
00363   if (BfC >= BfL) {
00364     // read more data, check for eof
00365     if (Eof()) {
00366       return -1;
00367     }
00368     if (CrEnd && Bf[BfC]=='\n') {
00369       BfC++;
00370       BfN = BfC-1;
00371       return 1;
00372     }
00373   }
00374 
00375   CrEnd = false;
00376   while (BfC < BfL) {
00377     Ch = Bf[BfC++];
00378     if (Ch=='\n') {
00379       BfN = BfC-1;
00380       return 1;
00381     }
00382     if (Ch=='\r') {
00383       if (BfC == BfL) {
00384         CrEnd = true;
00385         BfN = BfC-1;
00386         return 0;
00387       } else if (Bf[BfC]=='\n') {
00388         BfC++;
00389         BfN = BfC-2;
00390         return 1;
00391       }
00392     }
00393   }
00394   BfN = BfC;
00395 
00396   return 0;
00397 }
00398 
00400 // Output-File
00401 const TSize TFOut::MxBfL=16*1024;;
00402 
00403 void TFOut::FlushBf(){
00404   EAssertR(
00405    fwrite(Bf, 1, BfL, FileId)==BfL,
00406    "Error writting to the file '"+GetSNm()+"'.");
00407   BfL=0;
00408 }
00409 
00410 TFOut::TFOut(const TStr& FNm, const bool& Append):
00411   TSBase(FNm.CStr()), TSOut(FNm), FileId(NULL), Bf(NULL), BfL(0){
00412   if (FNm.GetUc()=="CON"){
00413     FileId=stdout;
00414   } else {
00415     if (Append){FileId=fopen(FNm.CStr(), "a+b");}
00416     else {FileId=fopen(FNm.CStr(), "w+b");}
00417     EAssertR(FileId!=NULL, "Can not open file '"+FNm+"'.");
00418     Bf=new char[MxBfL]; BfL=0;
00419   }
00420 }
00421 
00422 TFOut::TFOut(const TStr& FNm, const bool& Append, bool& OpenedP):
00423   TSBase(FNm.CStr()), TSOut(FNm), FileId(NULL), Bf(NULL), BfL(0){
00424   if (FNm.GetUc()=="CON"){
00425     FileId=stdout;
00426   } else {
00427     if (Append){FileId=fopen(FNm.CStr(), "a+b");}
00428     else {FileId=fopen(FNm.CStr(), "w+b");}
00429     OpenedP=(FileId!=NULL);
00430     if (OpenedP){
00431       Bf=new char[MxBfL]; BfL=0;}
00432   }
00433 }
00434 
00435 PSOut TFOut::New(const TStr& FNm, const bool& Append){
00436   return PSOut(new TFOut(FNm, Append));
00437 }
00438 
00439 PSOut TFOut::New(const TStr& FNm, const bool& Append, bool& OpenedP){
00440   PSOut SOut=PSOut(new TFOut(FNm, Append, OpenedP));
00441   if (OpenedP){return SOut;} else {return NULL;}
00442 }
00443 
00444 TFOut::~TFOut(){
00445   if (FileId!=NULL){FlushBf();}
00446   if (Bf!=NULL){delete[] Bf;}
00447   if (FileId!=NULL){
00448     EAssertR(fclose(FileId)==0, "Can not close file '"+GetSNm()+"'.");}
00449 }
00450 
00451 int TFOut::PutCh(const char& Ch){
00452   if (BfL==TSize(MxBfL)){FlushBf();}
00453   return Bf[BfL++]=Ch;
00454 }
00455 
00456 int TFOut::PutBf(const void* LBf, const TSize& LBfL){
00457   int LBfS=0;
00458   if (BfL+LBfL>MxBfL){
00459     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00460       LBfS+=PutCh(((char*)LBf)[LBfC]);}
00461   } else {
00462     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00463       LBfS+=(Bf[BfL++]=((char*)LBf)[LBfC]);}
00464   }
00465   return LBfS;
00466 }
00467 
00468 void TFOut::Flush(){
00469   FlushBf();
00470   EAssertR(fflush(FileId)==0, "Can not flush file '"+GetSNm()+"'.");
00471 }
00472 
00474 // Input-Output-File
00475 TFInOut::TFInOut(const TStr& FNm, const TFAccess& FAccess, const bool& CreateIfNo) :
00476  TSBase(TSStr(FNm.CStr())), FileId(NULL) {
00477   switch (FAccess){
00478     case faCreate: FileId=fopen(FNm.CStr(), "w+b"); break;
00479     case faUpdate: FileId=fopen(FNm.CStr(), "r+b"); break;
00480     case faAppend: FileId=fopen(FNm.CStr(), "r+b");
00481       if (FileId!=NULL){fseek(FileId, SEEK_END, 0);} break;
00482     case faRdOnly: FileId=fopen(FNm.CStr(), "rb"); break;
00483     default: Fail;
00484   }
00485   if ((FileId==NULL)&&(CreateIfNo)){FileId=fopen(FNm.CStr(), "w+b");}
00486   IAssert(FileId!=NULL);
00487 }
00488 
00489 PSInOut TFInOut::New(const TStr& FNm, const TFAccess& FAccess, const bool& CreateIfNo) {
00490   return PSInOut(new TFInOut(FNm, FAccess, CreateIfNo));
00491 }
00492 
00493 int TFInOut::GetSize() const {
00494   const int FPos = GetPos();
00495   IAssert(fseek(FileId, 0, SEEK_END) == 0);
00496   const int FLen = GetPos();
00497   IAssert(fseek(FileId, FPos, SEEK_SET) == 0);
00498   return FLen;
00499 }
00500 
00501 int TFInOut::PutBf(const void* LBf, const TSize& LBfL) {
00502   int LBfS = 0;
00503   for (TSize i = 0; i < LBfL; i++) {
00504     LBfS += ((char *)LBf)[i];
00505   }
00506   IAssert(fwrite(LBf, sizeof(char), LBfL, FileId) == (size_t) LBfL);
00507   return LBfS;
00508 }
00509 
00510 int TFInOut::GetBf(const void* LBf, const TSize& LBfL) {
00511   IAssert(fread((void *)LBf, sizeof(char), LBfL, FileId) == (size_t) LBfL);
00512   int LBfS = 0;
00513   for (TSize i = 0; i < LBfL; i++) {
00514     LBfS += ((char *)LBf)[i];
00515   }
00516   return LBfS;
00517 }
00518 
00519 bool TFInOut::GetNextLnBf(TChA& LnChA){
00520   // not implemented
00521   FailR(TStr::Fmt("TFInOut::GetNextLnBf: not implemented").CStr());
00522   return false;
00523 }
00524 
00525 TStr TFInOut::GetFNm() const {
00526   return GetSNm();
00527 }
00528 
00530 // Input-Memory
00531 TMIn::TMIn(const void* _Bf, const int& _BfL, const bool& TakeBf):
00532   TSBase("Input-Memory"), TSIn("Input-Memory"), Bf(NULL), BfC(0), BfL(_BfL){
00533   if (TakeBf){
00534     Bf=(char*)_Bf;
00535   } else {
00536     Bf=new char[BfL]; memmove(Bf, _Bf, BfL);
00537   }
00538 }
00539 
00540 TMIn::TMIn(TSIn& SIn):
00541   TSBase("Input-Memory"), TSIn("Input-Memory"), Bf(NULL), BfC(0), BfL(0){
00542   BfL=SIn.Len(); Bf=new char[BfL];
00543   for (int BfC=0; BfC<BfL; BfC++){Bf[BfC]=SIn.GetCh();}
00544 }
00545 
00546 TMIn::TMIn(const char* CStr):
00547   TSBase("Input-Memory"), TSIn("Input-Memory"), Bf(NULL), BfC(0), BfL(0){
00548   BfL=int(strlen(CStr)); Bf=new char[BfL+1]; strcpy(Bf, CStr);
00549 }
00550 
00551 TMIn::TMIn(const TStr& Str):
00552   TSBase("Input-Memory"), TSIn("Input-Memory"), Bf(NULL), BfC(0), BfL(0){
00553   BfL=Str.Len(); Bf=new char[BfL]; strncpy(Bf, Str.CStr(), BfL);
00554 }
00555 
00556 TMIn::TMIn(const TChA& ChA):
00557   TSBase("Input-Memory"), TSIn("Input-Memory"), Bf(NULL), BfC(0), BfL(0){
00558   BfL=ChA.Len(); Bf=new char[BfL]; strncpy(Bf, ChA.CStr(), BfL);
00559 }
00560 
00561 PSIn TMIn::New(const void* _Bf, const int& _BfL, const bool& TakeBf){
00562   return PSIn(new TMIn(_Bf, _BfL, TakeBf));
00563 }
00564 
00565 PSIn TMIn::New(const char* CStr){
00566   return PSIn(new TMIn(CStr));
00567 }
00568 
00569 PSIn TMIn::New(const TStr& Str){
00570   return PSIn(new TMIn(Str));
00571 }
00572 
00573 PSIn TMIn::New(const TChA& ChA){
00574   return PSIn(new TMIn(ChA));
00575 }
00576 
00577 char TMIn::GetCh(){
00578   EAssertR(BfC<BfL, "Reading beyond the end of stream.");
00579   return Bf[BfC++];
00580 }
00581 
00582 char TMIn::PeekCh(){
00583   EAssertR(BfC<BfL, "Reading beyond the end of stream.");
00584   return Bf[BfC];
00585 }
00586 
00587 int TMIn::GetBf(const void* LBf, const TSize& LBfL){
00588   EAssertR(TSize(BfC+LBfL)<=TSize(BfL), "Reading beyond the end of stream.");
00589   int LBfS=0;
00590   for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00591     LBfS+=(((char*)LBf)[LBfC]=Bf[BfC++]);}
00592   return LBfS;
00593 }
00594 
00595 bool TMIn::GetNextLnBf(TChA& LnChA){
00596   // not implemented
00597   FailR(TStr::Fmt("TMIn::GetNextLnBf: not implemented").CStr());
00598   return false;
00599 }
00600 
00602 // Output-Memory
00603 void TMOut::Resize(const int& ReqLen){
00604   IAssert(OwnBf&&(BfL==MxBfL || ReqLen >= 0));
00605   if (Bf==NULL){
00606     IAssert(MxBfL==0); 
00607     if (ReqLen < 0) Bf=new char[MxBfL=1024];
00608     else Bf=new char[MxBfL=ReqLen];
00609   } else {
00610     if (ReqLen < 0){ MxBfL*=2; }
00611     else if (ReqLen < MxBfL){ return; } // nothing to do 
00612     else { MxBfL=(2*MxBfL < ReqLen ? ReqLen : 2*MxBfL); }
00613     char* NewBf=new char[MxBfL];
00614     memmove(NewBf, Bf, BfL); delete[] Bf; Bf=NewBf;
00615   }
00616 }
00617 
00618 TMOut::TMOut(const int& _MxBfL):
00619   TSBase("Output-Memory"), TSOut("Output-Memory"),
00620   Bf(NULL), BfL(0), MxBfL(0), OwnBf(true){
00621   MxBfL=_MxBfL>0?_MxBfL:1024;
00622   Bf=new char[MxBfL];
00623 }
00624 
00625 TMOut::TMOut(char* _Bf, const int& _MxBfL):
00626   TSBase("Output-Memory"), TSOut("Output-Memory"),
00627   Bf(_Bf), BfL(0), MxBfL(_MxBfL), OwnBf(false){}
00628 
00629 void TMOut::AppendBf(const void* LBf, const TSize& LBfL) {
00630   Resize(Len() + (int)LBfL);
00631   memcpy(Bf + BfL, LBf, LBfL);
00632   BfL += (int)LBfL;
00633 }
00634 
00635 int TMOut::PutBf(const void* LBf, const TSize& LBfL){
00636   int LBfS=0;
00637   if (TSize(BfL+LBfL)>TSize(MxBfL)){
00638     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00639       LBfS+=PutCh(((char*)LBf)[LBfC]);}
00640   } else {
00641     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00642       LBfS+=(Bf[BfL++]=((char*)LBf)[LBfC]);}
00643   }
00644   return LBfS;
00645 }
00646 
00647 TStr TMOut::GetAsStr() const {
00648   TChA ChA(BfL);
00649   for (int BfC=0; BfC<BfL; BfC++){ChA+=Bf[BfC];}
00650   return ChA;
00651 }
00652 
00653 void TMOut::CutBf(const int& CutBfL){
00654   IAssert((0<=CutBfL)&&(CutBfL<=BfL));
00655   if (CutBfL==BfL){BfL=0;}
00656   else {memmove(Bf, Bf+CutBfL, BfL-CutBfL); BfL=BfL-CutBfL;}
00657 }
00658 
00659 PSIn TMOut::GetSIn(const bool& IsCut, const int& CutBfL){
00660   IAssert((CutBfL==-1)||((0<=CutBfL)));
00661   int SInBfL= (CutBfL==-1) ? BfL : TInt::GetMn(BfL, CutBfL);
00662   PSIn SIn;
00663   if (OwnBf&&IsCut&&(SInBfL==BfL)){
00664     SIn=PSIn(new TMIn(Bf, SInBfL, true));
00665     Bf=NULL; BfL=MxBfL=0; OwnBf=true;
00666   } else {
00667     SIn=PSIn(new TMIn(Bf, SInBfL, false));
00668     if (IsCut){CutBf(SInBfL);}
00669   }
00670   return SIn;
00671 }
00672 
00673 bool TMOut::IsCrLfLn() const {
00674   for (int BfC=0; BfC<BfL; BfC++){
00675     if ((Bf[BfC]==TCh::CrCh)&&((BfC+1<BfL)&&(Bf[BfC+1]==TCh::LfCh))){return true;}}
00676   return false;
00677 }
00678 
00679 TStr TMOut::GetCrLfLn(){
00680   IAssert(IsCrLfLn());
00681   TChA Ln;
00682   for (int BfC=0; BfC<BfL; BfC++){
00683     char Ch=Bf[BfC];
00684     if ((Ch==TCh::CrCh)&&((BfC+1<BfL)&&(Bf[BfC+1]==TCh::LfCh))){
00685       Ln+=TCh::CrCh; Ln+=TCh::LfCh; CutBf(BfC+1+1); break;
00686     } else {
00687       Ln+=Ch;
00688     }
00689   }
00690   return Ln;
00691 }
00692 
00693 bool TMOut::IsEolnLn() const {
00694   for (int BfC=0; BfC<BfL; BfC++){
00695     if ((Bf[BfC]==TCh::CrCh)||(Bf[BfC]==TCh::LfCh)){return true;}
00696   }
00697   return false;
00698 }
00699 
00700 TStr TMOut::GetEolnLn(const bool& DoAddEoln, const bool& DoCutBf){
00701   IAssert(IsEolnLn());
00702   int LnChs=0; TChA Ln;
00703   for (int BfC=0; BfC<BfL; BfC++){
00704     char Ch=Bf[BfC];
00705     if ((Ch==TCh::CrCh)||(Ch==TCh::LfCh)){
00706       LnChs++; if (DoAddEoln){Ln+=Ch;}
00707       if (BfC+1<BfL){
00708         char NextCh=Bf[BfC+1];
00709         if (((Ch==TCh::CrCh)&&(NextCh==TCh::LfCh))||
00710          ((Ch==TCh::LfCh)&&(NextCh==TCh::CrCh))){
00711           LnChs++; if (DoAddEoln){Ln+=NextCh;}
00712         }
00713       }
00714       break;
00715     } else {
00716       LnChs++; Ln+=Ch;
00717     }
00718   }
00719   if (DoCutBf){
00720     CutBf(LnChs);
00721   }
00722   return Ln;
00723 }
00724 
00725 void TMOut::MkEolnLn(){
00726   if (!IsEolnLn()){
00727     PutCh(TCh::CrCh); PutCh(TCh::LfCh);}
00728 }
00729 
00731 // Line-Returner
00732 // J: after talking to BlazF -- can be removed from GLib
00733 bool TLnRet::NextLn(TStr& LnStr) {
00734     if (SIn->Eof()) { return false; }
00735     TChA LnChA; char Ch = TCh::EofCh;
00736     while (!SIn->Eof() && ((Ch=SIn->GetCh())!='\n')) {
00737         if (Ch != '\r') { LnChA += Ch; }
00738     }
00739     LnStr = LnChA; return true;
00740 }
00741 
00743 // fseek-Constants-Definitions
00744 // because of strange Borland CBuilder behaviour in sysdefs.h
00745 #ifndef SEEK_SET
00746 #define SEEK_CUR    1
00747 #define SEEK_END    2
00748 #define SEEK_SET    0
00749 #endif
00750 
00752 // Random-File
00753 void TFRnd::RefreshFPos(){
00754   EAssertR(
00755    fseek(FileId, 0, SEEK_CUR)==0,
00756    "Error seeking into file '"+TStr(FNm)+"'.");
00757 }
00758 
00759 TFRnd::TFRnd(const TStr& _FNm, const TFAccess& FAccess,
00760  const bool& CreateIfNo, const int& _HdLen, const int& _RecLen):
00761   FileId(NULL), FNm(_FNm.CStr()),
00762   RecAct(false), HdLen(_HdLen), RecLen(_RecLen){
00763   RecAct=(HdLen>=0)&&(RecLen>0);
00764   switch (FAccess){
00765     case faCreate: FileId=fopen(FNm.CStr(), "w+b"); break;
00766     case faUpdate: FileId=fopen(FNm.CStr(), "r+b"); break;
00767     case faAppend: FileId=fopen(FNm.CStr(), "r+b");
00768       if (FileId!=NULL){fseek(FileId, SEEK_END, 0);} break;
00769     case faRdOnly: FileId=fopen(FNm.CStr(), "rb"); break;
00770     default: Fail;
00771   }
00772   if ((FileId==NULL)&&(CreateIfNo)){
00773     FileId=fopen(FNm.CStr(), "w+b");}
00774   EAssertR(FileId!=NULL, "Can not open file '"+_FNm+"'.");
00775 }
00776 
00777 TFRnd::~TFRnd(){
00778   EAssertR(fclose(FileId)==0, "Can not close file '"+TStr(FNm)+"'.");
00779 }
00780 
00781 TStr TFRnd::GetFNm() const {
00782   return FNm.CStr();
00783 }
00784 
00785 void TFRnd::SetFPos(const int& FPos){
00786   EAssertR(
00787    fseek(FileId, FPos, SEEK_SET)==0,
00788    "Error seeking into file '"+TStr(FNm)+"'.");
00789 }
00790 
00791 void TFRnd::MoveFPos(const int& DFPos){
00792   EAssertR(
00793    fseek(FileId, DFPos, SEEK_CUR)==0,
00794    "Error seeking into file '"+TStr(FNm)+"'.");
00795 }
00796 
00797 int TFRnd::GetFPos(){
00798   int FPos= (int) ftell(FileId);
00799   EAssertR(FPos!=-1, "Error seeking into file '"+TStr(FNm)+"'.");
00800   return FPos;
00801 }
00802 
00803 int TFRnd::GetFLen(){
00804   int FPos=GetFPos();
00805   EAssertR(
00806    fseek(FileId, 0, SEEK_END)==0,
00807    "Error seeking into file '"+TStr(FNm)+"'.");
00808   int FLen=GetFPos(); SetFPos(FPos); return FLen;
00809 }
00810 
00811 void TFRnd::SetRecN(const int& RecN){
00812   IAssert(RecAct);
00813   SetFPos(HdLen+RecN*RecLen);
00814 }
00815 
00816 int TFRnd::GetRecN(){
00817   IAssert(RecAct);
00818   int FPos=GetFPos()-HdLen;
00819   EAssertR(FPos%RecLen==0, "Invalid position in file'"+TStr(FNm)+"'.");
00820   return FPos/RecLen;
00821 }
00822 
00823 int TFRnd::GetRecs(){
00824   IAssert(RecAct);
00825   int FLen=GetFLen()-HdLen;
00826   EAssertR(FLen%RecLen==0, "Invalid length of file'"+TStr(FNm)+"'.");
00827   return FLen/RecLen;
00828 }
00829 
00830 void TFRnd::GetBf(void* Bf, const TSize& BfL){
00831   RefreshFPos();
00832   EAssertR(
00833    fread(Bf, 1, BfL, FileId)==BfL,
00834    "Error reading file '"+TStr(FNm)+"'.");
00835 }
00836 
00837 void TFRnd::PutBf(const void* Bf, const TSize& BfL){
00838   RefreshFPos();
00839   EAssertR(
00840    fwrite(Bf, 1, BfL, FileId)==BfL,
00841    "Error writting to the file '"+TStr(FNm)+"'.");
00842 }
00843 
00844 void TFRnd::Flush(){
00845   EAssertR(fflush(FileId)==0, "Can not flush file '"+TStr(FNm)+"'.");
00846 }
00847 
00848 void TFRnd::PutCh(const char& Ch, const int& Chs){
00849   if (Chs>0){
00850     char* CStr=new char[Chs];
00851     for (int ChN=0; ChN<Chs; ChN++){CStr[ChN]=Ch;}
00852     PutBf(CStr, Chs);
00853     delete[] CStr;
00854   }
00855 }
00856 
00857 void TFRnd::PutStr(const TStr& Str){
00858   PutBf(Str.CStr(), Str.Len()+1);
00859 }
00860 
00861 TStr TFRnd::GetStr(const int& StrLen, bool& IsOk){
00862   IsOk=false; TStr Str;
00863   if (GetFPos()+StrLen+1<=GetFLen()){
00864     char* CStr=new char[StrLen+1];
00865     GetBf(CStr, StrLen+1);
00866     if (CStr[StrLen+1-1]==TCh::NullCh){IsOk=true; Str=CStr;}
00867     delete[] CStr;
00868   }
00869   return Str;
00870 }
00871 
00872 TStr TFRnd::GetStr(const int& StrLen){
00873   TStr Str;
00874   char* CStr=new char[StrLen+1];
00875   GetBf(CStr, StrLen+1);
00876   EAssertR(CStr[StrLen+1-1]==TCh::NullCh, "Error reading file '"+TStr(FNm)+"'.");
00877   Str=CStr;
00878   delete[] CStr;
00879   return Str;
00880 }
00881 
00882 void TFRnd::PutSIn(const PSIn& SIn, TCs& Cs){
00883   int BfL=SIn->Len();
00884   char* Bf=new char[BfL];
00885   SIn->GetBf(Bf, BfL);
00886   Cs=TCs::GetCsFromBf(Bf, BfL);
00887   PutBf(Bf, BfL);
00888   delete[] Bf;
00889 }
00890 
00891 PSIn TFRnd::GetSIn(const int& BfL, TCs& Cs){
00892   char* Bf=new char[BfL];
00893   GetBf(Bf, BfL);
00894   Cs=TCs::GetCsFromBf(Bf, BfL);
00895   PSIn SIn=PSIn(new TMIn(Bf, BfL, true));
00896   return SIn;
00897 }
00898 
00899 TStr TFRnd::GetStrFromFAccess(const TFAccess& FAccess){
00900   switch (FAccess){
00901     case faCreate: return "Create";
00902     case faUpdate: return "Update";
00903     case faAppend: return "Append";
00904     case faRdOnly: return "ReadOnly";
00905     case faRestore: return "Restore";
00906     default: Fail; return TStr();
00907   }
00908 }
00909 
00910 TFAccess TFRnd::GetFAccessFromStr(const TStr& Str){
00911   TStr UcStr=Str.GetUc();
00912   if (UcStr=="CREATE"){return faCreate;}
00913   if (UcStr=="UPDATE"){return faUpdate;}
00914   if (UcStr=="APPEND"){return faAppend;}
00915   if (UcStr=="READONLY"){return faRdOnly;}
00916   if (UcStr=="RESTORE"){return faRestore;}
00917 
00918   if (UcStr=="NEW"){return faCreate;}
00919   if (UcStr=="CONT"){return faUpdate;}
00920   if (UcStr=="CONTINUE"){return faUpdate;}
00921   if (UcStr=="REST"){return faRestore;}
00922   if (UcStr=="RESTORE"){return faRestore;}
00923   return faUndef;
00924 }
00925 
00927 // Files
00928 const TStr TFile::TxtFExt=".Txt";
00929 const TStr TFile::HtmlFExt=".Html";
00930 const TStr TFile::HtmFExt=".Htm";
00931 const TStr TFile::GifFExt=".Gif";
00932 const TStr TFile::JarFExt=".Jar";
00933 
00934 bool TFile::Exists(const TStr& FNm){
00935   if (FNm.Empty()) { return false; }
00936   bool DoExists;
00937   TFIn FIn(FNm, DoExists);
00938   return DoExists;
00939 }
00940 
00941 #if defined(GLib_WIN32)
00942 
00943 void TFile::Copy(const TStr& SrcFNm, const TStr& DstFNm, 
00944  const bool& ThrowExceptP, const bool& FailIfExistsP){
00945   if (ThrowExceptP){
00946     if (CopyFile(SrcFNm.CStr(), DstFNm.CStr(), FailIfExistsP) == 0) {
00947         int ErrorCode = (int)GetLastError();
00948         TExcept::Throw(TStr::Fmt(
00949             "Error %d copying file '%s' to '%s'.", 
00950             ErrorCode, SrcFNm.CStr(), DstFNm.CStr()));
00951     }
00952   } else {
00953     CopyFile(SrcFNm.CStr(), DstFNm.CStr(), FailIfExistsP);
00954   }
00955 }
00956 
00957 #elif defined(GLib_LINUX)
00958 
00959 void TFile::Copy(const TStr& SrcFNm, const TStr& DstFNm,
00960  const bool& ThrowExceptP, const bool& FailIfExistsP){
00961         int input, output;
00962         size_t filesize;
00963         void *source, *target;
00964 
00965         if( (input = open(SrcFNm.CStr(), O_RDONLY)) == -1) {
00966                 if (ThrowExceptP) {
00967                         TExcept::Throw(TStr::Fmt(
00968                                     "Error copying file '%s' to '%s': cannot open source file for reading.",
00969                                     SrcFNm.CStr(), DstFNm.CStr()));
00970                 } else {
00971                         return;
00972                 }
00973         }
00974 
00975 
00976         if( (output = open(DstFNm.CStr(), O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1)     {
00977                 close(input);
00978 
00979                 if (ThrowExceptP) {
00980                         TExcept::Throw(TStr::Fmt(
00981                                     "Error copying file '%s' to '%s': cannot open destination file for writing.",
00982                                     SrcFNm.CStr(), DstFNm.CStr()));
00983                 } else {
00984                         return;
00985                 }
00986         }
00987 
00988 
00989         filesize = lseek(input, 0, SEEK_END);
00990         lseek(output, filesize - 1, SEEK_SET);
00991         write(output, '\0', 1);
00992 
00993         if((source = mmap(0, filesize, PROT_READ, MAP_SHARED, input, 0)) == (void *) -1) {
00994                 close(input);
00995                 close(output);
00996                 if (ThrowExceptP) {
00997                         TExcept::Throw(TStr::Fmt(
00998                                                 "Error copying file '%s' to '%s': cannot mmap input file.",
00999                                                 SrcFNm.CStr(), DstFNm.CStr()));
01000                 } else {
01001                         return;
01002                 }
01003         }
01004 
01005         if((target = mmap(0, filesize, PROT_WRITE, MAP_SHARED, output, 0)) == (void *) -1) {
01006                 munmap(source, filesize);
01007                 close(input);
01008                 close(output);
01009                 if (ThrowExceptP) {
01010                         TExcept::Throw(TStr::Fmt(
01011                                                 "Error copying file '%s' to '%s': cannot mmap output file.",
01012                                                 SrcFNm.CStr(), DstFNm.CStr()));
01013                 } else {
01014                         return;
01015                 }
01016         }
01017 
01018         memcpy(target, source, filesize);
01019 
01020         munmap(source, filesize);
01021         munmap(target, filesize);
01022 
01023         close(input);
01024         close(output);
01025 
01026 }
01027 
01028 
01029 
01030 #endif
01031 
01032 void TFile::Del(const TStr& FNm, const bool& ThrowExceptP){
01033   if (ThrowExceptP){
01034     EAssertR(
01035      remove(FNm.CStr())==0,
01036      "Error removing file '"+FNm+"'.");
01037   } else {
01038     remove(FNm.CStr());
01039   }
01040 }
01041 
01042 void TFile::DelWc(const TStr& WcStr, const bool& RecurseDirP){
01043   // collect file-names
01044   TStrV FNmV;
01045   TFFile FFile(WcStr, RecurseDirP); TStr FNm;
01046   while (FFile.Next(FNm)){
01047     FNmV.Add(FNm);}
01048   // delete files
01049   for (int FNmN=0; FNmN<FNmV.Len(); FNmN++){
01050     Del(FNmV[FNmN], false);}
01051 }
01052 
01053 void TFile::Rename(const TStr& SrcFNm, const TStr& DstFNm){
01054   EAssertR(
01055    rename(SrcFNm.CStr(), DstFNm.CStr())==0,
01056    "Error renaming file '"+SrcFNm+"' to "+DstFNm+"'.");
01057 }
01058 
01059 TStr TFile::GetUniqueFNm(const TStr& FNm){
01060   // <name>.#.txt --> <name>.<num>.txt
01061   int Cnt=1; int ch;
01062   TStr NewFNm; TStr TmpFNm=FNm;
01063   if (FNm.SearchCh('#') == -1) {
01064     for (ch = FNm.Len()-1; ch >= 0; ch--) if (FNm[ch] == '.') break;
01065     if (ch != -1) TmpFNm.InsStr(ch, ".#");
01066     else TmpFNm += ".#";
01067   }
01068   forever{
01069     NewFNm=TmpFNm;
01070     NewFNm.ChangeStr("#", TStr::Fmt("%03d", Cnt)); Cnt++;
01071     if (!TFile::Exists(NewFNm)){break;}
01072   }
01073   return NewFNm;
01074 }
01075 
01076 #ifdef GLib_WIN
01077 
01078 uint64 TFile::GetSize(const TStr& FNm) {
01079     // open 
01080     HANDLE hFile = CreateFile(
01081        FNm.CStr(),            // file to open
01082        GENERIC_READ,          // open for reading
01083        FILE_SHARE_READ | FILE_SHARE_WRITE,       // share for reading
01084        NULL,                  // default security
01085        OPEN_EXISTING,         // existing file only
01086        FILE_ATTRIBUTE_NORMAL, // normal file
01087        NULL);                 // no attr. template
01088     // check if we could open it
01089     if (hFile == INVALID_HANDLE_VALUE) {
01090         TExcept::Throw("Can not open file " + FNm + "!"); }
01091     // read file times
01092     LARGE_INTEGER lpFileSizeHigh;
01093         if (!GetFileSizeEx(hFile, &lpFileSizeHigh)) {
01094         TExcept::Throw("Can not read size of file " + FNm + "!"); }
01095     // close file
01096     CloseHandle(hFile);
01097     // convert to uint64
01098         return uint64(lpFileSizeHigh.QuadPart);
01099 }
01100 
01101 uint64 TFile::GetCreateTm(const TStr& FNm) {
01102     // open 
01103     HANDLE hFile = CreateFile(
01104        FNm.CStr(),            // file to open
01105        GENERIC_READ,          // open for reading
01106        FILE_SHARE_READ | FILE_SHARE_WRITE,       // share for reading
01107        NULL,                  // default security
01108        OPEN_EXISTING,         // existing file only
01109        FILE_ATTRIBUTE_NORMAL, // normal file
01110        NULL);                 // no attr. template
01111     // check if we could open it
01112     if (hFile == INVALID_HANDLE_VALUE) {
01113         TExcept::Throw("Can not open file " + FNm + "!"); }
01114     // read file times
01115     FILETIME lpCreationTime;
01116     if (!GetFileTime(hFile, &lpCreationTime, NULL, NULL)) {
01117         TExcept::Throw("Can not read time from file " + FNm + "!"); }
01118     // close file
01119     CloseHandle(hFile);
01120     // convert to uint64
01121     TUInt64 UInt64(uint(lpCreationTime.dwHighDateTime), 
01122         uint(lpCreationTime.dwLowDateTime));
01123     return UInt64.Val / uint64(10000);
01124 }
01125 
01126 uint64 TFile::GetLastAccessTm(const TStr& FNm) {
01127     // open 
01128     HANDLE hFile = CreateFile(
01129        FNm.CStr(),            // file to open
01130        GENERIC_READ,          // open for reading
01131        FILE_SHARE_READ | FILE_SHARE_WRITE,       // share for reading
01132        NULL,                  // default security
01133        OPEN_EXISTING,         // existing file only
01134        FILE_ATTRIBUTE_NORMAL, // normal file
01135        NULL);                 // no attr. template
01136     // check if we could open it
01137     if (hFile == INVALID_HANDLE_VALUE) {
01138         TExcept::Throw("Can not open file " + FNm + "!"); }
01139     // read file times
01140     FILETIME lpLastAccessTime;
01141     if (!GetFileTime(hFile, NULL, &lpLastAccessTime, NULL)) {
01142         TExcept::Throw("Can not read time from file " + FNm + "!"); }
01143     // close file
01144     CloseHandle(hFile);
01145     // convert to uint64
01146     TUInt64 UInt64(uint(lpLastAccessTime.dwHighDateTime), 
01147         uint(lpLastAccessTime.dwLowDateTime));
01148     return UInt64.Val / uint64(10000);
01149 }
01150 
01151 uint64 TFile::GetLastWriteTm(const TStr& FNm) {
01152     // open 
01153     HANDLE hFile = CreateFile(
01154        FNm.CStr(),            // file to open
01155        GENERIC_READ,          // open for reading
01156        FILE_SHARE_READ | FILE_SHARE_WRITE,       // share for reading
01157        NULL,                  // default security
01158        OPEN_EXISTING,         // existing file only
01159        FILE_ATTRIBUTE_NORMAL, // normal file
01160        NULL);                 // no attr. template
01161     // check if we could open it
01162     if (hFile == INVALID_HANDLE_VALUE) {
01163         TExcept::Throw("Can not open file " + FNm + "!"); }
01164     // read file times
01165     FILETIME lpLastWriteTime;
01166     if (!GetFileTime(hFile, NULL, NULL, &lpLastWriteTime)) {
01167         TExcept::Throw("Can not read time from file " + FNm + "!"); }
01168     // close file
01169     CloseHandle(hFile);
01170     // convert to uint64
01171     TUInt64 UInt64(uint(lpLastWriteTime.dwHighDateTime), 
01172         uint(lpLastWriteTime.dwLowDateTime));
01173     return UInt64.Val / uint64(10000);
01174 }
01175 
01176 #elif defined(GLib_LINUX)
01177 
01178 uint64 TFile::GetSize(const TStr& FNm) {
01179         Fail; return 0;
01180 }
01181 
01182 uint64 TFile::GetCreateTm(const TStr& FNm) {
01183         return GetLastWriteTm(FNm);
01184 }
01185 
01186 uint64 TFile::GetLastWriteTm(const TStr& FNm) {
01187         struct stat st;
01188         if (stat(FNm.CStr(), &st) != 0) {
01189                 TExcept::Throw("Cannot read tile from file " + FNm + "!");
01190         }
01191         return uint64(st.st_mtime);
01192 }
01193 
01194 
01195 #endif