libostd/examples/format.cc

130 lines
4.3 KiB
C++
Raw Normal View History

#include <tuple>
2016-02-03 22:21:53 +01:00
#include <ostd/algorithm.hh>
#include <ostd/vector.hh>
#include <ostd/unordered_map.hh>
2016-02-03 22:21:53 +01:00
#include <ostd/range.hh>
#include <ostd/io.hh>
using namespace ostd;
using namespace ostd::string_literals;
2016-02-03 22:21:53 +01:00
struct Foo {
};
/* implementing formatting for custom objects - external function */
template<typename R>
2017-02-16 20:39:05 +01:00
void to_format(Foo const &, R &writer, format_spec const &fs) {
2016-02-03 22:21:53 +01:00
switch (fs.spec()) {
2016-08-03 17:50:06 +02:00
case 'i':
range_put_all(writer, "Foo1"_sr);
2016-08-03 17:50:06 +02:00
break;
default:
range_put_all(writer, "Foo2"_sr);
2016-08-03 17:50:06 +02:00
break;
2016-02-03 22:21:53 +01:00
}
}
struct Bar {
/* implementing formatting for custom objects - method */
template<typename R>
2017-02-16 20:39:05 +01:00
void to_format(R &writer, format_spec const &fs) const {
2016-02-03 22:21:53 +01:00
switch (fs.spec()) {
2016-08-03 17:50:06 +02:00
case 'i':
range_put_all(writer, "Bar1"_sr);
2016-08-03 17:50:06 +02:00
break;
default:
range_put_all(writer, "Bar2"_sr);
2016-08-03 17:50:06 +02:00
break;
2016-02-03 22:21:53 +01:00
}
}
};
int main() {
2017-01-25 01:44:22 +01:00
std::vector<int> x = { 5, 10, 15, 20 };
/* prints [5|10|15|20] (using | as the delimiter and %s for each item),
2017-02-25 14:34:12 +01:00
* the syntax for ranges is %(CONTENTS%) where CONTENTS is a sequence
* up until and including the last format mark followed by a delimiter,
* so for example "%s, " has "%s" for formatting and ", " for the delimiter
* and "%d: %s, " has "%d: %s" for format and ", " for the delimiter; if
* you need to specify a complicated manual delimiter, you can use the
2017-02-25 14:34:12 +01:00
* "FORMAT%|DELIMITER" syntax, where %(%s, %) equals %(%s%|, %)
*/
2016-02-03 22:21:53 +01:00
writefln("[%(%s|%)]", x);
/* prints a range with default format {item, item, item, ...}
* you can enable item escaping by passing the @ flag
*/
writefln("%s", x);
2016-02-03 22:21:53 +01:00
int y[] = { 2, 4, 8, 16, 32 };
/* prints { 2, 4, 8, 16, 32 } using ", " as the delimiter */
2016-02-03 22:21:53 +01:00
writefln("{ %(%s, %) }", y);
2017-02-25 14:34:12 +01:00
/* nested range printing - prints each item of the main
* range with [ %(%s, %) ] and ",\n" as the delimiter
2017-02-25 14:34:12 +01:00
*/
2016-02-03 22:21:53 +01:00
writefln("[\n%([ %(%s, %) ]%|,\n%)\n]", map(range(10), [](int v) {
return range(v + 1);
}));
std::unordered_map<std::string, int> m = {
2016-02-03 22:21:53 +01:00
{ "foo", 5 },
{ "bar", 10 },
{ "baz", 15 }
};
2017-02-25 14:34:12 +01:00
/* prints something like { "baz": 15, "bar": 10, "foo": 5 }, note that
* the tuple is expanded into two formats (using the # flag) and the
* items are escaped with the @ flag (applies to strings and chars)
2016-02-03 22:21:53 +01:00
*/
writefln("{ %#(%@s: %d, %) }", m);
/* not escaped, you get { baz: 15, bar: 10, foo: 5} */
2017-02-25 14:34:12 +01:00
writefln("{ %#(%s: %d, %) }", m);
/* no expansion of the items, print entire tuple with default format,
* gets you something like { <"baz", 15>, <"bar", 10>, <"foo", 5> }
* because the default tuple format is <item, item, item, ...>
*/
writefln("{ %(%s, %) }", m);
/* as the @ flag enables escaping on strings and chars,
* you can use it standalone outside of range/tuple format
*/
writefln("not escaped: %s, escaped: %@s", "foo", "bar");
2017-02-25 14:34:12 +01:00
/* you can expand tuples similarly to ranges, with %<CONTENTS%> where
* CONTENTS is a regular format string like if the tuple was formatted
* separately with each item of the tuple passed as a separate argument
2017-02-25 14:34:12 +01:00
*/
std::tuple<std::string, int, float, std::string> tup{
"hello world", 1337, 3.14f, "test"
};
writefln("the tuple contains %<%@s, %d, %f, %s%>.", tup);
writefln("auto tuple: %s", tup);
writefln("auto tuple with escape: %@s", tup);
2016-02-03 22:21:53 +01:00
/* formatting a range of tuples, with each tuple expanded using #
2017-02-25 14:34:12 +01:00
*/
std::tuple<int, float, char const *> xt[] = {
std::make_tuple(5, 3.14f, "foo"),
std::make_tuple(3, 1.23f, "bar"),
std::make_tuple(9, 8.66f, "baz")
2016-02-03 22:21:53 +01:00
};
writefln("[ %#(<%d|%f|%@s>%|, %) ]", xt);
2016-02-03 22:21:53 +01:00
2017-02-25 14:34:12 +01:00
/* formatting custom objects, the information about the format mark
* is passed into the to_format function and the object can read it
*/
2016-05-25 18:12:28 +02:00
writefln("%s", Foo{});
writefln("%i", Foo{});
2016-02-03 22:21:53 +01:00
2017-02-25 14:34:12 +01:00
/* again, but using a method for formatting */
2016-05-25 18:12:28 +02:00
writefln("%s", Bar{});
writefln("%i", Bar{});
2016-02-03 22:21:53 +01:00
2017-02-25 14:34:12 +01:00
/* formatting into a string sink (can be any output range, but
* appender makes sure the capacity is unlimited so it's safe)
*/
2017-02-18 17:25:49 +01:00
auto s = appender_range<std::string>{};
2016-02-03 22:21:53 +01:00
format(s, "hello %s", "world");
writeln(s.get());
2016-02-07 22:17:15 +01:00
}