Revision 1cb92fac htools/Ganeti/HTools/Utils.hs

b/htools/Ganeti/HTools/Utils.hs
46 46
    , formatTable
47 47
    , annotateResult
48 48
    , defaultGroupID
49
    , parseUnit
49 50
    ) where
50 51

  
51 52
import Control.Monad (liftM)
53
import Data.Char (toUpper)
52 54
import Data.List
53 55
import Data.Maybe (fromMaybe)
54 56
import qualified Text.JSON as J
......
252 254
-- | Default group UUID (just a string, not a real UUID).
253 255
defaultGroupID :: GroupID
254 256
defaultGroupID = "00000000-0000-0000-0000-000000000000"
257

  
258
-- | Tries to extract number and scale from the given string.
259
--
260
-- Input must be in the format NUMBER+ SPACE* [UNIT]. If no unit is
261
-- specified, it defaults to MiB. Return value is always an integral
262
-- value in MiB.
263
parseUnit :: (Monad m, Integral a, Read a) => String -> m a
264
parseUnit str =
265
    -- TODO: enhance this by splitting the unit parsing code out and
266
    -- accepting floating-point numbers
267
    case reads str of
268
      [(v, suffix)] ->
269
          let unit = dropWhile (== ' ') suffix
270
              upper = map toUpper unit
271
              siConvert x = x * 1000000 `div` 1048576
272
          in case () of
273
               _ | null unit -> return v
274
                 | unit == "m" || upper == "MIB" -> return v
275
                 | unit == "M" || upper == "MB"  -> return $ siConvert v
276
                 | unit == "g" || upper == "GIB" -> return $ v * 1024
277
                 | unit == "G" || upper == "GB"  -> return $ siConvert
278
                                                    (v * 1000)
279
                 | unit == "t" || upper == "TIB" -> return $ v * 1048576
280
                 | unit == "T" || upper == "TB"  -> return $
281
                                                    siConvert (v * 1000000)
282
                 | otherwise -> fail $ "Unknown unit '" ++ unit ++ "'"
283
      _ -> fail $ "Can't parse string '" ++ str ++ "'"

Also available in: Unified diff