Moved journal reading code into journal_t

This commit is contained in:
John Wiegley 2009-11-05 02:26:06 -05:00
parent 817f1ae161
commit 34ee358f5e
9 changed files with 118 additions and 65 deletions

View file

@ -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'")

View file

@ -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);

View file

@ -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)

View file

@ -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,

View file

@ -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",

View file

@ -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)
{

View file

@ -113,6 +113,8 @@ private:
class scope_t
{
public:
static scope_t * default_scope;
explicit scope_t() {
TRACE_CTOR(scope_t, "");
}

View file

@ -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);
}
}

View file

@ -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();