]> gitweb.factorcode.org Git - factor.git/blob - core/io/encodings/utf8/utf8.factor
Merge branch 'require-when' of git://github.com/littledan/Factor
[factor.git] / core / io / encodings / utf8 / utf8.factor
1 ! Copyright (C) 2006, 2008 Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors byte-arrays math math.order kernel sequences
4 sbufs vectors growable io continuations namespaces io.encodings
5 combinators strings ;
6 IN: io.encodings.utf8
7
8 ! Decoding UTF-8
9
10 SINGLETON: utf8
11
12 <PRIVATE 
13
14 : starts-2? ( char -- ? )
15     dup [ -6 shift BIN: 10 number= ] when ; inline
16
17 : append-nums ( stream byte -- stream char )
18     over stream-read1 dup starts-2?
19     [ swap 6 shift swap BIN: 111111 bitand bitor ]
20     [ 2drop replacement-char ] if ; inline
21
22 : double ( stream byte -- stream char )
23     BIN: 11111 bitand append-nums ; inline
24
25 : triple ( stream byte -- stream char )
26     BIN: 1111 bitand append-nums append-nums ; inline
27
28 : quadruple ( stream byte -- stream char )
29     BIN: 111 bitand append-nums append-nums append-nums ; inline
30
31 : begin-utf8 ( stream byte -- stream char )
32     {
33         { [ dup -7 shift zero? ] [ ] }
34         { [ dup -5 shift BIN: 110 = ] [ double ] }
35         { [ dup -4 shift BIN: 1110 = ] [ triple ] }
36         { [ dup -3 shift BIN: 11110 = ] [ quadruple ] }
37         [ drop replacement-char ]
38     } cond ; inline
39
40 : decode-utf8 ( stream -- char/f )
41     dup stream-read1 dup [ begin-utf8 ] when nip ; inline
42
43 M: utf8 decode-char
44     drop decode-utf8 ; inline
45
46 ! Encoding UTF-8
47
48 : encoded ( stream char -- )
49     BIN: 111111 bitand BIN: 10000000 bitor swap stream-write1 ; inline
50
51 : char>utf8 ( char stream -- )
52     swap {
53         { [ dup -7 shift zero? ] [ swap stream-write1 ] }
54         { [ dup -11 shift zero? ] [
55             2dup -6 shift BIN: 11000000 bitor swap stream-write1
56             encoded
57         ] }
58         { [ dup -16 shift zero? ] [
59             2dup -12 shift BIN: 11100000 bitor swap stream-write1
60             2dup -6 shift encoded
61             encoded
62         ] }
63         [
64             2dup -18 shift BIN: 11110000 bitor swap stream-write1
65             2dup -12 shift encoded
66             2dup -6 shift encoded
67             encoded
68         ]
69     } cond ; inline
70
71 M: utf8 encode-char
72     drop char>utf8 ;
73
74 M: utf8 encode-string
75     drop
76     over aux>>
77     [ [ char>utf8 ] curry each ]
78     [ [ >byte-array ] dip stream-write ] if ;
79
80 PRIVATE>
81
82 : code-point-length ( n -- x )
83     [ 1 ] [
84         log2 {
85             { [ dup 0 6 between? ] [ 1 ] }
86             { [ dup 7 10 between? ] [ 2 ] }
87             { [ dup 11 15 between? ] [ 3 ] }
88             { [ dup 16 20 between? ] [ 4 ] }
89         } cond nip
90     ] if-zero ;
91
92 : code-point-offsets ( string -- indices )
93     0 [ code-point-length + ] accumulate swap suffix ;
94
95 : utf8-index> ( n string -- n' )
96     code-point-offsets [ <= ] with find drop ;
97
98 : >utf8-index ( n string -- n' )
99     code-point-offsets nth ;