diff options
Diffstat (limited to 'parser.cc')
-rw-r--r-- | parser.cc | 212 |
1 files changed, 37 insertions, 175 deletions
@@ -1,193 +1,55 @@ -#include "parser.h" -#include "journal.h" -#include "config.h" - -#include <fstream> -#ifdef WIN32 -#include <io.h> +#ifdef USE_PCH +#include "pch.h" #else -#include <unistd.h> +#include "parser.h" #endif -namespace ledger { - -typedef std::list<parser_t *> parsers_list; - -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++) - if (*i == parser) - break; - if (i != parsers->end()) - return false; - - parsers->push_back(parser); - - return true; -} - -bool unregister_parser(parser_t * parser) -{ - parsers_list::iterator i; - for (i = parsers->begin(); i != parsers->end(); i++) - if (*i == parser) - break; - if (i == parsers->end()) - return false; - - parsers->erase(i); - - return true; -} - -unsigned int parse_journal(std::istream& in, - config_t& config, - journal_t * journal, - account_t * master, - const std::string * original_file) -{ - if (! master) - master = journal->master; - - for (parsers_list::iterator i = parsers->begin(); - i != parsers->end(); - i++) - if ((*i)->test(in)) - return (*i)->parse(in, config, journal, master, original_file); - - return 0; -} - -unsigned int parse_journal_file(const std::string& path, - config_t& config, - journal_t * journal, - account_t * master, - const std::string * original_file) -{ - journal->sources.push_back(path); +#ifdef USE_BOOST_PYTHON - if (access(path.c_str(), R_OK) == -1) - throw new error(std::string("Cannot read file '") + path + "'"); - - if (! original_file) - original_file = &path; - - std::ifstream stream(path.c_str()); - return parse_journal(stream, config, journal, master, original_file); -} +#ifndef USE_PCH +#include <boost/python.hpp> +#include <Python.h> +#endif -extern parser_t * binary_parser_ptr; -extern parser_t * xml_parser_ptr; -extern parser_t * textual_parser_ptr; +using namespace boost::python; +using namespace ledger; -unsigned int parse_ledger_data(config_t& config, - journal_t * journal, - parser_t * cache_parser, - parser_t * xml_parser, - parser_t * stdin_parser) +struct py_parser_t : public parser_t { - unsigned int entry_count = 0; - - if (! cache_parser) - cache_parser = binary_parser_ptr; - if (! xml_parser) - xml_parser = xml_parser_ptr; - if (! stdin_parser) - stdin_parser = textual_parser_ptr; + PyObject * self; + py_parser_t(PyObject * self_) : self(self_) {} - DEBUG_PRINT("ledger.config.cache", - "3. use_cache = " << config.use_cache); - - if (! config.init_file.empty() && - access(config.init_file.c_str(), R_OK) != -1) { - if (parse_journal_file(config.init_file, config, journal) || - journal->auto_entries.size() > 0 || - journal->period_entries.size() > 0) - throw new error(std::string("Entries found in initialization file '") + - config.init_file + "'"); - - journal->sources.pop_front(); // remove init file + virtual bool test(std::istream& in) const { + return call_method<bool>(self, "test", in); } - if (config.use_cache && ! config.cache_file.empty() && - ! config.data_file.empty()) { - DEBUG_PRINT("ledger.config.cache", - "using_cache " << config.cache_file); - config.cache_dirty = true; - if (access(config.cache_file.c_str(), R_OK) != -1) { - std::ifstream stream(config.cache_file.c_str()); - if (cache_parser && cache_parser->test(stream)) { - std::string price_db_orig = journal->price_db; - journal->price_db = config.price_db; - entry_count += cache_parser->parse(stream, config, journal, - NULL, &config.data_file); - if (entry_count > 0) - config.cache_dirty = false; - else - journal->price_db = price_db_orig; - } - } + virtual repitem_t * parse(std::istream& in, + journal_t * journal, + account_t * master = NULL, + const std::string * original_file = NULL) { + return call_method<unsigned int>(self, "parse", in, journal, master, + original_file); } +}; - if (entry_count == 0 && ! config.data_file.empty()) { - account_t * acct = NULL; - if (! config.account.empty()) - acct = journal->find_account(config.account); +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(parser_parse_overloads, + py_parser_t::parse, 2, 4) - journal->price_db = config.price_db; - if (! journal->price_db.empty() && - access(journal->price_db.c_str(), R_OK) != -1) { - if (parse_journal_file(journal->price_db, config, journal)) { - throw new error("Entries not allowed in price history file"); - } else { - DEBUG_PRINT("ledger.config.cache", - "read price database " << journal->price_db); - journal->sources.pop_back(); - } - } +BOOST_PYTHON_FUNCTION_OVERLOADS(parse_journal_overloads, parse_journal, 2, 4) +BOOST_PYTHON_FUNCTION_OVERLOADS(parse_journal_file_overloads, + parse_journal_file, 2, 4) - DEBUG_PRINT("ledger.config.cache", - "rejected cache, parsing " << config.data_file); - if (config.data_file == "-") { - config.use_cache = false; - journal->sources.push_back("<stdin>"); -#if 0 - // jww (2006-03-23): Why doesn't XML work on stdin? - if (xml_parser && std::cin.peek() == '<') - entry_count += xml_parser->parse(std::cin, config, journal, - acct); - else if (stdin_parser) -#endif - entry_count += stdin_parser->parse(std::cin, config, - journal, acct); - } - else if (access(config.data_file.c_str(), R_OK) != -1) { - entry_count += parse_journal_file(config.data_file, config, - journal, acct); - if (! journal->price_db.empty()) - journal->sources.push_back(journal->price_db); - } - } +void export_parser() { + class_< parser_t, py_parser_t, boost::noncopyable > ("Parser") + .def("test", &py_parser_t::test) + .def("parse", &py_parser_t::parse, parser_parse_overloads()) + ; - VALIDATE(journal->valid()); + def("register_parser", register_parser); + def("unregister_parser", unregister_parser); - return entry_count; + def("parse_journal", parse_journal, parse_journal_overloads()); + def("parse_journal_file", parse_journal_file, parse_journal_file_overloads()); } -} // namespace ledger +#endif // USE_BOOST_PYTHON |