github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/mahonia/iso2022jp.go (about)

     1  package mahonia
     2  
     3  import (
     4  	"unicode/utf8"
     5  )
     6  
     7  // converters for ISO-2022-JP encoding
     8  
     9  const esc = 27
    10  
    11  func init() {
    12  	type jpEncoding int
    13  	const (
    14  		ascii jpEncoding = iota
    15  		jisX0201Roman
    16  		jisX0208
    17  	)
    18  
    19  	RegisterCharset(&Charset{
    20  		Name: "ISO-2022-JP",
    21  		NewDecoder: func() Decoder {
    22  			encoding := ascii
    23  			return func(p []byte) (c rune, size int, status Status) {
    24  				if len(p) == 0 {
    25  					return 0, 0, NO_ROOM
    26  				}
    27  
    28  				b := p[0]
    29  				if b == esc {
    30  					if len(p) < 3 {
    31  						return 0, 0, NO_ROOM
    32  					}
    33  					switch p[1] {
    34  					case '(':
    35  						switch p[2] {
    36  						case 'B':
    37  							encoding = ascii
    38  							return 0, 3, STATE_ONLY
    39  
    40  						case 'J':
    41  							encoding = jisX0201Roman
    42  							return 0, 3, STATE_ONLY
    43  						}
    44  
    45  					case '$':
    46  						switch p[2] {
    47  						case '@', 'B':
    48  							encoding = jisX0208
    49  							return 0, 3, STATE_ONLY
    50  						}
    51  					}
    52  				}
    53  
    54  				switch encoding {
    55  				case ascii:
    56  					if b > 127 {
    57  						return utf8.RuneError, 1, INVALID_CHAR
    58  					}
    59  					return rune(b), 1, SUCCESS
    60  
    61  				case jisX0201Roman:
    62  					if b > 127 {
    63  						return utf8.RuneError, 1, INVALID_CHAR
    64  					}
    65  					switch b {
    66  					case '\\':
    67  						return 0xA5, 1, SUCCESS
    68  					case '~':
    69  						return 0x203E, 1, SUCCESS
    70  					}
    71  					return rune(b), 1, SUCCESS
    72  
    73  				case jisX0208:
    74  					return jis0208Table.DecodeLow(p)
    75  				}
    76  				panic("unreachable")
    77  			}
    78  		},
    79  		NewEncoder: func() Encoder {
    80  			jis0208Table.Reverse()
    81  			encoding := ascii
    82  			return func(p []byte, c rune) (size int, status Status) {
    83  				if len(p) == 0 {
    84  					return 0, NO_ROOM
    85  				}
    86  
    87  				if c < 128 {
    88  					if encoding != ascii {
    89  						if len(p) < 4 {
    90  							return 0, NO_ROOM
    91  						}
    92  						p[0], p[1], p[2] = esc, '(', 'B'
    93  						p[3] = byte(c)
    94  						encoding = ascii
    95  						return 4, SUCCESS
    96  					}
    97  					p[0] = byte(c)
    98  					return 1, SUCCESS
    99  				}
   100  
   101  				if c > 65535 {
   102  					return 0, INVALID_CHAR
   103  				}
   104  				jis := jis0208Table.FromUnicode[c]
   105  				if jis == [2]byte{0, 0} && c != rune(jis0208Table.Data[0][0]) {
   106  					return 0, INVALID_CHAR
   107  				}
   108  
   109  				if encoding != jisX0208 {
   110  					if len(p) < 3 {
   111  						return 0, NO_ROOM
   112  					}
   113  					p[0], p[1], p[2] = esc, '$', 'B'
   114  					encoding = jisX0208
   115  					return 3, STATE_ONLY
   116  				}
   117  
   118  				p[0] = jis[0] + 0x21
   119  				p[1] = jis[1] + 0x21
   120  				return 2, SUCCESS
   121  			}
   122  		},
   123  	})
   124  }