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