11 template <
typename Val>
class Fmt>
16 std::function<void(
const String&)> _del;
20 FormatObject(
const String& fmt, F f)
24 FormatObject(
const String& fmt)
32 FormatObject(
const FormatObject& other) =
delete;
33 FormatObject& operator=(
const FormatObject&) =
delete;
35 FormatObject(FormatObject&& other)
36 : _data(std::move(other._data))
38 , _del(std::move(other._del)) {}
39 FormatObject& operator=(FormatObject&& other) {
44 operator String()
const {
45 return unescape(_data);
49 typename std::enable_if<std::is_fundamental<T>::value, FormatObject&>::type
50 operator<<(
const T& t) {
52 return place([&fmt](
auto iterator) {
57 FormatObject& operator<<(
const std::string& s) {
58 return place([&s](
auto iterator) {
60 placeEscapedChar(c, iterator);
64 FormatObject& operator<<(
const char* c) {
65 return place([&c](
auto iterator) {
67 placeEscapedChar(*(c++), iterator);
72 typename std::enable_if<std::is_base_of<Formatable, T>::value, FormatObject&>::type
73 operator<<(
const T& t) {
74 return place([&t](
auto iterator) {
79 FormatObject& fillWith() {
83 template <
typename T,
typename... Args>
84 FormatObject& fillWith(T t, Args... args) {
85 return (*
this << t).fillWith(args...);
89 static const SizeType npos = -1;
92 SizeType begin, end, id;
95 SizeType nextChar(SizeType pos,
char c) {
99 for (; pos < static_cast<SizeType>(_data.size()); pos++) {
100 if (skip || _data[pos] ==
'\\') {
111 Marker nextMarker(SizeType pos) {
112 SizeType b = nextChar(pos,
'{');
113 SizeType e = nextChar(b,
'}') + 1;
115 return { npos, npos, npos };
119 SizeType idx = strtol(&(_data[b + 1]),
nullptr, 0);
120 return { b, e, idx };
123 template <
typename F>
124 FormatObject& place(F replaceCallback) {
126 SizeType copyFrom = 0;
128 Marker m = nextMarker(0);
129 while (m.begin != npos) {
130 if (m.id == -1 || m.id == _idx) {
131 std::copy(_data.begin() + copyFrom, _data.begin() + m.begin,
132 std::back_inserter(result));
134 replaceCallback(std::back_inserter(result));
139 m = nextMarker(m.end);
141 std::copy(_data.begin() + copyFrom, _data.end(), std::back_inserter(result));
143 replaceCallback(std::back_inserter(result));
149 template <
typename OutIt>
150 static void placeEscapedChar(
char c, OutIt& iterator) {
151 if (c ==
'{' || c ==
'}' || c ==
'\\')
152 *(iterator++) =
'\\';
156 static String unescape(
const String& s) {
160 if (c ==
'\\' && ignore) {
170 void swap(FormatObject& other) {
172 swap(_data, other._data);
173 swap(_idx, other._idx);
174 swap(_del, other._del);
181 template <
typename Val>
class Fmt>
182 std::ostream& operator<<(std::ostream& stream,
183 const FormatObject<String, SizeType, Fmt>& fmt) {
184 return stream << static_cast<std::string>(fmt);
187 using FormatString = FormatObject<std::string, int, DefaultSprintfFormatter>;
189 template <
typename T>
190 using NumberFortmatter = NumberSprintfFormatter<T>;
192 template <
typename... Args>
193 inline FormatString format(
const char* fmt, Args... args) {
194 return std::move(FormatString(fmt).fillWith(args...));
197 inline FormatString format(
const char* fmt) {
198 return FormatString(fmt);
201 template <
typename T>
202 NumberFortmatter<T> number(T t) {
203 return NumberSprintfFormatter<T>(t);
206 using string = StringFormatter<std::string>;