diff options
author | John Wiegley <johnw@newartisans.com> | 2009-11-09 01:24:44 -0500 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2009-11-09 02:06:08 -0500 |
commit | fb8be53edb9d9fdd91fd906e9a4ce6c3e8e3adb3 (patch) | |
tree | e1e41cd4e926ad108743f29158b4ef8e451b90f5 | |
parent | c3535d06c89732a0ba4c13274702b0f48198ae79 (diff) | |
download | fork-ledger-fb8be53edb9d9fdd91fd906e9a4ce6c3e8e3adb3.tar.gz fork-ledger-fb8be53edb9d9fdd91fd906e9a4ce6c3e8e3adb3.tar.bz2 fork-ledger-fb8be53edb9d9fdd91fd906e9a4ce6c3e8e3adb3.zip |
Redesigned the format_t class
-rw-r--r-- | src/exprbase.h | 15 | ||||
-rw-r--r-- | src/format.cc | 80 | ||||
-rw-r--r-- | src/format.h | 40 | ||||
-rw-r--r-- | src/output.cc | 43 | ||||
-rw-r--r-- | src/precmd.cc | 2 | ||||
-rw-r--r-- | src/scope.h | 3 |
6 files changed, 97 insertions, 86 deletions
diff --git a/src/exprbase.h b/src/exprbase.h index 605c30f7..d2bf5a6d 100644 --- a/src/exprbase.h +++ b/src/exprbase.h @@ -118,7 +118,8 @@ public: return str; } void set_text(const string& txt) { - str = txt; + str = txt; + compiled = false; } void parse(const string& str, const parse_flags_t& flags = PARSE_DEFAULT) { @@ -128,9 +129,7 @@ public: virtual void parse(std::istream&, const parse_flags_t& = PARSE_DEFAULT, const optional<string>& original_string = none) { - str = original_string ? *original_string : "<stream>"; - context = NULL; - compiled = false; + set_text(original_string ? *original_string : "<stream>"); } void mark_uncompiled() { @@ -185,7 +184,9 @@ public: context = scope; } - virtual string context_to_str() const = 0; + virtual string context_to_str() const { + return empty_string; + } string print_to_str() const { std::ostringstream out; @@ -203,8 +204,8 @@ public: return out.str(); } - virtual void print(std::ostream& out) const = 0; - virtual void dump(std::ostream& out) const = 0; + virtual void print(std::ostream&) const {} + virtual void dump(std::ostream&) const {} result_type preview(std::ostream& out, scope_t& scope) const { out << _("--- Input expression ---") << std::endl; diff --git a/src/format.cc b/src/format.cc index f3f52f20..d949c350 100644 --- a/src/format.cc +++ b/src/format.cc @@ -61,8 +61,12 @@ void format_t::element_t::dump(std::ostream& out) const out << std::dec << int(max_width); switch (type) { - case STRING: out << " str: '" << chars << "'" << std::endl; break; - case EXPR: out << " expr: " << expr << std::endl; break; + case STRING: + out << " str: '" << boost::get<string>(data) << "'" << std::endl; + break; + case EXPR: + out << " expr: " << boost::get<expr_t>(data) << std::endl; + break; } } @@ -117,7 +121,7 @@ format_t::element_t * format_t::parse_elements(const string& fmt, if (q != buf) { current->type = element_t::STRING; - current->chars = string(buf, q); + current->data = string(buf, q); q = buf; current->next.reset(new element_t); @@ -128,14 +132,14 @@ format_t::element_t * format_t::parse_elements(const string& fmt, p++; current->type = element_t::STRING; switch (*p) { - case 'b': current->chars = "\b"; break; - case 'f': current->chars = "\f"; break; - case 'n': current->chars = "\n"; break; - case 'r': current->chars = "\r"; break; - case 't': current->chars = "\t"; break; - case 'v': current->chars = "\v"; break; - case '\\': current->chars = "\\"; break; - default: current->chars = string(1, *p); break; + case 'b': current->data = string("\b"); break; + case 'f': current->data = string("\f"); break; + case 'n': current->data = string("\n"); break; + case 'r': current->data = string("\r"); break; + case 't': current->data = string("\t"); break; + case 'v': current->data = string("\v"); break; + case '\\': current->data = string("\\"); break; + default: current->data = string(1, *p); break; } continue; } @@ -171,8 +175,8 @@ format_t::element_t * format_t::parse_elements(const string& fmt, switch (*p) { case '%': - current->type = element_t::STRING; - current->chars = "%"; + current->type = element_t::STRING; + current->data = string("%"); break; case '$': { @@ -207,7 +211,7 @@ format_t::element_t * format_t::parse_elements(const string& fmt, if (format_amount) p++; current->type = element_t::EXPR; - current->expr = parse_single_expression(p, ! format_amount); + current->data = parse_single_expression(p, ! format_amount); // Wrap the subexpression in calls to justify and scrub if (format_amount) { @@ -216,7 +220,7 @@ format_t::element_t * format_t::parse_elements(const string& fmt, else p++; - expr_t::ptr_op_t op = current->expr.get_op(); + expr_t::ptr_op_t op = boost::get<expr_t>(current->data).get_op(); expr_t::ptr_op_t amount_op; expr_t::ptr_op_t colorize_op; @@ -238,8 +242,10 @@ format_t::element_t * format_t::parse_elements(const string& fmt, expr_t::ptr_op_t arg2_node(new expr_t::op_t(expr_t::op_t::VALUE)); expr_t::ptr_op_t arg3_node(new expr_t::op_t(expr_t::op_t::VALUE)); - arg1_node->set_value(current->min_width > 0 ? long(current->min_width) : -1); - arg2_node->set_value(current->max_width > 0 ? long(current->max_width) : -1); + arg1_node->set_value(current->min_width > 0 ? + long(current->min_width) : -1); + arg2_node->set_value(current->max_width > 0 ? + long(current->max_width) : -1); arg3_node->set_value(! current->has_flags(ELEMENT_ALIGN_LEFT)); current->min_width = 0; @@ -264,7 +270,7 @@ format_t::element_t * format_t::parse_elements(const string& fmt, call2_node->set_left(justify_node); call2_node->set_right(args3_node); - string prev_expr = current->expr.text(); + string prev_expr = boost::get<expr_t>(current->data).text(); if (colorize_op) { expr_t::ptr_op_t ansify_if_node(new expr_t::op_t(expr_t::op_t::IDENT)); @@ -278,21 +284,18 @@ format_t::element_t * format_t::parse_elements(const string& fmt, call3_node->set_left(ansify_if_node); call3_node->set_right(args4_node); - current->expr = expr_t(call3_node); + current->data = expr_t(call3_node); } else { - current->expr = expr_t(call2_node); + current->data = expr_t(call2_node); } - current->expr.set_text(prev_expr); + boost::get<expr_t>(current->data).set_text(prev_expr); } break; } default: - current->type = element_t::EXPR; - current->chars = string(FMT_PREFIX) + *p; - current->expr.parse(current->chars); - break; + throw_(format_error, _("Unrecognized formatting character: %1") << *p); } } @@ -304,15 +307,17 @@ format_t::element_t * format_t::parse_elements(const string& fmt, current->next.reset(new element_t); current = current->next.get(); } - current->type = element_t::STRING; - current->chars = string(buf, q); + current->type = element_t::STRING; + current->data = string(buf, q); } return result.release(); } -void format_t::format(std::ostream& out_str, scope_t& scope) +string format_t::real_calc(scope_t& scope) { + std::ostringstream out_str; + for (element_t * elem = elements.get(); elem; elem = elem->next.get()) { std::ostringstream out; string name; @@ -326,20 +331,22 @@ void format_t::format(std::ostream& out_str, scope_t& scope) case element_t::STRING: if (elem->min_width > 0) out.width(elem->min_width); - out << elem->chars; + out << boost::get<string>(elem->data); break; - case element_t::EXPR: + case element_t::EXPR: { + expr_t& expr(boost::get<expr_t>(elem->data)); try { - elem->expr.compile(scope); + + expr.compile(scope); value_t value; - if (elem->expr.is_function()) { + if (expr.is_function()) { call_scope_t args(scope); args.push_back(long(elem->max_width)); - value = elem->expr.get_function()(args); + value = expr.get_function()(args); } else { - value = elem->expr.calc(scope); + value = expr.calc(scope); } DEBUG("format.expr", "value = (" << value << ")"); @@ -348,10 +355,11 @@ void format_t::format(std::ostream& out_str, scope_t& scope) } catch (const calc_error&) { add_error_context(_("While calculating format expression:")); - add_error_context(elem->expr.context_to_str()); + add_error_context(expr.context_to_str()); throw; } break; + } default: assert(false); @@ -375,6 +383,8 @@ void format_t::format(std::ostream& out_str, scope_t& scope) out_str << out.str(); } } + + return out_str.str(); } string format_t::truncate(const unistring& ustr, diff --git a/src/format.h b/src/format.h index 8043594b..516b6d7e 100644 --- a/src/format.h +++ b/src/format.h @@ -50,20 +50,20 @@ class unistring; DECLARE_EXCEPTION(format_error, std::runtime_error); -class format_t : public noncopyable +class format_t : public expr_base_t<string> { + typedef expr_base_t<string> base_type; + struct element_t : public supports_flags<> { #define ELEMENT_ALIGN_LEFT 0x01 enum kind_t { STRING, EXPR }; - kind_t type; - std::size_t min_width; - std::size_t max_width; - string chars; - expr_t expr; - + kind_t type; + std::size_t min_width; + std::size_t max_width; + variant<string, expr_t> data; scoped_ptr<struct element_t> next; element_t() throw() @@ -83,8 +83,7 @@ class format_t : public noncopyable type = elem.type; min_width = elem.min_width; max_width = elem.max_width; - chars = elem.chars; - expr = elem.expr; + data = elem.data; } return *this; } @@ -124,25 +123,28 @@ private: const optional<format_t&>& tmpl); public: - format_t() { + format_t() : base_type() { TRACE_CTOR(format_t, ""); } - format_t(const string& _format) { + format_t(const string& _str, scope_t * context = NULL) + : base_type(context) { TRACE_CTOR(format_t, "const string&"); - parse(_format); + if (! _str.empty()) + parse_format(_str); } ~format_t() { TRACE_DTOR(format_t); } - void parse(const string& _format, const optional<format_t&>& tmpl = none) { + void parse_format(const string& _format, + const optional<format_t&>& tmpl = none) { elements.reset(parse_elements(_format, tmpl)); - format_string = _format; + set_text(_format); } - void format(std::ostream& out, scope_t& scope); + virtual result_type real_calc(scope_t& scope); - void dump(std::ostream& out) const { + virtual void dump(std::ostream& out) const { for (const element_t * elem = elements.get(); elem; elem = elem->next.get()) @@ -154,12 +156,6 @@ public: const std::size_t account_abbrev_length = 0); }; -#define FMT_PREFIX "fmt_" -#define FMT_PREFIX_LEN 4 - -#define WANT_FMT() \ - (std::strncmp(p, FMT_PREFIX, FMT_PREFIX_LEN) == 0) - } // namespace ledger #endif // _FORMAT_H diff --git a/src/output.cc b/src/output.cc index eee84553..2a6f0c20 100644 --- a/src/output.cc +++ b/src/output.cc @@ -51,17 +51,19 @@ format_posts::format_posts(report_t& _report, const char * f = format.c_str(); if (const char * p = std::strstr(f, "%/")) { - first_line_format.parse(string(f, 0, p - f)); + first_line_format.parse_format(string(f, 0, p - f)); const char * n = p + 2; if (const char * p = std::strstr(n, "%/")) { - next_lines_format.parse(string(n, 0, p - n), first_line_format); - between_format.parse(string(p + 2), first_line_format); + next_lines_format.parse_format(string(n, 0, p - n), + first_line_format); + between_format.parse_format(string(p + 2), + first_line_format); } else { - next_lines_format.parse(n, first_line_format); + next_lines_format.parse_format(string(n), first_line_format); } } else { - first_line_format.parse(format); - next_lines_format.parse(format); + first_line_format.parse_format(format); + next_lines_format.parse_format(format); } } @@ -80,7 +82,7 @@ void format_posts::operator()(post_t& post) if (last_xact != post.xact) { if (last_xact) { bind_scope_t xact_scope(report, *last_xact); - between_format.format(out, xact_scope); + out << between_format(xact_scope); } print_item(out, *post.xact); out << '\n'; @@ -96,16 +98,16 @@ void format_posts::operator()(post_t& post) if (last_xact != post.xact) { if (last_xact) { bind_scope_t xact_scope(report, *last_xact); - between_format.format(out, xact_scope); + out << between_format(xact_scope); } - first_line_format.format(out, bound_scope); + out << first_line_format(bound_scope); last_xact = post.xact; } else if (last_post && last_post->date() != post.date()) { - first_line_format.format(out, bound_scope); + out << first_line_format(bound_scope); } else { - next_lines_format.format(out, bound_scope); + out << next_lines_format(bound_scope); } post.xdata().add_flags(POST_EXT_DISPLAYED); @@ -122,17 +124,17 @@ format_accounts::format_accounts(report_t& _report, const char * f = format.c_str(); if (const char * p = std::strstr(f, "%/")) { - account_line_format.parse(string(f, 0, p - f)); + account_line_format.parse_format(string(f, 0, p - f)); const char * n = p + 2; if (const char * p = std::strstr(n, "%/")) { - total_line_format.parse(string(n, 0, p - n), account_line_format); - separator_format.parse(string(p + 2), account_line_format); + total_line_format.parse_format(string(n, 0, p - n), account_line_format); + separator_format.parse_format(string(p + 2), account_line_format); } else { - total_line_format.parse(n, account_line_format); + total_line_format.parse_format(n, account_line_format); } } else { - account_line_format.parse(format); - total_line_format.parse(format, account_line_format); + account_line_format.parse_format(format); + total_line_format.parse_format(format, account_line_format); } } @@ -148,7 +150,8 @@ std::size_t format_accounts::post_account(account_t& account, const bool flat) account.xdata().add_flags(ACCOUNT_EXT_DISPLAYED); bind_scope_t bound_scope(report, account); - account_line_format.format(report.output_stream, bound_scope); + static_cast<std::ostream&>(report.output_stream) + << account_line_format(bound_scope); return 1; } @@ -213,8 +216,8 @@ void format_accounts::flush() if (displayed > 1 && ! report.HANDLED(no_total) && ! report.HANDLED(percent)) { bind_scope_t bound_scope(report, *report.session.journal->master); - separator_format.format(out, bound_scope); - total_line_format.format(out, bound_scope); + out << separator_format(bound_scope); + out << total_line_format(bound_scope); } out.flush(); diff --git a/src/precmd.cc b/src/precmd.cc index 277e7b89..92483dc8 100644 --- a/src/precmd.cc +++ b/src/precmd.cc @@ -148,7 +148,7 @@ value_t format_command(call_scope_t& args) out << std::endl << _("--- Formatted string ---") << std::endl; bind_scope_t bound_scope(args, *post); out << '"'; - fmt.format(out, bound_scope); + out << fmt(bound_scope); out << "\"\n"; return NULL_VALUE; diff --git a/src/scope.h b/src/scope.h index cd7d93c7..44ca3229 100644 --- a/src/scope.h +++ b/src/scope.h @@ -54,7 +54,8 @@ struct symbol_t OPTION, PRECOMMAND, COMMAND, - DIRECTIVE + DIRECTIVE, + FORMAT }; kind_t kind; |