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