summaryrefslogtreecommitdiff
path: root/amount.cc
diff options
context:
space:
mode:
Diffstat (limited to 'amount.cc')
-rw-r--r--amount.cc42
1 files changed, 38 insertions, 4 deletions
diff --git a/amount.cc b/amount.cc
index 078e03a0..d0cd5ef9 100644
--- a/amount.cc
+++ b/amount.cc
@@ -932,9 +932,41 @@ void parse_quantity(std::istream& in, std::string& value)
char c = peek_next_nonws(in);
READ_INTO(in, buf, 255, c,
std::isdigit(c) || c == '-' || c == '.' || c == ',');
+
+ int len = std::strlen(buf);
+ while (len > 0 && ! std::isdigit(buf[len - 1])) {
+ buf[--len] = '\0';
+ in.unget();
+ }
+
value = buf;
}
+// Invalid commodity characters:
+// SPACE, TAB, NEWLINE, RETURN
+// 0-9 . , ; - + * / ^ ? : & | ! =
+// < > { } [ ] ( ) @
+
+int invalid_chars[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+/* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
+/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 20 */ 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 40 */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
+/* 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
+/* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* b0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* c0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* d0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* e0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* f0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
void parse_commodity(std::istream& in, std::string& symbol)
{
char buf[256];
@@ -947,8 +979,7 @@ void parse_commodity(std::istream& in, std::string& symbol)
else
throw new amount_error("Quoted commodity symbol lacks closing quote");
} else {
- READ_INTO(in, buf, 255, c, ! std::isspace(c) && ! std::isdigit(c) &&
- c != '-' && c != '.');
+ READ_INTO(in, buf, 255, c, ! invalid_chars[(unsigned char)c]);
}
symbol = buf;
}
@@ -1041,7 +1072,7 @@ void amount_t::parse(std::istream& in, unsigned char flags)
}
char n;
- if (std::isdigit(c) || c == '.') {
+ if (std::isdigit(c)) {
parse_quantity(in, quant);
if (! in.eof() && ((n = in.peek()) != '\n')) {
@@ -1065,7 +1096,7 @@ void amount_t::parse(std::istream& in, unsigned char flags)
parse_quantity(in, quant);
- if (! in.eof() && ((n = in.peek()) != '\n'))
+ if (! quant.empty() && ! in.eof() && ((n = in.peek()) != '\n'))
parse_annotations(in, price, date, tag);
}
}
@@ -1651,6 +1682,9 @@ namespace {
const std::time_t date,
const std::string& tag)
{
+ if (price < 0)
+ throw new amount_error("A commodity's price may not be negative");
+
std::ostringstream name;
comm.write(name);