iso2022jp.go 6.6 KB

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