diff options
Diffstat (limited to 'lobject.c')
-rw-r--r-- | lobject.c | 87 |
1 files changed, 77 insertions, 10 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.c,v 2.43 2010/10/29 15:54:55 roberto Exp roberto $ | 2 | ** $Id: lobject.c,v 2.44 2010/12/06 21:08:36 roberto Exp roberto $ |
3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -106,20 +106,87 @@ lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { | |||
106 | } | 106 | } |
107 | 107 | ||
108 | 108 | ||
109 | static int checkend (const char *s, const char *e, const char *endptr) { | 109 | int luaO_hexavalue (int c) { |
110 | if (endptr == s) return 0; /* no characters converted */ | 110 | if (lisdigit(c)) return c - '0'; |
111 | while (lisspace(cast(unsigned char, *endptr))) endptr++; | 111 | else if (lisupper(c)) return c - 'A' + 10; |
112 | return (endptr == e); /* OK if no trailing characters */ | 112 | else return c - 'a' + 10; |
113 | } | 113 | } |
114 | 114 | ||
115 | 115 | ||
116 | #if !defined(lua_strx2number) | ||
117 | |||
118 | #include <math.h> | ||
119 | |||
120 | |||
121 | static int isneg (const char **s) { | ||
122 | if (**s == '-') { (*s)++; return 1; } | ||
123 | else if (**s == '+') (*s)++; | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | |||
128 | static lua_Number readhexa (const char **s, lua_Number r, int *count) { | ||
129 | while (lisxdigit(cast_uchar(**s))) { /* read integer part */ | ||
130 | r = (r * 16.0) + (double)luaO_hexavalue(*(*s)++); | ||
131 | (*count)++; | ||
132 | } | ||
133 | return r; | ||
134 | } | ||
135 | |||
136 | |||
137 | /* | ||
138 | ** convert an hexadecimal numeric string to a number, following | ||
139 | ** C99 specification for 'strtod' | ||
140 | */ | ||
141 | static lua_Number lua_strx2number (const char *s, char **endptr) { | ||
142 | lua_Number r = 0.0; | ||
143 | int e = 0, i = 0; | ||
144 | int neg = 0; /* 1 if number is negative */ | ||
145 | *endptr = cast(char *, s); /* nothing is valid yet */ | ||
146 | while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ | ||
147 | neg = isneg(&s); /* check signal */ | ||
148 | if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ | ||
149 | return 0.0; /* invalid format (no '0x') */ | ||
150 | s += 2; /* skip '0x' */ | ||
151 | r = readhexa(&s, r, &i); /* read integer part */ | ||
152 | if (*s == '.') { | ||
153 | s++; /* skip dot */ | ||
154 | r = readhexa(&s, r, &e); /* read fractional part */ | ||
155 | } | ||
156 | if (i == 0 && e == 0) | ||
157 | return 0.0; /* invalid format (no digit) */ | ||
158 | e *= -4; /* each fractional digit divides value by 2^-4 */ | ||
159 | *endptr = cast(char *, s); /* valid up to here */ | ||
160 | if (*s == 'p' || *s == 'P') { /* exponent part? */ | ||
161 | int exp1 = 0; | ||
162 | int neg1; | ||
163 | s++; /* skip 'p' */ | ||
164 | neg1 = isneg(&s); /* signal */ | ||
165 | if (!lisdigit(cast_uchar(*s))) | ||
166 | goto ret; /* must have at least one digit */ | ||
167 | while (lisdigit(cast_uchar(*s))) /* read exponent */ | ||
168 | exp1 = exp1 * 10 + *(s++) - '0'; | ||
169 | if (neg1) exp1 = -exp1; | ||
170 | e += exp1; | ||
171 | } | ||
172 | *endptr = cast(char *, s); /* valid up to here */ | ||
173 | ret: | ||
174 | if (neg) r = -r; | ||
175 | return ldexp(r, e); | ||
176 | } | ||
177 | |||
178 | #endif | ||
179 | |||
180 | |||
116 | int luaO_str2d (const char *s, size_t len, lua_Number *result) { | 181 | int luaO_str2d (const char *s, size_t len, lua_Number *result) { |
117 | char *endptr; | 182 | char *endptr; |
118 | const char *e = s + len; /* string 's' ends here */ | 183 | if (strpbrk(s, "xX")) /* hexa? */ |
119 | *result = lua_str2number(s, &endptr); | 184 | *result = lua_strx2number(s, &endptr); |
120 | if (checkend(s, e, endptr)) return 1; /* conversion OK? */ | 185 | else |
121 | *result = cast_num(strtoul(s, &endptr, 0)); /* try hexadecimal */ | 186 | *result = lua_str2number(s, &endptr); |
122 | return checkend(s, e, endptr); | 187 | if (endptr == s) return 0; /* nothing recognized */ |
188 | while (lisspace(cast_uchar(*endptr))) endptr++; | ||
189 | return (endptr == s + len); /* OK if no trailing characters */ | ||
123 | } | 190 | } |
124 | 191 | ||
125 | 192 | ||