several significant speed improvements (removed excessive copying of strings)
This commit is contained in:
parent
9e235d04a1
commit
325cf53ea7
8 changed files with 86 additions and 118 deletions
6
Makefile
6
Makefile
|
|
@ -42,12 +42,6 @@ all: make.deps ledger
|
|||
|
||||
docs: ledger.info ledger.pdf
|
||||
|
||||
install:
|
||||
make clean
|
||||
make DFLAGS="-O3 -fomit-frame-pointer"
|
||||
cp ledger $(HOME)/bin
|
||||
strip $(HOME)/bin/ledger
|
||||
|
||||
libledger.a: $(OBJS)
|
||||
ar rv $@ $?
|
||||
ranlib $@
|
||||
|
|
|
|||
38
amount.cc
38
amount.cc
|
|
@ -1,6 +1,5 @@
|
|||
#include "amount.h"
|
||||
|
||||
#include <list>
|
||||
#include "ledger.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "gmp.h"
|
||||
|
||||
|
|
@ -585,43 +584,30 @@ static inline char peek_next_nonws(std::istream& in)
|
|||
|
||||
void parse_quantity(std::istream& in, std::string& value)
|
||||
{
|
||||
static char buf[256];
|
||||
char c = peek_next_nonws(in);
|
||||
while (std::isdigit(c) || c == '-' || c == '.' || c == ',') {
|
||||
in.get(c);
|
||||
if (in.eof())
|
||||
break;
|
||||
value += c;
|
||||
c = in.peek();
|
||||
}
|
||||
READ_INTO(in, buf, 256, c,
|
||||
std::isdigit(c) || c == '-' || c == '.' || c == ',');
|
||||
value = buf;
|
||||
}
|
||||
|
||||
void parse_commodity(std::istream& in, std::string& symbol)
|
||||
{
|
||||
static char buf[256];
|
||||
|
||||
char c = peek_next_nonws(in);
|
||||
if (c == '"') {
|
||||
in.get(c);
|
||||
c = in.peek();
|
||||
while (! in.eof() && c != '"') {
|
||||
in.get(c);
|
||||
if (c == '\\')
|
||||
in.get(c);
|
||||
symbol += c;
|
||||
c = in.peek();
|
||||
}
|
||||
|
||||
READ_INTO(in, buf, 256, c, c != '"');
|
||||
if (c == '"')
|
||||
in.get(c);
|
||||
else
|
||||
assert(0);
|
||||
} else {
|
||||
while (! std::isspace(c) && ! std::isdigit(c) && c != '-' && c != '.') {
|
||||
in.get(c);
|
||||
if (in.eof())
|
||||
break;
|
||||
symbol += c;
|
||||
c = in.peek();
|
||||
}
|
||||
READ_INTO(in, buf, 256, c, ! std::isspace(c) && ! std::isdigit(c) &&
|
||||
c != '-' && c != '.');
|
||||
}
|
||||
symbol = buf;
|
||||
}
|
||||
|
||||
void amount_t::parse(std::istream& in)
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ config_t::config_t()
|
|||
{
|
||||
if (const char * p = std::getenv("HOME"))
|
||||
init_file = cache_file = price_db = p;
|
||||
else
|
||||
init_file = cache_file = price_db = "";
|
||||
|
||||
init_file += "/.ledgerrc";
|
||||
cache_file += "/.ledger";
|
||||
|
|
|
|||
59
format.cc
59
format.cc
|
|
@ -47,7 +47,9 @@ element_t * format_t::parse_elements(const std::string& fmt)
|
|||
{
|
||||
element_t * result = NULL;
|
||||
element_t * current = NULL;
|
||||
std::string str;
|
||||
|
||||
static char buf[1024];
|
||||
char * q = buf;
|
||||
|
||||
for (const char * p = fmt.c_str(); *p; p++) {
|
||||
if (*p == '%') {
|
||||
|
|
@ -58,10 +60,10 @@ element_t * format_t::parse_elements(const std::string& fmt)
|
|||
current = current->next;
|
||||
}
|
||||
|
||||
if (! str.empty()) {
|
||||
if (q != buf) {
|
||||
current->type = element_t::STRING;
|
||||
current->chars = str;
|
||||
str = "";
|
||||
current->chars = std::string(buf, q);
|
||||
q = buf;
|
||||
|
||||
current->next = new element_t;
|
||||
current = current->next;
|
||||
|
|
@ -73,22 +75,23 @@ element_t * format_t::parse_elements(const std::string& fmt)
|
|||
++p;
|
||||
}
|
||||
|
||||
std::string num;
|
||||
while (*p && std::isdigit(*p))
|
||||
num += *p++;
|
||||
if (! num.empty())
|
||||
current->min_width = std::atol(num.c_str());
|
||||
int num = 0;
|
||||
while (*p && std::isdigit(*p)) {
|
||||
num *= 10;
|
||||
num += *p++ - '0';
|
||||
}
|
||||
current->min_width = num;
|
||||
|
||||
if (*p == '.') {
|
||||
++p;
|
||||
num = "";
|
||||
while (*p && std::isdigit(*p))
|
||||
num += *p++;
|
||||
if (! num.empty()) {
|
||||
current->max_width = std::atol(num.c_str());
|
||||
if (current->min_width == 0)
|
||||
current->min_width = current->max_width;
|
||||
num = 0;
|
||||
while (*p && std::isdigit(*p)) {
|
||||
num *= 10;
|
||||
num += *p++ - '0';
|
||||
}
|
||||
current->max_width = num;
|
||||
if (current->min_width == 0)
|
||||
current->min_width = current->max_width;
|
||||
}
|
||||
|
||||
switch (*p) {
|
||||
|
|
@ -97,29 +100,31 @@ element_t * format_t::parse_elements(const std::string& fmt)
|
|||
current->chars = "%";
|
||||
break;
|
||||
|
||||
case '(':
|
||||
case '(': {
|
||||
++p;
|
||||
num = "";
|
||||
const char * b = p;
|
||||
while (*p && *p != ')')
|
||||
num += *p++;
|
||||
p++;
|
||||
if (*p != ')')
|
||||
throw format_error("Missing ')'");
|
||||
|
||||
current->type = element_t::VALUE_EXPR;
|
||||
current->val_expr = parse_value_expr(num);
|
||||
current->val_expr = parse_value_expr(std::string(b, p));
|
||||
break;
|
||||
}
|
||||
|
||||
case '[':
|
||||
case '[': {
|
||||
++p;
|
||||
num = "";
|
||||
const char * b = p;
|
||||
while (*p && *p != ']')
|
||||
num += *p++;
|
||||
p++;
|
||||
if (*p != ']')
|
||||
throw format_error("Missing ']'");
|
||||
|
||||
current->type = element_t::DATE_STRING;
|
||||
current->chars = num;
|
||||
current->chars = std::string(b, p);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'D':
|
||||
current->type = element_t::DATE_STRING;
|
||||
|
|
@ -137,11 +142,11 @@ element_t * format_t::parse_elements(const std::string& fmt)
|
|||
case '_': current->type = element_t::SPACER; break;
|
||||
}
|
||||
} else {
|
||||
str += *p;
|
||||
*q++ = *p;
|
||||
}
|
||||
}
|
||||
|
||||
if (! str.empty()) {
|
||||
if (q != buf) {
|
||||
if (! result) {
|
||||
current = result = new element_t;
|
||||
} else {
|
||||
|
|
@ -149,7 +154,7 @@ element_t * format_t::parse_elements(const std::string& fmt)
|
|||
current = current->next;
|
||||
}
|
||||
current->type = element_t::STRING;
|
||||
current->chars = str;
|
||||
current->chars = std::string(buf, q);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
|||
21
option.cc
21
option.cc
|
|
@ -1,4 +1,5 @@
|
|||
#include "option.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdarg>
|
||||
|
|
@ -9,11 +10,16 @@ option_handler::option_handler(const std::string& label,
|
|||
{
|
||||
option_t opt;
|
||||
|
||||
static char buf[128];
|
||||
char * p = buf;
|
||||
for (const char * q = label.c_str(); *q; q++)
|
||||
if (*q == '_')
|
||||
opt.long_opt += '-';
|
||||
*p++ = '-';
|
||||
else
|
||||
opt.long_opt += *q;
|
||||
*p++ = *q;
|
||||
assert(p < buf + 127);
|
||||
*p = '\0';
|
||||
opt.long_opt = buf;
|
||||
|
||||
handlers.insert(option_handler_pair(opt.long_opt, this));
|
||||
|
||||
|
|
@ -130,15 +136,18 @@ void process_environment(char ** envp, const std::string& tag)
|
|||
{
|
||||
for (char ** p = envp; *p; p++)
|
||||
if (std::strncmp(*p, tag.c_str(), 7) == 0) {
|
||||
std::string opt;
|
||||
char * q;
|
||||
static char buf[128];
|
||||
char * r = buf;
|
||||
for (q = *p + 7; *q && *q != '='; q++)
|
||||
if (*q == '_')
|
||||
opt += '-';
|
||||
*r++ += '-';
|
||||
else
|
||||
opt += std::tolower(*q);
|
||||
*r++ += std::tolower(*q);
|
||||
assert(r < buf + 127);
|
||||
*r = '\0';
|
||||
|
||||
if (*q == '=')
|
||||
process_option(opt, q + 1);
|
||||
process_option(buf, q + 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -385,13 +385,12 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
|
|||
in >> c;
|
||||
in >> date;
|
||||
in >> time;
|
||||
date += " ";
|
||||
date += time;
|
||||
|
||||
in.getline(line, MAX_LINE);
|
||||
linenum++;
|
||||
|
||||
date += " ";
|
||||
date += time;
|
||||
|
||||
struct std::tm when;
|
||||
if (strptime(date.c_str(), "%Y/%m/%d %H:%M:%S", &when)) {
|
||||
entry_t * curr = new entry_t;
|
||||
|
|
|
|||
71
valexpr.cc
71
valexpr.cc
|
|
@ -1,6 +1,8 @@
|
|||
#include "valexpr.h"
|
||||
#include "error.h"
|
||||
#include "datetime.h"
|
||||
#include "debug.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -344,32 +346,20 @@ value_expr_t * parse_value_term(std::istream& in)
|
|||
|
||||
char c = peek_next_nonws(in);
|
||||
if (std::isdigit(c) || c == '.' || c == '{') {
|
||||
std::string ident;
|
||||
|
||||
static char buf[2048];
|
||||
if (c == '{') {
|
||||
in.get(c);
|
||||
c = in.peek();
|
||||
while (! in.eof() && c != '}') {
|
||||
in.get(c);
|
||||
ident += c;
|
||||
c = in.peek();
|
||||
}
|
||||
READ_INTO(in, buf, 2048, c, c != '}');
|
||||
if (c == '}')
|
||||
in.get(c);
|
||||
else
|
||||
throw value_expr_error("Missing '}'");
|
||||
} else {
|
||||
while (! in.eof() && std::isdigit(c) || c == '.') {
|
||||
in.get(c);
|
||||
ident += c;
|
||||
c = in.peek();
|
||||
}
|
||||
READ_INTO(in, buf, 2048, c, std::isdigit(c) || c == '.');
|
||||
}
|
||||
|
||||
if (! ident.empty()) {
|
||||
node = new value_expr_t(value_expr_t::CONSTANT_A);
|
||||
node->constant_a.parse(ident);
|
||||
}
|
||||
node = new value_expr_t(value_expr_t::CONSTANT_A);
|
||||
node->constant_a.parse(buf);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
@ -443,7 +433,6 @@ value_expr_t * parse_value_term(std::istream& in)
|
|||
|
||||
// Other
|
||||
case '/': {
|
||||
std::string ident;
|
||||
bool payee_mask = false;
|
||||
|
||||
c = peek_next_nonws(in);
|
||||
|
|
@ -453,22 +442,15 @@ value_expr_t * parse_value_term(std::istream& in)
|
|||
c = in.peek();
|
||||
}
|
||||
|
||||
while (! in.eof() && c != '/') {
|
||||
in.get(c);
|
||||
if (c == '\\')
|
||||
in.get(c);
|
||||
ident += c;
|
||||
c = in.peek();
|
||||
}
|
||||
|
||||
if (c == '/') {
|
||||
in.get(c);
|
||||
node = new value_expr_t(payee_mask ?
|
||||
value_expr_t::F_PAYEE_MASK : value_expr_t::F_ACCOUNT_MASK);
|
||||
node->mask = new mask_t(ident);
|
||||
} else {
|
||||
static char buf[4096];
|
||||
READ_INTO(in, buf, 4096, c, c != '/');
|
||||
if (c != '/')
|
||||
throw value_expr_error("Missing closing '/'");
|
||||
}
|
||||
|
||||
in.get(c);
|
||||
node = new value_expr_t(payee_mask ? value_expr_t::F_PAYEE_MASK :
|
||||
value_expr_t::F_ACCOUNT_MASK);
|
||||
node->mask = new mask_t(buf);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -481,22 +463,15 @@ value_expr_t * parse_value_term(std::istream& in)
|
|||
break;
|
||||
|
||||
case '[': {
|
||||
std::string ident;
|
||||
|
||||
c = in.peek();
|
||||
while (! in.eof() && c != ']') {
|
||||
in.get(c);
|
||||
ident += c;
|
||||
c = in.peek();
|
||||
}
|
||||
if (c == ']') {
|
||||
in.get(c);
|
||||
node = new value_expr_t(value_expr_t::CONSTANT_T);
|
||||
if (! parse_date(ident.c_str(), &node->constant_t))
|
||||
throw value_expr_error("Failed to parse date");
|
||||
} else {
|
||||
static char buf[1024];
|
||||
READ_INTO(in, buf, 1024, c, c != ']');
|
||||
if (c != ']')
|
||||
throw value_expr_error("Missing ']'");
|
||||
}
|
||||
|
||||
in.get(c);
|
||||
node = new value_expr_t(value_expr_t::CONSTANT_T);
|
||||
if (! parse_date(buf, &node->constant_t))
|
||||
throw value_expr_error("Failed to parse date");
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -133,9 +133,11 @@ class item_predicate
|
|||
predicate = NULL;
|
||||
if (! _predicate.empty()) {
|
||||
try {
|
||||
#ifdef DEBUG_ENABLED
|
||||
DEBUG_CLASS("valexpr.predicate.parse");
|
||||
|
||||
DEBUG_PRINT_("parsing: '" << _predicate << "'");
|
||||
#endif
|
||||
predicate = parse_value_expr(_predicate);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue