webmcp
view framework/env/parse/decimal.lua @ 3:795b764629ca
Version 1.0.3
Important bugfix related to internal forwards (Bug was introduced by the restriction of views with underscore prefix in Version 1.0.2)
Important bugfix related to internal forwards (Bug was introduced by the restriction of views with underscore prefix in Version 1.0.2)
author | jbe |
---|---|
date | Thu Dec 10 12:00:00 2009 +0100 (2009-12-10) |
parents | 9fdfb27f8e67 |
children |
line source
1 local digit_set = {
2 ["0"] = true, ["1"] = true, ["2"] = true, ["3"] = true, ["4"] = true,
3 ["5"] = true, ["6"] = true, ["7"] = true, ["8"] = true, ["9"] = true
4 }
6 function parse.decimal(str, dest_type, options)
7 local str = parse._pre_fold(str)
8 local dest_type = dest_type or atom.number
9 local options = options or {}
10 if str == "" then
11 return nil
12 else
13 local decimal_shift = options.decimal_shift or 0
14 if decimal_shift == true then
15 decimal_shift = options.precision
16 end
17 local decimal_point = locale.get("decimal_point") or "."
18 local negative = nil
19 local int = 0
20 local frac = 0
21 local precision = 0
22 local after_point = false
23 for char in string.gmatch(str, ".") do
24 local skip = false
25 if negative == nil then
26 if char == "+" then
27 negative = false
28 skip = true
29 elseif char == "-" then -- real minus sign already replaced by _pre_fold
30 negative = true
31 skip = true
32 end
33 end
34 if not skip then
35 if digit_set[char] then
36 if after_point then
37 if decimal_shift > 0 then
38 int = 10 * int + tonumber(char)
39 decimal_shift = decimal_shift - 1
40 else
41 frac = 10 * frac + tonumber(char)
42 precision = precision + 1
43 end
44 else
45 int = 10 * int + tonumber(char)
46 end
47 elseif char == decimal_point then
48 if after_point then
49 return dest_type.invalid
50 else
51 after_point = true
52 end
53 elseif char ~= " " then -- TODO: ignore thousand seperator too, when supported by format.decimal
54 return dest_type.invalid
55 end
56 end
57 end
58 int = int * 10 ^ decimal_shift
59 if dest_type == atom.number or dest_type == atom.integer then
60 if dest_type == atom.integer and frac ~= 0 then
61 return atom.not_a_number
62 else
63 local f = int + frac / 10 ^ precision
64 if negative then
65 f = -f
66 end
67 return f
68 end
69 elseif dest_type == atom.fraction then
70 return atom.fraction(int * 10 ^ precision + frac, 10 ^ precision)
71 else
72 error("Missing or invalid destination type for parsing.")
73 end
74 end
75 end