func (c *Set) String() string {
	if c == nil || len(c.flat) == 0 {
		return "<invalid>"
	}
	bins := make([]int, 8)
	patterns := make([]uint, maxValues)
	c.mu.RLock()
	defer c.mu.RUnlock()
	m := c.histo(bins, patterns, 0, Value(maxValues))
	vs := []string{"=" + combos[m]}
	for i := uint(8); i > 0; {
		i--
		if i == m || bins[i] == 0 {
			continue
		}
		var list []string
		for j, p := range patterns {
			if p != i {
				continue
			}
			list = append(list, Value(j).String())
		}
		x := strings.Join(list, ",")
		var y, z string
		if cf := i & ^m; cf != 0 {
			op := "+"
			if len(vs) == 1 && vs[0] == "=" {
				vs = nil
				op = "="
			}
			y = op + combos[cf]
		}
		if cf := m & ^i; cf != 0 {
			z = "-" + combos[cf]
		}
		vs = append(vs, x+y+z)
	}
	uBins := make([]int, 8)
	uPatterns := make([]uint, 32*words)
	c.histo(uBins, uPatterns, Value(maxValues), 32*Value(words))
	for i := uint(7); i > 0; i-- {
		if uBins[i] == 0 {
			continue
		}
		var list []string
		for j, p := range uPatterns {
			if p != i {
				continue
			}
			list = append(list, Value(j).String())
		}
		vs = append(vs, strings.Join(list, ",")+"+"+combos[i])
	}
	return strings.Join(vs, " ")
}
String converts a full capability Set into a single short readable
string representation (which may contain spaces). See the
cap.FromText() function for an explanation of its return values.

Note (*cap.Set).String() may evolve to generate more compact
strings representing the a given Set over time, but it should
maintain compatibility with the libcap:cap_to_text() function for
any given release. Further, it will always be an inverse of
cap.FromText().
package cap
import (
	"bufio"
	"errors"
	"strconv"
	"strings"
)
func (v Value) String() string {
	name, ok := names[v]
	if ok {
		return name
	}
	return strconv.Itoa(int(v))
}
func FromName(name string) (Value, error) {
	startUp.Do(multisc.cInit)
	v, ok := bits[name]
	if ok {
		if v >= Value(words*32) {
			return 0, ErrBadValue
		}
		return v, nil
	}
	i, err := strconv.Atoi(name)
	if err != nil {
		return 0, err
	}
	if i >= 0 && i < int(words*32) {
		return Value(i), nil
	}
	return 0, ErrBadValue
}
const (
	eBin uint = (1 << Effective)
	pBin      = (1 << Permitted)
	iBin      = (1 << Inheritable)
)
var combos = []string{"", "e", "p", "ep", "i", "ei", "ip", "eip"}
func (c *Set) histo(bins []int, patterns []uint, from, limit Value) uint {
	for v := from; v < limit; v++ {
		b := uint(v & 31)
		u, bit, err := bitOf(0, v)
		if err != nil {
			break
		}
		x := uint((c.flat[u][Effective]&bit)>>b) * eBin
		x |= uint((c.flat[u][Permitted]&bit)>>b) * pBin
		x |= uint((c.flat[u][Inheritable]&bit)>>b) * iBin
		bins[x]++
		patterns[uint(v)] = x
	}
	m := uint(7)
	for t := m; t > 0; {
		t--
		if bins[t] >= bins[m] {
			m = t
		}
	}
	return m
}