ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

wsprintf.c
Go to the documentation of this file.
00001 /*
00002  * wsprintf functions
00003  *
00004  * Copyright 1996 Alexandre Julliard
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  *
00020  * NOTE:
00021  * This code is duplicated in user32. If you change something here make sure
00022  * to change it in user32 too.
00023  */
00024 
00025 #include <stdarg.h>
00026 #include <string.h>
00027 #include <stdio.h>
00028 
00029 #include "windef.h"
00030 #include "winbase.h"
00031 #define NO_SHLWAPI_REG
00032 #include "shlwapi.h"
00033 
00034 #include "wine/debug.h"
00035 
00036 WINE_DEFAULT_DEBUG_CHANNEL(string);
00037 
00038 
00039 #define WPRINTF_LEFTALIGN   0x0001  /* Align output on the left ('-' prefix) */
00040 #define WPRINTF_PREFIX_HEX  0x0002  /* Prefix hex with 0x ('#' prefix) */
00041 #define WPRINTF_ZEROPAD     0x0004  /* Pad with zeros ('0' prefix) */
00042 #define WPRINTF_LONG        0x0008  /* Long arg ('l' prefix) */
00043 #define WPRINTF_SHORT       0x0010  /* Short arg ('h' prefix) */
00044 #define WPRINTF_UPPER_HEX   0x0020  /* Upper-case hex ('X' specifier) */
00045 #define WPRINTF_WIDE        0x0040  /* Wide arg ('w' prefix) */
00046 
00047 typedef enum
00048 {
00049     WPR_UNKNOWN,
00050     WPR_CHAR,
00051     WPR_WCHAR,
00052     WPR_STRING,
00053     WPR_WSTRING,
00054     WPR_SIGNED,
00055     WPR_UNSIGNED,
00056     WPR_HEXA
00057 } WPRINTF_TYPE;
00058 
00059 typedef struct
00060 {
00061     UINT         flags;
00062     UINT         width;
00063     UINT         precision;
00064     WPRINTF_TYPE   type;
00065 } WPRINTF_FORMAT;
00066 
00067 typedef union {
00068     WCHAR   wchar_view;
00069     CHAR    char_view;
00070     LPCSTR  lpcstr_view;
00071     LPCWSTR lpcwstr_view;
00072     INT     int_view;
00073 } WPRINTF_DATA;
00074 
00075 static const CHAR null_stringA[] = "(null)";
00076 static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
00077 
00078 /***********************************************************************
00079  *           WPRINTF_ParseFormatA
00080  *
00081  * Parse a format specification. A format specification has the form:
00082  *
00083  * [-][#][0][width][.precision]type
00084  *
00085  * Return value is the length of the format specification in characters.
00086  */
00087 static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res )
00088 {
00089     LPCSTR p = format;
00090 
00091     res->flags = 0;
00092     res->width = 0;
00093     res->precision = 0;
00094     if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
00095     if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
00096     if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
00097     while ((*p >= '0') && (*p <= '9'))  /* width field */
00098     {
00099         res->width = res->width * 10 + *p - '0';
00100         p++;
00101     }
00102     if (*p == '.')  /* precision field */
00103     {
00104         p++;
00105         while ((*p >= '0') && (*p <= '9'))
00106         {
00107             res->precision = res->precision * 10 + *p - '0';
00108             p++;
00109         }
00110     }
00111     if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
00112     else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
00113     else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
00114     switch(*p)
00115     {
00116     case 'c':
00117         res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
00118         break;
00119     case 'C':
00120         res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
00121         break;
00122     case 'd':
00123     case 'i':
00124         res->type = WPR_SIGNED;
00125         break;
00126     case 's':
00127         res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
00128         break;
00129     case 'S':
00130         res->type = (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
00131         break;
00132     case 'u':
00133         res->type = WPR_UNSIGNED;
00134         break;
00135     case 'X':
00136         res->flags |= WPRINTF_UPPER_HEX;
00137         /* fall through */
00138     case 'x':
00139         res->type = WPR_HEXA;
00140         break;
00141     default: /* unknown format char */
00142         res->type = WPR_UNKNOWN;
00143         p--;  /* print format as normal char */
00144         break;
00145     }
00146     return (INT)(p - format) + 1;
00147 }
00148 
00149 
00150 /***********************************************************************
00151  *           WPRINTF_ParseFormatW
00152  *
00153  * Parse a format specification. A format specification has the form:
00154  *
00155  * [-][#][0][width][.precision]type
00156  *
00157  * Return value is the length of the format specification in characters.
00158  */
00159 static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res )
00160 {
00161     LPCWSTR p = format;
00162 
00163     res->flags = 0;
00164     res->width = 0;
00165     res->precision = 0;
00166     if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
00167     if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
00168     if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
00169     while ((*p >= '0') && (*p <= '9'))  /* width field */
00170     {
00171         res->width = res->width * 10 + *p - '0';
00172         p++;
00173     }
00174     if (*p == '.')  /* precision field */
00175     {
00176         p++;
00177         while ((*p >= '0') && (*p <= '9'))
00178         {
00179             res->precision = res->precision * 10 + *p - '0';
00180             p++;
00181         }
00182     }
00183     if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
00184     else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
00185     else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
00186     switch((CHAR)*p)
00187     {
00188     case 'c':
00189         res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
00190         break;
00191     case 'C':
00192         res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
00193         break;
00194     case 'd':
00195     case 'i':
00196         res->type = WPR_SIGNED;
00197         break;
00198     case 's':
00199         res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
00200         break;
00201     case 'S':
00202         res->type = (res->flags & (WPRINTF_LONG|WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
00203         break;
00204     case 'u':
00205         res->type = WPR_UNSIGNED;
00206         break;
00207     case 'X':
00208         res->flags |= WPRINTF_UPPER_HEX;
00209         /* fall through */
00210     case 'x':
00211         res->type = WPR_HEXA;
00212         break;
00213     default:
00214         res->type = WPR_UNKNOWN;
00215         p--;  /* print format as normal char */
00216         break;
00217     }
00218     return (INT)(p - format) + 1;
00219 }
00220 
00221 
00222 /***********************************************************************
00223  *           WPRINTF_GetLen
00224  */
00225 static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg,
00226                               LPSTR number, UINT maxlen )
00227 {
00228     UINT len;
00229 
00230     if (format->flags & WPRINTF_LEFTALIGN) format->flags &= ~WPRINTF_ZEROPAD;
00231     if (format->width > maxlen) format->width = maxlen;
00232     switch(format->type)
00233     {
00234     case WPR_CHAR:
00235     case WPR_WCHAR:
00236         return (format->precision = 1);
00237     case WPR_STRING:
00238         if (!arg->lpcstr_view) arg->lpcstr_view = null_stringA;
00239         for (len = 0; !format->precision || (len < format->precision); len++)
00240             if (!*(arg->lpcstr_view + len)) break;
00241         if (len > maxlen) len = maxlen;
00242         return (format->precision = len);
00243     case WPR_WSTRING:
00244         if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW;
00245         for (len = 0; !format->precision || (len < format->precision); len++)
00246             if (!*(arg->lpcwstr_view + len)) break;
00247         if (len > maxlen) len = maxlen;
00248         return (format->precision = len);
00249     case WPR_SIGNED:
00250         len = sprintf( number, "%d", arg->int_view );
00251         break;
00252     case WPR_UNSIGNED:
00253         len = sprintf( number, "%u", (UINT)arg->int_view );
00254         break;
00255     case WPR_HEXA:
00256         len = sprintf( number,
00257                        (format->flags & WPRINTF_UPPER_HEX) ? "%X" : "%x",
00258                        (UINT)arg->int_view);
00259         break;
00260     default:
00261         return 0;
00262     }
00263     if (len > maxlen) len = maxlen;
00264     if (format->precision < len) format->precision = len;
00265     if (format->precision > maxlen) format->precision = maxlen;
00266     if ((format->flags & WPRINTF_ZEROPAD) && (format->width > format->precision))
00267         format->precision = format->width;
00268     if (format->flags & WPRINTF_PREFIX_HEX) len += 2;
00269     return len;
00270 }
00271 
00272 
00273 /***********************************************************************
00274  *           wvnsprintfA   (SHLWAPI.@)
00275  *
00276  * Print formatted output to a string, up to a maximum number of chars.
00277  *
00278  * PARAMS
00279  * buffer [O] Destination for output string
00280  * maxlen [I] Maximum number of characters to write
00281  * spec   [I] Format string
00282  *
00283  * RETURNS
00284  *  Success: The number of characters written.
00285  *  Failure: -1.
00286  */
00287 INT WINAPI wvnsprintfA( LPSTR buffer, INT maxlen, LPCSTR spec, __ms_va_list args )
00288 {
00289     WPRINTF_FORMAT format;
00290     LPSTR p = buffer;
00291     UINT i, len, sign;
00292     CHAR number[20];
00293     WPRINTF_DATA argData;
00294 
00295     TRACE("%p %u %s\n", buffer, maxlen, debugstr_a(spec));
00296 
00297     while (*spec && (maxlen > 1))
00298     {
00299         if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
00300         spec++;
00301         if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
00302         spec += WPRINTF_ParseFormatA( spec, &format );
00303 
00304         switch(format.type)
00305         {
00306         case WPR_WCHAR:
00307             argData.wchar_view = (WCHAR)va_arg( args, int );
00308             break;
00309         case WPR_CHAR:
00310             argData.char_view = (CHAR)va_arg( args, int );
00311             break;
00312         case WPR_STRING:
00313             argData.lpcstr_view = va_arg( args, LPCSTR );
00314             break;
00315         case WPR_WSTRING:
00316             argData.lpcwstr_view = va_arg( args, LPCWSTR );
00317             break;
00318         case WPR_HEXA:
00319         case WPR_SIGNED:
00320         case WPR_UNSIGNED:
00321             argData.int_view = va_arg( args, INT );
00322             break;
00323         default:
00324             argData.wchar_view = 0;
00325             break;
00326         }
00327 
00328         len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
00329         sign = 0;
00330         if (!(format.flags & WPRINTF_LEFTALIGN))
00331             for (i = format.precision; i < format.width; i++, maxlen--)
00332                 *p++ = ' ';
00333         switch(format.type)
00334         {
00335         case WPR_WCHAR:
00336             *p++ = argData.wchar_view;
00337             break;
00338         case WPR_CHAR:
00339             *p++ = argData.char_view;
00340             break;
00341         case WPR_STRING:
00342             memcpy( p, argData.lpcstr_view, len );
00343             p += len;
00344             break;
00345         case WPR_WSTRING:
00346             {
00347                 LPCWSTR ptr = argData.lpcwstr_view;
00348                 for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++;
00349             }
00350             break;
00351         case WPR_HEXA:
00352             if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
00353             {
00354                 *p++ = '0';
00355                 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
00356                 maxlen -= 2;
00357                 len -= 2;
00358             }
00359             /* fall through */
00360         case WPR_SIGNED:
00361             /* Transfer the sign now, just in case it will be zero-padded*/
00362             if (number[0] == '-')
00363             {
00364                 *p++ = '-';
00365                 sign = 1;
00366             }
00367             /* fall through */
00368         case WPR_UNSIGNED:
00369             for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
00370             memcpy( p, number + sign, len - sign  );
00371             p += len - sign;
00372             break;
00373         case WPR_UNKNOWN:
00374             continue;
00375         }
00376         if (format.flags & WPRINTF_LEFTALIGN)
00377             for (i = format.precision; i < format.width; i++, maxlen--)
00378                 *p++ = ' ';
00379         maxlen -= len;
00380     }
00381     *p = 0;
00382     TRACE("%s\n",debugstr_a(buffer));
00383     return (maxlen > 1) ? (INT)(p - buffer) : -1;
00384 }
00385 
00386 
00387 /***********************************************************************
00388  *           wvnsprintfW   (SHLWAPI.@)
00389  *
00390  * See wvnsprintfA.
00391  */
00392 INT WINAPI wvnsprintfW( LPWSTR buffer, INT maxlen, LPCWSTR spec, __ms_va_list args )
00393 {
00394     WPRINTF_FORMAT format;
00395     LPWSTR p = buffer;
00396     UINT i, len, sign;
00397     CHAR number[20];
00398     WPRINTF_DATA argData;
00399 
00400     TRACE("%p %u %s\n", buffer, maxlen, debugstr_w(spec));
00401 
00402     while (*spec && (maxlen > 1))
00403     {
00404         if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
00405         spec++;
00406         if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
00407         spec += WPRINTF_ParseFormatW( spec, &format );
00408 
00409         switch(format.type)
00410         {
00411         case WPR_WCHAR:
00412             argData.wchar_view = (WCHAR)va_arg( args, int );
00413             break;
00414         case WPR_CHAR:
00415             argData.char_view = (CHAR)va_arg( args, int );
00416             break;
00417         case WPR_STRING:
00418             argData.lpcstr_view = va_arg( args, LPCSTR );
00419             break;
00420         case WPR_WSTRING:
00421             argData.lpcwstr_view = va_arg( args, LPCWSTR );
00422             break;
00423         case WPR_HEXA:
00424         case WPR_SIGNED:
00425         case WPR_UNSIGNED:
00426             argData.int_view = va_arg( args, INT );
00427             break;
00428         default:
00429             argData.wchar_view = 0;
00430             break;
00431         }
00432 
00433         len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
00434         sign = 0;
00435         if (!(format.flags & WPRINTF_LEFTALIGN))
00436             for (i = format.precision; i < format.width; i++, maxlen--)
00437                 *p++ = ' ';
00438         switch(format.type)
00439         {
00440         case WPR_WCHAR:
00441             *p++ = argData.wchar_view;
00442             break;
00443         case WPR_CHAR:
00444             *p++ = argData.char_view;
00445             break;
00446         case WPR_STRING:
00447             {
00448                 LPCSTR ptr = argData.lpcstr_view;
00449                 for (i = 0; i < len; i++) *p++ = (WCHAR)*ptr++;
00450             }
00451             break;
00452         case WPR_WSTRING:
00453             if (len) memcpy( p, argData.lpcwstr_view, len * sizeof(WCHAR) );
00454             p += len;
00455             break;
00456         case WPR_HEXA:
00457             if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
00458             {
00459                 *p++ = '0';
00460                 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
00461                 maxlen -= 2;
00462                 len -= 2;
00463             }
00464             /* fall through */
00465         case WPR_SIGNED:
00466             /* Transfer the sign now, just in case it will be zero-padded*/
00467             if (number[0] == '-')
00468             {
00469                 *p++ = '-';
00470                 sign = 1;
00471             }
00472             /* fall through */
00473         case WPR_UNSIGNED:
00474             for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
00475             for (i = sign; i < len; i++) *p++ = (WCHAR)number[i];
00476             break;
00477         case WPR_UNKNOWN:
00478             continue;
00479         }
00480         if (format.flags & WPRINTF_LEFTALIGN)
00481             for (i = format.precision; i < format.width; i++, maxlen--)
00482                 *p++ = ' ';
00483         maxlen -= len;
00484     }
00485     *p = 0;
00486     TRACE("%s\n",debugstr_w(buffer));
00487     return (maxlen > 1) ? (INT)(p - buffer) : -1;
00488 }
00489 
00490 
00491 /*************************************************************************
00492  *           wnsprintfA   (SHLWAPI.@)
00493  *
00494  * Print formatted output to a string, up to a maximum number of chars.
00495  *
00496  * PARAMS
00497  * lpOut      [O] Destination for output string
00498  * cchLimitIn [I] Maximum number of characters to write
00499  * lpFmt      [I] Format string
00500  *
00501  * RETURNS
00502  *  Success: The number of characters written.
00503  *  Failure: -1.
00504  */
00505 int WINAPIV wnsprintfA(LPSTR lpOut, int cchLimitIn, LPCSTR lpFmt, ...)
00506 {
00507     __ms_va_list valist;
00508     INT res;
00509 
00510     __ms_va_start( valist, lpFmt );
00511     res = wvnsprintfA( lpOut, cchLimitIn, lpFmt, valist );
00512     __ms_va_end( valist );
00513     return res;
00514 }
00515 
00516 
00517 /*************************************************************************
00518  *           wnsprintfW   (SHLWAPI.@)
00519  *
00520  * See wnsprintfA.
00521  */
00522 int WINAPIV wnsprintfW(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, ...)
00523 {
00524     __ms_va_list valist;
00525     INT res;
00526 
00527     __ms_va_start( valist, lpFmt );
00528     res = wvnsprintfW( lpOut, cchLimitIn, lpFmt, valist );
00529     __ms_va_end( valist );
00530     return res;
00531 }

Generated on Mon May 28 2012 04:26:10 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.