1package pb
2
3import (
4	"bytes"
5	"fmt"
6	"github.com/mattn/go-runewidth"
7	"math"
8	"regexp"
9	//"unicode/utf8"
10)
11
12const (
13	_KiB = 1024
14	_MiB = 1048576
15	_GiB = 1073741824
16	_TiB = 1099511627776
17
18	_kB = 1e3
19	_MB = 1e6
20	_GB = 1e9
21	_TB = 1e12
22)
23
24var ctrlFinder = regexp.MustCompile("\x1b\x5b[0-9;]+\x6d")
25
26func CellCount(s string) int {
27	n := runewidth.StringWidth(s)
28	for _, sm := range ctrlFinder.FindAllString(s, -1) {
29		n -= runewidth.StringWidth(sm)
30	}
31	return n
32}
33
34func StripString(s string, w int) string {
35	l := CellCount(s)
36	if l <= w {
37		return s
38	}
39	var buf = bytes.NewBuffer(make([]byte, 0, len(s)))
40	StripStringToBuffer(s, w, buf)
41	return buf.String()
42}
43
44func StripStringToBuffer(s string, w int, buf *bytes.Buffer) {
45	var seqs = ctrlFinder.FindAllStringIndex(s, -1)
46	var maxWidthReached bool
47mainloop:
48	for i, r := range s {
49		for _, seq := range seqs {
50			if i >= seq[0] && i < seq[1] {
51				buf.WriteRune(r)
52				continue mainloop
53			}
54		}
55		if rw := CellCount(string(r)); rw <= w && !maxWidthReached {
56			w -= rw
57			buf.WriteRune(r)
58		} else {
59			maxWidthReached = true
60		}
61	}
62	for w > 0 {
63		buf.WriteByte(' ')
64		w--
65	}
66	return
67}
68
69func round(val float64) (newVal float64) {
70	roundOn := 0.5
71	places := 0
72	var round float64
73	pow := math.Pow(10, float64(places))
74	digit := pow * val
75	_, div := math.Modf(digit)
76	if div >= roundOn {
77		round = math.Ceil(digit)
78	} else {
79		round = math.Floor(digit)
80	}
81	newVal = round / pow
82	return
83}
84
85// Convert bytes to human readable string. Like a 2 MiB, 64.2 KiB, or 2 MB, 64.2 kB
86// if useSIPrefix is set to true
87func formatBytes(i int64, useSIPrefix bool) (result string) {
88	if !useSIPrefix {
89		switch {
90		case i >= _TiB:
91			result = fmt.Sprintf("%.02f TiB", float64(i)/_TiB)
92		case i >= _GiB:
93			result = fmt.Sprintf("%.02f GiB", float64(i)/_GiB)
94		case i >= _MiB:
95			result = fmt.Sprintf("%.02f MiB", float64(i)/_MiB)
96		case i >= _KiB:
97			result = fmt.Sprintf("%.02f KiB", float64(i)/_KiB)
98		default:
99			result = fmt.Sprintf("%d B", i)
100		}
101	} else {
102		switch {
103		case i >= _TB:
104			result = fmt.Sprintf("%.02f TB", float64(i)/_TB)
105		case i >= _GB:
106			result = fmt.Sprintf("%.02f GB", float64(i)/_GB)
107		case i >= _MB:
108			result = fmt.Sprintf("%.02f MB", float64(i)/_MB)
109		case i >= _kB:
110			result = fmt.Sprintf("%.02f kB", float64(i)/_kB)
111		default:
112			result = fmt.Sprintf("%d B", i)
113		}
114	}
115	return
116}
117