SNAP Library , Developer Reference
2013-01-07 14:03:36
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
|
00001 00002 // Random 00003 const int TRnd::RndSeed=0; 00004 const int TRnd::a=16807; 00005 const int TRnd::m=2147483647; 00006 const int TRnd::q=127773; // m DIV a 00007 const int TRnd::r=2836; // m MOD a 00008 00009 void TRnd::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 00010 XLoadHd(Nm); 00011 Seed=TXmlObjSer::GetIntArg(XmlTok, "Seed"); 00012 } 00013 00014 void TRnd::SaveXml(TSOut& SOut, const TStr& Nm) const { 00015 XSaveBETagArg(Nm, "Seed", TInt::GetStr(Seed)); 00016 } 00017 00018 void TRnd::PutSeed(const int& _Seed){ 00019 Assert(_Seed>=0); 00020 if (_Seed==0){ 00021 //Seed=int(time(NULL)); 00022 Seed=abs(int(TSysTm::GetPerfTimerTicks())); 00023 } else { 00024 Seed=_Seed; 00025 //Seed=abs(_Seed*100000)+1; 00026 } 00027 } 00028 00029 void TRnd::Move(const int& Steps){ 00030 for (int StepN=0; StepN<Steps; StepN++){GetNextSeed();} 00031 } 00032 00033 bool TRnd::Check(){ 00034 int PSeed=Seed; Seed=1; 00035 for (int SeedN=0; SeedN<10000; SeedN++){GetNextSeed();} 00036 bool Ok=Seed==1043618065; Seed=PSeed; return Ok; 00037 } 00038 00039 int TRnd::GetUniDevInt(const int& Range){ 00040 int Seed=GetNextSeed(); 00041 if (Range==0){return Seed;} 00042 else {return Seed%Range;} 00043 } 00044 00045 uint TRnd::GetUniDevUInt(const uint& Range){ 00046 uint Seed=uint(GetNextSeed()%0x10000)*0x10000+uint(GetNextSeed()%0x10000); 00047 if (Range==0){return Seed;} 00048 else {return Seed%Range;} 00049 } 00050 00051 double TRnd::GetNrmDev(){ 00052 double v1, v2, rsq; 00053 do { 00054 v1=2.0*GetUniDev()-1.0; // pick two uniform numbers in the square 00055 v2=2.0*GetUniDev()-1.0; // extending from -1 to +1 in each direction 00056 rsq=v1*v1+v2*v2; // see if they are in the unit cicrcle 00057 } while ((rsq>=1.0)||(rsq==0.0)); // and if they are not, try again 00058 double fac=sqrt(-2.0*log(rsq)/rsq); // Box-Muller transformation 00059 return v1*fac; 00060 // return v2*fac; // second deviate 00061 } 00062 00063 double TRnd::GetNrmDev( 00064 const double& Mean, const double& SDev, const double& Mn, const double& Mx){ 00065 double Val=Mean+GetNrmDev()*SDev; 00066 if (Val<Mn){Val=Mn;} 00067 if (Val>Mx){Val=Mx;} 00068 return Val; 00069 } 00070 00071 double TRnd::GetExpDev(){ 00072 double UniDev; 00073 do { 00074 UniDev=GetUniDev(); 00075 } while (UniDev==0.0); 00076 return -log(UniDev); 00077 } 00078 00079 double TRnd::GetExpDev(const double& Lambda) { 00080 return GetExpDev()/Lambda; 00081 } 00082 00083 double TRnd::GetGammaDev(const int& Order){ 00084 int j; 00085 double am,e,s,v1,v2,x,y; 00086 if (Order<1){Fail;} 00087 if (Order<6) { 00088 x=1.0; 00089 for (j=1;j<=Order;j++) x *=GetUniDev(); 00090 x = -log(x); 00091 } else { 00092 do { 00093 do { 00094 do { 00095 v1=2.0*GetUniDev()-1.0; 00096 v2=2.0*GetUniDev()-1.0; 00097 } while (v1*v1+v2*v2 > 1.0); 00098 y=v2/v1; 00099 am=Order-1; 00100 s=sqrt(2.0*am+1.0); 00101 x=s*y+am; 00102 } while (x <= 0.0); 00103 e=(1.0+y*y)*exp(am*log(x/am)-s*y); 00104 } while (GetUniDev()>e); 00105 } 00106 return x; 00107 } 00108 00109 double TRnd::GetPoissonDev(const double& Mean){ 00110 static double sq,alxm,g,oldm=(-1.0); 00111 double em,t,y; 00112 if (Mean < 12.0) { 00113 if (Mean != oldm) { 00114 oldm=Mean; 00115 g=exp(-Mean); 00116 } 00117 em = -1; 00118 t=1.0; 00119 do { 00120 ++em; 00121 t *= GetUniDev(); 00122 } while (t>g); 00123 } else { 00124 if (Mean != oldm) { 00125 oldm=Mean; 00126 sq=sqrt(2.0*Mean); 00127 alxm=log(Mean); 00128 g=Mean*alxm-TSpecFunc::LnGamma(Mean+1.0); 00129 } 00130 do { 00131 do { 00132 y=tan(TMath::Pi*GetUniDev()); 00133 em=sq*y+Mean; 00134 } while (em < 0.0); 00135 em=floor(em); 00136 t=0.9*(1.0+y*y)*exp(em*alxm-TSpecFunc::LnGamma(em+1.0)-g); 00137 } while (GetUniDev()>t); 00138 } 00139 return em; 00140 } 00141 00142 double TRnd::GetBinomialDev(const double& Prb, const int& Trials){ 00143 int j; 00144 static int nold=(-1); 00145 double am,em,g,angle,p,bnl,sq,t,y; 00146 static double pold=(-1.0),pc,plog,pclog,en,oldg; 00147 00148 p=(Prb <= 0.5 ? Prb : 1.0-Prb); 00149 am=Trials*p; 00150 if (Trials < 25) { 00151 bnl=0.0; 00152 for (j=1;j<=Trials;j++) 00153 if (GetUniDev() < p) ++bnl; 00154 } else if (am < 1.0) { 00155 g=exp(-am); 00156 t=1.0; 00157 for (j=0;j<=Trials;j++) { 00158 t *= GetUniDev(); 00159 if (t < g) break; 00160 } 00161 bnl=(j <= Trials ? j : Trials); 00162 } else { 00163 if (Trials != nold) { 00164 en=Trials; 00165 oldg=TSpecFunc::LnGamma(en+1.0); 00166 nold=Trials; 00167 } if (p != pold) { 00168 pc=1.0-p; 00169 plog=log(p); 00170 pclog=log(pc); 00171 pold=p; 00172 } 00173 sq=sqrt(2.0*am*pc); 00174 do { 00175 do { 00176 angle=TMath::Pi*GetUniDev(); 00177 y=tan(angle); 00178 em=sq*y+am; 00179 } while (em < 0.0 || em >= (en+1.0)); 00180 em=floor(em); 00181 t=1.2*sq*(1.0+y*y)*exp(oldg-(em+1.0) 00182 -TSpecFunc::LnGamma(en-em+1.0)+em*plog+(en-em)*pclog); 00183 } while (GetUniDev() > t); 00184 bnl=em; 00185 } 00186 if (p != Prb) bnl=Trials-bnl; 00187 return bnl; 00188 } 00189 00190 // sample points from d-dimensional unit sphere 00191 /*void TRnd::GetSphereDev(const int& Dim, TFltV& ValV) { 00192 if (ValV.Len() != Dim) { ValV.Gen(Dim); } 00193 double Length = 0.0; 00194 for (int i = 0; i < Dim; i++) { 00195 ValV[i] = GetNrmDev(); 00196 Length += TMath::Sqr(ValV[i]); } 00197 Length = 1.0 / sqrt(Length); 00198 for (int i = 0; i < Dim; i++) { 00199 ValV[i] *= Length; 00200 } 00201 }*/ 00202 00203 TRnd TRnd::LoadTxt(TILx& Lx){ 00204 return TRnd(Lx.GetInt()); 00205 } 00206 00207 void TRnd::SaveTxt(TOLx& Lx) const { 00208 Lx.PutInt(Seed); 00209 } 00210 00212 // Memory 00213 void TMem::Resize(const int& _MxBfL){ 00214 if (_MxBfL<=MxBfL){return;} 00215 else {if (MxBfL*2<_MxBfL){MxBfL=_MxBfL;} else {MxBfL*=2;}} 00216 char* NewBf=new char[MxBfL]; IAssert(NewBf!=NULL); 00217 if (BfL>0){memcpy(NewBf, Bf, BfL);} 00218 if (Bf!=NULL){delete[] Bf;} 00219 Bf=NewBf; 00220 } 00221 00222 TMem::TMem(const TStr& Str): 00223 MxBfL(Str.Len()), BfL(MxBfL), Bf(NULL){ 00224 if (MxBfL>0){ 00225 Bf=new char[MxBfL]; 00226 if (BfL>0){memcpy(Bf, Str.CStr(), BfL);} 00227 } 00228 } 00229 00230 void TMem::SaveXml(TSOut& SOut, const TStr& Nm) const { 00231 XSaveHdArg(Nm, "BfL", TInt::GetStr(BfL)); 00232 SOut.PutStr(TXmlLx::GetXmlStrFromPlainMem(*this)); 00233 } 00234 00235 bool TMem::DoFitStr(const TStr& Str) const { 00236 return DoFitLen(Str.Len()+1); 00237 } 00238 00239 TMem& TMem::operator+=(const char& Ch){ 00240 if (BfL==MxBfL){Resize(BfL+1);} 00241 Bf[BfL]=Ch; BfL++; return *this; 00242 } 00243 00244 TMem& TMem::operator+=(const TMem& Mem){ 00245 int LBfL=Mem.Len(); if (BfL+LBfL>MxBfL){Resize(BfL+LBfL);} 00246 if (LBfL>0){memcpy(&Bf[BfL], Mem(), LBfL);} 00247 BfL+=LBfL; return *this; 00248 } 00249 00250 TMem& TMem::operator+=(const TStr& Str){ 00251 int LBfL=Str.Len(); if (BfL+LBfL>MxBfL){Resize(BfL+LBfL);} 00252 if (LBfL>0){memcpy(Bf+BfL, Str.CStr(), LBfL);} 00253 BfL+=LBfL; return *this; 00254 } 00255 00256 TMem& TMem::operator+=(const PSIn& SIn){ 00257 int LBfL=SIn->Len(); if (BfL+LBfL>MxBfL){Resize(BfL+LBfL);} 00258 char* LBf=new char[LBfL]; 00259 SIn->GetBf(LBf, LBfL); 00260 if (LBfL>0){memcpy(Bf+BfL, LBf, LBfL);} 00261 delete[] LBf; 00262 BfL+=LBfL; return *this; 00263 } 00264 00265 void TMem::Del(const int& BChN, const int& EChN){ 00266 if (BChN>EChN){return;} 00267 if ((BChN==0)&&(EChN==BfL-1)){Clr(); return;} 00268 IAssert((0<=BChN)&&(BChN<=EChN)&&(EChN<BfL)); 00269 memmove(Bf+BChN, Bf+EChN+1, BfL-EChN-1); 00270 BfL-=(EChN-BChN+1); 00271 } 00272 00273 //int TMem::AddStr(const TStr& Str){ 00274 // int LBfL=Str.Len()+1; Resize(BfL+LBfL); 00275 // if (LBfL>0){memcpy(&Bf[BfL], Str.CStr(), LBfL);} 00276 // int FChN=BfL; BfL+=LBfL; return FChN; 00277 //} 00278 00279 void TMem::AddBf(const void* _Bf, const int& _BfL){ 00280 IAssert((_BfL>=0) && (_Bf != NULL)); 00281 Reserve(Len() + _BfL, false); 00282 memcpy(Bf + BfL, _Bf, _BfL); 00283 BfL+=_BfL; 00284 //char* ChBf=(char*)Bf; 00285 //for (int BfC=0; BfC<BfL; BfC++){ 00286 // char Ch=ChBf[BfC]; 00287 // operator+=(Ch); 00288 //} 00289 } 00290 00291 TStr TMem::GetAsStr(const char& NewNullCh) const { 00292 if (NewNullCh!='\0'){ 00293 TChA ChA(*this); 00294 ChA.ChangeCh('\0', NewNullCh); 00295 return ChA; 00296 } else { 00297 return TStr(*this); 00298 } 00299 } 00300 00302 // Input-Memory 00303 TMemIn::TMemIn(const TMem& _Mem, const int& _BfC): 00304 TSBase("Input-Memory"), TSIn("Input-Memory"), Mem(), Bf(_Mem()), BfC(_BfC), BfL(_Mem.Len()){} 00305 00306 int TMemIn::GetBf(const void* LBf, const TSize& LBfL){ 00307 Assert(TSize(BfC+LBfL)<=TSize(BfL)); 00308 int LBfS=0; 00309 for (TSize LBfC=0; LBfC<LBfL; LBfC++){ 00310 LBfS+=(((char*)LBf)[LBfC]=Bf[BfC++]);} 00311 return LBfS; 00312 } 00313 00315 // Output-Memory 00316 TMemOut::TMemOut(const PMem& _Mem): TSBase("Output-Memory"), TSOut("Output-Memory"), Mem(_Mem){} 00317 00318 int TMemOut::PutBf(const void* LBf, const TSize& LBfL){ 00319 int LBfS=0; 00320 TMem& _Mem=*Mem; 00321 for (TSize LBfC=0; LBfC<LBfL; LBfC++){ 00322 char Ch=((char*)LBf)[LBfC]; 00323 LBfS+=Ch; _Mem+=Ch; 00324 } 00325 return LBfS; 00326 } 00327 00329 // Char-Array 00330 void TChA::Resize(const int& _MxBfL){ 00331 if (_MxBfL<=MxBfL){return;} 00332 else {if (MxBfL*2<_MxBfL){MxBfL=_MxBfL;} else {MxBfL*=2;}} 00333 char* NewBf=new char[MxBfL+1]; IAssert(NewBf!=NULL); 00334 strcpy(NewBf, Bf); 00335 delete[] Bf; Bf=NewBf; 00336 } 00337 00338 TChA::TChA(const TStr& Str){ 00339 Bf=new char[(MxBfL=BfL=Str.Len())+1]; 00340 strcpy(Bf, Str.CStr()); 00341 } 00342 00343 void TChA::SaveXml(TSOut& SOut, const TStr& Nm) const { 00344 XSaveHdArg(Nm, "BfL", TInt::GetStr(BfL)); 00345 SOut.PutStr(TXmlLx::GetXmlStrFromPlainStr(*this)); 00346 } 00347 00348 TChA& TChA::operator=(const TChA& ChA){ 00349 if (this!=&ChA){ 00350 if (ChA.BfL>MxBfL){delete[] Bf; Bf=new char[(MxBfL=ChA.BfL)+1];} 00351 BfL=ChA.BfL; strcpy(Bf, ChA.CStr()); 00352 } 00353 return *this; 00354 } 00355 00356 TChA& TChA::operator=(const TStr& Str){ 00357 if (Str.Len()>MxBfL){delete[] Bf; Bf=new char[(MxBfL=Str.Len())+1];} 00358 BfL=Str.Len(); strcpy(Bf, Str.CStr()); 00359 return *this; 00360 } 00361 00362 TChA& TChA::operator=(const char* CStr){ 00363 int CStrLen=int(strlen(CStr)); 00364 if (CStrLen>MxBfL){delete[] Bf; Bf=new char[(MxBfL=CStrLen)+1];} 00365 BfL=CStrLen; strcpy(Bf, CStr); 00366 return *this; 00367 } 00368 00369 TChA& TChA::operator+=(const TMem& Mem) { 00370 Resize(BfL+Mem.Len()); 00371 strcpy(Bf+BfL, Mem.GetBf()); BfL+=Mem.Len(); return *this; 00372 } 00373 00374 TChA& TChA::operator+=(const TChA& ChA){ 00375 Resize(BfL+ChA.Len()); 00376 strcpy(Bf+BfL, ChA.CStr()); BfL+=ChA.Len(); return *this; 00377 } 00378 00379 TChA& TChA::operator+=(const TStr& Str){ 00380 Resize(BfL+Str.Len()); 00381 strcpy(Bf+BfL, Str.CStr()); BfL+=Str.Len(); return *this; 00382 } 00383 00384 TChA& TChA::operator+=(const char* CStr){ 00385 int CStrLen=(int)strlen(CStr); Resize(BfL+CStrLen); 00386 strcpy(Bf+BfL, CStr); BfL+=CStrLen; return *this; 00387 } 00388 00389 void TChA::Ins(const int& BChN, const char* CStr){ 00390 Assert((0<=BChN)&&(BChN<=BfL)); //** ali je <= v (BChN<=BfL) upravicen? 00391 int CStrLen=int(strlen(CStr)); Resize(BfL+CStrLen); 00392 memmove(Bf+BChN+CStrLen, Bf+BChN, BfL-BChN+1); 00393 memmove(Bf+BChN, CStr, CStrLen); BfL+=CStrLen; 00394 } 00395 00396 void TChA::Del(const int& ChN){ 00397 Assert((0<=ChN)&&(ChN<BfL)); 00398 memmove(Bf+ChN, Bf+ChN+1, BfL-ChN); 00399 BfL--; 00400 } 00401 00402 void TChA::Trunc(){ 00403 int BChN=0; while ((BChN<BfL)&&(GetCh(BChN)<=' ')){BChN++;} 00404 int EChN=BfL-1; while ((0<=EChN)&&(GetCh(EChN)<=' ')){EChN--;} 00405 if (BChN<=EChN){ 00406 for (int ChN=BChN; ChN<=EChN; ChN++){ 00407 PutCh(ChN-BChN, GetCh(ChN));} 00408 Trunc(EChN-BChN+1); 00409 } else { 00410 Clr(); 00411 } 00412 /* int BChN=0; while ((BChN<BfL)&&(Bf[BChN]<=' ')){BChN++;} 00413 int EChN=BfL-1; while ((0<=EChN)&&(Bf[EChN]<=' ')){EChN--;} 00414 if (BChN<=EChN){ 00415 for (int ChN=BChN; ChN<=EChN; ChN++){Bf[ChN-BChN]=Bf[ChN];} 00416 Bf[BfL=EChN+1]=0; 00417 } else { 00418 Clr(); 00419 }*/ 00420 } 00421 00422 void TChA::Reverse(){ 00423 for (int ChN=0; ChN<BfL/2; ChN++){ 00424 char Ch=Bf[ChN]; 00425 Bf[ChN]=Bf[BfL-ChN-1]; 00426 Bf[BfL-ChN-1]=Ch; 00427 } 00428 } 00429 00430 TChA TChA::GetSubStr(const int& _BChN, const int& _EChN) const { 00431 int BChN=TInt::GetMx(_BChN, 0); 00432 int EChN=TInt::GetMn(_EChN, Len()-1); 00433 int Chs=EChN-BChN+1; 00434 if (Chs<=0){return TStr::GetNullStr();} 00435 else if (Chs==Len()){return *this;} 00436 else { 00437 //char* Bf=new char[Chs+1]; strncpy(Bf, CStr()+BChN, Chs); Bf[Chs]=0; 00438 //TStr Str(Bf); delete[] Bf; 00439 //return Str; 00440 return TChA(CStr()+BChN, Chs); 00441 } 00442 } 00443 00444 int TChA::CountCh(const char& Ch, const int& BChN) const { 00445 int ChN=TInt::GetMx(BChN, 0); 00446 const int ThisLen=Len(); 00447 int Cnt = 0; 00448 while (ChN<ThisLen){if (Bf[ChN]==Ch){ Cnt++;} ChN++;} 00449 return Cnt; 00450 } 00451 00452 int TChA::SearchCh(const char& Ch, const int& BChN) const { 00453 int ChN=TInt::GetMx(BChN, 0); 00454 const int ThisLen=Len(); 00455 while (ChN<ThisLen){if (Bf[ChN]==Ch){return ChN;} ChN++;} 00456 return -1; 00457 } 00458 00459 int TChA::SearchChBack(const char& Ch, int BChN) const { 00460 if (BChN >= Len() || BChN < 0) { BChN = Len()-1; } 00461 for (int i = BChN; i >= 0; i--) { 00462 if (GetCh(i) == Ch) { return i; } 00463 } 00464 return -1; 00465 } 00466 00467 int TChA::SearchStr(const TChA& Str, const int& BChN) const { 00468 return SearchStr(Str.CStr(), BChN); 00469 } 00470 00471 int TChA::SearchStr(const TStr& Str, const int& BChN) const { 00472 return SearchStr(Str.CStr(), BChN); 00473 } 00474 00475 int TChA::SearchStr(const char* CStr, const int& BChN) const { 00476 const char* BegPos=strstr(Bf+BChN, CStr); 00477 if (BegPos==NULL){return -1;} 00478 else {return int(BegPos-Bf);} 00479 } 00480 00481 bool TChA::IsPrefix(const char* CStr, const int& BChN) const { 00482 if (BChN+(int)strlen(CStr)>Len()){return false;} 00483 const char* B = Bf+BChN; 00484 const char* C = CStr; 00485 while (*C!=0 && *B==*C) { 00486 B++; C++; 00487 } 00488 if (*C==0){return true;} 00489 else {return false;} 00490 } 00491 00492 bool TChA::IsPrefix(const TStr& Str) const { 00493 return IsPrefix(Str.CStr()); 00494 } 00495 00496 bool TChA::IsPrefix(const TChA& Str) const { 00497 return IsPrefix(Str.CStr()); 00498 } 00499 00500 bool TChA::IsSuffix(const char* CStr) const { 00501 if ((int)strlen(CStr) > Len()) { return false; } 00502 const char* E = Bf+Len()-1; 00503 const char* C = CStr+strlen(CStr)-1; 00504 while (C >= CStr && *E==*C) { 00505 E--; C--; 00506 } 00507 if (C+1 == CStr) { return true; } 00508 else { return false; } 00509 } 00510 00511 bool TChA::IsSuffix(const TStr& Str) const { 00512 return IsSuffix(Str.CStr()); 00513 } 00514 00515 bool TChA::IsSuffix(const TChA& Str) const { 00516 return IsSuffix(Str.CStr()); 00517 } 00518 00519 void TChA::ChangeCh(const char& SrcCh, const char& DstCh){ 00520 int StrLen=Len(); 00521 for (int ChN=0; ChN<StrLen; ChN++){if (Bf[ChN]==SrcCh){Bf[ChN]=DstCh;}} 00522 } 00523 00524 /*void TChA::ToUc(){ 00525 int StrLen=Len(); 00526 for (int ChN=0; ChN<StrLen; ChN++){Bf[ChN]=(char)toupper(Bf[ChN]);} 00527 } 00528 00529 void TChA::ToLc(){ 00530 int StrLen=Len(); 00531 for (int ChN=0; ChN<StrLen; ChN++){Bf[ChN]=(char)tolower(Bf[ChN]);} 00532 }*/ 00533 00534 TChA& TChA::ToLc() { 00535 char *c = Bf; 00536 while (*c) { 00537 *c = (char) tolower(*c); c++; 00538 } 00539 return *this; 00540 } 00541 00542 TChA& TChA::ToUc() { 00543 char *c = Bf; 00544 while (*c) { 00545 *c = (char) toupper(*c); c++; 00546 } 00547 return *this; 00548 } 00549 00550 TChA& TChA::ToTrunc(){ 00551 int StrLen=Len(); int BChN=0; int EChN=StrLen-1; 00552 while ((BChN<StrLen)&&TCh::IsWs(GetCh(BChN))){BChN++;} 00553 while ((EChN>=0)&&TCh::IsWs(GetCh(EChN))){EChN--;} 00554 if ((BChN!=0)||(EChN!=StrLen-1)){ 00555 int DstChN=0; 00556 for (int SrcChN=BChN; SrcChN<=EChN; SrcChN++){ 00557 PutCh(DstChN, GetCh(SrcChN)); DstChN++;} 00558 Trunc(DstChN); 00559 } 00560 return *this; 00561 } 00562 00563 void TChA::CompressWs(){ 00564 int StrLen=Len(); int SrcChN=0; int DstChN=0; 00565 while ((SrcChN<StrLen)&&TCh::IsWs(GetCh(SrcChN))){SrcChN++;} 00566 while (SrcChN<StrLen){ 00567 if ((TCh::IsWs(GetCh(SrcChN)))&&(DstChN>0)&&(TCh::IsWs(GetCh(DstChN-1)))){ 00568 SrcChN++; 00569 } else { 00570 PutCh(DstChN, GetCh(SrcChN)); SrcChN++; DstChN++; 00571 } 00572 } 00573 if ((DstChN>0)&&(TCh::IsWs(GetCh(DstChN-1)))){DstChN--;} 00574 Trunc(DstChN); 00575 } 00576 00577 void TChA::Swap(const int& ChN1, const int& ChN2){ 00578 char Ch=GetCh(ChN1); 00579 PutCh(ChN1, GetCh(ChN2)); 00580 PutCh(ChN2, Ch); 00581 } 00582 00583 void TChA::Swap(TChA& ChA) { 00584 ::Swap(MxBfL, ChA.MxBfL); 00585 ::Swap(BfL, ChA.BfL); 00586 ::Swap(Bf, ChA.Bf); 00587 } 00588 00589 int TChA::GetPrimHashCd() const { 00590 return TStrHashF_DJB::GetPrimHashCd(CStr()); 00591 } 00592 00593 int TChA::GetSecHashCd() const { 00594 return TStrHashF_DJB::GetSecHashCd(CStr()); 00595 } 00596 00597 00598 void TChA::LoadTxt(const PSIn& SIn, TChA& ChA){ 00599 delete[] ChA.Bf; 00600 ChA.Bf=new char[(ChA.MxBfL=ChA.BfL=SIn->Len())+1]; 00601 SIn->GetBf(ChA.CStr(), SIn->Len()); ChA.Bf[ChA.BfL]=0; 00602 } 00603 00604 void TChA::SaveTxt(const PSOut& SOut) const { 00605 SOut->SaveBf(CStr(), Len()); 00606 } 00607 00608 /*TChA operator+(const TChA& LStr, const TChA& RStr){ 00609 return LStr+=RStr; } 00610 } 00611 00612 TChA operator+(const TChA& LStr, const TStr& RStr){ 00613 return LStr+=RStr.CStr(); 00614 } 00615 00616 TChA operator+(const TStr& LStr, const char* RCStr){ 00617 return LStr+=RCStr; 00618 }*/ 00619 00620 00622 // Input-Char-Array 00623 TChAIn::TChAIn(const TChA& ChA, const int& _BfC): 00624 TSBase("Input-Char-Array"), TSIn("Input-Char-Array"), Bf(ChA.CStr()), BfC(_BfC), BfL(ChA.Len()){} 00625 00626 int TChAIn::GetBf(const void* LBf, const TSize& LBfL){ 00627 Assert(TSize(BfC+LBfL)<=TSize(BfL)); 00628 int LBfS=0; 00629 for (TSize LBfC=0; LBfC<LBfL; LBfC++){ 00630 LBfS+=(((char*)LBf)[LBfC]=Bf[BfC++]);} 00631 return LBfS; 00632 } 00633 00635 // Ref-String 00636 bool TRStr::IsUc() const { 00637 int StrLen=Len(); 00638 for (int ChN=0; ChN<StrLen; ChN++){ 00639 if (('a'<=Bf[ChN])&&(Bf[ChN]<='z')){return false;}} 00640 return true; 00641 } 00642 00643 void TRStr::ToUc(){ 00644 int StrLen=Len(); 00645 for (int ChN=0; ChN<StrLen; ChN++){ 00646 Bf[ChN]=(char)toupper(Bf[ChN]);}} 00647 00648 bool TRStr::IsLc() const { 00649 int StrLen=Len(); 00650 for (int ChN=0; ChN<StrLen; ChN++){ 00651 if (('A'<=Bf[ChN])&&(Bf[ChN]<='Z')){return false;}} 00652 return true; 00653 } 00654 00655 void TRStr::ToLc(){ 00656 int StrLen=Len(); 00657 for (int ChN=0; ChN<StrLen; ChN++){ 00658 Bf[ChN]=(char)tolower(Bf[ChN]);} 00659 } 00660 00661 void TRStr::ToCap(){ 00662 int StrLen=Len(); 00663 if (StrLen>0){ 00664 Bf[0]=(char)toupper(Bf[0]);} 00665 for (int ChN=1; ChN<StrLen; ChN++){ 00666 Bf[ChN]=(char)tolower(Bf[ChN]);} 00667 } 00668 00669 void TRStr::ConvUsFromYuAscii(){ 00670 int StrLen=Len(); 00671 for (int ChN=0; ChN<StrLen; ChN++){ 00672 Bf[ChN]=TCh::GetUsFromYuAscii(Bf[ChN]);} 00673 } 00674 00675 int TRStr::CmpI(const char* p, const char* r){ 00676 if (!p){return r ? (*r ? -1 : 0) : 0;} 00677 if (!r){return (*p ? 1 : 0);} 00678 while (*p && *r){ 00679 int i=int(toupper(*p++))-int(toupper(*r++)); 00680 if (i!=0){return i;} 00681 } 00682 return int(toupper(*p++))-int(toupper(*r++)); 00683 } 00684 00685 int TRStr::GetPrimHashCd() const { 00686 return TStrHashF_DJB::GetPrimHashCd(Bf); 00687 } 00688 00689 int TRStr::GetSecHashCd() const { 00690 return TStrHashF_DJB::GetSecHashCd(Bf); 00691 } 00692 00694 // String 00695 TRStr* TStr::GetRStr(const char* CStr){ 00696 int CStrLen; 00697 if (CStr==NULL){CStrLen=0;} else {CStrLen=int(strlen(CStr));} 00698 if (CStrLen==0){return TRStr::GetNullRStr();} 00699 // next lines are not multi-threading safe 00700 //else if (CStrLen==1){return GetChStr(CStr[0]).RStr;} 00701 //else if (CStrLen==2){return GetDChStr(CStr[0], CStr[1]).RStr;} 00702 else {return new TRStr(CStr);} 00703 } 00704 00705 void TStr::Optimize(){ 00706 char* CStr=RStr->CStr(); int CStrLen=int(strlen(CStr)); 00707 TRStr* NewRStr; 00708 if (CStrLen==0){NewRStr=TRStr::GetNullRStr();} 00709 // next lines are not multi-threading safe 00710 //else if (CStrLen==1){NewRStr=GetChStr(CStr[0]).RStr;} 00711 //else if (CStrLen==2){NewRStr=GetDChStr(CStr[0], CStr[1]).RStr;} 00712 else {NewRStr=RStr;} 00713 NewRStr->MkRef(); RStr->UnRef(); RStr=NewRStr; 00714 } 00715 00716 void TStr::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 00717 XLoadHd(Nm); 00718 TStr TokStr=XmlTok->GetTokStr(false); 00719 operator=(TokStr); 00720 } 00721 00722 void TStr::SaveXml(TSOut& SOut, const TStr& Nm) const { 00723 TStr XmlStr=TXmlLx::GetXmlStrFromPlainStr(*this); 00724 if (XmlStr.Empty()){XSaveBETag(Nm);} 00725 else {XSaveHd(Nm); SOut.PutStr(XmlStr);} 00726 } 00727 00728 TStr& TStr::ToUc(){ 00729 TRStr* NewRStr=new TRStr(RStr->CStr()); NewRStr->ToUc(); 00730 RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); 00731 Optimize(); return *this; 00732 } 00733 00734 TStr& TStr::ToLc(){ 00735 TRStr* NewRStr=new TRStr(RStr->CStr()); NewRStr->ToLc(); 00736 RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); 00737 Optimize(); return *this; 00738 } 00739 00740 TStr& TStr::ToCap(){ 00741 TRStr* NewRStr=new TRStr(RStr->CStr()); NewRStr->ToCap(); 00742 RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); 00743 Optimize(); return *this; 00744 } 00745 00746 TStr& TStr::ToTrunc(){ 00747 int ThisLen=Len(); char* ThisBf=CStr(); 00748 int BChN=0; int EChN=ThisLen-1; 00749 while ((BChN<ThisLen)&&TCh::IsWs(ThisBf[BChN])){BChN++;} 00750 while ((EChN>=0)&&TCh::IsWs(ThisBf[EChN])){EChN--;} 00751 *this=GetSubStr(BChN, EChN); 00752 return *this; 00753 } 00754 00755 TStr& TStr::ConvUsFromYuAscii(){ 00756 TRStr* NewRStr=new TRStr(RStr->CStr()); NewRStr->ConvUsFromYuAscii(); 00757 RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); 00758 Optimize(); return *this; 00759 } 00760 00761 TStr& TStr::ToHex(){ 00762 TChA ChA; 00763 int StrLen=Len(); 00764 for (int ChN=0; ChN<StrLen; ChN++){ 00765 uchar Ch=uchar(RStr->Bf[ChN]); 00766 char MshCh=TCh::GetHexCh((Ch/16)%16); 00767 char LshCh=TCh::GetHexCh(Ch%16); 00768 ChA+=MshCh; ChA+=LshCh; 00769 } 00770 *this=ChA; 00771 return *this; 00772 } 00773 00774 TStr& TStr::FromHex(){ 00775 int StrLen=Len(); IAssert(StrLen%2==0); 00776 TChA ChA; int ChN=0; 00777 while (ChN<StrLen){ 00778 char MshCh=RStr->Bf[ChN]; ChN++; 00779 char LshCh=RStr->Bf[ChN]; ChN++; 00780 uchar Ch=uchar(TCh::GetHex(MshCh)*16+TCh::GetHex(LshCh)); 00781 ChA+=Ch; 00782 } 00783 *this=ChA; 00784 return *this; 00785 } 00786 00787 TStr TStr::GetSubStr(const int& _BChN, const int& _EChN) const { 00788 int StrLen=Len(); 00789 int BChN=TInt::GetMx(_BChN, 0); 00790 int EChN=TInt::GetMn(_EChN, StrLen-1); 00791 int Chs=EChN-BChN+1; 00792 if (Chs<=0){return TStr();} 00793 else if (Chs==StrLen){return *this;} 00794 else { 00795 char* Bf=new char[Chs+1]; strncpy(Bf, CStr()+BChN, Chs); Bf[Chs]=0; 00796 TStr Str(Bf); delete[] Bf; 00797 return Str; 00798 } 00799 } 00800 00801 void TStr::InsStr(const int& BChN, const TStr& Str){ 00802 int ThisLen=Len(); 00803 IAssert((0<=BChN)&&(BChN<=ThisLen)); 00804 TStr NewStr; 00805 if (BChN==0){ 00806 NewStr=Str+*this; 00807 } else 00808 if (BChN==ThisLen){ 00809 NewStr=*this+Str; 00810 } else { 00811 NewStr=GetSubStr(0, BChN-1)+Str+GetSubStr(BChN, ThisLen-1); 00812 } 00813 *this=NewStr; 00814 } 00815 00816 void TStr::DelChAll(const char& Ch){ 00817 TChA ChA(*this); 00818 int ChN=ChA.SearchCh(Ch); 00819 while (ChN!=-1){ 00820 ChA.Del(ChN); 00821 ChN=ChA.SearchCh(Ch); 00822 } 00823 *this=ChA; 00824 } 00825 00826 void TStr::DelSubStr(const int& _BChN, const int& _EChN){ 00827 int BChN=TInt::GetMx(_BChN, 0); 00828 int EChN=TInt::GetMn(_EChN, Len()-1); 00829 int Chs=Len()-(EChN-BChN+1); 00830 if (Chs==0){Clr();} 00831 else if (Chs<Len()){ 00832 char* Bf=new char[Chs+1]; strncpy(Bf, CStr(), BChN); 00833 strncpy(Bf+BChN, CStr()+EChN+1, Len()-EChN-1); Bf[Chs]=0; 00834 TStr Str(Bf); delete[] Bf; 00835 *this=Str; 00836 } 00837 } 00838 00839 bool TStr::DelStr(const TStr& Str){ 00840 int ChN=SearchStr(Str); 00841 if (ChN==-1){ 00842 return false; 00843 } else { 00844 DelSubStr(ChN, ChN+Str.Len()-1); 00845 return true; 00846 } 00847 } 00848 00849 TStr TStr::LeftOf(const char& SplitCh) const { 00850 int ThisLen=Len(); const char* ThisBf=CStr(); 00851 int ChN=0; 00852 while ((ChN<ThisLen)&&(ThisBf[ChN]!=SplitCh)){ChN++;} 00853 return (ChN==ThisLen) ? "" : GetSubStr(0, ChN-1); 00854 } 00855 00856 TStr TStr::LeftOfLast(const char& SplitCh) const { 00857 const char* ThisBf=CStr(); 00858 int ChN=Len()-1; 00859 while ((ChN>=0)&&(ThisBf[ChN]!=SplitCh)){ChN--;} 00860 return (ChN==-1) ? "" : GetSubStr(0, ChN-1); 00861 } 00862 00863 TStr TStr::RightOf(const char& SplitCh) const { 00864 int ThisLen=Len(); const char* ThisBf=CStr(); 00865 int ChN=0; 00866 while ((ChN<ThisLen)&&(ThisBf[ChN]!=SplitCh)){ChN++;} 00867 return (ChN==ThisLen) ? "" : GetSubStr(ChN+1, ThisLen-1); 00868 } 00869 00870 TStr TStr::RightOfLast(const char& SplitCh) const { 00871 int ThisLen=Len(); const char* ThisBf=CStr(); 00872 int ChN=Len()-1; 00873 while ((ChN>=0)&&(ThisBf[ChN]!=SplitCh)){ChN--;} 00874 return (ChN==-1) ? "" : GetSubStr(ChN+1, ThisLen-1); 00875 } 00876 00877 void TStr::SplitOnCh(TStr& LStr, const char& SplitCh, TStr& RStr) const { 00878 int ThisLen=Len(); const char* ThisBf=CStr(); 00879 int ChN=0; 00880 while ((ChN<ThisLen)&&(ThisBf[ChN]!=SplitCh)){ChN++;} 00881 if (ChN==ThisLen){ 00882 LStr=GetSubStr(0, ThisLen-1); RStr=""; 00883 } else { 00884 LStr=GetSubStr(0, ChN-1); RStr=GetSubStr(ChN+1, ThisLen-1); 00885 } 00886 } 00887 00888 void TStr::SplitOnLastCh(TStr& LStr, const char& SplitCh, TStr& RStr) const { 00889 int ThisLen=Len(); const char* ThisBf=CStr(); 00890 int ChN=Len()-1; 00891 while ((ChN>=0)&&(ThisBf[ChN]!=SplitCh)){ChN--;} 00892 if (ChN==-1){ 00893 LStr=""; RStr=*this; 00894 } else 00895 if (ChN==0){ 00896 LStr=""; RStr=GetSubStr(1, ThisLen-1); 00897 } else { 00898 LStr=GetSubStr(0, ChN-1); RStr=GetSubStr(ChN+1, ThisLen-1); 00899 } 00900 } 00901 00902 void TStr::SplitOnAllCh( 00903 const char& SplitCh, TStrV& StrV, const bool& SkipEmpty) const { 00904 StrV.Clr(); 00905 char* Bf=new char[Len()+1]; 00906 strcpy(Bf, CStr()); 00907 char* CurStrBf=Bf; 00908 forever{ 00909 char* BfC=CurStrBf; 00910 while ((*BfC!=0)&&(*BfC!=SplitCh)){BfC++;} 00911 bool IsEnd=(*BfC=='\0'); 00912 *BfC=0; 00913 if ((BfC>CurStrBf)||(!SkipEmpty)){StrV.Add(TStr(CurStrBf));} 00914 if (IsEnd){break;} 00915 CurStrBf=BfC+1; 00916 } 00917 delete[] Bf; 00918 } 00919 00920 void TStr::SplitOnAllAnyCh( 00921 const TStr& SplitChStr, TStrV& StrV, const bool& SkipEmpty) const { 00922 // reset string output-vector 00923 StrV.Clr(); 00924 // prepare working-copy of string 00925 char* Bf=new char[Len()+1]; 00926 strcpy(Bf, CStr()); 00927 char* CurStrBf=Bf; // pointer to current string 00928 // prepare pointer to split-char-string 00929 const char* SplitChBf=SplitChStr.CStr(); 00930 forever{ 00931 char* BfC=CurStrBf; // set the counter for working-string 00932 while (*BfC!=0){ 00933 const char* SplitChBfC=SplitChBf; // set counter for split-char-string 00934 while ((*SplitChBfC!=0)&&(*SplitChBfC!=*BfC)){SplitChBfC++;} 00935 if (*SplitChBfC!=0){break;} // if split-char found 00936 BfC++; 00937 } 00938 bool IsEnd=(*BfC==0); 00939 *BfC=0; 00940 if ((BfC>CurStrBf)||(!SkipEmpty)){StrV.Add(TStr(CurStrBf));} 00941 if (IsEnd){break;} 00942 CurStrBf=BfC+1; 00943 } 00944 // delete working-copy 00945 delete[] Bf; 00946 } 00947 00948 void TStr::SplitOnWs(TStrV& StrV) const { 00949 StrV.Clr(); 00950 char* Bf=new char[Len()+1]; 00951 strcpy(Bf, CStr()); 00952 char* StrBf=Bf; 00953 forever{ 00954 while ((*StrBf!=0)&&(TCh::IsWs(*StrBf))){StrBf++;} 00955 char* BfC=StrBf; 00956 while ((*BfC!=0)&&(!TCh::IsWs(*BfC))){BfC++;} 00957 bool IsEnd=(*BfC=='\0'); 00958 *BfC=0; 00959 if (BfC>StrBf){StrV.Add(TStr(StrBf));} 00960 if (IsEnd){break;} 00961 StrBf=BfC+1; 00962 } 00963 delete[] Bf; 00964 } 00965 00966 void TStr::SplitOnNonAlNum(TStrV& StrV) const { 00967 StrV.Clr(); 00968 char* Bf=new char[Len()+1]; 00969 strcpy(Bf, CStr()); 00970 char* StrBf=Bf; 00971 forever{ 00972 while ((*StrBf!=0)&&(!TCh::IsAlNum(*StrBf))){StrBf++;} 00973 char* BfC=StrBf; 00974 while ((*BfC!=0)&&(TCh::IsAlNum(*BfC))){BfC++;} 00975 bool IsEnd=(*BfC=='\0'); 00976 *BfC=0; 00977 if (BfC>StrBf){StrV.Add(TStr(StrBf));} 00978 if (IsEnd){break;} 00979 StrBf=BfC+1; 00980 } 00981 delete[] Bf; 00982 } 00983 00984 void TStr::SplitOnStr(const TStr& SplitStr, TStrV& StrV) const { 00985 StrV.Clr(); 00986 int SplitStrLen=SplitStr.Len(); 00987 int PrevChN=0; int ChN=0; 00988 while ((ChN=SearchStr(SplitStr, ChN))!=-1){ 00989 // extract & add string 00990 TStr SubStr=GetSubStr(PrevChN, ChN-1); 00991 StrV.Add(SubStr); 00992 PrevChN=ChN=ChN+SplitStrLen; 00993 } 00994 // add last string 00995 TStr LastSubStr=GetSubStr(PrevChN, Len()-1); 00996 StrV.Add(LastSubStr); 00997 } 00998 00999 void TStr::SplitOnStr(TStr& LeftStr, const TStr& MidStr, TStr& RightStr) const { 01000 const int ChN=SearchStr(MidStr); 01001 if (ChN==-1){ 01002 LeftStr=*this; RightStr=GetNullStr(); 01003 } else { 01004 LeftStr=GetSubStr(0, ChN-1); 01005 RightStr=GetSubStr(ChN+MidStr.Len(), Len()-1); 01006 } 01007 } 01008 01009 int TStr::CountCh(const char& Ch, const int& BChN) const { 01010 const int ThisLen=Len(); 01011 const char* ThisBf=CStr(); 01012 int Chs=0; 01013 for (int ChN=TInt::GetMx(BChN, 0); ChN<ThisLen; ChN++){ 01014 if (ThisBf[ChN]==Ch){Chs++;} 01015 } 01016 return Chs; 01017 } 01018 01019 int TStr::SearchCh(const char& Ch, const int& BChN) const { 01020 int ThisLen=Len(); const char* ThisBf=CStr(); 01021 int ChN=TInt::GetMx(BChN, 0); 01022 while (ChN<ThisLen){ 01023 if (ThisBf[ChN]==Ch){return ChN;} 01024 ChN++; 01025 } 01026 return -1; 01027 } 01028 01029 int TStr::SearchChBack(const char& Ch, int BChN) const { 01030 const int StrLen=Len(); 01031 if (BChN==-1||BChN>=StrLen){BChN=StrLen-1;} 01032 const char* ThisBf=CStr(); 01033 const char* Pt=ThisBf + BChN; 01034 while (Pt>=ThisBf) { 01035 if (*Pt==Ch){return (int)(Pt-ThisBf);} 01036 Pt--; 01037 } 01038 return -1; 01039 } 01040 01041 int TStr::SearchStr(const TStr& Str, const int& BChN) const { 01042 int NrBChN=TInt::GetMx(BChN, 0); 01043 const char* StrPt=strstr((const char*)CStr()+NrBChN, Str.CStr()); 01044 if (StrPt==NULL){return -1;} 01045 else {return int(StrPt-CStr());} 01046 /* // slow implementation 01047 int ThisLen=Len(); int StrLen=Str.Len(); 01048 int ChN=TInt::GetMx(BChN, 0); 01049 while (ChN<ThisLen-StrLen+1){ 01050 if (strncmp(CStr()+ChN, Str.CStr(), StrLen)==0){ 01051 return ChN;} 01052 ChN++; 01053 } 01054 return -1;*/ 01055 } 01056 01057 bool TStr::IsPrefix(const char *Str) const { 01058 size_t len = strlen(Str); 01059 size_t thisLen = Len(); 01060 if (len > thisLen) { 01061 return false; 01062 } else { 01063 size_t minLen = min(len, thisLen); 01064 int cmp = strncmp(Str, RStr->Bf, minLen); 01065 return cmp == 0; 01066 } 01067 } 01068 01069 bool TStr::IsSuffix(const char *Str) const { 01070 size_t len = strlen(Str); 01071 size_t thisLen = Len(); 01072 if (len > thisLen) { 01073 // too long to be a suffix anyway 01074 return false; 01075 } else { 01076 // move to the point in the buffer where we would expect the suffix to be 01077 const char *ending = RStr->Bf + thisLen - len; 01078 int cmp = strncmp(Str, ending, len); 01079 return cmp == 0; 01080 } 01081 } 01082 01083 int TStr::ChangeCh(const char& SrcCh, const char& DstCh, const int& BChN){ 01084 int ChN=SearchCh(SrcCh, BChN); 01085 if (ChN!=-1){PutCh(ChN, DstCh);} 01086 return ChN; 01087 } 01088 01089 int TStr::ChangeChAll(const char& SrcCh, const char& DstCh){ 01090 int FirstChN=SearchCh(SrcCh); 01091 if (FirstChN==-1){ 01092 return 0; 01093 } else { 01094 TRStr* NewRStr=new TRStr(RStr->CStr()); 01095 RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); 01096 char* ThisBf=CStr(); int StrLen=Len(); int Changes=0; 01097 for (int ChN=FirstChN; ChN<StrLen; ChN++){ 01098 // slow: if (GetCh(ChN)==SrcCh){RStr->PutCh(ChN, DstCh); Changes++;} 01099 if (ThisBf[ChN]==SrcCh){ThisBf[ChN]=DstCh; Changes++;} 01100 } 01101 Optimize(); 01102 return Changes; 01103 } 01104 } 01105 01106 int TStr::ChangeStr(const TStr& SrcStr, const TStr& DstStr, const int& BChN){ 01107 int ChN=SearchStr(SrcStr, BChN); 01108 if (ChN==-1){ 01109 return -1; 01110 } else { 01111 DelSubStr(ChN, ChN+SrcStr.Len()-1); 01112 InsStr(ChN, DstStr); 01113 return ChN; 01114 } 01115 } 01116 01117 int TStr::ChangeStrAll(const TStr& SrcStr, const TStr& DstStr, const bool& FromStartP){ 01118 const int DstStrLen=DstStr.Len(); 01119 int Changes=0-1; int BChN=0-DstStrLen; 01120 do { 01121 Changes++; 01122 if (FromStartP){BChN=0-DstStrLen;} 01123 BChN+=DstStrLen; 01124 BChN=ChangeStr(SrcStr, DstStr, BChN); 01125 } while (BChN!=-1); 01126 return Changes; 01127 } 01128 01129 bool TStr::IsBool(bool& Val) const { 01130 if (operator==("T")){Val=true; return true;} 01131 else if (operator==("F")){Val=false; return true;} 01132 else {return false;} 01133 } 01134 01135 bool TStr::IsInt( 01136 const bool& Check, const int& MnVal, const int& MxVal, int& Val) const { 01137 // parsing format {ws} [+/-] +{ddd} 01138 int _Val=0; 01139 bool Minus=false; 01140 TChRet Ch(TStrIn::New(*this)); 01141 while (TCh::IsWs(Ch.GetCh())){} 01142 if (Ch()=='+'){Minus=false; Ch.GetCh();} 01143 if (Ch()=='-'){Minus=true; Ch.GetCh();} 01144 if (!TCh::IsNum(Ch())){return false;} 01145 _Val=TCh::GetNum(Ch()); 01146 while (TCh::IsNum(Ch.GetCh())){_Val=10*_Val+TCh::GetNum(Ch());} 01147 if (Minus){_Val=-_Val;} 01148 if (Check&&((_Val<MnVal)||(_Val>MxVal))){return false;} 01149 if (Ch.Eof()){Val=_Val; return true;} else {return false;} 01150 } 01151 01152 bool TStr::IsUInt( 01153 const bool& Check, const uint& MnVal, const uint& MxVal, uint& Val) const { 01154 // parsing format {ws} [+]{ddd} 01155 uint _Val=0; 01156 TChRet Ch(TStrIn::New(*this)); 01157 while (TCh::IsWs(Ch.GetCh())){} 01158 if (Ch()=='+'){Ch.GetCh();} 01159 if (!TCh::IsNum(Ch())){return false;} 01160 _Val=TCh::GetNum(Ch()); 01161 while (TCh::IsNum(Ch.GetCh())){_Val=10*_Val+TCh::GetNum(Ch());} 01162 if (Check&&((_Val<MnVal)||(_Val>MxVal))){return false;} 01163 if (Ch.Eof()){Val=_Val; return true;} else {return false;} 01164 } 01165 01166 bool TStr::IsHexInt( const bool& Check, const int& MnVal, const int& MxVal, int& Val) const { 01167 // parsing format {ws} [+/-][0x] +{XXX} 01168 int _Val=0; 01169 bool Minus=false; 01170 TChRet Ch(TStrIn::New(*this)); 01171 while (TCh::IsWs(Ch.GetCh())){} 01172 if (Ch()=='+'){Minus=false; Ch.GetCh();} 01173 if (Ch()=='-'){Minus=true; Ch.GetCh();} 01174 if (Ch()=='0'){ 01175 Ch.GetCh(); 01176 if (tolower(Ch())=='x' ){ 01177 Ch.GetCh(); if (Ch.Eof()){return false;} 01178 } 01179 } 01180 if (! Ch.Eof()) _Val = TCh::GetHex(Ch()); 01181 while (TCh::IsHex(Ch.GetCh())){_Val=16*_Val+TCh::GetHex(Ch());} 01182 if (Minus){_Val=-_Val;} 01183 if (Check&&((_Val<MnVal)||(_Val>MxVal))){return false;} 01184 if (Ch.Eof()){Val=_Val; return true;} else {return false;} 01185 } 01186 01187 bool TStr::IsInt64( 01188 const bool& Check, const int64& MnVal, const int64& MxVal, int64& Val) const { 01189 // parsing format {ws} [+/-] +{ddd} 01190 int64 _Val=0; 01191 bool Minus=false; 01192 TChRet Ch(TStrIn::New(*this)); 01193 while (TCh::IsWs(Ch.GetCh())){} 01194 if (Ch()=='+'){Minus=false; Ch.GetCh();} 01195 if (Ch()=='-'){Minus=true; Ch.GetCh();} 01196 if (!TCh::IsNum(Ch())){return false;} 01197 _Val=TCh::GetNum(Ch()); 01198 while (TCh::IsNum(Ch.GetCh())){_Val=10*_Val+TCh::GetNum(Ch());} 01199 if (Minus){_Val=-_Val;} 01200 if (Check&&((_Val<MnVal)||(_Val>MxVal))){return false;} 01201 if (Ch.Eof()){Val=_Val; return true;} else {return false;} 01202 } 01203 01204 bool TStr::IsUInt64( 01205 const bool& Check, const uint64& MnVal, const uint64& MxVal, uint64& Val) const { 01206 // parsing format {ws} [+]{ddd} 01207 uint64 _Val=0; 01208 TChRet Ch(TStrIn::New(*this)); 01209 while (TCh::IsWs(Ch.GetCh())){} 01210 if (Ch()=='+'){Ch.GetCh();} 01211 if (!TCh::IsNum(Ch())){return false;} 01212 _Val=TCh::GetNum(Ch()); 01213 while (TCh::IsNum(Ch.GetCh())){_Val=10*_Val+TCh::GetNum(Ch());} 01214 if (Check&&((_Val<MnVal)||(_Val>MxVal))){return false;} 01215 if (Ch.Eof()){Val=_Val; return true;} else {return false;} 01216 } 01217 01218 bool TStr::IsHexInt64( 01219 const bool& Check, const int64& MnVal, const int64& MxVal, int64& Val) const { 01220 // parsing format {ws} [+/-][0x] +{XXX} 01221 int64 _Val=0; 01222 bool Minus=false; 01223 TChRet Ch(TStrIn::New(*this)); 01224 while (TCh::IsWs(Ch.GetCh())){} 01225 if (Ch()=='+'){Minus=false; Ch.GetCh();} 01226 if (Ch()=='-'){Minus=true; Ch.GetCh();} 01227 if (Ch()=='0'){ 01228 Ch.GetCh(); 01229 if (tolower(Ch())=='x' ){ 01230 Ch.GetCh(); if (Ch.Eof()){return false;} 01231 } 01232 } 01233 if (!Ch.Eof()) _Val=TCh::GetHex(Ch()); 01234 while (TCh::IsHex(Ch.GetCh())){_Val=16*_Val+TCh::GetHex(Ch());} 01235 if (Minus){_Val=-_Val;} 01236 if (Check&&((_Val<MnVal)||(_Val>MxVal))){return false;} 01237 if (Ch.Eof()){Val=_Val; return true;} else {return false;} 01238 } 01239 01240 bool TStr::IsFlt(const bool& Check, const double& MnVal, const double& MxVal, 01241 double& Val, const char& DecDelimCh) const { 01242 // parsing format {ws} [+/-] +{d} ([.]{d}) ([E|e] [+/-] +{d}) 01243 TChRet Ch(TStrIn::New(*this)); 01244 while (TCh::IsWs(Ch.GetCh())){} 01245 if ((Ch()=='+')||(Ch()=='-')){Ch.GetCh();} 01246 if (!TCh::IsNum(Ch())&&Ch()!=DecDelimCh){return false;} 01247 while (TCh::IsNum(Ch.GetCh())){} 01248 if (Ch()==DecDelimCh){ 01249 Ch.GetCh(); 01250 while (TCh::IsNum(Ch.GetCh())){} 01251 } 01252 if ((Ch()=='e')||(Ch()=='E')){ 01253 Ch.GetCh(); 01254 if ((Ch()=='+')||(Ch()=='-')){Ch.GetCh();} 01255 if (!TCh::IsNum(Ch())){return false;} 01256 while (TCh::IsNum(Ch.GetCh())){} 01257 } 01258 if (!Ch.Eof()){return false;} 01259 double _Val=atof(CStr()); 01260 if (Check&&((_Val<MnVal)||(_Val>MxVal))){ 01261 return false; 01262 } else { 01263 Val=_Val; return true; 01264 } 01265 } 01266 01267 bool TStr::IsWord(const bool& WsPrefixP, const bool& FirstUcAllowedP) const { 01268 // parsing format {ws} (A-Z,a-z) *{A-Z,a-z,0-9} 01269 TChRet Ch(TStrIn::New(*this)); 01270 if (WsPrefixP){while (TCh::IsWs(Ch.GetCh())){}} 01271 else {Ch.GetCh();} 01272 if (!TCh::IsAlpha(Ch())){return false;} 01273 else if (!FirstUcAllowedP&&(TCh::IsUc(Ch()))){return false;} 01274 while (TCh::IsAlNum(Ch.GetCh())){} 01275 if (!Ch.Eof()){return false;} 01276 return true; 01277 } 01278 01279 bool TStr::IsWs() const { 01280 // if string is just a bunch of whitespace chars 01281 TChRet Ch(TStrIn::New(*this)); 01282 while (TCh::IsWs(Ch.GetCh())){} 01283 return Ch.Eof(); 01284 } 01285 01286 bool TStr::IsWcMatch( 01287 const int& StrBChN, const TStr& WcStr, const int& WcStrBChN, TStrV& StarStrV, 01288 const char& StarCh, const char& QuestCh) const { 01289 int StrLen=Len(); int WcStrLen=WcStr.Len(); 01290 int StrChN=StrBChN; int WcStrChN=WcStrBChN; 01291 while ((StrChN<StrLen)&&(WcStrChN<WcStrLen)){ 01292 if ((WcStr[WcStrChN]==QuestCh)||(GetCh(StrChN)==WcStr[WcStrChN])){ 01293 StrChN++; WcStrChN++; 01294 } else 01295 if (WcStr[WcStrChN]==StarCh){ 01296 TChA StarChA; // string substituted by star character 01297 for (int AfterStrChN=StrChN; AfterStrChN<=StrLen; AfterStrChN++){ 01298 if (AfterStrChN>StrChN){ 01299 StarChA+=GetCh(AfterStrChN-1);} 01300 if (IsWcMatch(AfterStrChN, WcStr, WcStrChN+1, StarStrV, StarCh, QuestCh)){ 01301 StarStrV.Add(StarChA); return true; 01302 } 01303 } 01304 return false; 01305 } else { 01306 return false; 01307 } 01308 } 01309 if (StrChN==StrLen){ 01310 for (int AfterWcStrChN=WcStrChN; AfterWcStrChN<WcStrLen; AfterWcStrChN++){ 01311 if (WcStr[AfterWcStrChN]!=StarCh){return false;}} 01312 return true; 01313 } else { 01314 return false; 01315 } 01316 } 01317 01318 bool TStr::IsWcMatch( 01319 const TStr& WcStr, TStrV& StarStrV, const char& StarCh, const char& QuestCh) const { 01320 bool WcMatch=IsWcMatch(0, WcStr, 0, StarStrV, StarCh, QuestCh); 01321 if (WcMatch){ 01322 StarStrV.Reverse(); 01323 return true; 01324 } else { 01325 return false; 01326 } 01327 } 01328 01329 bool TStr::IsWcMatch( 01330 const TStr& WcStr, const char& StarCh, const char& QuestCh) const { 01331 TStrV StarStrV; 01332 return IsWcMatch(0, WcStr, 0, StarStrV, StarCh, QuestCh); 01333 } 01334 01335 bool TStr::IsWcMatch(const TStr& WcStr, const int& StarStrN, TStr& StarStr) const { 01336 TStrV StarStrV; 01337 if (IsWcMatch(WcStr, StarStrV)){ 01338 if (StarStrV.Len()>StarStrN){ 01339 StarStr=StarStrV[StarStrV.Len()-StarStrN-1]; 01340 } else { 01341 StarStr=""; 01342 } 01343 return true; 01344 } else { 01345 return false; 01346 } 01347 } 01348 01349 bool TStr::IsWcMatch(const TStr& WcStr) const { 01350 TStrV StarStrV; 01351 return IsWcMatch(0, WcStr, 0, StarStrV); 01352 } 01353 01354 TStr TStr::GetWcMatch(const TStr& WcStr, const int& StarStrN) const { 01355 TStrV StarStrV; 01356 if (IsWcMatch(WcStr, StarStrV)&&(StarStrV.Len()>=StarStrN)){ 01357 IAssert(StarStrN>=0); 01358 return StarStrV[StarStrV.Len()-StarStrN-1]; 01359 } else { 01360 return ""; 01361 } 01362 } 01363 01364 TStr TStr::GetFPath() const { 01365 int ThisLen=Len(); const char* ThisBf=CStr(); 01366 int ChN=ThisLen-1; 01367 while ((ChN>=0)&&(ThisBf[ChN]!='/')&&(ThisBf[ChN]!='\\')){ChN--;} 01368 return GetSubStr(0, ChN); 01369 } 01370 01371 TStr TStr::GetFBase() const { 01372 int ThisLen=Len(); const char* ThisBf=CStr(); 01373 int ChN=ThisLen-1; 01374 while ((ChN>=0)&&(ThisBf[ChN]!='/')&&(ThisBf[ChN]!='\\')){ChN--;} 01375 return GetSubStr(ChN+1, ThisLen); 01376 } 01377 01378 TStr TStr::GetFMid() const { 01379 int ThisLen=Len(); const char* ThisBf=CStr(); 01380 int ChN=ThisLen-1; 01381 while ((ChN>=0)&&(ThisBf[ChN]!='/')&&(ThisBf[ChN]!='\\')&&(ThisBf[ChN]!='.')){ 01382 ChN--;} 01383 if (ChN<0){ 01384 return *this; 01385 } else { 01386 if (ThisBf[ChN]=='.'){ 01387 int EChN= --ChN; 01388 while ((ChN>=0)&&(ThisBf[ChN]!='/')&&(ThisBf[ChN]!='\\')){ChN--;} 01389 return GetSubStr(ChN+1, EChN); 01390 } else { 01391 return GetSubStr(ChN+1, ThisLen); 01392 } 01393 } 01394 } 01395 01396 TStr TStr::GetFExt() const { 01397 int ThisLen=Len(); const char* ThisBf=CStr(); 01398 int ChN=ThisLen-1; 01399 while ((ChN>=0)&&(ThisBf[ChN]!='/')&&(ThisBf[ChN]!='\\')&& 01400 (ThisBf[ChN]!='.')){ChN--;} 01401 if ((ChN>=0)&&(ThisBf[ChN]=='.')){return GetSubStr(ChN, Len());} 01402 else {return TStr();} 01403 } 01404 01405 TStr TStr::GetNrFPath(const TStr& FPath){ 01406 TChA NrFPath(FPath.Len()+4); NrFPath+=FPath; 01407 NrFPath.ChangeCh('\\', '/'); 01408 if (NrFPath.Empty()){NrFPath="./";} 01409 if ((NrFPath.Len()>=2)&&isalpha(NrFPath[0])&&(NrFPath[1]==':')){ 01410 if (NrFPath.Len()==2){NrFPath+="./";} 01411 if ((NrFPath[2]!='.')&&(NrFPath[2]!='/')){NrFPath.Ins(2, "./");} 01412 if (NrFPath[NrFPath.Len()-1]!='/'){NrFPath+="/";} 01413 } else { 01414 if ((NrFPath[0]!='.')&&(NrFPath[0]!='/')){NrFPath.Ins(0, "./");} 01415 if (NrFPath[NrFPath.Len()-1]!='/'){NrFPath+="/";} 01416 } 01417 return NrFPath; 01418 } 01419 01420 TStr TStr::GetNrFMid(const TStr& FMid){ 01421 TChA NrFMid; 01422 int FMidLen=FMid.Len(); 01423 for (int ChN=0; ChN<FMidLen; ChN++){ 01424 char Ch=FMid[ChN]; 01425 if (TCh::IsAlNum(Ch)){NrFMid+=Ch;} else {NrFMid+='_';} 01426 } 01427 return NrFMid; 01428 } 01429 01430 TStr TStr::GetNrFExt(const TStr& FExt){ 01431 if (FExt.Empty()||(FExt[0]=='.')){return FExt;} 01432 else {return TStr(".")+FExt;} 01433 } 01434 01435 TStr TStr::GetNrNumFExt(const int& FExtN){ 01436 TStr FExtNStr=TInt::GetStr(FExtN); 01437 while (FExtNStr.Len()<3){ 01438 FExtNStr=TStr("0")+FExtNStr;} 01439 return FExtNStr; 01440 } 01441 01442 TStr TStr::GetNrFNm(const TStr& FNm){ 01443 return GetNrFPath(FNm.GetFPath())+FNm.GetFMid()+GetNrFExt(FNm.GetFExt()); 01444 } 01445 01446 TStr TStr::GetNrAbsFPath(const TStr& FPath, const TStr& BaseFPath){ 01447 TStr NrBaseFPath; 01448 if (BaseFPath.Empty()){ 01449 NrBaseFPath=GetNrFPath(TDir::GetCurDir()); 01450 } else { 01451 NrBaseFPath=GetNrFPath(BaseFPath); 01452 } 01453 IAssert(IsAbsFPath(NrBaseFPath)); 01454 TStr NrFPath=GetNrFPath(FPath); 01455 TStr NrAbsFPath; 01456 if (IsAbsFPath(NrFPath)){ 01457 NrAbsFPath=NrFPath; 01458 } else { 01459 NrAbsFPath=GetNrFPath(NrBaseFPath+NrFPath); 01460 } 01461 NrAbsFPath.ChangeStrAll("/./", "/"); 01462 NrAbsFPath.ChangeStrAll("\\.\\", "\\"); 01463 return NrAbsFPath; 01464 } 01465 01466 bool TStr::IsAbsFPath(const TStr& FPath){ 01467 if ((FPath.Len()>=3)&&isalpha(FPath[0])&&(FPath[1]==':')&& 01468 ((FPath[2]=='/')||(FPath[2]=='\\'))){ 01469 return true; 01470 } 01471 return false; 01472 } 01473 01474 TStr TStr::PutFExt(const TStr& FNm, const TStr& FExt){ 01475 return FNm.GetFPath()+FNm.GetFMid()+FExt; 01476 } 01477 01478 TStr TStr::PutFExtIfEmpty(const TStr& FNm, const TStr& FExt){ 01479 if (FNm.GetFExt().Empty()){ 01480 return FNm.GetFPath()+FNm.GetFMid()+FExt; 01481 } else { 01482 return FNm; 01483 } 01484 } 01485 01486 TStr TStr::PutFBase(const TStr& FNm, const TStr& FBase){ 01487 return FNm.GetFPath()+FBase; 01488 } 01489 01490 TStr TStr::PutFBaseIfEmpty(const TStr& FNm, const TStr& FBase){ 01491 if (FNm.GetFBase().Empty()){ 01492 return FNm.GetFPath()+FBase; 01493 } else { 01494 return FNm; 01495 } 01496 } 01497 01498 TStr TStr::AddToFMid(const TStr& FNm, const TStr& ExtFMid){ 01499 return FNm.GetFPath()+FNm.GetFMid()+ExtFMid+FNm.GetFExt(); 01500 } 01501 01502 TStr TStr::GetNumFNm(const TStr& FNm, const int& Num){ 01503 return FNm.GetFPath()+FNm.GetFMid()+TInt::GetStr(Num, "%03d")+FNm.GetFExt(); 01504 } 01505 01506 TStr TStr::GetFNmStr(const TStr& Str, const bool& AlNumOnlyP){ 01507 TChA FNm=Str; 01508 for (int ChN=0; ChN<FNm.Len(); ChN++){ 01509 uchar Ch=FNm[ChN]; 01510 if (AlNumOnlyP){ 01511 if ( 01512 (('0'<=Ch)&&(Ch<='9'))|| 01513 (('A'<=Ch)&&(Ch<='Z'))|| 01514 (('a'<=Ch)&&(Ch<='z'))|| 01515 (Ch=='-')||(Ch=='_')){} 01516 else {Ch='_';} 01517 } else { 01518 if ((Ch<=' ')||(Ch=='/')||(Ch=='\\')||(Ch==':')||(Ch=='.')){ 01519 Ch='_';} 01520 } 01521 FNm.PutCh(ChN, Ch); 01522 } 01523 return FNm; 01524 } 01525 01526 TStr& TStr::GetChStr(const char& Ch){ 01527 static char MnCh=char(CHAR_MIN); 01528 static char MxCh=char(CHAR_MAX); 01529 static int Chs=int(MxCh)-int(MnCh)+1; 01530 static TStrV ChStrV; 01531 if (ChStrV.Empty()){ 01532 ChStrV.Gen(Chs); 01533 for (int ChN=0; ChN<Chs; ChN++){ 01534 ChStrV[ChN]=TStr(char(MnCh+ChN), true);} 01535 } 01536 return ChStrV[int(Ch-MnCh)]; 01537 } 01538 01539 TStr& TStr::GetDChStr(const char& Ch1, const char& Ch2){ 01540 Fail; // temporary 01541 static TStrVV DChStrVV; 01542 if (DChStrVV.Empty()){ 01543 DChStrVV.Gen(TCh::Vals, TCh::Vals); 01544 for (int Ch1N=0; Ch1N<TCh::Vals; Ch1N++){ 01545 for (int Ch2N=0; Ch2N<TCh::Vals; Ch2N++){ 01546 DChStrVV.At(Ch1N, Ch2N)= 01547 TStr(char(TCh::Mn+Ch1N), char(TCh::Mn+Ch2N), true); 01548 } 01549 } 01550 } 01551 return DChStrVV.At(int(Ch1-TCh::Mn), int(Ch2-TCh::Mn)); 01552 } 01553 01554 TStr TStr::GetStr(const TStr& Str, const char* FmtStr){ 01555 if (FmtStr==NULL){ 01556 return Str; 01557 } else { 01558 char Bf[1000]; 01559 sprintf(Bf, FmtStr, Str.CStr()); 01560 return TStr(Bf); 01561 } 01562 } 01563 01564 TStr TStr::GetStr(const TStrV& StrV, const TStr& DelimiterStr){ 01565 if (StrV.Empty()){return TStr();} 01566 TChA ResStr=StrV[0]; 01567 for (int StrN=1; StrN<StrV.Len(); StrN++){ 01568 ResStr+=DelimiterStr; 01569 ResStr+=StrV[StrN]; 01570 } 01571 return ResStr; 01572 } 01573 01574 TStr TStr::Fmt(const char *FmtStr, ...){ 01575 char Bf[10*1024]; 01576 va_list valist; 01577 va_start(valist, FmtStr); 01578 const int RetVal=vsnprintf(Bf, 10*1024-2, FmtStr, valist); 01579 va_end(valist); 01580 return RetVal!=-1 ? TStr(Bf) : TStr::GetNullStr(); 01581 } 01582 01583 TStr TStr::GetSpaceStr(const int& Spaces){ 01584 static TStrV SpaceStrV; 01585 if (SpaceStrV.Len()==0){ 01586 for (int SpaceStrN=0; SpaceStrN<10; SpaceStrN++){ 01587 TChA SpaceChA; 01588 for (int ChN=0; ChN<SpaceStrN; ChN++){SpaceChA+=' ';} 01589 SpaceStrV.Add(SpaceChA); 01590 } 01591 } 01592 if ((0<=Spaces)&&(Spaces<SpaceStrV.Len())){ 01593 return SpaceStrV[Spaces]; 01594 } else { 01595 TChA SpaceChA; 01596 for (int ChN=0; ChN<Spaces; ChN++){SpaceChA+=' ';} 01597 return SpaceChA; 01598 } 01599 } 01600 01601 TStr TStr::GetNullStr(){ 01602 static TStr NullStr=""; 01603 return NullStr; 01604 } 01605 01606 TStr operator+(const TStr& LStr, const TStr& RStr){ 01607 if (LStr.Empty()){return RStr;} 01608 else if (RStr.Empty()){return LStr;} 01609 else {return TStr(LStr)+=RStr;} 01610 } 01611 01612 TStr operator+(const TStr& LStr, const char* RCStr){ 01613 return TStr(LStr)+=RCStr; 01614 } 01615 01617 // Input-String 01618 TStrIn::TStrIn(const TStr& _Str): 01619 TSBase("Input-String"), TSIn("Input-String"), Str(_Str), Bf(Str.CStr()), BfC(0), BfL(Str.Len()){} 01620 01621 int TStrIn::GetBf(const void* LBf, const TSize& LBfL){ 01622 Assert(TSize(BfC+LBfL)<=TSize(BfL)); 01623 int LBfS=0; 01624 for (TSize LBfC=0; LBfC<LBfL; LBfC++){ 01625 LBfS+=(((char*)LBf)[LBfC]=Bf[BfC++]);} 01626 return LBfS; 01627 } 01628 01630 // String-Pool 01631 void TStrPool::Resize(const uint& _MxBfL) { 01632 uint newSize = MxBfL; 01633 while (newSize < _MxBfL) { 01634 if (newSize >= GrowBy && GrowBy > 0) newSize += GrowBy; 01635 else if (newSize > 0) newSize *= 2; 01636 else newSize = TInt::GetMn(GrowBy, 1024); 01637 // check for overflow at 4GB 01638 IAssertR(newSize >= MxBfL, TStr::Fmt("TStrPool::Resize: %u, %u [Size larger than 4Gb, which is not supported by TStrPool]", newSize, MxBfL).CStr()); 01639 } 01640 if (newSize > MxBfL) { 01641 Bf = (char *) realloc(Bf, newSize); 01642 IAssertR(Bf, TStr::Fmt("old Bf size: %u, new size: %u", MxBfL, newSize).CStr()); 01643 MxBfL = newSize; 01644 } 01645 IAssertR(MxBfL >= _MxBfL, TStr::Fmt("new size: %u, requested size: %u", MxBfL, _MxBfL).CStr()); 01646 } 01647 01648 TStrPool::TStrPool(const uint& MxBfLen, const uint& _GrowBy) : MxBfL(MxBfLen), BfL(0), GrowBy(_GrowBy), Bf(0) { 01649 //IAssert(MxBfL >= 0); IAssert(GrowBy >= 0); 01650 if (MxBfL > 0) { Bf = (char *) malloc(MxBfL); IAssertR(Bf, TStr::Fmt("Can not resize buffer to %u bytes. [Program failed to allocate more memory. Solution: Get a bigger machine.]", MxBfL).CStr()); } 01651 AddStr(""); // add an empty string at the beginning for fast future access 01652 } 01653 01654 TStrPool::TStrPool(TSIn& SIn, bool LoadCompact) : MxBfL(0), BfL(0), GrowBy(0), Bf(0) { 01655 SIn.Load(MxBfL); SIn.Load(BfL); SIn.Load(GrowBy); 01656 //IAssert(MxBfL >= BfL); IAssert(BfL >= 0); IAssert(GrowBy >= 0); 01657 if (LoadCompact) MxBfL = BfL; 01658 if (MxBfL > 0) { Bf = (char *) malloc(MxBfL); IAssertR(Bf, TStr::Fmt("Can not resize buffer to %u bytes. [Program failed to allocate more memory. Solution: Get a bigger machine.]", MxBfL).CStr()); } 01659 if (BfL > 0) SIn.LoadBf(Bf, BfL); 01660 SIn.LoadCs(); 01661 } 01662 01663 void TStrPool::Save(TSOut& SOut) const { 01664 SOut.Save(MxBfL); SOut.Save(BfL); SOut.Save(GrowBy); 01665 SOut.SaveBf(Bf, BfL); 01666 SOut.SaveCs(); 01667 } 01668 01669 TStrPool& TStrPool::operator = (const TStrPool& Pool) { 01670 if (this != &Pool) { 01671 GrowBy = Pool.GrowBy; MxBfL = Pool.MxBfL; BfL = Pool.BfL; 01672 if (Bf) free(Bf); else IAssertR(MxBfL == 0, TStr::Fmt("size: %u, expected size: 0", MxBfL).CStr()); 01673 Bf = (char *) malloc(MxBfL); IAssertR(Bf, TStr::Fmt("Can not resize buffer to %u bytes. [Program failed to allocate more memory. Solution: Get a bigger machine.]", MxBfL).CStr()); memcpy(Bf, Pool.Bf, BfL); 01674 } 01675 return *this; 01676 } 01677 01678 // Adds Len characters to pool. To append a null 01679 // terminated string Len must be equal to strlen(s) + 1 01680 uint TStrPool::AddStr(const char *Str, const uint& Len) { 01681 IAssertR(Len > 0, "String too short (length includes the null character)"); //J: if (! Len) return -1; 01682 if (Len == 1 && BfL > 0) { return 0; } // empty string 01683 Assert(Str); Assert(Len > 0); 01684 if (BfL + Len > MxBfL) Resize(BfL + Len); 01685 memcpy(Bf + BfL, Str, Len); 01686 uint Pos = BfL; BfL += Len; return Pos; 01687 } 01688 01689 int TStrPool::GetPrimHashCd(const char *CStr) { 01690 return TStrHashF_DJB::GetPrimHashCd(CStr); 01691 } 01692 01693 int TStrPool::GetSecHashCd(const char *CStr) { 01694 return TStrHashF_DJB::GetSecHashCd(CStr); 01695 } 01696 01698 // String-Pool-64bit 01699 void TStrPool64::Resize(const ::TSize& _MxBfL) { 01700 ::TSize newSize = MxBfL; 01701 while (newSize < _MxBfL) { 01702 if (newSize >= GrowBy && GrowBy > 0) newSize += GrowBy; 01703 else if (newSize > 0) newSize *= 2; 01704 else newSize = (GrowBy > ::TSize(1024)) ? ::TSize(1024) : GrowBy; 01705 IAssert(newSize >= MxBfL); // assert we are growing 01706 } 01707 if (newSize > MxBfL) { 01708 Bf = (char *) realloc(Bf, newSize); 01709 IAssertR(Bf, TStr::Fmt("old Bf size: %u, new size: %u", MxBfL, newSize).CStr()); 01710 MxBfL = newSize; 01711 } 01712 IAssert(MxBfL >= _MxBfL); 01713 } 01714 01715 TStrPool64::TStrPool64(::TSize _MxBfL, ::TSize _GrowBy): 01716 MxBfL(_MxBfL), BfL(0), GrowBy(_GrowBy), Bf(NULL) { 01717 01718 if (MxBfL > 0) { Bf = (char*)malloc(MxBfL); IAssert(Bf != NULL); } 01719 AddStr(""); 01720 } 01721 01722 TStrPool64::TStrPool64(const TStrPool64& StrPool): 01723 MxBfL(StrPool.MxBfL), BfL(StrPool.BfL), GrowBy(StrPool.GrowBy) { 01724 if (Bf != NULL) { free(Bf); } else { IAssert(MxBfL == 0); } 01725 Bf = (char*)malloc(StrPool.MxBfL); IAssert(Bf != NULL); 01726 memcpy(Bf, StrPool.Bf, BfL); 01727 } 01728 01729 TStrPool64::TStrPool64(TSIn& SIn, bool LoadCompact): 01730 MxBfL(0), BfL(0), GrowBy(0), Bf(0) { 01731 uint64 _GrowBy, _MxBfL, _BfL; 01732 SIn.Load(_GrowBy); SIn.Load(_MxBfL); SIn.Load(_BfL); 01733 GrowBy = (::TSize)_GrowBy; MxBfL = (::TSize)_MxBfL; BfL = (::TSize)_BfL; 01734 if (LoadCompact) { MxBfL = BfL; } 01735 if (MxBfL > 0) { Bf = (char*)malloc(MxBfL); IAssert(Bf != NULL); } 01736 for (::TSize BfN = 0; BfN < _BfL; BfN++) { Bf[BfN] = SIn.GetCh(); } 01737 SIn.LoadCs(); 01738 } 01739 01740 void TStrPool64::Save(TSOut& SOut) const { 01741 uint64 _GrowBy = GrowBy, _MxBfL = MxBfL, _BfL = BfL; 01742 SOut.Save(_GrowBy); SOut.Save(_MxBfL); SOut.Save(_BfL); 01743 for (::TSize BfN = 0; BfN < _BfL; BfN++) { SOut.PutCh(Bf[BfN]); } 01744 SOut.SaveCs(); 01745 } 01746 01747 TStrPool64& TStrPool64::operator=(const TStrPool64& StrPool) { 01748 if (this != &StrPool) { 01749 GrowBy = StrPool.GrowBy; MxBfL = StrPool.MxBfL; BfL = StrPool.BfL; 01750 if (Bf != NULL) { free(Bf); } else { IAssert(MxBfL == 0); } 01751 Bf = (char*)malloc(MxBfL); IAssert(Bf != NULL); 01752 memcpy(Bf, StrPool.Bf, BfL); 01753 } 01754 return *this; 01755 } 01756 01757 void TStrPool64::Clr(bool DoDel) { 01758 BfL = 0; 01759 if (DoDel && (Bf!=NULL)) { 01760 free(Bf); 01761 Bf = NULL; MxBfL = 0; 01762 } 01763 } 01764 01765 uint64 TStrPool64::AddStr(const TStr& Str) { 01766 const int Len = Str.Len() + 1; 01767 if (BfL + Len > MxBfL) { Resize(BfL + Len); } 01768 memcpy(Bf + BfL, Str.CStr(), Len); 01769 ::TSize Offset = BfL; BfL += Len; 01770 return uint64(Offset); 01771 } 01772 01773 TStr TStrPool64::GetStr(const uint64& StrId) const { 01774 ::TSize Offset = (::TSize)StrId; 01775 return TStr(Bf + Offset); 01776 } 01777 01779 // Void 01780 void TVoid::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 01781 XLoadHd(Nm); 01782 } 01783 01784 void TVoid::SaveXml(TSOut& SOut, const TStr& Nm) const { 01785 XSaveBETag(Nm); 01786 } 01787 01789 // Boolean 01790 const bool TBool::Mn=0; 01791 const bool TBool::Mx=1; 01792 const int TBool::Vals=TBool::Mx-TBool::Mn+1; 01793 TRnd TBool::Rnd; 01794 01795 const TStr TBool::FalseStr="F"; 01796 const TStr TBool::TrueStr="T"; 01797 const TStr TBool::NStr="N"; 01798 const TStr TBool::YStr="Y"; 01799 const TStr TBool::NoStr="No"; 01800 const TStr TBool::YesStr="Yes"; 01801 01802 void TBool::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 01803 XLoadHd(Nm); 01804 Val=TXmlObjSer::GetBoolArg(XmlTok, "Val"); 01805 } 01806 01807 void TBool::SaveXml(TSOut& SOut, const TStr& Nm) const { 01808 XSaveBETagArg(Nm, "Val", TBool::GetStr(Val)); 01809 } 01810 01811 bool TBool::IsValStr(const TStr& Str){ 01812 TStr UcStr=Str.GetUc(); 01813 return 01814 (UcStr==FalseStr)||(UcStr==TrueStr)|| 01815 (UcStr==YStr)||(UcStr==NStr)|| 01816 (UcStr==YesStr)||(UcStr==NoStr); 01817 } 01818 01819 bool TBool::GetValFromStr(const TStr& Str){ 01820 return (Str==TrueStr)||(Str==YStr)||(Str==YesStr); 01821 } 01822 01823 bool TBool::GetValFromStr(const TStr& Str, const bool& DfVal){ 01824 TStr UcStr=Str.GetUc(); 01825 if (IsValStr(UcStr)){ 01826 return (UcStr==TrueStr)||(UcStr==YStr)||(UcStr==YesStr); 01827 } else { 01828 return DfVal; 01829 } 01830 } 01831 01833 // Char 01834 const char TCh::Mn=CHAR_MIN; 01835 const char TCh::Mx=CHAR_MAX; 01836 const int TCh::Vals=int(TCh::Mx)-int(TCh::Mn)+1; 01837 01838 const char TCh::NullCh=char(0); 01839 const char TCh::TabCh=char(9); 01840 const char TCh::LfCh=char(10); 01841 const char TCh::CrCh=char(13); 01842 const char TCh::EofCh=char(26); 01843 const char TCh::HashCh='#'; 01844 01845 void TCh::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 01846 XLoadHd(Nm); 01847 Val=char(TXmlObjSer::GetIntArg(XmlTok, "Val")); 01848 } 01849 01850 void TCh::SaveXml(TSOut& SOut, const TStr& Nm) const { 01851 XSaveBETagArg(Nm, "Val", TInt::GetStr(Val)); 01852 } 01853 01854 char TCh::GetUsFromYuAscii(const char& Ch){ 01855 switch (Ch){ 01856 case '~': return 'c'; 01857 case '^': return 'C'; 01858 case '{': return 's'; 01859 case '[': return 'S'; 01860 case '`': return 'z'; 01861 case '@': return 'Z'; 01862 case '|': return 'd'; 01863 case '\\': return 'D'; 01864 default: return Ch; 01865 } 01866 } 01867 01869 // Unsigned-Char 01870 const uchar TUCh::Mn=0; 01871 const uchar TUCh::Mx=UCHAR_MAX; 01872 const int TUCh::Vals=int(TUCh::Mx)-int(TUCh::Mn)+1; 01873 01874 void TUCh::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 01875 XLoadHd(Nm); 01876 Val=uchar(TXmlObjSer::GetIntArg(XmlTok, "Val")); 01877 } 01878 01879 void TUCh::SaveXml(TSOut& SOut, const TStr& Nm) const { 01880 XSaveBETagArg(Nm, "Val", TInt::GetStr(Val)); 01881 } 01882 01884 // Integer 01885 const int TInt::Mn=INT_MIN; 01886 const int TInt::Mx=INT_MAX; 01887 const int TInt::Kilo=1024; 01888 const int TInt::Mega=1024*1024; 01889 const int TInt::Giga=1024*1024*1024; 01890 TRnd TInt::Rnd; 01891 01892 void TInt::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 01893 XLoadHd(Nm); 01894 Val=TXmlObjSer::GetIntArg(XmlTok, "Val"); 01895 } 01896 01897 void TInt::SaveXml(TSOut& SOut, const TStr& Nm) const { 01898 XSaveBETagArg(Nm, "Val", TInt::GetStr(Val)); 01899 } 01900 01901 TStr TInt::GetStr(const int& Val, const char* FmtStr){ 01902 if (FmtStr==NULL){ 01903 return GetStr(Val); 01904 } else { 01905 char Bf[255]; 01906 sprintf(Bf, FmtStr, Val); 01907 return TStr(Bf); 01908 } 01909 } 01910 01911 //----------------------------------------------------------------------------- 01912 // Frugal integer serialization 01913 //----------------------------------------------------------------------------- 01914 // These routines serialize integers to sequences of 1..4 bytes, with smaller 01915 // integers receiving shorter codes. They do not work directly with streams 01916 // but rather with a user-provided buffer. It is expected that one will want 01917 // to store several such integers at once, and it would be inefficient to 01918 // call the virtual TSOut::PutCh method once for every byte; this is why 01919 // SaveFrugalInt and LoadFrugalInt work with a user-provided char* buffer 01920 // rather than with TSIn/TSOut. To store a vector of such integers, use the 01921 // SaveFrugalIntV/LoadFrugalIntV pair. 01922 01923 char* TInt::SaveFrugalInt(char *pDest, int i){ 01924 // <0xxx xxxx> has 128 combinations and is used to store -1..126. 01925 // <1xxx xxxx> <00xx xxxx> has 2^13 = 8192 combinations and is used to store 127..8318. 01926 // <1xxx xxxx> <01xx xxxx> has 2^13 = 8192 combinations and is used to store -2..-8193. 01927 // <1xxx xxxx> <1xxx xxxx> <xxxx xxxx> <0xxx xxxx> has 2^29 = 536870912 combinations and is used to store 8319..536879230. 01928 // <1xxx xxxx> <1xxx xxxx> <xxxx xxxx> <1xxx xxxx> has 2^29 = 536870912 combinations and is used to store -8194..-536879105. 01929 i++; 01930 if (i >= 0 && i <= 127) { *pDest++ = char(i); return pDest; } 01931 if (i >= 128 && i < 128 + 8192) { i -= 128; *pDest++ = char(0x80 | (i & 0x7f)); 01932 *pDest++ = char((i >> 7) & 0x3f); return pDest; } 01933 if (i <= -1 && i > -1 - 8192) { i = -1 - i; *pDest++ = char(0x80 | (i & 0x7f)); 01934 *pDest++ = char(0x40 | ((i >> 7) & 0x3f)); return pDest; } 01935 if (i >= 128 + 8192 && i < 128 + 8192 + 536870912) { i -= 128 + 8192; 01936 *pDest++ = char(0x80 | (i & 0x7f)); *pDest++ = char(0x80 | ((i >> 7) & 0x7f)); 01937 *pDest++ = char((i >> 14) & 0xff); *pDest++ = char((i >> 22) & 0x7f); return pDest; } 01938 if (i <= -1 - 8192 && i > -1 - 8192 - 536870912) { i = (-1 - 8192) - i; 01939 *pDest++ = char(0x80 | (i & 0x7f)); *pDest++ = char(0x80 | ((i >> 7) & 0x7f)); 01940 *pDest++ = char((i >> 14) & 0xff); *pDest++ = char(0x80 | ((i >> 22) & 0x7f)); return pDest; } 01941 IAssertR(false, TInt::GetStr(i)); return 0; 01942 } 01943 01944 char* TInt::LoadFrugalInt(char *pSrc, int& i){ 01945 i = 0; 01946 int ch = (int) ((unsigned char) (*pSrc++)); 01947 if ((ch & 0x80) == 0) { i = ch; i--; return pSrc; } 01948 i = (ch & 0x7f); 01949 ch = (int) ((unsigned char) (*pSrc++)); 01950 if ((ch & 0x80) == 0) 01951 { 01952 i |= (ch & 0x3f) << 7; 01953 if ((ch & 0x40) == 0) i += 128; else i = -1 - i; 01954 i--; return pSrc; 01955 } 01956 i |= (ch & 0x7f) << 7; 01957 ch = (int) ((unsigned char) (*pSrc++)); 01958 i |= ch << 14; 01959 ch = (int) ((unsigned char) (*pSrc++)); 01960 i |= (ch & 0x7f) << 22; 01961 if ((ch & 0x80) == 0) i += 128 + 8192; else i = (-1 - 8192) - i; 01962 i--; return pSrc; 01963 } 01964 01965 // Tests the SaveFrugalInt/LoadFrugalInt combination on all the 01966 // integers they can work with (about 10^9 integers). 01967 void TInt::TestFrugalInt(){ 01968 char buf[10], *p = &buf[0], *r, *s; 01969 int i, j; 01970 #define __TEST(from, to, len) \ 01971 for (i = (from); i <= (to); i++) \ 01972 { if ((i & 0xffff) == 0) printf("%d\r", i); \ 01973 r = SaveFrugalInt(p, i); s = LoadFrugalInt(p, j); \ 01974 IAssert(r == s); IAssert(i == j); IAssert(r - p == len); } 01975 01976 __TEST(-1, 126, 1); 01977 __TEST(127, 127 + 8191, 2); 01978 __TEST(-2 - 8191, -2, 2); 01979 __TEST(127 + 8192, 127 + 8191 + (1 << 29), 4); 01980 __TEST(-2 - 8191 - (1 << 29), -2 - 8192, 4); 01981 #undef __TEST 01982 } 01983 01984 // Suppose that the contents of 'v', encoded using SaveFrugalInt, 01985 // occupy 'n' bytes. SaveFrugalIntV first stores 'n' (using 01986 // SaveFrugalInt), then the contents. 01987 void TInt::SaveFrugalIntV(TSOut& SOut, const TIntV& v){ 01988 // Prepare a large enough buffer. 01989 int count = v.Len(); 01990 char *buf = new char[4 * (count + 1)], *pStart, *pEnd; 01991 // Encode the contents of 'v'. 01992 pStart = buf + 4; pEnd = pStart; 01993 for (int i = 0; i < count; i++) 01994 pEnd = SaveFrugalInt(pEnd, v[i].Val); 01995 // Encode the size of the encoded contents of 'v'. 01996 // This is stored at the beginning of 'buf' and is then 01997 // moved so that there is no gap between it and the 01998 // beginning of the stored contents (at pStart). 01999 int size = int(pEnd - pStart); 02000 char *pSizeStart = buf; 02001 char *pSizeEnd = SaveFrugalInt(pSizeStart, size); 02002 while (pSizeEnd > pSizeStart) *(--pStart) = *(--pSizeEnd); 02003 // Write the buffer and free the memory. 02004 SOut.PutBf(pStart, TSize(pEnd - pStart)); 02005 delete[] buf; 02006 } 02007 02008 // Loads an integer 'n' (using LoadFrugalInt), then loads 02009 // 'n' bytes, decoding them using LoadFrugalInt and adding 02010 // them to the vector 'v'. If clearVec is true, 'v' is 02011 // cleared before anything is added to it. 02012 void TInt::LoadFrugalIntV(TSIn& SIn, TIntV& v, bool clearVec){ 02013 if (clearVec) v.Clr(); 02014 char sizeBuf[4], *p, *pEnd; 02015 // Load the first frugally-stored integer into the sizeBuf 02016 // buffer. 'count' bytes will be read. 02017 sizeBuf[0] = SIn.GetCh(); int count = 1; 02018 if (sizeBuf[0] & 0x80) 02019 { 02020 sizeBuf[1] = SIn.GetCh(); count++; 02021 if (sizeBuf[1] & 0x80) { sizeBuf[2] = SIn.GetCh(); 02022 sizeBuf[3] = SIn.GetCh(); count += 2;} 02023 } 02024 // Decode the stored size. 02025 int size; 02026 pEnd = LoadFrugalInt(&sizeBuf[0], size); 02027 IAssert(pEnd - &sizeBuf[0] == count); 02028 if (size <= 0) return; 02029 // Allocate a buffer and read the compressed data. 02030 char *buf = new char[size]; 02031 SIn.GetBf(buf, size); 02032 // Decode the compressed integers and add them into 'v'. 02033 p = buf; pEnd = buf + size; 02034 while (p < pEnd) 02035 { int i; p = LoadFrugalInt(p, i); v.Add(i); } 02036 IAssert(p == pEnd); 02037 delete[] buf; 02038 } 02039 02041 // Unsigned-Integer 02042 const uint TUInt::Mn=0; 02043 const uint TUInt::Mx=UINT_MAX; 02044 TRnd TUInt::Rnd; 02045 02046 void TUInt::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 02047 XLoadHd(Nm); 02048 Val=TXmlObjSer::GetIntArg(XmlTok, "Val"); 02049 } 02050 02051 void TUInt::SaveXml(TSOut& SOut, const TStr& Nm) const { 02052 XSaveBETagArg(Nm, "Val", TInt::GetStr(Val)); 02053 } 02054 02055 TStr TUInt::GetStr(const uint& Val, const char* FmtStr){ 02056 if (FmtStr==NULL){ 02057 return GetStr(Val); 02058 } else { 02059 char Bf[255]; 02060 sprintf(Bf, FmtStr, Val); 02061 return TStr(Bf); 02062 } 02063 } 02064 02065 bool TUInt::IsIpStr(const TStr& IpStr, uint& Ip, const char& SplitCh) { 02066 TStrV IpStrV; IpStr.SplitOnAllCh(SplitCh, IpStrV); 02067 Ip = 0; int Byte = 0; 02068 if (!IpStrV[0].IsInt(true, 0, 255, Byte)) { return false; }; Ip = (uint)Byte; 02069 if (!IpStrV[1].IsInt(true, 0, 255, Byte)) { return false; }; Ip = (Ip << 8) | (uint)Byte; 02070 if (!IpStrV[2].IsInt(true, 0, 255, Byte)) { return false; }; Ip = (Ip << 8) | (uint)Byte; 02071 if (!IpStrV[3].IsInt(true, 0, 255, Byte)) { return false; }; Ip = (Ip << 8) | (uint)Byte; 02072 return true; 02073 } 02074 02075 uint TUInt::GetUIntFromIpStr(const TStr& IpStr, const char& SplitCh) { 02076 TStrV IpStrV; IpStr.SplitOnAllCh(SplitCh, IpStrV); 02077 uint Ip = 0; int Byte = 0; 02078 EAssertR(IpStrV[0].IsInt(true, 0, 255, Byte), TStr::Fmt("Bad IP: '%s;", IpStr.CStr())); Ip = (uint)Byte; 02079 EAssertR(IpStrV[1].IsInt(true, 0, 255, Byte), TStr::Fmt("Bad IP: '%s;", IpStr.CStr())); Ip = (Ip << 8) | (uint)Byte; 02080 EAssertR(IpStrV[2].IsInt(true, 0, 255, Byte), TStr::Fmt("Bad IP: '%s;", IpStr.CStr())); Ip = (Ip << 8) | (uint)Byte; 02081 EAssertR(IpStrV[3].IsInt(true, 0, 255, Byte), TStr::Fmt("Bad IP: '%s;", IpStr.CStr())); Ip = (Ip << 8) | (uint)Byte; 02082 return Ip; 02083 } 02084 02085 TStr TUInt::GetStrFromIpUInt(const uint& Ip) { 02086 return TStr::Fmt("%d.%d.%d.%d", ((Ip>>24) & 0xFF), 02087 ((Ip>>16) & 0xFF), ((Ip>>8) & 0xFF), (Ip & 0xFF)); 02088 } 02089 02091 // Unsigned-Integer-64Bit 02092 02093 #if defined (GLib_WIN32) 02094 const TUInt64 TUInt64::Mn(uint64(0x0000000000000000i64)); 02095 const TUInt64 TUInt64::Mx(uint64(0xFFFFFFFFFFFFFFFFi64)); 02096 #elif defined (GLib_BCB) 02097 const TUInt64 TUInt64::Mn(0x0000000000000000i64); 02098 const TUInt64 TUInt64::Mx(0xFFFFFFFFFFFFFFFFi64); 02099 #else 02100 const TUInt64 TUInt64::Mn((uint64)0x0000000000000000LL); 02101 const TUInt64 TUInt64::Mx(0xFFFFFFFFFFFFFFFFLL); 02102 #endif 02103 02104 void TUInt64::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 02105 XLoadHd(Nm); 02106 Val=TXmlObjSer::GetInt64Arg(XmlTok, "Val"); 02107 } 02108 02109 void TUInt64::SaveXml(TSOut& SOut, const TStr& Nm) const { 02110 XSaveBETagArg(Nm, "Val", TUInt64::GetStr(Val)); 02111 } 02112 02113 /*///////////////////////////////////////////////// 02114 // Unsigned-Integer-64Bit 02115 const TUInt64 TUInt64::Mn(0, 0); 02116 const TUInt64 TUInt64::Mx(UINT_MAX, UINT_MAX); 02117 02118 void TUInt64::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 02119 XLoadHd(Nm); XLoad(TInt(MsVal)); XLoad(TInt(LsVal)); 02120 } 02121 02122 void TUInt64::SaveXml(TSOut& SOut, const TStr& Nm) const { 02123 XSaveHd(Nm); XSave(TInt(MsVal)); XSave(TInt(LsVal)); 02124 } 02125 02126 TUInt64& TUInt64::operator+=(const TUInt64& Int){ 02127 uint CarryVal=(LsVal>TUInt::Mx-Int.LsVal) ? 1 : 0; 02128 LsVal+=Int.LsVal; 02129 MsVal+=Int.MsVal+CarryVal; 02130 return *this; 02131 } 02132 02133 TUInt64& TUInt64::operator-=(const TUInt64& Int){ 02134 IAssert(*this>=Int); 02135 uint CarryVal; 02136 if (LsVal>=Int.LsVal){ 02137 LsVal-=Int.LsVal; CarryVal=0; 02138 } else { 02139 LsVal+=(TUInt::Mx-Int.LsVal)+1; CarryVal=1; 02140 } 02141 MsVal-=(Int.MsVal+CarryVal); 02142 return *this; 02143 } 02144 02145 TUInt64 TUInt64::operator++(int){ 02146 if (LsVal==TUInt::Mx){ 02147 Assert(MsVal<TUInt::Mx); MsVal++; LsVal=0;} 02148 else {LsVal++;} 02149 return *this; 02150 } 02151 02152 TUInt64 TUInt64::operator--(int){ 02153 if (LsVal==0){ 02154 Assert(MsVal>0); MsVal--; LsVal=TUInt::Mx;} 02155 else {LsVal--;} 02156 return *this; 02157 } 02158 02159 TStr TUInt64::GetStr(const TUInt64& Int){ 02160 char Bf[255]; sprintf(Bf, "%.0Lf", ldouble(Int)); 02161 return TStr(Bf); 02162 } 02163 02164 TStr TUInt64::GetHexStr(const TUInt64& Int){ 02165 char Bf[255]; sprintf(Bf, "%08X%08X", Int.MsVal, Int.LsVal); 02166 return TStr(Bf); 02167 }*/ 02168 02170 // Float 02171 const double TFlt::Mn=-DBL_MAX; 02172 const double TFlt::Mx=+DBL_MAX; 02173 const double TFlt::NInf=-DBL_MAX; 02174 const double TFlt::PInf=+DBL_MAX; 02175 const double TFlt::Eps=1e-16; 02176 const double TFlt::EpsHalf =1e-7; 02177 02178 TRnd TFlt::Rnd; 02179 02180 void TFlt::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 02181 XLoadHd(Nm); 02182 Val=TXmlObjSer::GetFltArg(XmlTok, "Val"); 02183 } 02184 02185 void TFlt::SaveXml(TSOut& SOut, const TStr& Nm) const { 02186 XSaveBETagArg(Nm, "Val", TFlt::GetStr(Val)); 02187 } 02188 02189 TStr TFlt::GetStr(const double& Val, const int& Width, const int& Prec){ 02190 char Bf[255]; 02191 if ((Width==-1)&&(Prec==-1)){sprintf(Bf, "%g", Val);} 02192 else {sprintf(Bf, "%*.*f", Width, Prec, Val);} 02193 return TStr(Bf); 02194 } 02195 02196 TStr TFlt::GetStr(const double& Val, const char* FmtStr){ 02197 if (FmtStr==NULL){ 02198 return GetStr(Val); 02199 } else { 02200 char Bf[255]; 02201 sprintf(Bf, FmtStr, Val); 02202 return TStr(Bf); 02203 } 02204 } 02205 02207 // Short-Float 02208 const sdouble TSFlt::Mn=-FLT_MIN; 02209 const sdouble TSFlt::Mx=+FLT_MAX; 02210 02211 void TSFlt::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 02212 XLoadHd(Nm); 02213 Val=sdouble(TXmlObjSer::GetFltArg(XmlTok, "Val")); 02214 } 02215 02216 void TSFlt::SaveXml(TSOut& SOut, const TStr& Nm) const { 02217 XSaveBETagArg(Nm, "Val", TFlt::GetStr(Val)); 02218 } 02219 02221 // Long-Float 02222 const ldouble TLFlt::Mn=-LDBL_MAX; 02223 const ldouble TLFlt::Mx=+LDBL_MAX; 02224 /*const ldouble TUInt64::Mn_LFlt=TUInt64::Mn; 02225 const ldouble TUInt64::Mx_LFlt=TUInt64::Mx; 02226 const ldouble TUInt64::MxP1_LFlt=ldouble(TUInt::Mx)+ldouble(1);*/ 02227 02228 void TLFlt::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 02229 XLoadHd(Nm); 02230 Val=TXmlObjSer::GetFltArg(XmlTok, "Val"); 02231 } 02232 02233 void TLFlt::SaveXml(TSOut& SOut, const TStr& Nm) const { 02234 XSaveBETagArg(Nm, "Val", TFlt::GetStr(double(Val))); 02235 } 02236 02237 TStr TLFlt::GetStr(const ldouble& Val, const int& Width, const int& Prec){ 02238 char Bf[255]; 02239 if ((Width==-1)&&(Prec==-1)){sprintf(Bf, "%Lg", Val);} 02240 else {sprintf(Bf, "%*.*Lf", Width, Prec, Val);} 02241 return TStr(Bf); 02242 } 02243 02244 TStr TLFlt::GetStr(const ldouble& Val, const char* FmtStr){ 02245 if (FmtStr==NULL){ 02246 return GetStr(Val); 02247 } else { 02248 char Bf[255]; 02249 sprintf(Bf, FmtStr, Val); 02250 return TStr(Bf); 02251 } 02252 } 02253 02255 // Float-Rectangle 02256 void TFltRect::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ 02257 XLoadHd(Nm); 02258 MnX=TXmlObjSer::GetFltArg(XmlTok, "MnX"); 02259 MnY=TXmlObjSer::GetFltArg(XmlTok, "MnY"); 02260 MxX=TXmlObjSer::GetFltArg(XmlTok, "MxX"); 02261 MxY=TXmlObjSer::GetFltArg(XmlTok, "MxY"); 02262 } 02263 02264 void TFltRect::SaveXml(TSOut& SOut, const TStr& Nm) const { 02265 XSaveBETagArg4(Nm, 02266 "MnX", TFlt::GetStr(double(MnX)), "MnY", TFlt::GetStr(double(MnY)), 02267 "MxX", TFlt::GetStr(double(MxX)), "MxY", TFlt::GetStr(double(MxY))); 02268 } 02269 02270 bool TFltRect::Intersection(const TFltRect& Rect1, const TFltRect& Rect2){ 02271 const double MnXX = TFlt::GetMx(Rect1.GetMnX(), Rect2.GetMnX()); 02272 const double MnYY = TFlt::GetMx(Rect1.GetMnY(), Rect2.GetMnY()); 02273 const double MxXX = TFlt::GetMn(Rect1.GetMxX(), Rect2.GetMxX()); 02274 const double MxYY = TFlt::GetMn(Rect1.GetMxY(), Rect2.GetMxY()); 02275 return (MnXX < MxXX) && (MnYY < MxYY); 02276 } 02277 02278 TStr TFltRect::GetStr() const { 02279 TChA ChA; 02280 ChA+='('; 02281 ChA+=TFlt::GetStr(MnX, "%0.2f"); ChA+=','; 02282 ChA+=TFlt::GetStr(MnY, "%0.2f"); ChA+=','; 02283 ChA+=TFlt::GetStr(MxX, "%0.2f"); ChA+=','; 02284 ChA+=TFlt::GetStr(MxY, "%0.2f"); ChA+=')'; 02285 return ChA; 02286 }