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
|
// open document, with a separate report_t object for each report it
|
||||||
// generated.
|
// generated.
|
||||||
report_stack.push_front(new report_t(session()));
|
report_stack.push_front(new report_t(session()));
|
||||||
|
scope_t::default_scope = &report();
|
||||||
|
|
||||||
// Read the user's options, in the following order:
|
// Read the user's options, in the following order:
|
||||||
//
|
//
|
||||||
|
|
@ -111,7 +112,7 @@ void global_scope_t::read_init()
|
||||||
|
|
||||||
ifstream init(init_file);
|
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->auto_xacts.size() > 0 ||
|
||||||
session().journal->period_xacts.size() > 0) {
|
session().journal->period_xacts.size() > 0) {
|
||||||
throw_(parse_error, _("Transactions found in initialization file '%1'")
|
throw_(parse_error, _("Transactions found in initialization file '%1'")
|
||||||
|
|
|
||||||
|
|
@ -75,10 +75,14 @@ public:
|
||||||
|
|
||||||
void push_report() {
|
void push_report() {
|
||||||
report_stack.push_front(new report_t(report_stack.front()));
|
report_stack.push_front(new report_t(report_stack.front()));
|
||||||
|
scope_t::default_scope = &report();
|
||||||
}
|
}
|
||||||
void pop_report() {
|
void pop_report() {
|
||||||
if (! report_stack.empty())
|
assert(! report_stack.empty());
|
||||||
report_stack.pop_front();
|
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);
|
void report_error(const std::exception& err);
|
||||||
|
|
|
||||||
|
|
@ -41,23 +41,23 @@
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
journal_t::journal_t()
|
journal_t::journal_t()
|
||||||
: master(new account_t), basket(NULL), was_loaded(false),
|
|
||||||
commodity_pool(new commodity_pool_t)
|
|
||||||
{
|
{
|
||||||
TRACE_CTOR(journal_t, "");
|
TRACE_CTOR(journal_t, "");
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
// Add time commodity conversions, so that timelog's may be parsed
|
journal_t::journal_t(const path& pathname)
|
||||||
// in terms of seconds, but reported as minutes or hours.
|
{
|
||||||
if (commodity_t * commodity = commodity_pool->create("s"))
|
TRACE_CTOR(journal_t, "path");
|
||||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
initialize();
|
||||||
else
|
read(pathname);
|
||||||
assert(false);
|
}
|
||||||
|
|
||||||
// Add a "percentile" commodity
|
journal_t::journal_t(const string& str)
|
||||||
if (commodity_t * commodity = commodity_pool->create("%"))
|
{
|
||||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
TRACE_CTOR(journal_t, "string");
|
||||||
else
|
initialize();
|
||||||
assert(false);
|
read(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
journal_t::~journal_t()
|
journal_t::~journal_t()
|
||||||
|
|
@ -80,6 +80,28 @@ journal_t::~journal_t()
|
||||||
commodity_pool.reset();
|
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)
|
void journal_t::add_account(account_t * acct)
|
||||||
{
|
{
|
||||||
master->add_account(acct);
|
master->add_account(acct);
|
||||||
|
|
@ -134,6 +156,55 @@ bool journal_t::remove_xact(xact_t * xact)
|
||||||
return true;
|
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()
|
void journal_t::clear_xdata()
|
||||||
{
|
{
|
||||||
foreach (xact_t * xact, xacts)
|
foreach (xact_t * xact, xacts)
|
||||||
|
|
|
||||||
|
|
@ -126,8 +126,12 @@ public:
|
||||||
hooks_t<xact_finalizer_t, xact_t> xact_finalize_hooks;
|
hooks_t<xact_finalizer_t, xact_t> xact_finalize_hooks;
|
||||||
|
|
||||||
journal_t();
|
journal_t();
|
||||||
|
journal_t(const path& pathname);
|
||||||
|
journal_t(const string& str);
|
||||||
~journal_t();
|
~journal_t();
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
std::list<fileinfo_t>::iterator sources_begin() {
|
std::list<fileinfo_t>::iterator sources_begin() {
|
||||||
return sources.begin();
|
return sources.begin();
|
||||||
}
|
}
|
||||||
|
|
@ -171,6 +175,14 @@ public:
|
||||||
xact_finalize_hooks.remove_hook(finalizer);
|
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,
|
std::size_t parse(std::istream& in,
|
||||||
scope_t& session_scope,
|
scope_t& session_scope,
|
||||||
account_t * master = NULL,
|
account_t * master = NULL,
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,8 @@ namespace {
|
||||||
void export_journal()
|
void export_journal()
|
||||||
{
|
{
|
||||||
class_< journal_t::fileinfo_t > ("FileInfo")
|
class_< journal_t::fileinfo_t > ("FileInfo")
|
||||||
|
.def(init<path>())
|
||||||
|
|
||||||
.add_property("filename",
|
.add_property("filename",
|
||||||
make_getter(&journal_t::fileinfo_t::filename),
|
make_getter(&journal_t::fileinfo_t::filename),
|
||||||
make_setter(&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")
|
class_< journal_t, boost::noncopyable > ("Journal")
|
||||||
|
.def(init<path>())
|
||||||
|
.def(init<string>())
|
||||||
|
|
||||||
.add_property("master", make_getter(&journal_t::master,
|
.add_property("master", make_getter(&journal_t::master,
|
||||||
return_internal_reference<1>()))
|
return_internal_reference<1>()))
|
||||||
.add_property("basket",
|
.add_property("basket",
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
scope_t * scope_t::default_scope = NULL;
|
||||||
|
|
||||||
void symbol_scope_t::define(const symbol_t::kind_t kind,
|
void symbol_scope_t::define(const symbol_t::kind_t kind,
|
||||||
const string& name, expr_t::ptr_op_t def)
|
const string& name, expr_t::ptr_op_t def)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,8 @@ private:
|
||||||
class scope_t
|
class scope_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static scope_t * default_scope;
|
||||||
|
|
||||||
explicit scope_t() {
|
explicit scope_t() {
|
||||||
TRACE_CTOR(scope_t, "");
|
TRACE_CTOR(scope_t, "");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,35 +72,6 @@ session_t::session_t()
|
||||||
HANDLER(price_db_).on(none, path("./.pricedb").string());
|
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)
|
std::size_t session_t::read_data(const string& master_account)
|
||||||
{
|
{
|
||||||
bool populated_data_files = false;
|
bool populated_data_files = false;
|
||||||
|
|
@ -144,16 +115,14 @@ std::size_t session_t::read_data(const string& master_account)
|
||||||
cache->load(journal))) {
|
cache->load(journal))) {
|
||||||
if (price_db_path) {
|
if (price_db_path) {
|
||||||
if (exists(*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"));
|
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);
|
HANDLER(file_).data_files.remove(*price_db_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (const path& pathname, HANDLER(file_).data_files) {
|
foreach (const path& pathname, HANDLER(file_).data_files) {
|
||||||
path filename = resolve_path(pathname);
|
if (pathname == "-") {
|
||||||
if (filename == "-") {
|
|
||||||
// To avoid problems with stdin and pipes, etc., we read the entire
|
// To avoid problems with stdin and pipes, etc., we read the entire
|
||||||
// file in beforehand into a memory buffer, and then parcel it out
|
// file in beforehand into a memory buffer, and then parcel it out
|
||||||
// from there.
|
// from there.
|
||||||
|
|
@ -169,15 +138,10 @@ std::size_t session_t::read_data(const string& master_account)
|
||||||
|
|
||||||
std::istringstream buf_in(buffer.str());
|
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());
|
journal->sources.push_back(journal_t::fileinfo_t());
|
||||||
}
|
} else {
|
||||||
else if (exists(filename)) {
|
xact_count += journal->read(pathname, acct);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,14 +80,6 @@ public:
|
||||||
flush_on_next_data_file = truth;
|
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 = "");
|
std::size_t read_data(const string& master_account = "");
|
||||||
|
|
||||||
void read_journal_files();
|
void read_journal_files();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue