aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/format.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/g3dlite/format.cpp')
-rw-r--r--dep/g3dlite/format.cpp164
1 files changed, 164 insertions, 0 deletions
diff --git a/dep/g3dlite/format.cpp b/dep/g3dlite/format.cpp
new file mode 100644
index 00000000000..d9d1b516393
--- /dev/null
+++ b/dep/g3dlite/format.cpp
@@ -0,0 +1,164 @@
+/**
+ @file format.cpp
+
+ @author Morgan McGuire, graphics3d.com
+
+ @created 2000-09-09
+ @edited 2006-08-14
+*/
+
+#include "G3D/format.h"
+#include "G3D/platform.h"
+#include "G3D/System.h"
+
+#ifdef _MSC_VER
+ // disable: "C++ exception handler used"
+# pragma warning (push)
+# pragma warning (disable : 4530)
+#endif // _MSC_VER
+
+// If your platform does not have vsnprintf, you can find a
+// implementation at http://www.ijs.si/software/snprintf/
+
+namespace G3D {
+
+std::string __cdecl format(const char* fmt,...) {
+ va_list argList;
+ va_start(argList,fmt);
+ std::string result = vformat(fmt, argList);
+ va_end(argList);
+
+ return result;
+}
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1300)
+// Both MSVC seems to use the non-standard vsnprintf
+// so we are using vscprintf to determine buffer size, however
+// only MSVC7 and up headers include vscprintf for some reason.
+std::string vformat(const char *fmt, va_list argPtr) {
+ // We draw the line at a 1MB string.
+ const int maxSize = 1000000;
+
+ // If the string is less than 161 characters,
+ // allocate it on the stack because this saves
+ // the malloc/free time.
+ const int bufSize = 161;
+ char stackBuffer[bufSize];
+
+ // MSVC does not support va_copy
+ int actualSize = _vscprintf(fmt, argPtr) + 1;
+
+ if (actualSize > bufSize) {
+
+ // Now use the heap.
+ char* heapBuffer = NULL;
+
+ if (actualSize < maxSize) {
+
+ heapBuffer = (char*)System::malloc(maxSize + 1);
+ _vsnprintf(heapBuffer, maxSize, fmt, argPtr);
+ heapBuffer[maxSize] = '\0';
+ } else {
+ heapBuffer = (char*)System::malloc(actualSize);
+ vsprintf(heapBuffer, fmt, argPtr);
+ }
+
+ std::string formattedString(heapBuffer);
+ System::free(heapBuffer);
+ return formattedString;
+ } else {
+
+ vsprintf(stackBuffer, fmt, argPtr);
+ return std::string(stackBuffer);
+ }
+}
+
+#elif defined(_MSC_VER) && (_MSC_VER < 1300)
+
+std::string vformat(const char *fmt, va_list argPtr) {
+ // We draw the line at a 1MB string.
+ const int maxSize = 1000000;
+
+ // If the string is less than 161 characters,
+ // allocate it on the stack because this saves
+ // the malloc/free time.
+ const int bufSize = 161;
+ char stackBuffer[bufSize];
+
+ // MSVC6 doesn't support va_copy, however it also seems to compile
+ // correctly if we just pass our argument list along. Note that
+ // this whole code block is only compiled if we're on MSVC6 anyway
+ int actualWritten = _vsnprintf(stackBuffer, bufSize, fmt, argPtr);
+
+ // Not a big enough buffer, bufSize characters written
+ if (actualWritten == -1) {
+
+ int heapSize = 512;
+ double powSize = 1.0;
+ char* heapBuffer = (char*)System::malloc(heapSize);
+
+ while ((_vsnprintf(heapBuffer, heapSize, fmt, argPtr) == -1) &&
+ (heapSize < maxSize)) {
+
+ heapSize = iCeil(heapSize * ::pow((double)2.0, powSize++));
+ heapBuffer = (char*)System::realloc(heapBuffer, heapSize);
+ }
+
+ heapBuffer[heapSize-1] = '\0';
+
+ std::string heapString(heapBuffer);
+ System::free(heapBuffer);
+
+ return heapString;
+ } else {
+
+ return std::string(stackBuffer);
+ }
+}
+
+#else
+
+// glibc 2.1 has been updated to the C99 standard
+std::string vformat(const char* fmt, va_list argPtr) {
+ // If the string is less than 161 characters,
+ // allocate it on the stack because this saves
+ // the malloc/free time. The number 161 is chosen
+ // to support two lines of text on an 80 character
+ // console (plus the null terminator).
+ const int bufSize = 161;
+ char stackBuffer[bufSize];
+
+ va_list argPtrCopy;
+ va_copy(argPtrCopy, argPtr);
+ int numChars = vsnprintf(stackBuffer, bufSize, fmt, argPtrCopy);
+ va_end(argPtrCopy);
+
+ if (numChars >= bufSize) {
+ // We didn't allocate a big enough string.
+ char* heapBuffer = (char*)System::malloc((numChars + 1) * sizeof(char));
+
+ debugAssert(heapBuffer);
+ int numChars2 = vsnprintf(heapBuffer, numChars + 1, fmt, argPtr);
+ debugAssert(numChars2 == numChars);
+ (void)numChars2;
+
+ std::string result(heapBuffer);
+
+ System::free(heapBuffer);
+
+ return result;
+
+ } else {
+
+ return std::string(stackBuffer);
+
+ }
+}
+
+#endif
+
+} // namespace
+
+#ifdef _MSC_VER
+# pragma warning (pop)
+#endif