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