summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2007-05-07 10:24:55 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 03:38:38 -0400
commit8aada79971b772fda92131053fa03021cfbc625a (patch)
treefbb25be31a419958167d1d166ab0f35d3b7f6a86 /src
parent65e4fc7ebff0245fe13f99663c341e000a29af48 (diff)
downloadfork-ledger-8aada79971b772fda92131053fa03021cfbc625a.tar.gz
fork-ledger-8aada79971b772fda92131053fa03021cfbc625a.tar.bz2
fork-ledger-8aada79971b772fda92131053fa03021cfbc625a.zip
Added a facility for handling scoped executions.
Diffstat (limited to 'src')
-rw-r--r--src/scoped_execute.h73
-rw-r--r--src/session.cc21
-rw-r--r--src/textual.cc35
-rw-r--r--src/utils.h9
4 files changed, 94 insertions, 44 deletions
diff --git a/src/scoped_execute.h b/src/scoped_execute.h
new file mode 100644
index 00000000..da3f388e
--- /dev/null
+++ b/src/scoped_execute.h
@@ -0,0 +1,73 @@
+#ifndef _SCOPE_EXECUTE_H
+#define _SCOPE_EXECUTE_H
+
+template <typename T>
+class scoped_variable : public boost::noncopyable
+{
+ T& var;
+ T prev;
+ bool enabled;
+
+public:
+ explicit scoped_variable(T& _var)
+ : var(_var), prev(var), enabled(true) {}
+ explicit scoped_variable(T& _var, const T& value)
+ : var(_var), prev(var), enabled(true) {
+ var = value;
+ }
+ ~scoped_variable() {
+ if (enabled)
+ var = prev;
+ }
+
+ void clear() {
+ enabled = false;
+ }
+};
+
+template <typename T>
+class scoped_execute : public boost::noncopyable
+{
+ typedef boost::function<void (T)> function_t;
+
+ function_t code;
+ T arg;
+ bool enabled;
+
+public:
+ explicit scoped_execute(const function_t& _code, T _arg)
+ : code(_code), arg(_arg), enabled(true) {}
+
+ ~scoped_execute() {
+ if (enabled)
+ code(arg);
+ }
+
+ void clear() {
+ enabled = false;
+ }
+};
+
+template <>
+class scoped_execute<void> : public boost::noncopyable
+{
+ typedef boost::function<void ()> function_t;
+
+ function_t code;
+ bool enabled;
+
+public:
+ explicit scoped_execute(const function_t& _code)
+ : code(_code), enabled(true) {}
+
+ ~scoped_execute() {
+ if (enabled)
+ code();
+ }
+
+ void clear() {
+ enabled = false;
+ }
+};
+
+#endif // _SCOPE_EXECUTE_H
diff --git a/src/session.cc b/src/session.cc
index d53faf09..1477139c 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -103,22 +103,13 @@ journal_t * session_t::read_data(const string& master_account)
DEBUG("ledger.cache", "using_cache " << cache_file->string());
cache_dirty = true;
if (exists(*cache_file)) {
- ifstream stream(*cache_file);
-
- optional<path> price_db_orig = journal->price_db;
- try {
- journal->price_db = price_db;
-
- entry_count += read_journal(stream, journal, NULL, data_file);
- if (entry_count > 0)
- cache_dirty = false;
+ scoped_variable<optional<path> >
+ save_price_db(journal->price_db, price_db);
- journal->price_db = price_db_orig;
- }
- catch (...) {
- journal->price_db = price_db_orig;
- throw;
- }
+ ifstream stream(*cache_file);
+ entry_count += read_journal(stream, journal, NULL, data_file);
+ if (entry_count > 0)
+ cache_dirty = false;
}
}
diff --git a/src/textual.cc b/src/textual.cc
index 8ed83698..5c2dd81d 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -10,7 +10,8 @@ static unsigned int linenum;
static unsigned int src_idx;
static accounts_map account_aliases;
-static std::list<std::pair<path, int> > include_stack;
+typedef std::list<std::pair<path, int> > include_stack_t;
+static include_stack_t include_stack;
#define TIMELOG_SUPPORT 1
#ifdef TIMELOG_SUPPORT
@@ -508,14 +509,6 @@ entry_t * parse_entry(std::istream& in, char * line, journal_t * journal,
return curr.release();
}
-template <typename T>
-struct push_var {
- T& var;
- T prev;
- push_var(T& _var) : var(_var), prev(var) {}
- ~push_var() { var = prev; }
-};
-
static inline void parse_symbol(char *& p, string& symbol)
{
if (*p == '"') {
@@ -836,11 +829,11 @@ unsigned int textual_parser_t::parse(std::istream& in,
char * p = next_element(line);
string word(line + 1);
if (word == "include") {
- push_var<path> save_path(pathname);
- push_var<unsigned int> save_src_idx(src_idx);
- push_var<unsigned long> save_beg_pos(beg_pos);
- push_var<unsigned long> save_end_pos(end_pos);
- push_var<unsigned int> save_linenum(linenum);
+ scoped_variable<path> save_path(pathname);
+ scoped_variable<unsigned int> save_src_idx(src_idx);
+ scoped_variable<unsigned long> save_beg_pos(beg_pos);
+ scoped_variable<unsigned long> save_end_pos(end_pos);
+ scoped_variable<unsigned int> save_linenum(linenum);
if (*p != '~' && *p != '/')
pathname = (pathname.branch_path() / path(p)).normalize();
@@ -850,18 +843,14 @@ unsigned int textual_parser_t::parse(std::istream& in,
DEBUG("ledger.textual.include", "Line " << linenum << ": " <<
"Including path '" << pathname.string() << "'");
+ scoped_execute<void>
+ pop_include_stack(boost::bind(&include_stack_t::pop_back,
+ boost::ref(include_stack)));
include_stack.push_back
(std::pair<path, int>(journal->sources.back(), linenum - 1));
- try {
- count += journal->session->read_journal(pathname, journal,
- account_stack.front());
- include_stack.pop_back();
- }
- catch (...) {
- include_stack.pop_back();
- throw;
- }
+ count += journal->session->read_journal(pathname, journal,
+ account_stack.front());
}
else if (word == "account") {
if (account_t * acct = account_stack.front()->find_account(p))
diff --git a/src/utils.h b/src/utils.h
index 22fc48dc..a3ef8d39 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -441,16 +441,13 @@ inline void throw_unexpected_error(char c, char wanted) {
/**********************************************************************
*
* Date/time support classes
- */
-
-#include "times.h"
-
-/**********************************************************************
- *
* General support for objects with "flags"
+ * Support for scoped execution and variable restoration
*/
+#include "times.h"
#include "flags.h"
+#include "scoped_execute.h"
/**********************************************************************
*