// Copyright 2014 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 cases

import 

// A context is used for iterating over source bytes, fetching case info and
// writing to a destination buffer.
//
// Casing operations may need more than one rune of context to decide how a rune
// should be cased. Casing implementations should call checkpoint on context
// whenever it is known to be safe to return the runes processed so far.
//
// It is recommended for implementations to not allow for more than 30 case
// ignorables as lookahead (analogous to the limit in norm) and to use state if
// unbounded lookahead is needed for cased runes.
type context struct {
	dst, src []byte
	atEOF    bool

	pDst int // pDst points past the last written rune in dst.
	pSrc int // pSrc points to the start of the currently scanned rune.

	// checkpoints safe to return in Transform, where nDst <= pDst and nSrc <= pSrc.
	nDst, nSrc int
	err        error

	sz   int  // size of current rune
	info info // case information of currently scanned rune

	// State preserved across calls to Transform.
	isMidWord bool // false if next cased letter needs to be title-cased.
}

func ( *context) () {
	.isMidWord = false
}

// ret returns the return values for the Transform method. It checks whether
// there were insufficient bytes in src to complete and introduces an error
// accordingly, if necessary.
func ( *context) () (,  int,  error) {
	if .err != nil || .nSrc == len(.src) {
		return .nDst, .nSrc, .err
	}
	// This point is only reached by mappers if there was no short destination
	// buffer. This means that the source buffer was exhausted and that c.sz was
	// set to 0 by next.
	if .atEOF && .pSrc == len(.src) {
		return .pDst, .pSrc, nil
	}
	return .nDst, .nSrc, transform.ErrShortSrc
}

// retSpan returns the return values for the Span method. It checks whether
// there were insufficient bytes in src to complete and introduces an error
// accordingly, if necessary.
func ( *context) () ( int,  error) {
	, ,  := .ret()
	return , 
}

// checkpoint sets the return value buffer points for Transform to the current
// positions.
func ( *context) () {
	if .err == nil {
		.nDst, .nSrc = .pDst, .pSrc+.sz
	}
}

// unreadRune causes the last rune read by next to be reread on the next
// invocation of next. Only one unreadRune may be called after a call to next.
func ( *context) () {
	.sz = 0
}

func ( *context) () bool {
	.pSrc += .sz
	if .pSrc == len(.src) || .err != nil {
		.info, .sz = 0, 0
		return false
	}
	,  := trie.lookup(.src[.pSrc:])
	.info, .sz = info(), 
	if .sz == 0 {
		if .atEOF {
			// A zero size means we have an incomplete rune. If we are atEOF,
			// this means it is an illegal rune, which we will consume one
			// byte at a time.
			.sz = 1
		} else {
			.err = transform.ErrShortSrc
			return false
		}
	}
	return true
}

// writeBytes adds bytes to dst.
func ( *context) ( []byte) bool {
	if len(.dst)-.pDst < len() {
		.err = transform.ErrShortDst
		return false
	}
	// This loop is faster than using copy.
	for ,  := range  {
		.dst[.pDst] = 
		.pDst++
	}
	return true
}

// writeString writes the given string to dst.
func ( *context) ( string) bool {
	if len(.dst)-.pDst < len() {
		.err = transform.ErrShortDst
		return false
	}
	// This loop is faster than using copy.
	for  := 0;  < len(); ++ {
		.dst[.pDst] = []
		.pDst++
	}
	return true
}

// copy writes the current rune to dst.
func ( *context) () bool {
	return .writeBytes(.src[.pSrc : .pSrc+.sz])
}

// copyXOR copies the current rune to dst and modifies it by applying the XOR
// pattern of the case info. It is the responsibility of the caller to ensure
// that this is a rune with a XOR pattern defined.
func ( *context) () bool {
	if !.copy() {
		return false
	}
	if .info&xorIndexBit == 0 {
		// Fast path for 6-bit XOR pattern, which covers most cases.
		.dst[.pDst-1] ^= byte(.info >> xorShift)
	} else {
		// Interpret XOR bits as an index.
		// TODO: test performance for unrolling this loop. Verify that we have
		// at least two bytes and at most three.
		 := .info >> xorShift
		for  := .pDst - 1; ; -- {
			.dst[] ^= xorData[]
			--
			if xorData[] == 0 {
				break
			}
		}
	}
	return true
}

// hasPrefix returns true if src[pSrc:] starts with the given string.
func ( *context) ( string) bool {
	 := .src[.pSrc:]
	if len() < len() {
		return false
	}
	for ,  := range [:len()] {
		if  != [] {
			return false
		}
	}
	return true
}

// caseType returns an info with only the case bits, normalized to either
// cLower, cUpper, cTitle or cUncased.
func ( *context) () info {
	 := .info & 0x7
	if  < 4 {
		return 
	}
	if  >= cXORCase {
		// xor the last bit of the rune with the case type bits.
		 := .src[.pSrc+.sz-1]
		return info(&1) ^ &0x3
	}
	if  == cIgnorableCased {
		return cLower
	}
	return cUncased
}

// lower writes the lowercase version of the current rune to dst.
func lower( *context) bool {
	 := .caseType()
	if .info&hasMappingMask == 0 ||  == cLower {
		return .copy()
	}
	if .info&exceptionBit == 0 {
		return .copyXOR()
	}
	 := exceptions[.info>>exceptionShift:]
	 := 2 + [0]&lengthMask // size of header + fold string
	if  := ([1] >> lengthBits) & lengthMask;  != noChange {
		return .writeString([ : +])
	}
	return .copy()
}

func isLower( *context) bool {
	 := .caseType()
	if .info&hasMappingMask == 0 ||  == cLower {
		return true
	}
	if .info&exceptionBit == 0 {
		.err = transform.ErrEndOfSpan
		return false
	}
	 := exceptions[.info>>exceptionShift:]
	if  := ([1] >> lengthBits) & lengthMask;  != noChange {
		.err = transform.ErrEndOfSpan
		return false
	}
	return true
}

// upper writes the uppercase version of the current rune to dst.
func upper( *context) bool {
	 := .caseType()
	if .info&hasMappingMask == 0 ||  == cUpper {
		return .copy()
	}
	if .info&exceptionBit == 0 {
		return .copyXOR()
	}
	 := exceptions[.info>>exceptionShift:]
	 := 2 + [0]&lengthMask // size of header + fold string
	// Get length of first special case mapping.
	 := ([1] >> lengthBits) & lengthMask
	if  == cTitle {
		// The first special case mapping is for lower. Set n to the second.
		if  == noChange {
			 = 0
		}
		,  = [1]&lengthMask, [:]
	}
	if  != noChange {
		return .writeString([ : +])
	}
	return .copy()
}

// isUpper writes the isUppercase version of the current rune to dst.
func isUpper( *context) bool {
	 := .caseType()
	if .info&hasMappingMask == 0 ||  == cUpper {
		return true
	}
	if .info&exceptionBit == 0 {
		.err = transform.ErrEndOfSpan
		return false
	}
	 := exceptions[.info>>exceptionShift:]
	// Get length of first special case mapping.
	 := ([1] >> lengthBits) & lengthMask
	if  == cTitle {
		 = [1] & lengthMask
	}
	if  != noChange {
		.err = transform.ErrEndOfSpan
		return false
	}
	return true
}

// title writes the title case version of the current rune to dst.
func title( *context) bool {
	 := .caseType()
	if .info&hasMappingMask == 0 ||  == cTitle {
		return .copy()
	}
	if .info&exceptionBit == 0 {
		if  == cLower {
			return .copyXOR()
		}
		return .copy()
	}
	// Get the exception data.
	 := exceptions[.info>>exceptionShift:]
	 := 2 + [0]&lengthMask // size of header + fold string

	 := ([1] >> lengthBits) & lengthMask
	if  := [1] & lengthMask;  != noChange {
		if  != noChange {
			 = [:]
		}
		return .writeString([ : +])
	}
	if  == cLower &&  != noChange {
		// Use the uppercase version instead.
		return .writeString([ : +])
	}
	// Already in correct case.
	return .copy()
}

// isTitle reports whether the current rune is in title case.
func isTitle( *context) bool {
	 := .caseType()
	if .info&hasMappingMask == 0 ||  == cTitle {
		return true
	}
	if .info&exceptionBit == 0 {
		if  == cLower {
			.err = transform.ErrEndOfSpan
			return false
		}
		return true
	}
	// Get the exception data.
	 := exceptions[.info>>exceptionShift:]
	if  := [1] & lengthMask;  != noChange {
		.err = transform.ErrEndOfSpan
		return false
	}
	 := ([1] >> lengthBits) & lengthMask
	if  == cLower &&  != noChange {
		.err = transform.ErrEndOfSpan
		return false
	}
	return true
}

// foldFull writes the foldFull version of the current rune to dst.
func foldFull( *context) bool {
	if .info&hasMappingMask == 0 {
		return .copy()
	}
	 := .caseType()
	if .info&exceptionBit == 0 {
		if  != cLower || .info&inverseFoldBit != 0 {
			return .copyXOR()
		}
		return .copy()
	}
	 := exceptions[.info>>exceptionShift:]
	 := [0] & lengthMask
	if  == 0 {
		if  == cLower {
			return .copy()
		}
		 = ([1] >> lengthBits) & lengthMask
	}
	return .writeString([2 : 2+])
}

// isFoldFull reports whether the current run is mapped to foldFull
func isFoldFull( *context) bool {
	if .info&hasMappingMask == 0 {
		return true
	}
	 := .caseType()
	if .info&exceptionBit == 0 {
		if  != cLower || .info&inverseFoldBit != 0 {
			.err = transform.ErrEndOfSpan
			return false
		}
		return true
	}
	 := exceptions[.info>>exceptionShift:]
	 := [0] & lengthMask
	if  == 0 &&  == cLower {
		return true
	}
	.err = transform.ErrEndOfSpan
	return false
}