summaryrefslogtreecommitdiff
path: root/parser.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2005-11-09 07:11:22 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 02:41:21 -0400
commite1d0dbf220a5301f6125a1548a380492ad488515 (patch)
treedf7a5de60353d3558b00d21ee83cf01e8da56331 /parser.cc
parent6f4957c8c31395bca44d078972690eb2b3258a8f (diff)
downloadfork-ledger-e1d0dbf220a5301f6125a1548a380492ad488515.tar.gz
fork-ledger-e1d0dbf220a5301f6125a1548a380492ad488515.tar.bz2
fork-ledger-e1d0dbf220a5301f6125a1548a380492ad488515.zip
Restructed the code that it can build and be used as a shared library.
The command-line version is still statically bound in the build process by default (for the sake of speed).
Diffstat (limited to 'parser.cc')
-rw-r--r--parser.cc138
1 files changed, 129 insertions, 9 deletions
diff --git a/parser.cc b/parser.cc
index cc93b9dc..6d589bf8 100644
--- a/parser.cc
+++ b/parser.cc
@@ -1,5 +1,6 @@
#include "parser.h"
#include "journal.h"
+#include "config.h"
#include <fstream>
#ifdef WIN32
@@ -12,18 +13,31 @@ namespace ledger {
typedef std::list<parser_t *> parsers_list;
-static parsers_list parsers;
+static parsers_list * parsers = NULL;
+
+void initialize_parser_support()
+{
+ parsers = new parsers_list;
+}
+
+void shutdown_parser_support()
+{
+ if (parsers) {
+ delete parsers;
+ parsers = NULL;
+ }
+}
bool register_parser(parser_t * parser)
{
parsers_list::iterator i;
- for (i = parsers.begin(); i != parsers.end(); i++)
+ for (i = parsers->begin(); i != parsers->end(); i++)
if (*i == parser)
break;
- if (i != parsers.end())
+ if (i != parsers->end())
return false;
- parsers.push_back(parser);
+ parsers->push_back(parser);
return true;
}
@@ -31,13 +45,13 @@ bool register_parser(parser_t * parser)
bool unregister_parser(parser_t * parser)
{
parsers_list::iterator i;
- for (i = parsers.begin(); i != parsers.end(); i++)
+ for (i = parsers->begin(); i != parsers->end(); i++)
if (*i == parser)
break;
- if (i == parsers.end())
+ if (i == parsers->end())
return false;
- parsers.erase(i);
+ parsers->erase(i);
return true;
}
@@ -50,8 +64,8 @@ unsigned int parse_journal(std::istream& in,
if (! master)
master = journal->master;
- for (parsers_list::iterator i = parsers.begin();
- i != parsers.end();
+ for (parsers_list::iterator i = parsers->begin();
+ i != parsers->end();
i++)
if ((*i)->test(in))
return (*i)->parse(in, journal, master, original_file);
@@ -76,6 +90,106 @@ unsigned int parse_journal_file(const std::string& path,
return parse_journal(stream, journal, master, original_file);
}
+unsigned int parse_ledger_data(journal_t * journal,
+ const std::string& data_file,
+ const std::string& init_file,
+ const std::string& price_db,
+ bool use_cache,
+ const std::string& cache_file,
+ bool * cache_dirty,
+ parser_t * cache_parser,
+ parser_t * xml_parser,
+ parser_t * stdin_parser,
+ const std::string& default_account)
+{
+ unsigned int entry_count = 0;
+
+ DEBUG_PRINT("ledger.config.cache", "3. use_cache = " << use_cache);
+
+ if (! init_file.empty() && access(init_file.c_str(), R_OK) != -1) {
+ if (parse_journal_file(init_file, journal) ||
+ journal->auto_entries.size() > 0 ||
+ journal->period_entries.size() > 0)
+ throw error(std::string("Entries found in initialization file '") +
+ init_file + "'");
+
+ journal->sources.pop_front(); // remove init file
+ }
+
+ if (use_cache && ! cache_file.empty() && ! data_file.empty()) {
+ DEBUG_PRINT("ledger.config.cache", "using_cache " << cache_file);
+ if (cache_dirty)
+ *cache_dirty = true;
+ if (access(cache_file.c_str(), R_OK) != -1) {
+ std::ifstream stream(cache_file.c_str());
+ if (cache_parser && cache_parser->test(stream)) {
+ std::string price_db_orig = journal->price_db;
+ journal->price_db = price_db;
+ entry_count += cache_parser->parse(stream, journal, NULL, &data_file);
+ if (entry_count > 0) {
+ if (cache_dirty)
+ *cache_dirty = false;
+ } else {
+ journal->price_db = price_db_orig;
+ }
+ }
+ }
+ }
+
+ if (entry_count == 0 && ! data_file.empty()) {
+ account_t * acct = NULL;
+ if (! default_account.empty())
+ acct = journal->find_account(default_account);
+
+ journal->price_db = price_db;
+ if (! journal->price_db.empty() &&
+ access(journal->price_db.c_str(), R_OK) != -1) {
+ if (parse_journal_file(journal->price_db, journal)) {
+ throw error("Entries not allowed in price history file");
+ } else {
+ DEBUG_PRINT("ledger.config.cache",
+ "read price database " << journal->price_db);
+ journal->sources.pop_back();
+ }
+ }
+
+ DEBUG_PRINT("ledger.config.cache",
+ "rejected cache, parsing " << data_file);
+ if (data_file == "-") {
+ use_cache = false;
+ journal->sources.push_back("<stdin>");
+#if 0
+ if (xml_parser && std::cin.peek() == '<')
+ entry_count += xml_parser->parse(std::cin, journal, acct);
+ else if (stdin_parser)
+#endif
+ entry_count += stdin_parser->parse(std::cin, journal, acct);
+ }
+ else if (access(data_file.c_str(), R_OK) != -1) {
+ entry_count += parse_journal_file(data_file, journal, acct);
+ if (! journal->price_db.empty())
+ journal->sources.push_back(journal->price_db);
+ }
+ }
+
+ VALIDATE(journal->valid());
+
+ return entry_count;
+}
+
+extern parser_t * binary_parser_ptr;
+extern parser_t * xml_parser_ptr;
+extern parser_t * textual_parser_ptr;
+
+unsigned int parse_ledger_data(journal_t * journal, config_t& config)
+{
+ return parse_ledger_data(journal, config.data_file, config.init_file,
+ config.price_db, config.use_cache,
+ config.cache_file, &config.cache_dirty,
+ binary_parser_ptr, xml_parser_ptr,
+ textual_parser_ptr, config.account);
+}
+
} // namespace ledger
#ifdef USE_BOOST_PYTHON
@@ -108,6 +222,9 @@ BOOST_PYTHON_FUNCTION_OVERLOADS(parse_journal_overloads, parse_journal, 2, 4)
BOOST_PYTHON_FUNCTION_OVERLOADS(parse_journal_file_overloads,
parse_journal_file, 2, 4)
+BOOST_PYTHON_FUNCTION_OVERLOADS(parse_ledger_data_overloads,
+ parse_ledger_data, 1, 2)
+
void export_parser() {
class_< parser_t, parser_wrap, boost::noncopyable > ("Parser")
;
@@ -116,6 +233,9 @@ void export_parser() {
def("unregister_parser", unregister_parser);
def("parse_journal", parse_journal, parse_journal_overloads());
def("parse_journal_file", parse_journal_file, parse_journal_file_overloads());
+#if 0
+ def("parse_ledger_data", parse_ledger_data, parse_ledger_data_overloads());
+#endif
}
#endif // USE_BOOST_PYTHON