]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/strvararg.cpp
fixing RTTI
[wxWidgets.git] / src / common / strvararg.cpp
index 4559748fb4ff8d875c94c1878b064f441c1f6a82..a4c2256dfb474ac44d40fa4c977ecc5288a4d1e3 100644 (file)
@@ -26,6 +26,7 @@
 #include "wx/strvararg.h"
 #include "wx/string.h"
 #include "wx/crt.h"
 #include "wx/strvararg.h"
 #include "wx/string.h"
 #include "wx/crt.h"
+#include "wx/private/wxprintf.h"
 
 // ============================================================================
 // implementation
 
 // ============================================================================
 // implementation
@@ -46,13 +47,17 @@ const wxStringCharType *wxArgNormalizerNative<const wxCStrData&>::get() const
 }
 
 #if wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
 }
 
 #if wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
-wxArgNormalizerWchar<const wxString&>::wxArgNormalizerWchar(const wxString& s)
-    : wxArgNormalizerWithBuffer<wchar_t>(s.wc_str())
+wxArgNormalizerWchar<const wxString&>::wxArgNormalizerWchar(
+                            const wxString& s,
+                            const wxFormatString *fmt, unsigned index)
+    : wxArgNormalizerWithBuffer<wchar_t>(s.wc_str(), fmt, index)
 {
 }
 
 {
 }
 
-wxArgNormalizerWchar<const wxCStrData&>::wxArgNormalizerWchar(const wxCStrData& s)
-    : wxArgNormalizerWithBuffer<wchar_t>(s.AsWCharBuf())
+wxArgNormalizerWchar<const wxCStrData&>::wxArgNormalizerWchar(
+                            const wxCStrData& s,
+                            const wxFormatString *fmt, unsigned index)
+    : wxArgNormalizerWithBuffer<wchar_t>(s.AsWCharBuf(), fmt, index)
 {
 }
 #endif // wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
 {
 }
 #endif // wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
@@ -67,14 +72,14 @@ wxString wxArgNormalizedString::GetString() const
         return wxEmptyString;
 
 #if wxUSE_UTF8_LOCALE_ONLY
         return wxEmptyString;
 
 #if wxUSE_UTF8_LOCALE_ONLY
-    return wxString(wx_reinterpret_cast(const char*, m_ptr));
+    return wxString(reinterpret_cast<const char*>(m_ptr));
 #else
     #if wxUSE_UNICODE_UTF8
         if ( wxLocaleIsUtf8 )
 #else
     #if wxUSE_UNICODE_UTF8
         if ( wxLocaleIsUtf8 )
-            return wxString(wx_reinterpret_cast(const char*, m_ptr));
+            return wxString(reinterpret_cast<const char*>(m_ptr));
         else
     #endif
         else
     #endif
-        return wxString(wx_reinterpret_cast(const wxChar*, m_ptr));
+        return wxString(reinterpret_cast<const wxChar*>(m_ptr));
 #endif // !wxUSE_UTF8_LOCALE_ONLY
 }
 
 #endif // !wxUSE_UTF8_LOCALE_ONLY
 }
 
@@ -128,10 +133,6 @@ wxArgNormalizedString::operator wxString() const
 
    And, of course, the same should be done for %c as well.
 
 
    And, of course, the same should be done for %c as well.
 
-   4) Finally, in UTF-8 build when calling ANSI printf() function, we need to
-      translate %c to %s, because not every Unicode character can be
-      represented by a char.
-
 
    wxScanf() family of functions is simpler, because we don't normalize their
    variadic arguments and we only have to handle 2) above and only for widechar
 
    wxScanf() family of functions is simpler, because we don't normalize their
    variadic arguments and we only have to handle 2) above and only for widechar
@@ -151,30 +152,30 @@ public:
         m_nCopied = 0;
     }
 
         m_nCopied = 0;
     }
 
-    wxCharTypeBuffer<CharType> Convert(const CharType *format)
+    wxScopedCharTypeBuffer<CharType> Convert(const CharType *format)
     {
         // this is reset to NULL if we modify the format string
         m_fmtOrig = format;
 
         while ( *format )
         {
     {
         // this is reset to NULL if we modify the format string
         m_fmtOrig = format;
 
         while ( *format )
         {
-            if ( CopyFmtChar(*format++) == _T('%') )
+            if ( CopyFmtChar(*format++) == wxT('%') )
             {
                 // skip any flags
                 while ( IsFlagChar(*format) )
                     CopyFmtChar(*format++);
 
                 // and possible width
             {
                 // skip any flags
                 while ( IsFlagChar(*format) )
                     CopyFmtChar(*format++);
 
                 // and possible width
-                if ( *format == _T('*') )
+                if ( *format == wxT('*') )
                     CopyFmtChar(*format++);
                 else
                     SkipDigits(&format);
 
                 // precision?
                     CopyFmtChar(*format++);
                 else
                     SkipDigits(&format);
 
                 // precision?
-                if ( *format == _T('.') )
+                if ( *format == wxT('.') )
                 {
                     CopyFmtChar(*format++);
                 {
                     CopyFmtChar(*format++);
-                    if ( *format == _T('*') )
+                    if ( *format == wxT('*') )
                         CopyFmtChar(*format++);
                     else
                         SkipDigits(&format);
                         CopyFmtChar(*format++);
                     else
                         SkipDigits(&format);
@@ -210,16 +211,16 @@ public:
                 // and finally we should have the type
                 switch ( *format )
                 {
                 // and finally we should have the type
                 switch ( *format )
                 {
-                    case _T('S'):
-                    case _T('s'):
+                    case wxT('S'):
+                    case wxT('s'):
                         // all strings were converted into the same form by
                         // wxArgNormalizer<T>, this form depends on the context
                         // in which the value is used (scanf/printf/wprintf):
                         HandleString(*format, size, outConv, outSize);
                         break;
 
                         // all strings were converted into the same form by
                         // wxArgNormalizer<T>, this form depends on the context
                         // in which the value is used (scanf/printf/wprintf):
                         HandleString(*format, size, outConv, outSize);
                         break;
 
-                    case _T('C'):
-                    case _T('c'):
+                    case wxT('C'):
+                    case wxT('c'):
                         HandleChar(*format, size, outConv, outSize);
                         break;
 
                         HandleChar(*format, size, outConv, outSize);
                         break;
 
@@ -239,11 +240,11 @@ public:
                     switch ( outSize )
                     {
                         case Size_Long:
                     switch ( outSize )
                     {
                         case Size_Long:
-                            InsertFmtChar(_T('l'));
+                            InsertFmtChar(wxT('l'));
                             break;
 
                         case Size_Short:
                             break;
 
                         case Size_Short:
-                            InsertFmtChar(_T('h'));
+                            InsertFmtChar(wxT('h'));
                             break;
 
                         case Size_Default:
                             break;
 
                         case Size_Default:
@@ -262,12 +263,14 @@ public:
         // format
         if ( m_fmtOrig )
         {
         // format
         if ( m_fmtOrig )
         {
-            return wxCharTypeBuffer<CharType>::CreateNonOwned(m_fmtOrig);
+            return wxScopedCharTypeBuffer<CharType>::CreateNonOwned(m_fmtOrig);
         }
         else
         {
         }
         else
         {
-            // NULL-terminate converted format string:
-            *m_fmtLast = 0;
+            // shrink converted format string to actual size (instead of
+            // over-sized allocation from CopyAllBefore()) and NUL-terminate
+            // it:
+            m_fmt.shrink(m_fmtLast - m_fmt.data());
             return m_fmt;
         }
     }
             return m_fmt;
         }
     }
@@ -350,13 +353,13 @@ private:
 
     static bool IsFlagChar(CharType ch)
     {
 
     static bool IsFlagChar(CharType ch)
     {
-        return ch == _T('-') || ch == _T('+') ||
-               ch == _T('0') || ch == _T(' ') || ch == _T('#');
+        return ch == wxT('-') || ch == wxT('+') ||
+               ch == wxT('0') || ch == wxT(' ') || ch == wxT('#');
     }
 
     void SkipDigits(const CharType **ptpc)
     {
     }
 
     void SkipDigits(const CharType **ptpc)
     {
-        while ( **ptpc >= _T('0') && **ptpc <= _T('9') )
+        while ( **ptpc >= wxT('0') && **ptpc <= wxT('9') )
             CopyFmtChar(*(*ptpc)++);
     }
 
             CopyFmtChar(*(*ptpc)++);
     }
 
@@ -372,9 +375,7 @@ private:
     size_t m_nCopied;
 };
 
     size_t m_nCopied;
 };
 
-
-
-#ifdef __WINDOWS
+#if defined(__WINDOWS__) && !defined(__CYGWIN__)
 
 // on Windows, we should use %s and %c regardless of the build:
 class wxPrintfFormatConverterWchar : public wxFormatConverterBase<wchar_t>
 
 // on Windows, we should use %s and %c regardless of the build:
 class wxPrintfFormatConverterWchar : public wxFormatConverterBase<wchar_t>
@@ -436,9 +437,10 @@ class wxPrintfFormatConverterUtf8 : public wxFormatConverterBase<char>
                             SizeModifier WXUNUSED(size),
                             CharType& outConv, SizeModifier& outSize)
     {
                             SizeModifier WXUNUSED(size),
                             CharType& outConv, SizeModifier& outSize)
     {
-        // added complication: %c should be translated to %s in UTF-8 build
-        outConv = 's';
-        outSize = Size_Default;
+        // chars are represented using wchar_t in both builds, so this is
+        // the same as above
+        outConv = 'c';
+        outSize = Size_Long;
     }
 };
 #endif // wxUSE_UNICODE_UTF8
     }
 };
 #endif // wxUSE_UNICODE_UTF8
@@ -518,7 +520,7 @@ class wxScanfFormatConverterWchar : public wxFormatConverterBase<wchar_t>
     }
 };
 
     }
 };
 
-const wxWCharBuffer wxScanfConvertFormatW(const wchar_t *format)
+const wxScopedWCharBuffer wxScanfConvertFormatW(const wchar_t *format)
 {
     return wxScanfFormatConverterWchar().Convert(format);
 }
 {
     return wxScanfFormatConverterWchar().Convert(format);
 }
@@ -608,3 +610,107 @@ const wchar_t* wxFormatString::AsWChar()
     return m_convertedWChar.data();
 }
 #endif // wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
     return m_convertedWChar.data();
 }
 #endif // wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
+
+wxString wxFormatString::InputAsString() const
+{
+    if ( m_str )
+        return *m_str;
+    if ( m_cstr )
+        return m_cstr->AsString();
+    if ( m_wchar )
+        return wxString(m_wchar);
+    if ( m_char )
+        return wxString(m_char);
+
+    wxFAIL_MSG( "invalid wxFormatString - not initialized?" );
+    return wxString();
+}
+
+// ----------------------------------------------------------------------------
+// wxFormatString::GetArgumentType()
+// ----------------------------------------------------------------------------
+
+namespace
+{
+
+template<typename CharType>
+wxFormatString::ArgumentType DoGetArgumentType(const CharType *format,
+                                               unsigned n)
+{
+    wxCHECK_MSG( format, wxFormatString::Arg_Unknown,
+                 "empty format string not allowed here" );
+
+    wxPrintfConvSpecParser<CharType> parser(format);
+
+    wxCHECK_MSG( n <= parser.nargs, wxFormatString::Arg_Unknown,
+                 "more arguments than format string specifiers?" );
+
+    wxCHECK_MSG( parser.pspec[n-1] != NULL, wxFormatString::Arg_Unknown,
+                 "requested argument not found - invalid format string?" );
+
+    switch ( parser.pspec[n-1]->m_type )
+    {
+        case wxPAT_CHAR:
+        case wxPAT_WCHAR:
+            return wxFormatString::Arg_Char;
+
+        case wxPAT_PCHAR:
+        case wxPAT_PWCHAR:
+            return wxFormatString::Arg_String;
+
+        case wxPAT_INT:
+            return wxFormatString::Arg_Int;
+        case wxPAT_LONGINT:
+            return wxFormatString::Arg_LongInt;
+#ifdef wxLongLong_t
+        case wxPAT_LONGLONGINT:
+            return wxFormatString::Arg_LongLongInt;
+#endif
+        case wxPAT_SIZET:
+            return wxFormatString::Arg_Size_t;
+
+        case wxPAT_DOUBLE:
+            return wxFormatString::Arg_Double;
+        case wxPAT_LONGDOUBLE:
+            return wxFormatString::Arg_LongDouble;
+
+        case wxPAT_POINTER:
+            return wxFormatString::Arg_Pointer;
+
+        case wxPAT_NINT:
+            return wxFormatString::Arg_IntPtr;
+        case wxPAT_NSHORTINT:
+            return wxFormatString::Arg_ShortIntPtr;
+        case wxPAT_NLONGINT:
+            return wxFormatString::Arg_LongIntPtr;
+
+        case wxPAT_STAR:
+            // "*" requires argument of type int
+            return wxFormatString::Arg_Int;
+
+        case wxPAT_INVALID:
+            // (handled after the switch statement)
+            break;
+    }
+
+    // silence warning
+    wxFAIL_MSG( "unexpected argument type" );
+    return wxFormatString::Arg_Unknown;
+}
+
+} // anonymous namespace
+
+wxFormatString::ArgumentType wxFormatString::GetArgumentType(unsigned n) const
+{
+    if ( m_char )
+        return DoGetArgumentType(m_char.data(), n);
+    else if ( m_wchar )
+        return DoGetArgumentType(m_wchar.data(), n);
+    else if ( m_str )
+        return DoGetArgumentType(m_str->wx_str(), n);
+    else if ( m_cstr )
+        return DoGetArgumentType(m_cstr->AsInternal(), n);
+
+    wxFAIL_MSG( "unreachable code" );
+    return Arg_Unknown;
+}