SNAP Library 2.0, Developer Reference
2013-05-13 16:33:57
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
|
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