mirror of
https://gitee.com/johng/gf.git
synced 2024-11-29 18:57:44 +08:00
tidy gstr file
This commit is contained in:
parent
de17302ad0
commit
a9647a7bf3
@ -138,12 +138,3 @@ func ReplaceStringFuncMatch(pattern string, src string, replaceFunc func(match [
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split slices `src` into substrings separated by the expression and returns a slice of
|
|
||||||
// the substrings between those expression matches.
|
|
||||||
func Split(pattern string, src string) []string {
|
|
||||||
if r, err := getRegexp(pattern); err == nil {
|
|
||||||
return r.Split(src, -1)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -7,20 +7,6 @@
|
|||||||
// Package gstr provides functions for string handling.
|
// Package gstr provides functions for string handling.
|
||||||
package gstr
|
package gstr
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/internal/utils"
|
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
|
||||||
"github.com/gogf/gf/v2/util/grand"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// NotFoundIndex is the position index for string not found in searching functions.
|
// NotFoundIndex is the position index for string not found in searching functions.
|
||||||
NotFoundIndex = -1
|
NotFoundIndex = -1
|
||||||
@ -29,441 +15,3 @@ const (
|
|||||||
const (
|
const (
|
||||||
defaultSuffixForStrLimit = "..."
|
defaultSuffixForStrLimit = "..."
|
||||||
)
|
)
|
||||||
|
|
||||||
// Count counts the number of `substr` appears in `s`.
|
|
||||||
// It returns 0 if no `substr` found in `s`.
|
|
||||||
func Count(s, substr string) int {
|
|
||||||
return strings.Count(s, substr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountI counts the number of `substr` appears in `s`, case-insensitively.
|
|
||||||
// It returns 0 if no `substr` found in `s`.
|
|
||||||
func CountI(s, substr string) int {
|
|
||||||
return strings.Count(ToLower(s), ToLower(substr))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToLower returns a copy of the string s with all Unicode letters mapped to their lower case.
|
|
||||||
func ToLower(s string) string {
|
|
||||||
return strings.ToLower(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToUpper returns a copy of the string s with all Unicode letters mapped to their upper case.
|
|
||||||
func ToUpper(s string) string {
|
|
||||||
return strings.ToUpper(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UcFirst returns a copy of the string s with the first letter mapped to its upper case.
|
|
||||||
func UcFirst(s string) string {
|
|
||||||
return utils.UcFirst(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LcFirst returns a copy of the string s with the first letter mapped to its lower case.
|
|
||||||
func LcFirst(s string) string {
|
|
||||||
if len(s) == 0 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
if IsLetterUpper(s[0]) {
|
|
||||||
return string(s[0]+32) + s[1:]
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// UcWords uppercase the first character of each word in a string.
|
|
||||||
func UcWords(str string) string {
|
|
||||||
return strings.Title(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsLetterLower tests whether the given byte b is in lower case.
|
|
||||||
func IsLetterLower(b byte) bool {
|
|
||||||
return utils.IsLetterLower(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsLetterUpper tests whether the given byte b is in upper case.
|
|
||||||
func IsLetterUpper(b byte) bool {
|
|
||||||
return utils.IsLetterUpper(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNumeric tests whether the given string s is numeric.
|
|
||||||
func IsNumeric(s string) bool {
|
|
||||||
return utils.IsNumeric(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse returns a string which is the reverse of `str`.
|
|
||||||
func Reverse(str string) string {
|
|
||||||
runes := []rune(str)
|
|
||||||
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
|
|
||||||
runes[i], runes[j] = runes[j], runes[i]
|
|
||||||
}
|
|
||||||
return string(runes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumberFormat formats a number with grouped thousands.
|
|
||||||
// `decimals`: Sets the number of decimal points.
|
|
||||||
// `decPoint`: Sets the separator for the decimal point.
|
|
||||||
// `thousandsSep`: Sets the thousands' separator.
|
|
||||||
// See http://php.net/manual/en/function.number-format.php.
|
|
||||||
func NumberFormat(number float64, decimals int, decPoint, thousandsSep string) string {
|
|
||||||
neg := false
|
|
||||||
if number < 0 {
|
|
||||||
number = -number
|
|
||||||
neg = true
|
|
||||||
}
|
|
||||||
// Will round off
|
|
||||||
str := fmt.Sprintf("%."+strconv.Itoa(decimals)+"F", number)
|
|
||||||
prefix, suffix := "", ""
|
|
||||||
if decimals > 0 {
|
|
||||||
prefix = str[:len(str)-(decimals+1)]
|
|
||||||
suffix = str[len(str)-decimals:]
|
|
||||||
} else {
|
|
||||||
prefix = str
|
|
||||||
}
|
|
||||||
sep := []byte(thousandsSep)
|
|
||||||
n, l1, l2 := 0, len(prefix), len(sep)
|
|
||||||
// thousands sep num
|
|
||||||
c := (l1 - 1) / 3
|
|
||||||
tmp := make([]byte, l2*c+l1)
|
|
||||||
pos := len(tmp) - 1
|
|
||||||
for i := l1 - 1; i >= 0; i, n, pos = i-1, n+1, pos-1 {
|
|
||||||
if l2 > 0 && n > 0 && n%3 == 0 {
|
|
||||||
for j := range sep {
|
|
||||||
tmp[pos] = sep[l2-j-1]
|
|
||||||
pos--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmp[pos] = prefix[i]
|
|
||||||
}
|
|
||||||
s := string(tmp)
|
|
||||||
if decimals > 0 {
|
|
||||||
s += decPoint + suffix
|
|
||||||
}
|
|
||||||
if neg {
|
|
||||||
s = "-" + s
|
|
||||||
}
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChunkSplit splits a string into smaller chunks.
|
|
||||||
// Can be used to split a string into smaller chunks which is useful for
|
|
||||||
// e.g. converting BASE64 string output to match RFC 2045 semantics.
|
|
||||||
// It inserts end every chunkLen characters.
|
|
||||||
// It considers parameter `body` and `end` as unicode string.
|
|
||||||
func ChunkSplit(body string, chunkLen int, end string) string {
|
|
||||||
if end == "" {
|
|
||||||
end = "\r\n"
|
|
||||||
}
|
|
||||||
runes, endRunes := []rune(body), []rune(end)
|
|
||||||
l := len(runes)
|
|
||||||
if l <= 1 || l < chunkLen {
|
|
||||||
return body + end
|
|
||||||
}
|
|
||||||
ns := make([]rune, 0, len(runes)+len(endRunes))
|
|
||||||
for i := 0; i < l; i += chunkLen {
|
|
||||||
if i+chunkLen > l {
|
|
||||||
ns = append(ns, runes[i:]...)
|
|
||||||
} else {
|
|
||||||
ns = append(ns, runes[i:i+chunkLen]...)
|
|
||||||
}
|
|
||||||
ns = append(ns, endRunes...)
|
|
||||||
}
|
|
||||||
return string(ns)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare returns an integer comparing two strings lexicographically.
|
|
||||||
// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
|
|
||||||
func Compare(a, b string) int {
|
|
||||||
return strings.Compare(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equal reports whether `a` and `b`, interpreted as UTF-8 strings,
|
|
||||||
// are equal under Unicode case-folding, case-insensitively.
|
|
||||||
func Equal(a, b string) bool {
|
|
||||||
return strings.EqualFold(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fields returns the words used in a string as slice.
|
|
||||||
func Fields(str string) []string {
|
|
||||||
return strings.Fields(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasPrefix tests whether the string s begins with prefix.
|
|
||||||
func HasPrefix(s, prefix string) bool {
|
|
||||||
return strings.HasPrefix(s, prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasSuffix tests whether the string s ends with suffix.
|
|
||||||
func HasSuffix(s, suffix string) bool {
|
|
||||||
return strings.HasSuffix(s, suffix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountWords returns information about words' count used in a string.
|
|
||||||
// It considers parameter `str` as unicode string.
|
|
||||||
func CountWords(str string) map[string]int {
|
|
||||||
m := make(map[string]int)
|
|
||||||
buffer := bytes.NewBuffer(nil)
|
|
||||||
for _, r := range []rune(str) {
|
|
||||||
if unicode.IsSpace(r) {
|
|
||||||
if buffer.Len() > 0 {
|
|
||||||
m[buffer.String()]++
|
|
||||||
buffer.Reset()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buffer.WriteRune(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if buffer.Len() > 0 {
|
|
||||||
m[buffer.String()]++
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountChars returns information about chars' count used in a string.
|
|
||||||
// It considers parameter `str` as unicode string.
|
|
||||||
func CountChars(str string, noSpace ...bool) map[string]int {
|
|
||||||
m := make(map[string]int)
|
|
||||||
countSpace := true
|
|
||||||
if len(noSpace) > 0 && noSpace[0] {
|
|
||||||
countSpace = false
|
|
||||||
}
|
|
||||||
for _, r := range []rune(str) {
|
|
||||||
if !countSpace && unicode.IsSpace(r) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
m[string(r)]++
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// WordWrap wraps a string to a given number of characters.
|
|
||||||
// TODO: Enable cut parameter, see http://php.net/manual/en/function.wordwrap.php.
|
|
||||||
func WordWrap(str string, width int, br string) string {
|
|
||||||
if br == "" {
|
|
||||||
br = "\n"
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
current int
|
|
||||||
wordBuf, spaceBuf bytes.Buffer
|
|
||||||
init = make([]byte, 0, len(str))
|
|
||||||
buf = bytes.NewBuffer(init)
|
|
||||||
)
|
|
||||||
for _, char := range []rune(str) {
|
|
||||||
if char == '\n' {
|
|
||||||
if wordBuf.Len() == 0 {
|
|
||||||
if current+spaceBuf.Len() > width {
|
|
||||||
current = 0
|
|
||||||
} else {
|
|
||||||
current += spaceBuf.Len()
|
|
||||||
spaceBuf.WriteTo(buf)
|
|
||||||
}
|
|
||||||
spaceBuf.Reset()
|
|
||||||
} else {
|
|
||||||
current += spaceBuf.Len() + wordBuf.Len()
|
|
||||||
spaceBuf.WriteTo(buf)
|
|
||||||
spaceBuf.Reset()
|
|
||||||
wordBuf.WriteTo(buf)
|
|
||||||
wordBuf.Reset()
|
|
||||||
}
|
|
||||||
buf.WriteRune(char)
|
|
||||||
current = 0
|
|
||||||
} else if unicode.IsSpace(char) {
|
|
||||||
if spaceBuf.Len() == 0 || wordBuf.Len() > 0 {
|
|
||||||
current += spaceBuf.Len() + wordBuf.Len()
|
|
||||||
spaceBuf.WriteTo(buf)
|
|
||||||
spaceBuf.Reset()
|
|
||||||
wordBuf.WriteTo(buf)
|
|
||||||
wordBuf.Reset()
|
|
||||||
}
|
|
||||||
spaceBuf.WriteRune(char)
|
|
||||||
} else {
|
|
||||||
wordBuf.WriteRune(char)
|
|
||||||
if current+spaceBuf.Len()+wordBuf.Len() > width && wordBuf.Len() < width {
|
|
||||||
buf.WriteString(br)
|
|
||||||
current = 0
|
|
||||||
spaceBuf.Reset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if wordBuf.Len() == 0 {
|
|
||||||
if current+spaceBuf.Len() <= width {
|
|
||||||
spaceBuf.WriteTo(buf)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
spaceBuf.WriteTo(buf)
|
|
||||||
wordBuf.WriteTo(buf)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// LenRune returns string length of unicode.
|
|
||||||
func LenRune(str string) int {
|
|
||||||
return utf8.RuneCountInString(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repeat returns a new string consisting of multiplier copies of the string input.
|
|
||||||
func Repeat(input string, multiplier int) string {
|
|
||||||
return strings.Repeat(input, multiplier)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shuffle randomly shuffles a string.
|
|
||||||
// It considers parameter `str` as unicode string.
|
|
||||||
func Shuffle(str string) string {
|
|
||||||
runes := []rune(str)
|
|
||||||
s := make([]rune, len(runes))
|
|
||||||
for i, v := range grand.Perm(len(runes)) {
|
|
||||||
s[i] = runes[v]
|
|
||||||
}
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split splits string `str` by a string `delimiter`, to an array.
|
|
||||||
func Split(str, delimiter string) []string {
|
|
||||||
return strings.Split(str, delimiter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SplitAndTrim splits string `str` by a string `delimiter` to an array,
|
|
||||||
// and calls Trim to every element of this array. It ignores the elements
|
|
||||||
// which are empty after Trim.
|
|
||||||
func SplitAndTrim(str, delimiter string, characterMask ...string) []string {
|
|
||||||
return utils.SplitAndTrim(str, delimiter, characterMask...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join concatenates the elements of `array` to create a single string. The separator string
|
|
||||||
// `sep` is placed between elements in the resulting string.
|
|
||||||
func Join(array []string, sep string) string {
|
|
||||||
return strings.Join(array, sep)
|
|
||||||
}
|
|
||||||
|
|
||||||
// JoinAny concatenates the elements of `array` to create a single string. The separator string
|
|
||||||
// `sep` is placed between elements in the resulting string.
|
|
||||||
//
|
|
||||||
// The parameter `array` can be any type of slice, which be converted to string array.
|
|
||||||
func JoinAny(array interface{}, sep string) string {
|
|
||||||
return strings.Join(gconv.Strings(array), sep)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Explode splits string `str` by a string `delimiter`, to an array.
|
|
||||||
// See http://php.net/manual/en/function.explode.php.
|
|
||||||
func Explode(delimiter, str string) []string {
|
|
||||||
return Split(str, delimiter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implode joins array elements `pieces` with a string `glue`.
|
|
||||||
// http://php.net/manual/en/function.implode.php
|
|
||||||
func Implode(glue string, pieces []string) string {
|
|
||||||
return strings.Join(pieces, glue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chr return the ascii string of a number(0-255).
|
|
||||||
func Chr(ascii int) string {
|
|
||||||
return string([]byte{byte(ascii % 256)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ord converts the first byte of a string to a value between 0 and 255.
|
|
||||||
func Ord(char string) int {
|
|
||||||
return int(char[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
// HideStr replaces part of the string `str` to `hide` by `percentage` from the `middle`.
|
|
||||||
// It considers parameter `str` as unicode string.
|
|
||||||
func HideStr(str string, percent int, hide string) string {
|
|
||||||
array := strings.Split(str, "@")
|
|
||||||
if len(array) > 1 {
|
|
||||||
str = array[0]
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
rs = []rune(str)
|
|
||||||
length = len(rs)
|
|
||||||
mid = math.Floor(float64(length / 2))
|
|
||||||
hideLen = int(math.Floor(float64(length) * (float64(percent) / 100)))
|
|
||||||
start = int(mid - math.Floor(float64(hideLen)/2))
|
|
||||||
hideStr = []rune("")
|
|
||||||
hideRune = []rune(hide)
|
|
||||||
)
|
|
||||||
for i := 0; i < hideLen; i++ {
|
|
||||||
hideStr = append(hideStr, hideRune...)
|
|
||||||
}
|
|
||||||
buffer := bytes.NewBuffer(nil)
|
|
||||||
buffer.WriteString(string(rs[0:start]))
|
|
||||||
buffer.WriteString(string(hideStr))
|
|
||||||
buffer.WriteString(string(rs[start+hideLen:]))
|
|
||||||
if len(array) > 1 {
|
|
||||||
buffer.WriteString("@" + array[1])
|
|
||||||
}
|
|
||||||
return buffer.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nl2Br inserts HTML line breaks(`br`|<br />) before all newlines in a string:
|
|
||||||
// \n\r, \r\n, \r, \n.
|
|
||||||
// It considers parameter `str` as unicode string.
|
|
||||||
func Nl2Br(str string, isXhtml ...bool) string {
|
|
||||||
r, n, runes := '\r', '\n', []rune(str)
|
|
||||||
var br []byte
|
|
||||||
if len(isXhtml) > 0 && isXhtml[0] {
|
|
||||||
br = []byte("<br />")
|
|
||||||
} else {
|
|
||||||
br = []byte("<br>")
|
|
||||||
}
|
|
||||||
skip := false
|
|
||||||
length := len(runes)
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for i, v := range runes {
|
|
||||||
if skip {
|
|
||||||
skip = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch v {
|
|
||||||
case n, r:
|
|
||||||
if (i+1 < length) && (v == r && runes[i+1] == n) || (v == n && runes[i+1] == r) {
|
|
||||||
buf.Write(br)
|
|
||||||
skip = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
buf.Write(br)
|
|
||||||
default:
|
|
||||||
buf.WriteRune(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddSlashes quotes chars('"\) with slashes.
|
|
||||||
func AddSlashes(str string) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for _, char := range str {
|
|
||||||
switch char {
|
|
||||||
case '\'', '"', '\\':
|
|
||||||
buf.WriteRune('\\')
|
|
||||||
}
|
|
||||||
buf.WriteRune(char)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// StripSlashes un-quotes a quoted string by AddSlashes.
|
|
||||||
func StripSlashes(str string) string {
|
|
||||||
return utils.StripSlashes(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
// QuoteMeta returns a version of str with a backslash character (\)
|
|
||||||
// before every character that is among: .\+*?[^]($)
|
|
||||||
func QuoteMeta(str string, chars ...string) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for _, char := range str {
|
|
||||||
if len(chars) > 0 {
|
|
||||||
for _, c := range chars[0] {
|
|
||||||
if c == char {
|
|
||||||
buf.WriteRune('\\')
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch char {
|
|
||||||
case '.', '+', '\\', '(', '$', ')', '[', '^', ']', '*', '?':
|
|
||||||
buf.WriteRune('\\')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.WriteRune(char)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
21
text/gstr/gstr_compare.go
Normal file
21
text/gstr/gstr_compare.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
|
package gstr
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Compare returns an integer comparing two strings lexicographically.
|
||||||
|
// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
|
||||||
|
func Compare(a, b string) int {
|
||||||
|
return strings.Compare(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal reports whether `a` and `b`, interpreted as UTF-8 strings,
|
||||||
|
// are equal under Unicode case-folding, case-insensitively.
|
||||||
|
func Equal(a, b string) bool {
|
||||||
|
return strings.EqualFold(a, b)
|
||||||
|
}
|
@ -7,10 +7,26 @@
|
|||||||
package gstr
|
package gstr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"github.com/gogf/gf/v2/util/grand"
|
||||||
|
"math"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Chr return the ascii string of a number(0-255).
|
||||||
|
func Chr(ascii int) string {
|
||||||
|
return string([]byte{byte(ascii % 256)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ord converts the first byte of a string to a value between 0 and 255.
|
||||||
|
func Ord(char string) int {
|
||||||
|
return int(char[0])
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// octReg is the regular expression object for checks octal string.
|
// octReg is the regular expression object for checks octal string.
|
||||||
octReg = regexp.MustCompile(`\\[0-7]{3}`)
|
octReg = regexp.MustCompile(`\\[0-7]{3}`)
|
||||||
@ -28,3 +44,193 @@ func OctStr(str string) string {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reverse returns a string which is the reverse of `str`.
|
||||||
|
func Reverse(str string) string {
|
||||||
|
runes := []rune(str)
|
||||||
|
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
runes[i], runes[j] = runes[j], runes[i]
|
||||||
|
}
|
||||||
|
return string(runes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumberFormat formats a number with grouped thousands.
|
||||||
|
// `decimals`: Sets the number of decimal points.
|
||||||
|
// `decPoint`: Sets the separator for the decimal point.
|
||||||
|
// `thousandsSep`: Sets the thousands' separator.
|
||||||
|
// See http://php.net/manual/en/function.number-format.php.
|
||||||
|
func NumberFormat(number float64, decimals int, decPoint, thousandsSep string) string {
|
||||||
|
neg := false
|
||||||
|
if number < 0 {
|
||||||
|
number = -number
|
||||||
|
neg = true
|
||||||
|
}
|
||||||
|
// Will round off
|
||||||
|
str := fmt.Sprintf("%."+strconv.Itoa(decimals)+"F", number)
|
||||||
|
prefix, suffix := "", ""
|
||||||
|
if decimals > 0 {
|
||||||
|
prefix = str[:len(str)-(decimals+1)]
|
||||||
|
suffix = str[len(str)-decimals:]
|
||||||
|
} else {
|
||||||
|
prefix = str
|
||||||
|
}
|
||||||
|
sep := []byte(thousandsSep)
|
||||||
|
n, l1, l2 := 0, len(prefix), len(sep)
|
||||||
|
// thousands sep num
|
||||||
|
c := (l1 - 1) / 3
|
||||||
|
tmp := make([]byte, l2*c+l1)
|
||||||
|
pos := len(tmp) - 1
|
||||||
|
for i := l1 - 1; i >= 0; i, n, pos = i-1, n+1, pos-1 {
|
||||||
|
if l2 > 0 && n > 0 && n%3 == 0 {
|
||||||
|
for j := range sep {
|
||||||
|
tmp[pos] = sep[l2-j-1]
|
||||||
|
pos--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp[pos] = prefix[i]
|
||||||
|
}
|
||||||
|
s := string(tmp)
|
||||||
|
if decimals > 0 {
|
||||||
|
s += decPoint + suffix
|
||||||
|
}
|
||||||
|
if neg {
|
||||||
|
s = "-" + s
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shuffle randomly shuffles a string.
|
||||||
|
// It considers parameter `str` as unicode string.
|
||||||
|
func Shuffle(str string) string {
|
||||||
|
runes := []rune(str)
|
||||||
|
s := make([]rune, len(runes))
|
||||||
|
for i, v := range grand.Perm(len(runes)) {
|
||||||
|
s[i] = runes[v]
|
||||||
|
}
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HideStr replaces part of the string `str` to `hide` by `percentage` from the `middle`.
|
||||||
|
// It considers parameter `str` as unicode string.
|
||||||
|
func HideStr(str string, percent int, hide string) string {
|
||||||
|
array := strings.Split(str, "@")
|
||||||
|
if len(array) > 1 {
|
||||||
|
str = array[0]
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
rs = []rune(str)
|
||||||
|
length = len(rs)
|
||||||
|
mid = math.Floor(float64(length / 2))
|
||||||
|
hideLen = int(math.Floor(float64(length) * (float64(percent) / 100)))
|
||||||
|
start = int(mid - math.Floor(float64(hideLen)/2))
|
||||||
|
hideStr = []rune("")
|
||||||
|
hideRune = []rune(hide)
|
||||||
|
)
|
||||||
|
for i := 0; i < hideLen; i++ {
|
||||||
|
hideStr = append(hideStr, hideRune...)
|
||||||
|
}
|
||||||
|
buffer := bytes.NewBuffer(nil)
|
||||||
|
buffer.WriteString(string(rs[0:start]))
|
||||||
|
buffer.WriteString(string(hideStr))
|
||||||
|
buffer.WriteString(string(rs[start+hideLen:]))
|
||||||
|
if len(array) > 1 {
|
||||||
|
buffer.WriteString("@" + array[1])
|
||||||
|
}
|
||||||
|
return buffer.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nl2Br inserts HTML line breaks(`br`|<br />) before all newlines in a string:
|
||||||
|
// \n\r, \r\n, \r, \n.
|
||||||
|
// It considers parameter `str` as unicode string.
|
||||||
|
func Nl2Br(str string, isXhtml ...bool) string {
|
||||||
|
r, n, runes := '\r', '\n', []rune(str)
|
||||||
|
var br []byte
|
||||||
|
if len(isXhtml) > 0 && isXhtml[0] {
|
||||||
|
br = []byte("<br />")
|
||||||
|
} else {
|
||||||
|
br = []byte("<br>")
|
||||||
|
}
|
||||||
|
skip := false
|
||||||
|
length := len(runes)
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for i, v := range runes {
|
||||||
|
if skip {
|
||||||
|
skip = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch v {
|
||||||
|
case n, r:
|
||||||
|
if (i+1 < length) && (v == r && runes[i+1] == n) || (v == n && runes[i+1] == r) {
|
||||||
|
buf.Write(br)
|
||||||
|
skip = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
buf.Write(br)
|
||||||
|
default:
|
||||||
|
buf.WriteRune(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WordWrap wraps a string to a given number of characters.
|
||||||
|
// TODO: Enable cut parameter, see http://php.net/manual/en/function.wordwrap.php.
|
||||||
|
func WordWrap(str string, width int, br string) string {
|
||||||
|
if br == "" {
|
||||||
|
br = "\n"
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
current int
|
||||||
|
wordBuf, spaceBuf bytes.Buffer
|
||||||
|
init = make([]byte, 0, len(str))
|
||||||
|
buf = bytes.NewBuffer(init)
|
||||||
|
)
|
||||||
|
for _, char := range []rune(str) {
|
||||||
|
if char == '\n' {
|
||||||
|
if wordBuf.Len() == 0 {
|
||||||
|
if current+spaceBuf.Len() > width {
|
||||||
|
current = 0
|
||||||
|
} else {
|
||||||
|
current += spaceBuf.Len()
|
||||||
|
spaceBuf.WriteTo(buf)
|
||||||
|
}
|
||||||
|
spaceBuf.Reset()
|
||||||
|
} else {
|
||||||
|
current += spaceBuf.Len() + wordBuf.Len()
|
||||||
|
spaceBuf.WriteTo(buf)
|
||||||
|
spaceBuf.Reset()
|
||||||
|
wordBuf.WriteTo(buf)
|
||||||
|
wordBuf.Reset()
|
||||||
|
}
|
||||||
|
buf.WriteRune(char)
|
||||||
|
current = 0
|
||||||
|
} else if unicode.IsSpace(char) {
|
||||||
|
if spaceBuf.Len() == 0 || wordBuf.Len() > 0 {
|
||||||
|
current += spaceBuf.Len() + wordBuf.Len()
|
||||||
|
spaceBuf.WriteTo(buf)
|
||||||
|
spaceBuf.Reset()
|
||||||
|
wordBuf.WriteTo(buf)
|
||||||
|
wordBuf.Reset()
|
||||||
|
}
|
||||||
|
spaceBuf.WriteRune(char)
|
||||||
|
} else {
|
||||||
|
wordBuf.WriteRune(char)
|
||||||
|
if current+spaceBuf.Len()+wordBuf.Len() > width && wordBuf.Len() < width {
|
||||||
|
buf.WriteString(br)
|
||||||
|
current = 0
|
||||||
|
spaceBuf.Reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if wordBuf.Len() == 0 {
|
||||||
|
if current+spaceBuf.Len() <= width {
|
||||||
|
spaceBuf.WriteTo(buf)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spaceBuf.WriteTo(buf)
|
||||||
|
wordBuf.WriteTo(buf)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
63
text/gstr/gstr_count.go
Normal file
63
text/gstr/gstr_count.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
|
package gstr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Count counts the number of `substr` appears in `s`.
|
||||||
|
// It returns 0 if no `substr` found in `s`.
|
||||||
|
func Count(s, substr string) int {
|
||||||
|
return strings.Count(s, substr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountI counts the number of `substr` appears in `s`, case-insensitively.
|
||||||
|
// It returns 0 if no `substr` found in `s`.
|
||||||
|
func CountI(s, substr string) int {
|
||||||
|
return strings.Count(ToLower(s), ToLower(substr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountWords returns information about words' count used in a string.
|
||||||
|
// It considers parameter `str` as unicode string.
|
||||||
|
func CountWords(str string) map[string]int {
|
||||||
|
m := make(map[string]int)
|
||||||
|
buffer := bytes.NewBuffer(nil)
|
||||||
|
for _, r := range []rune(str) {
|
||||||
|
if unicode.IsSpace(r) {
|
||||||
|
if buffer.Len() > 0 {
|
||||||
|
m[buffer.String()]++
|
||||||
|
buffer.Reset()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer.WriteRune(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if buffer.Len() > 0 {
|
||||||
|
m[buffer.String()]++
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountChars returns information about chars' count used in a string.
|
||||||
|
// It considers parameter `str` as unicode string.
|
||||||
|
func CountChars(str string, noSpace ...bool) map[string]int {
|
||||||
|
m := make(map[string]int)
|
||||||
|
countSpace := true
|
||||||
|
if len(noSpace) > 0 && noSpace[0] {
|
||||||
|
countSpace = false
|
||||||
|
}
|
||||||
|
for _, r := range []rune(str) {
|
||||||
|
if !countSpace && unicode.IsSpace(r) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
m[string(r)]++
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
14
text/gstr/gstr_create.go
Normal file
14
text/gstr/gstr_create.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
|
package gstr
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Repeat returns a new string consisting of multiplier copies of the string input.
|
||||||
|
func Repeat(input string, multiplier int) string {
|
||||||
|
return strings.Repeat(input, multiplier)
|
||||||
|
}
|
14
text/gstr/gstr_is.go
Normal file
14
text/gstr/gstr_is.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
|
package gstr
|
||||||
|
|
||||||
|
import "github.com/gogf/gf/v2/internal/utils"
|
||||||
|
|
||||||
|
// IsNumeric tests whether the given string s is numeric.
|
||||||
|
func IsNumeric(s string) bool {
|
||||||
|
return utils.IsNumeric(s)
|
||||||
|
}
|
14
text/gstr/gstr_length.go
Normal file
14
text/gstr/gstr_length.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
|
package gstr
|
||||||
|
|
||||||
|
import "unicode/utf8"
|
||||||
|
|
||||||
|
// LenRune returns string length of unicode.
|
||||||
|
func LenRune(str string) int {
|
||||||
|
return utf8.RuneCountInString(str)
|
||||||
|
}
|
@ -1,61 +0,0 @@
|
|||||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the MIT License.
|
|
||||||
// If a copy of the MIT was not distributed with this file,
|
|
||||||
// You can obtain one at https://github.com/gogf/gf.
|
|
||||||
|
|
||||||
package gstr
|
|
||||||
|
|
||||||
// Levenshtein calculates Levenshtein distance between two strings.
|
|
||||||
// costIns: Defines the cost of insertion.
|
|
||||||
// costRep: Defines the cost of replacement.
|
|
||||||
// costDel: Defines the cost of deletion.
|
|
||||||
// See http://php.net/manual/en/function.levenshtein.php.
|
|
||||||
func Levenshtein(str1, str2 string, costIns, costRep, costDel int) int {
|
|
||||||
var maxLen = 255
|
|
||||||
l1 := len(str1)
|
|
||||||
l2 := len(str2)
|
|
||||||
if l1 == 0 {
|
|
||||||
return l2 * costIns
|
|
||||||
}
|
|
||||||
if l2 == 0 {
|
|
||||||
return l1 * costDel
|
|
||||||
}
|
|
||||||
if l1 > maxLen || l2 > maxLen {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp := make([]int, l2+1)
|
|
||||||
p1 := make([]int, l2+1)
|
|
||||||
p2 := make([]int, l2+1)
|
|
||||||
var c0, c1, c2 int
|
|
||||||
var i1, i2 int
|
|
||||||
for i2 := 0; i2 <= l2; i2++ {
|
|
||||||
p1[i2] = i2 * costIns
|
|
||||||
}
|
|
||||||
for i1 = 0; i1 < l1; i1++ {
|
|
||||||
p2[0] = p1[0] + costDel
|
|
||||||
for i2 = 0; i2 < l2; i2++ {
|
|
||||||
if str1[i1] == str2[i2] {
|
|
||||||
c0 = p1[i2]
|
|
||||||
} else {
|
|
||||||
c0 = p1[i2] + costRep
|
|
||||||
}
|
|
||||||
c1 = p1[i2+1] + costDel
|
|
||||||
if c1 < c0 {
|
|
||||||
c0 = c1
|
|
||||||
}
|
|
||||||
c2 = p2[i2] + costIns
|
|
||||||
if c2 < c0 {
|
|
||||||
c0 = c2
|
|
||||||
}
|
|
||||||
p2[i2+1] = c0
|
|
||||||
}
|
|
||||||
tmp = p1
|
|
||||||
p1 = p2
|
|
||||||
p2 = tmp
|
|
||||||
}
|
|
||||||
c0 = p1[l2]
|
|
||||||
|
|
||||||
return c0
|
|
||||||
}
|
|
158
text/gstr/gstr_similar.go
Normal file
158
text/gstr/gstr_similar.go
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
|
package gstr
|
||||||
|
|
||||||
|
// Levenshtein calculates Levenshtein distance between two strings.
|
||||||
|
// costIns: Defines the cost of insertion.
|
||||||
|
// costRep: Defines the cost of replacement.
|
||||||
|
// costDel: Defines the cost of deletion.
|
||||||
|
// See http://php.net/manual/en/function.levenshtein.php.
|
||||||
|
func Levenshtein(str1, str2 string, costIns, costRep, costDel int) int {
|
||||||
|
var maxLen = 255
|
||||||
|
l1 := len(str1)
|
||||||
|
l2 := len(str2)
|
||||||
|
if l1 == 0 {
|
||||||
|
return l2 * costIns
|
||||||
|
}
|
||||||
|
if l2 == 0 {
|
||||||
|
return l1 * costDel
|
||||||
|
}
|
||||||
|
if l1 > maxLen || l2 > maxLen {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := make([]int, l2+1)
|
||||||
|
p1 := make([]int, l2+1)
|
||||||
|
p2 := make([]int, l2+1)
|
||||||
|
var c0, c1, c2 int
|
||||||
|
var i1, i2 int
|
||||||
|
for i2 := 0; i2 <= l2; i2++ {
|
||||||
|
p1[i2] = i2 * costIns
|
||||||
|
}
|
||||||
|
for i1 = 0; i1 < l1; i1++ {
|
||||||
|
p2[0] = p1[0] + costDel
|
||||||
|
for i2 = 0; i2 < l2; i2++ {
|
||||||
|
if str1[i1] == str2[i2] {
|
||||||
|
c0 = p1[i2]
|
||||||
|
} else {
|
||||||
|
c0 = p1[i2] + costRep
|
||||||
|
}
|
||||||
|
c1 = p1[i2+1] + costDel
|
||||||
|
if c1 < c0 {
|
||||||
|
c0 = c1
|
||||||
|
}
|
||||||
|
c2 = p2[i2] + costIns
|
||||||
|
if c2 < c0 {
|
||||||
|
c0 = c2
|
||||||
|
}
|
||||||
|
p2[i2+1] = c0
|
||||||
|
}
|
||||||
|
tmp = p1
|
||||||
|
p1 = p2
|
||||||
|
p2 = tmp
|
||||||
|
}
|
||||||
|
c0 = p1[l2]
|
||||||
|
|
||||||
|
return c0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimilarText calculates the similarity between two strings.
|
||||||
|
// See http://php.net/manual/en/function.similar-text.php.
|
||||||
|
func SimilarText(first, second string, percent *float64) int {
|
||||||
|
var similarText func(string, string, int, int) int
|
||||||
|
similarText = func(str1, str2 string, len1, len2 int) int {
|
||||||
|
var sum, max int
|
||||||
|
pos1, pos2 := 0, 0
|
||||||
|
|
||||||
|
// Find the longest segment of the same section in two strings
|
||||||
|
for i := 0; i < len1; i++ {
|
||||||
|
for j := 0; j < len2; j++ {
|
||||||
|
for l := 0; (i+l < len1) && (j+l < len2) && (str1[i+l] == str2[j+l]); l++ {
|
||||||
|
if l+1 > max {
|
||||||
|
max = l + 1
|
||||||
|
pos1 = i
|
||||||
|
pos2 = j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sum = max; sum > 0 {
|
||||||
|
if pos1 > 0 && pos2 > 0 {
|
||||||
|
sum += similarText(str1, str2, pos1, pos2)
|
||||||
|
}
|
||||||
|
if (pos1+max < len1) && (pos2+max < len2) {
|
||||||
|
s1 := []byte(str1)
|
||||||
|
s2 := []byte(str2)
|
||||||
|
sum += similarText(string(s1[pos1+max:]), string(s2[pos2+max:]), len1-pos1-max, len2-pos2-max)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum
|
||||||
|
}
|
||||||
|
|
||||||
|
l1, l2 := len(first), len(second)
|
||||||
|
if l1+l2 == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
sim := similarText(first, second, l1, l2)
|
||||||
|
if percent != nil {
|
||||||
|
*percent = float64(sim*200) / float64(l1+l2)
|
||||||
|
}
|
||||||
|
return sim
|
||||||
|
}
|
||||||
|
|
||||||
|
// Soundex calculates the soundex key of a string.
|
||||||
|
// See http://php.net/manual/en/function.soundex.php.
|
||||||
|
func Soundex(str string) string {
|
||||||
|
if str == "" {
|
||||||
|
panic("str: cannot be an empty string")
|
||||||
|
}
|
||||||
|
table := [26]rune{
|
||||||
|
'0', '1', '2', '3', // A, B, C, D
|
||||||
|
'0', '1', '2', // E, F, G
|
||||||
|
'0', // H
|
||||||
|
'0', '2', '2', '4', '5', '5', // I, J, K, L, M, N
|
||||||
|
'0', '1', '2', '6', '2', '3', // O, P, Q, R, S, T
|
||||||
|
'0', '1', // U, V
|
||||||
|
'0', '2', // W, X
|
||||||
|
'0', '2', // Y, Z
|
||||||
|
}
|
||||||
|
last, code, small := -1, 0, 0
|
||||||
|
sd := make([]rune, 4)
|
||||||
|
// build soundex string
|
||||||
|
for i := 0; i < len(str) && small < 4; i++ {
|
||||||
|
// ToUpper
|
||||||
|
char := str[i]
|
||||||
|
if char < '\u007F' && 'a' <= char && char <= 'z' {
|
||||||
|
code = int(char - 'a' + 'A')
|
||||||
|
} else {
|
||||||
|
code = int(char)
|
||||||
|
}
|
||||||
|
if code >= 'A' && code <= 'Z' {
|
||||||
|
if small == 0 {
|
||||||
|
sd[small] = rune(code)
|
||||||
|
small++
|
||||||
|
last = int(table[code-'A'])
|
||||||
|
} else {
|
||||||
|
code = int(table[code-'A'])
|
||||||
|
if code != last {
|
||||||
|
if code != 0 {
|
||||||
|
sd[small] = rune(code)
|
||||||
|
small++
|
||||||
|
}
|
||||||
|
last = code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// pad with "0"
|
||||||
|
for ; small < 4; small++ {
|
||||||
|
sd[small] = '0'
|
||||||
|
}
|
||||||
|
return string(sd)
|
||||||
|
}
|
@ -1,53 +0,0 @@
|
|||||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the MIT License.
|
|
||||||
// If a copy of the MIT was not distributed with this file,
|
|
||||||
// You can obtain one at https://github.com/gogf/gf.
|
|
||||||
|
|
||||||
package gstr
|
|
||||||
|
|
||||||
// SimilarText calculates the similarity between two strings.
|
|
||||||
// See http://php.net/manual/en/function.similar-text.php.
|
|
||||||
func SimilarText(first, second string, percent *float64) int {
|
|
||||||
var similarText func(string, string, int, int) int
|
|
||||||
similarText = func(str1, str2 string, len1, len2 int) int {
|
|
||||||
var sum, max int
|
|
||||||
pos1, pos2 := 0, 0
|
|
||||||
|
|
||||||
// Find the longest segment of the same section in two strings
|
|
||||||
for i := 0; i < len1; i++ {
|
|
||||||
for j := 0; j < len2; j++ {
|
|
||||||
for l := 0; (i+l < len1) && (j+l < len2) && (str1[i+l] == str2[j+l]); l++ {
|
|
||||||
if l+1 > max {
|
|
||||||
max = l + 1
|
|
||||||
pos1 = i
|
|
||||||
pos2 = j
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if sum = max; sum > 0 {
|
|
||||||
if pos1 > 0 && pos2 > 0 {
|
|
||||||
sum += similarText(str1, str2, pos1, pos2)
|
|
||||||
}
|
|
||||||
if (pos1+max < len1) && (pos2+max < len2) {
|
|
||||||
s1 := []byte(str1)
|
|
||||||
s2 := []byte(str2)
|
|
||||||
sum += similarText(string(s1[pos1+max:]), string(s2[pos2+max:]), len1-pos1-max, len2-pos2-max)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sum
|
|
||||||
}
|
|
||||||
|
|
||||||
l1, l2 := len(first), len(second)
|
|
||||||
if l1+l2 == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
sim := similarText(first, second, l1, l2)
|
|
||||||
if percent != nil {
|
|
||||||
*percent = float64(sim*200) / float64(l1+l2)
|
|
||||||
}
|
|
||||||
return sim
|
|
||||||
}
|
|
53
text/gstr/gstr_slashes.go
Normal file
53
text/gstr/gstr_slashes.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
|
package gstr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"github.com/gogf/gf/v2/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddSlashes quotes chars('"\) with slashes.
|
||||||
|
func AddSlashes(str string) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for _, char := range str {
|
||||||
|
switch char {
|
||||||
|
case '\'', '"', '\\':
|
||||||
|
buf.WriteRune('\\')
|
||||||
|
}
|
||||||
|
buf.WriteRune(char)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// StripSlashes un-quotes a quoted string by AddSlashes.
|
||||||
|
func StripSlashes(str string) string {
|
||||||
|
return utils.StripSlashes(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuoteMeta returns a version of str with a backslash character (\)
|
||||||
|
// before every character that is among: .\+*?[^]($)
|
||||||
|
func QuoteMeta(str string, chars ...string) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for _, char := range str {
|
||||||
|
if len(chars) > 0 {
|
||||||
|
for _, c := range chars[0] {
|
||||||
|
if c == char {
|
||||||
|
buf.WriteRune('\\')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch char {
|
||||||
|
case '.', '+', '\\', '(', '$', ')', '[', '^', ']', '*', '?':
|
||||||
|
buf.WriteRune('\\')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.WriteRune(char)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
@ -1,58 +0,0 @@
|
|||||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the MIT License.
|
|
||||||
// If a copy of the MIT was not distributed with this file,
|
|
||||||
// You can obtain one at https://github.com/gogf/gf.
|
|
||||||
|
|
||||||
package gstr
|
|
||||||
|
|
||||||
// Soundex calculates the soundex key of a string.
|
|
||||||
// See http://php.net/manual/en/function.soundex.php.
|
|
||||||
func Soundex(str string) string {
|
|
||||||
if str == "" {
|
|
||||||
panic("str: cannot be an empty string")
|
|
||||||
}
|
|
||||||
table := [26]rune{
|
|
||||||
'0', '1', '2', '3', // A, B, C, D
|
|
||||||
'0', '1', '2', // E, F, G
|
|
||||||
'0', // H
|
|
||||||
'0', '2', '2', '4', '5', '5', // I, J, K, L, M, N
|
|
||||||
'0', '1', '2', '6', '2', '3', // O, P, Q, R, S, T
|
|
||||||
'0', '1', // U, V
|
|
||||||
'0', '2', // W, X
|
|
||||||
'0', '2', // Y, Z
|
|
||||||
}
|
|
||||||
last, code, small := -1, 0, 0
|
|
||||||
sd := make([]rune, 4)
|
|
||||||
// build soundex string
|
|
||||||
for i := 0; i < len(str) && small < 4; i++ {
|
|
||||||
// ToUpper
|
|
||||||
char := str[i]
|
|
||||||
if char < '\u007F' && 'a' <= char && char <= 'z' {
|
|
||||||
code = int(char - 'a' + 'A')
|
|
||||||
} else {
|
|
||||||
code = int(char)
|
|
||||||
}
|
|
||||||
if code >= 'A' && code <= 'Z' {
|
|
||||||
if small == 0 {
|
|
||||||
sd[small] = rune(code)
|
|
||||||
small++
|
|
||||||
last = int(table[code-'A'])
|
|
||||||
} else {
|
|
||||||
code = int(table[code-'A'])
|
|
||||||
if code != last {
|
|
||||||
if code != 0 {
|
|
||||||
sd[small] = rune(code)
|
|
||||||
small++
|
|
||||||
}
|
|
||||||
last = code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// pad with "0"
|
|
||||||
for ; small < 4; small++ {
|
|
||||||
sd[small] = '0'
|
|
||||||
}
|
|
||||||
return string(sd)
|
|
||||||
}
|
|
82
text/gstr/gstr_split_join.go
Normal file
82
text/gstr/gstr_split_join.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
|
package gstr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gogf/gf/v2/internal/utils"
|
||||||
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Split splits string `str` by a string `delimiter`, to an array.
|
||||||
|
func Split(str, delimiter string) []string {
|
||||||
|
return strings.Split(str, delimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SplitAndTrim splits string `str` by a string `delimiter` to an array,
|
||||||
|
// and calls Trim to every element of this array. It ignores the elements
|
||||||
|
// which are empty after Trim.
|
||||||
|
func SplitAndTrim(str, delimiter string, characterMask ...string) []string {
|
||||||
|
return utils.SplitAndTrim(str, delimiter, characterMask...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join concatenates the elements of `array` to create a single string. The separator string
|
||||||
|
// `sep` is placed between elements in the resulting string.
|
||||||
|
func Join(array []string, sep string) string {
|
||||||
|
return strings.Join(array, sep)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JoinAny concatenates the elements of `array` to create a single string. The separator string
|
||||||
|
// `sep` is placed between elements in the resulting string.
|
||||||
|
//
|
||||||
|
// The parameter `array` can be any type of slice, which be converted to string array.
|
||||||
|
func JoinAny(array interface{}, sep string) string {
|
||||||
|
return strings.Join(gconv.Strings(array), sep)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explode splits string `str` by a string `delimiter`, to an array.
|
||||||
|
// See http://php.net/manual/en/function.explode.php.
|
||||||
|
func Explode(delimiter, str string) []string {
|
||||||
|
return Split(str, delimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implode joins array elements `pieces` with a string `glue`.
|
||||||
|
// http://php.net/manual/en/function.implode.php
|
||||||
|
func Implode(glue string, pieces []string) string {
|
||||||
|
return strings.Join(pieces, glue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChunkSplit splits a string into smaller chunks.
|
||||||
|
// Can be used to split a string into smaller chunks which is useful for
|
||||||
|
// e.g. converting BASE64 string output to match RFC 2045 semantics.
|
||||||
|
// It inserts end every chunkLen characters.
|
||||||
|
// It considers parameter `body` and `end` as unicode string.
|
||||||
|
func ChunkSplit(body string, chunkLen int, end string) string {
|
||||||
|
if end == "" {
|
||||||
|
end = "\r\n"
|
||||||
|
}
|
||||||
|
runes, endRunes := []rune(body), []rune(end)
|
||||||
|
l := len(runes)
|
||||||
|
if l <= 1 || l < chunkLen {
|
||||||
|
return body + end
|
||||||
|
}
|
||||||
|
ns := make([]rune, 0, len(runes)+len(endRunes))
|
||||||
|
for i := 0; i < l; i += chunkLen {
|
||||||
|
if i+chunkLen > l {
|
||||||
|
ns = append(ns, runes[i:]...)
|
||||||
|
} else {
|
||||||
|
ns = append(ns, runes[i:i+chunkLen]...)
|
||||||
|
}
|
||||||
|
ns = append(ns, endRunes...)
|
||||||
|
}
|
||||||
|
return string(ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fields returns the words used in a string as slice.
|
||||||
|
func Fields(str string) []string {
|
||||||
|
return strings.Fields(str)
|
||||||
|
}
|
@ -1,52 +0,0 @@
|
|||||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the MIT License.
|
|
||||||
// If a copy of the MIT was not distributed with this file,
|
|
||||||
// You can obtain one at https://github.com/gogf/gf.
|
|
||||||
|
|
||||||
package gstr
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// Str returns part of `haystack` string starting from and including
|
|
||||||
// the first occurrence of `needle` to the end of `haystack`.
|
|
||||||
// See http://php.net/manual/en/function.strstr.php.
|
|
||||||
func Str(haystack string, needle string) string {
|
|
||||||
if needle == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
pos := strings.Index(haystack, needle)
|
|
||||||
if pos == NotFoundIndex {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return haystack[pos+len([]byte(needle))-1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// StrEx returns part of `haystack` string starting from and excluding
|
|
||||||
// the first occurrence of `needle` to the end of `haystack`.
|
|
||||||
func StrEx(haystack string, needle string) string {
|
|
||||||
if s := Str(haystack, needle); s != "" {
|
|
||||||
return s[1:]
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// StrTill returns part of `haystack` string ending to and including
|
|
||||||
// the first occurrence of `needle` from the start of `haystack`.
|
|
||||||
func StrTill(haystack string, needle string) string {
|
|
||||||
pos := strings.Index(haystack, needle)
|
|
||||||
if pos == NotFoundIndex || pos == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return haystack[:pos+1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// StrTillEx returns part of `haystack` string ending to and excluding
|
|
||||||
// the first occurrence of `needle` from the start of `haystack`.
|
|
||||||
func StrTillEx(haystack string, needle string) string {
|
|
||||||
pos := strings.Index(haystack, needle)
|
|
||||||
if pos == NotFoundIndex || pos == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return haystack[:pos]
|
|
||||||
}
|
|
@ -6,6 +6,51 @@
|
|||||||
|
|
||||||
package gstr
|
package gstr
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Str returns part of `haystack` string starting from and including
|
||||||
|
// the first occurrence of `needle` to the end of `haystack`.
|
||||||
|
// See http://php.net/manual/en/function.strstr.php.
|
||||||
|
func Str(haystack string, needle string) string {
|
||||||
|
if needle == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
pos := strings.Index(haystack, needle)
|
||||||
|
if pos == NotFoundIndex {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return haystack[pos+len([]byte(needle))-1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrEx returns part of `haystack` string starting from and excluding
|
||||||
|
// the first occurrence of `needle` to the end of `haystack`.
|
||||||
|
func StrEx(haystack string, needle string) string {
|
||||||
|
if s := Str(haystack, needle); s != "" {
|
||||||
|
return s[1:]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrTill returns part of `haystack` string ending to and including
|
||||||
|
// the first occurrence of `needle` from the start of `haystack`.
|
||||||
|
func StrTill(haystack string, needle string) string {
|
||||||
|
pos := strings.Index(haystack, needle)
|
||||||
|
if pos == NotFoundIndex || pos == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return haystack[:pos+1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrTillEx returns part of `haystack` string ending to and excluding
|
||||||
|
// the first occurrence of `needle` from the start of `haystack`.
|
||||||
|
func StrTillEx(haystack string, needle string) string {
|
||||||
|
pos := strings.Index(haystack, needle)
|
||||||
|
if pos == NotFoundIndex || pos == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return haystack[:pos]
|
||||||
|
}
|
||||||
|
|
||||||
// SubStr returns a portion of string `str` specified by the `start` and `length` parameters.
|
// SubStr returns a portion of string `str` specified by the `start` and `length` parameters.
|
||||||
// The parameter `length` is optional, it uses the length of `str` in default.
|
// The parameter `length` is optional, it uses the length of `str` in default.
|
||||||
func SubStr(str string, start int, length ...int) (substr string) {
|
func SubStr(str string, start int, length ...int) (substr string) {
|
@ -102,3 +102,13 @@ func TrimAll(str string, characterMask ...string) string {
|
|||||||
}
|
}
|
||||||
return string(slice)
|
return string(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasPrefix tests whether the string s begins with prefix.
|
||||||
|
func HasPrefix(s, prefix string) bool {
|
||||||
|
return strings.HasPrefix(s, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasSuffix tests whether the string s ends with suffix.
|
||||||
|
func HasSuffix(s, suffix string) bool {
|
||||||
|
return strings.HasSuffix(s, suffix)
|
||||||
|
}
|
||||||
|
53
text/gstr/gstr_upper_lower.go
Normal file
53
text/gstr/gstr_upper_lower.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
|
package gstr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gogf/gf/v2/internal/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToLower returns a copy of the string s with all Unicode letters mapped to their lower case.
|
||||||
|
func ToLower(s string) string {
|
||||||
|
return strings.ToLower(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUpper returns a copy of the string s with all Unicode letters mapped to their upper case.
|
||||||
|
func ToUpper(s string) string {
|
||||||
|
return strings.ToUpper(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UcFirst returns a copy of the string s with the first letter mapped to its upper case.
|
||||||
|
func UcFirst(s string) string {
|
||||||
|
return utils.UcFirst(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LcFirst returns a copy of the string s with the first letter mapped to its lower case.
|
||||||
|
func LcFirst(s string) string {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
if IsLetterUpper(s[0]) {
|
||||||
|
return string(s[0]+32) + s[1:]
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// UcWords uppercase the first character of each word in a string.
|
||||||
|
func UcWords(str string) string {
|
||||||
|
return strings.Title(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsLetterLower tests whether the given byte b is in lower case.
|
||||||
|
func IsLetterLower(b byte) bool {
|
||||||
|
return utils.IsLetterLower(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsLetterUpper tests whether the given byte b is in upper case.
|
||||||
|
func IsLetterUpper(b byte) bool {
|
||||||
|
return utils.IsLetterUpper(b)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user