root/trunk/dep/src/g3dlite/format.cpp @ 2

Revision 2, 4.2 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/**
2 @file format.cpp
3
4 @author Morgan McGuire, graphics3d.com
5
6 @created 2000-09-09
7 @edited  2006-04-30
8*/
9
10#include "G3D/format.h"
11#include "G3D/platform.h"
12#include "G3D/System.h"
13
14#ifdef G3D_WIN32
15    #include <math.h>
16    #define vsnprintf _vsnprintf
17    #define NEWLINE "\r\n"
18#else
19    #include <stdarg.h>
20    #define NEWLINE "\n"
21#endif
22
23#ifdef _MSC_VER
24    // disable: "C++ exception handler used"
25#   pragma warning (push)
26#   pragma warning (disable : 4530)
27#endif // _MSC_VER
28
29// If your platform does not have vsnprintf, you can find a
30// implementation at http://www.ijs.si/software/snprintf/
31
32namespace G3D {
33
34std::string format(const char* fmt,...) {
35    va_list argList;
36    va_start(argList,fmt);
37    std::string result = vformat(fmt, argList);
38    va_end(argList);
39
40    return result;
41}
42
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.
47std::string vformat(const char *fmt, va_list argPtr) {
48    // We draw the line at a 1MB string.
49    const int maxSize = 1000000;
50
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];
56
57    int actualSize = _vscprintf(fmt, argPtr) + 1;
58
59    if (actualSize > bufSize) {
60
61        // Now use the heap.
62        char* heapBuffer = NULL;
63
64        if (actualSize < maxSize) {
65
66            heapBuffer = (char*)System::malloc(maxSize + 1);
67            vsnprintf(heapBuffer, maxSize, fmt, argPtr);
68            heapBuffer[maxSize] = '\0';
69        } else {
70            heapBuffer = (char*)System::malloc(actualSize);
71            vsprintf(heapBuffer, fmt, argPtr);           
72        }
73
74        std::string formattedString(heapBuffer);
75        System::free(heapBuffer);
76        return formattedString;
77    } else {
78
79        vsprintf(stackBuffer, fmt, argPtr);
80        return std::string(stackBuffer);
81    }
82}
83
84#elif defined(G3D_WIN32) && (_MSC_VER < 1300)
85
86std::string vformat(const char *fmt, va_list argPtr) {
87    // We draw the line at a 1MB string.
88    const int maxSize = 1000000;
89
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];
95
96    int actualWritten = vsnprintf(stackBuffer, bufSize, fmt, argPtr);
97
98    // Not a big enough buffer, bufSize characters written
99    if (actualWritten == -1) {
100
101        int heapSize = 512;
102        double powSize = 1.0;
103        char* heapBuffer = (char*)System::malloc(heapSize);
104       
105        while ((vsnprintf(heapBuffer, heapSize, fmt, argPtr) == -1) &&
106            (heapSize  < maxSize)) {
107
108            heapSize = iCeil(heapSize * ::pow((double)2.0, powSize++));
109            heapBuffer = (char*)System::realloc(heapBuffer, heapSize);
110        }
111
112        heapBuffer[heapSize-1] = '\0';
113
114        std::string heapString(heapBuffer);
115        System::free(heapBuffer);
116
117        return heapString;
118    } else {
119
120        return std::string(stackBuffer);
121    }
122}
123
124#else
125
126// glibc 2.1 has been updated to the C99 standard
127std::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];
135
136    int numChars = vsnprintf(stackBuffer, bufSize, fmt, argPtr);
137
138    if (numChars >= bufSize) {
139      // We didn't allocate a big enough string.
140      char* heapBuffer = (char*)System::malloc((numChars + 1) * sizeof(char));
141
142      assert(heapBuffer);
143      int numChars2 = vsnprintf(heapBuffer, numChars + 1, fmt, argPtr);
144      assert(numChars2 == numChars);
145
146      std::string result(heapBuffer);
147     
148      System::free(heapBuffer);
149
150      return result;
151
152    } else {
153
154      return std::string(stackBuffer);
155
156    }
157}
158
159#endif
160
161} // namespace
162
163#ifdef G3D_WIN32
164#   undef vsnprintf
165#endif
166
167#ifdef _MSC_VER
168#   pragma warning (pop)
169#endif
170
171#undef NEWLINE
Note: See TracBrowser for help on using the browser.