27 #include "precompiled.h"
60 # define tstring wstring
61 # define tstringstream wstringstream
63 # define tstring string
64 # define tstringstream stringstream
73 #if MSC_VERSION < 1400
74 # define USE_I64_FORMAT 1
76 # define USE_I64_FORMAT 0
81 SPECFLAG_THOUSANDS = 1,
82 SPECFLAG_LEFTJUSTIFIED = 2,
84 SPECFLAG_SPACEPREFIX = 8,
85 SPECFLAG_ALTERNATE = 16,
91 virtual ~FormatChunk() { }
92 virtual int ChunkType() = 0;
95 struct FormatVariable :
public FormatChunk
97 int ChunkType() {
return 0; }
106 struct FormatString :
public FormatChunk
108 int ChunkType() {
return 1; }
109 FormatString(std::tstring t) : text(t) {}
114 int get_flag(TCHAR c)
118 case _T(
'\''): return SPECFLAG_THOUSANDS;
119 case _T(
'-'): return SPECFLAG_LEFTJUSTIFIED;
120 case _T(
'+'): return SPECFLAG_SIGNED;
121 case _T(
' '): return SPECFLAG_SPACEPREFIX;
122 case _T(
'#'): return SPECFLAG_ALTERNATE;
123 case _T(
'0'): return SPECFLAG_ZEROPAD;
128 std::tstring flags_to_string(
char flags)
131 const char* c =
"\'-+ #0";
132 for (
int i=0; i<6; ++i)
139 std::tstring to_string(
T n)
142 std::tstringstream str;
148 int is_lengthmod(TCHAR c)
160 #define _T2(a) ((a<<8) | a)
162 int type_size(TCHAR type,
int length)
170 case _T (
'l'): return sizeof(long);
171 case _T2(
'l'): return sizeof(long long);
172 case _T (
'h'): return sizeof(short);
173 case _T2(
'h'): return sizeof(char);
174 default:
return sizeof(int);
179 case 'X':
return sizeof(unsigned);
188 if (length == _T(
'L'))
189 return sizeof(
long double);
191 return sizeof(double);
195 if (length == _T(
'l'))
196 return sizeof(wint_t);
202 if (length == _T(
'l'))
203 return sizeof(
wchar_t*);
205 return sizeof(
char*);
208 return sizeof(
void*);
217 int sys_vswprintf(TCHAR* buffer,
size_t count,
const TCHAR* format, va_list argptr)
220 memset(buffer, 0, count*
sizeof(TCHAR));
233 std::vector<FormatChunk*> specs;
234 std::tstring stringchunk;
238 #define readchar(x) if ((x = *format++) == '\0') { delete s; goto finished_reading; }
240 while ((chr = *format++) !=
'\0')
245 if (*format == _T(
'%'))
247 stringchunk += _T(
'%');
252 if (stringchunk.length())
254 specs.push_back(
new FormatString(stringchunk));
255 stringchunk = _T(
"");
258 FormatVariable *s =
new FormatVariable;
274 if (!number && get_flag(chr))
275 s->flags = (char)(s->flags|get_flag(chr));
278 else if (isdigit(chr))
279 number = number*10 + (chr-
'0');
283 else if (chr == _T(
'$'))
285 s->position = number;
307 number = number*10 + (chr-
'0');
310 s->precision = number;
325 if (is_lengthmod(chr))
330 if (chr == _T(
'l') || chr == _T(
'h'))
334 s->length |= (chr << 8);
360 if (stringchunk.length())
362 specs.push_back(
new FormatString(stringchunk));
363 stringchunk = _T(
"");
368 std::tstring newformat;
370 std::vector<int> varsizes;
372 typedef std::vector<FormatChunk*>::iterator ChunkIt;
374 for (ChunkIt it = specs.begin(); it != specs.end(); ++it)
376 if ((*it)->ChunkType() == 0)
378 FormatVariable* s =
static_cast<FormatVariable*
>(*it);
383 if (s->position >= (
int)varsizes.size())
384 varsizes.resize(s->position+1, -1);
386 varsizes[s->position] = type_size(s->type, s->length);
390 newformat += _T(
"%");
393 newformat += flags_to_string(s->flags);
398 newformat += to_string(s->width);
403 if (s->precision == -1)
406 newformat += to_string(s->precision);
413 if (s->length == 0x00006c6c)
417 newformat += _T(
"ll");
419 else if (s->length == 0x00006868)
420 newformat += _T(
"hh");
424 newformat += (char) s->length;
428 newformat += s->type;
432 FormatString* s =
static_cast<FormatString*
>(*it);
433 newformat += s->text;
451 #error SLIGHTLY FATAL ERROR: Only x86 is supported!
455 std::string newstack;
457 std::vector< std::pair<char*, char*> > stackitems;
459 va_list arglist = argptr;
462 const u8* newstackptr;
467 for (
size_t i = 1; i < varsizes.size(); ++i)
469 if (varsizes[i] <= 0)
478 #define INTSIZE(n) ( (n + sizeof(int) - 1) & ~(sizeof(int) - 1) )
480 size_t size = INTSIZE(varsizes[i]);
481 stackitems.push_back( std::pair<char*, char*>( arglist, arglist+size ));
486 for (ChunkIt it = specs.begin(); it != specs.end(); ++it)
488 FormatChunk* chunk = *it;
489 if (chunk->ChunkType() == 0)
491 FormatVariable* s =
static_cast<FormatVariable*
>(chunk);
492 if (s->position <= 0)
497 newstack += std::string( stackitems[s->position-1].first, stackitems[s->position-1].second );
501 newstackptr = (
const u8*)newstack.c_str();
505 newstackptr = (
const u8*)arglist;
508 for (ChunkIt it = specs.begin(); it != specs.end(); ++it)
509 if ((*it)->ChunkType() == 0)
510 delete static_cast<FormatVariable*>(*it);
512 delete static_cast<FormatString*
>(*it);
514 int ret = _vsntprintf(buffer, count, newformat.c_str(), (va_list)newstackptr);
519 buffer[count-1] =
'\0';
520 if (ret == (
int)count)
#define T(string_literal)
#define DEBUG_WARN_ERR(status)
display the error dialog with text corresponding to the given error code.
int sys_vswprintf(wchar_t *buffer, size_t count, const wchar_t *format, va_list argptr)
sys_vswprintf: doesn't quite follow the standard for vswprintf, but works better across compilers: ...