Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /smlnj-lib/trunk/Util/utf8.sml
ViewVC logotype

Annotation of /smlnj-lib/trunk/Util/utf8.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2270 - (view) (download)

1 : jhr 2270 (* utf8.sml
2 :     *
3 :     * COPYRIGHT (c) 2007 John Reppy (http://www.cs.uchicago.edu/~jhr)
4 :     * All rights reserved.
5 :     *
6 :     * Routines for working with UTF8 encoded strings.
7 :     *
8 :     * Unicode value 1st byte 2nd byte 3rd byte 4th byte
9 :     * ----------------- -------- -------- -------- --------
10 :     * 00000000 0xxxxxxx 0xxxxxxx
11 :     * 00000yyy yyxxxxxx 110yyyyy 10xxxxxx
12 :     * zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx
13 :     * 110110ww wwzzzzyy+
14 :     * 110111yy yyxxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx!
15 :     *
16 :     * (!) where uuuuu = wwww+1
17 :     *
18 :     * TODO:
19 :     * Add support for surrogate pairs.
20 :     *)
21 :    
22 :     structure UTF8 :> UTF8 =
23 :     struct
24 :    
25 :     structure W = Word32
26 :     structure SS = Substring
27 :    
28 :     type wchar = W.word
29 :    
30 :     exception Incomplete
31 :     (* raised by some operations when applied to incomplete strings. *)
32 :    
33 :     fun getContByte getc (wc, ss) = (case (getc ss)
34 :     of NONE => raise Incomplete
35 :     | SOME(c, ss') => let
36 :     val b = W.fromInt(Char.ord c)
37 :     in
38 :     if (W.andb(0wxc0, b) = 0wx80)
39 :     then (W.orb(W.<<(wc, 0w6), W.andb(0wx3f, b)), ss')
40 :     else raise Incomplete
41 :     end
42 :     (* end case *))
43 :    
44 :     (* convert a character reader to a wide-character reader *)
45 :     fun getu getc = let
46 :     val getContByte = getContByte getc
47 :     fun get strm = (case getc strm
48 :     of NONE => NONE
49 :     | SOME(c, strm) => let
50 :     val w = W.fromInt(Char.ord c)
51 :     in
52 :     if (w < 0w128)
53 :     then SOME(w, strm)
54 :     else (case (W.andb(0wxe0, w))
55 :     of 0wxc0 => SOME(getContByte (W.andb(0wx1f, w), strm))
56 :     | 0wxe0 => SOME(getContByte(getContByte(W.andb(0wx0f, w), strm)))
57 :     | _ => raise Incomplete
58 :     (* end case *))
59 :     end
60 :     (* end case *))
61 :     in
62 :     get
63 :     end
64 :    
65 :     (* fold a function over the Unicode characters in the string *)
66 :     fun fold f = let
67 :     val getContByte = getContByte SS.getc
68 :     fun foldf (ss, acc) = (case SS.getc ss
69 :     of NONE => acc
70 :     | SOME(c, ss) => let
71 :     val w = W.fromInt(Char.ord c)
72 :     in
73 :     if (w < 0w128)
74 :     then foldf (ss, f(w, acc))
75 :     else (case (W.andb(0wxe0, w))
76 :     of 0wxc0 => let
77 :     val (wc, ss) = getContByte(W.andb(0wx1f, w), ss)
78 :     in
79 :     foldf (ss, f(wc, acc))
80 :     end
81 :     | 0wxe0 => let
82 :     val (wc, ss) =
83 :     getContByte(
84 :     getContByte(W.andb(0wx0f, w), ss))
85 :     in
86 :     foldf (ss, f(wc, acc))
87 :     end
88 :     | _ => raise Incomplete
89 :     (* end case *))
90 :     end
91 :     (* end case *))
92 :     in
93 :     fn init => fn s => foldf (SS.full s, init)
94 :     end
95 :    
96 :     (* return the list of wide characters that are encoded by a string *)
97 :     fun explode s = rev(fold (op ::) [] s)
98 :    
99 :     (* return the number of Unicode characters *)
100 :     fun size s = fold (fn (_, n) => n+1) 0 s
101 :    
102 :     fun w2c w = Char.chr(W.toInt w)
103 :    
104 :     (* return the UTF8 encoding of a wide character *)
105 :     fun encode wc = if (W.<(wc, 0wx80))
106 :     then String.str(w2c wc)
107 :     else if (W.<(wc, 0wx800))
108 :     then String.implode[
109 :     w2c(W.orb(0wxc0, W.>>(wc, 0w6))),
110 :     w2c(W.orb(0wx80, W.andb(wc, 0wx3f)))
111 :     ]
112 :     else String.implode[
113 :     w2c(W.orb(0wxe0, W.>>(wc, 0w12))),
114 :     w2c(W.orb(0wx80, W.andb(W.>>(wc, 0w6), 0wx3f))),
115 :     w2c(W.orb(0wx80, W.andb(wc, 0wx3f)))
116 :     ]
117 :    
118 :     fun isAscii (wc : wchar) = (wc < 0wx80)
119 :     fun toAscii (wc : wchar) = w2c(W.andb(0wx7f, wc))
120 :     fun fromAscii c = W.andb(0wx7f, W.fromInt(Char.ord c))
121 :    
122 :     (* return a printable string representation of a wide character *)
123 :     fun toString wc =
124 :     if isAscii wc
125 :     then Char.toCString(toAscii wc)
126 :     else "\\u" ^ (StringCvt.padLeft #"0" 4 (W.toString wc))
127 :    
128 :     end
129 :    

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0