diff options
Diffstat (limited to 'binary.cc')
-rw-r--r-- | binary.cc | 606 |
1 files changed, 189 insertions, 417 deletions
@@ -1,4 +1,5 @@ #include "ledger.h" +#include "debug.h" #include <vector> #include <fstream> @@ -13,85 +14,97 @@ namespace ledger { - unsigned long binary_magic_number = 0xFFEED765; -static unsigned long format_version = 0x00020009; +static char buf[4096]; -static char buf[4096]; + unsigned long binary_magic_number = 0xFFEED765; +static unsigned long format_version = 0x0002000a; static std::vector<account_t *> accounts; +static account_t::ident_t ident; static std::vector<commodity_t *> commodities; +static commodity_t::ident_t c_ident; -static unsigned long ident; -static unsigned long c_ident; +#ifdef RELEASE_LEVEL >= ALPHA +#define read_binary_guard(in, id) { \ + unsigned short guard; \ + in.read((char *)&guard, sizeof(guard)); \ + assert(guard == id); \ +} +#else +#define read_binary_guard(in, id) +#endif -void read_binary_amount(std::istream& in, amount_t& amt) +template <typename T> +inline void read_binary_number(std::istream& in, T& num) { + in.read((char *)&num, sizeof(num)); +} + +template <typename T> +inline T read_binary_number(std::istream& in) { + T num; + in.read((char *)&num, sizeof(num)); + return num; +} + +inline void read_binary_string(std::istream& in, std::string& str) { - unsigned long id; + read_binary_guard(in, 0x3001); -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1001); + unsigned char len; + read_binary_number(in, len); + if (len) { + in.read(buf, len); + buf[len] = '\0'; + str = buf; } -#endif - in.read((char *)&id, sizeof(id)); - if (id == 0xffffffff) + read_binary_guard(in, 0x3002); +} + +inline std::string read_binary_string(std::istream& in) +{ + read_binary_guard(in, 0x3001); + + unsigned char len; + read_binary_number(in, len); + if (len) { + in.read(buf, len); + buf[len] = '\0'; + read_binary_guard(in, 0x3002); + return buf; + } + + read_binary_guard(in, 0x3002); + + return ""; +} + +void read_binary_amount(std::istream& in, amount_t& amt) +{ + commodity_t::ident_t id; + read_binary_number(in, id); + if (id == 0xffff) amt.commodity = NULL; else amt.commodity = commodities[id]; amt.read_quantity(in); - -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1002); - } -#endif } transaction_t * read_binary_transaction(std::istream& in, entry_t * entry) { transaction_t * xact = new transaction_t(entry, NULL); - unsigned long id; - -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1003); - } -#endif - - in.read((char *)&id, sizeof(id)); + account_t::ident_t id; + read_binary_number(in, id); xact->account = accounts[id]; xact->account->add_transaction(xact); read_binary_amount(in, xact->amount); read_binary_amount(in, xact->cost); - - in.read((char *)&xact->flags, sizeof(xact->flags)); - - unsigned short len; - in.read((char *)&len, sizeof(len)); - if (len) { - in.read(buf, len); - buf[len] = '\0'; - xact->note = buf; - } - -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1004); - } -#endif + read_binary_number(in, xact->flags); + read_binary_string(in, xact->note); return xact; } @@ -100,101 +113,42 @@ entry_t * read_binary_entry(std::istream& in, journal_t * journal) { entry_t * entry = new entry_t; -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1005); - } -#endif - - in.read((char *)&entry->date, sizeof(entry->date)); - in.read((char *)&entry->state, sizeof(entry->state)); - - unsigned short len; - in.read((char *)&len, sizeof(len)); - if (len) { - in.read(buf, len); - buf[len] = '\0'; - entry->code = buf; - } - - in.read((char *)&len, sizeof(len)); - if (len) { - in.read(buf, len); - buf[len] = '\0'; - entry->payee = buf; - } - - unsigned long count; - in.read((char *)&count, sizeof(count)); + read_binary_number(in, entry->date); + read_binary_number(in, entry->state); + read_binary_string(in, entry->code); + read_binary_string(in, entry->payee); - for (int i = count; --i >= 0; ) { + for (unsigned long i = 0, count = read_binary_number<unsigned long>(in); + i < count; + i++) { transaction_t * xact = read_binary_transaction(in, entry); entry->transactions.push_back(xact); } -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1006); - } -#endif - return entry; } commodity_t * read_binary_commodity(std::istream& in) { - unsigned long id; - commodity_t * commodity = new commodity_t; commodities.push_back(commodity); -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1007); - } -#endif - - in.read((char *)&id, sizeof(id)); + commodity_t::ident_t id; + read_binary_number(in, id); commodity->ident = id; assert(id == commodities.size() - 1); - unsigned short len; - in.read((char *)&len, sizeof(len)); - if (len) { - in.read(buf, len); - buf[len] = '\0'; - commodity->symbol = buf; - } - - in.read((char *)&len, sizeof(len)); - if (len) { - in.read(buf, len); - buf[len] = '\0'; - commodity->name = buf; - } - - in.read((char *)&len, sizeof(len)); - if (len) { - in.read(buf, len); - buf[len] = '\0'; - commodity->note = buf; - } + read_binary_string(in, commodity->symbol); + read_binary_string(in, commodity->name); + read_binary_string(in, commodity->note); + read_binary_number(in, commodity->precision); + read_binary_number(in, commodity->flags); - in.read((char *)&commodity->precision, sizeof(commodity->precision)); - in.read((char *)&commodity->flags, sizeof(commodity->flags)); - - unsigned long count; - in.read((char *)&count, sizeof(count)); - - for (int i = count; --i >= 0; ) { + for (unsigned long i = 0, count = read_binary_number<unsigned long>(in); + i < count; + i++) { std::time_t when; - in.read((char *)&when, sizeof(std::time_t)); + read_binary_number(in, when); amount_t amt; read_binary_amount(in, amt); commodity->history.insert(history_pair(when, amt)); @@ -202,60 +156,28 @@ commodity_t * read_binary_commodity(std::istream& in) read_binary_amount(in, commodity->conversion); -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1008); - } -#endif - return commodity; } account_t * read_binary_account(std::istream& in, account_t * master = NULL) { - unsigned long id; - account_t * acct = new account_t(NULL); accounts.push_back(acct); -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1009); - } -#endif - - in.read((char *)&id, sizeof(id)); + account_t::ident_t id; + read_binary_number(in, id); acct->ident = id; assert(id == accounts.size() - 1); - in.read((char *)&id, sizeof(id)); - if (id == 0xffffffff) + read_binary_number(in, id); // parent id + if (id == 0xffff) acct->parent = NULL; else acct->parent = accounts[id]; - unsigned short len; - in.read((char *)&len, sizeof(len)); - if (len) { - in.read(buf, len); - buf[len] = '\0'; - acct->name = buf; - } - - in.read((char *)&len, sizeof(len)); - if (len) { - in.read(buf, len); - buf[len] = '\0'; - acct->note = buf; - } - - in.read((char *)&acct->depth, sizeof(acct->depth)); - - in.read((char *)&len, sizeof(len)); + read_binary_string(in, acct->name); + read_binary_string(in, acct->note); + read_binary_number(in, acct->depth); // If all of the subaccounts will be added to a different master // account, throw away what we've learned about the recorded @@ -266,82 +188,49 @@ account_t * read_binary_account(std::istream& in, account_t * master = NULL) acct = master; } - for (int i = 0; i < len; i++) { + for (account_t::ident_t i = 0, + count = read_binary_number<account_t::ident_t>(in); + i < count; + i++) { account_t * child = read_binary_account(in); child->parent = acct; acct->add_account(child); } -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1010); - } -#endif - return acct; } -unsigned int read_binary_journal(std::istream& in, - const std::string& leader, - journal_t * journal, - account_t * master) +unsigned int read_binary_journal(std::istream& in, + journal_t * journal, + account_t * master) { - ident = 0; + ident = 0; c_ident = 0; - unsigned long magic; - in.read((char *)&magic, sizeof(magic)); - if (magic != binary_magic_number) + if (read_binary_number<unsigned long>(in) != binary_magic_number || + read_binary_number<unsigned long>(in) != format_version) return 0; -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1011); - } -#endif - - unsigned long this_ver; - in.read((char *)&this_ver, sizeof(this_ver)); - if (this_ver != format_version) - return 0; - - unsigned short len; - in.read((char *)&len, sizeof(len)); - if (! len) - return 0; - in.read(buf, len); - - if (leader != buf) - return 0; - - in.read((char *)&len, sizeof(len)); - - for (int i = len; --i >= 0; ) { - in.read((char *)&len, sizeof(len)); - assert(len); - in.read(buf, len); - buf[len] = '\0'; - - journal->sources.push_back(buf); - + for (unsigned short i = 0, + count = read_binary_number<unsigned short>(in); + i < count; + i++) { + std::string path = read_binary_string(in); std::time_t old_mtime; + read_binary_number(in, old_mtime); struct stat info; - in.read((char *)&old_mtime, sizeof(old_mtime)); - stat(buf, &info); - if (info.st_mtime > old_mtime) + stat(path.c_str(), &info); + if (std::difftime(info.st_mtime, old_mtime) > 0) return 0; + journal->sources.push_back(path); } journal->master = read_binary_account(in, master); - unsigned long count; - in.read((char *)&count, sizeof(count)); - - for (int i = count; --i >= 0; ) { + for (account_t::ident_t i = 0, + count = read_binary_number<account_t::ident_t>(in); + i < count; + i++) { commodity_t * commodity = read_binary_commodity(in); std::pair<commodities_map::iterator, bool> result = commodity_t::commodities.insert(commodities_pair(commodity->symbol, @@ -349,21 +238,14 @@ unsigned int read_binary_journal(std::istream& in, assert(result.second || master); } - in.read((char *)&count, sizeof(count)); - - for (int i = count; --i >= 0; ) { + unsigned int count = read_binary_number<unsigned long>(in); + for (unsigned long i = 0; + i < count; + i++) { entry_t * entry = read_binary_entry(in, journal); journal->entries.push_back(entry); } -#ifdef DEBUG_ENABLED - { - unsigned short guard; - in.read((char *)&guard, sizeof(guard)); - assert(guard == 0x1012); - } -#endif - accounts.clear(); commodities.clear(); @@ -371,254 +253,144 @@ unsigned int read_binary_journal(std::istream& in, } -void write_binary_amount(std::ostream& out, const amount_t& amt) -{ -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1001; - out.write((char *)&guard, sizeof(guard)); - } +#ifdef RELEASE_LEVEL >= ALPHA +#define write_binary_guard(in, id) { \ + unsigned short guard = id; \ + out.write((char *)&guard, sizeof(guard)); \ +} +#else +#define write_binary_guard(in, id) #endif - if (amt.commodity) { - out.write((char *)&amt.commodity->ident, sizeof(amt.commodity->ident)); - } else { - unsigned long end = 0xffffffff; - out.write((char *)&end, sizeof(end)); - } - - amt.write_quantity(out); - -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1002; - out.write((char *)&guard, sizeof(guard)); - } -#endif +template <typename T> +inline void write_binary_number(std::ostream& out, T num) { + out.write((char *)&num, sizeof(num)); } -void write_binary_transaction(std::ostream& out, transaction_t * xact) +inline void write_binary_string(std::ostream& out, const std::string& str) { -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1003; - out.write((char *)&guard, sizeof(guard)); - } -#endif - - out.write((char *)&xact->account->ident, sizeof(xact->account->ident)); - write_binary_amount(out, xact->amount); - write_binary_amount(out, xact->cost); - out.write((char *)&xact->flags, sizeof(xact->flags)); + write_binary_guard(out, 0x3001); - unsigned short len = xact->note.length(); - out.write((char *)&len, sizeof(len)); + unsigned char len = str.length(); + write_binary_number(out, len); if (len) - out.write(xact->note.c_str(), len); + out.write(str.c_str(), len); -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1004; - out.write((char *)&guard, sizeof(guard)); - } -#endif + write_binary_guard(out, 0x3002); } -void write_binary_entry(std::ostream& out, entry_t * entry) +void write_binary_amount(std::ostream& out, const amount_t& amt) { -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1005; - out.write((char *)&guard, sizeof(guard)); - } -#endif - - out.write((char *)&entry->date, sizeof(entry->date)); - out.write((char *)&entry->state, sizeof(entry->state)); + if (amt.commodity) + write_binary_number(out, amt.commodity->ident); + else + write_binary_number<commodity_t::ident_t>(out, 0xffff); - unsigned short len = entry->code.length(); - out.write((char *)&len, sizeof(len)); - if (len) - out.write(entry->code.c_str(), len); + amt.write_quantity(out); +} - len = entry->payee.length(); - out.write((char *)&len, sizeof(len)); - if (len) - out.write(entry->payee.c_str(), len); +void write_binary_transaction(std::ostream& out, transaction_t * xact) +{ + write_binary_number(out, xact->account->ident); + write_binary_amount(out, xact->amount); + write_binary_amount(out, xact->cost); + write_binary_number(out, xact->flags); + write_binary_string(out, xact->note); +} - unsigned long count = entry->transactions.size(); - out.write((char *)&count, sizeof(count)); +void write_binary_entry(std::ostream& out, entry_t * entry) +{ + write_binary_number(out, entry->date); + write_binary_number(out, entry->state); + write_binary_string(out, entry->code); + write_binary_string(out, entry->payee); + write_binary_number<unsigned long>(out, entry->transactions.size()); for (transactions_list::const_iterator i = entry->transactions.begin(); i != entry->transactions.end(); i++) write_binary_transaction(out, *i); - -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1006; - out.write((char *)&guard, sizeof(guard)); - } -#endif } void write_binary_commodity(std::ostream& out, commodity_t * commodity) { -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1007; - out.write((char *)&guard, sizeof(guard)); - } -#endif - - out.write((char *)&c_ident, sizeof(c_ident)); + write_binary_number(out, c_ident); commodity->ident = c_ident; ++c_ident; - unsigned short len = commodity->symbol.length(); - out.write((char *)&len, sizeof(len)); - out.write(commodity->symbol.c_str(), len); - - len = commodity->name.length(); - out.write((char *)&len, sizeof(len)); - if (len) - out.write(commodity->name.c_str(), len); - - len = commodity->note.length(); - out.write((char *)&len, sizeof(len)); - if (len) - out.write(commodity->note.c_str(), len); - - out.write((char *)&commodity->precision, sizeof(commodity->precision)); - out.write((char *)&commodity->flags, sizeof(commodity->flags)); - - unsigned long count = commodity->history.size(); - out.write((char *)&count, sizeof(count)); + write_binary_string(out, commodity->symbol); + write_binary_string(out, commodity->name); + write_binary_string(out, commodity->note); + write_binary_number(out, commodity->precision); + write_binary_number(out, commodity->flags); + write_binary_number<unsigned long>(out, commodity->history.size()); for (history_map::const_iterator i = commodity->history.begin(); i != commodity->history.end(); i++) { - out.write((char *)&((*i).first), sizeof(std::time_t)); + write_binary_number(out, (*i).first); write_binary_amount(out, (*i).second); } write_binary_amount(out, commodity->conversion); - -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1008; - out.write((char *)&guard, sizeof(guard)); - } -#endif } void write_binary_account(std::ostream& out, account_t * account) { -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1009; - out.write((char *)&guard, sizeof(guard)); - } -#endif - - out.write((char *)&ident, sizeof(ident)); + write_binary_number(out, ident); account->ident = ident; ++ident; - if (account->parent) { - out.write((char *)&account->parent->ident, sizeof(account->parent->ident)); - } else { - unsigned long end = 0xffffffff; - out.write((char *)&end, sizeof(end)); - } - - unsigned short len = account->name.length(); - out.write((char *)&len, sizeof(len)); - if (len) - out.write(account->name.c_str(), len); - - len = account->note.length(); - out.write((char *)&len, sizeof(len)); - if (len) - out.write(account->note.c_str(), len); - - out.write((char *)&account->depth, sizeof(account->depth)); + if (account->parent) + write_binary_number(out, account->parent->ident); + else + write_binary_number<account_t::ident_t>(out, 0xffff); - len = account->accounts.size(); - out.write((char *)&len, sizeof(len)); + write_binary_string(out, account->name); + write_binary_string(out, account->note); + write_binary_number(out, account->depth); + write_binary_number<account_t::ident_t>(out, account->accounts.size()); for (accounts_map::iterator i = account->accounts.begin(); i != account->accounts.end(); i++) write_binary_account(out, (*i).second); - -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1010; - out.write((char *)&guard, sizeof(guard)); - } -#endif } void write_binary_journal(std::ostream& out, journal_t * journal, - const std::string& leader) + strings_list * files) { - out.write((char *)&binary_magic_number, sizeof(binary_magic_number)); + write_binary_number(out, binary_magic_number); + write_binary_number(out, format_version); -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1011; - out.write((char *)&guard, sizeof(guard)); - } -#endif - - out.write((char *)&format_version, sizeof(format_version)); - - unsigned short len = leader.length(); - assert(len > 0); - out.write((char *)&len, sizeof(len)); - out.write(leader.c_str(), len); - - len = journal->sources.size(); - out.write((char *)&len, sizeof(len)); - - for (std::list<std::string>::const_iterator i = journal->sources.begin(); - i != journal->sources.end(); - i++) { - len = (*i).length(); - out.write((char *)&len, sizeof(len)); - assert(len); - out.write((*i).c_str(), len); - struct stat info; - stat((*i).c_str(), &info); - out.write((char *)&info.st_mtime, sizeof(info.st_mtime)); + if (! files) { + write_binary_number<unsigned short>(out, 0); + } else { + write_binary_number<unsigned short>(out, files->size()); + for (strings_list::const_iterator i = files->begin(); + i != files->end(); + i++) { + write_binary_string(out, *i); + struct stat info; + stat((*i).c_str(), &info); + write_binary_number(out, std::time_t(info.st_mtime)); + } } write_binary_account(out, journal->master); - unsigned long count = commodity_t::commodities.size() - 1; - out.write((char *)&count, sizeof(count)); - + write_binary_number<commodity_t::ident_t>(out, commodity_t::commodities.size() - 1); for (commodities_map::const_iterator i = commodity_t::commodities.begin(); i != commodity_t::commodities.end(); i++) if (! (*i).first.empty()) write_binary_commodity(out, (*i).second); - count = journal->entries.size(); - out.write((char *)&count, sizeof(count)); - + write_binary_number<unsigned long>(out, journal->entries.size()); for (entries_list::const_iterator i = journal->entries.begin(); i != journal->entries.end(); i++) write_binary_entry(out, *i); - -#ifdef DEBUG_ENABLED - { - unsigned short guard = 0x1012; - out.write((char *)&guard, sizeof(guard)); - } -#endif } } // namespace ledger |