Browse Source

Fix parse_int with hexadecimal notation (#532)

* Fix parse_int with whitespace and hex number

- All whitespace is ignored before hex prefix
- '+' is also allowed before prefix for positive numbers
- Fix hexadecimals with trailing text
  - e.g. parse `0xABCZ` as `0xABC`, with trailing text. The majority of
    Haxe targets do this.

* Cleanup parse_float to match parse_int

No need to handle whitespace in parse_float, because the library
functions handle these already, and we don't need to check for
hexadecimal prefix.

* Use consts

* Remove unused len parameters of utoi and utod

* Cleanup overkill consts
tobil4sk 3 years ago
parent
commit
5d45c13691
4 changed files with 55 additions and 60 deletions
  1. 6 6
      src/hl.h
  2. 1 2
      src/profile.c
  3. 28 18
      src/std/bytes.c
  4. 20 34
      src/std/ucs2.c

+ 6 - 6
src/hl.h

@@ -224,8 +224,8 @@ typedef wchar_t	uchar;
 #	define ustrlen		wcslen
 #	define ustrdup		_wcsdup
 HL_API int uvszprintf( uchar *out, int out_size, const uchar *fmt, va_list arglist );
-#	define _utod(s,end)	wcstod(s,end)
-#	define _utoi(s,end)	wcstol(s,end,10)
+#	define utod(s,end)	wcstod(s,end)
+#	define utoi(s,end)	wcstol(s,end,10)
 #	define ucmp(a,b)	wcscmp(a,b)
 #	define utostr(out,size,str) wcstombs(out,str,size)
 #elif defined(HL_MAC)
@@ -250,9 +250,9 @@ typedef char16_t uchar;
 #endif
 
 C_FUNCTION_BEGIN
-HL_API double utod( const uchar *str, uchar **end );
-HL_API int utoi( const uchar *str, uchar **end );
 #ifndef HL_NATIVE_UCHAR_FUN
+HL_API double utod( const uchar *str, const uchar **end );
+HL_API int utoi( const uchar *str, const uchar **end );
 HL_API int ustrlen( const uchar *str );
 HL_API uchar *ustrdup( const uchar *str );
 HL_API int ucmp( const uchar *a, const uchar *b );
@@ -659,7 +659,7 @@ HL_API vdynamic *hl_dyn_call_safe( vclosure *c, vdynamic **args, int nargs, bool
 	so you are sure it's of the used typed. Otherwise use hl_dyn_call
 */
 #define hl_call0(ret,cl) \
-	(cl->hasValue ? ((ret(*)(vdynamic*))cl->fun)(cl->value) : ((ret(*)())cl->fun)()) 
+	(cl->hasValue ? ((ret(*)(vdynamic*))cl->fun)(cl->value) : ((ret(*)())cl->fun)())
 #define hl_call1(ret,cl,t,v) \
 	(cl->hasValue ? ((ret(*)(vdynamic*,t))cl->fun)(cl->value,v) : ((ret(*)(t))cl->fun)(v))
 #define hl_call2(ret,cl,t1,v1,t2,v2) \
@@ -923,7 +923,7 @@ typedef struct {
 
 HL_API hl_track_info hl_track;
 
-#else 
+#else
 
 #define hl_is_tracking(_) false
 #define hl_track_call(a,b)

+ 1 - 2
src/profile.c

@@ -433,7 +433,7 @@ static void profile_event( int code, vbyte *ptr, int dataLen ) {
 		break;
 	case -7:
 		{
-			uchar *end = NULL;
+			const uchar *end = NULL;
 			hl_profile_setup( ptr ? utoi((uchar*)ptr,&end) : 1000);
 		}
 		break;
@@ -456,4 +456,3 @@ static void profile_event( int code, vbyte *ptr, int dataLen ) {
 		break;
 	}
 }
-

+ 28 - 18
src/std/bytes.c

@@ -176,28 +176,35 @@ HL_PRIM void hl_bsort_f64( vbyte *bytes, int pos, int len, vclosure *cmp ) {
 	merge_sort_rec_f64(&m,0,len);
 }
 
+static inline bool is_space_char(uchar c) {
+	return c == 32 || (c > 8 && c < 14);
+}
+
 HL_PRIM double hl_parse_float( vbyte *bytes, int pos, int len ) {
-	uchar *str = (uchar*)(bytes+pos);
-	uchar *end = NULL;
-	double d;
-	while( *str == ' ' ) str++; 
-	d = utod(str,&end);
+	const uchar *str = (uchar*)(bytes+pos), *end = NULL;
+	while( is_space_char(*str) ) str++;
+	double d = utod(str,&end);
 	if( end == str )
 		return hl_nan();
 	return d;
 }
 
+static inline bool has_hex_prefix( const uchar *c, int len, bool is_signed ) {
+	if (is_signed)
+		return len >= 3 && c[1] == '0' && (c[2] == 'x' || c[2] == 'X');
+	return len >= 2 && c[0] == '0' && (c[1] == 'x' || c[1] == 'X');
+}
+
 HL_PRIM vdynamic *hl_parse_int( vbyte *bytes, int pos, int len ) {
-	uchar *c = (uchar*)(bytes + pos), *end = NULL;
+	const uchar *c = (uchar*)(bytes + pos);
+	const uchar *const start = c;
 	int h;
-	while( *c == ' ' ) {
-		c++;
-		len--;
-	}
-	if( (len >= 2 && c[0] == '0' && (c[1] == 'x' || c[1] == 'X')) || (len >= 3 && c[0] == '-' && c[1] == '0' && (c[2] == 'x' || c[2] == 'X')) ) {
-		bool neg = c[0] == '-';
+	while( is_space_char(*c) ) c++;
+	uchar sign = c[0];
+	bool is_signed = sign == '-' || sign == '+';
+	if( has_hex_prefix(c,len+start-c,is_signed) ) {
 		h = 0;
-		c += neg ? 3 : 2;
+		c += is_signed ? 3 : 2;
 		while( *c ) {
 			uchar k = *c++;
 			if( k >= '0' && k <= '9' )
@@ -207,13 +214,16 @@ HL_PRIM vdynamic *hl_parse_int( vbyte *bytes, int pos, int len ) {
 			else if( k >= 'a' && k <= 'f' )
 				h = (h << 4) | ((k - 'a') + 10);
 			else
-				return NULL;
+				break;
 		}
-		if( neg ) h = -h;
-		return hl_make_dyn(&h,&hlt_i32);
+		if( sign == '-' ) h = -h;
+	} else {
+		const uchar *end = NULL;
+		h = utoi(c,&end);
+		if( c == end )
+			return NULL;
 	}
-	h = utoi(c,&end);
-	return c == end ? NULL : hl_make_dyn(&h,&hlt_i32);
+	return hl_make_dyn(&h,&hlt_i32);
 }
 
 // pointer manipulation

+ 20 - 34
src/std/ucs2.c

@@ -22,23 +22,7 @@
 #include <hl.h>
 #include <stdarg.h>
 
-static bool is_space_char( uchar c ) {
-	return c > 8 && c < 14;
-}
-
-#ifdef HL_NATIVE_UCHAR_FUN
-
-HL_PRIM double utod( const uchar *str, uchar **end ) {
-	while( is_space_char(*str) ) str++;
-	return _utod(str,end);
-}
-
-HL_PRIM int utoi( const uchar *str, uchar **end ) {
-	while( is_space_char(*str) ) str++;
-	return _utoi(str,end);
-}
-
-#else
+#ifndef HL_NATIVE_UCHAR_FUN
 
 #ifdef HL_ANDROID
 #	include <android/log.h>
@@ -57,7 +41,7 @@ int ustrlen( const uchar *str ) {
 	return (int)(p - str);
 }
 
-int ustrlen_utf8( const uchar *str ) {
+static int ustrlen_utf8( const uchar *str ) {
 	int size = 0;
 	while(1) {
 		uchar c = *str++;
@@ -83,45 +67,47 @@ uchar *ustrdup( const uchar *str ) {
 	return d;
 }
 
-double utod( const uchar *str, uchar **end ) {
+double utod( const uchar *str, const uchar **end ) {
 	char buf[31];
 	char *bend;
+	double result;
 	int i = 0;
-	double v;
-	while( is_space_char(*str) ) str++;
 	while( i < 30 ) {
-		int c = *str++;
+		int c = str[i];
 		if( (c < '0' || c > '9') && c != '.' && c != 'e' && c != 'E' && c != '-' && c != '+' )
 			break;
 		buf[i++] = (char)c;
 	}
 	buf[i] = 0;
-	v = strtod(buf,&bend);
-	*end = (uchar*)(str - 1) + (bend - buf);
-	return v;
+	result = strtod(buf,&bend);
+	*end = str + (bend - buf);
+	return result;
 }
 
-int utoi( const uchar *str, uchar **end ) {
+int utoi( const uchar *str, const uchar **end ) {
 	char buf[17];
 	char *bend;
+	int result;
 	int i = 0;
-	int v;
-	while( is_space_char(*str) ) str++;
+	uchar sign = str[0];
+	if( sign == '-' || sign == '+' ) {
+		buf[i++] = (char)sign;
+	}
 	while( i < 16 ) {
-		int c = *str++;
-		if( (c < '0' || c > '9') && c != '-' && c != '+')
+		int c = str[i];
+		if( c < '0' || c > '9' )
 			break;
 		buf[i++] = (char)c;
 	}
 	buf[i] = 0;
-	v = strtol(buf,&bend,10);
-	*end = (uchar*)(str - 1) + (bend - buf);
-	return v;
+	result = strtol(buf,&bend,10);
+	*end = str + (bend - buf);
+	return result;
 }
 
 int ucmp( const uchar *a, const uchar *b ) {
 	while(true) {
-		int d = (unsigned)*a - (unsigned)*b; 
+		int d = (unsigned)*a - (unsigned)*b;
 		if( d ) return d;
 		if( !*a ) return 0;
 		a++;