more efficient str2num
This commit is contained in:
parent
fd7677f94f
commit
b25a1bc3f4
102
nasal.h
102
nasal.h
|
@ -26,92 +26,84 @@
|
|||
check if a string can be converted to a number
|
||||
if this string cannot be converted to a number,it will return nan
|
||||
*/
|
||||
inline double hex_to_double(std::string& str)
|
||||
|
||||
inline double hex_to_double(const char* str)
|
||||
{
|
||||
double ret=0;
|
||||
for(int i=2;str[i];++i)
|
||||
for(;*str;++str)
|
||||
{
|
||||
ret*=16;
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
ret+=(str[i]-'0');
|
||||
else if('a'<=str[i] && str[i]<='f')
|
||||
ret+=(str[i]-'a'+10);
|
||||
else if('A'<=str[i] && str[i]<='F')
|
||||
ret+=(str[i]-'A'+10);
|
||||
if('0'<=*str && *str<='9')
|
||||
ret+=(*str-'0');
|
||||
else if('a'<=*str && *str<='f')
|
||||
ret+=(*str-'a'+10);
|
||||
else if('A'<=*str && *str<='F')
|
||||
ret+=(*str-'A'+10);
|
||||
else
|
||||
return std::nan("");
|
||||
return nan("");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double oct_to_double(std::string& str)
|
||||
inline double oct_to_double(const char* str)
|
||||
{
|
||||
double ret=0;
|
||||
for(int i=2;str[i];++i)
|
||||
for(;*str;++str)
|
||||
{
|
||||
ret*=8;
|
||||
if('0'<=str[i] && str[i]<='8')
|
||||
ret+=(str[i]-'0');
|
||||
if('0'<=*str && *str<='8')
|
||||
ret+=(*str-'0');
|
||||
else
|
||||
return std::nan("");
|
||||
return nan("");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double dec_to_double(std::string& str,int len)
|
||||
inline double dec_to_double(const char* str)
|
||||
{
|
||||
double ret=0;
|
||||
int i=0;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len)
|
||||
ret=ret*10+(str[i++]-'0');
|
||||
if(i==len) return ret;
|
||||
if(str[i]!='.' && str[i]!='e' && str[i]!='E')
|
||||
return std::nan("");
|
||||
if(str[i]=='.')
|
||||
double ret=0,negative=1,num_pow=0;
|
||||
while('0'<=*str && *str<='9')
|
||||
ret=ret*10+(*str++-'0');
|
||||
if(!*str) return ret;
|
||||
if(*str=='.')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return std::nan("");
|
||||
double num_pow=0.1;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len)
|
||||
if(!*++str) return nan("");
|
||||
num_pow=0.1;
|
||||
while('0'<=*str && *str<='9')
|
||||
{
|
||||
ret+=num_pow*(str[i++]-'0');
|
||||
ret+=num_pow*(*str++-'0');
|
||||
num_pow*=0.1;
|
||||
}
|
||||
if(!*str) return ret;
|
||||
}
|
||||
if(i==len) return ret;
|
||||
if(str[i]!='e' && str[i]!='E')
|
||||
return std::nan("");
|
||||
++i;
|
||||
if(i==len) return std::nan("");
|
||||
double negative=(str[i]=='-'? -1:1);
|
||||
if(str[i]=='-' || str[i]=='+')
|
||||
++i;
|
||||
if(i==len) return std::nan("");
|
||||
double num_pow=0;
|
||||
for(;i<len;++i)
|
||||
if(*str!='e' && *str!='E')
|
||||
return nan("");
|
||||
if(!*++str) return nan("");
|
||||
if(*str=='-' || *str=='+')
|
||||
negative=(*str++=='-'? -1:1);
|
||||
if(!*str) return nan("");
|
||||
num_pow=0;
|
||||
for(;*str;++str)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
num_pow=num_pow*10+(str[i]-'0');
|
||||
if('0'<=*str && *str<='9')
|
||||
num_pow=num_pow*10+(*str-'0');
|
||||
else
|
||||
return std::nan("");
|
||||
return nan("");
|
||||
}
|
||||
return ret*std::pow(10,negative*num_pow);
|
||||
}
|
||||
double str2num(std::string str)
|
||||
double str2num(const char* str)
|
||||
{
|
||||
bool is_negative=false;
|
||||
int len=str.length();
|
||||
double ret_num=0;
|
||||
if(str[0]=='-' || str[0]=='+')
|
||||
{
|
||||
if(len==1) return std::nan("");
|
||||
is_negative=(str[0]=='-');
|
||||
str=str.substr(1,len--);
|
||||
}
|
||||
if(len>1 && str[0]=='0' && str[1]=='x')
|
||||
ret_num=hex_to_double(str);
|
||||
else if(len>1 && str[0]=='0' && str[1]=='o')
|
||||
ret_num=oct_to_double(str);
|
||||
if(*str=='-' || *str=='+')
|
||||
is_negative=(*str++=='-');
|
||||
if(!*str)
|
||||
return nan("");
|
||||
if(str[0]=='0' && str[1]=='x')
|
||||
ret_num=hex_to_double(str+2);
|
||||
else if(str[0]=='0' && str[1]=='o')
|
||||
ret_num=oct_to_double(str+2);
|
||||
else
|
||||
ret_num=dec_to_double(str,len);
|
||||
ret_num=dec_to_double(str);
|
||||
return is_negative?-ret_num:ret_num;
|
||||
}
|
||||
|
||||
|
|
32
nasal_gc.h
32
nasal_gc.h
|
@ -24,12 +24,9 @@ const int increment[vm_type_size]=
|
|||
8 // vm_hash
|
||||
};
|
||||
|
||||
struct nasal_vec; //24 bytes
|
||||
struct nasal_hash;//56 bytes
|
||||
struct nasal_func;//120 bytes
|
||||
struct nasal_val; // 16 bytes
|
||||
struct nasal_val;//declaration of nasal_val
|
||||
|
||||
struct nasal_vec
|
||||
struct nasal_vec// 24 bytes
|
||||
{
|
||||
std::vector<nasal_val*> elems;
|
||||
|
||||
|
@ -38,7 +35,7 @@ struct nasal_vec
|
|||
nasal_val** get_mem(int);
|
||||
};
|
||||
|
||||
struct nasal_hash
|
||||
struct nasal_hash// 56 bytes
|
||||
{
|
||||
std::unordered_map<std::string,nasal_val*> elems;
|
||||
|
||||
|
@ -47,20 +44,20 @@ struct nasal_hash
|
|||
nasal_val** get_mem(std::string&);
|
||||
};
|
||||
|
||||
struct nasal_func
|
||||
struct nasal_func// 120 bytes
|
||||
{
|
||||
int32_t dynpara;// dynamic parameter name index in hash
|
||||
uint32_t offset;
|
||||
uint32_t entry;
|
||||
std::vector<nasal_val*> default_para;
|
||||
int32_t dynpara;// dynamic parameter name index in hash
|
||||
uint32_t offset; // arguments will be loaded into local scope from this offset
|
||||
uint32_t entry; // pc will set to entry-1 to call this function
|
||||
std::vector<nasal_val*> default_para;// default value(nasal_val*)
|
||||
std::unordered_map<std::string,int> key_table;// parameter name hash
|
||||
std::vector<nasal_val*> closure;
|
||||
std::vector<nasal_val*> closure;// closure will be loaded to gc.local.back() as the local scope
|
||||
|
||||
nasal_func();
|
||||
void clear();
|
||||
};
|
||||
|
||||
struct nasal_val
|
||||
struct nasal_val// 16 bytes
|
||||
{
|
||||
#define GC_UNCOLLECTED 0
|
||||
#define GC_FOUND 1
|
||||
|
@ -76,7 +73,6 @@ struct nasal_val
|
|||
nasal_func* func;
|
||||
}ptr;
|
||||
|
||||
nasal_val();
|
||||
nasal_val(int);
|
||||
~nasal_val();
|
||||
double to_number();
|
||||
|
@ -203,12 +199,6 @@ void nasal_func::clear()
|
|||
}
|
||||
|
||||
/*functions of nasal_val*/
|
||||
nasal_val::nasal_val()
|
||||
{
|
||||
mark=GC_COLLECTED;
|
||||
type=vm_nil;
|
||||
return;
|
||||
}
|
||||
nasal_val::nasal_val(int val_type)
|
||||
{
|
||||
mark=GC_COLLECTED;
|
||||
|
@ -238,7 +228,7 @@ nasal_val::~nasal_val()
|
|||
double nasal_val::to_number()
|
||||
{
|
||||
if(type==vm_str)
|
||||
return str2num(*ptr.str);
|
||||
return str2num(ptr.str->c_str());
|
||||
return ptr.num;
|
||||
}
|
||||
std::string nasal_val::to_string()
|
||||
|
|
|
@ -315,7 +315,7 @@ nasal_ast nasal_parse::nil_gen()
|
|||
nasal_ast nasal_parse::num_gen()
|
||||
{
|
||||
nasal_ast node(tok_list[ptr].line,ast_num);
|
||||
node.set_num(str2num(tok_list[ptr].str));
|
||||
node.set_num(str2num(tok_list[ptr].str.c_str()));
|
||||
return node;
|
||||
}
|
||||
nasal_ast nasal_parse::str_gen()
|
||||
|
|
|
@ -135,7 +135,7 @@ bool nasal_vm::condition(nasal_val* val_addr)
|
|||
else if(type==vm_str)
|
||||
{
|
||||
std::string& str=*val_addr->ptr.str;
|
||||
double number=str2num(str);
|
||||
double number=str2num(str.c_str());
|
||||
if(std::isnan(number))
|
||||
return !str.empty();
|
||||
return number;
|
||||
|
@ -267,7 +267,7 @@ void nasal_vm::opr_unot()
|
|||
new_val=val->ptr.num?gc.zero_addr:gc.one_addr;
|
||||
else if(type==vm_str)
|
||||
{
|
||||
double number=str2num(*val->ptr.str);
|
||||
double number=str2num(val->ptr.str->c_str());
|
||||
if(std::isnan(number))
|
||||
new_val=val->ptr.str->empty()?gc.one_addr:gc.zero_addr;
|
||||
else
|
||||
|
@ -752,7 +752,7 @@ void nasal_vm::opr_slc()
|
|||
switch(val->type)
|
||||
{
|
||||
case vm_num:num=val->ptr.num;break;
|
||||
case vm_str:num=str2num(*val->ptr.str);break;
|
||||
case vm_str:num=str2num(val->ptr.str->c_str());break;
|
||||
default:die("slc: error value type");break;
|
||||
}
|
||||
nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num);
|
||||
|
@ -819,7 +819,7 @@ void nasal_vm::opr_mcallv()
|
|||
switch(val->type)
|
||||
{
|
||||
case vm_num:num=(int)val->ptr.num;break;
|
||||
case vm_str:num=(int)str2num(*val->ptr.str);break;
|
||||
case vm_str:num=(int)str2num(val->ptr.str->c_str());break;
|
||||
default:die("mcallv: error value type");break;
|
||||
}
|
||||
nasal_val** res=(*vec_addr)->ptr.vec->get_mem(num);
|
||||
|
|
Loading…
Reference in New Issue