mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 14:31:02 +00:00 
			
		
		
		
	* update github.com/alecthomas/chroma v0.8.0 -> v0.8.1 * github.com/blevesearch/bleve v1.0.10 -> v1.0.12 * editorconfig-core-go v2.1.1 -> v2.3.7 * github.com/gliderlabs/ssh v0.2.2 -> v0.3.1 * migrate editorconfig.ParseBytes to Parse * github.com/shurcooL/vfsgen to 0d455de96546 * github.com/go-git/go-git/v5 v5.1.0 -> v5.2.0 * github.com/google/uuid v1.1.1 -> v1.1.2 * github.com/huandu/xstrings v1.3.0 -> v1.3.2 * github.com/klauspost/compress v1.10.11 -> v1.11.1 * github.com/markbates/goth v1.61.2 -> v1.65.0 * github.com/mattn/go-sqlite3 v1.14.0 -> v1.14.4 * github.com/mholt/archiver v3.3.0 -> v3.3.2 * github.com/microcosm-cc/bluemonday 4f7140c49acb -> v1.0.4 * github.com/minio/minio-go v7.0.4 -> v7.0.5 * github.com/olivere/elastic v7.0.9 -> v7.0.20 * github.com/urfave/cli v1.20.0 -> v1.22.4 * github.com/prometheus/client_golang v1.1.0 -> v1.8.0 * github.com/xanzy/go-gitlab v0.37.0 -> v0.38.1 * mvdan.cc/xurls v2.1.0 -> v2.2.0 Co-authored-by: Lauris BH <lauris@nix.lv>
		
			
				
	
	
		
			216 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			216 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| // Copyright 2015 Huan Du. All rights reserved.
 | |
| // Licensed under the MIT license that can be found in the LICENSE file.
 | |
| 
 | |
| package xstrings
 | |
| 
 | |
| import (
 | |
| 	"strings"
 | |
| 	"unicode/utf8"
 | |
| )
 | |
| 
 | |
| // Reverse a utf8 encoded string.
 | |
| func Reverse(str string) string {
 | |
| 	var size int
 | |
| 
 | |
| 	tail := len(str)
 | |
| 	buf := make([]byte, tail)
 | |
| 	s := buf
 | |
| 
 | |
| 	for len(str) > 0 {
 | |
| 		_, size = utf8.DecodeRuneInString(str)
 | |
| 		tail -= size
 | |
| 		s = append(s[:tail], []byte(str[:size])...)
 | |
| 		str = str[size:]
 | |
| 	}
 | |
| 
 | |
| 	return string(buf)
 | |
| }
 | |
| 
 | |
| // Slice a string by rune.
 | |
| //
 | |
| // Start must satisfy 0 <= start <= rune length.
 | |
| //
 | |
| // End can be positive, zero or negative.
 | |
| // If end >= 0, start and end must satisfy start <= end <= rune length.
 | |
| // If end < 0, it means slice to the end of string.
 | |
| //
 | |
| // Otherwise, Slice will panic as out of range.
 | |
| func Slice(str string, start, end int) string {
 | |
| 	var size, startPos, endPos int
 | |
| 
 | |
| 	origin := str
 | |
| 
 | |
| 	if start < 0 || end > len(str) || (end >= 0 && start > end) {
 | |
| 		panic("out of range")
 | |
| 	}
 | |
| 
 | |
| 	if end >= 0 {
 | |
| 		end -= start
 | |
| 	}
 | |
| 
 | |
| 	for start > 0 && len(str) > 0 {
 | |
| 		_, size = utf8.DecodeRuneInString(str)
 | |
| 		start--
 | |
| 		startPos += size
 | |
| 		str = str[size:]
 | |
| 	}
 | |
| 
 | |
| 	if end < 0 {
 | |
| 		return origin[startPos:]
 | |
| 	}
 | |
| 
 | |
| 	endPos = startPos
 | |
| 
 | |
| 	for end > 0 && len(str) > 0 {
 | |
| 		_, size = utf8.DecodeRuneInString(str)
 | |
| 		end--
 | |
| 		endPos += size
 | |
| 		str = str[size:]
 | |
| 	}
 | |
| 
 | |
| 	if len(str) == 0 && (start > 0 || end > 0) {
 | |
| 		panic("out of range")
 | |
| 	}
 | |
| 
 | |
| 	return origin[startPos:endPos]
 | |
| }
 | |
| 
 | |
| // Partition splits a string by sep into three parts.
 | |
| // The return value is a slice of strings with head, match and tail.
 | |
| //
 | |
| // If str contains sep, for example "hello" and "l", Partition returns
 | |
| //     "he", "l", "lo"
 | |
| //
 | |
| // If str doesn't contain sep, for example "hello" and "x", Partition returns
 | |
| //     "hello", "", ""
 | |
| func Partition(str, sep string) (head, match, tail string) {
 | |
| 	index := strings.Index(str, sep)
 | |
| 
 | |
| 	if index == -1 {
 | |
| 		head = str
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	head = str[:index]
 | |
| 	match = str[index : index+len(sep)]
 | |
| 	tail = str[index+len(sep):]
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // LastPartition splits a string by last instance of sep into three parts.
 | |
| // The return value is a slice of strings with head, match and tail.
 | |
| //
 | |
| // If str contains sep, for example "hello" and "l", LastPartition returns
 | |
| //     "hel", "l", "o"
 | |
| //
 | |
| // If str doesn't contain sep, for example "hello" and "x", LastPartition returns
 | |
| //     "", "", "hello"
 | |
| func LastPartition(str, sep string) (head, match, tail string) {
 | |
| 	index := strings.LastIndex(str, sep)
 | |
| 
 | |
| 	if index == -1 {
 | |
| 		tail = str
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	head = str[:index]
 | |
| 	match = str[index : index+len(sep)]
 | |
| 	tail = str[index+len(sep):]
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // Insert src into dst at given rune index.
 | |
| // Index is counted by runes instead of bytes.
 | |
| //
 | |
| // If index is out of range of dst, panic with out of range.
 | |
| func Insert(dst, src string, index int) string {
 | |
| 	return Slice(dst, 0, index) + src + Slice(dst, index, -1)
 | |
| }
 | |
| 
 | |
| // Scrub scrubs invalid utf8 bytes with repl string.
 | |
| // Adjacent invalid bytes are replaced only once.
 | |
| func Scrub(str, repl string) string {
 | |
| 	var buf *stringBuilder
 | |
| 	var r rune
 | |
| 	var size, pos int
 | |
| 	var hasError bool
 | |
| 
 | |
| 	origin := str
 | |
| 
 | |
| 	for len(str) > 0 {
 | |
| 		r, size = utf8.DecodeRuneInString(str)
 | |
| 
 | |
| 		if r == utf8.RuneError {
 | |
| 			if !hasError {
 | |
| 				if buf == nil {
 | |
| 					buf = &stringBuilder{}
 | |
| 				}
 | |
| 
 | |
| 				buf.WriteString(origin[:pos])
 | |
| 				hasError = true
 | |
| 			}
 | |
| 		} else if hasError {
 | |
| 			hasError = false
 | |
| 			buf.WriteString(repl)
 | |
| 
 | |
| 			origin = origin[pos:]
 | |
| 			pos = 0
 | |
| 		}
 | |
| 
 | |
| 		pos += size
 | |
| 		str = str[size:]
 | |
| 	}
 | |
| 
 | |
| 	if buf != nil {
 | |
| 		buf.WriteString(origin)
 | |
| 		return buf.String()
 | |
| 	}
 | |
| 
 | |
| 	// No invalid byte.
 | |
| 	return origin
 | |
| }
 | |
| 
 | |
| // WordSplit splits a string into words. Returns a slice of words.
 | |
| // If there is no word in a string, return nil.
 | |
| //
 | |
| // Word is defined as a locale dependent string containing alphabetic characters,
 | |
| // which may also contain but not start with `'` and `-` characters.
 | |
| func WordSplit(str string) []string {
 | |
| 	var word string
 | |
| 	var words []string
 | |
| 	var r rune
 | |
| 	var size, pos int
 | |
| 
 | |
| 	inWord := false
 | |
| 
 | |
| 	for len(str) > 0 {
 | |
| 		r, size = utf8.DecodeRuneInString(str)
 | |
| 
 | |
| 		switch {
 | |
| 		case isAlphabet(r):
 | |
| 			if !inWord {
 | |
| 				inWord = true
 | |
| 				word = str
 | |
| 				pos = 0
 | |
| 			}
 | |
| 
 | |
| 		case inWord && (r == '\'' || r == '-'):
 | |
| 			// Still in word.
 | |
| 
 | |
| 		default:
 | |
| 			if inWord {
 | |
| 				inWord = false
 | |
| 				words = append(words, word[:pos])
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		pos += size
 | |
| 		str = str[size:]
 | |
| 	}
 | |
| 
 | |
| 	if inWord {
 | |
| 		words = append(words, word[:pos])
 | |
| 	}
 | |
| 
 | |
| 	return words
 | |
| }
 |