| 1 /* |
|
| 2 Copyright 2014, 2015 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 #pragma once |
|
| 32 #include "mystring.h" |
|
| 33 #include "basics.h" |
|
| 34 #include "geometry.h" |
|
| 35 |
|
| 36 // ------------------------------------------------------------------------------------------------- |
|
| 37 // |
|
| 38 inline String make_format_argument (String a) { return a; } |
|
| 39 inline String make_format_argument (char a) { return String (a); } |
|
| 40 inline String make_format_argument (short a) { return String::from_number (a); } |
|
| 41 inline String make_format_argument (int a) { return String::from_number (a); } |
|
| 42 inline String make_format_argument (long a) { return String::from_number (a); } |
|
| 43 inline String make_format_argument (double a) { return String::from_number (a); } |
|
| 44 inline String make_format_argument (unsigned short a) { return String::from_number (a); } |
|
| 45 inline String make_format_argument (unsigned int a) { return String::from_number (a); } |
|
| 46 inline String make_format_argument (unsigned long a) { return String::from_number (a); } |
|
| 47 inline String make_format_argument (const char* a) { return a; } |
|
| 48 inline String make_format_argument (std::nullptr_t) { return "<null pointer>"; } |
|
| 49 inline String make_format_argument (bool a) { return a ? "true" : "false"; } |
|
| 50 |
|
| 51 inline String make_format_argument (const void* a) |
|
| 52 { |
|
| 53 String result; |
|
| 54 result.sprintf ("%p", a); |
|
| 55 return result; |
|
| 56 } |
|
| 57 |
|
| 58 template<typename T, typename C> |
|
| 59 inline String make_format_argument (const Container<T, C>& a) |
|
| 60 { |
|
| 61 String result; |
|
| 62 |
|
| 63 if (a.is_empty()) |
|
| 64 return "{}"; |
|
| 65 |
|
| 66 result = "{"; |
|
| 67 |
|
| 68 for (auto it = a.begin(); it != a.end(); ++it) |
|
| 69 { |
|
| 70 if (it != a.begin()) |
|
| 71 result += ", "; |
|
| 72 |
|
| 73 result += make_format_argument (*it); |
|
| 74 } |
|
| 75 |
|
| 76 result += "}"; |
|
| 77 return result; |
|
| 78 } |
|
| 79 |
|
| 80 inline String make_format_argument (Color a) |
|
| 81 { |
|
| 82 static const char* colorstrings[] = |
|
| 83 { |
|
| 84 "BLACK", "RED", "GREEN", "YELLOW", |
|
| 85 "BLUE", "MAGENTA", "CYAN", "WHITE", "DEFAULT" |
|
| 86 }; |
|
| 87 |
|
| 88 static_assert (sizeof colorstrings / sizeof *colorstrings == NUM_COLORS, |
|
| 89 "colostrings[] has an incorrect amount of elements"); |
|
| 90 |
|
| 91 if (int (a) >= 0 and int (a) < NUM_COLORS) |
|
| 92 return colorstrings[int (a)]; |
|
| 93 |
|
| 94 return "???"; |
|
| 95 } |
|
| 96 |
|
| 97 inline String make_format_argument (const Position& a) |
|
| 98 { |
|
| 99 return String ("(") + a.x + ", " + a.y + ")"; |
|
| 100 } |
|
| 101 |
|
| 102 inline String make_format_argument (const Size& a) |
|
| 103 { |
|
| 104 return String ("(") + a.width + "x" + a.height + ")"; |
|
| 105 } |
|
| 106 |
|
| 107 inline String make_format_argument (const Rectangle& a) |
|
| 108 { |
|
| 109 String result; |
|
| 110 result.sprintf ("{(%d, %d), (%dx%d)}", a.x, a.y, a.width, a.height); |
|
| 111 return result; |
|
| 112 } |
|
| 113 |
|
| 114 // ------------------------------------------------------------------------------------------------- |
|
| 115 // |
|
| 116 // Formats the given string with the given args. |
|
| 117 // |
|
| 118 String format_args (const String& fmtstr, const Vector<String>& args); |
|
| 119 |
|
| 120 // ------------------------------------------------------------------------------------------------- |
|
| 121 // |
|
| 122 // Expands the given arguments into a vector of strings. |
|
| 123 // |
|
| 124 template<typename T, typename... RestTypes> |
|
| 125 void expand_format_arguments (Vector<String>& data, const T& arg, const RestTypes& ... rest) |
|
| 126 { |
|
| 127 data.append (make_format_argument (arg)); |
|
| 128 expand_format_arguments (data, rest...); |
|
| 129 } |
|
| 130 |
|
| 131 static void expand_format_arguments (Vector<String>&) __attribute__((unused)); |
|
| 132 static void expand_format_arguments (Vector<String>&) {} |
|
| 133 |
|
| 134 // ------------------------------------------------------------------------------------------------- |
|
| 135 // |
|
| 136 // Formats the given formatter string and args and returns the string. |
|
| 137 // This is essentially a modernized sprintf. |
|
| 138 // |
|
| 139 // Args in the format string take the form %n where n is a digit. The argument |
|
| 140 // will be expanded to the nth argument passed. This is essentially Qt's |
|
| 141 // QString::arg() syntax. Note: %0 is invalid. |
|
| 142 // |
|
| 143 // Arguments can be passed a modifier which takes the form of a character |
|
| 144 // just before the digit. Currently supported modifiers are s, d and x. |
|
| 145 // |
|
| 146 // - s: The argument will expand into "s" if it would've not expanded into "1" |
|
| 147 // otherwise. If it would have expanded into "1" it will expand into an |
|
| 148 // empty string. |
|
| 149 // |
|
| 150 // - d: The argument expands into the numeric form of the first character of |
|
| 151 // its previous expansion. Use this to get numeric forms of @c char |
|
| 152 // arguments. |
|
| 153 // |
|
| 154 // - x: The numeric argument will be represented in hexadecimal notation. This |
|
| 155 // will work if the argument is a string representing a number. If the |
|
| 156 // argument did not expand into a number in the first place, 0 is used |
|
| 157 // and 0x0 is printed. |
|
| 158 // |
|
| 159 template<typename... argtypes> |
|
| 160 String format (const String& fmtstr, const argtypes&... raw_args) |
|
| 161 { |
|
| 162 Vector<String> args; |
|
| 163 expand_format_arguments (args, raw_args...); |
|
| 164 return format_args (fmtstr, args); |
|
| 165 } |
|
| 166 |
|
| 167 // ------------------------------------------------------------------------------------------------- |
|
| 168 // |
|
| 169 // This is an overload of format() where no arguments are supplied. |
|
| 170 // It returns the formatter string as-is. |
|
| 171 // |
|
| 172 static String format (const String& fmtstr) __attribute__ ((unused)); |
|
| 173 static String format (const String& fmtstr) // -> String |
|
| 174 { |
|
| 175 return fmtstr; |
|
| 176 } |
|
| 177 |
|
| 178 // ------------------------------------------------------------------------------------------------- |
|
| 179 // |
|
| 180 // Prints the formatting result to the given file handle |
|
| 181 // |
|
| 182 template<typename... Args> |
|
| 183 void print_to (FILE* fp, const String& fmtstr, Args const& ...args) |
|
| 184 { |
|
| 185 std::fprintf (fp, "%s", format (fmtstr, args...).chars()); |
|
| 186 } |
|
| 187 |
|
| 188 // ------------------------------------------------------------------------------------------------- |
|
| 189 // |
|
| 190 // Appends the formatting result to the given filename, if opening it succeeds |
|
| 191 // |
|
| 192 template<typename... argtypes> |
|
| 193 void print_to (const String& filename, const String& fmtstr, const argtypes&... args) |
|
| 194 { |
|
| 195 FILE* handle; |
|
| 196 |
|
| 197 if ((handle = fopen (filename, "a"))) |
|
| 198 { |
|
| 199 print_to (handle, fmtstr, args...); |
|
| 200 fclose (handle); |
|
| 201 } |
|
| 202 } |
|