2 | import public Data.List
4 | import public Data.SnocList
9 | singleton : Char -> String
10 | singleton c = strCons c ""
14 | replicate : Nat -> Char -> String
15 | replicate n c = pack (replicate n c)
19 | indent : (n : Nat) -> String -> String
20 | indent n x = replicate n ' ' ++ x
24 | padLeft : Nat -> Char -> String -> String
25 | padLeft n c str = replicate (minus n (String.length str)) c ++ str
29 | padRight : Nat -> Char -> String -> String
30 | padRight n c str = str ++ replicate (minus n (String.length str)) c
34 | fastUnlines : List String -> String
35 | fastUnlines = fastConcat . unlines'
36 | where unlines' : List String -> List String
38 | unlines' (x :: xs) = x :: "\n" :: unlines' xs
46 | words : String -> List String
47 | words s = map pack (words' (unpack s) [<] [<])
50 | wordsHelper : SnocList Char -> SnocList (List Char) -> SnocList (List Char)
51 | wordsHelper [<] css = css
52 | wordsHelper sc css = css :< (sc <>> Nil)
61 | -> SnocList (List Char)
63 | words' (c :: cs) sc css =
65 | then words' cs [<] (wordsHelper sc css)
66 | else words' cs (sc :< c) css
67 | words' [] sc css = wordsHelper sc css <>> Nil
74 | joinBy : String -> List String -> String
75 | joinBy sep ws = concat (intersperse sep ws)
83 | unwords : List String -> String
84 | unwords = joinBy " "
96 | lines' : List Char -> List (List Char)
97 | lines' s = linesHelp [] s
98 | where linesHelp : List Char -> List Char -> List (List Char)
99 | linesHelp [] [] = []
100 | linesHelp acc [] = [reverse acc]
101 | linesHelp acc ('\n' :: xs) = reverse acc :: linesHelp [] xs
102 | linesHelp acc ('\r' :: '\n' :: xs) = reverse acc :: linesHelp [] xs
103 | linesHelp acc ('\r' :: xs) = reverse acc :: linesHelp [] xs
104 | linesHelp acc (c :: xs) = linesHelp (c :: acc) xs
117 | lines : String -> List String
118 | lines s = map pack (lines' (unpack s))
126 | unlines : List String -> String
127 | unlines ls = concat (interleave ls ("\n" <$ ls))
129 | %transform "fastUnlines"
unlines = fastUnlines
134 | data StrM : String -> Type where
136 | StrCons : (x : Char) -> (xs : String) -> StrM (strCons x xs)
140 | strM : (x : String) -> StrM x
144 | = assert_total $
believe_me $
145 | StrCons (prim__strHead x) (prim__strTail x)
149 | data AsList : String -> Type where
151 | (::) : (c : Char) -> {str : String} -> Lazy (AsList str) -> AsList (strCons c str)
156 | asList : (str : String) -> AsList str
157 | asList str with (strM str)
158 | asList "" | StrNil = []
159 | asList str@(strCons x xs) | StrCons _ _ = x :: asList (assert_smaller str xs)
163 | ltrim : String -> String
164 | ltrim str with (asList str)
166 | ltrim str@_ | x :: xs = if isSpace x then ltrim _ | xs else str
170 | rtrim : String -> String
171 | rtrim = reverse . ltrim . reverse
175 | trim : String -> String
176 | trim = ltrim . rtrim
188 | span : (Char -> Bool) -> String -> (String, String)
190 | = case span p (unpack xs) of
191 | (x, y) => (pack x, pack y)
203 | break : (Char -> Bool) -> String -> (String, String)
204 | break p = span (not . p)
214 | split : (Char -> Bool) -> String -> List1 String
215 | split p xs = map pack (split p (unpack xs))
218 | stringToNatOrZ : String -> Nat
219 | stringToNatOrZ = fromInteger . prim__cast_StringInteger
222 | toUpper : String -> String
223 | toUpper str = pack (map toUpper (unpack str))
226 | toLower : String -> String
227 | toLower str = pack (map toLower (unpack str))
229 | public export partial
230 | strIndex : String -> Int -> Char
231 | strIndex = prim__strIndex
233 | public export covering
234 | strLength : String -> Int
235 | strLength = prim__strLength
237 | public export covering
238 | strSubstr : Int -> Int -> String -> String
239 | strSubstr = prim__strSubstr
241 | public export partial
242 | strTail : String -> String
243 | strTail = prim__strTail
246 | isPrefixOf : String -> String -> Bool
247 | isPrefixOf a b = isPrefixOf (unpack a) (unpack b)
250 | isSuffixOf : String -> String -> Bool
251 | isSuffixOf a b = isSuffixOf (unpack a) (unpack b)
254 | isInfixOf : String -> String -> Bool
255 | isInfixOf a b = isInfixOf (unpack a) (unpack b)
258 | parseNumWithoutSign : List Char -> Integer -> Maybe Integer
259 | parseNumWithoutSign [] acc = Just acc
260 | parseNumWithoutSign (c :: cs) acc =
261 | if (c >= '0' && c <= '9')
262 | then parseNumWithoutSign cs ((acc * 10) + (cast ((ord c) - (ord '0'))))
274 | parsePositive : Num a => String -> Maybe a
275 | parsePositive s = parsePosTrimmed (trim s)
277 | parsePosTrimmed : String -> Maybe a
278 | parsePosTrimmed s with (strM s)
279 | parsePosTrimmed "" | StrNil = Nothing
280 | parsePosTrimmed (strCons '+' xs) | (StrCons '+' xs) =
281 | map fromInteger (parseNumWithoutSign (unpack xs) 0)
282 | parsePosTrimmed (strCons x xs) | (StrCons x xs) =
283 | if (x >= '0' && x <= '9')
284 | then map fromInteger (parseNumWithoutSign (unpack xs) (cast (ord x - ord '0')))
296 | parseInteger : Num a => Neg a => String -> Maybe a
297 | parseInteger s = parseIntTrimmed (trim s)
299 | parseIntTrimmed : String -> Maybe a
300 | parseIntTrimmed s with (strM s)
301 | parseIntTrimmed "" | StrNil = Nothing
302 | parseIntTrimmed (strCons x xs) | (StrCons x xs) =
304 | then map (\y => negate (fromInteger y)) (parseNumWithoutSign (unpack xs) 0)
306 | then map fromInteger (parseNumWithoutSign (unpack xs) (cast {from=Int} 0))
307 | else if (x >= '0' && x <= '9')
308 | then map fromInteger (parseNumWithoutSign (unpack xs) (cast (ord x - ord '0')))
325 | parseDouble : String -> Maybe Double
326 | parseDouble = mkDouble . wfe . trim
328 | intPow : Integer -> Integer -> Double
329 | intPow base exp = assert_total $
if exp > 0 then (num base exp) else 1 / (num base exp)
331 | num : Integer -> Integer -> Double
333 | num base e = if e < 0
334 | then cast base * num base (e + 1)
335 | else cast base * num base (e - 1)
337 | natpow : Double -> Nat -> Double
339 | natpow x (S n) = x * (natpow x n)
341 | mkDouble : Maybe (Double, Double, Integer) -> Maybe Double
342 | mkDouble (Just (w, f, e)) = let ex = intPow 10 e in
343 | Just $
(w * ex + f * ex)
344 | mkDouble Nothing = Nothing
346 | wfe : String -> Maybe (Double, Double, Integer)
347 | wfe cs = case split (== '.') cs of
348 | (wholeAndExp ::: []) =>
349 | case split (\c => c == 'e' || c == 'E') wholeAndExp of
350 | (whole:::exp::[]) =>
352 | w <- cast {from=Integer} <$> parseInteger whole
353 | e <- parseInteger exp
357 | w <- cast {from=Integer} <$> parseInteger whole
360 | (whole:::fracAndExp::[]) =>
361 | case split (\c => c == 'e' || c == 'E') fracAndExp of
362 | ("":::exp::[]) => Nothing
363 | (frac:::exp::[]) =>
365 | w <- cast {from=Integer} <$> parseInteger whole
366 | f <- (/ (natpow 10 (length frac))) <$>
367 | (cast <$> parseNumWithoutSign (unpack frac) 0)
368 | e <- parseInteger exp
369 | pure (w, if w < 0 then (-f) else f, e)
372 | w <- cast {from=Integer} <$> parseInteger whole
373 | f <- (/ (natpow 10 (length frac))) <$>
374 | (cast <$> parseNumWithoutSign (unpack frac) 0)
375 | pure (w, if w < 0 then (-f) else f, 0)
380 | null : String -> Bool