Преглед на файлове

vsnprintf: Added more unit tests.

Branimir Karadžić преди 8 години
родител
ревизия
71cc735785
променени са 6 файла, в които са добавени 75 реда и са изтрити 26 реда
  1. 6 0
      include/bx/string.h
  2. 27 12
      src/crt.cpp
  3. 13 13
      src/dtoa.cpp
  4. 20 0
      src/string.cpp
  5. 1 1
      tests/string_test.cpp
  6. 8 0
      tests/vsnprintf_test.cpp

+ 6 - 0
include/bx/string.h

@@ -110,9 +110,15 @@ namespace bx
 	///
 	char toLower(char _ch);
 
+	///
+	void toLower(char* _inOutStr, size_t _max = INT32_MAX);
+
 	///
 	char toUpper(char _ch);
 
+	///
+	void toUpper(char* _inOutStr, size_t _max = INT32_MAX);
+
 	///
 	bool toBool(const char* _str);
 

+ 27 - 12
src/crt.cpp

@@ -286,22 +286,30 @@ namespace bx
 				return 0;
 			}
 
+			if (_param.upper)
+			{
+				toUpper(str, len);
+			}
+
 			const char* dot = strnchr(str, '.');
-			const int32_t precLen = int32_t(
-					  dot
-					+ uint32_min(_param.prec + _param.spec, 1)
-					+ _param.prec
-					- str
-					);
-			if (precLen > len)
+			if (NULL != dot)
 			{
-				for (int32_t ii = len; ii < precLen; ++ii)
+				const int32_t precLen = int32_t(
+						dot
+						+ uint32_min(_param.prec + _param.spec, 1)
+						+ _param.prec
+						- str
+						);
+				if (precLen > len)
 				{
-					str[ii] = '0';
+					for (int32_t ii = len; ii < precLen; ++ii)
+					{
+						str[ii] = '0';
+					}
+					str[precLen] = '\0';
 				}
-				str[precLen] = '\0';
+				len = precLen;
 			}
-			len = precLen;
 
 			return write(_writer, str, len, _param, _err);
 		}
@@ -440,9 +448,15 @@ namespace bx
 							{
 								case 'h': param.bits = sizeof(signed char  )*8; break;
 								case 'l': param.bits = sizeof(long long int)*8; break;
+								case '3':
 								case '6':
 									read(&reader, ch);
-									if ('4' == ch) { param.bits = sizeof(int64_t)*8; }
+									switch (ch)
+									{
+										case '2': param.bits = sizeof(int32_t)*8; break;
+										case '4': param.bits = sizeof(int64_t)*8; break;
+										default: break;
+									}
 									break;
 
 								default: seek(&reader, -1); break;
@@ -484,6 +498,7 @@ namespace bx
 						break;
 
 					case 'f':
+						param.upper = isUpper(ch);
 						size += write(_writer, va_arg(_argList, double), param, _err);
 						break;
 

+ 13 - 13
src/dtoa.cpp

@@ -424,34 +424,34 @@ namespace bx
 		return length + 2 + exp;
 	}
 
-	int32_t toString(char* _dst, size_t _max, double value)
+	int32_t toString(char* _dst, size_t _max, double _value)
 	{
-		if (isNan(value) )
+		int32_t sign = 0 != (doubleToBits(_value) & (UINT64_C(1)<<63) ) ? 1 : 0;
+		if (1 == sign)
 		{
-			return (int32_t)strlncpy(_dst, _max, "NaN");
+			*_dst++ = '-';
+			--_max;
+			_value = -_value;
 		}
-		else if (isInfinite(value) )
+
+		if (isNan(_value) )
 		{
-			return (int32_t)strlncpy(_dst, _max, "Inf");
+			return (int32_t)strlncpy(_dst, _max, "nan") + sign;
 		}
-
-		int32_t sign = 0.0 > value ? 1 : 0;
-		if (1 == sign)
+		else if (isInfinite(_value) )
 		{
-			*_dst++ = '-';
-			--_max;
-			value = -value;
+			return (int32_t)strlncpy(_dst, _max, "inf") + sign;
 		}
 
 		int32_t len;
-		if (0.0 == value)
+		if (0.0 == _value)
 		{
 			len = (int32_t)strlncpy(_dst, _max, "0.0");
 		}
 		else
 		{
 			int32_t kk;
-			Grisu2(value, _dst, &len, &kk);
+			Grisu2(_value, _dst, &len, &kk);
 			len = Prettify(_dst, len, kk);
 		}
 

+ 20 - 0
src/string.cpp

@@ -60,11 +60,31 @@ namespace bx
 		return _ch + (isUpper(_ch) ? 0x20 : 0);
 	}
 
+	void toLower(char* _inOutStr, size_t _max)
+	{
+		size_t len = strnlen(_inOutStr, _max);
+
+		for (size_t ii = 0; ii < len; ++ii)
+		{
+			*_inOutStr = toLower(*_inOutStr);
+		}
+	}
+
 	char toUpper(char _ch)
 	{
 		return _ch - (isLower(_ch) ? 0x20 : 0);
 	}
 
+	void toUpper(char* _inOutStr, size_t _max)
+	{
+		size_t len = strnlen(_inOutStr, _max);
+
+		for (size_t ii = 0; ii < len; ++ii)
+		{
+			*_inOutStr = toUpper(*_inOutStr);
+		}
+	}
+
 	bool toBool(const char* _str)
 	{
 		char ch = toLower(_str[0]);

+ 1 - 1
tests/string_test.cpp

@@ -152,7 +152,7 @@ TEST_CASE("toString int32_t/uint32_t", "")
 TEST_CASE("toString double", "")
 {
 	REQUIRE(testToString(0.0,                     "0.0") );
-	REQUIRE(testToString(-0.0,                    "0.0") );
+	REQUIRE(testToString(-0.0,                    "-0.0") );
 	REQUIRE(testToString(1.0,                     "1.0") );
 	REQUIRE(testToString(-1.0,                    "-1.0") );
 	REQUIRE(testToString(1.2345,                  "1.2345") );

+ 8 - 0
tests/vsnprintf_test.cpp

@@ -6,6 +6,7 @@
 #include "test.h"
 #include <bx/string.h>
 #include <inttypes.h>
+#include <float.h>
 
 TEST_CASE("vsnprintf NULL buffer", "No output buffer provided.")
 {
@@ -52,6 +53,13 @@ TEST_CASE("vsnprintf f", "")
 	REQUIRE(test("  13.370", "%*.*f", 8, 3, 13.37) );
 	REQUIRE(test("13.370  ", "%-8.3f", 13.37) );
 	REQUIRE(test("13.370  ", "%*.*f", -8, 3, 13.37) );
+
+	REQUIRE(test("nan     ", "%-8f",  NAN) );
+	REQUIRE(test("     nan", "%8f",   NAN) );
+	REQUIRE(test("-NAN    ", "%-8F", -NAN) );
+	REQUIRE(test("     inf", "%8f",   INFINITY) );
+	REQUIRE(test("inf     ", "%-8f",  INFINITY) );
+	REQUIRE(test("    -INF", "%8F",  -INFINITY) );
 }
 
 TEST_CASE("vsnprintf d/i/o/u/x", "")