// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package japanese

import (
	

	
	
	
	
)

// ISO2022JP is the ISO-2022-JP encoding.
var ISO2022JP encoding.Encoding = &iso2022JP

var iso2022JP = internal.Encoding{
	internal.FuncEncoding{iso2022JPNewDecoder, iso2022JPNewEncoder},
	"ISO-2022-JP",
	identifier.ISO2022JP,
}

func iso2022JPNewDecoder() transform.Transformer {
	return new(iso2022JPDecoder)
}

func iso2022JPNewEncoder() transform.Transformer {
	return new(iso2022JPEncoder)
}

const (
	asciiState = iota
	katakanaState
	jis0208State
	jis0212State
)

const asciiEsc = 0x1b

type iso2022JPDecoder int

func ( *iso2022JPDecoder) () {
	* = asciiState
}

func ( *iso2022JPDecoder) (,  []byte,  bool) (,  int,  error) {
	,  := rune(0), 0
	for ;  < len();  +=  {
		 := []
		if  >= utf8.RuneSelf {
			,  = '\ufffd', 1
			goto 
		}

		if  == asciiEsc {
			if +2 >= len() {
				if ! {
					return , , transform.ErrShortSrc
				}
				// TODO: is it correct to only skip 1??
				,  = '\ufffd', 1
				goto 
			}
			 = 3
			 := [+1]
			 := [+2]
			switch {
			case  == '$' && ( == '@' ||  == 'B'): // 0x24 {0x40, 0x42}
				* = jis0208State
				continue
			case  == '$' &&  == '(': // 0x24 0x28
				if +3 >= len() {
					if ! {
						return , , transform.ErrShortSrc
					}
					,  = '\ufffd', 1
					goto 
				}
				 = 4
				if [+3] == 'D' {
					* = jis0212State
					continue
				}
			case  == '(' && ( == 'B' ||  == 'J'): // 0x28 {0x42, 0x4A}
				* = asciiState
				continue
			case  == '(' &&  == 'I': // 0x28 0x49
				* = katakanaState
				continue
			}
			,  = '\ufffd', 1
			goto 
		}

		switch * {
		case asciiState:
			,  = rune(), 1

		case katakanaState:
			if  < 0x21 || 0x60 <=  {
				,  = '\ufffd', 1
				goto 
			}
			,  = rune()+(0xff61-0x21), 1

		default:
			if  == 0x0a {
				* = asciiState
				,  = rune(), 1
				goto 
			}
			if +1 >= len() {
				if ! {
					return , , transform.ErrShortSrc
				}
				,  = '\ufffd', 1
				goto 
			}
			 = 2
			 := [+1]
			 := int(-0x21)*94 + int(-0x21)
			if * == jis0208State &&  < len(jis0208Decode) {
				 = rune(jis0208Decode[])
			} else if * == jis0212State &&  < len(jis0212Decode) {
				 = rune(jis0212Decode[])
			} else {
				 = '\ufffd'
				goto 
			}
			if  == 0 {
				 = '\ufffd'
			}
		}

	:
		if +utf8.RuneLen() > len() {
			return , , transform.ErrShortDst
		}
		 += utf8.EncodeRune([:], )
	}
	return , , 
}

type iso2022JPEncoder int

func ( *iso2022JPEncoder) () {
	* = asciiState
}

func ( *iso2022JPEncoder) (,  []byte,  bool) (,  int,  error) {
	,  := rune(0), 0
	for ;  < len();  +=  {
		 = rune([])

		// Decode a 1-byte rune.
		if  < utf8.RuneSelf {
			 = 1

		} else {
			// Decode a multi-byte rune.
			,  = utf8.DecodeRune([:])
			if  == 1 {
				// All valid runes of size 1 (those below utf8.RuneSelf) were
				// handled above. We have invalid UTF-8 or we haven't seen the
				// full character yet.
				if ! && !utf8.FullRune([:]) {
					 = transform.ErrShortSrc
					break
				}
			}

			// func init checks that the switch covers all tables.
			//
			// http://encoding.spec.whatwg.org/#iso-2022-jp says that "the index jis0212
			// is not used by the iso-2022-jp encoder due to lack of widespread support".
			//
			// TODO: do we have to special-case U+00A5 and U+203E, as per
			// http://encoding.spec.whatwg.org/#iso-2022-jp
			// Doing so would mean that "\u00a5" would not be preserved
			// after an encode-decode round trip.
			switch {
			case encode0Low <=  &&  < encode0High:
				if  = rune(encode0[-encode0Low]); >>tableShift == jis0208 {
					goto 
				}
			case encode1Low <=  &&  < encode1High:
				if  = rune(encode1[-encode1Low]); >>tableShift == jis0208 {
					goto 
				}
			case encode2Low <=  &&  < encode2High:
				if  = rune(encode2[-encode2Low]); >>tableShift == jis0208 {
					goto 
				}
			case encode3Low <=  &&  < encode3High:
				if  = rune(encode3[-encode3Low]); >>tableShift == jis0208 {
					goto 
				}
			case encode4Low <=  &&  < encode4High:
				if  = rune(encode4[-encode4Low]); >>tableShift == jis0208 {
					goto 
				}
			case encode5Low <=  &&  < encode5High:
				if 0xff61 <=  &&  < 0xffa0 {
					goto 
				}
				if  = rune(encode5[-encode5Low]); >>tableShift == jis0208 {
					goto 
				}
			}

			// Switch back to ASCII state in case of error so that an ASCII
			// replacement character can be written in the correct state.
			if * != asciiState {
				if +3 > len() {
					 = transform.ErrShortDst
					break
				}
				* = asciiState
				[+0] = asciiEsc
				[+1] = '('
				[+2] = 'B'
				 += 3
			}
			 = internal.ErrASCIIReplacement
			break
		}

		if * != asciiState {
			if +4 > len() {
				 = transform.ErrShortDst
				break
			}
			* = asciiState
			[+0] = asciiEsc
			[+1] = '('
			[+2] = 'B'
			 += 3
		} else if  >= len() {
			 = transform.ErrShortDst
			break
		}
		[] = uint8()
		++
		continue

	:
		if * != jis0208State {
			if +5 > len() {
				 = transform.ErrShortDst
				break
			}
			* = jis0208State
			[+0] = asciiEsc
			[+1] = '$'
			[+2] = 'B'
			 += 3
		} else if +2 > len() {
			 = transform.ErrShortDst
			break
		}
		[+0] = 0x21 + uint8(>>codeShift)&codeMask
		[+1] = 0x21 + uint8()&codeMask
		 += 2
		continue

	:
		if * != katakanaState {
			if +4 > len() {
				 = transform.ErrShortDst
				break
			}
			* = katakanaState
			[+0] = asciiEsc
			[+1] = '('
			[+2] = 'I'
			 += 3
		} else if  >= len() {
			 = transform.ErrShortDst
			break
		}
		[] = uint8( - (0xff61 - 0x21))
		++
		continue
	}
	if  &&  == nil && * != asciiState {
		if +3 > len() {
			 = transform.ErrShortDst
		} else {
			* = asciiState
			[+0] = asciiEsc
			[+1] = '('
			[+2] = 'B'
			 += 3
		}
	}
	return , , 
}