/* we use this so that we can do without the ctype library */
#define is_digit(c) ((c) >= L'0' && (c) <= L'9')
static int skip_atoi(const wchar_t **s)
{
int i=0;
while (is_digit(**s))
i = i*10 + *((*s)++) - L'0';
return i;
}
static wchar_t * int_number(wchar_t * str, int num)
{
_itow(num, str, 10);
while( *str)
str ++;
return str;
}
static wchar_t * double_number(wchar_t * str, double num)
{
char *s;
char tmp[_CVTBUFSIZE + 1];
s = _gcvt ( num, 12, tmp );
while ( *s )
*str++ = *s++;
return str;
}
int __stdcall expandstring_internel( wchar_t* buf, wchar_t* fmt, const VARIANT* args, int number_of_args)
{
wchar_t *str;
wchar_t *s;
LONG arg_lbound, arg_ubound;
ULONG arg_count; // count of argument int args
int arg_index;
if ( buf == NULL || fmt==NULL || (args==NULL && number_of_args>0))
return -1;
arg_lbound = 0;
arg_count = number_of_args;
arg_ubound = arg_lbound + arg_count - 1;
for (str=buf ; *fmt; ) {
while (*fmt != L'%' && *fmt)
*str++ = *fmt++;
if ( (*fmt) == 0)
break;
++fmt; // skips first '%'
if (*fmt == L'%') { // %%
*str++ = L'%';
++fmt;
continue;
}
if ( ! is_digit(*fmt))
break;
arg_index = skip_atoi( (const wchar_t **) &fmt) - 1;
if ( arg_index < arg_lbound || arg_index> arg_ubound )
break; // not a valid argument index
switch (args[arg_index].vt ) {
case VT_I1:
str = int_number( str, args[arg_index].cVal);
break;
case VT_I2:
str = int_number( str, args[arg_index].iVal);
break;
case VT_I4:
str = int_number( str, args[arg_index].lVal);
break;
case VT_INT:
str = int_number( str, args[arg_index].intVal);
break;
case VT_UI1:
str = int_number( str, args[arg_index].bVal);
break;
case VT_UI2:
str = int_number( str, args[arg_index].uiVal);
break;
case VT_UI4:
str = int_number( str, args[arg_index].ulVal);
break;
case VT_UINT:
str = int_number( str, args[arg_index].uintVal);
break;
case VT_R4:
str = double_number( str, args[arg_index].fltVal);
break;
case VT_R8:
str = double_number( str, args[arg_index].dblVal);
break;
case VT_BSTR:
s = (wchar_t*)args[arg_index].bstrVal;
while ( *s )
*str++ = *s++;
break;
case VT_DATE:
break;
}
}
*str = L'\0';
return str-buf;
}