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)
46mainloop:
47	for i, r := range s {
48		for _, seq := range seqs {
49			if i >= seq[0] && i < seq[1] {
50				buf.WriteRune(r)
51				continue mainloop
52			}
53		}
54		if rw := CellCount(string(r)); rw <= w {
55			w -= rw
56			buf.WriteRune(r)
57		} else {
58			break
59		}
60	}
61	for w > 0 {
62		buf.WriteByte(' ')
63		w--
64	}
65	return
66}
67
68func round(val float64) (newVal float64) {
69	roundOn := 0.5
70	places := 0
71	var round float64
72	pow := math.Pow(10, float64(places))
73	digit := pow * val
74	_, div := math.Modf(digit)
75	if div >= roundOn {
76		round = math.Ceil(digit)
77	} else {
78		round = math.Floor(digit)
79	}
80	newVal = round / pow
81	return
82}
83
84// Convert bytes to human readable string. Like a 2 MiB, 64.2 KiB, or 2 MB, 64.2 kB
85// if useSIPrefix is set to true
86func formatBytes(i int64, useSIPrefix bool) (result string) {
87	if !useSIPrefix {
88		switch {
89		case i >= _TiB:
90			result = fmt.Sprintf("%.02f TiB", float64(i)/_TiB)
91		case i >= _GiB:
92			result = fmt.Sprintf("%.02f GiB", float64(i)/_GiB)
93		case i >= _MiB:
94			result = fmt.Sprintf("%.02f MiB", float64(i)/_MiB)
95		case i >= _KiB:
96			result = fmt.Sprintf("%.02f KiB", float64(i)/_KiB)
97		default:
98			result = fmt.Sprintf("%d B", i)
99		}
100	} else {
101		switch {
102		case i >= _TB:
103			result = fmt.Sprintf("%.02f TB", float64(i)/_TB)
104		case i >= _GB:
105			result = fmt.Sprintf("%.02f GB", float64(i)/_GB)
106		case i >= _MB:
107			result = fmt.Sprintf("%.02f MB", float64(i)/_MB)
108		case i >= _kB:
109			result = fmt.Sprintf("%.02f kB", float64(i)/_kB)
110		default:
111			result = fmt.Sprintf("%d B", i)
112		}
113	}
114	return
115}
116