Copyright 2015 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 runes

import (
	

	
)
Note: below we pass invalid UTF-8 to the tIn and tNotIn transformers as is. This is done for various reasons: - To retain the semantics of the Nop transformer: if input is passed to a Nop one would expect it to be unchanged. - It would be very expensive to pass a converted RuneError to a transformer: a transformer might need more source bytes after RuneError, meaning that the only way to pass it safely is to create a new buffer and manage the intermingling of RuneErrors and normal input. - Many transformers leave ill-formed UTF-8 as is, so this is not inconsistent. Generally ill-formed UTF-8 is only replaced if it is a logical consequence of the operation (as for Map) or if it otherwise would pose security concerns (as for Remove). - An alternative would be to return an error on ill-formed UTF-8, but this would be inconsistent with other operations.
If returns a transformer that applies tIn to consecutive runes for which s.Contains(r) and tNotIn to consecutive runes for which !s.Contains(r). Reset is called on tIn and tNotIn at the start of each run. A Nop transformer will substitute a nil value passed to tIn or tNotIn. Invalid UTF-8 is translated to RuneError to determine which transformer to apply, but is passed as is to the respective transformer.
func ( Set, ,  transform.Transformer) Transformer {
	if  == nil &&  == nil {
		return Transformer{transform.Nop}
	}
	if  == nil {
		 = transform.Nop
	}
	if  == nil {
		 = transform.Nop
	}
	,  := .(transform.SpanningTransformer)
	if ! {
		 = dummySpan{}
	}
	,  := .(transform.SpanningTransformer)
	if ! {
		 = dummySpan{}
	}

	 := &cond{
		tIn:    ,
		tNotIn: ,
		f:      .Contains,
	}
	.Reset()
	return Transformer{}
}

type dummySpan struct{ transform.Transformer }

func ( dummySpan) ( []byte,  bool) ( int,  error) {
	return 0, transform.ErrEndOfSpan
}

type cond struct {
	tIn, tNotIn transform.SpanningTransformer
	f           func(rune) bool
	check       func(rune) bool               // current check to perform
	t           transform.SpanningTransformer // current transformer to use
}
Reset implements transform.Transformer.
func ( *cond) () {
	.check = .is
	.t = .tIn
	.t.Reset() // notIn will be reset on first usage.
}

func ( *cond) ( rune) bool {
	if .f() {
		return true
	}
	.check = .isNot
	.t = .tNotIn
	.tNotIn.Reset()
	return false
}

func ( *cond) ( rune) bool {
	if !.f() {
		return true
	}
	.check = .is
	.t = .tIn
	.tIn.Reset()
	return false
}
This implementation of Span doesn't help all too much, but it needs to be there to satisfy this package's Transformer interface. TODO: there are certainly room for improvements, though. For example, if t.t == transform.Nop (which will a common occurrence) it will save a bundle to special-case that loop.
func ( *cond) ( []byte,  bool) ( int,  error) {
	 := 0
Don't process too much at a time as the Spanner that will be called on this block may terminate early.
		const  = 4096
		 := len()
		if  :=  + ;  <  {
			 = 
		}
		 := false
		 := 0
		 := .t
		for ;  < ;  +=  {
			 := rune([])
			if  < utf8.RuneSelf {
				 = 1
			} else if ,  = utf8.DecodeRune([:]);  == 1 {
				if ! && !utf8.FullRune([:]) {
					 = transform.ErrShortSrc
					break
				}
			}
The next rune will be the start of a new run.
				 = true
				break
			}
		}
		,  := .Span([:],  || ( &&  == len()))
		 += 
		if  != nil {
			return , 
At this point either err != nil or t.check will pass for the rune at p.
		 =  + 
	}
	return , 
}

func ( *cond) (,  []byte,  bool) (,  int,  error) {
	 := 0
Don't process too much at a time, as the work might be wasted if the destination buffer isn't large enough to hold the result or a transform returns an error early.
		const  = 4096
		 := len()
		if  :=  + ;  < len() {
			 = 
		}
		 := false
		 := 0
		 := .t
		for ;  < ;  +=  {
			 := rune([])
			if  < utf8.RuneSelf {
				 = 1
			} else if ,  = utf8.DecodeRune([:]);  == 1 {
				if ! && !utf8.FullRune([:]) {
					 = transform.ErrShortSrc
					break
				}
			}
The next rune will be the start of a new run.
				 = true
				break
			}
		}
		, ,  := .Transform([:], [:],  || ( &&  == len()))
		 += 
		 += 
		if  != nil {
			return , , 
At this point either err != nil or t.check will pass for the rune at p.
		 =  + 
	}
	return , ,