@@ -11,11 +11,13 @@ module Data.Yaml.Internal
1111 , decodeHelper_
1212 , specialStrings
1313 , isNumeric
14+ , textToScientific
1415 ) where
1516
1617#if !MIN_VERSION_base(4,8,0)
1718import Control.Applicative ((<$>), Applicative(..))
1819#endif
20+import Control.Applicative ((<|>))
1921import Control.Exception
2022import Control.Monad (liftM, ap, unless)
2123import Control.Monad.IO.Class (MonadIO, liftIO)
@@ -25,8 +27,9 @@ import Control.Monad.Trans.State
2527import Data.Aeson
2628import Data.Aeson.Types hiding (parse)
2729import qualified Data.Attoparsec.Text as Atto
30+import Data.Bits (shiftL, (.|.))
2831import Data.ByteString (ByteString)
29−import Data.Char (toUpper)
32+import Data.Char (toUpper, ord)
3033import Data.Conduit ((.|), ConduitM, runConduit)
3134import qualified Data.Conduit.List as CL
3235import qualified Data.HashMap.Strict as M
@@ -176,7 +179,16 @@ textToValue _ _ t
176179 where titleCased = toUpper (T.head ref) `T.cons` T.tail ref
177180
178181textToScientific :: Text -> Either String Scientific
179−textToScientific = Atto.parseOnly (Atto.scientific <* Atto.endOfInput)
182+textToScientific = Atto.parseOnly (num <* Atto.endOfInput)
183+ where
184+ num = (fromInteger <$> ("0x" *> Atto.hexadecimal))
185+ <|> (fromInteger <$> ("0o" *> octal))
186+ <|> Atto.scientific
187+
188+ octal = T.foldl' step 0 <$> Atto.takeWhile1 isOctalDigit
189+ where
190+ isOctalDigit c = (c >= '0' && c <= '7')
191+ step a c = (a `shiftL` 3) .|. fromIntegral (ord c - 48)
180192
181193parseO :: ConduitM Event o Parse Value
182194parseO = do
@@ -291,6 +303,8 @@ isNumeric t =
291303 isNumeric' c = isNumber c
292304 || c == 'e'
293305 || c == 'E'
306+ || c == 'o'
307+ || c == 'x'
294308 || c == '.'
295309 || c == '-'
296310 || c == '+'