func (d *GoDict) S(id int) (s string, ok bool) {
	d.rwm.RLock()          
	defer d.rwm.RUnlock()  
	if id >= len(d.is) {
		return "", false
	}
	return d.is[id], true
}
S maps an id to its string value and ok == true. Id values not contained in the bijection
return "", false.
package strutil
import (
	"bytes"
	"encoding/base32"
	"encoding/base64"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"sync"
)
func Base32ExtDecode(text []byte) (data []byte, err error) {
	n := base32.HexEncoding.DecodedLen(len(text))
	data = make([]byte, n)
	decoder := base32.NewDecoder(base32.HexEncoding, bytes.NewBuffer(text))
	if n, err = decoder.Read(data); err != nil {
		n = 0
	}
	data = data[:n]
	return
}
func Base32ExtEncode(data []byte) (text []byte) {
	n := base32.HexEncoding.EncodedLen(len(data))
	buf := bytes.NewBuffer(make([]byte, 0, n))
	encoder := base32.NewEncoder(base32.HexEncoding, buf)
	encoder.Write(data)
	encoder.Close()
	if buf.Len() != n {
		panic("internal error")
	}
	return buf.Bytes()
}
func Base64Decode(text []byte) (data []byte, err error) {
	n := base64.StdEncoding.DecodedLen(len(text))
	data = make([]byte, n)
	decoder := base64.NewDecoder(base64.StdEncoding, bytes.NewBuffer(text))
	if n, err = decoder.Read(data); err != nil {
		n = 0
	}
	data = data[:n]
	return
}
func Base64Encode(data []byte) (text []byte) {
	n := base64.StdEncoding.EncodedLen(len(data))
	buf := bytes.NewBuffer(make([]byte, 0, n))
	encoder := base64.NewEncoder(base64.StdEncoding, buf)
	encoder.Write(data)
	encoder.Close()
	if buf.Len() != n {
		panic("internal error")
	}
	return buf.Bytes()
}
type Formatter interface {
	io.Writer
	Format(format string, args ...interface{}) (n int, errno error)
}
type indentFormatter struct {
	io.Writer
	indent      []byte
	indentLevel int
	state       int
}
const (
	st0 = iota
	stBOL
	stPERC
	stBOLPERC
)
func IndentFormatter(w io.Writer, indent string) Formatter {
	return &indentFormatter{w, []byte(indent), 0, stBOL}
}
func (f *indentFormatter) format(flat bool, format string, args ...interface{}) (n int, errno error) {
	buf := []byte{}
	for i := 0; i < len(format); i++ {
		c := format[i]
		switch f.state {
		case st0:
			switch c {
			case '\n':
				cc := c
				if flat && f.indentLevel != 0 {
					cc = ' '
				}
				buf = append(buf, cc)
				f.state = stBOL
			case '%':
				f.state = stPERC
			default:
				buf = append(buf, c)
			}
		case stBOL:
			switch c {
			case '\n':
				cc := c
				if flat && f.indentLevel != 0 {
					cc = ' '
				}
				buf = append(buf, cc)
			case '%':
				f.state = stBOLPERC
			default:
				if !flat {
					for i := 0; i < f.indentLevel; i++ {
						buf = append(buf, f.indent...)
					}
				}
				buf = append(buf, c)
				f.state = st0
			}
		case stBOLPERC:
			switch c {
			case 'i':
				f.indentLevel++
				f.state = stBOL
			case 'u':
				f.indentLevel--
				f.state = stBOL
			default:
				if !flat {
					for i := 0; i < f.indentLevel; i++ {
						buf = append(buf, f.indent...)
					}
				}
				buf = append(buf, '%', c)
				f.state = st0
			}
		case stPERC:
			switch c {
			case 'i':
				f.indentLevel++
				f.state = st0
			case 'u':
				f.indentLevel--
				f.state = st0
			default:
				buf = append(buf, '%', c)
				f.state = st0
			}
		default:
			panic("unexpected state")
		}
	}
	switch f.state {
	case stPERC, stBOLPERC:
		buf = append(buf, '%')
	}
	return f.Write([]byte(fmt.Sprintf(string(buf), args...)))
}
func (f *indentFormatter) Format(format string, args ...interface{}) (n int, errno error) {
	return f.format(false, format, args...)
}
type flatFormatter indentFormatter
func FlatFormatter(w io.Writer) Formatter {
	return (*flatFormatter)(IndentFormatter(w, "").(*indentFormatter))
}
func (f *flatFormatter) Format(format string, args ...interface{}) (n int, errno error) {
	return (*indentFormatter)(f).format(true, format, args...)
}
type Pool struct {
	pool map[string]string
}
func NewPool() *Pool {
	return &Pool{map[string]string{}}
}
func (p *Pool) Align(s string) string {
	if a, ok := p.pool[s]; ok {
		return a
	}
	s = StrPack(s)
	p.pool[s] = s
	return s
}
func (p *Pool) Count() int {
	return len(p.pool)
}
type GoPool struct {
	pool map[string]string
	rwm  *sync.RWMutex
}
func NewGoPool() (p *GoPool) {
	return &GoPool{map[string]string{}, &sync.RWMutex{}}
}
func (p *GoPool) Align(s string) (y string) {
	if s != "" {
		p.rwm.RLock()                
		if a, ok := p.pool[s]; ok {  
			p.rwm.RUnlock()  
			return a
		}
		p.rwm.RUnlock()  
		p.rwm.Lock()                 
		defer p.rwm.Unlock()         
		if a, ok := p.pool[s]; ok {  
			return a
		}
		s = StrPack(s)
		p.pool[s] = s
		return s
	}
	return
}
func (p *GoPool) Count() int {
	return len(p.pool)
}
type Dict struct {
	si map[string]int
	is []string
}
func NewDict() (d *Dict) {
	d = &Dict{map[string]int{}, []string{}}
	d.Id("")
	return
}
func (d *Dict) Count() int {
	return len(d.is)
}
func (d *Dict) Id(s string) (y int) {
	if y, ok := d.si[s]; ok {
		return y
	}
	s = StrPack(s)
	y = len(d.is)
	d.si[s] = y
	d.is = append(d.is, s)
	return
}
func (d *Dict) S(id int) (s string, ok bool) {
	if id >= len(d.is) {
		return "", false
	}
	return d.is[id], true
}
type GoDict struct {
	si  map[string]int
	is  []string
	rwm *sync.RWMutex
}
func NewGoDict() (d *GoDict) {
	d = &GoDict{map[string]int{}, []string{}, &sync.RWMutex{}}
	d.Id("")
	return
}
func (d *GoDict) Count() int {
	return len(d.is)
}
func (d *GoDict) Id(s string) (y int) {
	d.rwm.RLock()              
	if y, ok := d.si[s]; ok {  
		d.rwm.RUnlock()  
		return y
	}
	d.rwm.RUnlock()  
	d.rwm.Lock()               
	defer d.rwm.Unlock()       
	if y, ok := d.si[s]; ok {  
		return y
	}
	s = StrPack(s)
	y = len(d.is)
	d.si[s] = y
	d.is = append(d.is, s)
	return
}