github.com/primecitizens/pcz/std@v0.2.1/text/unicode/utf8/runtime.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright 2023 The Prime Citizens
     3  //
     4  // Copyright 2009 The Go Authors. All rights reserved.
     5  // Use of this source code is governed by a BSD-style
     6  // license that can be found in the LICENSE file.
     7  
     8  package utf8
     9  
    10  import (
    11  	. "github.com/primecitizens/pcz/std/text/unicode/common"
    12  )
    13  
    14  // functions used by the runtime
    15  
    16  // IterRune returns the rune at the start of p[pos:] and the index
    17  // after the rune in p.
    18  //
    19  // If the string appears to be incomplete or decoding problems are
    20  // encountered (RuneError, pos+1) is returned to ensure
    21  // progress when IterRune is used to iterate over a string.
    22  func IterRune(p string, pos int) (r rune, next int) {
    23  	n := len(p) - pos
    24  	if n < 1 {
    25  		return RuneError, pos + 1
    26  	}
    27  
    28  	p = p[pos:]
    29  
    30  	p0 := p[0]
    31  	x := first[p0]
    32  	if x >= as {
    33  		// The following code simulates an additional check for x == xx and
    34  		// handling the ASCII and invalid cases accordingly. This mask-and-or
    35  		// approach prevents an additional branch.
    36  		mask := rune(x) << 31 >> 31 // Create 0x0000 or 0xFFFF.
    37  		return rune(p0)&^mask | RuneError&mask, pos + 1
    38  	}
    39  
    40  	sz := int(x & 7)
    41  	if n < sz {
    42  		return RuneError, pos + 1
    43  	}
    44  
    45  	b1 := p[1]
    46  	accept := acceptRanges[x>>4]
    47  	if b1 < accept.lo || accept.hi < b1 {
    48  		return RuneError, pos + 1
    49  	}
    50  
    51  	if sz <= 2 { // <= instead of == to help the compiler eliminate some bounds checks
    52  		return rune(p0&mask2)<<6 | rune(b1&maskx), pos + 2
    53  	}
    54  
    55  	b2 := p[2]
    56  	if b2 < locb || hicb < b2 {
    57  		return RuneError, pos + 1
    58  	}
    59  
    60  	if sz <= 3 {
    61  		return rune(p0&mask3)<<12 | rune(b1&maskx)<<6 | rune(b2&maskx), pos + 3
    62  	}
    63  
    64  	b3 := p[3]
    65  	if b3 < locb || hicb < b3 {
    66  		return RuneError, pos + 1
    67  	}
    68  
    69  	return rune(p0&mask4)<<18 | rune(b1&maskx)<<12 | rune(b2&maskx)<<6 | rune(b3&maskx), pos + 4
    70  }