sources/format.h

changeset 1
4dd5bde4e777
child 5
146825d63b9a
equal deleted inserted replaced
0:792876306489 1:4dd5bde4e777
1 /*
2 Copyright 2014 Teemu Piippo
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 3. Neither the name of the copyright holder nor the names of its
15 contributors may be used to endorse or promote products derived from
16 this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
22 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "mystring.h"
32 #include "basics.h"
33 #include "geometry.h"
34
35 #define FORMAT_OVERLOAD(T) \
36 inline FUNCTION make_format_argument (T a) -> String
37
38 //
39 // -------------------------------------------------------------------------------------------------
40 //
41
42 FORMAT_OVERLOAD (String) { return a; }
43 FORMAT_OVERLOAD (char) { return String (a); }
44 FORMAT_OVERLOAD (int) { return String::from_number (a); }
45 FORMAT_OVERLOAD (long int) { return String::from_number (a); }
46 FORMAT_OVERLOAD (double) { return String::from_number (a); }
47 FORMAT_OVERLOAD (size_t) { return String::from_number (a); }
48 FORMAT_OVERLOAD (const char*) { return a; }
49 FORMAT_OVERLOAD (std::nullptr_t) { (void) a; return "<null pointer>"; }
50 FORMAT_OVERLOAD (bool) { return a ? "true" : "false"; }
51
52 FORMAT_OVERLOAD (const void*)
53 {
54 String result;
55 result.sprintf ("%p", a);
56 return result;
57 }
58
59 template<typename T>
60 FORMAT_OVERLOAD (const List<T>&)
61 {
62 String result;
63
64 if (a.is_empty())
65 return "{}";
66
67 result = "{";
68
69 for (auto it = a.begin(); it != a.end(); ++it)
70 {
71 if (it != a.begin())
72 result += ", ";
73
74 result += make_format_argument (*it);
75 }
76
77 result += "}";
78 return result;
79 }
80
81 FORMAT_OVERLOAD (Color)
82 {
83 static const char* colorstrings[] =
84 {
85 "BLACK", "RED", "GREEN", "YELLOW",
86 "BLUE", "MAGENTA", "CYAN", "WHITE", "DEFAULT"
87 };
88
89 static_assert (sizeof colorstrings / sizeof *colorstrings == NUM_COLORS,
90 "colostrings[] has an incorrect amount of elements");
91
92 if (int (a) >= 0 and int (a) < NUM_COLORS)
93 return colorstrings[int (a)];
94
95 return "???";
96 }
97
98 FORMAT_OVERLOAD (Position) { return String ("(") + a.x + ", " + a.y + ")"; }
99 FORMAT_OVERLOAD (Size) { return String ("(") + a.width + "x" + a.height + ")"; }
100
101 FORMAT_OVERLOAD (Rectangle)
102 {
103 String result;
104 result.sprintf ("{(%d, %d), (%dx%d)}", a.x, a.y, a.width, a.height);
105 return result;
106 }
107
108 //
109 // -------------------------------------------------------------------------------------------------
110 //
111 // Formats the given string with the given args.
112 //
113 auto format_args (const String& fmtstr, const Vector<String>& args) -> String;
114
115 //
116 // -------------------------------------------------------------------------------------------------
117 //
118 // Expands the given arguments into a vector of strings.
119 //
120 template<typename T, typename... RestTypes>
121 auto expand_format_arguments (Vector<String>& data, const T& arg, const RestTypes& ... rest) -> void
122 {
123 data.append (make_format_argument (arg).text());
124 expand_format_arguments (data, rest...);
125 }
126
127 static void expand_format_arguments (Vector<String>&) __attribute__( (unused));
128 static void expand_format_arguments (Vector<String>&) {}
129
130 //
131 // -------------------------------------------------------------------------------------------------
132 //
133 // Formats the given formatter string and args and returns the string.
134 // This is essentially a modernized sprintf.
135 //
136 // Args in the format string take the form %n where n is a digit. The argument
137 // will be expanded to the nth argument passed. This is essentially Qt's
138 // QString::arg() syntax. Note: %0 is invalid.
139 //
140 // Arguments can be passed a modifier which takes the form of a character
141 // just before the digit. Currently supported modifiers are s, d and x.
142 //
143 // - s: The argument will expand into "s" if it would've not expanded into "1"
144 // otherwise. If it would have expanded into "1" it will expand into an
145 // empty string.
146 //
147 // - d: The argument expands into the numeric form of the first character of
148 // its previous expansion. Use this to get numeric forms of @c char
149 // arguments.
150 //
151 // - x: The numeric argument will be represented in hexadecimal notation. This
152 // will work if the argument is a string representing a number. If the
153 // argument did not expand into a number in the first place, 0 is used
154 // and 0x0 is printed.
155 //
156 template<typename... argtypes>
157 String format (const String& fmtstr, const argtypes&... raw_args)
158 {
159 Vector<String> args;
160 expand_format_arguments (args, raw_args...);
161 return format_args (fmtstr, args);
162 }
163
164 //
165 // -------------------------------------------------------------------------------------------------
166 //
167 // This is an overload of format() where no arguments are supplied.
168 // It returns the formatter string as-is.
169 //
170 static String format (const String& fmtstr) __attribute__ ((unused));
171 static String format (const String& fmtstr)
172 {
173 return fmtstr;
174 }
175
176 //
177 // -------------------------------------------------------------------------------------------------
178 //
179
180 template<typename... Args>
181 void print_to (FILE* fp, const String& fmtstr, Args const& ...args)
182 {
183 std::fprintf (fp, "%s", format (fmtstr, args...).chars());
184 }
185
186 //
187 // -------------------------------------------------------------------------------------------------
188 //
189
190 template<typename... argtypes>
191 void print_to (const String& filename, const String& fmtstr, const argtypes&... args)
192 {
193 FILE* handle;
194
195 if ((handle = fopen (filename, "w+")))
196 {
197 print_to (handle, fmtstr, args...);
198 fclose (handle);
199 }
200 }
201
202 //
203 // -------------------------------------------------------------------------------------------------
204 //
205
206 template<typename... argtypes>
207 void print (const String& fmtstr, const argtypes&... args)
208 {
209 print_to (stdout, fmtstr, args...);
210 }
211
212 #define PRINT_TO_LOG(...) \
213 { \
214 print_to (LOGFILE, "%1:%2: ", __PRETTY_FUNCTION__, __LINE__); \
215 print_to (LOGFILE, __VA_ARGS__); \
216 }

mercurial