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