// 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 runesimport ()// 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 {returnTransformer{transform.Nop} }if == nil { = transform.Nop }if == nil { = transform.Nop } , := .(transform.SpanningTransformer)if ! { = dummySpan{} } , := .(transform.SpanningTransformer)if ! { = dummySpan{} } := &cond{tIn: ,tNotIn: ,f: .Contains, } .Reset()returnTransformer{}}type dummySpan struct{ transform.Transformer }func ( dummySpan) ( []byte, bool) ( int, error) {return0, 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() {returntrue } .check = .isNot .t = .tNotIn .tNotIn.Reset()returnfalse}func ( *cond) ( rune) bool {if !.f() {returntrue } .check = .is .t = .tIn .tIn.Reset()returnfalse}// 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) { := 0for < len() && == nil {// 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 := .tfor ; < ; += { := rune([])if < utf8.RuneSelf { = 1 } elseif , = utf8.DecodeRune([:]); == 1 {if ! && !utf8.FullRune([:]) { = transform.ErrShortSrcbreak } }if !.check() {// The next rune will be the start of a new run. = truebreak } } , := .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) { := 0for < len() && == nil {// 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 := .tfor ; < ; += { := rune([])if < utf8.RuneSelf { = 1 } elseif , = utf8.DecodeRune([:]); == 1 {if ! && !utf8.FullRune([:]) { = transform.ErrShortSrcbreak } }if !.check() {// The next rune will be the start of a new run. = truebreak } } , , := .Transform([:], [:], || ( && == len())) += += if != nil {return , , }// At this point either err != nil or t.check will pass for the rune at p. = + }return , , }
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.