///////////////////////////////////////////////// // Random const int TRnd::RndSeed=0; const int TRnd::a=16807; const int TRnd::m=2147483647; const int TRnd::q=127773; // m DIV a const int TRnd::r=2836; // m MOD a void TRnd::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); Seed=TXmlObjSer::GetIntArg(XmlTok, "Seed"); } void TRnd::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg(Nm, "Seed", TInt::GetStr(Seed)); } void TRnd::PutSeed(const int& _Seed){ Assert(_Seed>=0); if (_Seed==0){ //Seed=int(time(NULL)); Seed=abs(int(TSysTm::GetPerfTimerTicks())); } else { Seed=_Seed; //Seed=abs(_Seed*100000)+1; } } void TRnd::Move(const int& Steps){ for (int StepN=0; StepN=1.0)||(rsq==0.0)); // and if they are not, try again double fac=sqrt(-2.0*log(rsq)/rsq); // Box-Muller transformation return v1*fac; // return v2*fac; // second deviate } double TRnd::GetNrmDev( const double& Mean, const double& SDev, const double& Mn, const double& Mx){ double Val=Mean+GetNrmDev()*SDev; if (ValMx){Val=Mx;} return Val; } double TRnd::GetExpDev(){ double UniDev; do { UniDev=GetUniDev(); } while (UniDev==0.0); return -log(UniDev); } double TRnd::GetExpDev(const double& Lambda) { return GetExpDev()/Lambda; } double TRnd::GetGammaDev(const int& Order){ int j; double am,e,s,v1,v2,x,y; if (Order<1){Fail;} if (Order<6) { x=1.0; for (j=1;j<=Order;j++) x *=GetUniDev(); x = -log(x); } else { do { do { do { v1=2.0*GetUniDev()-1.0; v2=2.0*GetUniDev()-1.0; } while (v1*v1+v2*v2 > 1.0); y=v2/v1; am=Order-1; s=sqrt(2.0*am+1.0); x=s*y+am; } while (x <= 0.0); e=(1.0+y*y)*exp(am*log(x/am)-s*y); } while (GetUniDev()>e); } return x; } double TRnd::GetPoissonDev(const double& Mean){ static double sq,alxm,g,oldm=(-1.0); double em,t,y; if (Mean < 12.0) { if (Mean != oldm) { oldm=Mean; g=exp(-Mean); } em = -1; t=1.0; do { ++em; t *= GetUniDev(); } while (t>g); } else { if (Mean != oldm) { oldm=Mean; sq=sqrt(2.0*Mean); alxm=log(Mean); g=Mean*alxm-TSpecFunc::LnGamma(Mean+1.0); } do { do { y=tan(TMath::Pi*GetUniDev()); em=sq*y+Mean; } while (em < 0.0); em=floor(em); t=0.9*(1.0+y*y)*exp(em*alxm-TSpecFunc::LnGamma(em+1.0)-g); } while (GetUniDev()>t); } return em; } double TRnd::GetBinomialDev(const double& Prb, const int& Trials){ int j; static int nold=(-1); double am,em,g,angle,p,bnl,sq,t,y; static double pold=(-1.0),pc,plog,pclog,en,oldg; p=(Prb <= 0.5 ? Prb : 1.0-Prb); am=Trials*p; if (Trials < 25) { bnl=0.0; for (j=1;j<=Trials;j++) if (GetUniDev() < p) ++bnl; } else if (am < 1.0) { g=exp(-am); t=1.0; for (j=0;j<=Trials;j++) { t *= GetUniDev(); if (t < g) break; } bnl=(j <= Trials ? j : Trials); } else { if (Trials != nold) { en=Trials; oldg=TSpecFunc::LnGamma(en+1.0); nold=Trials; } if (p != pold) { pc=1.0-p; plog=log(p); pclog=log(pc); pold=p; } sq=sqrt(2.0*am*pc); do { do { angle=TMath::Pi*GetUniDev(); y=tan(angle); em=sq*y+am; } while (em < 0.0 || em >= (en+1.0)); em=floor(em); t=1.2*sq*(1.0+y*y)*exp(oldg-(em+1.0) -TSpecFunc::LnGamma(en-em+1.0)+em*plog+(en-em)*pclog); } while (GetUniDev() > t); bnl=em; } if (p != Prb) bnl=Trials-bnl; return bnl; } // sample points from d-dimensional unit sphere /*void TRnd::GetSphereDev(const int& Dim, TFltV& ValV) { if (ValV.Len() != Dim) { ValV.Gen(Dim); } double Length = 0.0; for (int i = 0; i < Dim; i++) { ValV[i] = GetNrmDev(); Length += TMath::Sqr(ValV[i]); } Length = 1.0 / sqrt(Length); for (int i = 0; i < Dim; i++) { ValV[i] *= Length; } }*/ TRnd TRnd::LoadTxt(TILx& Lx){ return TRnd(Lx.GetInt()); } void TRnd::SaveTxt(TOLx& Lx) const { Lx.PutInt(Seed); } ///////////////////////////////////////////////// // Memory void TMem::Resize(const int& _MxBfL){ if (_MxBfL<=MxBfL){return;} else {if (MxBfL*2<_MxBfL){MxBfL=_MxBfL;} else {MxBfL*=2;}} char* NewBf=new char[MxBfL]; IAssert(NewBf!=NULL); if (BfL>0){memcpy(NewBf, Bf, BfL);} if (Bf!=NULL){delete[] Bf;} Bf=NewBf; } TMem::TMem(const TStr& Str): MxBfL(Str.Len()), BfL(MxBfL), Bf(NULL){ if (MxBfL>0){ Bf=new char[MxBfL]; if (BfL>0){memcpy(Bf, Str.CStr(), BfL);} } } void TMem::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveHdArg(Nm, "BfL", TInt::GetStr(BfL)); SOut.PutStr(TXmlLx::GetXmlStrFromPlainMem(*this)); } bool TMem::DoFitStr(const TStr& Str) const { return DoFitLen(Str.Len()+1); } TMem& TMem::operator+=(const char& Ch){ if (BfL==MxBfL){Resize(BfL+1);} Bf[BfL]=Ch; BfL++; return *this; } TMem& TMem::operator+=(const TMem& Mem){ int LBfL=Mem.Len(); if (BfL+LBfL>MxBfL){Resize(BfL+LBfL);} if (LBfL>0){memcpy(&Bf[BfL], Mem(), LBfL);} BfL+=LBfL; return *this; } TMem& TMem::operator+=(const TStr& Str){ int LBfL=Str.Len(); if (BfL+LBfL>MxBfL){Resize(BfL+LBfL);} if (LBfL>0){memcpy(Bf+BfL, Str.CStr(), LBfL);} BfL+=LBfL; return *this; } TMem& TMem::operator+=(const PSIn& SIn){ int LBfL=SIn->Len(); if (BfL+LBfL>MxBfL){Resize(BfL+LBfL);} char* LBf=new char[LBfL]; SIn->GetBf(LBf, LBfL); if (LBfL>0){memcpy(Bf+BfL, LBf, LBfL);} delete[] LBf; BfL+=LBfL; return *this; } void TMem::Del(const int& BChN, const int& EChN){ if (BChN>EChN){return;} if ((BChN==0)&&(EChN==BfL-1)){Clr(); return;} IAssert((0<=BChN)&&(BChN<=EChN)&&(EChN0){memcpy(&Bf[BfL], Str.CStr(), LBfL);} // int FChN=BfL; BfL+=LBfL; return FChN; //} void TMem::AddBf(const void* Bf, const int& BfL){ char* ChBf=(char*)Bf; for (int BfC=0; BfCMxBfL){delete[] Bf; Bf=new char[(MxBfL=ChA.BfL)+1];} BfL=ChA.BfL; strcpy(Bf, ChA.CStr()); } return *this; } TChA& TChA::operator=(const TStr& Str){ if (Str.Len()>MxBfL){delete[] Bf; Bf=new char[(MxBfL=Str.Len())+1];} BfL=Str.Len(); strcpy(Bf, Str.CStr()); return *this; } TChA& TChA::operator=(const char* CStr){ int CStrLen=int(strlen(CStr)); if (CStrLen>MxBfL){delete[] Bf; Bf=new char[(MxBfL=CStrLen)+1];} BfL=CStrLen; strcpy(Bf, CStr); return *this; } TChA& TChA::operator+=(const TChA& ChA){ Resize(BfL+ChA.Len()); strcpy(Bf+BfL, ChA.CStr()); BfL+=ChA.Len(); return *this; } TChA& TChA::operator+=(const TStr& Str){ Resize(BfL+Str.Len()); strcpy(Bf+BfL, Str.CStr()); BfL+=Str.Len(); return *this; } TChA& TChA::operator+=(const char* CStr){ int CStrLen=(int)strlen(CStr); Resize(BfL+CStrLen); strcpy(Bf+BfL, CStr); BfL+=CStrLen; return *this; } void TChA::Ins(const int& BChN, const char* CStr){ Assert((0<=BChN)&&(BChN<=BfL)); //** ali je <= v (BChN<=BfL) upravicen? int CStrLen=int(strlen(CStr)); Resize(BfL+CStrLen); memmove(Bf+BChN+CStrLen, Bf+BChN, BfL-BChN+1); memmove(Bf+BChN, CStr, CStrLen); BfL+=CStrLen; } void TChA::Del(const int& ChN){ Assert((0<=ChN)&&(ChN= Len() || BChN < 0) { BChN = Len()-1; } for (int i = BChN; i >= 0; i--) { if (GetCh(i) == Ch) { return i; } } return -1; } int TChA::SearchStr(const TChA& Str, const int& BChN) const { return SearchStr(Str.CStr(), BChN); } int TChA::SearchStr(const TStr& Str, const int& BChN) const { return SearchStr(Str.CStr(), BChN); } int TChA::SearchStr(const char* CStr, const int& BChN) const { const char* BegPos=strstr(Bf+BChN, CStr); if (BegPos==NULL){return -1;} else {return int(BegPos-Bf);} } bool TChA::IsPrefix(const char* CStr) const { //J: if ((int)strlen(CStr) > Len()) { return false; } const char* B = Bf; const char* C = CStr; while (*C!=0 && *B==*C) { B++; C++; } if (*C == 0) { return true; } else { return false; } } bool TChA::IsPrefix(const TStr& Str) const { return IsPrefix(Str.CStr()); } bool TChA::IsPrefix(const TChA& Str) const { return IsPrefix(Str.CStr()); } bool TChA::IsSuffix(const char* CStr) const { if ((int)strlen(CStr) > Len()) { return false; } const char* E = Bf+Len()-1; const char* C = CStr+strlen(CStr)-1; while (C >= CStr && *E==*C) { E--; C--; } if (C+1 == CStr) { return true; } else { return false; } } bool TChA::IsSuffix(const TStr& Str) const { return IsSuffix(Str.CStr()); } bool TChA::IsSuffix(const TChA& Str) const { return IsSuffix(Str.CStr()); } void TChA::ChangeCh(const char& SrcCh, const char& DstCh){ int StrLen=Len(); for (int ChN=0; ChN=0)&&TCh::IsWs(GetCh(EChN))){EChN--;} if ((BChN!=0)||(EChN!=StrLen-1)){ int DstChN=0; for (int SrcChN=BChN; SrcChN<=EChN; SrcChN++){ PutCh(DstChN, GetCh(SrcChN)); DstChN++;} Trunc(DstChN); } return *this; } void TChA::CompressWs(){ int StrLen=Len(); int SrcChN=0; int DstChN=0; while ((SrcChN0)&&(TCh::IsWs(GetCh(DstChN-1)))){ SrcChN++; } else { PutCh(DstChN, GetCh(SrcChN)); SrcChN++; DstChN++; } } if ((DstChN>0)&&(TCh::IsWs(GetCh(DstChN-1)))){DstChN--;} Trunc(DstChN); } void TChA::Swap(const int& ChN1, const int& ChN2){ char Ch=GetCh(ChN1); PutCh(ChN1, GetCh(ChN2)); PutCh(ChN2, Ch); } void TChA::Swap(TChA& ChA) { ::Swap(MxBfL, ChA.MxBfL); ::Swap(BfL, ChA.BfL); ::Swap(Bf, ChA.Bf); } int TChA::GetPrimHashCd() const { return TStrHashF_DJB::GetPrimHashCd(CStr()); } int TChA::GetSecHashCd() const { return TStrHashF_DJB::GetSecHashCd(CStr()); } void TChA::LoadTxt(const PSIn& SIn, TChA& ChA){ delete[] ChA.Bf; ChA.Bf=new char[(ChA.MxBfL=ChA.BfL=SIn->Len())+1]; SIn->GetBf(ChA.CStr(), SIn->Len()); ChA.Bf[ChA.BfL]=0; } void TChA::SaveTxt(const PSOut& SOut) const { SOut->SaveBf(CStr(), Len()); } /*TChA operator+(const TChA& LStr, const TChA& RStr){ return LStr+=RStr; } } TChA operator+(const TChA& LStr, const TStr& RStr){ return LStr+=RStr.CStr(); } TChA operator+(const TStr& LStr, const char* RCStr){ return LStr+=RCStr; }*/ ///////////////////////////////////////////////// // Input-Char-Array TChAIn::TChAIn(const TChA& ChA, const int& _BfC): TSBase("Input-Char-Array"), TSIn("Input-Char-Array"), Bf(ChA.CStr()), BfC(_BfC), BfL(ChA.Len()){} int TChAIn::GetBf(const void* LBf, const TSize& LBfL){ Assert(TSize(BfC+LBfL)<=TSize(BfL)); int LBfS=0; for (TSize LBfC=0; LBfC0){ Bf[0]=(char)toupper(Bf[0]);} for (int ChN=1; ChNCStr(); int CStrLen=int(strlen(CStr)); TRStr* NewRStr; if (CStrLen==0){NewRStr=TRStr::GetNullRStr();} // next lines are not multi-threading safe //else if (CStrLen==1){NewRStr=GetChStr(CStr[0]).RStr;} //else if (CStrLen==2){NewRStr=GetDChStr(CStr[0], CStr[1]).RStr;} else {NewRStr=RStr;} NewRStr->MkRef(); RStr->UnRef(); RStr=NewRStr; } void TStr::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); TStr TokStr=XmlTok->GetTokStr(false); operator=(TokStr); } void TStr::SaveXml(TSOut& SOut, const TStr& Nm) const { TStr XmlStr=TXmlLx::GetXmlStrFromPlainStr(*this); if (XmlStr.Empty()){XSaveBETag(Nm);} else {XSaveHd(Nm); SOut.PutStr(XmlStr);} } TStr& TStr::ToUc(){ TRStr* NewRStr=new TRStr(RStr->CStr()); NewRStr->ToUc(); RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); Optimize(); return *this; } TStr& TStr::ToLc(){ TRStr* NewRStr=new TRStr(RStr->CStr()); NewRStr->ToLc(); RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); Optimize(); return *this; } TStr& TStr::ToCap(){ TRStr* NewRStr=new TRStr(RStr->CStr()); NewRStr->ToCap(); RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); Optimize(); return *this; } TStr& TStr::ToTrunc(){ int ThisLen=Len(); char* ThisBf=CStr(); int BChN=0; int EChN=ThisLen-1; while ((BChN=0)&&TCh::IsWs(ThisBf[EChN])){EChN--;} *this=GetSubStr(BChN, EChN); return *this; } TStr& TStr::ConvUsFromYuAscii(){ TRStr* NewRStr=new TRStr(RStr->CStr()); NewRStr->ConvUsFromYuAscii(); RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); Optimize(); return *this; } TStr& TStr::ToHex(){ TChA ChA; int StrLen=Len(); for (int ChN=0; ChNBf[ChN]); char MshCh=TCh::GetHexCh((Ch/16)%16); char LshCh=TCh::GetHexCh(Ch%16); ChA+=MshCh; ChA+=LshCh; } *this=ChA; return *this; } TStr& TStr::FromHex(){ int StrLen=Len(); IAssert(StrLen%2==0); TChA ChA; int ChN=0; while (ChNBf[ChN]; ChN++; char LshCh=RStr->Bf[ChN]; ChN++; uchar Ch=uchar(TCh::GetHex(MshCh)*16+TCh::GetHex(LshCh)); ChA+=Ch; } *this=ChA; return *this; } TStr TStr::GetSubStr(const int& _BChN, const int& _EChN) const { int StrLen=Len(); int BChN=TInt::GetMx(_BChN, 0); int EChN=TInt::GetMn(_EChN, StrLen-1); int Chs=EChN-BChN+1; if (Chs<=0){return TStr();} else if (Chs==StrLen){return *this;} else { char* Bf=new char[Chs+1]; strncpy(Bf, CStr()+BChN, Chs); Bf[Chs]=0; TStr Str(Bf); delete[] Bf; return Str; } } void TStr::InsStr(const int& BChN, const TStr& Str){ int ThisLen=Len(); IAssert((0<=BChN)&&(BChN<=ThisLen)); TStr NewStr; if (BChN==0){ NewStr=Str+*this; } else if (BChN==ThisLen){ NewStr=*this+Str; } else { NewStr=GetSubStr(0, BChN-1)+Str+GetSubStr(BChN, ThisLen-1); } *this=NewStr; } void TStr::DelChAll(const char& Ch){ TChA ChA(*this); int ChN=ChA.SearchCh(Ch); while (ChN!=-1){ ChA.Del(ChN); ChN=ChA.SearchCh(Ch); } *this=ChA; } void TStr::DelSubStr(const int& _BChN, const int& _EChN){ int BChN=TInt::GetMx(_BChN, 0); int EChN=TInt::GetMn(_EChN, Len()-1); int Chs=Len()-(EChN-BChN+1); if (Chs==0){Clr();} else if (Chs=0)&&(ThisBf[ChN]!=SplitCh)){ChN--;} if (ChN==-1){ LStr=""; RStr=*this; } else if (ChN==0){ LStr=""; RStr=GetSubStr(1, ThisLen-1); } else { LStr=GetSubStr(0, ChN-1); RStr=GetSubStr(ChN+1, ThisLen-1); } } void TStr::SplitOnAllCh( const char& SplitCh, TStrV& StrV, const bool& SkipEmpty) const { StrV.Clr(); char* Bf=new char[Len()+1]; strcpy(Bf, CStr()); char* CurStrBf=Bf; forever{ char* BfC=CurStrBf; while ((*BfC!=0)&&(*BfC!=SplitCh)){BfC++;} bool IsEnd=(*BfC=='\0'); *BfC=0; if ((BfC>CurStrBf)||(!SkipEmpty)){StrV.Add(TStr(CurStrBf));} if (IsEnd){break;} CurStrBf=BfC+1; } delete[] Bf; } void TStr::SplitOnAllAnyCh( const TStr& SplitChStr, TStrV& StrV, const bool& SkipEmpty) const { // reset string output-vector StrV.Clr(); // prepare working-copy of string char* Bf=new char[Len()+1]; strcpy(Bf, CStr()); char* CurStrBf=Bf; // pointer to current string // prepare pointer to split-char-string const char* SplitChBf=SplitChStr.CStr(); forever{ char* BfC=CurStrBf; // set the counter for working-string while (*BfC!=0){ const char* SplitChBfC=SplitChBf; // set counter for split-char-string while ((*SplitChBfC!=0)&&(*SplitChBfC!=*BfC)){SplitChBfC++;} if (*SplitChBfC!=0){break;} // if split-char found BfC++; } bool IsEnd=(*BfC==0); *BfC=0; if ((BfC>CurStrBf)||(!SkipEmpty)){StrV.Add(TStr(CurStrBf));} if (IsEnd){break;} CurStrBf=BfC+1; } // delete working-copy delete[] Bf; } void TStr::SplitOnWs(TStrV& StrV) const { StrV.Clr(); char* Bf=new char[Len()+1]; strcpy(Bf, CStr()); char* StrBf=Bf; forever{ while ((*StrBf!=0)&&(isspace(*StrBf))){StrBf++;} char* BfC=StrBf; while ((*BfC!=0)&&(!isspace(*BfC))){BfC++;} bool IsEnd=(*BfC=='\0'); *BfC=0; if (BfC>StrBf){StrV.Add(TStr(StrBf));} if (IsEnd){break;} StrBf=BfC+1; } delete[] Bf; } void TStr::SplitOnNonAlNum(TStrV& StrV) const { StrV.Clr(); char* Bf=new char[Len()+1]; strcpy(Bf, CStr()); char* StrBf=Bf; forever{ while ((*StrBf!=0)&&(!TCh::IsAlNum(*StrBf))){StrBf++;} char* BfC=StrBf; while ((*BfC!=0)&&(TCh::IsAlNum(*BfC))){BfC++;} bool IsEnd=(*BfC=='\0'); *BfC=0; if (BfC>StrBf){StrV.Add(TStr(StrBf));} if (IsEnd){break;} StrBf=BfC+1; } delete[] Bf; } void TStr::SplitOnStr(const TStr& SplitStr, TStrV& StrV) const { StrV.Clr(); int SplitStrLen=SplitStr.Len(); int PrevChN=0; int ChN=0; while ((ChN=SearchStr(SplitStr, ChN))!=-1){ // extract & add string TStr SubStr=GetSubStr(PrevChN, ChN-1); StrV.Add(SubStr); PrevChN=ChN=ChN+SplitStrLen; } // add last string TStr LastSubStr=GetSubStr(PrevChN, Len()-1); StrV.Add(LastSubStr); } void TStr::SplitOnStr(TStr& LeftStr, const TStr& MidStr, TStr& RightStr) const { const int ChN=SearchStr(MidStr); if (ChN==-1){ LeftStr=*this; RightStr=GetNullStr(); } else { LeftStr=GetSubStr(0, ChN-1); RightStr=GetSubStr(ChN+MidStr.Len(), Len()-1); } } int TStr::CountCh(const char& Ch, const int& BChN) const { const int ThisLen=Len(); const char* ThisBf=CStr(); int Chs=0; for (int ChN=TInt::GetMx(BChN, 0); ChN=StrLen){BChN=StrLen-1;} const char* ThisBf=CStr(); const char* Pt=ThisBf + BChN; while (Pt>=ThisBf) { if (*Pt==Ch){return (int)(Pt-ThisBf);} Pt--; } return -1; } int TStr::SearchStr(const TStr& Str, const int& BChN) const { int NrBChN=TInt::GetMx(BChN, 0); const char* StrPt=strstr((const char*)CStr()+NrBChN, Str.CStr()); if (StrPt==NULL){return -1;} else {return int(StrPt-CStr());} /* // slow implementation int ThisLen=Len(); int StrLen=Str.Len(); int ChN=TInt::GetMx(BChN, 0); while (ChNCStr()); RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); char* ThisBf=CStr(); int StrLen=Len(); int Changes=0; for (int ChN=FirstChN; ChNPutCh(ChN, DstCh); Changes++;} if (ThisBf[ChN]==SrcCh){ThisBf[ChN]=DstCh; Changes++;} } Optimize(); return Changes; } } int TStr::ChangeStr(const TStr& SrcStr, const TStr& DstStr, const int& BChN){ int ChN=SearchStr(SrcStr, BChN); if (ChN==-1){ return -1; } else { DelSubStr(ChN, ChN+SrcStr.Len()-1); InsStr(ChN, DstStr); return ChN; } } int TStr::ChangeStrAll(const TStr& SrcStr, const TStr& DstStr){ const int DstStrLen=DstStr.Len(); int Changes=0-1; int BChN=0-DstStrLen; do { Changes++; BChN+=DstStrLen; BChN=ChangeStr(SrcStr, DstStr, BChN); } while (BChN!=-1); return Changes; } bool TStr::IsBool(bool& Val) const { if (operator==("T")){Val=true; return true;} else if (operator==("F")){Val=false; return true;} else {return false;} } bool TStr::IsInt( const bool& Check, const int& MnVal, const int& MxVal, int& Val) const { // parsing format {ws} [+/-] +{ddd} int _Val=0; bool Minus=false; TChRet Ch(TStrIn::New(*this)); while (TCh::IsWs(Ch.GetCh())){} if (Ch()=='+'){Minus=false; Ch.GetCh();} if (Ch()=='-'){Minus=true; Ch.GetCh();} if (!TCh::IsNum(Ch())){return false;} _Val=TCh::GetNum(Ch()); while (TCh::IsNum(Ch.GetCh())){_Val=10*_Val+TCh::GetNum(Ch());} if (Minus){_Val=-_Val;} if (Check&&((_ValMxVal))){return false;} if (Ch.Eof()){Val=_Val; return true;} else {return false;} } bool TStr::IsUInt( const bool& Check, const uint& MnVal, const uint& MxVal, uint& Val) const { // parsing format {ws} [+]{ddd} uint _Val=0; TChRet Ch(TStrIn::New(*this)); while (TCh::IsWs(Ch.GetCh())){} if (Ch()=='+'){Ch.GetCh();} if (!TCh::IsNum(Ch())){return false;} _Val=TCh::GetNum(Ch()); while (TCh::IsNum(Ch.GetCh())){_Val=10*_Val+TCh::GetNum(Ch());} if (Check&&((_ValMxVal))){return false;} if (Ch.Eof()){Val=_Val; return true;} else {return false;} } bool TStr::IsHexInt( const bool& Check, const int& MnVal, const int& MxVal, int& Val) const { // parsing format {ws} [+/-][0x] +{XXX} int _Val=0; bool Minus=false; TChRet Ch(TStrIn::New(*this)); while (TCh::IsWs(Ch.GetCh())){} if (Ch()=='+'){Minus=false; Ch.GetCh();} if (Ch()=='-'){Minus=true; Ch.GetCh();} if (Ch()=='0'){ Ch.GetCh(); if (tolower(Ch())=='x' ){ Ch.GetCh(); if (Ch.Eof()){return false;} } } if (! Ch.Eof()) _Val = TCh::GetHex(Ch()); while (TCh::IsHex(Ch.GetCh())){_Val=16*_Val+TCh::GetHex(Ch());} if (Minus){_Val=-_Val;} if (Check&&((_ValMxVal))){return false;} if (Ch.Eof()){Val=_Val; return true;} else {return false;} } bool TStr::IsInt64( const bool& Check, const int64& MnVal, const int64& MxVal, int64& Val) const { // parsing format {ws} [+/-] +{ddd} int64 _Val=0; bool Minus=false; TChRet Ch(TStrIn::New(*this)); while (TCh::IsWs(Ch.GetCh())){} if (Ch()=='+'){Minus=false; Ch.GetCh();} if (Ch()=='-'){Minus=true; Ch.GetCh();} if (!TCh::IsNum(Ch())){return false;} _Val=TCh::GetNum(Ch()); while (TCh::IsNum(Ch.GetCh())){_Val=10*_Val+TCh::GetNum(Ch());} if (Minus){_Val=-_Val;} if (Check&&((_ValMxVal))){return false;} if (Ch.Eof()){Val=_Val; return true;} else {return false;} } bool TStr::IsUInt64( const bool& Check, const uint64& MnVal, const uint64& MxVal, uint64& Val) const { // parsing format {ws} [+]{ddd} uint64 _Val=0; TChRet Ch(TStrIn::New(*this)); while (TCh::IsWs(Ch.GetCh())){} if (Ch()=='+'){Ch.GetCh();} if (!TCh::IsNum(Ch())){return false;} _Val=TCh::GetNum(Ch()); while (TCh::IsNum(Ch.GetCh())){_Val=10*_Val+TCh::GetNum(Ch());} if (Check&&((_ValMxVal))){return false;} if (Ch.Eof()){Val=_Val; return true;} else {return false;} } bool TStr::IsHexInt64( const bool& Check, const int64& MnVal, const int64& MxVal, int64& Val) const { // parsing format {ws} [+/-][0x] +{XXX} int64 _Val=0; bool Minus=false; TChRet Ch(TStrIn::New(*this)); while (TCh::IsWs(Ch.GetCh())){} if (Ch()=='+'){Minus=false; Ch.GetCh();} if (Ch()=='-'){Minus=true; Ch.GetCh();} if (Ch()=='0'){ Ch.GetCh(); if (tolower(Ch())=='x' ){ Ch.GetCh(); if (Ch.Eof()){return false;} } } if (!Ch.Eof()) _Val=TCh::GetHex(Ch()); while (TCh::IsHex(Ch.GetCh())){_Val=16*_Val+TCh::GetHex(Ch());} if (Minus){_Val=-_Val;} if (Check&&((_ValMxVal))){return false;} if (Ch.Eof()){Val=_Val; return true;} else {return false;} } bool TStr::IsFlt(const bool& Check, const double& MnVal, const double& MxVal, double& Val, const char& DecDelimCh) const { // parsing format {ws} [+/-] +{d} ([.]{d}) ([E|e] [+/-] +{d}) TChRet Ch(TStrIn::New(*this)); while (TCh::IsWs(Ch.GetCh())){} if ((Ch()=='+')||(Ch()=='-')){Ch.GetCh();} if (!TCh::IsNum(Ch())&&Ch()!=DecDelimCh){return false;} while (TCh::IsNum(Ch.GetCh())){} if (Ch()==DecDelimCh){ Ch.GetCh(); while (TCh::IsNum(Ch.GetCh())){} } if ((Ch()=='e')||(Ch()=='E')){ Ch.GetCh(); if ((Ch()=='+')||(Ch()=='-')){Ch.GetCh();} if (!TCh::IsNum(Ch())){return false;} while (TCh::IsNum(Ch.GetCh())){} } if (!Ch.Eof()){return false;} double _Val=atof(CStr()); if (Check&&((_ValMxVal))){ return false; } else { Val=_Val; return true; } } bool TStr::IsWord(const bool& WsPrefixP, const bool& FirstUcAllowedP) const { // parsing format {ws} (A-Z,a-z) *{A-Z,a-z,0-9} TChRet Ch(TStrIn::New(*this)); if (WsPrefixP){while (TCh::IsWs(Ch.GetCh())){}} else {Ch.GetCh();} if (!TCh::IsAlpha(Ch())){return false;} else if (!FirstUcAllowedP&&(TCh::IsUc(Ch()))){return false;} while (TCh::IsAlNum(Ch.GetCh())){} if (!Ch.Eof()){return false;} return true; } bool TStr::IsWs() const { // if string is just a bunch of whitespace chars TChRet Ch(TStrIn::New(*this)); while (TCh::IsWs(Ch.GetCh())){} return Ch.Eof(); } bool TStr::IsWcMatch( const int& StrBChN, const TStr& WcStr, const int& WcStrBChN, TStrV& StarStrV, const char& StarCh, const char& QuestCh) const { int StrLen=Len(); int WcStrLen=WcStr.Len(); int StrChN=StrBChN; int WcStrChN=WcStrBChN; while ((StrChNStrChN){ StarChA+=GetCh(AfterStrChN-1);} if (IsWcMatch(AfterStrChN, WcStr, WcStrChN+1, StarStrV, StarCh, QuestCh)){ StarStrV.Add(StarChA); return true; } } return false; } else { return false; } } if (StrChN==StrLen){ for (int AfterWcStrChN=WcStrChN; AfterWcStrChNStarStrN){ StarStr=StarStrV[StarStrV.Len()-StarStrN-1]; } else { StarStr=""; } return true; } else { return false; } } bool TStr::IsWcMatch(const TStr& WcStr) const { TStrV StarStrV; return IsWcMatch(0, WcStr, 0, StarStrV); } TStr TStr::GetWcMatch(const TStr& WcStr, const int& StarStrN) const { TStrV StarStrV; if (IsWcMatch(WcStr, StarStrV)&&(StarStrV.Len()>=StarStrN)){ IAssert(StarStrN>=0); return StarStrV[StarStrV.Len()-StarStrN-1]; } else { return ""; } } TStr TStr::GetFPath() const { int ThisLen=Len(); const char* ThisBf=CStr(); int ChN=ThisLen-1; while ((ChN>=0)&&(ThisBf[ChN]!='/')&&(ThisBf[ChN]!='\\')){ChN--;} return GetSubStr(0, ChN); } TStr TStr::GetFBase() const { int ThisLen=Len(); const char* ThisBf=CStr(); int ChN=ThisLen-1; while ((ChN>=0)&&(ThisBf[ChN]!='/')&&(ThisBf[ChN]!='\\')){ChN--;} return GetSubStr(ChN+1, ThisLen); } TStr TStr::GetFMid() const { int ThisLen=Len(); const char* ThisBf=CStr(); int ChN=ThisLen-1; while ((ChN>=0)&&(ThisBf[ChN]!='/')&&(ThisBf[ChN]!='\\')&&(ThisBf[ChN]!='.')){ ChN--;} if (ChN<0){ return *this; } else { if (ThisBf[ChN]=='.'){ int EChN= --ChN; while ((ChN>=0)&&(ThisBf[ChN]!='/')&&(ThisBf[ChN]!='\\')){ChN--;} return GetSubStr(ChN+1, EChN); } else { return GetSubStr(ChN+1, ThisLen); } } } TStr TStr::GetFExt() const { int ThisLen=Len(); const char* ThisBf=CStr(); int ChN=ThisLen-1; while ((ChN>=0)&&(ThisBf[ChN]!='/')&&(ThisBf[ChN]!='\\')&& (ThisBf[ChN]!='.')){ChN--;} if ((ChN>=0)&&(ThisBf[ChN]=='.')){return GetSubStr(ChN, Len());} else {return TStr();} } TStr TStr::GetNrFPath(const TStr& FPath){ TChA NrFPath(FPath.Len()+4); NrFPath+=FPath; NrFPath.ChangeCh('\\', '/'); if (NrFPath.Empty()){NrFPath="./";} if ((NrFPath.Len()>=2)&&isalpha(NrFPath[0])&&(NrFPath[1]==':')){ if (NrFPath.Len()==2){NrFPath+="./";} if ((NrFPath[2]!='.')&&(NrFPath[2]!='/')){NrFPath.Ins(2, "./");} if (NrFPath[NrFPath.Len()-1]!='/'){NrFPath+="/";} } else { if ((NrFPath[0]!='.')&&(NrFPath[0]!='/')){NrFPath.Ins(0, "./");} if (NrFPath[NrFPath.Len()-1]!='/'){NrFPath+="/";} } return NrFPath; } TStr TStr::GetNrFMid(const TStr& FMid){ TChA NrFMid; int FMidLen=FMid.Len(); for (int ChN=0; ChN=3)&&isalpha(FPath[0])&&(FPath[1]==':')&& ((FPath[2]=='/')||(FPath[2]=='\\'))){ return true; } return false; } TStr TStr::PutFExt(const TStr& FNm, const TStr& FExt){ return FNm.GetFPath()+FNm.GetFMid()+FExt; } TStr TStr::PutFExtIfEmpty(const TStr& FNm, const TStr& FExt){ if (FNm.GetFExt().Empty()){ return FNm.GetFPath()+FNm.GetFMid()+FExt; } else { return FNm; } } TStr TStr::PutFBase(const TStr& FNm, const TStr& FBase){ return FNm.GetFPath()+FBase; } TStr TStr::PutFBaseIfEmpty(const TStr& FNm, const TStr& FBase){ if (FNm.GetFBase().Empty()){ return FNm.GetFPath()+FBase; } else { return FNm; } } TStr TStr::AddToFMid(const TStr& FNm, const TStr& ExtFMid){ return FNm.GetFPath()+FNm.GetFMid()+ExtFMid+FNm.GetFExt(); } TStr TStr::GetNumFNm(const TStr& FNm, const int& Num){ return FNm.GetFPath()+FNm.GetFMid()+TInt::GetStr(Num, "%03d")+FNm.GetFExt(); } TStr TStr::GetFNmStr(const TStr& Str, const bool& AlNumOnlyP){ TChA FNm=Str; for (int ChN=0; ChN= GrowBy && GrowBy > 0) newSize += GrowBy; else if (newSize > 0) newSize *= 2; else newSize = TInt::GetMn(GrowBy, 1024); } if (newSize > MxBfL) { Bf = (char *) realloc(Bf, newSize); IAssertR(Bf, TStr::Fmt("old Bf size: %u, new size: %u", MxBfL, newSize).CStr()); MxBfL = newSize; } IAssert(MxBfL >= _MxBfL); } TStrPool::TStrPool(uint MxBfLen, uint _GrowBy) : MxBfL(MxBfLen), BfL(0), GrowBy(_GrowBy), Bf(0) { //IAssert(MxBfL >= 0); IAssert(GrowBy >= 0); if (MxBfL > 0) { Bf = (char *) malloc(MxBfL); IAssert(Bf); } AddStr(""); // add empty string } TStrPool::TStrPool(TSIn& SIn, bool LoadCompact) : MxBfL(0), BfL(0), GrowBy(0), Bf(0) { SIn.Load(MxBfL); SIn.Load(BfL); SIn.Load(GrowBy); //IAssert(MxBfL >= BfL); IAssert(BfL >= 0); IAssert(GrowBy >= 0); if (LoadCompact) MxBfL = BfL; if (MxBfL > 0) { Bf = (char *) malloc(MxBfL); IAssert(Bf); } if (BfL > 0) SIn.LoadBf(Bf, BfL); SIn.LoadCs(); } void TStrPool::Save(TSOut& SOut) const { SOut.Save(MxBfL); SOut.Save(BfL); SOut.Save(GrowBy); SOut.SaveBf(Bf, BfL); SOut.SaveCs(); } TStrPool& TStrPool::operator = (const TStrPool& Pool) { if (this != &Pool) { GrowBy = Pool.GrowBy; MxBfL = Pool.MxBfL; BfL = Pool.BfL; if (Bf) free(Bf); else IAssert(MxBfL == 0); Bf = (char *) malloc(MxBfL); IAssert(Bf); memcpy(Bf, Pool.Bf, BfL); } return *this; } // Adds Len characters to pool. To append a null // terminated string Len must be equal to strlen(s) + 1 uint TStrPool::AddStr(const char *Str, uint Len) { IAssertR(Len > 0, "String too short (lenght includes the null character)"); //J: if (! Len) return -1; if (Len == 1 && BfL > 0) { return 0; } // empty string Assert(Str); Assert(Len > 0); if (BfL + Len > MxBfL) Resize(BfL + Len); memcpy(Bf + BfL, Str, Len); uint Pos = BfL; BfL += Len; return Pos; } int TStrPool::GetPrimHashCd(const char *CStr) { return TStrHashF_DJB::GetPrimHashCd(CStr); } int TStrPool::GetSecHashCd(const char *CStr) { return TStrHashF_DJB::GetSecHashCd(CStr); } ///////////////////////////////////////////////// // Void void TVoid::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); } void TVoid::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETag(Nm); } ///////////////////////////////////////////////// // Boolean const bool TBool::Mn=0; const bool TBool::Mx=1; const int TBool::Vals=TBool::Mx-TBool::Mn+1; TRnd TBool::Rnd; const TStr TBool::FalseStr="F"; const TStr TBool::TrueStr="T"; const TStr TBool::NStr="N"; const TStr TBool::YStr="Y"; const TStr TBool::NoStr="No"; const TStr TBool::YesStr="Yes"; void TBool::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); Val=TXmlObjSer::GetBoolArg(XmlTok, "Val"); } void TBool::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg(Nm, "Val", TBool::GetStr(Val)); } bool TBool::IsValStr(const TStr& Str){ TStr UcStr=Str.GetUc(); return (UcStr==FalseStr)||(UcStr==TrueStr)|| (UcStr==YStr)||(UcStr==NStr)|| (UcStr==YesStr)||(UcStr==NoStr); } bool TBool::GetValFromStr(const TStr& Str){ return (Str==TrueStr)||(Str==YStr)||(Str==YesStr); } bool TBool::GetValFromStr(const TStr& Str, const bool& DfVal){ TStr UcStr=Str.GetUc(); if (IsValStr(UcStr)){ return (UcStr==TrueStr)||(UcStr==YStr)||(UcStr==YesStr); } else { return DfVal; } } ///////////////////////////////////////////////// // Char const char TCh::Mn=CHAR_MIN; const char TCh::Mx=CHAR_MAX; const int TCh::Vals=int(TCh::Mx)-int(TCh::Mn)+1; const char TCh::NullCh=char(0); const char TCh::TabCh=char(9); const char TCh::LfCh=char(10); const char TCh::CrCh=char(13); const char TCh::EofCh=char(26); const char TCh::HashCh='#'; void TCh::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); Val=char(TXmlObjSer::GetIntArg(XmlTok, "Val")); } void TCh::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg(Nm, "Val", TInt::GetStr(Val)); } char TCh::GetUsFromYuAscii(const char& Ch){ switch (Ch){ case '~': return 'c'; case '^': return 'C'; case '{': return 's'; case '[': return 'S'; case '`': return 'z'; case '@': return 'Z'; case '|': return 'd'; case '\\': return 'D'; default: return Ch; } } ///////////////////////////////////////////////// // Unsigned-Char const uchar TUCh::Mn=0; const uchar TUCh::Mx=UCHAR_MAX; const int TUCh::Vals=int(TUCh::Mx)-int(TUCh::Mn)+1; void TUCh::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); Val=uchar(TXmlObjSer::GetIntArg(XmlTok, "Val")); } void TUCh::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg(Nm, "Val", TInt::GetStr(Val)); } ///////////////////////////////////////////////// // Integer const int TInt::Mn=INT_MIN; const int TInt::Mx=INT_MAX; const int TInt::Kilo=1024; const int TInt::Mega=1024*1024; const int TInt::Giga=1024*1024*1024; TRnd TInt::Rnd; void TInt::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); Val=TXmlObjSer::GetIntArg(XmlTok, "Val"); } void TInt::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg(Nm, "Val", TInt::GetStr(Val)); } TStr TInt::GetStr(const int& Val, const char* FmtStr){ if (FmtStr==NULL){ return GetStr(Val); } else { char Bf[255]; sprintf(Bf, FmtStr, Val); return TStr(Bf); } } //----------------------------------------------------------------------------- // Frugal integer serialization //----------------------------------------------------------------------------- // These routines serialize integers to sequences of 1..4 bytes, with smaller // integers receiving shorter codes. They do not work directly with streams // but rather with a user-provided buffer. It is expected that one will want // to store several such integers at once, and it would be inefficient to // call the virtual TSOut::PutCh method once for every byte; this is why // SaveFrugalInt and LoadFrugalInt work with a user-provided char* buffer // rather than with TSIn/TSOut. To store a vector of such integers, use the // SaveFrugalIntV/LoadFrugalIntV pair. char* TInt::SaveFrugalInt(char *pDest, int i){ // <0xxx xxxx> has 128 combinations and is used to store -1..126. // <1xxx xxxx> <00xx xxxx> has 2^13 = 8192 combinations and is used to store 127..8318. // <1xxx xxxx> <01xx xxxx> has 2^13 = 8192 combinations and is used to store -2..-8193. // <1xxx xxxx> <1xxx xxxx> <0xxx xxxx> has 2^29 = 536870912 combinations and is used to store 8319..536879230. // <1xxx xxxx> <1xxx xxxx> <1xxx xxxx> has 2^29 = 536870912 combinations and is used to store -8194..-536879105. i++; if (i >= 0 && i <= 127) { *pDest++ = char(i); return pDest; } if (i >= 128 && i < 128 + 8192) { i -= 128; *pDest++ = char(0x80 | (i & 0x7f)); *pDest++ = char((i >> 7) & 0x3f); return pDest; } if (i <= -1 && i > -1 - 8192) { i = -1 - i; *pDest++ = char(0x80 | (i & 0x7f)); *pDest++ = char(0x40 | ((i >> 7) & 0x3f)); return pDest; } if (i >= 128 + 8192 && i < 128 + 8192 + 536870912) { i -= 128 + 8192; *pDest++ = char(0x80 | (i & 0x7f)); *pDest++ = char(0x80 | ((i >> 7) & 0x7f)); *pDest++ = char((i >> 14) & 0xff); *pDest++ = char((i >> 22) & 0x7f); return pDest; } if (i <= -1 - 8192 && i > -1 - 8192 - 536870912) { i = (-1 - 8192) - i; *pDest++ = char(0x80 | (i & 0x7f)); *pDest++ = char(0x80 | ((i >> 7) & 0x7f)); *pDest++ = char((i >> 14) & 0xff); *pDest++ = char(0x80 | ((i >> 22) & 0x7f)); return pDest; } IAssertR(false, TInt::GetStr(i)); return 0; } char* TInt::LoadFrugalInt(char *pSrc, int& i){ i = 0; int ch = (int) ((unsigned char) (*pSrc++)); if ((ch & 0x80) == 0) { i = ch; i--; return pSrc; } i = (ch & 0x7f); ch = (int) ((unsigned char) (*pSrc++)); if ((ch & 0x80) == 0) { i |= (ch & 0x3f) << 7; if ((ch & 0x40) == 0) i += 128; else i = -1 - i; i--; return pSrc; } i |= (ch & 0x7f) << 7; ch = (int) ((unsigned char) (*pSrc++)); i |= ch << 14; ch = (int) ((unsigned char) (*pSrc++)); i |= (ch & 0x7f) << 22; if ((ch & 0x80) == 0) i += 128 + 8192; else i = (-1 - 8192) - i; i--; return pSrc; } // Tests the SaveFrugalInt/LoadFrugalInt combination on all the // integers they can work with (about 10^9 integers). void TInt::TestFrugalInt(){ char buf[10], *p = &buf[0], *r, *s; int i, j; #define __TEST(from, to, len) \ for (i = (from); i <= (to); i++) \ { if ((i & 0xffff) == 0) printf("%d\r", i); \ r = SaveFrugalInt(p, i); s = LoadFrugalInt(p, j); \ IAssert(r == s); IAssert(i == j); IAssert(r - p == len); } __TEST(-1, 126, 1); __TEST(127, 127 + 8191, 2); __TEST(-2 - 8191, -2, 2); __TEST(127 + 8192, 127 + 8191 + (1 << 29), 4); __TEST(-2 - 8191 - (1 << 29), -2 - 8192, 4); #undef __TEST } // Suppose that the contents of 'v', encoded using SaveFrugalInt, // occupy 'n' bytes. SaveFrugalIntV first stores 'n' (using // SaveFrugalInt), then the contents. void TInt::SaveFrugalIntV(TSOut& SOut, const TIntV& v){ // Prepare a large enough buffer. int count = v.Len(); char *buf = new char[4 * (count + 1)], *pStart, *pEnd; // Encode the contents of 'v'. pStart = buf + 4; pEnd = pStart; for (int i = 0; i < count; i++) pEnd = SaveFrugalInt(pEnd, v[i].Val); // Encode the size of the encoded contents of 'v'. // This is stored at the beginning of 'buf' and is then // moved so that there is no gap between it and the // beginning of the stored contents (at pStart). int size = int(pEnd - pStart); char *pSizeStart = buf; char *pSizeEnd = SaveFrugalInt(pSizeStart, size); while (pSizeEnd > pSizeStart) *(--pStart) = *(--pSizeEnd); // Write the buffer and free the memory. SOut.PutBf(pStart, TSize(pEnd - pStart)); delete[] buf; } // Loads an integer 'n' (using LoadFrugalInt), then loads // 'n' bytes, decoding them using LoadFrugalInt and adding // them to the vector 'v'. If clearVec is true, 'v' is // cleared before anything is added to it. void TInt::LoadFrugalIntV(TSIn& SIn, TIntV& v, bool clearVec){ if (clearVec) v.Clr(); char sizeBuf[4], *p, *pEnd; // Load the first frugally-stored integer into the sizeBuf // buffer. 'count' bytes will be read. sizeBuf[0] = SIn.GetCh(); int count = 1; if (sizeBuf[0] & 0x80) { sizeBuf[1] = SIn.GetCh(); count++; if (sizeBuf[1] & 0x80) { sizeBuf[2] = SIn.GetCh(); sizeBuf[3] = SIn.GetCh(); count += 2;} } // Decode the stored size. int size; pEnd = LoadFrugalInt(&sizeBuf[0], size); IAssert(pEnd - &sizeBuf[0] == count); if (size <= 0) return; // Allocate a buffer and read the compressed data. char *buf = new char[size]; SIn.GetBf(buf, size); // Decode the compressed integers and add them into 'v'. p = buf; pEnd = buf + size; while (p < pEnd) { int i; p = LoadFrugalInt(p, i); v.Add(i); } IAssert(p == pEnd); delete[] buf; } ///////////////////////////////////////////////// // Unsigned-Integer const uint TUInt::Mn=0; const uint TUInt::Mx=UINT_MAX; TRnd TUInt::Rnd; void TUInt::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); Val=TXmlObjSer::GetIntArg(XmlTok, "Val"); } void TUInt::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg(Nm, "Val", TInt::GetStr(Val)); } TStr TUInt::GetStr(const uint& Val, const char* FmtStr){ if (FmtStr==NULL){ return GetStr(Val); } else { char Bf[255]; sprintf(Bf, FmtStr, Val); return TStr(Bf); } } uint TUInt::GetUIntFromIpStr(const TStr& IpStr, const char& SplitCh) { TStrV IpStrV; IpStr.SplitOnAllCh(SplitCh, IpStrV); const uchar Ch1 = (uchar)IpStrV[0].GetInt(); const uchar Ch2 = (uchar)IpStrV[1].GetInt(); const uchar Ch3 = (uchar)IpStrV[2].GetInt(); const uchar Ch4 = (uchar)IpStrV[3].GetInt(); return uint((Ch1<<24) | (Ch2<<16) | (Ch3<<8) | (Ch4)); } TStr TUInt::GetStrFromIpUInt(const uint& Ip) { return TStr::Fmt("%d.%d.%d.%d", ((Ip>>24) & 0xFF), ((Ip>>16) & 0xFF), ((Ip>>8) & 0xFF), (Ip & 0xFF)); } ///////////////////////////////////////////////// // Unsigned-Integer-64Bit #if defined (GLib_WIN32) const TUInt64 TUInt64::Mn(uint64(0x0000000000000000i64)); const TUInt64 TUInt64::Mx(uint64(0xFFFFFFFFFFFFFFFFi64)); #elif defined (GLib_BCB) const TUInt64 TUInt64::Mn(0x0000000000000000i64); const TUInt64 TUInt64::Mx(0xFFFFFFFFFFFFFFFFi64); #else const TUInt64 TUInt64::Mn((uint64)0x0000000000000000LL); const TUInt64 TUInt64::Mx(0xFFFFFFFFFFFFFFFFLL); #endif void TUInt64::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); Val=TXmlObjSer::GetInt64Arg(XmlTok, "Val"); } void TUInt64::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg(Nm, "Val", TUInt64::GetStr(Val)); } /*///////////////////////////////////////////////// // Unsigned-Integer-64Bit const TUInt64 TUInt64::Mn(0, 0); const TUInt64 TUInt64::Mx(UINT_MAX, UINT_MAX); void TUInt64::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); XLoad(TInt(MsVal)); XLoad(TInt(LsVal)); } void TUInt64::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveHd(Nm); XSave(TInt(MsVal)); XSave(TInt(LsVal)); } TUInt64& TUInt64::operator+=(const TUInt64& Int){ uint CarryVal=(LsVal>TUInt::Mx-Int.LsVal) ? 1 : 0; LsVal+=Int.LsVal; MsVal+=Int.MsVal+CarryVal; return *this; } TUInt64& TUInt64::operator-=(const TUInt64& Int){ IAssert(*this>=Int); uint CarryVal; if (LsVal>=Int.LsVal){ LsVal-=Int.LsVal; CarryVal=0; } else { LsVal+=(TUInt::Mx-Int.LsVal)+1; CarryVal=1; } MsVal-=(Int.MsVal+CarryVal); return *this; } TUInt64 TUInt64::operator++(int){ if (LsVal==TUInt::Mx){ Assert(MsVal0); MsVal--; LsVal=TUInt::Mx;} else {LsVal--;} return *this; } TStr TUInt64::GetStr(const TUInt64& Int){ char Bf[255]; sprintf(Bf, "%.0Lf", ldouble(Int)); return TStr(Bf); } TStr TUInt64::GetHexStr(const TUInt64& Int){ char Bf[255]; sprintf(Bf, "%08X%08X", Int.MsVal, Int.LsVal); return TStr(Bf); }*/ ///////////////////////////////////////////////// // Float const double TFlt::Mn=-DBL_MAX; const double TFlt::Mx=+DBL_MAX; const double TFlt::NInf=-DBL_MAX; const double TFlt::PInf=+DBL_MAX; const double TFlt::Eps=1e-16; const double TFlt::EpsHalf =1e-7; TRnd TFlt::Rnd; void TFlt::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); Val=TXmlObjSer::GetFltArg(XmlTok, "Val"); } void TFlt::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg(Nm, "Val", TFlt::GetStr(Val)); } TStr TFlt::GetStr(const double& Val, const int& Width, const int& Prec){ char Bf[255]; if ((Width==-1)&&(Prec==-1)){sprintf(Bf, "%g", Val);} else {sprintf(Bf, "%*.*f", Width, Prec, Val);} return TStr(Bf); } TStr TFlt::GetStr(const double& Val, const char* FmtStr){ if (FmtStr==NULL){ return GetStr(Val); } else { char Bf[255]; sprintf(Bf, FmtStr, Val); return TStr(Bf); } } ///////////////////////////////////////////////// // Short-Float const sdouble TSFlt::Mn=-FLT_MIN; const sdouble TSFlt::Mx=+FLT_MAX; void TSFlt::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); Val=sdouble(TXmlObjSer::GetFltArg(XmlTok, "Val")); } void TSFlt::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg(Nm, "Val", TFlt::GetStr(Val)); } ///////////////////////////////////////////////// // Long-Float const ldouble TLFlt::Mn=-LDBL_MAX; const ldouble TLFlt::Mx=+LDBL_MAX; /*const ldouble TUInt64::Mn_LFlt=TUInt64::Mn; const ldouble TUInt64::Mx_LFlt=TUInt64::Mx; const ldouble TUInt64::MxP1_LFlt=ldouble(TUInt::Mx)+ldouble(1);*/ void TLFlt::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); Val=TXmlObjSer::GetFltArg(XmlTok, "Val"); } void TLFlt::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg(Nm, "Val", TFlt::GetStr(double(Val))); } TStr TLFlt::GetStr(const ldouble& Val, const int& Width, const int& Prec){ char Bf[255]; if ((Width==-1)&&(Prec==-1)){sprintf(Bf, "%Lg", Val);} else {sprintf(Bf, "%*.*Lf", Width, Prec, Val);} return TStr(Bf); } TStr TLFlt::GetStr(const ldouble& Val, const char* FmtStr){ if (FmtStr==NULL){ return GetStr(Val); } else { char Bf[255]; sprintf(Bf, FmtStr, Val); return TStr(Bf); } } ///////////////////////////////////////////////// // Float-Rectangle void TFltRect::LoadXml(const PXmlTok& XmlTok, const TStr& Nm){ XLoadHd(Nm); MnX=TXmlObjSer::GetFltArg(XmlTok, "MnX"); MnY=TXmlObjSer::GetFltArg(XmlTok, "MnY"); MxX=TXmlObjSer::GetFltArg(XmlTok, "MxX"); MxY=TXmlObjSer::GetFltArg(XmlTok, "MxY"); } void TFltRect::SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveBETagArg4(Nm, "MnX", TFlt::GetStr(double(MnX)), "MnY", TFlt::GetStr(double(MnY)), "MxX", TFlt::GetStr(double(MxX)), "MxY", TFlt::GetStr(double(MxY))); } bool TFltRect::Intersection(const TFltRect& Rect1, const TFltRect& Rect2){ const double MnXX = TFlt::GetMx(Rect1.GetMnX(), Rect2.GetMnX()); const double MnYY = TFlt::GetMx(Rect1.GetMnY(), Rect2.GetMnY()); const double MxXX = TFlt::GetMn(Rect1.GetMxX(), Rect2.GetMxX()); const double MxYY = TFlt::GetMn(Rect1.GetMxY(), Rect2.GetMxY()); return (MnXX < MxXX) && (MnYY < MxYY); } TStr TFltRect::GetStr() const { TChA ChA; ChA+='('; ChA+=TFlt::GetStr(MnX, "%0.2f"); ChA+=','; ChA+=TFlt::GetStr(MnY, "%0.2f"); ChA+=','; ChA+=TFlt::GetStr(MxX, "%0.2f"); ChA+=','; ChA+=TFlt::GetStr(MxY, "%0.2f"); ChA+=')'; return ChA; }