module STH.Lib.Read (
  readDecimalNat, readPosIntList, readHexadecimalNat
) where

import Control.Arrow ((>>>))
import STH.Lib.Maybe (filterMaybe)
import STH.Lib.Int (digitsToBase)
import STH.Lib.Text.Esc (bsUnEsc)
import STH.Lib.List (unfoldrMaybe)


{-|
  Convert a string (decimal digits) to an integer.
  (Natural numbers only.)
-}
--readDecimalNat.S
readDecimalNat :: String -> Maybe Int
readDecimalNat xs = do
  ys <- sequence $ map decToInt $ reverse xs
  return $ sum $ zipWith (*) ys [10^t | t <- [0..]]
  where
    decToInt :: Char -> Maybe Int
    decToInt x = lookup x
      [ ('0',0), ('1',1), ('2',2), ('3',3), ('4',4)
      , ('5',5), ('6',6), ('7',7), ('8',8), ('9',9)
      ]
--readDecimalNat.E


{-|
  Convert a list of strings of decimal digits
  to a list of integers. (Natural numbers only.)
  If any individual read fails, the whole read fails.
-}
--readPosIntList.S
readPosIntList :: [String] -> Maybe [Int]
readPosIntList = map readDecimalNat
  >>> map (filterMaybe (>0))
  >>> sequence
--readPosIntList.E


{-|
  Convert a string (hexadecimal digits) to an integer.
  (Natural numbers only.)
-}
readHexadecimalNat :: String -> Maybe Int
readHexadecimalNat xs = do
  ys <- sequence $ map hexToInt $ reverse xs
  return $ sum $ zipWith (*) ys [16^t | t <- [0..]]
  where
    hexToInt :: Char -> Maybe Int
    hexToInt x = lookup x
      [ ('0',0), ('1',1), ('2',2), ('3',3), ('4',4)
      , ('5',5), ('6',6), ('7',7), ('8',8), ('9',9)
      , ('a',10), ('b',11), ('c',12), ('d',13), ('e',14), ('f',15)
      , ('A',10), ('B',11), ('C',12), ('D',13), ('E',14), ('F',15)
      ]
