Moved journal reading code into journal_t
This commit is contained in:
parent
817f1ae161
commit
34ee358f5e
9 changed files with 118 additions and 65 deletions
|
|
@ -67,6 +67,7 @@ global_scope_t::global_scope_t(char ** envp)
|
|||
// open document, with a separate report_t object for each report it
|
||||
// generated.
|
||||
report_stack.push_front(new report_t(session()));
|
||||
scope_t::default_scope = &report();
|
||||
|
||||
// Read the user's options, in the following order:
|
||||
//
|
||||
|
|
@ -111,7 +112,7 @@ void global_scope_t::read_init()
|
|||
|
||||
ifstream init(init_file);
|
||||
|
||||
if (session().read_journal(init_file, NULL, &report()) > 0 ||
|
||||
if (session().journal->read(init_file, NULL, &report()) > 0 ||
|
||||
session().journal->auto_xacts.size() > 0 ||
|
||||
session().journal->period_xacts.size() > 0) {
|
||||
throw_(parse_error, _("Transactions found in initialization file '%1'")
|
||||
|
|
|
|||
|
|
@ -75,10 +75,14 @@ public:
|
|||
|
||||
void push_report() {
|
||||
report_stack.push_front(new report_t(report_stack.front()));
|
||||
scope_t::default_scope = &report();
|
||||
}
|
||||
void pop_report() {
|
||||
if (! report_stack.empty())
|
||||
assert(! report_stack.empty());
|
||||
report_stack.pop_front();
|
||||
// There should always be the "default report" waiting on the stack.
|
||||
assert(! report_stack.empty());
|
||||
scope_t::default_scope = &report();
|
||||
}
|
||||
|
||||
void report_error(const std::exception& err);
|
||||
|
|
|
|||
|
|
@ -41,23 +41,23 @@
|
|||
namespace ledger {
|
||||
|
||||
journal_t::journal_t()
|
||||
: master(new account_t), basket(NULL), was_loaded(false),
|
||||
commodity_pool(new commodity_pool_t)
|
||||
{
|
||||
TRACE_CTOR(journal_t, "");
|
||||
initialize();
|
||||
}
|
||||
|
||||
// Add time commodity conversions, so that timelog's may be parsed
|
||||
// in terms of seconds, but reported as minutes or hours.
|
||||
if (commodity_t * commodity = commodity_pool->create("s"))
|
||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||
else
|
||||
assert(false);
|
||||
journal_t::journal_t(const path& pathname)
|
||||
{
|
||||
TRACE_CTOR(journal_t, "path");
|
||||
initialize();
|
||||
read(pathname);
|
||||
}
|
||||
|
||||
// Add a "percentile" commodity
|
||||
if (commodity_t * commodity = commodity_pool->create("%"))
|
||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||
else
|
||||
assert(false);
|
||||
journal_t::journal_t(const string& str)
|
||||
{
|
||||
TRACE_CTOR(journal_t, "string");
|
||||
initialize();
|
||||
read(str);
|
||||
}
|
||||
|
||||
journal_t::~journal_t()
|
||||
|
|
@ -80,6 +80,28 @@ journal_t::~journal_t()
|
|||
commodity_pool.reset();
|
||||
}
|
||||
|
||||
void journal_t::initialize()
|
||||
{
|
||||
master = new account_t;
|
||||
basket = NULL;
|
||||
was_loaded = false;
|
||||
|
||||
commodity_pool.reset(new commodity_pool_t);
|
||||
|
||||
// Add time commodity conversions, so that timelog's may be parsed
|
||||
// in terms of seconds, but reported as minutes or hours.
|
||||
if (commodity_t * commodity = commodity_pool->create("s"))
|
||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||
else
|
||||
assert(false);
|
||||
|
||||
// Add a "percentile" commodity
|
||||
if (commodity_t * commodity = commodity_pool->create("%"))
|
||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void journal_t::add_account(account_t * acct)
|
||||
{
|
||||
master->add_account(acct);
|
||||
|
|
@ -134,6 +156,55 @@ bool journal_t::remove_xact(xact_t * xact)
|
|||
return true;
|
||||
}
|
||||
|
||||
std::size_t journal_t::read(std::istream& in,
|
||||
const path& pathname,
|
||||
account_t * master_alt,
|
||||
scope_t * scope)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
try {
|
||||
if (! scope)
|
||||
scope = scope_t::default_scope;
|
||||
|
||||
if (! scope)
|
||||
throw_(std::runtime_error,
|
||||
_("No default scope in which to read journal file '%1'")
|
||||
<< pathname);
|
||||
|
||||
value_t strict = expr_t("strict").calc(*scope);
|
||||
|
||||
count = parse(in, *scope, master_alt ? master_alt : master,
|
||||
&pathname, strict.to_boolean());
|
||||
}
|
||||
catch (...) {
|
||||
clear_xdata();
|
||||
throw;
|
||||
}
|
||||
|
||||
// xdata may have been set for some accounts and transaction due to the use
|
||||
// of balance assertions or other calculations performed in valexpr-based
|
||||
// posting amounts.
|
||||
clear_xdata();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
std::size_t journal_t::read(const path& pathname,
|
||||
account_t * master,
|
||||
scope_t * scope)
|
||||
{
|
||||
path filename = resolve_path(pathname);
|
||||
|
||||
if (! exists(filename))
|
||||
throw_(std::runtime_error,
|
||||
_("Cannot read journal file '%1'") << filename);
|
||||
|
||||
ifstream stream(filename);
|
||||
std::size_t count = read(stream, filename, master, scope);
|
||||
sources.push_back(fileinfo_t(filename));
|
||||
return count;
|
||||
}
|
||||
|
||||
void journal_t::clear_xdata()
|
||||
{
|
||||
foreach (xact_t * xact, xacts)
|
||||
|
|
|
|||
|
|
@ -126,8 +126,12 @@ public:
|
|||
hooks_t<xact_finalizer_t, xact_t> xact_finalize_hooks;
|
||||
|
||||
journal_t();
|
||||
journal_t(const path& pathname);
|
||||
journal_t(const string& str);
|
||||
~journal_t();
|
||||
|
||||
void initialize();
|
||||
|
||||
std::list<fileinfo_t>::iterator sources_begin() {
|
||||
return sources.begin();
|
||||
}
|
||||
|
|
@ -171,6 +175,14 @@ public:
|
|||
xact_finalize_hooks.remove_hook(finalizer);
|
||||
}
|
||||
|
||||
std::size_t read(std::istream& in,
|
||||
const path& pathname,
|
||||
account_t * master = NULL,
|
||||
scope_t * scope = NULL);
|
||||
std::size_t read(const path& pathname,
|
||||
account_t * master = NULL,
|
||||
scope_t * scope = NULL);
|
||||
|
||||
std::size_t parse(std::istream& in,
|
||||
scope_t& session_scope,
|
||||
account_t * master = NULL,
|
||||
|
|
|
|||
|
|
@ -171,6 +171,8 @@ namespace {
|
|||
void export_journal()
|
||||
{
|
||||
class_< journal_t::fileinfo_t > ("FileInfo")
|
||||
.def(init<path>())
|
||||
|
||||
.add_property("filename",
|
||||
make_getter(&journal_t::fileinfo_t::filename),
|
||||
make_setter(&journal_t::fileinfo_t::filename))
|
||||
|
|
@ -186,6 +188,9 @@ void export_journal()
|
|||
;
|
||||
|
||||
class_< journal_t, boost::noncopyable > ("Journal")
|
||||
.def(init<path>())
|
||||
.def(init<string>())
|
||||
|
||||
.add_property("master", make_getter(&journal_t::master,
|
||||
return_internal_reference<1>()))
|
||||
.add_property("basket",
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
scope_t * scope_t::default_scope = NULL;
|
||||
|
||||
void symbol_scope_t::define(const symbol_t::kind_t kind,
|
||||
const string& name, expr_t::ptr_op_t def)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ private:
|
|||
class scope_t
|
||||
{
|
||||
public:
|
||||
static scope_t * default_scope;
|
||||
|
||||
explicit scope_t() {
|
||||
TRACE_CTOR(scope_t, "");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,35 +72,6 @@ session_t::session_t()
|
|||
HANDLER(price_db_).on(none, path("./.pricedb").string());
|
||||
}
|
||||
|
||||
std::size_t session_t::read_journal(std::istream& in,
|
||||
const path& pathname,
|
||||
account_t * master,
|
||||
scope_t * scope)
|
||||
{
|
||||
if (! master)
|
||||
master = journal->master;
|
||||
|
||||
std::size_t count = journal->parse(in, scope ? *scope : *this,
|
||||
master, &pathname, HANDLED(strict));
|
||||
|
||||
// remove calculated totals and flags
|
||||
clean_posts();
|
||||
clean_accounts();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
std::size_t session_t::read_journal(const path& pathname,
|
||||
account_t * master,
|
||||
scope_t * scope)
|
||||
{
|
||||
if (! exists(pathname))
|
||||
throw_(std::logic_error, _("Cannot read file '%1'") << pathname);
|
||||
|
||||
ifstream stream(pathname);
|
||||
return read_journal(stream, pathname, master, scope);
|
||||
}
|
||||
|
||||
std::size_t session_t::read_data(const string& master_account)
|
||||
{
|
||||
bool populated_data_files = false;
|
||||
|
|
@ -144,16 +115,14 @@ std::size_t session_t::read_data(const string& master_account)
|
|||
cache->load(journal))) {
|
||||
if (price_db_path) {
|
||||
if (exists(*price_db_path)) {
|
||||
if (read_journal(*price_db_path) > 0)
|
||||
if (journal->read(*price_db_path) > 0)
|
||||
throw_(parse_error, _("Transactions not allowed in price history file"));
|
||||
journal->sources.push_back(journal_t::fileinfo_t(*price_db_path));
|
||||
}
|
||||
HANDLER(file_).data_files.remove(*price_db_path);
|
||||
}
|
||||
|
||||
foreach (const path& pathname, HANDLER(file_).data_files) {
|
||||
path filename = resolve_path(pathname);
|
||||
if (filename == "-") {
|
||||
if (pathname == "-") {
|
||||
// To avoid problems with stdin and pipes, etc., we read the entire
|
||||
// file in beforehand into a memory buffer, and then parcel it out
|
||||
// from there.
|
||||
|
|
@ -169,15 +138,10 @@ std::size_t session_t::read_data(const string& master_account)
|
|||
|
||||
std::istringstream buf_in(buffer.str());
|
||||
|
||||
xact_count += read_journal(buf_in, "/dev/stdin", acct);
|
||||
xact_count += journal->read(buf_in, "/dev/stdin", acct);
|
||||
journal->sources.push_back(journal_t::fileinfo_t());
|
||||
}
|
||||
else if (exists(filename)) {
|
||||
xact_count += read_journal(filename, acct);
|
||||
journal->sources.push_back(journal_t::fileinfo_t(filename));
|
||||
}
|
||||
else {
|
||||
throw_(parse_error, _("Could not read journal file '%1'") << filename);
|
||||
} else {
|
||||
xact_count += journal->read(pathname, acct);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,14 +80,6 @@ public:
|
|||
flush_on_next_data_file = truth;
|
||||
}
|
||||
|
||||
std::size_t read_journal(std::istream& in,
|
||||
const path& pathname,
|
||||
account_t * master = NULL,
|
||||
scope_t * scope = NULL);
|
||||
std::size_t read_journal(const path& pathname,
|
||||
account_t * master = NULL,
|
||||
scope_t * scope = NULL);
|
||||
|
||||
std::size_t read_data(const string& master_account = "");
|
||||
|
||||
void read_journal_files();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue