]> gitweb.factorcode.org Git - factor.git/blob - core/io/encodings/utf8/utf8.factor
Merge remote-tracking branch 'malu/semantic-versioning'
[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 : minimum-code-point ( char minimum -- char )
23     over > [ drop replacement-char ] when ; inline
24
25 : maximum-code-point ( char maximum -- char )
26     over < [ drop replacement-char ] when ; inline
27
28 : double ( stream byte -- stream char )
29     BIN: 11111 bitand append-nums
30     HEX: 80 minimum-code-point ; inline
31
32 : triple ( stream byte -- stream char )
33     BIN: 1111 bitand append-nums append-nums
34     HEX: 800 minimum-code-point ; inline
35
36 : quadruple ( stream byte -- stream char )
37     BIN: 111 bitand append-nums append-nums append-nums
38     HEX: 10000 minimum-code-point
39     HEX: 10FFFF maximum-code-point ; inline
40
41 : begin-utf8 ( stream byte -- stream char )
42     {
43         { [ dup -7 shift zero? ] [ ] }
44         { [ dup -5 shift BIN: 110 = ] [ double ] }
45         { [ dup -4 shift BIN: 1110 = ] [ triple ] }
46         { [ dup -3 shift BIN: 11110 = ] [ quadruple ] }
47         [ drop replacement-char ]
48     } cond ; inline
49
50 : decode-utf8 ( stream -- char/f )
51     dup stream-read1 dup [ begin-utf8 ] when nip ; inline
52
53 M: utf8 decode-char
54     drop decode-utf8 ; inline
55
56 ! Encoding UTF-8
57
58 : encoded ( stream char -- )
59     BIN: 111111 bitand BIN: 10000000 bitor swap stream-write1 ; inline
60
61 : char>utf8 ( char stream -- )
62     swap {
63         { [ dup -7 shift zero? ] [ swap stream-write1 ] }
64         { [ dup -11 shift zero? ] [
65             2dup -6 shift BIN: 11000000 bitor swap stream-write1
66             encoded
67         ] }
68         { [ dup -16 shift zero? ] [
69             2dup -12 shift BIN: 11100000 bitor swap stream-write1
70             2dup -6 shift encoded
71             encoded
72         ] }
73         [
74             2dup -18 shift BIN: 11110000 bitor swap stream-write1
75             2dup -12 shift encoded
76             2dup -6 shift encoded
77             encoded
78         ]
79     } cond ; inline
80
81 M: utf8 encode-char
82     drop char>utf8 ;
83
84 M: utf8 encode-string
85     drop
86     over aux>>
87     [ [ char>utf8 ] curry each ]
88     [ [ >byte-array ] dip stream-write ] if ;
89
90 PRIVATE>
91
92 : code-point-length ( n -- x )
93     [ 1 ] [
94         log2 {
95             { [ dup 0 6 between? ] [ 1 ] }
96             { [ dup 7 10 between? ] [ 2 ] }
97             { [ dup 11 15 between? ] [ 3 ] }
98             { [ dup 16 20 between? ] [ 4 ] }
99         } cond nip
100     ] if-zero ;
101
102 : code-point-offsets ( string -- indices )
103     0 [ code-point-length + ] accumulate swap suffix ;
104
105 : utf8-index> ( n string -- n' )
106     code-point-offsets [ <= ] with find drop ;
107
108 : >utf8-index ( n string -- n' )
109     code-point-offsets nth ;