SNAP Library , Developer Reference  2013-01-07 14:03:36
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 
00225 // Standard-Output
00226 int TStdOut::PutBf(const void* LBf, const TSize& LBfL){
00227   int LBfS=0;
00228   for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00229     LBfS+=PutCh(((char*)LBf)[LBfC]);}
00230   return LBfS;
00231 }
00232 
00234 // Input-File
00235 const int TFIn::MxBfL=16*1024;
00236 
00237 void TFIn::SetFPos(const int& FPos) const {
00238   EAssertR(
00239    fseek(FileId, FPos, SEEK_SET)==0,
00240    "Error seeking into file '"+GetSNm()+"'.");
00241 }
00242 
00243 int TFIn::GetFPos() const {
00244   const int FPos=(int)ftell(FileId);
00245   EAssertR(FPos!=-1, "Error seeking into file '"+GetSNm()+"'.");
00246   return FPos;
00247 }
00248 
00249 int TFIn::GetFLen() const {
00250   const int FPos=GetFPos();
00251   EAssertR(
00252    fseek(FileId, 0, SEEK_END)==0,
00253    "Error seeking into file '"+GetSNm()+"'.");
00254   const int FLen=GetFPos(); SetFPos(FPos);
00255   return FLen;
00256 }
00257 
00258 void TFIn::FillBf(){
00259   EAssertR(
00260    (BfC==BfL)&&((BfL==-1)||(BfL==MxBfL)),
00261    "Error reading file '"+GetSNm()+"'.");
00262   BfL=int(fread(Bf, 1, MxBfL, FileId));
00263   EAssertR((BfC!=0)||(BfL!=0), "Error reading file '"+GetSNm()+"'.");
00264   BfC=0;
00265 }
00266 
00267 TFIn::TFIn(const TStr& FNm):
00268   TSBase(FNm.CStr()), TSIn(FNm), FileId(NULL), Bf(NULL), BfC(0), BfL(0){
00269   EAssertR(!FNm.Empty(), "Empty file-name.");
00270   FileId=fopen(FNm.CStr(), "rb");
00271   EAssertR(FileId!=NULL, "Can not open file '"+FNm+"'.");
00272   Bf=new char[MxBfL]; BfC=BfL=-1; FillBf();
00273 }
00274 
00275 TFIn::TFIn(const TStr& FNm, bool& OpenedP):
00276   TSBase(FNm.CStr()), TSIn(FNm), FileId(NULL), Bf(NULL), BfC(0), BfL(0){
00277   EAssertR(!FNm.Empty(), "Empty file-name.");
00278   FileId=fopen(FNm.CStr(), "rb");
00279   OpenedP=(FileId!=NULL);
00280   if (OpenedP){
00281     Bf=new char[MxBfL]; BfC=BfL=-1; FillBf();}
00282 }
00283 
00284 PSIn TFIn::New(const TStr& FNm){
00285   return PSIn(new TFIn(FNm));
00286 }
00287 
00288 PSIn TFIn::New(const TStr& FNm, bool& OpenedP){
00289   return PSIn(new TFIn(FNm, OpenedP));
00290 }
00291 
00292 TFIn::~TFIn(){
00293   if (FileId!=NULL){
00294     EAssertR(fclose(FileId)==0, "Can not close file '"+GetSNm()+"'.");}
00295   if (Bf!=NULL){delete[] Bf;}
00296 }
00297 
00298 int TFIn::GetBf(const void* LBf, const TSize& LBfL){
00299   int LBfS=0;
00300   if (TSize(BfC+LBfL)>TSize(BfL)){
00301     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00302       if (BfC==BfL){FillBf();}
00303       LBfS+=((char*)LBf)[LBfC]=Bf[BfC++];}
00304   } else {
00305     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00306       LBfS+=(((char*)LBf)[LBfC]=Bf[BfC++]);}
00307   }
00308   return LBfS;
00309 }
00310 
00312 // Output-File
00313 const TSize TFOut::MxBfL=16*1024;;
00314 
00315 void TFOut::FlushBf(){
00316   EAssertR(
00317    fwrite(Bf, 1, BfL, FileId)==BfL,
00318    "Error writting to the file '"+GetSNm()+"'.");
00319   BfL=0;
00320 }
00321 
00322 TFOut::TFOut(const TStr& FNm, const bool& Append):
00323   TSBase(FNm.CStr()), TSOut(FNm), FileId(NULL), Bf(NULL), BfL(0){
00324   if (FNm.GetUc()=="CON"){
00325     FileId=stdout;
00326   } else {
00327     if (Append){FileId=fopen(FNm.CStr(), "a+b");}
00328     else {FileId=fopen(FNm.CStr(), "w+b");}
00329     EAssertR(FileId!=NULL, "Can not open file '"+FNm+"'.");
00330     Bf=new char[MxBfL]; BfL=0;
00331   }
00332 }
00333 
00334 TFOut::TFOut(const TStr& FNm, const bool& Append, bool& OpenedP):
00335   TSBase(FNm.CStr()), TSOut(FNm), FileId(NULL), Bf(NULL), BfL(0){
00336   if (FNm.GetUc()=="CON"){
00337     FileId=stdout;
00338   } else {
00339     if (Append){FileId=fopen(FNm.CStr(), "a+b");}
00340     else {FileId=fopen(FNm.CStr(), "w+b");}
00341     OpenedP=(FileId!=NULL);
00342     if (OpenedP){
00343       Bf=new char[MxBfL]; BfL=0;}
00344   }
00345 }
00346 
00347 PSOut TFOut::New(const TStr& FNm, const bool& Append){
00348   return PSOut(new TFOut(FNm, Append));
00349 }
00350 
00351 PSOut TFOut::New(const TStr& FNm, const bool& Append, bool& OpenedP){
00352   PSOut SOut=PSOut(new TFOut(FNm, Append, OpenedP));
00353   if (OpenedP){return SOut;} else {return NULL;}
00354 }
00355 
00356 TFOut::~TFOut(){
00357   if (FileId!=NULL){FlushBf();}
00358   if (Bf!=NULL){delete[] Bf;}
00359   if (FileId!=NULL){
00360     EAssertR(fclose(FileId)==0, "Can not close file '"+GetSNm()+"'.");}
00361 }
00362 
00363 int TFOut::PutCh(const char& Ch){
00364   if (BfL==TSize(MxBfL)){FlushBf();}
00365   return Bf[BfL++]=Ch;
00366 }
00367 
00368 int TFOut::PutBf(const void* LBf, const TSize& LBfL){
00369   int LBfS=0;
00370   if (BfL+LBfL>MxBfL){
00371     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00372       LBfS+=PutCh(((char*)LBf)[LBfC]);}
00373   } else {
00374     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00375       LBfS+=(Bf[BfL++]=((char*)LBf)[LBfC]);}
00376   }
00377   return LBfS;
00378 }
00379 
00380 void TFOut::Flush(){
00381   FlushBf();
00382   EAssertR(fflush(FileId)==0, "Can not flush file '"+GetSNm()+"'.");
00383 }
00384 
00386 // Input-Output-File
00387 TFInOut::TFInOut(const TStr& FNm, const TFAccess& FAccess, const bool& CreateIfNo) :
00388  TSBase(TSStr(FNm.CStr())), FileId(NULL) {
00389   switch (FAccess){
00390     case faCreate: FileId=fopen(FNm.CStr(), "w+b"); break;
00391     case faUpdate: FileId=fopen(FNm.CStr(), "r+b"); break;
00392     case faAppend: FileId=fopen(FNm.CStr(), "r+b");
00393       if (FileId!=NULL){fseek(FileId, SEEK_END, 0);} break;
00394     case faRdOnly: FileId=fopen(FNm.CStr(), "rb"); break;
00395     default: Fail;
00396   }
00397   if ((FileId==NULL)&&(CreateIfNo)){FileId=fopen(FNm.CStr(), "w+b");}
00398   IAssert(FileId!=NULL);
00399 }
00400 
00401 PSInOut TFInOut::New(const TStr& FNm, const TFAccess& FAccess, const bool& CreateIfNo) {
00402   return PSInOut(new TFInOut(FNm, FAccess, CreateIfNo));
00403 }
00404 
00405 int TFInOut::GetSize() const {
00406   const int FPos = GetPos();
00407   IAssert(fseek(FileId, 0, SEEK_END) == 0);
00408   const int FLen = GetPos();
00409   IAssert(fseek(FileId, FPos, SEEK_SET) == 0);
00410   return FLen;
00411 }
00412 
00413 int TFInOut::PutBf(const void* LBf, const TSize& LBfL) {
00414   int LBfS = 0;
00415   for (TSize i = 0; i < LBfL; i++) {
00416     LBfS += ((char *)LBf)[i];
00417   }
00418   IAssert(fwrite(LBf, sizeof(char), LBfL, FileId) == (size_t) LBfL);
00419   return LBfS;
00420 }
00421 
00422 int TFInOut::GetBf(const void* LBf, const TSize& LBfL) {
00423   IAssert(fread((void *)LBf, sizeof(char), LBfL, FileId) == (size_t) LBfL);
00424   int LBfS = 0;
00425   for (TSize i = 0; i < LBfL; i++) {
00426     LBfS += ((char *)LBf)[i];
00427   }
00428   return LBfS;
00429 }
00430 
00431 TStr TFInOut::GetFNm() const {
00432   return GetSNm();
00433 }
00434 
00436 // Input-Memory
00437 TMIn::TMIn(const void* _Bf, const int& _BfL, const bool& TakeBf):
00438   TSBase("Input-Memory"), TSIn("Input-Memory"), Bf(NULL), BfC(0), BfL(_BfL){
00439   if (TakeBf){
00440     Bf=(char*)_Bf;
00441   } else {
00442     Bf=new char[BfL]; memmove(Bf, _Bf, BfL);
00443   }
00444 }
00445 
00446 TMIn::TMIn(TSIn& SIn):
00447   TSBase("Input-Memory"), TSIn("Input-Memory"), Bf(NULL), BfC(0), BfL(0){
00448   BfL=SIn.Len(); Bf=new char[BfL];
00449   for (int BfC=0; BfC<BfL; BfC++){Bf[BfC]=SIn.GetCh();}
00450 }
00451 
00452 TMIn::TMIn(const char* CStr):
00453   TSBase("Input-Memory"), TSIn("Input-Memory"), Bf(NULL), BfC(0), BfL(0){
00454   BfL=int(strlen(CStr)); Bf=new char[BfL+1]; strcpy(Bf, CStr);
00455 }
00456 
00457 TMIn::TMIn(const TStr& Str):
00458   TSBase("Input-Memory"), TSIn("Input-Memory"), Bf(NULL), BfC(0), BfL(0){
00459   BfL=Str.Len(); Bf=new char[BfL]; strncpy(Bf, Str.CStr(), BfL);
00460 }
00461 
00462 TMIn::TMIn(const TChA& ChA):
00463   TSBase("Input-Memory"), TSIn("Input-Memory"), Bf(NULL), BfC(0), BfL(0){
00464   BfL=ChA.Len(); Bf=new char[BfL]; strncpy(Bf, ChA.CStr(), BfL);
00465 }
00466 
00467 PSIn TMIn::New(const char* CStr){
00468   return PSIn(new TMIn(CStr));
00469 }
00470 
00471 PSIn TMIn::New(const TStr& Str){
00472   return PSIn(new TMIn(Str));
00473 }
00474 
00475 PSIn TMIn::New(const TChA& ChA){
00476   return PSIn(new TMIn(ChA));
00477 }
00478 
00479 char TMIn::GetCh(){
00480   EAssertR(BfC<BfL, "Reading beyond the end of stream.");
00481   return Bf[BfC++];
00482 }
00483 
00484 char TMIn::PeekCh(){
00485   EAssertR(BfC<BfL, "Reading beyond the end of stream.");
00486   return Bf[BfC];
00487 }
00488 
00489 int TMIn::GetBf(const void* LBf, const TSize& LBfL){
00490   EAssertR(TSize(BfC+LBfL)<=TSize(BfL), "Reading beyond the end of stream.");
00491   int LBfS=0;
00492   for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00493     LBfS+=(((char*)LBf)[LBfC]=Bf[BfC++]);}
00494   return LBfS;
00495 }
00496 
00498 // Output-Memory
00499 void TMOut::Resize(){
00500   IAssert(OwnBf&&(BfL==MxBfL));
00501   if (Bf==NULL){
00502     IAssert(MxBfL==0); Bf=new char[MxBfL=1024];
00503   } else {
00504     MxBfL*=2; char* NewBf=new char[MxBfL];
00505     memmove(NewBf, Bf, BfL); delete[] Bf; Bf=NewBf;
00506   }
00507 }
00508 
00509 TMOut::TMOut(const int& _MxBfL):
00510   TSBase("Output-Memory"), TSOut("Output-Memory"),
00511   Bf(NULL), BfL(0), MxBfL(0), OwnBf(true){
00512   MxBfL=_MxBfL>0?_MxBfL:1024;
00513   Bf=new char[MxBfL];
00514 }
00515 
00516 TMOut::TMOut(char* _Bf, const int& _MxBfL):
00517   TSBase("Output-Memory"), TSOut("Output-Memory"),
00518   Bf(_Bf), BfL(0), MxBfL(_MxBfL), OwnBf(false){}
00519 
00520 int TMOut::PutBf(const void* LBf, const TSize& LBfL){
00521   int LBfS=0;
00522   if (TSize(BfL+LBfL)>TSize(MxBfL)){
00523     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00524       LBfS+=PutCh(((char*)LBf)[LBfC]);}
00525   } else {
00526     for (TSize LBfC=0; LBfC<LBfL; LBfC++){
00527       LBfS+=(Bf[BfL++]=((char*)LBf)[LBfC]);}
00528   }
00529   return LBfS;
00530 }
00531 
00532 TStr TMOut::GetAsStr() const {
00533   TChA ChA(BfL);
00534   for (int BfC=0; BfC<BfL; BfC++){ChA+=Bf[BfC];}
00535   return ChA;
00536 }
00537 
00538 void TMOut::CutBf(const int& CutBfL){
00539   IAssert((0<=CutBfL)&&(CutBfL<=BfL));
00540   if (CutBfL==BfL){BfL=0;}
00541   else {memmove(Bf, Bf+CutBfL, BfL-CutBfL); BfL=BfL-CutBfL;}
00542 }
00543 
00544 PSIn TMOut::GetSIn(const bool& IsCut, const int& CutBfL){
00545   IAssert((CutBfL==-1)||((0<=CutBfL)));
00546   int SInBfL= (CutBfL==-1) ? BfL : TInt::GetMn(BfL, CutBfL);
00547   PSIn SIn;
00548   if (OwnBf&&IsCut&&(SInBfL==BfL)){
00549     SIn=PSIn(new TMIn(Bf, SInBfL, true));
00550     Bf=NULL; BfL=MxBfL=0; OwnBf=true;
00551   } else {
00552     SIn=PSIn(new TMIn(Bf, SInBfL, false));
00553     if (IsCut){CutBf(SInBfL);}
00554   }
00555   return SIn;
00556 }
00557 
00558 bool TMOut::IsCrLfLn() const {
00559   for (int BfC=0; BfC<BfL; BfC++){
00560     if ((Bf[BfC]==TCh::CrCh)&&((BfC+1<BfL)&&(Bf[BfC+1]==TCh::LfCh))){return true;}}
00561   return false;
00562 }
00563 
00564 TStr TMOut::GetCrLfLn(){
00565   IAssert(IsCrLfLn());
00566   TChA Ln;
00567   for (int BfC=0; BfC<BfL; BfC++){
00568     char Ch=Bf[BfC];
00569     if ((Ch==TCh::CrCh)&&((BfC+1<BfL)&&(Bf[BfC+1]==TCh::LfCh))){
00570       Ln+=TCh::CrCh; Ln+=TCh::LfCh; CutBf(BfC+1+1); break;
00571     } else {
00572       Ln+=Ch;
00573     }
00574   }
00575   return Ln;
00576 }
00577 
00578 bool TMOut::IsEolnLn() const {
00579   for (int BfC=0; BfC<BfL; BfC++){
00580     if ((Bf[BfC]==TCh::CrCh)||(Bf[BfC]==TCh::LfCh)){return true;}
00581   }
00582   return false;
00583 }
00584 
00585 TStr TMOut::GetEolnLn(const bool& DoAddEoln, const bool& DoCutBf){
00586   IAssert(IsEolnLn());
00587   int LnChs=0; TChA Ln;
00588   for (int BfC=0; BfC<BfL; BfC++){
00589     char Ch=Bf[BfC];
00590     if ((Ch==TCh::CrCh)||(Ch==TCh::LfCh)){
00591       LnChs++; if (DoAddEoln){Ln+=Ch;}
00592       if (BfC+1<BfL){
00593         char NextCh=Bf[BfC+1];
00594         if (((Ch==TCh::CrCh)&&(NextCh==TCh::LfCh))||
00595          ((Ch==TCh::LfCh)&&(NextCh==TCh::CrCh))){
00596           LnChs++; if (DoAddEoln){Ln+=NextCh;}
00597         }
00598       }
00599       break;
00600     } else {
00601       LnChs++; Ln+=Ch;
00602     }
00603   }
00604   if (DoCutBf){
00605     CutBf(LnChs);
00606   }
00607   return Ln;
00608 }
00609 
00610 void TMOut::MkEolnLn(){
00611   if (!IsEolnLn()){
00612     PutCh(TCh::CrCh); PutCh(TCh::LfCh);}
00613 }
00614 
00616 // Line-Returner
00617 // J: after talking to BlazF -- can be removed from GLib
00618 bool TLnRet::NextLn(TStr& LnStr) {
00619     if (SIn->Eof()) { return false; }
00620     TChA LnChA; char Ch = TCh::EofCh;
00621     while (!SIn->Eof() && ((Ch=SIn->GetCh())!='\n')) {
00622         if (Ch != '\r') { LnChA += Ch; }
00623     }
00624     LnStr = LnChA; return true;
00625 }
00626 
00628 // fseek-Constants-Definitions
00629 // because of strange Borland CBuilder behaviour in sysdefs.h
00630 #ifndef SEEK_SET
00631 #define SEEK_CUR    1
00632 #define SEEK_END    2
00633 #define SEEK_SET    0
00634 #endif
00635 
00637 // Random-File
00638 void TFRnd::RefreshFPos(){
00639   EAssertR(
00640    fseek(FileId, 0, SEEK_CUR)==0,
00641    "Error seeking into file '"+TStr(FNm)+"'.");
00642 }
00643 
00644 TFRnd::TFRnd(const TStr& _FNm, const TFAccess& FAccess,
00645  const bool& CreateIfNo, const int& _HdLen, const int& _RecLen):
00646   FileId(NULL), FNm(_FNm.CStr()),
00647   RecAct(false), HdLen(_HdLen), RecLen(_RecLen){
00648   RecAct=(HdLen>=0)&&(RecLen>0);
00649   switch (FAccess){
00650     case faCreate: FileId=fopen(FNm.CStr(), "w+b"); break;
00651     case faUpdate: FileId=fopen(FNm.CStr(), "r+b"); break;
00652     case faAppend: FileId=fopen(FNm.CStr(), "r+b");
00653       if (FileId!=NULL){fseek(FileId, SEEK_END, 0);} break;
00654     case faRdOnly: FileId=fopen(FNm.CStr(), "rb"); break;
00655     default: Fail;
00656   }
00657   if ((FileId==NULL)&&(CreateIfNo)){
00658     FileId=fopen(FNm.CStr(), "w+b");}
00659   EAssertR(FileId!=NULL, "Can not open file '"+_FNm+"'.");
00660 }
00661 
00662 TFRnd::~TFRnd(){
00663   EAssertR(fclose(FileId)==0, "Can not close file '"+TStr(FNm)+"'.");
00664 }
00665 
00666 TStr TFRnd::GetFNm() const {
00667   return FNm.CStr();
00668 }
00669 
00670 void TFRnd::SetFPos(const int& FPos){
00671   EAssertR(
00672    fseek(FileId, FPos, SEEK_SET)==0,
00673    "Error seeking into file '"+TStr(FNm)+"'.");
00674 }
00675 
00676 void TFRnd::MoveFPos(const int& DFPos){
00677   EAssertR(
00678    fseek(FileId, DFPos, SEEK_CUR)==0,
00679    "Error seeking into file '"+TStr(FNm)+"'.");
00680 }
00681 
00682 int TFRnd::GetFPos(){
00683   int FPos= (int) ftell(FileId);
00684   EAssertR(FPos!=-1, "Error seeking into file '"+TStr(FNm)+"'.");
00685   return FPos;
00686 }
00687 
00688 int TFRnd::GetFLen(){
00689   int FPos=GetFPos();
00690   EAssertR(
00691    fseek(FileId, 0, SEEK_END)==0,
00692    "Error seeking into file '"+TStr(FNm)+"'.");
00693   int FLen=GetFPos(); SetFPos(FPos); return FLen;
00694 }
00695 
00696 void TFRnd::SetRecN(const int& RecN){
00697   IAssert(RecAct);
00698   SetFPos(HdLen+RecN*RecLen);
00699 }
00700 
00701 int TFRnd::GetRecN(){
00702   IAssert(RecAct);
00703   int FPos=GetFPos()-HdLen;
00704   EAssertR(FPos%RecLen==0, "Invalid position in file'"+TStr(FNm)+"'.");
00705   return FPos/RecLen;
00706 }
00707 
00708 int TFRnd::GetRecs(){
00709   IAssert(RecAct);
00710   int FLen=GetFLen()-HdLen;
00711   EAssertR(FLen%RecLen==0, "Invalid length of file'"+TStr(FNm)+"'.");
00712   return FLen/RecLen;
00713 }
00714 
00715 void TFRnd::GetBf(void* Bf, const TSize& BfL){
00716   RefreshFPos();
00717   EAssertR(
00718    fread(Bf, 1, BfL, FileId)==BfL,
00719    "Error reading file '"+TStr(FNm)+"'.");
00720 }
00721 
00722 void TFRnd::PutBf(const void* Bf, const TSize& BfL){
00723   RefreshFPos();
00724   EAssertR(
00725    fwrite(Bf, 1, BfL, FileId)==BfL,
00726    "Error writting to the file '"+TStr(FNm)+"'.");
00727 }
00728 
00729 void TFRnd::Flush(){
00730   EAssertR(fflush(FileId)==0, "Can not flush file '"+TStr(FNm)+"'.");
00731 }
00732 
00733 void TFRnd::PutCh(const char& Ch, const int& Chs){
00734   if (Chs>0){
00735     char* CStr=new char[Chs];
00736     for (int ChN=0; ChN<Chs; ChN++){CStr[ChN]=Ch;}
00737     PutBf(CStr, Chs);
00738     delete[] CStr;
00739   }
00740 }
00741 
00742 void TFRnd::PutStr(const TStr& Str){
00743   PutBf(Str.CStr(), Str.Len()+1);
00744 }
00745 
00746 TStr TFRnd::GetStr(const int& StrLen, bool& IsOk){
00747   IsOk=false; TStr Str;
00748   if (GetFPos()+StrLen+1<=GetFLen()){
00749     char* CStr=new char[StrLen+1];
00750     GetBf(CStr, StrLen+1);
00751     if (CStr[StrLen+1-1]==TCh::NullCh){IsOk=true; Str=CStr;}
00752     delete[] CStr;
00753   }
00754   return Str;
00755 }
00756 
00757 TStr TFRnd::GetStr(const int& StrLen){
00758   TStr Str;
00759   char* CStr=new char[StrLen+1];
00760   GetBf(CStr, StrLen+1);
00761   EAssertR(CStr[StrLen+1-1]==TCh::NullCh, "Error reading file '"+TStr(FNm)+"'.");
00762   Str=CStr;
00763   delete[] CStr;
00764   return Str;
00765 }
00766 
00767 void TFRnd::PutSIn(const PSIn& SIn, TCs& Cs){
00768   int BfL=SIn->Len();
00769   char* Bf=new char[BfL];
00770   SIn->GetBf(Bf, BfL);
00771   Cs=TCs::GetCsFromBf(Bf, BfL);
00772   PutBf(Bf, BfL);
00773   delete[] Bf;
00774 }
00775 
00776 PSIn TFRnd::GetSIn(const int& BfL, TCs& Cs){
00777   char* Bf=new char[BfL];
00778   GetBf(Bf, BfL);
00779   Cs=TCs::GetCsFromBf(Bf, BfL);
00780   PSIn SIn=PSIn(new TMIn(Bf, BfL, true));
00781   return SIn;
00782 }
00783 
00784 TStr TFRnd::GetStrFromFAccess(const TFAccess& FAccess){
00785   switch (FAccess){
00786     case faCreate: return "Create";
00787     case faUpdate: return "Update";
00788     case faAppend: return "Append";
00789     case faRdOnly: return "ReadOnly";
00790     case faRestore: return "Restore";
00791     default: Fail; return TStr();
00792   }
00793 }
00794 
00795 TFAccess TFRnd::GetFAccessFromStr(const TStr& Str){
00796   TStr UcStr=Str.GetUc();
00797   if (UcStr=="CREATE"){return faCreate;}
00798   if (UcStr=="UPDATE"){return faUpdate;}
00799   if (UcStr=="APPEND"){return faAppend;}
00800   if (UcStr=="READONLY"){return faRdOnly;}
00801   if (UcStr=="RESTORE"){return faRestore;}
00802 
00803   if (UcStr=="NEW"){return faCreate;}
00804   if (UcStr=="CONT"){return faUpdate;}
00805   if (UcStr=="CONTINUE"){return faUpdate;}
00806   if (UcStr=="REST"){return faRestore;}
00807   if (UcStr=="RESTORE"){return faRestore;}
00808   return faUndef;
00809 }
00810 
00812 // Files
00813 const TStr TFile::TxtFExt=".Txt";
00814 const TStr TFile::HtmlFExt=".Html";
00815 const TStr TFile::HtmFExt=".Htm";
00816 const TStr TFile::GifFExt=".Gif";
00817 const TStr TFile::JarFExt=".Jar";
00818 
00819 bool TFile::Exists(const TStr& FNm){
00820   if (FNm.Empty()) { return false; }
00821   bool DoExists;
00822   TFIn FIn(FNm, DoExists);
00823   return DoExists;
00824 }
00825 
00826 #if defined(GLib_WIN32)
00827 
00828 void TFile::Copy(const TStr& SrcFNm, const TStr& DstFNm, 
00829  const bool& ThrowExceptP, const bool& FailIfExistsP){
00830   if (ThrowExceptP){
00831     if (CopyFile(SrcFNm.CStr(), DstFNm.CStr(), FailIfExistsP) == 0) {
00832         int ErrorCode = (int)GetLastError();
00833         TExcept::Throw(TStr::Fmt(
00834             "Error %d copying file '%s' to '%s'.", 
00835             ErrorCode, SrcFNm.CStr(), DstFNm.CStr()));
00836     }
00837   } else {
00838     CopyFile(SrcFNm.CStr(), DstFNm.CStr(), FailIfExistsP);
00839   }
00840 }
00841 
00842 #elif defined(GLib_LINUX)
00843 
00844 void TFile::Copy(const TStr& SrcFNm, const TStr& DstFNm,
00845  const bool& ThrowExceptP, const bool& FailIfExistsP){
00846         int input, output;
00847         size_t filesize;
00848         void *source, *target;
00849 
00850         if( (input = open(SrcFNm.CStr(), O_RDONLY)) == -1) {
00851                 if (ThrowExceptP) {
00852                         TExcept::Throw(TStr::Fmt(
00853                                     "Error copying file '%s' to '%s': cannot open source file for reading.",
00854                                     SrcFNm.CStr(), DstFNm.CStr()));
00855                 } else {
00856                         return;
00857                 }
00858         }
00859 
00860 
00861         if( (output = open(DstFNm.CStr(), O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1)     {
00862                 close(input);
00863 
00864                 if (ThrowExceptP) {
00865                         TExcept::Throw(TStr::Fmt(
00866                                     "Error copying file '%s' to '%s': cannot open destination file for writing.",
00867                                     SrcFNm.CStr(), DstFNm.CStr()));
00868                 } else {
00869                         return;
00870                 }
00871         }
00872 
00873 
00874         filesize = lseek(input, 0, SEEK_END);
00875         lseek(output, filesize - 1, SEEK_SET);
00876         write(output, '\0', 1);
00877 
00878         if((source = mmap(0, filesize, PROT_READ, MAP_SHARED, input, 0)) == (void *) -1) {
00879                 close(input);
00880                 close(output);
00881                 if (ThrowExceptP) {
00882                         TExcept::Throw(TStr::Fmt(
00883                                                 "Error copying file '%s' to '%s': cannot mmap input file.",
00884                                                 SrcFNm.CStr(), DstFNm.CStr()));
00885                 } else {
00886                         return;
00887                 }
00888         }
00889 
00890         if((target = mmap(0, filesize, PROT_WRITE, MAP_SHARED, output, 0)) == (void *) -1) {
00891                 munmap(source, filesize);
00892                 close(input);
00893                 close(output);
00894                 if (ThrowExceptP) {
00895                         TExcept::Throw(TStr::Fmt(
00896                                                 "Error copying file '%s' to '%s': cannot mmap output file.",
00897                                                 SrcFNm.CStr(), DstFNm.CStr()));
00898                 } else {
00899                         return;
00900                 }
00901         }
00902 
00903         memcpy(target, source, filesize);
00904 
00905         munmap(source, filesize);
00906         munmap(target, filesize);
00907 
00908         close(input);
00909         close(output);
00910 
00911 }
00912 
00913 
00914 
00915 #endif
00916 
00917 void TFile::Del(const TStr& FNm, const bool& ThrowExceptP){
00918   if (ThrowExceptP){
00919     EAssertR(
00920      remove(FNm.CStr())==0,
00921      "Error removing file '"+FNm+"'.");
00922   } else {
00923     remove(FNm.CStr());
00924   }
00925 }
00926 
00927 void TFile::DelWc(const TStr& WcStr, const bool& RecurseDirP){
00928   // collect file-names
00929   TStrV FNmV;
00930   TFFile FFile(WcStr, RecurseDirP); TStr FNm;
00931   while (FFile.Next(FNm)){
00932     FNmV.Add(FNm);}
00933   // delete files
00934   for (int FNmN=0; FNmN<FNmV.Len(); FNmN++){
00935     Del(FNmV[FNmN], false);}
00936 }
00937 
00938 void TFile::Rename(const TStr& SrcFNm, const TStr& DstFNm){
00939   EAssertR(
00940    rename(SrcFNm.CStr(), DstFNm.CStr())==0,
00941    "Error renaming file '"+SrcFNm+"' to "+DstFNm+"'.");
00942 }
00943 
00944 TStr TFile::GetUniqueFNm(const TStr& FNm){
00945   // <name>.#.txt --> <name>.<num>.txt
00946   int Cnt=1; int ch;
00947   TStr NewFNm; TStr TmpFNm=FNm;
00948   if (FNm.SearchCh('#') == -1) {
00949     for (ch = FNm.Len()-1; ch >= 0; ch--) if (FNm[ch] == '.') break;
00950     if (ch != -1) TmpFNm.InsStr(ch, ".#");
00951     else TmpFNm += ".#";
00952   }
00953   forever{
00954     NewFNm=TmpFNm;
00955     NewFNm.ChangeStr("#", TStr::Fmt("%03d", Cnt)); Cnt++;
00956     if (!TFile::Exists(NewFNm)){break;}
00957   }
00958   return NewFNm;
00959 }
00960 
00961 #ifdef GLib_WIN
00962 
00963 uint64 TFile::GetSize(const TStr& FNm) {
00964     // open 
00965     HANDLE hFile = CreateFile(
00966        FNm.CStr(),            // file to open
00967        GENERIC_READ,          // open for reading
00968        FILE_SHARE_READ | FILE_SHARE_WRITE,       // share for reading
00969        NULL,                  // default security
00970        OPEN_EXISTING,         // existing file only
00971        FILE_ATTRIBUTE_NORMAL, // normal file
00972        NULL);                 // no attr. template
00973     // check if we could open it
00974     if (hFile == INVALID_HANDLE_VALUE) {
00975         TExcept::Throw("Can not open file " + FNm + "!"); }
00976     // read file times
00977     LARGE_INTEGER lpFileSizeHigh;
00978         if (!GetFileSizeEx(hFile, &lpFileSizeHigh)) {
00979         TExcept::Throw("Can not read size of file " + FNm + "!"); }
00980     // close file
00981     CloseHandle(hFile);
00982     // convert to uint64
00983         return uint64(lpFileSizeHigh.QuadPart);
00984 }
00985 
00986 uint64 TFile::GetCreateTm(const TStr& FNm) {
00987     // open 
00988     HANDLE hFile = CreateFile(
00989        FNm.CStr(),            // file to open
00990        GENERIC_READ,          // open for reading
00991        FILE_SHARE_READ | FILE_SHARE_WRITE,       // share for reading
00992        NULL,                  // default security
00993        OPEN_EXISTING,         // existing file only
00994        FILE_ATTRIBUTE_NORMAL, // normal file
00995        NULL);                 // no attr. template
00996     // check if we could open it
00997     if (hFile == INVALID_HANDLE_VALUE) {
00998         TExcept::Throw("Can not open file " + FNm + "!"); }
00999     // read file times
01000     FILETIME lpCreationTime;
01001     if (!GetFileTime(hFile, &lpCreationTime, NULL, NULL)) {
01002         TExcept::Throw("Can not read time from file " + FNm + "!"); }
01003     // close file
01004     CloseHandle(hFile);
01005     // convert to uint64
01006     TUInt64 UInt64(uint(lpCreationTime.dwHighDateTime), 
01007         uint(lpCreationTime.dwLowDateTime));
01008     return UInt64.Val / uint64(10000);
01009 }
01010 
01011 uint64 TFile::GetLastAccessTm(const TStr& FNm) {
01012     // open 
01013     HANDLE hFile = CreateFile(
01014        FNm.CStr(),            // file to open
01015        GENERIC_READ,          // open for reading
01016        FILE_SHARE_READ | FILE_SHARE_WRITE,       // share for reading
01017        NULL,                  // default security
01018        OPEN_EXISTING,         // existing file only
01019        FILE_ATTRIBUTE_NORMAL, // normal file
01020        NULL);                 // no attr. template
01021     // check if we could open it
01022     if (hFile == INVALID_HANDLE_VALUE) {
01023         TExcept::Throw("Can not open file " + FNm + "!"); }
01024     // read file times
01025     FILETIME lpLastAccessTime;
01026     if (!GetFileTime(hFile, NULL, &lpLastAccessTime, NULL)) {
01027         TExcept::Throw("Can not read time from file " + FNm + "!"); }
01028     // close file
01029     CloseHandle(hFile);
01030     // convert to uint64
01031     TUInt64 UInt64(uint(lpLastAccessTime.dwHighDateTime), 
01032         uint(lpLastAccessTime.dwLowDateTime));
01033     return UInt64.Val / uint64(10000);
01034 }
01035 
01036 uint64 TFile::GetLastWriteTm(const TStr& FNm) {
01037     // open 
01038     HANDLE hFile = CreateFile(
01039        FNm.CStr(),            // file to open
01040        GENERIC_READ,          // open for reading
01041        FILE_SHARE_READ | FILE_SHARE_WRITE,       // share for reading
01042        NULL,                  // default security
01043        OPEN_EXISTING,         // existing file only
01044        FILE_ATTRIBUTE_NORMAL, // normal file
01045        NULL);                 // no attr. template
01046     // check if we could open it
01047     if (hFile == INVALID_HANDLE_VALUE) {
01048         TExcept::Throw("Can not open file " + FNm + "!"); }
01049     // read file times
01050     FILETIME lpLastWriteTime;
01051     if (!GetFileTime(hFile, NULL, NULL, &lpLastWriteTime)) {
01052         TExcept::Throw("Can not read time from file " + FNm + "!"); }
01053     // close file
01054     CloseHandle(hFile);
01055     // convert to uint64
01056     TUInt64 UInt64(uint(lpLastWriteTime.dwHighDateTime), 
01057         uint(lpLastWriteTime.dwLowDateTime));
01058     return UInt64.Val / uint64(10000);
01059 }
01060 
01061 #elif defined(GLib_LINUX)
01062 
01063 uint64 TFile::GetSize(const TStr& FNm) {
01064         Fail; return 0;
01065 }
01066 
01067 uint64 TFile::GetCreateTm(const TStr& FNm) {
01068         return GetLastWriteTm(FNm);
01069 }
01070 
01071 uint64 TFile::GetLastWriteTm(const TStr& FNm) {
01072         struct stat st;
01073         if (stat(FNm.CStr(), &st) != 0) {
01074                 TExcept::Throw("Cannot read tile from file " + FNm + "!");
01075         }
01076         return uint64(st.st_mtime);
01077 }
01078 
01079 
01080 #endif