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 | trim : String -> String
171 | trim = ltrim . reverse . ltrim . reverse
183 | span : (Char -> Bool) -> String -> (String, String)
185 | = case span p (unpack xs) of
186 | (x, y) => (pack x, pack y)
198 | break : (Char -> Bool) -> String -> (String, String)
199 | break p = span (not . p)
209 | split : (Char -> Bool) -> String -> List1 String
210 | split p xs = map pack (split p (unpack xs))
213 | stringToNatOrZ : String -> Nat
214 | stringToNatOrZ = fromInteger . prim__cast_StringInteger
217 | toUpper : String -> String
218 | toUpper str = pack (map toUpper (unpack str))
221 | toLower : String -> String
222 | toLower str = pack (map toLower (unpack str))
224 | public export partial
225 | strIndex : String -> Int -> Char
226 | strIndex = prim__strIndex
228 | public export covering
229 | strLength : String -> Int
230 | strLength = prim__strLength
232 | public export covering
233 | strSubstr : Int -> Int -> String -> String
234 | strSubstr = prim__strSubstr
236 | public export partial
237 | strTail : String -> String
238 | strTail = prim__strTail
241 | isPrefixOf : String -> String -> Bool
242 | isPrefixOf a b = isPrefixOf (unpack a) (unpack b)
245 | isSuffixOf : String -> String -> Bool
246 | isSuffixOf a b = isSuffixOf (unpack a) (unpack b)
249 | isInfixOf : String -> String -> Bool
250 | isInfixOf a b = isInfixOf (unpack a) (unpack b)
253 | parseNumWithoutSign : List Char -> Integer -> Maybe Integer
254 | parseNumWithoutSign [] acc = Just acc
255 | parseNumWithoutSign (c :: cs) acc =
256 | if (c >= '0' && c <= '9')
257 | then parseNumWithoutSign cs ((acc * 10) + (cast ((ord c) - (ord '0'))))
269 | parsePositive : Num a => String -> Maybe a
270 | parsePositive s = parsePosTrimmed (trim s)
272 | parsePosTrimmed : String -> Maybe a
273 | parsePosTrimmed s with (strM s)
274 | parsePosTrimmed "" | StrNil = Nothing
275 | parsePosTrimmed (strCons '+' xs) | (StrCons '+' xs) =
276 | map fromInteger (parseNumWithoutSign (unpack xs) 0)
277 | parsePosTrimmed (strCons x xs) | (StrCons x xs) =
278 | if (x >= '0' && x <= '9')
279 | then map fromInteger (parseNumWithoutSign (unpack xs) (cast (ord x - ord '0')))
291 | parseInteger : Num a => Neg a => String -> Maybe a
292 | parseInteger s = parseIntTrimmed (trim s)
294 | parseIntTrimmed : String -> Maybe a
295 | parseIntTrimmed s with (strM s)
296 | parseIntTrimmed "" | StrNil = Nothing
297 | parseIntTrimmed (strCons x xs) | (StrCons x xs) =
299 | then map (\y => negate (fromInteger y)) (parseNumWithoutSign (unpack xs) 0)
301 | then map fromInteger (parseNumWithoutSign (unpack xs) (cast {from=Int} 0))
302 | else if (x >= '0' && x <= '9')
303 | then map fromInteger (parseNumWithoutSign (unpack xs) (cast (ord x - ord '0')))
320 | parseDouble : String -> Maybe Double
321 | parseDouble = mkDouble . wfe . trim
323 | intPow : Integer -> Integer -> Double
324 | intPow base exp = assert_total $
if exp > 0 then (num base exp) else 1 / (num base exp)
326 | num : Integer -> Integer -> Double
328 | num base e = if e < 0
329 | then cast base * num base (e + 1)
330 | else cast base * num base (e - 1)
332 | natpow : Double -> Nat -> Double
334 | natpow x (S n) = x * (natpow x n)
336 | mkDouble : Maybe (Double, Double, Integer) -> Maybe Double
337 | mkDouble (Just (w, f, e)) = let ex = intPow 10 e in
338 | Just $
(w * ex + f * ex)
339 | mkDouble Nothing = Nothing
341 | wfe : String -> Maybe (Double, Double, Integer)
342 | wfe cs = case split (== '.') cs of
343 | (wholeAndExp ::: []) =>
344 | case split (\c => c == 'e' || c == 'E') wholeAndExp of
345 | (whole:::exp::[]) =>
347 | w <- cast {from=Integer} <$> parseInteger whole
348 | e <- parseInteger exp
352 | w <- cast {from=Integer} <$> parseInteger whole
355 | (whole:::fracAndExp::[]) =>
356 | case split (\c => c == 'e' || c == 'E') fracAndExp of
357 | ("":::exp::[]) => Nothing
358 | (frac:::exp::[]) =>
360 | w <- cast {from=Integer} <$> parseInteger whole
361 | f <- (/ (natpow 10 (length frac))) <$>
362 | (cast <$> parseNumWithoutSign (unpack frac) 0)
363 | e <- parseInteger exp
364 | pure (w, if w < 0 then (-f) else f, e)
367 | w <- cast {from=Integer} <$> parseInteger whole
368 | f <- (/ (natpow 10 (length frac))) <$>
369 | (cast <$> parseNumWithoutSign (unpack frac) 0)
370 | pure (w, if w < 0 then (-f) else f, 0)
375 | null : String -> Bool