debian: fix build-deps for focal
[amule.git] / src / libs / common / Format.h
blobaebe5be2d4166ead5076974576f92fc819b1d857
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2005-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 //
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
8 // respective authors.
9 //
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #ifndef FORMAT_H
26 #define FORMAT_H
28 #include <list>
29 #include <string> // Needed to use std::string
30 #include "MuleDebug.h"
33 /**
34 * This class offers a typesafe alternative to wxString::Format.
36 * %CFormat has been implemented against the description of printf found
37 * in the "man 3 printf" manual page.
39 * %CFormat lacks the following capabilities:
40 * - The @c "*" width-modifier, because only one argument is fed at a time.
41 * - The @c "n" type, just unsafe and won't be implemented.
42 * - The @c "C" and @c "S" types, which are considered obsolete.
43 * - The Long Double type, which is extremly slow and shouldn't be used.
45 * Support for the C99 @c a, @c A conversions and the non-standard @c ', @c I
46 * flags depend on the underlying C library. Do not use them.
48 * Supports the glibc-specific @c m conversion on all platforms, where there's
49 * a way to get the error description. If the underlying C library has a
50 * thread-safe way to get the error description, then this conversion is
51 * thread-safe, too.
53 * Deviations from printf(3):
55 * %CFormat tries hard to format the passed POD-type according to the
56 * conversion type. Basic type conversions may take place to accomplish this
57 * goal. This results in formats accepting a variety of types, namely:
58 * - @c c, @c i, @c d, @c u, @c o, @c x, @c X accept @c wxChar and all integer
59 * types,
60 * - @c a, @c A, @c e, @c E, @c f, @c F, @c g, @c G accept @c wxChar, integer
61 * and floating-point types,
62 * - @c p accepts only pointers,
63 * - @c s accepts all the above mentioned types in addition to @c wxString and
64 * @c wxChar* types.
66 * The only exception from this rule is integer (@c d, @c i, @c u) conversion.
67 * It will always use the correct conversion (@c i or @c u) depending on the
68 * signedness of the passed argument.
70 * @c 's' conversions are inspired by the <em>"we're converting to string,
71 * anyway"</em> mood. Thus they use a 'default' conversion for each accepted
72 * type: @c 'c' for @c wxChar, @c 'i' and @c 'u' for signed and unsigned
73 * integers, respectively, @c 'g' for floating-point numbers and @c 'p' for
74 * pointers.
76 * Other relaxations / differences from printf(3):
77 * - Length modifiers are read and validated, but always ignored.
78 * - As a consequence, invalid combinations of length modifiers and conversion
79 * types are silently ignored (i.e. for example the invalid @c '%%qs'
80 * format-specifier is silently treated as @c '%%s').
81 * - @c 'p' conversion ignores all modifiers except the argument index reference.
82 * - You can mix positional and indexed argument references. (You actually can't,
83 * because msgfmt will treat this as an error.)
84 * - With indexed argument references we allow to leave gaps in the indices.
86 class CFormat
88 private:
89 /**
90 * Structure to hold a format specifier.
92 struct FormatSpecifier {
93 unsigned argIndex; //!< Argument index. (Position, unless specified otherwise.)
94 wxChar flag; //!< The optional flag character.
95 unsigned width; //!< The optional field width.
96 signed precision; //!< The optional precision value.
97 // length is not stored
98 wxChar type; //!< The conversion type.
99 size_t startPos; //!< Position of the first character of the format-specifier in the format-string.
100 size_t endPos; //!< Position of the last character of the format-specifier in the format-string.
101 wxString result; //!< Result of the conversion. Initialized to the format-specifier.
104 public:
106 * Constructor.
108 * @param str The format-string to be used.
110 CFormat(const wxChar* str) { Init(str); }
113 * Constructor.
115 * This form is required to construct from a plain char *
116 * with wx 2.9
118 * @param str The format-string to be used.
120 CFormat(const wxString& str) { Init(str); }
123 * Feeds a value into the format-string.
125 * Passing a type that isn't compatible with the current format
126 * field results in the field being skipped, and an exception raised.
128 * Passing any type to a CFormat with no free fields results in the
129 * argument being ignored.
131 * Specialize this member template to teach CFormat how to handle
132 * other types.
134 template<typename _Tp> CFormat& operator%(_Tp value);
136 // Overload hack to map all pointer types to void*
137 template<typename _Tp> CFormat& operator%(_Tp* value) { return this->operator%<void*>(value); }
139 // explicit overloads to avoid pass-by-value even in debug builds.
140 CFormat& operator%(const wxString& value) { return this->operator%<const wxString&>(value); }
141 CFormat& operator%(const CFormat& value) { return this->operator%<const wxString&>(value); }
142 CFormat& operator%(const std::string& value) { return this->operator%<const wxString&>(wxString(value.c_str(), wxConvUTF8)); }
145 * Returns the resulting string.
147 wxString GetString() const;
150 * Implicit conversion to wxString.
152 operator wxString() const { return GetString(); };
154 private:
156 * Initialize internal structures.
158 * Initializes member variables and parses the given format string.
160 void Init(const wxString& str);
162 //! Type holding format specifiers.
163 typedef std::list<FormatSpecifier> FormatList;
165 //! Retrieve the modifiers for the given format specifier.
166 wxString GetModifiers(FormatList::const_iterator it) const;
168 //! Do one argument conversion.
169 template<typename _Tp>
170 void ProcessArgument(FormatList::iterator it, _Tp value);
172 //! List of the valid format-specifiers found in the format string.
173 FormatList m_formats;
175 //! Number of the previous argument.
176 unsigned m_argIndex;
178 //! The format-string fed to the parser.
179 wxString m_formatString;
182 // type mappings
183 template<> inline CFormat& CFormat::operator%(char value) { return *this % (wxChar)value; }
184 template<> inline CFormat& CFormat::operator%(signed char value) { return *this % (wxChar)value; }
185 template<> inline CFormat& CFormat::operator%(unsigned char value) { return *this % (wxChar)value; }
186 template<> inline CFormat& CFormat::operator%(bool value) { return *this % (signed long long)value; }
187 template<> inline CFormat& CFormat::operator%(signed short value) { return *this % (signed long long)value; }
188 template<> inline CFormat& CFormat::operator%(unsigned short value) { return *this % (unsigned long long)value; }
189 template<> inline CFormat& CFormat::operator%(signed int value) { return *this % (signed long long)value; }
190 template<> inline CFormat& CFormat::operator%(unsigned int value) { return *this % (unsigned long long)value; }
191 template<> inline CFormat& CFormat::operator%(signed long value) { return *this % (signed long long)value; }
192 template<> inline CFormat& CFormat::operator%(unsigned long value) { return *this % (unsigned long long)value; }
193 template<> inline CFormat& CFormat::operator%(float value) { return *this % (double)value; }
194 template<> inline CFormat& CFormat::operator%(const wxChar* value) { return this->operator%<const wxString&>(wxString(value)); }
197 #if wxCHECK_VERSION(2, 9, 0)
198 #define WXLONGLONGFMTSPEC wxT(wxLongLongFmtSpec)
199 #else
200 #define WXLONGLONGFMTSPEC wxLongLongFmtSpec
201 #endif
203 #endif
204 // File_checked_for_headers