📄 wytimespec_strnum.cpp
字号:
/* Copyright is licensed under GNU LGPL. by I.J.Wang 2003*/#define WYLIB_SOURCE#include "wytimespec.h"#include "wy__scanum.h"#include <cstdlib>// [Internal] Provide common functions for _strnum(WyTimeSpec&,..)//class Wy__P10 { public: static const size_t MaxP10=18; private: typedef signed long long value_type; // better able to hold all precision static const int GiDig10=WyTimeSpec::_GigaDigit10; static const value_type Giga=WY_CONST_GIGA; // 1x10^9 static const value_type p10tab[MaxP10+1]; public: // [Syn] Get power of 10 // // Note: use MaxP10 for limit of exp // // [Ret] 10^exp // inline static value_type p10(int exp) { return p10tab[exp]; }; // [Syn] Convert input number (taken as num/10^exp10) to // another representation, as follows: // // Let input_number= num/10^exp10, then upon returned, // res1= input_number/Giga // res2= input_number%Giga // // Note: result value less than 1/Giga is ignored // // [Ret] Ok // Wym_EBADMSG exp10>MaxP10+GiDig10 (for cooperate with _strnum) // Wym_ERANGE overflow occurred in operation // static WyRet norm_nano(value_type& res1, value_type& res2, value_type num, int exp10) { if((std::numeric_limits<value_type>::max()!= std::numeric_limits<long long>::max())|| (std::numeric_limits<value_type>::min()!= std::numeric_limits<long long>::min())) { WY_TERMINATE(""); // as lldiv_t is used, check for signed long long. } if(exp10<0) { if(exp10>=-GiDig10) { std::lldiv_t dt; WyRet r; value_type tmp; const size_t ddp=GiDig10+exp10; if(ddp>Wy__P10::MaxP10) { // assertion failed (GiDig10<Wy__P10::MaxP10) WY_THROW(WyRet(Wym_ERANGE)); } if((r=Wy::wy_mul(tmp,num,p10tab[ddp]))!=Ok) { WY_RETURN(r); } dt=std::lldiv(tmp,Giga); res1=dt.quot; res2=dt.rem; } else if(exp10>=-(int)MaxP10) { const size_t ddp=-exp10-GiDig10; std::lldiv_t dt; if(ddp>MaxP10) { WY_RETURN(Wym_EBADMSG); } dt=std::lldiv(num,p10tab[ddp]); res1=0; res2=dt.quot; // dt.rem ignored } else { res1=res2=0; } } else { WyRet r; value_type tmp; if(exp10>(int)MaxP10) { WY_RETURN(Wym_EBADMSG); } if((r=Wy::wy_mul(tmp,num,p10tab[exp10]))!=Ok) { WY_RETURN(r); } res1=tmp; res2=0; } return(Ok); };};const Wy__P10::value_type Wy__P10::p10tab[MaxP10+1]={ 1LL,10LL,100LL,1000LL,10000LL,100000LL,1000000LL, 10000000LL, // 10^0 - 10^7 100000000LL, // 10^8 1000000000LL, // 10^9 10000000000LL, // 10^10 100000000000LL, // 10^11 1000000000000LL, // 10^12 10000000000000LL, // 10^13 100000000000000LL, // 10^14 1000000000000000LL, // 10^15 10000000000000000LL, // 10^16 100000000000000000LL, // 10^17 1000000000000000000LL // 10^18};// S::= S1|S2|S3// S1::= [+-]ddd[<Exp>]// S2::= [+-].ddd[<Exp>]// S3::= [+-]ddd.[ddd][<Exp>]// Exp::= [Ee][+-]ddd//// Wym_EBADMSG failed processing string representation//WyRet Wy::_strnum(WyTimeSpec& res, const char** endptr, WyCSeg cseg){ typedef long long TmpInt; // better able to hold all precision const int Radix=10; TmpInt ll_sec; TmpInt ll_nsec; int exptv_nsec; const char* cptr; size_t clft; WyRet r( Wy::wy_strnum2(ll_sec,ll_nsec,exptv_nsec,&cptr,cseg.begin(),cseg.size()) ); // SRC_NUM= ll_sec + ll_nsec*10^exptv_nsec (exptv_nsec<=0) // if(r==Ok) { if(endptr!=0) { *endptr=cptr; } if((ll_sec>(TmpInt)std::numeric_limits<Wy_Second>::max())|| (ll_sec<(TmpInt)std::numeric_limits<Wy_Second>::min())) { WY_RETURN(Wym_ERANGE); } // normalize ll_nsec TmpInt tmp; if((r=Wy__P10::norm_nano(tmp, ll_nsec,ll_nsec,exptv_nsec))!=Ok) { WY_RETURN(r); } if(tmp!=0) { // assertion failed WY_THROW(WyRet(Wym_ERANGE)); } if((ll_nsec>=TmpInt(WY_CONST_GIGA))|| (ll_nsec<=-TmpInt(WY_CONST_GIGA))) { // assertion failed WY_THROW(WyRet(Wym_ERANGE)); } // S= [+-]ddd[.ddd] // = [+-]ddd. // = [+-].ddd WY_RETURN( res.reset(Wy_Second(ll_sec),Wy_Nano(ll_nsec)) ); } if(r!=Wym_EBADMSG) { if(endptr!=0) { *endptr=cptr; } WY_RETURN(r); } clft=cseg.size()-(cptr-cseg.begin()); if(clft<2) { if(endptr!=0) { *endptr=cptr; } WY_RETURN(Wym_EBADMSG); } if((*cptr!='e')&&(*cptr!='E')) { if(endptr!=0) { *endptr=cptr; } if((ll_sec>(TmpInt)std::numeric_limits<Wy_Second>::max())|| (ll_sec<(TmpInt)std::numeric_limits<Wy_Second>::min())) { WY_RETURN(Wym_ERANGE); } // normalize ll_nsec TmpInt tmp; if((r=Wy__P10::norm_nano(tmp, ll_nsec,ll_nsec,exptv_nsec))!=Ok) { WY_RETURN(r); } if(tmp!=0) { // assertion failed WY_THROW(WyRet(Wym_ERANGE)); } if((ll_nsec>=TmpInt(WY_CONST_GIGA))|| (ll_nsec<=-TmpInt(WY_CONST_GIGA))) { // assertion failed WY_THROW(WyRet(Wym_ERANGE)); } // S= [+-]ddd[.ddd] // = [+-]ddd. // = [+-].ddd if((r=res.reset(Wy_Second(ll_sec),Wy_Nano(ll_nsec)))!=Ok) { WY_RETURN(r); } WY_RETURN(Wym_EBADMSG); } const char* const ptr_exp(cptr); --clft; ++cptr; int tt_exp; r=Wy::_strnum(tt_exp,&cptr,WyCSeg(cptr,clft),Radix); const WyRet r_exp(r); if(r!=Ok) { if(endptr!=0) { *endptr=ptr_exp; } if((r==Wym_ERANGE)||(r==Wym_ENOENT)) do { // stop at ptr_exp if((ll_sec>(TmpInt)std::numeric_limits<Wy_Second>::max())|| (ll_sec<(TmpInt)std::numeric_limits<Wy_Second>::min())) { WY_RETURN(Wym_ERANGE); } // normalize ll_nsec TmpInt tmp; if((r=Wy__P10::norm_nano(tmp, ll_nsec,ll_nsec,exptv_nsec))!=Ok) { break; } if(tmp!=0) { // assertion failed WY_THROW(WyRet(Wym_ERANGE)); } if((ll_nsec>=TmpInt(WY_CONST_GIGA))|| (ll_nsec<=-TmpInt(WY_CONST_GIGA))) { // assertion failed WY_THROW(WyRet(Wym_ERANGE)); } // S= [+-]ddd[.ddd] // = [+-]ddd. // = [+-].ddd if((r=res.reset(Wy_Second(ll_sec),Wy_Nano(ll_nsec)))!=Ok) { WY_RETURN(r); } if(r_exp==Wym_ENOENT) { WY_RETURN( Wym_EBADMSG); } WY_RETURN( Wym_ERANGE ); } while(false); // FALLTHROW (Wym_EBADMSG) } if(endptr!=0) { *endptr=cptr; } // SRC_NUM= (ll_sec + ll_nsec*10^exptv_nsec)*10^tt_exp (exptv_nsec<=0) // if(tt_exp>=0) { if(tt_exp>(int)Wy__P10::MaxP10) { WY_RETURN(Wym_ERANGE); } TmpInt tmp; if((r=Wy::wy_mul(ll_sec,ll_sec,Wy__P10::p10(tt_exp)))!=Ok) { WY_RETURN(r); } if((r=Wy__P10::norm_nano(tmp,ll_nsec,ll_nsec,exptv_nsec+tt_exp))!=Ok) { WY_RETURN(r); } if((r=Wy::wy_add(ll_sec,ll_sec,tmp))!=Ok) { WY_RETURN(r); } if((ll_sec>(TmpInt)std::numeric_limits<Wy_Second>::max())|| (ll_sec<(TmpInt)std::numeric_limits<Wy_Second>::min())) { WY_RETURN(Wym_ERANGE); } if((r=res.reset(Wy_Second(ll_sec),Wy_Nano(ll_nsec)))!=Ok) { WY_RETURN(r); } WY_RETURN(r_exp); } else { const int tt_exp_abs=-tt_exp; TmpInt tmp; if(tt_exp_abs>(int)Wy__P10::MaxP10) { WY_RETURN(Wym_ERANGE); } std::lldiv_t dt=std::lldiv(ll_sec,Wy__P10::p10(tt_exp_abs)); ll_sec=dt.quot; { const int dpp=-exptv_nsec; if(dpp>(int)Wy__P10::MaxP10) { WY_RETURN(Wym_EBADMSG); } if((r=Wy::wy_mul(tmp,dt.rem,Wy__P10::p10(dpp)))!=Ok) { WY_RETURN(r); } } if((r=Wy::wy_add(tmp,tmp,ll_nsec))!=Ok) { WY_RETURN(r); } if((r=Wy__P10::norm_nano(tmp,ll_nsec,tmp,tt_exp+exptv_nsec))!=Ok) { WY_RETURN(r); } if((r=Wy::wy_add(ll_sec,ll_sec,tmp))!=Ok) { WY_RETURN(r); } if((ll_sec>(TmpInt)std::numeric_limits<Wy_Second>::max())|| (ll_sec<(TmpInt)std::numeric_limits<Wy_Second>::min())) { WY_RETURN(Wym_ERANGE); } if((r=res.reset(Wy_Second(ll_sec),Wy_Nano(ll_nsec)))!=Ok) { WY_RETURN(r); } WY_RETURN(r_exp); }};WyRet Wy::_strnum(WyTimeSpec& res, const char** endptr, WyCSeg cseg, const int& radix){ if((radix!=10)&&(radix!=0)) { WY_RETURN( Wym_EINVAL ); } return _strnum(res,endptr,cseg); };WyRet Wy::_strnum(WyTimeSpec& res, const char** endptr, WyCSeg cseg, int& radix){ if(radix!=10) { if(radix!=0) { WY_RETURN( Wym_EINVAL ); } radix=10; } return _strnum(res,endptr,cseg); };WyRet Wy::_scanum(WyTimeSpec& n, size_t& idx, const WyCSeg& text, const int& radix){ return wy__scanum(n,idx,text,radix); };WyRet Wy::_scanum(WyTimeSpec& n, size_t& idx, const WyCSeg& text){ return wy__scanum(n,idx,text,0); };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -