SNAP Library 2.2, User Reference  2014-03-11 19:15:55
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
dt.cpp
Go to the documentation of this file.
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 }