Files
opencloud/vendor/github.com/gookit/goutil/strutil/padding.go
PC Kitty d97217f22c Update github.com/gookit/goutil to v0.7.4 for FreeBSD compatibility
The goutil that OpenCloud currently uses is one version from the release that adds FreeBSD support, this now compiles successfully on FreeBSD.
2026-04-28 18:03:17 +02:00

222 lines
5.6 KiB
Go

package strutil
import (
"strings"
"github.com/gookit/goutil/comdef"
)
// PosFlag type
type PosFlag = comdef.Position
// Position for padding/resize string
const (
PosLeft PosFlag = iota
PosMiddle
PosRight
PosAuto
)
/*************************************************************
* String padding operation
*************************************************************/
// Padding Fill the string to the specified length.
//
// params:
// - s: 原始字符串
// - pad: 用于填充的字符或字符串
// - length: 目标长度
// - padPos: 填充位置标志(左填充或右填充)
func Padding(s, pad string, length int, padPos PosFlag) string {
return padding(s, pad, len(s), length, padPos)
}
// Utf8Padding Fill the string to the specified length. use utf8 width.
func Utf8Padding(s, pad string, wantLen int, padPos PosFlag) string {
return padding(s, pad, Utf8Width(s), wantLen, padPos)
}
func padding(s, pad string, sLen, wantLen int, padPos PosFlag) string {
diff := sLen - wantLen
if diff >= 0 { // do not need padding.
return s
}
// pad space.
if len(s) == sLen && (pad == "" || pad == " ") {
// Sprintf: 是按字数来填充的,不管中英文都是一个字符 - 有问题
if padPos == PosRight { // to right
return s + strings.Repeat(" ", -diff)
}
return strings.Repeat(" ", -diff) + s
}
// other character.
if padPos == PosRight { // to right
return s + Repeat(pad, -diff)
}
return Repeat(pad, -diff) + s
}
// PadLeft a string.
func PadLeft(s, pad string, length int) string {
return Padding(s, pad, length, PosLeft)
}
// PadRight a string.
func PadRight(s, pad string, length int) string {
return Padding(s, pad, length, PosRight)
}
// PadChars padding a rune/byte to want length and with position flag
func PadChars[T byte | rune](cs []T, pad T, length int, pos PosFlag) []T {
ln := len(cs)
if ln >= length {
ns := make([]T, length)
copy(ns, cs[:length])
return ns
}
idx := length - ln
ns := make([]T, length)
if pos == PosRight {
copy(ns, cs)
for i := ln; i < length; i++ {
ns[i] = pad
}
return ns
}
// to left
for i := 0; i < idx; i++ {
ns[i] = pad
}
copy(ns[idx:], cs)
return ns
}
// PadBytes padding a byte to want length and with position flag
func PadBytes(bs []byte, pad byte, length int, pos PosFlag) []byte {
return PadChars(bs, pad, length, pos)
}
// PadBytesLeft a byte to want length
func PadBytesLeft(bs []byte, pad byte, length int) []byte {
return PadChars(bs, pad, length, PosLeft)
}
// PadBytesRight a byte to want length
func PadBytesRight(bs []byte, pad byte, length int) []byte {
return PadChars(bs, pad, length, PosRight)
}
// PadRunes padding a rune to want length and with position flag
func PadRunes(rs []rune, pad rune, length int, pos PosFlag) []rune {
return PadChars(rs, pad, length, pos)
}
// PadRunesLeft a rune to want length
func PadRunesLeft(rs []rune, pad rune, length int) []rune {
return PadChars(rs, pad, length, PosLeft)
}
// PadRunesRight a rune to want length
func PadRunesRight(rs []rune, pad rune, length int) []rune {
return PadChars(rs, pad, length, PosRight)
}
// Align a string by given length and align settings. alias of Resize
func Align(s string, length int, align comdef.Align) string {
return resize(s, len(s), length, align, false)
}
// Utf8Align a string by given length and align settings. alias of Utf8Resize
func Utf8Align(s string, length int, align comdef.Align) string {
return resize(s, Utf8Width(s), length, align, false)
}
// Resize a string by given length and align settings. use padding space.
// If len(s) > wantLen, will truncate it.
func Resize(s string, length int, align comdef.Align) string {
return resize(s, len(s), length, align, true)
}
// Utf8Resize a string by given length and align settings. use padding space.
// If width(s) > wantLen, will truncate it.
func Utf8Resize(s string, length int, align comdef.Align) string {
return resize(s, Utf8Width(s), length, align, true)
}
// resize a string by given length and align settings. use padding space.
func resize(s string, sLen, wantLen int, align comdef.Align, cutOverflow bool) string {
diff := sLen - wantLen
if diff >= 0 { // do not need padding.
// cutOverflow: truncate on sLen > wantLen
if cutOverflow && sLen > wantLen {
if len(s) == sLen {
return s[:wantLen]
}
return utf8Truncate(s, sLen, wantLen, "")
}
return s
}
if align == comdef.Center {
padLn := (wantLen - sLen) / 2
if diff = wantLen - padLn*2; diff > 0 {
s += " "
}
padStr := string(RepeatBytes(' ', padLn))
return padStr + s + padStr
}
padStr := string(RepeatBytes(' ', wantLen-sLen))
// tip: 左对齐 - 使用空白填充右边
if align == comdef.Left || align == comdef.PosAuto {
return s + padStr
}
return padStr + s
}
/*************************************************************
* String repeat operation
*************************************************************/
// Repeat a string by given times.
func Repeat(s string, times int) string {
if times < 1 {
return ""
}
if times == 1 {
return s
}
var sb strings.Builder
sb.Grow(len(s) * times)
for i := 0; i < times; i++ {
sb.WriteString(s)
}
return sb.String()
}
// RepeatRune repeat a rune char.
func RepeatRune(char rune, times int) []rune { return RepeatChars(char, times) }
// RepeatBytes repeat a byte char.
func RepeatBytes(char byte, times int) []byte { return RepeatChars(char, times) }
// RepeatChars repeat a byte char.
func RepeatChars[T byte | rune](char T, times int) []T {
if times <= 0 {
return make([]T, 0)
}
chars := make([]T, times)
for i := 0; i < times; i++ {
chars[i] = char
}
return chars
}