1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

Improved double ToString

This commit is contained in:
Brian Fiete 2022-08-25 12:32:51 -07:00
parent 5dfe300599
commit cb13198609

View file

@ -28,7 +28,7 @@
#ifdef _MSC_VER #ifdef _MSC_VER
#include <intrin.h> #include <intrin.h>
#pragma intrinsic(_ReturnAddress) #pragma intrinsic(_ReturnAddress)
#define BF_RETURN_ADDRESS _ReturnAddress() #define BF_RETURN_ADDRESS _ReturnAddress()
#else #else
#define BF_RETURN_ADDRESS __builtin_return_address(0) #define BF_RETURN_ADDRESS __builtin_return_address(0)
@ -49,7 +49,7 @@
#include <io.h> #include <io.h>
#endif #endif
USING_NS_BF; USING_NS_BF;
static Beefy::StringT<0> gCmdLineString; static Beefy::StringT<0> gCmdLineString;
bf::System::Runtime::BfRtCallbacks gBfRtCallbacks; bf::System::Runtime::BfRtCallbacks gBfRtCallbacks;
@ -76,7 +76,7 @@ namespace bf
class Exception; class Exception;
//System::Threading::Thread* gMainThread; //System::Threading::Thread* gMainThread;
class Internal class Internal
{ {
private: private:
@ -90,7 +90,7 @@ namespace bf
BFRT_EXPORT static Object* UnsafeCastToObject(void* inPtr); BFRT_EXPORT static Object* UnsafeCastToObject(void* inPtr);
BFRT_EXPORT static void* UnsafeCastToPtr(Object* obj); BFRT_EXPORT static void* UnsafeCastToPtr(Object* obj);
BFRT_EXPORT static void ObjectDynCheck(Object* object, int typeId, bool allowNull); BFRT_EXPORT static void ObjectDynCheck(Object* object, int typeId, bool allowNull);
BFRT_EXPORT static void ObjectDynCheckFailed(Object* object, int typeId); BFRT_EXPORT static void ObjectDynCheckFailed(Object* object, int typeId);
BFRT_EXPORT static void ThrowIndexOutOfRange(intptr stackOffset); BFRT_EXPORT static void ThrowIndexOutOfRange(intptr stackOffset);
BFRT_EXPORT static void ThrowObjectNotInitialized(intptr stackOffset); BFRT_EXPORT static void ThrowObjectNotInitialized(intptr stackOffset);
BFRT_EXPORT static void FatalError(String* error, intptr stackOffset = 0); BFRT_EXPORT static void FatalError(String* error, intptr stackOffset = 0);
@ -110,7 +110,7 @@ namespace bf
BFRT_EXPORT static char* GetCommandLineArgs(); BFRT_EXPORT static char* GetCommandLineArgs();
BFRT_EXPORT static void BfLog(char* str); BFRT_EXPORT static void BfLog(char* str);
BFRT_EXPORT static void ProfilerCmd(char* str); BFRT_EXPORT static void ProfilerCmd(char* str);
BFRT_EXPORT static void ReportMemory(); BFRT_EXPORT static void ReportMemory();
private: private:
BFRT_EXPORT static void Test_Init(char* testData); BFRT_EXPORT static void Test_Init(char* testData);
@ -118,7 +118,7 @@ namespace bf
BFRT_EXPORT static void Test_Write(char* str); BFRT_EXPORT static void Test_Write(char* str);
BFRT_EXPORT static int32 Test_Query(); BFRT_EXPORT static int32 Test_Query();
BFRT_EXPORT static void Test_Finish(); BFRT_EXPORT static void Test_Finish();
}; };
namespace IO namespace IO
{ {
@ -145,7 +145,7 @@ namespace bf
enum ContractFailureKind : uint8 enum ContractFailureKind : uint8
{ {
ContractFailureKind_Precondition, ContractFailureKind_Precondition,
//[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")] //[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")]
ContractFailureKind_Postcondition, ContractFailureKind_Postcondition,
//[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")] //[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")]
ContractFailureKind_PostconditionOnException, ContractFailureKind_PostconditionOnException,
@ -162,7 +162,7 @@ namespace bf
class Debug class Debug
{ {
private: private:
BFRT_EXPORT static void Write(char* str, intptr strLen); BFRT_EXPORT static void Write(char* str, intptr strLen);
}; };
} }
@ -233,7 +233,7 @@ static void Internal_FatalError(const char* error)
TestString(str); TestString(str);
Beefy::String result; Beefy::String result;
TestReadCmd(result); TestReadCmd(result);
exit(1); exit(1);
} }
else else
@ -313,15 +313,15 @@ void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
if (version != BFRT_VERSION) if (version != BFRT_VERSION)
{ {
BfpSystem_FatalError(StrFormat("BeefRT build version '%d' does not match requested version '%d'", BFRT_VERSION, version).c_str(), "BEEF FATAL ERROR"); BfpSystem_FatalError(StrFormat("BeefRT build version '%d' does not match requested version '%d'", BFRT_VERSION, version).c_str(), "BEEF FATAL ERROR");
} }
gBfRtCallbacks = *callbacks; gBfRtCallbacks = *callbacks;
gBfRtFlags = (BfRtFlags)flags; gBfRtFlags = (BfRtFlags)flags;
Beefy::String cmdLine; Beefy::String cmdLine;
BfpSystemResult result; BfpSystemResult result;
BFP_GETSTR_HELPER(cmdLine, result, BfpSystem_GetCommandLine(__STR, __STRLEN, &result)); BFP_GETSTR_HELPER(cmdLine, result, BfpSystem_GetCommandLine(__STR, __STRLEN, &result));
char* cmdLineStr = (char*)cmdLine.c_str(); char* cmdLineStr = (char*)cmdLine.c_str();
@ -356,8 +356,8 @@ void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
gCmdLineString = useCmdLineStr; gCmdLineString = useCmdLineStr;
#ifdef BF_PLATFORM_WINDOWS #ifdef BF_PLATFORM_WINDOWS
gBfTLSKey = FlsAlloc(TlsFreeFunc); gBfTLSKey = FlsAlloc(TlsFreeFunc);
#else #else
pthread_key_create(&gBfTLSKey, TlsFreeFunc); pthread_key_create(&gBfTLSKey, TlsFreeFunc);
#endif #endif
} }
@ -383,7 +383,7 @@ void Internal::Shutdown()
{ {
BfInternalThread::WaitForAllDone(); BfInternalThread::WaitForAllDone();
if (gBfRtCallbacks.GC_Shutdown != NULL) if (gBfRtCallbacks.GC_Shutdown != NULL)
gBfRtCallbacks.GC_Shutdown(); gBfRtCallbacks.GC_Shutdown();
BfpSystem_Shutdown(); BfpSystem_Shutdown();
} }
@ -394,17 +394,17 @@ void Internal::BfStaticCtor()
void Internal::__BfStaticCtor() void Internal::__BfStaticCtor()
{ {
} }
void Internal::BfStaticDtor() void Internal::BfStaticDtor()
{ {
} }
void Internal::__BfStaticDtor() void Internal::__BfStaticDtor()
{ {
} }
Object* Internal::UnsafeCastToObject(void* inPtr) Object* Internal::UnsafeCastToObject(void* inPtr)
@ -427,7 +427,7 @@ void Internal::ThrowIndexOutOfRange(intptr stackOffset)
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();
} }
Beefy::String str = ":TestFail\tIndex out of range\n"; Beefy::String str = ":TestFail\tIndex out of range\n";
TestString(str); TestString(str);
exit(1); exit(1);
} }
@ -437,7 +437,7 @@ void Internal::ThrowIndexOutOfRange(intptr stackOffset)
SETUP_ERROR("Index out of range", (int)(2 + stackOffset)); SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();
} }
Internal_FatalError("Index out of range"); Internal_FatalError("Index out of range");
} }
@ -466,7 +466,7 @@ void Internal::ThrowObjectNotInitialized(intptr stackOffset)
} }
void Internal::FatalError(bf::System::String* error, intptr stackOffset) void Internal::FatalError(bf::System::String* error, intptr stackOffset)
{ {
if (gClientPipe != NULL) if (gClientPipe != NULL)
{ {
if (gTestBreakOnFailure) if (gTestBreakOnFailure)
@ -482,11 +482,11 @@ void Internal::FatalError(bf::System::String* error, intptr stackOffset)
TestString(str); TestString(str);
exit(1); exit(1);
} }
if ((stackOffset != -1) && (::IsDebuggerPresent())) if ((stackOffset != -1) && (::IsDebuggerPresent()))
{ {
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset)); SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();
} }
Internal_FatalError(error->CStr()); Internal_FatalError(error->CStr());
@ -624,22 +624,22 @@ void* Internal::GetSharedProcAddress(void* libHandle, char* procName)
} }
void Internal::GetSharedProcAddressInto(void* libHandle, char* procName, void** procDest) void Internal::GetSharedProcAddressInto(void* libHandle, char* procName, void** procDest)
{ {
*procDest = GetSharedProcAddress(libHandle, procName); *procDest = GetSharedProcAddress(libHandle, procName);
} }
char* Internal::GetCommandLineArgs() char* Internal::GetCommandLineArgs()
{ {
return (char*)gCmdLineString.c_str(); return (char*)gCmdLineString.c_str();
} }
void Internal::BfLog(char* str) void Internal::BfLog(char* str)
{ {
// static int lineNum = 0; // static int lineNum = 0;
// lineNum++; // lineNum++;
// //
// static FILE* fp = fopen("dbg_internal.txt", "wb"); // static FILE* fp = fopen("dbg_internal.txt", "wb");
// //
// Beefy::String aResult = StrFormat("%d ", lineNum) + str; // Beefy::String aResult = StrFormat("%d ", lineNum) + str;
// fwrite(aResult.c_str(), 1, aResult.length(), fp); // fwrite(aResult.c_str(), 1, aResult.length(), fp);
// fflush(fp); // fflush(fp);
@ -651,7 +651,7 @@ void Internal::ProfilerCmd(char* str)
return; return;
gBfRtCallbacks.DebugMessageData_SetupProfilerCmd(str); gBfRtCallbacks.DebugMessageData_SetupProfilerCmd(str);
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();
} }
void Internal::ReportMemory() void Internal::ReportMemory()
@ -694,7 +694,7 @@ static void TestReadCmd(Beefy::String& str)
{ {
BF_FATAL("Failed to read pipe to test manager"); BF_FATAL("Failed to read pipe to test manager");
} }
} }
} }
void Internal::Test_Init(char* testData) void Internal::Test_Init(char* testData)
@ -702,7 +702,7 @@ void Internal::Test_Init(char* testData)
BfpSystem_SetCrashReportKind(BfpCrashReportKind_None); BfpSystem_SetCrashReportKind(BfpCrashReportKind_None);
Beefy::String args = GetCommandLineArgs(); Beefy::String args = GetCommandLineArgs();
BfpFileResult fileResult; BfpFileResult fileResult;
gClientPipe = BfpFile_Create(args.c_str(), BfpFileCreateKind_OpenExisting, (BfpFileCreateFlags)(BfpFileCreateFlag_Read | BfpFileCreateFlag_Write | BfpFileCreateFlag_Pipe), BfpFileAttribute_None, &fileResult); gClientPipe = BfpFile_Create(args.c_str(), BfpFileCreateKind_OpenExisting, (BfpFileCreateFlags)(BfpFileCreateFlag_Read | BfpFileCreateFlag_Write | BfpFileCreateFlag_Pipe), BfpFileAttribute_None, &fileResult);
if (fileResult != BfpFileResult_Ok) if (fileResult != BfpFileResult_Ok)
@ -749,18 +749,18 @@ void Internal::Test_Write(char* strPtr)
} }
int32 Internal::Test_Query() int32 Internal::Test_Query()
{ {
if (gTestMethodIdx != -1) if (gTestMethodIdx != -1)
{ {
uint32 tickEnd = BfpSystem_TickCount(); uint32 tickEnd = BfpSystem_TickCount();
TestString(StrFormat(":TestResult\t%d\n", tickEnd - gTestStartTick)); TestString(StrFormat(":TestResult\t%d\n", tickEnd - gTestStartTick));
} }
TestString(":TestQuery\n"); TestString(":TestQuery\n");
Beefy::String result; Beefy::String result;
TestReadCmd(result); TestReadCmd(result);
Beefy::String param; Beefy::String param;
int tabPos = (int)result.IndexOf('\t'); int tabPos = (int)result.IndexOf('\t');
if (tabPos != -1) if (tabPos != -1)
@ -793,8 +793,8 @@ int32 Internal::Test_Query()
printf("Command Str: %s\n", result.c_str()); printf("Command Str: %s\n", result.c_str());
BF_FATAL("Invalid test command string from test manager"); BF_FATAL("Invalid test command string from test manager");
} }
return false; return false;
} }
void Internal::Test_Finish() void Internal::Test_Finish()
@ -826,7 +826,7 @@ struct PendingAllocState
{ {
if ((mStackTraceCount > 255) || (mMetadataBytes > 255)) if ((mStackTraceCount > 255) || (mMetadataBytes > 255))
return false; return false;
const intptr maxSmallObjectSize = ((intptr)1 << ((sizeof(intptr) - 2) * 8)) - 1; const intptr maxSmallObjectSize = ((intptr)1 << ((sizeof(intptr) - 2) * 8)) - 1;
if (curAllocBytes <= maxSmallObjectSize) if (curAllocBytes <= maxSmallObjectSize)
return true; return true;
@ -844,7 +844,7 @@ void Internal::ObjectDynCheck(bf::System::Object* object, int typeId, bool allow
if (allowNull) if (allowNull)
return; return;
SETUP_ERROR("Attempting unboxing on null object", 1); SETUP_ERROR("Attempting unboxing on null object", 1);
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();
gBfRtCallbacks.DebugMessageData_Fatal(); gBfRtCallbacks.DebugMessageData_Fatal();
return; return;
} }
@ -862,21 +862,21 @@ void Internal::ObjectDynCheck(bf::System::Object* object, int typeId, bool allow
} }
void Internal::ObjectDynCheckFailed(bf::System::Object* object, int typeId) void Internal::ObjectDynCheckFailed(bf::System::Object* object, int typeId)
{ {
if (object == NULL) if (object == NULL)
{ {
SETUP_ERROR("Attempting unboxing on null object", 1); SETUP_ERROR("Attempting unboxing on null object", 1);
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();
gBfRtCallbacks.DebugMessageData_Fatal(); gBfRtCallbacks.DebugMessageData_Fatal();
return; return;
} }
Beefy::String errorStr = "Attempting invalid cast on object"; Beefy::String errorStr = "Attempting invalid cast on object";
errorStr += StrFormat("\x1LEAK\t0x%@\n (%s)0x%@\n", object, "System.Object", object); errorStr += StrFormat("\x1LEAK\t0x%@\n (%s)0x%@\n", object, "System.Object", object);
SETUP_ERROR(errorStr.c_str(), 2); SETUP_ERROR(errorStr.c_str(), 2);
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();
gBfRtCallbacks.DebugMessageData_Fatal(); gBfRtCallbacks.DebugMessageData_Fatal();
} }
extern "C" BFRT_EXPORT int PrintF(const char* fmt, ...) extern "C" BFRT_EXPORT int PrintF(const char* fmt, ...)
@ -914,7 +914,7 @@ void Contract::ReportFailure(Contract::ContractFailureKind failureKind, char* us
errorMsg += Beefy::String(": ") + userMessageStr; errorMsg += Beefy::String(": ") + userMessageStr;
if (conditionText != NULL) if (conditionText != NULL)
errorMsg += Beefy::String(": ") + conditionTextStr; errorMsg += Beefy::String(": ") + conditionTextStr;
if (::IsDebuggerPresent()) if (::IsDebuggerPresent())
{ {
SETUP_ERROR(errorMsg.c_str(), 3); SETUP_ERROR(errorMsg.c_str(), 3);
@ -929,7 +929,7 @@ void Contract::ReportFailure(Contract::ContractFailureKind failureKind, char* us
void bf::System::Diagnostics::Debug::Write(char* str, intptr strLen) void bf::System::Diagnostics::Debug::Write(char* str, intptr strLen)
{ {
Beefy::String strVal(str, strLen); Beefy::String strVal(str, strLen);
OutputDebugStr(strVal); OutputDebugStr(strVal);
} }
@ -1048,32 +1048,74 @@ static int ToString(double d, char* outStr, bool roundTrip)
if (!roundTrip) if (!roundTrip)
{ {
int digits; int digits;
if (d > 1000000000) if (d < 0)
digits = 1; {
else if (d > 100000000) if (d < -10000000000)
digits = 2; {
else if (d > 10000000) sprintf(outStr, "%g", d);
digits = 3; }
else if (d > 1000000) else
digits = 4; {
else if (d > 100000) if (d < -1000000000)
digits = 5; digits = 1;
else if (d > 10000) else if (d < -100000000)
digits = 6; digits = 2;
else if (d > 1000) else if (d < -10000000)
digits = 7; digits = 3;
else if (d > 100) else if (d < -1000000)
digits = 8; digits = 4;
else if (d > 10) else if (d < -100000)
digits = 9; digits = 5;
else else if (d < -10000)
digits = 10; digits = 6;
else if (d < -1000)
digits = 7;
else if (d < -100)
digits = 8;
else if (d < -10)
digits = 9;
else
digits = 10;
sprintf(outStr, "%1.*f", digits, d); sprintf(outStr, "%1.*f", digits, d);
}
}
else
{
if (d > 10000000000)
{
sprintf(outStr, "%g", d);
}
else
{
if (d > 1000000000)
digits = 1;
else if (d > 100000000)
digits = 2;
else if (d > 10000000)
digits = 3;
else if (d > 1000000)
digits = 4;
else if (d > 100000)
digits = 5;
else if (d > 10000)
digits = 6;
else if (d > 1000)
digits = 7;
else if (d > 100)
digits = 8;
else if (d > 10)
digits = 9;
else
digits = 10;
sprintf(outStr, "%1.*f", digits, d);
}
}
} }
else else
sprintf(outStr, "%1.17g", d); sprintf(outStr, "%1.17g", d);
int len = (int)strlen(outStr); int len = (int)strlen(outStr);
for (int i = 0; outStr[i] != 0; i++) for (int i = 0; outStr[i] != 0; i++)
{ {