4 @author Morgan McGuire, graphics3d.com
10 #include "G3D/format.h"
11 #include "G3D/platform.h"
12 #include "G3D/System.h"
16 #define vsnprintf _vsnprintf
17 #define NEWLINE "\r\n"
24 // disable: "C++ exception handler used"
25 # pragma warning (push)
26 # pragma warning (disable : 4530)
29 // If your platform does not have vsnprintf, you can find a
30 // implementation at http://www.ijs.si/software/snprintf/
34 std::string
format(const char* fmt
,...) {
36 va_start(argList
,fmt
);
37 std::string result
= vformat(fmt
, argList
);
43 #if defined(G3D_WIN32) && (_MSC_VER >= 1300)
44 // Both MSVC6 and 7 seem to use the non-standard vsnprintf
45 // so we are using vscprintf to determine buffer size, however
46 // only MSVC7 headers include vscprintf for some reason.
47 std::string
vformat(const char *fmt
, va_list argPtr
) {
48 // We draw the line at a 1MB string.
49 const int maxSize
= 1000000;
51 // If the string is less than 161 characters,
52 // allocate it on the stack because this saves
53 // the malloc/free time.
54 const int bufSize
= 161;
55 char stackBuffer
[bufSize
];
57 int actualSize
= _vscprintf(fmt
, argPtr
) + 1;
59 if (actualSize
> bufSize
) {
62 char* heapBuffer
= NULL
;
64 if (actualSize
< maxSize
) {
66 heapBuffer
= (char*)System::malloc(maxSize
+ 1);
67 vsnprintf(heapBuffer
, maxSize
, fmt
, argPtr
);
68 heapBuffer
[maxSize
] = '\0';
70 heapBuffer
= (char*)System::malloc(actualSize
);
71 vsprintf(heapBuffer
, fmt
, argPtr
);
74 std::string
formattedString(heapBuffer
);
75 System::free(heapBuffer
);
76 return formattedString
;
79 vsprintf(stackBuffer
, fmt
, argPtr
);
80 return std::string(stackBuffer
);
84 #elif defined(G3D_WIN32) && (_MSC_VER < 1300)
86 std::string
vformat(const char *fmt
, va_list argPtr
) {
87 // We draw the line at a 1MB string.
88 const int maxSize
= 1000000;
90 // If the string is less than 161 characters,
91 // allocate it on the stack because this saves
92 // the malloc/free time.
93 const int bufSize
= 161;
94 char stackBuffer
[bufSize
];
96 int actualWritten
= vsnprintf(stackBuffer
, bufSize
, fmt
, argPtr
);
98 // Not a big enough buffer, bufSize characters written
99 if (actualWritten
== -1) {
102 double powSize
= 1.0;
103 char* heapBuffer
= (char*)System::malloc(heapSize
);
105 while ((vsnprintf(heapBuffer
, heapSize
, fmt
, argPtr
) == -1) &&
106 (heapSize
< maxSize
)) {
108 heapSize
= iCeil(heapSize
* ::pow((double)2.0, powSize
++));
109 heapBuffer
= (char*)System::realloc(heapBuffer
, heapSize
);
112 heapBuffer
[heapSize
-1] = '\0';
114 std::string
heapString(heapBuffer
);
115 System::free(heapBuffer
);
120 return std::string(stackBuffer
);
126 // glibc 2.1 has been updated to the C99 standard
127 std::string
vformat(const char* fmt
, va_list argPtr
) {
128 // If the string is less than 161 characters,
129 // allocate it on the stack because this saves
130 // the malloc/free time. The number 161 is chosen
131 // to support two lines of text on an 80 character
132 // console (plus the null terminator).
133 const int bufSize
= 161;
134 char stackBuffer
[bufSize
];
136 int numChars
= vsnprintf(stackBuffer
, bufSize
, fmt
, argPtr
);
138 if (numChars
>= bufSize
) {
139 // We didn't allocate a big enough string.
140 char* heapBuffer
= (char*)System::malloc((numChars
+ 1) * sizeof(char));
143 int numChars2
= vsnprintf(heapBuffer
, numChars
+ 1, fmt
, argPtr
);
144 assert(numChars2
== numChars
);
146 std::string
result(heapBuffer
);
148 System::free(heapBuffer
);
154 return std::string(stackBuffer
);
168 # pragma warning (pop)