X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3aa077cebc213cd81734ff62809df1611c40fc86..4f13428c4f852674c8f8fc99af26d9486bf907db:/src/common/wxchar.cpp diff --git a/src/common/wxchar.cpp b/src/common/wxchar.cpp index 56095eefa8..089d645b82 100644 --- a/src/common/wxchar.cpp +++ b/src/common/wxchar.cpp @@ -1,8 +1,8 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/common/wxchar.cpp // Purpose: wxChar implementation -// Author: Ove Kåven -// Modified by: Ron Lee +// Author: Ove Kaven +// Modified by: Ron Lee, Francesco Montorsi // Created: 09/04/99 // RCS-ID: $Id$ // Copyright: (c) wxWidgets copyright @@ -186,7 +186,7 @@ bool WXDLLEXPORT wxOKlibc() #define wxMAX_SVNPRINTF_ARGUMENTS 64 #define wxMAX_SVNPRINTF_FLAGBUFFER_LEN 32 -// the conversion specifiers accepted by wxMyPosVsnprintf_ +// the conversion specifiers accepted by wxVsnprintf_ enum wxPrintfArgType { wxPAT_INVALID = -1, @@ -213,7 +213,7 @@ enum wxPrintfArgType { wxPAT_NLONGINT // %ln }; -// an argument passed to wxMyPosVsnprintf_ +// an argument passed to wxVsnprintf_ typedef union { int pad_int; // %d, %i, %o, %u, %x, %X long int pad_longint; // %ld, etc @@ -240,7 +240,7 @@ typedef union { // Contains parsed data relative to a conversion specifier given to -// wxMyPosVsnprintf_ and parsed from the format string +// wxVsnprintf_ and parsed from the format string // NOTE: in C++ there is almost no difference between struct & classes thus // there is no performance gain by using a struct here... class wxPrintfConvSpec @@ -274,13 +274,16 @@ public: // a little buffer where formatting flags like #+\.hlqLZ are stored by Parse() // for use in Process() + // NB: this buffer can be safely a char buffer instead of a wchar_t buffer + // since it's used only for numeric conversion specifier and always + // with sprintf(). char szFlags[wxMAX_SVNPRINTF_FLAGBUFFER_LEN]; public: // we don't declare this as a constructor otherwise it would be called - // automatically and we don't want this: to be optimized, wxMyPosVsnprintf_ + // automatically and we don't want this: to be optimized, wxVsnprintf_ // calls this function only on really-used instances of this class. void Init(); @@ -310,7 +313,10 @@ void wxPrintfConvSpec::Init() adj_left = false; argpos = argend = NULL; type = wxPAT_INVALID; - szFlags[0] = wxT('%'); + + // this character will never be removed from szFlags array and + // is important when calling sprintf() in wxPrintfConvSpec::Process() ! + szFlags[0] = '%'; } bool wxPrintfConvSpec::Parse(const wxChar *format) @@ -329,7 +335,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format) #define CHECK_PREC \ if (in_prec && !prec_dot) \ { \ - szFlags[flagofs++] = '.'; \ + szFlags[flagofs++] = (char)'.'; \ prec_dot = true; \ } @@ -349,13 +355,13 @@ bool wxPrintfConvSpec::Parse(const wxChar *format) case wxT('+'): case wxT('\''): CHECK_PREC - szFlags[flagofs++] = ch; + szFlags[flagofs++] = (char)ch; break; case wxT('-'): CHECK_PREC adj_left = true; - szFlags[flagofs++] = ch; + szFlags[flagofs++] = (char)ch; break; case wxT('.'): @@ -370,26 +376,26 @@ bool wxPrintfConvSpec::Parse(const wxChar *format) case wxT('h'): ilen = -1; CHECK_PREC - szFlags[flagofs++] = ch; + szFlags[flagofs++] = (char)ch; break; case wxT('l'): ilen = 1; CHECK_PREC - szFlags[flagofs++] = ch; + szFlags[flagofs++] = (char)ch; break; case wxT('q'): case wxT('L'): ilen = 2; CHECK_PREC - szFlags[flagofs++] = ch; + szFlags[flagofs++] = (char)ch; break; case wxT('Z'): ilen = 3; CHECK_PREC - szFlags[flagofs++] = ch; + szFlags[flagofs++] = (char)ch; break; case wxT('*'): @@ -410,7 +416,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format) // save the * in our formatting buffer... // will be replaced later by Process() - szFlags[flagofs++] = ch; + szFlags[flagofs++] = (char)ch; break; case wxT('1'): case wxT('2'): case wxT('3'): @@ -422,7 +428,7 @@ bool wxPrintfConvSpec::Parse(const wxChar *format) while ( (*argend >= wxT('0')) && (*argend <= wxT('9')) ) { - szFlags[flagofs++] = *argend; + szFlags[flagofs++] = (char)(*argend); len = len*10 + (*argend - wxT('0')); argend++; } @@ -464,8 +470,8 @@ bool wxPrintfConvSpec::Parse(const wxChar *format) case wxT('x'): case wxT('X'): CHECK_PREC - szFlags[flagofs++] = ch; - szFlags[flagofs] = '\0'; + szFlags[flagofs++] = (char)ch; + szFlags[flagofs] = (char)'\0'; if (ilen == 0) type = wxPAT_INT; else if (ilen == -1) @@ -492,8 +498,8 @@ bool wxPrintfConvSpec::Parse(const wxChar *format) case wxT('g'): case wxT('G'): CHECK_PREC - szFlags[flagofs++] = ch; - szFlags[flagofs] = '\0'; + szFlags[flagofs++] = (char)ch; + szFlags[flagofs] = (char)'\0'; if (ilen == 2) type = wxPAT_LONGDOUBLE; else @@ -652,10 +658,10 @@ bool wxPrintfConvSpec::LoadArg(wxPrintfArg *p, va_list &argptr) break; case wxPAT_CHAR: - p->pad_char = va_arg(argptr, int); // char is promoted to int when passed through '...' + p->pad_char = (char)va_arg(argptr, int); // char is promoted to int when passed through '...' break; case wxPAT_WCHAR: - p->pad_wchar = va_arg(argptr, int); // char is promoted to int when passed through '...' + p->pad_wchar = (wchar_t)va_arg(argptr, int); // char is promoted to int when passed through '...' break; case wxPAT_PCHAR: @@ -853,7 +859,7 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p) break; case wxPAT_NSHORTINT: - *p->pad_nshortint = lenCur; + *p->pad_nshortint = (short int)lenCur; break; case wxPAT_NLONGINT: @@ -901,6 +907,36 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p) return lenCur; } +// differences from standard strncpy: +// 1) copies everything from 'source' except for '%%' sequence which is copied as '%' +// 2) returns the number of written characters in 'dest' as it could differ from given 'n' +// 3) much less optimized, unfortunately... +static int wxCopyStrWithPercents(wxChar *dest, const wxChar *source, size_t n) +{ + size_t written = 0; + + if (n == 0) + return 0; + + size_t i; + for ( i = 0; i < n-1; source++, i++) + { + dest[written++] = *source; + if (*(source+1) == wxT('%')) + { + // skip this additional '%' character + source++; + i++; + } + } + + if (i < n) + // copy last character inconditionally + dest[written++] = *source; + + return written; +} + int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax, const wxChar *format, va_list argptr) { @@ -974,6 +1010,7 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax, va_end(ap); + // something failed while loading arguments from the variable list... if (!ok) return -1; @@ -987,8 +1024,7 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax, if (lenCur+tocopy >= lenMax) return -1; // not enough space in the output buffer ! - wxStrncpy(buf+lenCur, toparse, tocopy); - lenCur += tocopy; + lenCur += wxCopyStrWithPercents(buf+lenCur, toparse, tocopy); // process this specifier directly in the output buffer int n = arg[i].Process(buf+lenCur, lenMax - lenCur, &argdata[arg[i].pos]); @@ -1008,8 +1044,9 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax, size_t tocopy = wxStrlen(format) + 1 - ( toparse - format ) ; if (lenCur+tocopy >= lenMax) return -1; // not enough space in the output buffer ! - wxStrncpy(buf+lenCur, toparse, tocopy); - lenCur += tocopy - 1; // the -1 is because of the '\0' + + // the -1 is because of the '\0' + lenCur += wxCopyStrWithPercents(buf+lenCur, toparse, tocopy) - 1; // clean the static array portion used... // NOTE: other arrays do not need cleanup!