24 module Isabelle.Bytes ( |
24 module Isabelle.Bytes ( |
25 Bytes, |
25 Bytes, |
26 make, unmake, pack, unpack, |
26 make, unmake, pack, unpack, |
27 empty, null, length, index, all, any, |
27 empty, null, length, index, all, any, |
28 head, last, take, drop, isPrefixOf, isSuffixOf, |
28 head, last, take, drop, isPrefixOf, isSuffixOf, |
29 concat, space, spaces, char, byte, max_byte, max_char, singleton, |
29 concat, space, spaces, char, byte, max_byte, max_char, singleton |
30 trim_line |
|
31 ) |
30 ) |
32 where |
31 where |
33 |
32 |
34 import Prelude hiding (null, length, all, any, head, last, take, drop, concat) |
33 import Prelude hiding (null, length, all, any, head, last, take, drop, concat) |
35 |
34 |
313 |
304 |
314 {- string-like interfaces -} |
305 {- string-like interfaces -} |
315 |
306 |
316 class (IsString a, Monoid a, Eq a, Ord a) => StringLike a where |
307 class (IsString a, Monoid a, Eq a, Ord a) => StringLike a where |
317 space_explode :: Char -> a -> [a] |
308 space_explode :: Char -> a -> [a] |
|
309 trim_line :: a -> a |
318 |
310 |
319 instance StringLike String where |
311 instance StringLike String where |
|
312 space_explode :: Char -> String -> [String] |
320 space_explode c = Split.split (Split.dropDelims (Split.whenElt (== c))) |
313 space_explode c = Split.split (Split.dropDelims (Split.whenElt (== c))) |
|
314 trim_line :: String -> String |
|
315 trim_line s = |
|
316 if not (null s) && Symbol.is_ascii_line_terminator (last s) then |
|
317 case reverse s of |
|
318 '\n' : '\r' : rest -> reverse rest |
|
319 '\r' : rest -> reverse rest |
|
320 '\n' : rest -> reverse rest |
|
321 _ -> s |
|
322 else s |
321 |
323 |
322 instance StringLike Text where |
324 instance StringLike Text where |
|
325 space_explode :: Char -> Text -> [Text] |
323 space_explode c str = |
326 space_explode c str = |
324 if Text.null str then [] |
327 if Text.null str then [] |
325 else if Text.all (/= c) str then [str] |
328 else if Text.all (/= c) str then [str] |
326 else map Text.pack $ space_explode c $ Text.unpack str |
329 else map Text.pack $ space_explode c $ Text.unpack str |
|
330 trim_line :: Text -> Text |
|
331 trim_line s = |
|
332 if n >= 2 && at (n - 2) == '\r' && at (n - 1) == '\n' then Text.take (n - 2) s |
|
333 else if n >= 1 && Symbol.is_ascii_line_terminator (at (n - 1)) then Text.take (n - 1) s |
|
334 else s |
|
335 where |
|
336 n = Text.length s |
|
337 at = Text.index s |
327 |
338 |
328 instance StringLike Lazy.Text where |
339 instance StringLike Lazy.Text where |
|
340 space_explode :: Char -> Lazy.Text -> [Lazy.Text] |
329 space_explode c str = |
341 space_explode c str = |
330 if Lazy.null str then [] |
342 if Lazy.null str then [] |
331 else if Lazy.all (/= c) str then [str] |
343 else if Lazy.all (/= c) str then [str] |
332 else map Lazy.pack $ space_explode c $ Lazy.unpack str |
344 else map Lazy.pack $ space_explode c $ Lazy.unpack str |
|
345 trim_line :: Lazy.Text -> Lazy.Text |
|
346 trim_line = Lazy.fromStrict . trim_line . Lazy.toStrict |
333 |
347 |
334 instance StringLike Bytes where |
348 instance StringLike Bytes where |
|
349 space_explode :: Char -> Bytes -> [Bytes] |
335 space_explode c str = |
350 space_explode c str = |
336 if Bytes.null str then [] |
351 if Bytes.null str then [] |
337 else if c > Bytes.max_char || Bytes.all (/= (Bytes.byte c)) str then [str] |
352 else if c > Bytes.max_char || Bytes.all (/= (Bytes.byte c)) str then [str] |
338 else |
353 else |
339 explode (Bytes.unpack str) |
354 explode (Bytes.unpack str) |
340 where |
355 where |
341 explode rest = |
356 explode rest = |
342 case span (/= (Bytes.byte c)) rest of |
357 case span (/= (Bytes.byte c)) rest of |
343 (_, []) -> [Bytes.pack rest] |
358 (_, []) -> [Bytes.pack rest] |
344 (prfx, _ : rest') -> Bytes.pack prfx : explode rest' |
359 (prfx, _ : rest') -> Bytes.pack prfx : explode rest' |
|
360 trim_line :: Bytes -> Bytes |
|
361 trim_line s = |
|
362 if n >= 2 && at (n - 2) == '\r' && at (n - 1) == '\n' then Bytes.take (n - 2) s |
|
363 else if n >= 1 && Symbol.is_ascii_line_terminator (at (n - 1)) then Bytes.take (n - 1) s |
|
364 else s |
|
365 where |
|
366 n = Bytes.length s |
|
367 at = Bytes.char . Bytes.index s |
345 |
368 |
346 class StringLike a => STRING a where make_string :: a -> String |
369 class StringLike a => STRING a where make_string :: a -> String |
347 instance STRING String where make_string = id |
370 instance STRING String where make_string = id |
348 instance STRING Text where make_string = Text.unpack |
371 instance STRING Text where make_string = Text.unpack |
349 instance STRING Lazy.Text where make_string = Lazy.unpack |
372 instance STRING Lazy.Text where make_string = Lazy.unpack |
386 split_lines :: StringLike a => a -> [a] |
409 split_lines :: StringLike a => a -> [a] |
387 split_lines = space_explode '\n' |
410 split_lines = space_explode '\n' |
388 |
411 |
389 cat_lines :: StringLike a => [a] -> a |
412 cat_lines :: StringLike a => [a] -> a |
390 cat_lines = space_implode "\n" |
413 cat_lines = space_implode "\n" |
391 |
|
392 trim_line :: String -> String |
|
393 trim_line line = |
|
394 if not (null line) && Symbol.is_ascii_line_terminator (last line) then |
|
395 case reverse line of |
|
396 '\n' : '\r' : rest -> reverse rest |
|
397 '\r' : rest -> reverse rest |
|
398 '\n' : rest -> reverse rest |
|
399 _ -> line |
|
400 else line |
|
401 \<close> |
414 \<close> |
402 |
415 |
403 |
416 |
404 generate_file "Isabelle/Symbol.hs" = \<open> |
417 generate_file "Isabelle/Symbol.hs" = \<open> |
405 {- Title: Isabelle/Symbols.hs |
418 {- Title: Isabelle/Symbols.hs |