iso2022jp.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package japanese
  5. import (
  6. "errors"
  7. "unicode/utf8"
  8. "golang.org/x/text/encoding"
  9. "golang.org/x/text/encoding/internal"
  10. "golang.org/x/text/encoding/internal/identifier"
  11. "golang.org/x/text/transform"
  12. )
  13. // ISO2022JP is the ISO-2022-JP encoding.
  14. var ISO2022JP encoding.Encoding = &iso2022JP
  15. var iso2022JP = internal.Encoding{
  16. internal.FuncEncoding{iso2022JPNewDecoder, iso2022JPNewEncoder},
  17. "ISO-2022-JP",
  18. identifier.ISO2022JP,
  19. }
  20. func iso2022JPNewDecoder() transform.Transformer {
  21. return new(iso2022JPDecoder)
  22. }
  23. func iso2022JPNewEncoder() transform.Transformer {
  24. return new(iso2022JPEncoder)
  25. }
  26. var errInvalidISO2022JP = errors.New("japanese: invalid ISO-2022-JP encoding")
  27. const (
  28. asciiState = iota
  29. katakanaState
  30. jis0208State
  31. jis0212State
  32. )
  33. const asciiEsc = 0x1b
  34. type iso2022JPDecoder int
  35. func (d *iso2022JPDecoder) Reset() {
  36. *d = asciiState
  37. }
  38. func (d *iso2022JPDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
  39. r, size := rune(0), 0
  40. loop:
  41. for ; nSrc < len(src); nSrc += size {
  42. c0 := src[nSrc]
  43. if c0 >= utf8.RuneSelf {
  44. err = errInvalidISO2022JP
  45. break loop
  46. }
  47. if c0 == asciiEsc {
  48. if nSrc+2 >= len(src) {
  49. err = transform.ErrShortSrc
  50. break loop
  51. }
  52. size = 3
  53. c1 := src[nSrc+1]
  54. c2 := src[nSrc+2]
  55. switch {
  56. case c1 == '$' && (c2 == '@' || c2 == 'B'):
  57. *d = jis0208State
  58. continue
  59. case c1 == '$' && c2 == '(':
  60. if nSrc+3 >= len(src) {
  61. err = transform.ErrShortSrc
  62. break loop
  63. }
  64. size = 4
  65. if src[nSrc]+3 == 'D' {
  66. *d = jis0212State
  67. continue
  68. }
  69. case c1 == '(' && (c2 == 'B' || c2 == 'J'):
  70. *d = asciiState
  71. continue
  72. case c1 == '(' && c2 == 'I':
  73. *d = katakanaState
  74. continue
  75. }
  76. err = errInvalidISO2022JP
  77. break loop
  78. }
  79. switch *d {
  80. case asciiState:
  81. r, size = rune(c0), 1
  82. case katakanaState:
  83. if c0 < 0x21 || 0x60 <= c0 {
  84. err = errInvalidISO2022JP
  85. break loop
  86. }
  87. r, size = rune(c0)+(0xff61-0x21), 1
  88. default:
  89. if c0 == 0x0a {
  90. *d = asciiState
  91. r, size = rune(c0), 1
  92. break
  93. }
  94. if nSrc+1 >= len(src) {
  95. err = transform.ErrShortSrc
  96. break loop
  97. }
  98. size = 2
  99. c1 := src[nSrc+1]
  100. i := int(c0-0x21)*94 + int(c1-0x21)
  101. if *d == jis0208State && i < len(jis0208Decode) {
  102. r = rune(jis0208Decode[i])
  103. } else if *d == jis0212State && i < len(jis0212Decode) {
  104. r = rune(jis0212Decode[i])
  105. } else {
  106. r = '\ufffd'
  107. break
  108. }
  109. if r == 0 {
  110. r = '\ufffd'
  111. }
  112. }
  113. if nDst+utf8.RuneLen(r) > len(dst) {
  114. err = transform.ErrShortDst
  115. break loop
  116. }
  117. nDst += utf8.EncodeRune(dst[nDst:], r)
  118. }
  119. if atEOF && err == transform.ErrShortSrc {
  120. err = errInvalidISO2022JP
  121. }
  122. return nDst, nSrc, err
  123. }
  124. type iso2022JPEncoder int
  125. func (e *iso2022JPEncoder) Reset() {
  126. *e = asciiState
  127. }
  128. func (e *iso2022JPEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
  129. r, size := rune(0), 0
  130. for ; nSrc < len(src); nSrc += size {
  131. r = rune(src[nSrc])
  132. // Decode a 1-byte rune.
  133. if r < utf8.RuneSelf {
  134. size = 1
  135. } else {
  136. // Decode a multi-byte rune.
  137. r, size = utf8.DecodeRune(src[nSrc:])
  138. if size == 1 {
  139. // All valid runes of size 1 (those below utf8.RuneSelf) were
  140. // handled above. We have invalid UTF-8 or we haven't seen the
  141. // full character yet.
  142. if !atEOF && !utf8.FullRune(src[nSrc:]) {
  143. err = transform.ErrShortSrc
  144. break
  145. }
  146. }
  147. // func init checks that the switch covers all tables.
  148. //
  149. // http://encoding.spec.whatwg.org/#iso-2022-jp says that "the index jis0212
  150. // is not used by the iso-2022-jp encoder due to lack of widespread support".
  151. //
  152. // TODO: do we have to special-case U+00A5 and U+203E, as per
  153. // http://encoding.spec.whatwg.org/#iso-2022-jp
  154. // Doing so would mean that "\u00a5" would not be preserved
  155. // after an encode-decode round trip.
  156. switch {
  157. case encode0Low <= r && r < encode0High:
  158. if r = rune(encode0[r-encode0Low]); r>>tableShift == jis0208 {
  159. goto writeJIS
  160. }
  161. case encode1Low <= r && r < encode1High:
  162. if r = rune(encode1[r-encode1Low]); r>>tableShift == jis0208 {
  163. goto writeJIS
  164. }
  165. case encode2Low <= r && r < encode2High:
  166. if r = rune(encode2[r-encode2Low]); r>>tableShift == jis0208 {
  167. goto writeJIS
  168. }
  169. case encode3Low <= r && r < encode3High:
  170. if r = rune(encode3[r-encode3Low]); r>>tableShift == jis0208 {
  171. goto writeJIS
  172. }
  173. case encode4Low <= r && r < encode4High:
  174. if r = rune(encode4[r-encode4Low]); r>>tableShift == jis0208 {
  175. goto writeJIS
  176. }
  177. case encode5Low <= r && r < encode5High:
  178. if 0xff61 <= r && r < 0xffa0 {
  179. goto writeKatakana
  180. }
  181. if r = rune(encode5[r-encode5Low]); r>>tableShift == jis0208 {
  182. goto writeJIS
  183. }
  184. }
  185. // Switch back to ASCII state in case of error so that an ASCII
  186. // replacement character can be written in the correct state.
  187. if *e != asciiState {
  188. if nDst+3 > len(dst) {
  189. err = transform.ErrShortDst
  190. break
  191. }
  192. *e = asciiState
  193. dst[nDst+0] = asciiEsc
  194. dst[nDst+1] = '('
  195. dst[nDst+2] = 'B'
  196. nDst += 3
  197. }
  198. err = internal.ErrASCIIReplacement
  199. break
  200. }
  201. if *e != asciiState {
  202. if nDst+4 > len(dst) {
  203. err = transform.ErrShortDst
  204. break
  205. }
  206. *e = asciiState
  207. dst[nDst+0] = asciiEsc
  208. dst[nDst+1] = '('
  209. dst[nDst+2] = 'B'
  210. nDst += 3
  211. } else if nDst >= len(dst) {
  212. err = transform.ErrShortDst
  213. break
  214. }
  215. dst[nDst] = uint8(r)
  216. nDst++
  217. continue
  218. writeJIS:
  219. if *e != jis0208State {
  220. if nDst+5 > len(dst) {
  221. err = transform.ErrShortDst
  222. break
  223. }
  224. *e = jis0208State
  225. dst[nDst+0] = asciiEsc
  226. dst[nDst+1] = '$'
  227. dst[nDst+2] = 'B'
  228. nDst += 3
  229. } else if nDst+2 > len(dst) {
  230. err = transform.ErrShortDst
  231. break
  232. }
  233. dst[nDst+0] = 0x21 + uint8(r>>codeShift)&codeMask
  234. dst[nDst+1] = 0x21 + uint8(r)&codeMask
  235. nDst += 2
  236. continue
  237. writeKatakana:
  238. if *e != katakanaState {
  239. if nDst+4 > len(dst) {
  240. err = transform.ErrShortDst
  241. break
  242. }
  243. *e = katakanaState
  244. dst[nDst+0] = asciiEsc
  245. dst[nDst+1] = '('
  246. dst[nDst+2] = 'I'
  247. nDst += 3
  248. } else if nDst >= len(dst) {
  249. err = transform.ErrShortDst
  250. break
  251. }
  252. dst[nDst] = uint8(r - (0xff61 - 0x21))
  253. nDst++
  254. continue
  255. }
  256. if atEOF && err == nil && *e != asciiState {
  257. if nDst+3 > len(dst) {
  258. err = transform.ErrShortDst
  259. } else {
  260. *e = asciiState
  261. dst[nDst+0] = asciiEsc
  262. dst[nDst+1] = '('
  263. dst[nDst+2] = 'B'
  264. nDst += 3
  265. }
  266. }
  267. return nDst, nSrc, err
  268. }