webmcp
view framework/env/parse/decimal.lua @ 169:681367a16657
json.array and json.object functions create a new container rather than marking a table
| author | jbe | 
|---|---|
| date | Fri Aug 01 05:12:21 2014 +0200 (2014-08-01) | 
| 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
