Making String.escaped work on exotic Unicode strings
| Newsgroups | gmane.comp.lang.ocaml.beginners |
|---|---|
| Message-ID | <[email protected]> |
The example code below shows that String.escaped does not work
on exotic strings. How can I fix this ?
In the second code snippet below, I also append my failed attempt
to use the Uutf module.
I've also heard of Camomile, but I'd prefer a hands-on solution
explaining the principles at work rather than just use a bulky library.
$ echo -e "\xE2\x98\xA0" > barney
$ ocaml
OCaml version 4.02.1
# let barneys_channel=open_in "barney";;
val barneys_channel : in_channel = <abstr>
# let m=in_channel_length(barneys_channel);;
val m : int = 4
# let my_buffer=Buffer.create m;;
val my_buffer : Buffer.t = <abstr>
# Buffer.add_channel my_buffer barneys_channel m;;
- : unit = ()
# close_in barneys_channel;;
- : unit = ()
# let strange_string=Buffer.contents my_buffer;;
val strange_string : string = "?\152?\n"
# let quoted_strange_string=String.escaped strange_string;;
val quoted_strange_string : string = "?\\152?\\n"
# let my_strange_string="?\\152?\\n";;
val my_strange_string : string = "?\\152?\\n"
# let copy_successful=(my_strange_string=strange_string);;
val copy_successful : bool = false
Second attempt (using the Uutf library) :
# let lines ?encoding (src : [`Channel of in_channel | `String of string]) =
let rec loop d buf acc = match Uutf.decode d with
| `Uchar 0x000A ->
let line = Buffer.contents buf in
Buffer.clear buf; loop d buf (line :: acc)
| `Uchar u -> Uutf.Buffer.add_utf_8 buf u; loop d buf acc
| `End -> List.rev (Buffer.contents buf :: acc)
| `Malformed _ -> Uutf.Buffer.add_utf_8 buf Uutf.u_rep; loop d buf acc
| `Await -> assert false
in
let nln = `Readline 0x000A in
loop (Uutf.decoder ~nln ?encoding src) (Buffer.create 512) [] ;;
val lines :
?encoding:[< Uutf.decoder_encoding ] ->
[ `Channel of in_channel | `String of string ] -> string list = <fun>
# lines (`String strange_string);;
- : string list = ["?\152?"; ""]
# let second_copy_successful=(strange_string="?\152?");;
val second_copy_successful : bool = false