Merge branch 'use-template-for-vararg-funcs'
Use variadic templates for implementing the vararg functions. See #22981.
This commit is contained in:
commit
d0af75e88d
18 changed files with 395 additions and 399 deletions
2
.github/workflows/code_checks.yml
vendored
2
.github/workflows/code_checks.yml
vendored
|
|
@ -90,7 +90,7 @@ jobs:
|
|||
if git diff origin/master \
|
||||
':!.github/workflows/code_checks.yml' \
|
||||
':!src/stc/scintilla/' \
|
||||
| grep -E '^\+.*(wxOVERRIDE|wxNOEXCEPT|\WNULL)'; then
|
||||
| grep -E '^\+.*(wxOVERRIDE|wxNOEXCEPT|[^_@]NULL)'; then
|
||||
echo "::error ::Please use C++11 equivalents of the deprecated macros in the new code."
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
216
include/wx/log.h
216
include/wx/log.h
|
|
@ -26,7 +26,6 @@ typedef unsigned long wxLogLevel;
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "wx/string.h"
|
||||
#include "wx/strvararg.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// forward declarations
|
||||
|
|
@ -882,7 +881,7 @@ public:
|
|||
// remember that fatal errors can't be disabled
|
||||
if ( m_level == wxLOG_FatalError ||
|
||||
wxLog::IsLevelEnabled(m_level, wxASCII_STR(m_info.component)) )
|
||||
DoCallOnLog(format, argptr);
|
||||
DoCallOnLog(wxString::FormatV(format, argptr));
|
||||
}
|
||||
|
||||
// overloads used by functions with optional leading arguments (whose
|
||||
|
|
@ -912,173 +911,87 @@ public:
|
|||
}
|
||||
|
||||
|
||||
// vararg functions used by wxLogXXX():
|
||||
// variadic functions used by wxLogXXX():
|
||||
|
||||
// we need to use an extra class with a more restricted set of ctors than
|
||||
// wxString itself, as otherwise we'd get ambiguities between constructing
|
||||
// wxString from long
|
||||
struct FormatString : wxString
|
||||
{
|
||||
FormatString(const wxString& str) : wxString(str) {}
|
||||
FormatString(const wxCStrData& str) : wxString(str) {}
|
||||
FormatString(const wchar_t *str) : wxString(str) {}
|
||||
FormatString(const wxScopedWCharBuffer& str) : wxString(str) {}
|
||||
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
|
||||
FormatString(const char *str) : wxString(str) {}
|
||||
FormatString(const wxScopedCharBuffer& str) : wxString(str) {}
|
||||
#endif // !wxNO_IMPLICIT_WXSTRING_ENCODING
|
||||
};
|
||||
|
||||
// will log the message at the level specified in the ctor
|
||||
//
|
||||
// notice that this function supposes that the caller already checked that
|
||||
// the level was enabled and does no checks itself
|
||||
WX_DEFINE_VARARG_FUNC_VOID
|
||||
(
|
||||
Log,
|
||||
1, (const wxFormatString&),
|
||||
DoLog, DoLogUtf8
|
||||
)
|
||||
template <typename... Targs>
|
||||
void Log(const FormatString& format, Targs... args)
|
||||
{
|
||||
DoCallOnLog(wxString::Format(format, args...));
|
||||
}
|
||||
|
||||
// same as Log() but with an extra numeric or pointer parameters: this is
|
||||
// used to pass an optional value by storing it in m_info under the name
|
||||
// passed to MaybeStore() and is required to support "overloaded" versions
|
||||
// of wxLogStatus() and wxLogSysError()
|
||||
WX_DEFINE_VARARG_FUNC_VOID
|
||||
(
|
||||
Log,
|
||||
2, (long, const wxFormatString&),
|
||||
DoLogWithNum, DoLogWithNumUtf8
|
||||
)
|
||||
template <typename... Targs>
|
||||
void Log(long num, const FormatString& format, Targs... args)
|
||||
{
|
||||
Store(m_optKey, num);
|
||||
|
||||
DoCallOnLog(wxString::Format(format, args...));
|
||||
}
|
||||
|
||||
// unfortunately we can't use "void *" here as we get overload ambiguities
|
||||
// with Log(wxFormatString, ...) when the first argument is a "char *" or
|
||||
// with Log(FormatString, ...) when the first argument is a "char *" or
|
||||
// "wchar_t *" then -- so we only allow passing wxObject here, which is
|
||||
// ugly but fine in practice as this overload is only used by wxLogStatus()
|
||||
// whose first argument is a wxFrame
|
||||
WX_DEFINE_VARARG_FUNC_VOID
|
||||
(
|
||||
Log,
|
||||
2, (wxObject *, const wxFormatString&),
|
||||
DoLogWithPtr, DoLogWithPtrUtf8
|
||||
)
|
||||
template <typename... Targs>
|
||||
void Log(wxObject* ptr, const FormatString& format, Targs... args)
|
||||
{
|
||||
Store(m_optKey, wxPtrToUInt(ptr));
|
||||
|
||||
DoCallOnLog(wxString::Format(format, args...));
|
||||
}
|
||||
|
||||
// log the message at the level specified as its first argument
|
||||
//
|
||||
// as the macros don't have access to the level argument in this case, this
|
||||
// function does check that the level is enabled itself
|
||||
WX_DEFINE_VARARG_FUNC_VOID
|
||||
(
|
||||
LogAtLevel,
|
||||
2, (wxLogLevel, const wxFormatString&),
|
||||
DoLogAtLevel, DoLogAtLevelUtf8
|
||||
)
|
||||
template <typename... Targs>
|
||||
void LogAtLevel(wxLogLevel level, const wxString& format, Targs... args)
|
||||
{
|
||||
if ( !wxLog::IsLevelEnabled(level, wxASCII_STR(m_info.component)) )
|
||||
return;
|
||||
|
||||
DoCallOnLog(level, wxString::Format(format, args...));
|
||||
}
|
||||
|
||||
// special versions for wxLogTrace() which is passed either string or
|
||||
// integer mask as first argument determining whether the message should be
|
||||
// logged or not
|
||||
WX_DEFINE_VARARG_FUNC_VOID
|
||||
(
|
||||
LogTrace,
|
||||
2, (const wxString&, const wxFormatString&),
|
||||
DoLogTrace, DoLogTraceUtf8
|
||||
)
|
||||
template <typename... Targs>
|
||||
void LogTrace(const wxString& mask, const wxString& format, Targs... args)
|
||||
{
|
||||
if ( !wxLog::IsAllowedTraceMask(mask) )
|
||||
return;
|
||||
|
||||
Store(wxLOG_KEY_TRACE_MASK, mask);
|
||||
|
||||
DoCallOnLog(wxString::Format(format, args...));
|
||||
}
|
||||
|
||||
private:
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
void DoLog(const wxChar *format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
DoCallOnLog(format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void DoLogWithNum(long num, const wxChar *format, ...)
|
||||
{
|
||||
Store(m_optKey, num);
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
DoCallOnLog(format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void DoLogWithPtr(void *ptr, const wxChar *format, ...)
|
||||
{
|
||||
Store(m_optKey, wxPtrToUInt(ptr));
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
DoCallOnLog(format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void DoLogAtLevel(wxLogLevel level, const wxChar *format, ...)
|
||||
{
|
||||
if ( !wxLog::IsLevelEnabled(level, wxASCII_STR(m_info.component)) )
|
||||
return;
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
DoCallOnLog(level, format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void DoLogTrace(const wxString& mask, const wxChar *format, ...)
|
||||
{
|
||||
if ( !wxLog::IsAllowedTraceMask(mask) )
|
||||
return;
|
||||
|
||||
Store(wxLOG_KEY_TRACE_MASK, mask);
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
DoCallOnLog(format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
#endif // !wxUSE_UTF8_LOCALE_ONLY
|
||||
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
void DoLogUtf8(const char *format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
DoCallOnLog(format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void DoLogWithNumUtf8(long num, const char *format, ...)
|
||||
{
|
||||
Store(m_optKey, num);
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
DoCallOnLog(format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void DoLogWithPtrUtf8(void *ptr, const char *format, ...)
|
||||
{
|
||||
Store(m_optKey, wxPtrToUInt(ptr));
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
DoCallOnLog(format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void DoLogAtLevelUtf8(wxLogLevel level, const char *format, ...)
|
||||
{
|
||||
if ( !wxLog::IsLevelEnabled(level, wxASCII_STR(m_info.component)) )
|
||||
return;
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
DoCallOnLog(level, format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void DoLogTraceUtf8(const wxString& mask, const char *format, ...)
|
||||
{
|
||||
if ( !wxLog::IsAllowedTraceMask(mask) )
|
||||
return;
|
||||
|
||||
Store(wxLOG_KEY_TRACE_MASK, mask);
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
DoCallOnLog(format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
#endif // wxUSE_UNICODE_UTF8
|
||||
|
||||
void DoCallOnLog(wxLogLevel level, const wxString& format, va_list argptr)
|
||||
void DoCallOnLog(wxLogLevel level, const wxString& msg)
|
||||
{
|
||||
// As explained in wxLogRecordInfo ctor, we don't initialize its
|
||||
// timestamp to avoid calling time() unnecessary, but now that we are
|
||||
|
|
@ -1089,12 +1002,12 @@ private:
|
|||
m_info.timestamp = m_info.timestampMS / 1000;
|
||||
#endif // WXWIN_COMPATIBILITY_3_0
|
||||
|
||||
wxLog::OnLog(level, wxString::FormatV(format, argptr), m_info);
|
||||
wxLog::OnLog(level, msg, m_info);
|
||||
}
|
||||
|
||||
void DoCallOnLog(const wxString& format, va_list argptr)
|
||||
void DoCallOnLog(const wxString& msg)
|
||||
{
|
||||
DoCallOnLog(m_level, format, argptr);
|
||||
DoCallOnLog(m_level, msg);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1272,14 +1185,17 @@ WXDLLIMPEXP_BASE wxString wxSysErrorMsgStr(unsigned long nErrCode = 0);
|
|||
|
||||
// define macros for defining log functions which do nothing at all
|
||||
#define wxDEFINE_EMPTY_LOG_FUNCTION(level) \
|
||||
WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wxFormatString&)) \
|
||||
inline void wxVLog##level(const wxFormatString& WXUNUSED(format), \
|
||||
template <typename... Targs> \
|
||||
void wxLog##level(const wxString& WXUNUSED(format), Targs...) { } \
|
||||
inline void wxVLog##level(const wxString& WXUNUSED(format), \
|
||||
va_list WXUNUSED(argptr)) { } \
|
||||
|
||||
#define wxDEFINE_EMPTY_LOG_FUNCTION2(level, argclass) \
|
||||
WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxFormatString&)) \
|
||||
template <typename... Targs> \
|
||||
void wxLog##level(argclass WXUNUSED(arg), \
|
||||
const wxString& WXUNUSED(format), Targs...) { } \
|
||||
inline void wxVLog##level(argclass WXUNUSED(arg), \
|
||||
const wxFormatString& WXUNUSED(format), \
|
||||
const wxString& WXUNUSED(format), \
|
||||
va_list WXUNUSED(argptr)) {}
|
||||
|
||||
wxDEFINE_EMPTY_LOG_FUNCTION(FatalError);
|
||||
|
|
|
|||
|
|
@ -1111,6 +1111,12 @@ namespace std
|
|||
// it doesn't seem necessary).
|
||||
#include "wx/strvararg.h"
|
||||
|
||||
template<>
|
||||
struct wxFormatStringSpecifier<wxLongLong>
|
||||
{
|
||||
enum { value = wxFormatString::Arg_LongLongInt };
|
||||
};
|
||||
|
||||
template<>
|
||||
struct WXDLLIMPEXP_BASE wxArgNormalizer<wxLongLong>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -118,42 +118,18 @@ private:
|
|||
class WXDLLIMPEXP_BASE wxFileTypeInfo
|
||||
{
|
||||
private:
|
||||
void DoVarArgInit(const wxString& mimeType,
|
||||
const wxString& openCmd,
|
||||
const wxString& printCmd,
|
||||
const wxString& desc,
|
||||
va_list argptr);
|
||||
// Helpers of variadic ctor.
|
||||
void DoAddExts() { }
|
||||
void DoAddExts(std::nullptr_t) { }
|
||||
|
||||
void VarArgInit(const wxString *mimeType,
|
||||
const wxString *openCmd,
|
||||
const wxString *printCmd,
|
||||
const wxString *desc,
|
||||
// the other parameters form a nullptr terminated list of
|
||||
// extensions
|
||||
...);
|
||||
template <typename... Targs>
|
||||
void DoAddExts(const wxString& ext, Targs... extensions)
|
||||
{
|
||||
AddExtension(ext);
|
||||
DoAddExts(extensions...);
|
||||
}
|
||||
|
||||
public:
|
||||
// NB: This is a helper to get implicit conversion of variadic ctor's
|
||||
// fixed arguments into something that can be passed to VarArgInit().
|
||||
// Do not use, it's used by the ctor only.
|
||||
struct CtorString
|
||||
{
|
||||
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
|
||||
CtorString(const char *str) : m_str(str) {}
|
||||
#endif
|
||||
CtorString(const wchar_t *str) : m_str(str) {}
|
||||
CtorString(const wxString& str) : m_str(str) {}
|
||||
CtorString(const wxCStrData& str) : m_str(str) {}
|
||||
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
|
||||
CtorString(const wxScopedCharBuffer& str) : m_str(str) {}
|
||||
#endif
|
||||
CtorString(const wxScopedWCharBuffer& str) : m_str(str) {}
|
||||
|
||||
operator const wxString*() const { return &m_str; }
|
||||
|
||||
wxString m_str;
|
||||
};
|
||||
|
||||
// ctors
|
||||
|
||||
// Ctor specifying just the MIME type (which is mandatory), the other
|
||||
|
|
@ -163,21 +139,21 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
// Ctor allowing to specify the values of all fields at once:
|
||||
//
|
||||
// wxFileTypeInfo(const wxString& mimeType,
|
||||
// const wxString& openCmd,
|
||||
// const wxString& printCmd,
|
||||
// const wxString& desc,
|
||||
// // the other parameters form a list of extensions for this
|
||||
// // file type and should be terminated with nullptr
|
||||
// ...);
|
||||
WX_DEFINE_VARARG_FUNC_CTOR(wxFileTypeInfo,
|
||||
4, (const CtorString&,
|
||||
const CtorString&,
|
||||
const CtorString&,
|
||||
const CtorString&),
|
||||
VarArgInit, VarArgInit)
|
||||
// Ctor allowing to specify the values of all fields at once and also
|
||||
// allowing to specify the list of additional extensions for this file type
|
||||
template <typename... Targs>
|
||||
wxFileTypeInfo(const wxString& mimeType,
|
||||
const wxString& openCmd,
|
||||
const wxString& printCmd,
|
||||
const wxString& description,
|
||||
Targs... extensions)
|
||||
: m_mimeType{mimeType},
|
||||
m_openCmd{openCmd},
|
||||
m_printCmd{printCmd},
|
||||
m_desc{description}
|
||||
{
|
||||
DoAddExts(extensions...);
|
||||
}
|
||||
|
||||
// the array elements correspond to the parameters of the ctor above in
|
||||
// the same order
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "wx/defs.h"
|
||||
#include "wx/chartype.h"
|
||||
#include "wx/strvararg.h"
|
||||
#include "wx/string.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxMessageOutput is a class abstracting formatted output target, i.e.
|
||||
|
|
@ -37,22 +36,16 @@ public:
|
|||
static wxMessageOutput* Set(wxMessageOutput* msgout);
|
||||
|
||||
// show a message to the user
|
||||
// void Printf(const wxString& format, ...) = 0;
|
||||
WX_DEFINE_VARARG_FUNC_VOID(Printf, 1, (const wxFormatString&),
|
||||
DoPrintfWchar, DoPrintfUtf8)
|
||||
template <typename FormatString, typename... Targs>
|
||||
void Printf(FormatString format, Targs... args)
|
||||
{
|
||||
Output(wxString::Format(format, args...));
|
||||
}
|
||||
|
||||
// called by DoPrintf() to output formatted string but can also be called
|
||||
// directly if no formatting is needed
|
||||
virtual void Output(const wxString& str) = 0;
|
||||
|
||||
protected:
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
void DoPrintfWchar(const wxChar *format, ...);
|
||||
#endif
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
void DoPrintfUtf8(const char *format, ...);
|
||||
#endif
|
||||
|
||||
private:
|
||||
static wxMessageOutput* ms_msgOut;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "wx/beforestd.h"
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include "wx/afterstd.h"
|
||||
|
||||
// by default we cache the mapping of the positions in UTF-8 string to the byte
|
||||
|
|
@ -2195,17 +2196,34 @@ public:
|
|||
|
||||
// formatted input/output
|
||||
// as sprintf(), returns the number of characters written or < 0 on error
|
||||
// (take 'this' into account in attribute parameter count)
|
||||
// int Printf(const wxString& format, ...);
|
||||
WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wxFormatString&),
|
||||
DoPrintfWchar, DoPrintfUtf8)
|
||||
template <typename... Targs>
|
||||
int Printf(const wxFormatString& format, Targs... args)
|
||||
{
|
||||
format.Validate({wxFormatStringSpecifier<Targs>::value...});
|
||||
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
if ( wxLocaleIsUtf8 )
|
||||
#endif
|
||||
return DoPrintfUtf8(format, wxArgNormalizerUtf8<Targs>{args, nullptr, 0}.get()...);
|
||||
#endif // wxUSE_UNICODE_UTF8
|
||||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
return DoPrintfWchar(format, wxArgNormalizerWchar<Targs>{args, nullptr, 0}.get()...);
|
||||
#endif // !wxUSE_UTF8_LOCALE_ONLY
|
||||
}
|
||||
|
||||
// as vprintf(), returns the number of characters written or < 0 on error
|
||||
int PrintfV(const wxString& format, va_list argptr);
|
||||
|
||||
// returns the string containing the result of Printf() to it
|
||||
// static wxString Format(const wxString& format, ...) WX_ATTRIBUTE_PRINTF_1;
|
||||
WX_DEFINE_VARARG_FUNC(static wxString, Format, 1, (const wxFormatString&),
|
||||
DoFormatWchar, DoFormatUtf8)
|
||||
template <typename... Targs>
|
||||
static wxString Format(const wxFormatString& format, Targs... args)
|
||||
{
|
||||
wxString s;
|
||||
s.Printf(format, args...);
|
||||
return s;
|
||||
}
|
||||
// the same as above, but takes a va_list
|
||||
static wxString FormatV(const wxString& format, va_list argptr);
|
||||
|
||||
|
|
@ -2228,10 +2246,11 @@ public:
|
|||
enum stripType {leading = 0x1, trailing = 0x2, both = 0x3};
|
||||
|
||||
// use Printf()
|
||||
// (take 'this' into account in attribute parameter count)
|
||||
// int sprintf(const wxString& format, ...) WX_ATTRIBUTE_PRINTF_2;
|
||||
WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const wxFormatString&),
|
||||
DoPrintfWchar, DoPrintfUtf8)
|
||||
template <typename... Targs>
|
||||
int sprintf(const wxFormatString& format, Targs... args)
|
||||
{
|
||||
return Printf(format, args...);
|
||||
}
|
||||
|
||||
// use Cmp()
|
||||
int CompareTo(const wxChar* psz, caseCompare cmp = exact) const
|
||||
|
|
@ -3375,11 +3394,9 @@ public:
|
|||
private:
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
int DoPrintfWchar(const wxChar *format, ...);
|
||||
static wxString DoFormatWchar(const wxChar *format, ...);
|
||||
#endif
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
int DoPrintfUtf8(const char *format, ...);
|
||||
static wxString DoFormatUtf8(const char *format, ...);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,17 @@
|
|||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
This header contains helpers for implementing printf-like functions in
|
||||
wxWidgets as well as legacy WX_DEFINE_VARARG_FUNC macros that are not used
|
||||
by wxWidgets itself any more, but are preserved here as they can be used in
|
||||
the application code (even if they had never been part of documented API).
|
||||
|
||||
The only non-deprecated parts of this header are wxFormatString class and
|
||||
wxFormatStringSpecifier and wxArgNormalizer templates, which are used by
|
||||
wxWidgets itself.
|
||||
*/
|
||||
|
||||
#ifndef _WX_STRVARARG_H_
|
||||
#define _WX_STRVARARG_H_
|
||||
|
||||
|
|
@ -20,6 +31,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __cpp_lib_string_view
|
||||
#include <string_view>
|
||||
|
|
@ -195,6 +207,10 @@ public:
|
|||
Arg_Unknown = 0x8000 // unrecognized specifier (likely error)
|
||||
};
|
||||
|
||||
// Validate all format string parameters at once: the vector contains the
|
||||
// format specifiers corresponding to the actually given arguments.
|
||||
void Validate(const std::vector<int>& argTypes) const;
|
||||
|
||||
// returns the type of format specifier for n-th variadic argument (this is
|
||||
// not necessarily n-th format specifier if positional specifiers are used);
|
||||
// called by wxArgNormalizer<> specializations to get information about
|
||||
|
|
@ -335,6 +351,13 @@ struct wxFormatStringArgumentFinder<wxWCharBuffer>
|
|||
#define wxASSERT_ARG_TYPE(fmt, index, expected_mask) \
|
||||
wxUnusedVar(fmt); \
|
||||
wxUnusedVar(index)
|
||||
|
||||
// Also provide a trivial implementation of Validate() doing nothing in
|
||||
// this case.
|
||||
inline void
|
||||
wxFormatString::Validate(const std::vector<int>& WXUNUSED(argTypes)) const
|
||||
{
|
||||
}
|
||||
#endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL
|
||||
|
||||
|
||||
|
|
@ -384,6 +407,9 @@ struct wxFormatStringSpecifier<const T*>
|
|||
};
|
||||
|
||||
wxFORMAT_STRING_SPECIFIER(bool, wxFormatString::Arg_Int)
|
||||
wxFORMAT_STRING_SPECIFIER(char, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
|
||||
wxFORMAT_STRING_SPECIFIER(signed char, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
|
||||
wxFORMAT_STRING_SPECIFIER(unsigned char, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
|
||||
wxFORMAT_STRING_SPECIFIER(int, wxFormatString::Arg_Int)
|
||||
wxFORMAT_STRING_SPECIFIER(unsigned int, wxFormatString::Arg_Int)
|
||||
wxFORMAT_STRING_SPECIFIER(short int, wxFormatString::Arg_Int)
|
||||
|
|
@ -401,6 +427,8 @@ wxFORMAT_STRING_SPECIFIER(long double, wxFormatString::Arg_LongDouble)
|
|||
#if wxWCHAR_T_IS_REAL_TYPE
|
||||
wxFORMAT_STRING_SPECIFIER(wchar_t, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
|
||||
#endif
|
||||
wxFORMAT_STRING_SPECIFIER(wxUniChar, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
|
||||
wxFORMAT_STRING_SPECIFIER(wxUniCharRef, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
|
||||
|
||||
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
|
||||
wxFORMAT_STRING_SPECIFIER(char*, wxFormatString::Arg_String)
|
||||
|
|
@ -409,6 +437,12 @@ wxFORMAT_STRING_SPECIFIER(signed char*, wxFormatString::Arg_String)
|
|||
wxFORMAT_STRING_SPECIFIER(const char*, wxFormatString::Arg_String)
|
||||
wxFORMAT_STRING_SPECIFIER(const unsigned char*, wxFormatString::Arg_String)
|
||||
wxFORMAT_STRING_SPECIFIER(const signed char*, wxFormatString::Arg_String)
|
||||
wxFORMAT_STRING_SPECIFIER(wxCharBuffer, wxFormatString::Arg_String)
|
||||
wxFORMAT_STRING_SPECIFIER(wxScopedCharBuffer, wxFormatString::Arg_String)
|
||||
wxFORMAT_STRING_SPECIFIER(std::string, wxFormatString::Arg_String)
|
||||
#ifdef __cpp_lib_string_view
|
||||
wxFORMAT_STRING_SPECIFIER(std::string_view, wxFormatString::Arg_String)
|
||||
#endif
|
||||
#else // wxNO_IMPLICIT_WXSTRING_ENCODING
|
||||
wxDISABLED_FORMAT_STRING_SPECIFIER(char*)
|
||||
wxDISABLED_FORMAT_STRING_SPECIFIER(unsigned char*)
|
||||
|
|
@ -420,6 +454,12 @@ wxDISABLED_FORMAT_STRING_SPECIFIER(const signed char*)
|
|||
wxFORMAT_STRING_SPECIFIER(wchar_t*, wxFormatString::Arg_String)
|
||||
wxFORMAT_STRING_SPECIFIER(const wchar_t*, wxFormatString::Arg_String)
|
||||
|
||||
wxFORMAT_STRING_SPECIFIER(wxWCharBuffer, wxFormatString::Arg_String)
|
||||
wxFORMAT_STRING_SPECIFIER(wxScopedWCharBuffer, wxFormatString::Arg_String)
|
||||
wxFORMAT_STRING_SPECIFIER(wxString, wxFormatString::Arg_String)
|
||||
wxFORMAT_STRING_SPECIFIER(wxCStrData, wxFormatString::Arg_String)
|
||||
wxFORMAT_STRING_SPECIFIER(std::wstring, wxFormatString::Arg_String)
|
||||
|
||||
wxFORMAT_STRING_SPECIFIER(int*, wxFormatString::Arg_IntPtr | wxFormatString::Arg_Pointer)
|
||||
wxFORMAT_STRING_SPECIFIER(short int*, wxFormatString::Arg_ShortIntPtr | wxFormatString::Arg_Pointer)
|
||||
wxFORMAT_STRING_SPECIFIER(long int*, wxFormatString::Arg_LongIntPtr | wxFormatString::Arg_Pointer)
|
||||
|
|
@ -442,6 +482,10 @@ struct wxArgNormalizer
|
|||
// to printf-like format string or nullptr if the variadic function doesn't
|
||||
// use format string and 'index' is index of 'value' in variadic arguments
|
||||
// list (starting at 1)
|
||||
//
|
||||
// Because the format string and index are used for checking for the format
|
||||
// specifier mismatches and can be nullptr and 0, respectively, if they had
|
||||
// been already checked using wxFormatString::Validate().
|
||||
wxArgNormalizer(T value,
|
||||
const wxFormatString *fmt, unsigned index)
|
||||
: m_value(value)
|
||||
|
|
@ -467,6 +511,7 @@ struct wxArgNormalizerWchar : public wxArgNormalizer<T>
|
|||
const wxFormatString *fmt, unsigned index)
|
||||
: wxArgNormalizer<T>(value, fmt, index) {}
|
||||
};
|
||||
|
||||
#endif // !wxUSE_UTF8_LOCALE_ONLY
|
||||
|
||||
// normalizer for passing arguments to functions working with UTF-8 encoded
|
||||
|
|
@ -834,9 +879,7 @@ struct wxArgNormalizerNarrowChar
|
|||
wxASSERT_ARG_TYPE( fmt, index,
|
||||
wxFormatString::Arg_Char | wxFormatString::Arg_Int );
|
||||
|
||||
// We use char if there is no format string at all, i.e. when used like
|
||||
// e.g. Foo("foo", "bar", 'c', nullptr), but is this the bast choice?
|
||||
if ( !fmt || fmt->GetArgumentType(index) == wxFormatString::Arg_Char )
|
||||
if ( fmt && fmt->GetArgumentType(index) == wxFormatString::Arg_Char )
|
||||
m_value = wx_truncate_cast(T, wxUniChar(value).GetValue());
|
||||
else
|
||||
m_value = value;
|
||||
|
|
|
|||
|
|
@ -237,21 +237,43 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxGCC_ONLY_WARNING_SUPPRESS(format-nonliteral)
|
||||
wxGCC_ONLY_WARNING_SUPPRESS(format-security)
|
||||
|
||||
WX_DEFINE_VARARG_FUNC_SANS_N0(int, wxPrintf, 1, (const wxFormatString&),
|
||||
wxCRT_PrintfW, wxCRT_PrintfA)
|
||||
inline int wxPrintf(const wxFormatString& s)
|
||||
template <typename... Targs>
|
||||
int wxPrintf(const wxFormatString& format, Targs... args)
|
||||
{
|
||||
return wxPrintf(wxASCII_STR("%s"), s.InputAsString());
|
||||
format.Validate({wxFormatStringSpecifier<Targs>::value...});
|
||||
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
if ( wxLocaleIsUtf8 )
|
||||
#endif
|
||||
return wxCRT_PrintfA(format, wxArgNormalizerUtf8<Targs>{args, nullptr, 0}.get()...);
|
||||
#endif // wxUSE_UNICODE_UTF8
|
||||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
return wxCRT_PrintfW(format, wxArgNormalizerWchar<Targs>{args, nullptr, 0}.get()...);
|
||||
#endif // !wxUSE_UTF8_LOCALE_ONLY
|
||||
}
|
||||
|
||||
WX_DEFINE_VARARG_FUNC_SANS_N0(int, wxFprintf, 2, (FILE*, const wxFormatString&),
|
||||
wxCRT_FprintfW, wxCRT_FprintfA)
|
||||
inline int wxFprintf(FILE *f, const wxFormatString& s)
|
||||
template <typename... Targs>
|
||||
int wxFprintf(FILE* fp, const wxFormatString& format, Targs... args)
|
||||
{
|
||||
return wxFprintf(f, wxASCII_STR("%s"), s.InputAsString());
|
||||
format.Validate({wxFormatStringSpecifier<Targs>::value...});
|
||||
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
if ( wxLocaleIsUtf8 )
|
||||
#endif
|
||||
return wxCRT_FprintfA(fp, format, wxArgNormalizerUtf8<Targs>{args, nullptr, 0}.get()...);
|
||||
#endif // wxUSE_UNICODE_UTF8
|
||||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
return wxCRT_FprintfW(fp, format, wxArgNormalizerWchar<Targs>{args, nullptr, 0}.get()...);
|
||||
#endif // !wxUSE_UTF8_LOCALE_ONLY
|
||||
}
|
||||
|
||||
wxGCC_ONLY_WARNING_RESTORE(format-security)
|
||||
wxGCC_ONLY_WARNING_RESTORE(format-nonliteral)
|
||||
|
||||
// va_list versions of printf functions simply forward to the respective
|
||||
|
|
@ -296,49 +318,70 @@ wxVfprintf(FILE *f, const wxString& format, va_list ap)
|
|||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
int WXDLLIMPEXP_BASE wxDoSprintfWchar(char *str, const wxChar *format, ...);
|
||||
int WXDLLIMPEXP_BASE wxDoSprintfWchar(wchar_t *str, const wxChar *format, ...);
|
||||
#endif
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
int WXDLLIMPEXP_BASE wxDoSprintfUtf8(char *str, const char *format, ...);
|
||||
int WXDLLIMPEXP_BASE wxDoSprintfUtf8(wchar_t *str, const char *format, ...);
|
||||
#endif
|
||||
WX_DEFINE_VARARG_FUNC(int, wxSprintf, 2, (char*, const wxFormatString&),
|
||||
wxDoSprintfWchar, wxDoSprintfUtf8)
|
||||
|
||||
template <typename CharType, typename... Targs>
|
||||
int wxSprintf(CharType* str, const wxFormatString& format, Targs... args)
|
||||
{
|
||||
format.Validate({wxFormatStringSpecifier<Targs>::value...});
|
||||
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
if ( wxLocaleIsUtf8 )
|
||||
#endif
|
||||
return wxDoSprintfUtf8(str, format, wxArgNormalizerUtf8<Targs>{args, nullptr, 0}.get()...);
|
||||
#endif // wxUSE_UNICODE_UTF8
|
||||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
return wxDoSprintfWchar(str, format, wxArgNormalizerWchar<Targs>{args, nullptr, 0}.get()...);
|
||||
#endif // !wxUSE_UTF8_LOCALE_ONLY
|
||||
}
|
||||
|
||||
int WXDLLIMPEXP_BASE
|
||||
wxVsprintf(char *str, const wxString& format, va_list argptr);
|
||||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
int WXDLLIMPEXP_BASE wxDoSnprintfWchar(char *str, size_t size, const wxChar *format, ...);
|
||||
int WXDLLIMPEXP_BASE wxDoSnprintfWchar(wchar_t *str, size_t size, const wxChar *format, ...);
|
||||
#endif
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
int WXDLLIMPEXP_BASE wxDoSnprintfUtf8(char *str, size_t size, const char *format, ...);
|
||||
int WXDLLIMPEXP_BASE wxDoSnprintfUtf8(wchar_t *str, size_t size, const char *format, ...);
|
||||
#endif
|
||||
WX_DEFINE_VARARG_FUNC(int, wxSnprintf, 3, (char*, size_t, const wxFormatString&),
|
||||
wxDoSnprintfWchar, wxDoSnprintfUtf8)
|
||||
|
||||
template <typename CharType, typename... Targs>
|
||||
int wxSnprintf(CharType* str, size_t size, const wxFormatString& format, Targs... args)
|
||||
{
|
||||
format.Validate({wxFormatStringSpecifier<Targs>::value...});
|
||||
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
if ( wxLocaleIsUtf8 )
|
||||
#endif
|
||||
return wxDoSnprintfUtf8(str, size, format, wxArgNormalizerUtf8<Targs>{args, nullptr, 0}.get()...);
|
||||
#endif // wxUSE_UNICODE_UTF8
|
||||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
return wxDoSnprintfWchar(str, size, format, wxArgNormalizerWchar<Targs>{args, nullptr, 0}.get()...);
|
||||
#endif // !wxUSE_UTF8_LOCALE_ONLY
|
||||
}
|
||||
|
||||
int WXDLLIMPEXP_BASE
|
||||
wxVsnprintf(char *str, size_t size, const wxString& format, va_list argptr);
|
||||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
int WXDLLIMPEXP_BASE wxDoSprintfWchar(wchar_t *str, const wxChar *format, ...);
|
||||
#endif
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
int WXDLLIMPEXP_BASE wxDoSprintfUtf8(wchar_t *str, const char *format, ...);
|
||||
#endif
|
||||
WX_DEFINE_VARARG_FUNC(int, wxSprintf, 2, (wchar_t*, const wxFormatString&),
|
||||
wxDoSprintfWchar, wxDoSprintfUtf8)
|
||||
|
||||
int WXDLLIMPEXP_BASE
|
||||
wxVsprintf(wchar_t *str, const wxString& format, va_list argptr);
|
||||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
int WXDLLIMPEXP_BASE wxDoSnprintfWchar(wchar_t *str, size_t size, const wxChar *format, ...);
|
||||
#endif
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
int WXDLLIMPEXP_BASE wxDoSnprintfUtf8(wchar_t *str, size_t size, const char *format, ...);
|
||||
#endif
|
||||
WX_DEFINE_VARARG_FUNC(int, wxSnprintf, 3, (wchar_t*, size_t, const wxFormatString&),
|
||||
wxDoSnprintfWchar, wxDoSnprintfUtf8)
|
||||
|
||||
int WXDLLIMPEXP_BASE
|
||||
wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr);
|
||||
|
||||
|
|
|
|||
|
|
@ -433,16 +433,19 @@ public:
|
|||
/**
|
||||
Constructor allowing to specify all the fields at once.
|
||||
|
||||
This is a vararg constructor taking an arbitrary number of extensions
|
||||
after the first four required parameters. The list must be terminated
|
||||
by @NULL.
|
||||
This is a variadic constructor taking an arbitrary number of extensions
|
||||
(which can be strings of any kind) after the four required parameters.
|
||||
|
||||
In wxWidgets versions before 3.3.0 the list of extensions had to be
|
||||
terminated with @NULL, but this is not the case any more, trailing
|
||||
@NULL is still allowed, but will be ignored.
|
||||
*/
|
||||
template <typename... Targs>
|
||||
wxFileTypeInfo(const wxString& mimeType,
|
||||
const wxString& openCmd,
|
||||
const wxString& printCmd,
|
||||
const wxString& description,
|
||||
const wxString& extension,
|
||||
...);
|
||||
Targs... extensions);
|
||||
|
||||
/**
|
||||
Constructor using an array of string elements corresponding to the
|
||||
|
|
|
|||
|
|
@ -972,7 +972,7 @@ wxString wxAppTraitsBase::GetAssertStackTrace()
|
|||
#if !defined(__WINDOWS__)
|
||||
// on Unix stack frame generation may take some time, depending on the
|
||||
// size of the executable mainly... warn the user that we are working
|
||||
wxFprintf(stderr, "Collecting stack trace information, please wait...");
|
||||
wxFputs("Collecting stack trace information, please wait...", stderr);
|
||||
fflush(stderr);
|
||||
#endif // !__WINDOWS__
|
||||
|
||||
|
|
|
|||
|
|
@ -1341,7 +1341,7 @@ bool wxFileName::Rmdir(const wxString& dir, int flags)
|
|||
{
|
||||
// SHFileOperation may return non-Win32 error codes, so don't use
|
||||
// wxLogApiError() as the error message used by it could be wrong.
|
||||
wxLogDebug(wxS("SHFileOperation(FO_DELETE) failed: error 0x%08lx"),
|
||||
wxLogDebug(wxS("SHFileOperation(FO_DELETE) failed: error 0x%08x"),
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,55 +103,6 @@ wxString wxMimeTypeCommands::GetVerbCmd(size_t n) const
|
|||
// wxFileTypeInfo
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxFileTypeInfo::DoVarArgInit(const wxString& mimeType,
|
||||
const wxString& openCmd,
|
||||
const wxString& printCmd,
|
||||
const wxString& desc,
|
||||
va_list argptr)
|
||||
{
|
||||
m_mimeType = mimeType;
|
||||
m_openCmd = openCmd;
|
||||
m_printCmd = printCmd;
|
||||
m_desc = desc;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
// icc gives this warning in its own va_arg() macro, argh
|
||||
#ifdef __INTELC__
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 1684)
|
||||
#endif
|
||||
|
||||
wxArgNormalizedString ext(WX_VA_ARG_STRING(argptr));
|
||||
|
||||
#ifdef __INTELC__
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
if ( !ext )
|
||||
{
|
||||
// nullptr terminates the list
|
||||
break;
|
||||
}
|
||||
|
||||
m_exts.Add(ext.GetString());
|
||||
}
|
||||
}
|
||||
|
||||
void wxFileTypeInfo::VarArgInit(const wxString *mimeType,
|
||||
const wxString *openCmd,
|
||||
const wxString *printCmd,
|
||||
const wxString *desc,
|
||||
...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, desc);
|
||||
|
||||
DoVarArgInit(*mimeType, *openCmd, *printCmd, *desc, argptr);
|
||||
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
|
||||
wxFileTypeInfo::wxFileTypeInfo(const wxArrayString& sArray)
|
||||
: m_mimeType(sArray[0u])
|
||||
, m_openCmd( sArray[1u])
|
||||
|
|
|
|||
|
|
@ -69,34 +69,6 @@ wxMessageOutput* wxMessageOutput::Set(wxMessageOutput* msgout)
|
|||
return old;
|
||||
}
|
||||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
void wxMessageOutput::DoPrintfWchar(const wxChar *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
wxString out;
|
||||
|
||||
out.PrintfV(format, args);
|
||||
va_end(args);
|
||||
|
||||
Output(out);
|
||||
}
|
||||
#endif // !wxUSE_UTF8_LOCALE_ONLY
|
||||
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
void wxMessageOutput::DoPrintfUtf8(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
wxString out;
|
||||
|
||||
out.PrintfV(format, args);
|
||||
va_end(args);
|
||||
|
||||
Output(out);
|
||||
}
|
||||
#endif // wxUSE_UNICODE_UTF8
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxMessageOutputBest
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1679,38 +1679,6 @@ wxString wxString::FromCDouble(double val, int precision)
|
|||
// formatted output
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
/* static */
|
||||
wxString wxString::DoFormatWchar(const wxChar *format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
|
||||
wxString s;
|
||||
s.PrintfV(format, argptr);
|
||||
|
||||
va_end(argptr);
|
||||
|
||||
return s;
|
||||
}
|
||||
#endif // !wxUSE_UTF8_LOCALE_ONLY
|
||||
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
/* static */
|
||||
wxString wxString::DoFormatUtf8(const char *format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
|
||||
wxString s;
|
||||
s.PrintfV(format, argptr);
|
||||
|
||||
va_end(argptr);
|
||||
|
||||
return s;
|
||||
}
|
||||
#endif // wxUSE_UNICODE_UTF8
|
||||
|
||||
/* static */
|
||||
wxString wxString::FormatV(const wxString& format, va_list argptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -653,31 +653,9 @@ wxString wxFormatString::InputAsString() const
|
|||
namespace
|
||||
{
|
||||
|
||||
template<typename CharType>
|
||||
wxFormatString::ArgumentType DoGetArgumentType(const CharType *format,
|
||||
unsigned n)
|
||||
wxFormatString::ArgumentType ArgTypeFromParamType(wxPrintfArgType type)
|
||||
{
|
||||
wxCHECK_MSG( format, wxFormatString::Arg_Unknown,
|
||||
"empty format string not allowed here" );
|
||||
|
||||
wxPrintfConvSpecParser<CharType> parser(format);
|
||||
|
||||
if ( n > parser.nargs )
|
||||
{
|
||||
// The n-th argument doesn't appear in the format string and is unused.
|
||||
// This can happen e.g. if a translation of the format string is used
|
||||
// and the translation language tends to avoid numbers in singular forms.
|
||||
// The translator would then typically replace "%d" with "One" (e.g. in
|
||||
// Hebrew). Passing too many vararg arguments does not harm, so its
|
||||
// better to be more permissive here and allow legitimate uses in favour
|
||||
// of catching harmless errors.
|
||||
return wxFormatString::Arg_Unused;
|
||||
}
|
||||
|
||||
wxCHECK_MSG( parser.pspec[n-1] != nullptr, wxFormatString::Arg_Unknown,
|
||||
"requested argument not found - invalid format string?" );
|
||||
|
||||
switch ( parser.pspec[n-1]->m_type )
|
||||
switch ( type )
|
||||
{
|
||||
case wxPAT_CHAR:
|
||||
case wxPAT_WCHAR:
|
||||
|
|
@ -727,6 +705,91 @@ wxFormatString::ArgumentType DoGetArgumentType(const CharType *format,
|
|||
return wxFormatString::Arg_Unknown;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if ( n > parser.nargs )
|
||||
{
|
||||
// The n-th argument doesn't appear in the format string and is unused.
|
||||
// This can happen e.g. if a translation of the format string is used
|
||||
// and the translation language tends to avoid numbers in singular forms.
|
||||
// The translator would then typically replace "%d" with "One" (e.g. in
|
||||
// Hebrew). Passing too many vararg arguments does not harm, so its
|
||||
// better to be more permissive here and allow legitimate uses in favour
|
||||
// of catching harmless errors.
|
||||
return wxFormatString::Arg_Unused;
|
||||
}
|
||||
|
||||
wxCHECK_MSG( parser.pspec[n-1] != nullptr, wxFormatString::Arg_Unknown,
|
||||
"requested argument not found - invalid format string?" );
|
||||
|
||||
return ArgTypeFromParamType(parser.pspec[n-1]->m_type);
|
||||
}
|
||||
|
||||
#if wxDEBUG_LEVEL
|
||||
|
||||
template<typename CharType>
|
||||
void DoValidateFormat(const CharType* format, const std::vector<int>& argTypes)
|
||||
{
|
||||
wxPrintfConvSpecParser<CharType> parser(format);
|
||||
|
||||
// For the reasons mentioned in the comment in DoGetArgumentType() above,
|
||||
// we ignore any extraneous argument types, so we only check that the
|
||||
// format format specifiers we actually have match the types.
|
||||
for ( unsigned n = 0; n < parser.nargs; ++n )
|
||||
{
|
||||
if ( n == argTypes.size() )
|
||||
{
|
||||
wxFAIL_MSG
|
||||
(
|
||||
wxString::Format
|
||||
(
|
||||
"Not enough arguments, %zu given but at least %u needed",
|
||||
argTypes.size(),
|
||||
parser.nargs
|
||||
)
|
||||
);
|
||||
|
||||
// Useless to continue further.
|
||||
return;
|
||||
}
|
||||
|
||||
auto const pspec = parser.pspec[n];
|
||||
if ( !pspec )
|
||||
{
|
||||
wxFAIL_MSG
|
||||
(
|
||||
wxString::Format
|
||||
(
|
||||
"Missing format specifier for argument %u in \"%s\"",
|
||||
n + 1, format
|
||||
)
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
auto const ptype = ArgTypeFromParamType(pspec->m_type);
|
||||
wxASSERT_MSG
|
||||
(
|
||||
(ptype & argTypes[n]) == ptype,
|
||||
wxString::Format
|
||||
(
|
||||
"Format specifier mismatch for argument %u of \"%s\"",
|
||||
n + 1, format
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // wxDEBUG_LEVEL
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
wxFormatString::ArgumentType wxFormatString::GetArgumentType(unsigned n) const
|
||||
|
|
@ -743,3 +806,19 @@ wxFormatString::ArgumentType wxFormatString::GetArgumentType(unsigned n) const
|
|||
wxFAIL_MSG( "unreachable code" );
|
||||
return Arg_Unknown;
|
||||
}
|
||||
|
||||
#if wxDEBUG_LEVEL
|
||||
|
||||
void wxFormatString::Validate(const std::vector<int>& argTypes) const
|
||||
{
|
||||
if ( m_char )
|
||||
DoValidateFormat(m_char.data(), argTypes);
|
||||
else if ( m_wchar )
|
||||
DoValidateFormat(m_wchar.data(), argTypes);
|
||||
else if ( m_str )
|
||||
DoValidateFormat(m_str->wx_str(), argTypes);
|
||||
else if ( m_cstr )
|
||||
DoValidateFormat(m_cstr->AsInternal(), argTypes);
|
||||
}
|
||||
|
||||
#endif // wxDEBUG_LEVEL
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "wx/defs.h"
|
||||
|
||||
#include "wx/math.h"
|
||||
#include "wx/mimetype.h"
|
||||
|
||||
// just some classes using wxRTTI for wxStaticCast() test
|
||||
#include "wx/tarstrm.h"
|
||||
|
|
@ -213,3 +214,30 @@ TEST_CASE("wxMulDivInt32", "[math]")
|
|||
// Check that it doesn't overflow.
|
||||
CHECK( wxMulDivInt32((INT_MAX - 1)/2, 200, 100) == INT_MAX - 1 );
|
||||
}
|
||||
|
||||
#if wxUSE_MIMETYPE
|
||||
TEST_CASE("wxFileTypeInfo", "[mime]")
|
||||
{
|
||||
SECTION("no extensions")
|
||||
{
|
||||
wxFileTypeInfo fti("binary/*", "", wxString{}, L"plain binary");
|
||||
REQUIRE( fti.GetExtensionsCount() == 0 );
|
||||
}
|
||||
|
||||
SECTION("extension without null at the end")
|
||||
{
|
||||
wxFileTypeInfo fti("image/png", "", wxEmptyString, "PNG image", "png");
|
||||
REQUIRE( fti.GetExtensionsCount() == 1 );
|
||||
CHECK( fti.GetExtensions()[0] == "png" );
|
||||
}
|
||||
|
||||
SECTION("two extensions with null at the end")
|
||||
{
|
||||
wxFileTypeInfo fti("image/jpeg", "", "", "JPEG image",
|
||||
"jpg", L"jpeg", nullptr);
|
||||
REQUIRE( fti.GetExtensionsCount() == 2 );
|
||||
CHECK( fti.GetExtensions()[0] == "jpg" );
|
||||
CHECK( fti.GetExtensions()[1] == "jpeg" );
|
||||
}
|
||||
}
|
||||
#endif // wxUSE_MIMETYPE
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ TEST_CASE("ArgsValidation", "[wxString][vararg][error]")
|
|||
#endif
|
||||
|
||||
// but these are not:
|
||||
WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%d + %d = %d", 2, 2) );
|
||||
WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%i", "foo") );
|
||||
WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%s", (void*)&written) );
|
||||
WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%d", ptr) );
|
||||
|
|
|
|||
|
|
@ -417,7 +417,7 @@ wxArrayString XmlResApp::PrepareTempFiles()
|
|||
for (size_t i = 0; i < parFiles.GetCount(); i++)
|
||||
{
|
||||
if (flagVerbose)
|
||||
wxPrintf(wxT("processing ") + parFiles[i] + wxT("...\n"));
|
||||
wxPrintf(wxT("processing %s...\n"), parFiles[i]);
|
||||
|
||||
wxXmlDocument doc;
|
||||
|
||||
|
|
@ -529,7 +529,7 @@ void XmlResApp::FindFilesInXML(wxXmlNode *node, wxArrayString& flist, const wxSt
|
|||
fullname = inputPath + wxFILE_SEP_PATH + n->GetContent();
|
||||
|
||||
if (flagVerbose)
|
||||
wxPrintf(wxT("adding ") + fullname + wxT("...\n"));
|
||||
wxPrintf(wxT("adding %s...\n"), fullname);
|
||||
|
||||
wxString filename = GetInternalFileName(n->GetContent(), flist);
|
||||
n->SetContent(filename);
|
||||
|
|
@ -569,7 +569,7 @@ void XmlResApp::MakePackageZIP(const wxArrayString& flist)
|
|||
files.RemoveLast();
|
||||
|
||||
if (flagVerbose)
|
||||
wxPrintf(wxT("compressing ") + parOutput + wxT("...\n"));
|
||||
wxPrintf(wxT("compressing %s...\n"), parOutput);
|
||||
|
||||
wxString cwd = wxGetCwd();
|
||||
wxSetWorkingDirectory(parOutputPath);
|
||||
|
|
@ -639,7 +639,7 @@ void XmlResApp::MakePackageCPP(const wxArrayString& flist)
|
|||
unsigned i;
|
||||
|
||||
if (flagVerbose)
|
||||
wxPrintf(wxT("creating C++ source file ") + parOutput + wxT("...\n"));
|
||||
wxPrintf(wxT("creating C++ source file %s...\n"), parOutput);
|
||||
|
||||
file.Write(""
|
||||
"//\n"
|
||||
|
|
@ -797,7 +797,7 @@ void XmlResApp::MakePackagePython(const wxArrayString& flist)
|
|||
unsigned i;
|
||||
|
||||
if (flagVerbose)
|
||||
wxPrintf(wxT("creating Python source file ") + parOutput + wxT("...\n"));
|
||||
wxPrintf(wxT("creating Python source file %s...\n"), parOutput);
|
||||
|
||||
file.Write(
|
||||
"#\n"
|
||||
|
|
@ -881,7 +881,7 @@ ExtractedStrings XmlResApp::FindStrings()
|
|||
for (size_t i = 0; i < parFiles.GetCount(); i++)
|
||||
{
|
||||
if (flagVerbose)
|
||||
wxPrintf(wxT("processing ") + parFiles[i] + wxT("...\n"));
|
||||
wxPrintf(wxT("processing %s...\n"), parFiles[i]);
|
||||
|
||||
wxXmlDocument doc;
|
||||
if (!doc.Load(parFiles[i]))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue