summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/paulrosania/go-charset/charset/big5.go
blob: e01fa1afd023e0e2d8b494a7eb6836bc14372278 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package charset

import (
	"fmt"
	"unicode/utf8"
)

func init() {
	registerClass("big5", fromBig5, nil)
}

// Big5 consists of 89 fonts of 157 chars each
const (
	big5Max  = 13973
	big5Font = 157
	big5Data = "big5.dat"
)

type translateFromBig5 struct {
	font    int
	scratch []byte
	big5map []rune
}

func (p *translateFromBig5) Translate(data []byte, eof bool) (int, []byte, error) {
	p.scratch = p.scratch[:0]
	n := 0
	for len(data) > 0 {
		c := int(data[0])
		data = data[1:]
		n++
		if p.font == -1 {
			// idle state
			if c >= 0xa1 {
				p.font = c
				continue
			}
			if c == 26 {
				c = '\n'
			}
			continue
		}
		f := p.font
		p.font = -1
		r := utf8.RuneError
		switch {
		case c >= 64 && c <= 126:
			c -= 64
		case c >= 161 && c <= 254:
			c = c - 161 + 63
		default:
			// bad big5 char
			f = 255
		}
		if f <= 254 {
			f -= 161
			ix := f*big5Font + c
			if ix < len(p.big5map) {
				r = p.big5map[ix]
			}
			if r == -1 {
				r = utf8.RuneError
			}
		}
		p.scratch = appendRune(p.scratch, r)
	}
	return n, p.scratch, nil
}

type big5Key bool

func fromBig5(arg string) (Translator, error) {
	big5map, err := cache(big5Key(false), func() (interface{}, error) {
		data, err := readFile(big5Data)
		if err != nil {
			return nil, fmt.Errorf("charset: cannot open big5 data file: %v", err)
		}
		big5map := []rune(string(data))
		if len(big5map) != big5Max {
			return nil, fmt.Errorf("charset: corrupt big5 data")
		}
		return big5map, nil
	})
	if err != nil {
		return nil, err
	}
	return &translateFromBig5{big5map: big5map.([]rune), font: -1}, nil
}