diff --git a/internal/render/helpers.go b/internal/render/helpers.go index 5fa0c438a6..cc7d31174f 100644 --- a/internal/render/helpers.go +++ b/internal/render/helpers.go @@ -1,7 +1,6 @@ package render import ( - "regexp" "sort" "strconv" "strings" @@ -17,30 +16,42 @@ import ( "k8s.io/apimachinery/pkg/util/duration" ) -var durationRx = regexp.MustCompile(`\A(\d*d)*?(\d*h)*?(\d*m)*?(\d*s)*?\z`) +func runesToNum(rr []rune) int { + var n int + m := 1 + for i := len(rr) - 1; i >= 0; i-- { + v := int(rr[i] - '0') + n += v * m + m *= 10 + } + + return n +} func durationToSeconds(duration string) string { - tokens := durationRx.FindAllStringSubmatch(duration, -1) - if len(tokens) == 0 { - return duration - } - if len(tokens[0]) < 5 { + if len(duration) == 0 { return duration } - d, h, m, s := tokens[0][1], tokens[0][2], tokens[0][3], tokens[0][4] - var n int - if v, err := strconv.Atoi(strings.Replace(d, "d", "", 1)); err == nil { - n += v * 24 * 60 * 60 - } - if v, err := strconv.Atoi(strings.Replace(h, "h", "", 1)); err == nil { - n += v * 60 * 60 - } - if v, err := strconv.Atoi(strings.Replace(m, "m", "", 1)); err == nil { - n += v * 60 - } - if v, err := strconv.Atoi(strings.Replace(s, "s", "", 1)); err == nil { - n += v + num := make([]rune, 0, 5) + var n, m int + for _, r := range duration { + switch r { + case 'y': + m = 365 * 24 * 60 * 60 + case 'd': + m = 24 * 60 * 60 + case 'h': + m = 60 * 60 + case 'm': + m = 60 + case 's': + m = 1 + default: + num = append(num, r) + continue + } + n, num = n+runesToNum(num)*m, num[:0] } return strconv.Itoa(n) @@ -201,7 +212,7 @@ func Truncate(str string, width int) string { return runewidth.Truncate(str, width, string(tview.SemigraphicsHorizontalEllipsis)) } -func mapToStr(m map[string]string) (s string) { +func mapToStr(m map[string]string) string { if len(m) == 0 { return "" } @@ -212,14 +223,15 @@ func mapToStr(m map[string]string) (s string) { } sort.Strings(kk) + bb := make([]byte, 0, 100) for i, k := range kk { - s += k + "=" + m[k] + bb = append(bb, k+"="+m[k]...) if i < len(kk)-1 { - s += " " + bb = append(bb, ' ') } } - return + return string(bb) } func mapToIfc(m interface{}) (s string) { diff --git a/internal/render/helpers_test.go b/internal/render/helpers_test.go index 6befcf87a3..a65a72f58c 100644 --- a/internal/render/helpers_test.go +++ b/internal/render/helpers_test.go @@ -52,7 +52,7 @@ func TestLabelize(t *testing.T) { } } -func TestDurationToNumber(t *testing.T) { +func TestDurationToSecond(t *testing.T) { uu := map[string]struct { s, e string }{ @@ -63,6 +63,8 @@ func TestDurationToNumber(t *testing.T) { "day_hour": {s: "3d9h", e: "291600"}, "day_hour_minute": {s: "2d22h3m", e: "252180"}, "day_hour_minute_seconds": {s: "2d22h3m50s", e: "252230"}, + "year": {s: "3y", e: "94608000"}, + "year_day": {s: "1y2d", e: "31708800"}, } for k := range uu { @@ -73,6 +75,16 @@ func TestDurationToNumber(t *testing.T) { } } +func BenchmarkDurationToSecond(b *testing.B) { + t := "2d22h3m50s" + + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + durationToSeconds(t) + } +} + func TestToAge(t *testing.T) { uu := map[string]struct { t time.Time @@ -353,14 +365,55 @@ func BenchmarkMapToStr(b *testing.B) { "blee": "duh", "aa": "bb", } - b.ResetTimer() - b.ReportAllocs() + b.ReportAllocs() + b.ResetTimer() for i := 0; i < b.N; i++ { mapToStr(ll) } } +func TestRunesToNum(t *testing.T) { + uu := map[string]struct { + rr []rune + e int + }{ + "0": { + rr: []rune(""), + e: 0, + }, + "100": { + rr: []rune("100"), + e: 100, + }, + "64": { + rr: []rune("64"), + e: 64, + }, + "52640": { + rr: []rune("52640"), + e: 52640, + }, + } + + for k := range uu { + u := uu[k] + t.Run(k, func(t *testing.T) { + assert.Equal(t, u.e, runesToNum(u.rr)) + }) + } +} + +func BenchmarkRunesToNum(b *testing.B) { + rr := []rune("5465") + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + runesToNum(rr) + } +} + func TestToMc(t *testing.T) { uu := []struct { v int64