sources/format.h

changeset 1
4dd5bde4e777
child 5
146825d63b9a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/format.h	Wed Dec 10 19:17:00 2014 +0200
@@ -0,0 +1,216 @@
+/*
+	Copyright 2014 Teemu Piippo
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions
+	are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. Neither the name of the copyright holder nor the names of its
+	   contributors may be used to endorse or promote products derived from
+	   this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+	TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+	PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
+	OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "mystring.h"
+#include "basics.h"
+#include "geometry.h"
+
+#define FORMAT_OVERLOAD(T) \
+	inline FUNCTION make_format_argument (T a) -> String
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+FORMAT_OVERLOAD (String) { return a; }
+FORMAT_OVERLOAD (char) { return String (a); }
+FORMAT_OVERLOAD (int) { return String::from_number (a); }
+FORMAT_OVERLOAD (long int) { return String::from_number (a); }
+FORMAT_OVERLOAD (double) { return String::from_number (a); }
+FORMAT_OVERLOAD (size_t) { return String::from_number (a); }
+FORMAT_OVERLOAD (const char*) { return a; }
+FORMAT_OVERLOAD (std::nullptr_t) { (void) a; return "<null pointer>"; }
+FORMAT_OVERLOAD (bool) { return a ? "true" : "false"; }
+
+FORMAT_OVERLOAD (const void*)
+{
+	String result;
+	result.sprintf ("%p", a);
+	return result;
+}
+
+template<typename T>
+FORMAT_OVERLOAD (const List<T>&)
+{
+	String result;
+
+	if (a.is_empty())
+		return "{}";
+
+	result = "{";
+
+	for (auto it = a.begin(); it != a.end(); ++it)
+	{
+		if (it != a.begin())
+			result += ", ";
+
+		result += make_format_argument (*it);
+	}
+
+	result += "}";
+	return result;
+}
+
+FORMAT_OVERLOAD (Color)
+{
+	static const char* colorstrings[] =
+	{
+		"BLACK", "RED", "GREEN", "YELLOW",
+		"BLUE", "MAGENTA", "CYAN", "WHITE", "DEFAULT"
+	};
+
+	static_assert (sizeof colorstrings / sizeof *colorstrings == NUM_COLORS,
+		"colostrings[] has an incorrect amount of elements");
+
+	if (int (a) >= 0 and int (a) < NUM_COLORS)
+		return colorstrings[int (a)];
+
+	return "???";
+}
+
+FORMAT_OVERLOAD (Position) { return String ("(") + a.x + ", " + a.y + ")"; }
+FORMAT_OVERLOAD (Size) { return String ("(") + a.width + "x" + a.height + ")"; }
+
+FORMAT_OVERLOAD (Rectangle)
+{
+	String result;
+	result.sprintf ("{(%d, %d), (%dx%d)}", a.x, a.y, a.width, a.height);
+	return result;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+// Formats the given string with the given args.
+//
+auto format_args (const String& fmtstr, const Vector<String>& args) -> String;
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+// Expands the given arguments into a vector of strings.
+//
+template<typename T, typename... RestTypes>
+auto expand_format_arguments (Vector<String>& data, const T& arg, const RestTypes& ... rest) -> void
+{
+	data.append (make_format_argument (arg).text());
+	expand_format_arguments (data, rest...);
+}
+
+static void expand_format_arguments (Vector<String>&) __attribute__( (unused));
+static void expand_format_arguments (Vector<String>&) {}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+// Formats the given formatter string and args and returns the string.
+// This is essentially a modernized sprintf.
+//
+// Args in the format string take the form %n where n is a digit. The argument
+// will be expanded to the nth argument passed. This is essentially Qt's
+// QString::arg() syntax. Note: %0 is invalid.
+//
+// Arguments can be passed a modifier which takes the form of a character
+// just before the digit. Currently supported modifiers are s, d and x.
+//
+// - s: The argument will expand into "s" if it would've not expanded into "1"
+//      otherwise. If it would have expanded into "1" it will expand into an
+//      empty string.
+//
+// - d: The argument expands into the numeric form of the first character of
+//      its previous expansion. Use this to get numeric forms of @c char
+//      arguments.
+//
+// - x: The numeric argument will be represented in hexadecimal notation. This
+//      will work if the argument is a string representing a number. If the
+//      argument did not expand into a number in the first place, 0 is used
+//      and 0x0 is printed.
+//
+template<typename... argtypes>
+String format (const String& fmtstr, const argtypes&... raw_args)
+{
+	Vector<String> args;
+	expand_format_arguments (args, raw_args...);
+	return format_args (fmtstr, args);
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+// This is an overload of format() where no arguments are supplied.
+// It returns the formatter string as-is.
+//
+static String format (const String& fmtstr) __attribute__ ((unused));
+static String format (const String& fmtstr)
+{
+	return fmtstr;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename... Args>
+void print_to (FILE* fp, const String& fmtstr, Args const& ...args)
+{
+	std::fprintf (fp, "%s", format (fmtstr, args...).chars());
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename... argtypes>
+void print_to (const String& filename, const String& fmtstr, const argtypes&... args)
+{
+	FILE* handle;
+
+	if ((handle = fopen (filename, "w+")))
+	{
+		print_to (handle, fmtstr, args...);
+		fclose (handle);
+	}
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename... argtypes>
+void print (const String& fmtstr, const argtypes&... args)
+{
+	print_to (stdout, fmtstr, args...);
+}
+
+#define PRINT_TO_LOG(...) \
+{ \
+	print_to (LOGFILE, "%1:%2: ", __PRETTY_FUNCTION__, __LINE__); \
+	print_to (LOGFILE, __VA_ARGS__); \
+}

mercurial