replace zxq.co/ripple/hanayo
This commit is contained in:
18
vendor/github.com/thehowl/cieca/LICENSE
generated
vendored
Normal file
18
vendor/github.com/thehowl/cieca/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
Copyright (c) 2016 Morgan Bazalgette
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
117
vendor/github.com/thehowl/cieca/cieca.go
generated
vendored
Normal file
117
vendor/github.com/thehowl/cieca/cieca.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
// Package cieca is an in-memory Key-Value datastore for Go. The main purpose
|
||||
// is to easily cache data in the RAM for a certain amount of time.
|
||||
package cieca
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type element struct {
|
||||
data []byte
|
||||
expire time.Time
|
||||
cancel chan struct{}
|
||||
}
|
||||
|
||||
// DataStore is the datastore containing all the data.
|
||||
type DataStore struct {
|
||||
data map[string]element
|
||||
mutex *sync.RWMutex
|
||||
}
|
||||
|
||||
// Get retrieves a value in the datastore. If it is not found, nil is returned.
|
||||
func (d *DataStore) Get(key string) []byte {
|
||||
v, _ := d.GetWithExist(key)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetWithExist retrieves the value of a key, and a boolean indicating whether
|
||||
// the value existed in the store.
|
||||
func (d *DataStore) GetWithExist(key string) ([]byte, bool) {
|
||||
d.setup()
|
||||
d.mutex.RLock()
|
||||
defer d.mutex.RUnlock()
|
||||
el, ex := d.data[key]
|
||||
return el.data, ex
|
||||
}
|
||||
|
||||
// Expiration gets the time of expiration of a key.
|
||||
func (d *DataStore) Expiration(key string) *time.Time {
|
||||
d.setup()
|
||||
d.mutex.RLock()
|
||||
defer d.mutex.RUnlock()
|
||||
el, exist := d.data[key]
|
||||
if !exist || el.cancel == nil {
|
||||
return nil
|
||||
}
|
||||
t := el.expire
|
||||
return &t
|
||||
}
|
||||
|
||||
// Delete removes an element from the datastore.
|
||||
func (d *DataStore) Delete(key string) {
|
||||
d.setup()
|
||||
d.mutex.Lock()
|
||||
defer d.mutex.Unlock()
|
||||
exp := d.data[key].cancel
|
||||
if exp != nil && time.Now().Sub(d.data[key].expire) <= 0 {
|
||||
exp <- struct{}{}
|
||||
close(exp)
|
||||
}
|
||||
delete(d.data, key)
|
||||
}
|
||||
|
||||
// Set sets a key in the datastore with no expiration.
|
||||
func (d *DataStore) Set(key string, value []byte) {
|
||||
d.SetWithExpiration(key, value, -1)
|
||||
}
|
||||
|
||||
// SetWithExpiration sets a key in the datastore with a certain value.
|
||||
func (d *DataStore) SetWithExpiration(key string, value []byte, expiration time.Duration) {
|
||||
d.setup()
|
||||
var c chan struct{}
|
||||
if expiration >= 0 {
|
||||
c = make(chan struct{})
|
||||
}
|
||||
el := element{
|
||||
data: value,
|
||||
expire: time.Now().Add(expiration),
|
||||
cancel: c,
|
||||
}
|
||||
d.Delete(key)
|
||||
d.mutex.Lock()
|
||||
defer d.mutex.Unlock()
|
||||
d.data[key] = el
|
||||
if c != nil {
|
||||
go d.queueDeletion(expiration, c, key)
|
||||
}
|
||||
}
|
||||
|
||||
// Clean clears the datastore. Not so thread-safe. Use with care.
|
||||
func (d *DataStore) Clean() {
|
||||
if d == nil {
|
||||
return
|
||||
}
|
||||
for el := range d.data {
|
||||
d.Delete(el)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DataStore) queueDeletion(dur time.Duration, canc <-chan struct{}, key string) {
|
||||
select {
|
||||
case <-time.NewTimer(dur).C:
|
||||
d.Delete(key)
|
||||
case <-canc:
|
||||
// useless, but explicits what we're doing
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DataStore) setup() {
|
||||
if d.data == nil {
|
||||
d.data = make(map[string]element)
|
||||
}
|
||||
if d.mutex == nil {
|
||||
d.mutex = &sync.RWMutex{}
|
||||
}
|
||||
}
|
84
vendor/github.com/thehowl/cieca/cieca_test.go
generated
vendored
Normal file
84
vendor/github.com/thehowl/cieca/cieca_test.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
package cieca_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thehowl/cieca"
|
||||
)
|
||||
|
||||
func TestSetGet(t *testing.T) {
|
||||
x := []byte("carroponte")
|
||||
s := &cieca.DataStore{}
|
||||
s.Set("test", x)
|
||||
if string(s.Get("test")) != "carroponte" {
|
||||
t.Fatal("test != carroponte", string(s.Get("test")))
|
||||
}
|
||||
s.Clean()
|
||||
}
|
||||
func TestClean(t *testing.T) {
|
||||
s := &cieca.DataStore{}
|
||||
s.Set("test", []byte("a"))
|
||||
s.Clean()
|
||||
if _, ex := s.GetWithExist("test"); ex {
|
||||
t.Fatal("value exists even after Clean!")
|
||||
}
|
||||
}
|
||||
func TestExpire(t *testing.T) {
|
||||
s := &cieca.DataStore{}
|
||||
defer s.Clean()
|
||||
s.SetWithExpiration("zxcvbn", []byte("why?"), time.Nanosecond*100)
|
||||
if s.Get("zxcvbn") == nil {
|
||||
t.Fatal("Early expiration?")
|
||||
}
|
||||
if s.Expiration("zxcvbn") == nil {
|
||||
t.Fatal("key's expiration is nil")
|
||||
}
|
||||
time.Sleep(time.Nanosecond * 5000)
|
||||
if s.Get("zxcvbn") != nil {
|
||||
t.Fatal("Late expiration?")
|
||||
}
|
||||
}
|
||||
func TestOverwrite(t *testing.T) {
|
||||
s := &cieca.DataStore{}
|
||||
defer s.Clean()
|
||||
s.Set("meme", []byte("1451"))
|
||||
s.Set("meme", []byte("1337"))
|
||||
if string(s.Get("meme")) != "1337" {
|
||||
t.Fatal("No overwrite?")
|
||||
}
|
||||
}
|
||||
func TestOverwriteWithExpiration(t *testing.T) {
|
||||
s := &cieca.DataStore{}
|
||||
defer s.Clean()
|
||||
s.SetWithExpiration("carroponte", []byte("19689168196"), time.Second)
|
||||
s.Delete("carroponte")
|
||||
if s.Get("carroponte") != nil {
|
||||
t.Fatal("carroponte ain't nil")
|
||||
}
|
||||
}
|
||||
|
||||
// just for coverage
|
||||
func TestCleanOnNil(t *testing.T) {
|
||||
var s *cieca.DataStore
|
||||
s.Clean()
|
||||
}
|
||||
func TestExpirationWhenTheresNoExpiration(t *testing.T) {
|
||||
s := &cieca.DataStore{}
|
||||
defer s.Clean()
|
||||
s.Set("meme", []byte("x"))
|
||||
if s.Expiration("NotExisting") != nil || s.Expiration("meme") != nil {
|
||||
t.Fatal("WHAT EXPIRATION???")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSetGetDelete(b *testing.B) {
|
||||
s := &cieca.DataStore{}
|
||||
s.Get("NotExisting")
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
s.Set("test", []byte("x"))
|
||||
s.Get("test")
|
||||
s.Delete("test")
|
||||
}
|
||||
}
|
6
vendor/github.com/thehowl/conf/.travis.yml
generated
vendored
Normal file
6
vendor/github.com/thehowl/conf/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.5
|
||||
- 1.6
|
||||
- tip
|
18
vendor/github.com/thehowl/conf/LICENSE
generated
vendored
Normal file
18
vendor/github.com/thehowl/conf/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
Copyright (c) 2016 Morgan Bazalgette
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
83
vendor/github.com/thehowl/conf/README.md
generated
vendored
Normal file
83
vendor/github.com/thehowl/conf/README.md
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
# conf [](https://travis-ci.org/thehowl/conf) [](https://godoc.org/github.com/thehowl/conf)
|
||||
|
||||
(yes I am that creative with names)
|
||||
|
||||
I have been using [ini](http://gopkg.in/ini.v1) for managing configuration files in go for quite some time. One of the things that had bothered me though, was that it really was a pain to set up for small projects, as it's just boilerplate code over and over. So I decided to write my own configuration file system, and now I'm here.
|
||||
|
||||
## Quick start
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/thehowl/conf"
|
||||
)
|
||||
|
||||
type myConf struct {
|
||||
Port string `description:"The port from which the application will take HTTP requests"`
|
||||
Password string
|
||||
MaxUsers int
|
||||
}
|
||||
|
||||
func main() {
|
||||
c := myConf{}
|
||||
err := conf.Load(&c, "myapp.conf")
|
||||
if err == conf.ErrNoFile {
|
||||
// You can export your conf to a file, so you can write default values.
|
||||
conf.Export(myConf{
|
||||
Port: ":8080",
|
||||
Password: "hunter2",
|
||||
MaxUsers: 9001,
|
||||
}, "myapp.conf")
|
||||
fmt.Println("Please compile the configuration file (myapp.conf.)")
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// You can now use the values in `c` without thinking about the actual configuration ever again!
|
||||
fmt.Printf("%#v\n", c)
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration file format
|
||||
|
||||
```
|
||||
; This is an example configuration file generated with `conf`. Comments are done using semicolons.
|
||||
;
|
||||
; This is a simple string value in the configuration:
|
||||
String=Hello world!
|
||||
|
||||
; Note that there are no spaces between the field (key) name and its value. Conf does not trim strings.
|
||||
; int, float, uint values are done just as easily. You just need to write that they're of that type in
|
||||
; the struct, and conf will do all the magic!
|
||||
Int=481
|
||||
|
||||
; There are also bools.
|
||||
Bool=1
|
||||
; Bools are retrieved through [ParseBool](https://golang.org/pkg/strconv/#ParseBool), as such they
|
||||
; need to be one of 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.
|
||||
|
||||
; But, what about strings with newlines?
|
||||
AreTheyPossible=Yes\
|
||||
They\
|
||||
Are!
|
||||
; If you need to export a flag with a multiline string, conf will automatically escape it.
|
||||
;
|
||||
; By the way, conf automatically ignores lines without a valid field=value combination, including
|
||||
; empty lines, so you can use them as comments, although discouraged.
|
||||
So yes, this line will be silently ignored!
|
||||
=This one, too!
|
||||
And this one, too!=
|
||||
|
||||
; Escaping can not only be done with newlines. Here's what you can possibly escape!
|
||||
Fields\=With\=Equal\=Signs=can be escaped!
|
||||
Comments=Can \; be escaped!
|
||||
Oh yeah, fields=can also have spaces and what not in them.; You can also write comments straight after a value!
|
||||
|
||||
; And that's all you need to know for using `conf`!
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
165
vendor/github.com/thehowl/conf/conf.go
generated
vendored
Normal file
165
vendor/github.com/thehowl/conf/conf.go
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
// Package conf lets you manage configuration files in the easiest way possible, without the unnecessary pain.
|
||||
package conf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The only custom errors this package will return.
|
||||
var (
|
||||
ErrNoFile = errors.New("conf: the configuration file doesn't exist")
|
||||
ErrNotAStruct = errors.New("conf: the passed into/from variable is not a pointer to a struct")
|
||||
)
|
||||
|
||||
// Load unmarshals a file into the struct passed as the argument "into".
|
||||
func Load(into interface{}, filename string) error {
|
||||
intoValue := reflect.ValueOf(into)
|
||||
if intoValue.Kind() != reflect.Ptr || intoValue.Elem().Kind() != reflect.Struct {
|
||||
return ErrNotAStruct
|
||||
}
|
||||
intoValue = intoValue.Elem()
|
||||
f, err := ioutil.ReadFile(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return ErrNoFile
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return loadRaw(intoValue, f)
|
||||
}
|
||||
|
||||
// LoadRaw allows you to load into a struct some raw data bytes.
|
||||
func LoadRaw(into interface{}, data []byte) error {
|
||||
intoValue := reflect.ValueOf(into)
|
||||
if intoValue.Kind() != reflect.Ptr || intoValue.Elem().Kind() != reflect.Struct {
|
||||
return ErrNotAStruct
|
||||
}
|
||||
intoValue = intoValue.Elem()
|
||||
return loadRaw(intoValue, data)
|
||||
}
|
||||
|
||||
func loadRaw(intoValue reflect.Value, data []byte) error {
|
||||
fvs := Parse(data)
|
||||
for _, v := range fvs {
|
||||
for i := 0; i < intoValue.Type().NumField(); i++ {
|
||||
field := intoValue.Type().Field(i)
|
||||
if !intoValue.Field(i).CanSet() {
|
||||
continue
|
||||
}
|
||||
if field.Name == v.Field {
|
||||
switch field.Type.Kind() {
|
||||
case reflect.String:
|
||||
intoValue.Field(i).SetString(v.Value)
|
||||
case reflect.Bool:
|
||||
boolVal, err := strconv.ParseBool(v.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
intoValue.Field(i).SetBool(boolVal)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
intVal, err := strconv.ParseInt(v.Value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
intoValue.Field(i).SetInt(intVal)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
uintVal, err := strconv.ParseUint(v.Value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
intoValue.Field(i).SetUint(uintVal)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
floatVal, err := strconv.ParseFloat(v.Value, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
intoValue.Field(i).SetFloat(floatVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MustLoad has the same behaviour as Load, but panics if it returns an error.
|
||||
func MustLoad(into interface{}, filename string) {
|
||||
if err := Load(into, filename); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// MustLoadRaw has the same behaviour as LoadRaw, but panics if it returns an error.
|
||||
func MustLoadRaw(into interface{}, data []byte) {
|
||||
if err := LoadRaw(into, data); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Export uses ExportRaw to put the data into a file, specified with its name.
|
||||
func Export(from interface{}, filename string) error {
|
||||
data, err := ExportRaw(from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(filename, data, 0644)
|
||||
}
|
||||
|
||||
// ExportRaw can create a []byte that can then be loaded back by LoadRaw to get a struct's original form back.
|
||||
// I suck at explaining stuff.
|
||||
func ExportRaw(from interface{}) ([]byte, error) {
|
||||
fromValue := reflect.ValueOf(from)
|
||||
if fromValue.Kind() == reflect.Ptr {
|
||||
return ExportRaw(fromValue.Elem().Interface())
|
||||
}
|
||||
if fromValue.Kind() != reflect.Struct {
|
||||
return []byte{}, ErrNotAStruct
|
||||
}
|
||||
return exportRaw(fromValue), nil
|
||||
}
|
||||
|
||||
func exportRaw(fromValue reflect.Value) []byte {
|
||||
var ret []byte
|
||||
for i := 0; i < fromValue.Type().NumField(); i++ {
|
||||
curfield := fromValue.Field(i)
|
||||
curfieldType := fromValue.Type().Field(i)
|
||||
|
||||
// Dirty hack to ignore that field if we don't support that type.
|
||||
if !((curfield.Kind() >= reflect.Bool && curfield.Kind() <= reflect.Uint64) ||
|
||||
curfield.Kind() == reflect.String || curfield.Kind() == reflect.Float32 ||
|
||||
curfield.Kind() == reflect.Float64) {
|
||||
continue
|
||||
}
|
||||
|
||||
/* guten */ tag := curfieldType.Tag.Get("description")
|
||||
if tag != "" {
|
||||
tag = strings.Replace(tag, "\n", "\n; ", -1)
|
||||
ret = append(ret, []byte("; "+tag+"\n")...)
|
||||
}
|
||||
ret = append(ret, []byte(Escape(curfieldType.Name)+"="+Escape(fmt.Sprint(curfield.Interface()))+"\n")...)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// MustExport panics if Export returns an error, removing error checking from your code. For the lazy.
|
||||
func MustExport(from interface{}, filename string) {
|
||||
if err := Export(from, filename); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// MustExportRaw panics if ExportRaw returns an error, removing error checking from your code. For the lazy.
|
||||
func MustExportRaw(from interface{}) []byte {
|
||||
data, err := ExportRaw(from)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return data
|
||||
}
|
377
vendor/github.com/thehowl/conf/conf_test.go
generated
vendored
Normal file
377
vendor/github.com/thehowl/conf/conf_test.go
generated
vendored
Normal file
@@ -0,0 +1,377 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const sampleForParsing = `Key1=Value
|
||||
Test=Xd
|
||||
What=1294; This be a comment.
|
||||
; This be another comment.
|
||||
|
||||
|
||||
Multi=Line\
|
||||
String!
|
||||
Key\=With\=Equal=Indeed!
|
||||
ShouldNotOutput=
|
||||
=ShouldNotOutput
|
||||
ShouldNotOutput
|
||||
|
||||
Can=Contain\;Semicolons!
|
||||
EqualSign=Can also = not = be = escaped!
|
||||
|
||||
ThisShouldComeUp=Yup`
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
kvs := Parse([]byte(sampleForParsing))
|
||||
t.Log("Result:")
|
||||
for _, v := range kvs {
|
||||
t.Logf(" %s - %s\n", v.Field, v.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkParseWithSample(b *testing.B) {
|
||||
sp := []byte(sampleForParsing)
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
Parse(sp)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
escapeOriginal = `;aqsdwe103====aa\a\\aa!a;a
|
||||
|
||||
xd|`
|
||||
escapeExpected = `\;aqsdwe103\=\=\=\=aa\\a\\\\aa!a\;a\
|
||||
\
|
||||
xd|`
|
||||
)
|
||||
|
||||
func TestEscape(t *testing.T) {
|
||||
escaped := Escape(escapeOriginal)
|
||||
if escaped != escapeExpected {
|
||||
t.Fatalf("Expected Escape to return '%s', got '%s' instead.", escapeExpected, escaped)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEscape(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
Escape(escapeOriginal)
|
||||
}
|
||||
}
|
||||
|
||||
const sampleForUnmarshaling = `
|
||||
; Welcome to hell.
|
||||
; As we have to try every single possible value a struct can have, all of this is required.
|
||||
; Fuck.
|
||||
TestInt=1510591
|
||||
TestInt8=-100
|
||||
TestInt16=-12844
|
||||
TestInt32=-3211
|
||||
TestInt64=410491
|
||||
|
||||
TestUint=284129419
|
||||
TestUint8=255
|
||||
TestUint16=65535
|
||||
TestUint32=151529;Can't remember the max value. Won't bother googling.
|
||||
TestUint64=24148999
|
||||
|
||||
TestFloat32=24.1123
|
||||
TestFloat64=110.134141223
|
||||
|
||||
TestBool=1
|
||||
|
||||
TestString=How much wood would a woodchuck chuck if a woodchuck could chuck wood?
|
||||
TestEmpty=
|
||||
`
|
||||
|
||||
type sampleTest struct {
|
||||
TestInt int
|
||||
TestInt8 int8
|
||||
TestInt16 int16
|
||||
TestInt32 int32
|
||||
TestInt64 int64
|
||||
|
||||
TestUint uint
|
||||
TestUint8 uint8
|
||||
TestUint16 uint16
|
||||
TestUint32 uint32
|
||||
TestUint64 uint64
|
||||
|
||||
TestFloat32 float32
|
||||
TestFloat64 float64
|
||||
|
||||
TestBool bool
|
||||
|
||||
TestString string
|
||||
TestEmpty string
|
||||
}
|
||||
|
||||
func (si sampleTest) check(t *testing.T) {
|
||||
if true &&
|
||||
si.TestInt == 1510591 &&
|
||||
si.TestInt8 == -100 &&
|
||||
si.TestInt16 == -12844 &&
|
||||
si.TestInt32 == -3211 &&
|
||||
si.TestInt64 == 410491 &&
|
||||
|
||||
si.TestUint == 284129419 &&
|
||||
si.TestUint8 == 255 &&
|
||||
si.TestUint16 == 65535 &&
|
||||
si.TestUint32 == 151529 &&
|
||||
si.TestUint64 == 24148999 &&
|
||||
|
||||
si.TestFloat32 == 24.1123 &&
|
||||
si.TestFloat64 == 110.134141223 &&
|
||||
|
||||
si.TestBool == true &&
|
||||
|
||||
si.TestString == "How much wood would a woodchuck chuck if a woodchuck could chuck wood?" &&
|
||||
si.TestEmpty == "" {
|
||||
t.Log("It surprisingly worked.")
|
||||
} else {
|
||||
t.Log("Nope.")
|
||||
t.Fatalf("%#v", si)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
// Prepare file
|
||||
err := ioutil.WriteFile("test.conf", []byte(sampleForUnmarshaling), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove("test.conf")
|
||||
|
||||
// Prepare struct
|
||||
si := sampleTest{}
|
||||
|
||||
// Load
|
||||
err = Load(&si, "test.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Check for all values to be valid.
|
||||
si.check(t)
|
||||
}
|
||||
|
||||
func TestLoadShouldErrNotAStruct(t *testing.T) {
|
||||
if err := Load(2, "test.conf"); err != ErrNotAStruct {
|
||||
t.Fatalf("Should have panicked with ErrNotAStruct, got error '%s' instead.", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadShouldErrNoFile(t *testing.T) {
|
||||
si := sampleTest{}
|
||||
if err := Load(&si, "test.conf"); err != ErrNoFile {
|
||||
t.Fatalf("Should have panicked with ErrNoFile, got error '%s' instead.", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustLoadShouldPanic(t *testing.T) {
|
||||
defer func() {
|
||||
c := recover()
|
||||
if c == nil {
|
||||
t.Fatal("MustLoad with wrong values didn't panic!")
|
||||
}
|
||||
}()
|
||||
MustLoad(2, "test.conf")
|
||||
}
|
||||
|
||||
func TestFailBool(t *testing.T) {
|
||||
// Prepare file
|
||||
err := ioutil.WriteFile("test.conf", []byte(`TestBool=Lolno.`), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove("test.conf")
|
||||
|
||||
// Prepare struct
|
||||
si := sampleTest{}
|
||||
|
||||
// Load
|
||||
err = Load(&si, "test.conf")
|
||||
if err == nil {
|
||||
t.Fatal("Should have returned an error, didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFailInt(t *testing.T) {
|
||||
// Prepare file
|
||||
err := ioutil.WriteFile("test.conf", []byte(`TestInt=10934104912049120491204912031301293102`), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove("test.conf")
|
||||
|
||||
// Prepare struct
|
||||
si := sampleTest{}
|
||||
|
||||
// Load
|
||||
err = Load(&si, "test.conf")
|
||||
if err == nil {
|
||||
t.Fatal("Should have returned an error, didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFailFloat(t *testing.T) {
|
||||
// Prepare file
|
||||
err := ioutil.WriteFile("test.conf", []byte(`TestFloat32=2931.23111aaddfffeep`), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove("test.conf")
|
||||
|
||||
// Prepare struct
|
||||
si := sampleTest{}
|
||||
|
||||
// Load
|
||||
err = Load(&si, "test.conf")
|
||||
if err == nil {
|
||||
t.Fatal("Should have returned an error, didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFailUint(t *testing.T) {
|
||||
// Prepare file
|
||||
err := ioutil.WriteFile("test.conf", []byte(`TestUint8=asd`), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove("test.conf")
|
||||
|
||||
// Prepare struct
|
||||
si := sampleTest{}
|
||||
|
||||
// Load
|
||||
err = Load(&si, "test.conf")
|
||||
if err == nil {
|
||||
t.Fatal("Should have returned an error, didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadRaw(t *testing.T) {
|
||||
si := sampleTest{}
|
||||
|
||||
LoadRaw(&si, []byte(sampleForUnmarshaling))
|
||||
si.check(t)
|
||||
}
|
||||
|
||||
func TestMustLoadRawShouldPanic(t *testing.T) {
|
||||
defer func() {
|
||||
c := recover()
|
||||
if c == nil {
|
||||
t.Fatal("MustLoad with wrong values didn't panic!")
|
||||
}
|
||||
}()
|
||||
MustLoadRaw(2, []byte("a"))
|
||||
}
|
||||
|
||||
func BenchmarkLoadRaw(b *testing.B) {
|
||||
si := &sampleTest{}
|
||||
data := []byte(sampleForUnmarshaling)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
LoadRaw(si, data)
|
||||
}
|
||||
}
|
||||
|
||||
type exportTypeTest struct {
|
||||
Name string
|
||||
Age int `description:"The age of the patient.\nDescriptions can be multi-line."`
|
||||
}
|
||||
|
||||
const expectedExportType = `Name=Jack
|
||||
; The age of the patient.
|
||||
; Descriptions can be multi-line.
|
||||
Age=19
|
||||
`
|
||||
|
||||
func TestMustExportRaw(t *testing.T) {
|
||||
defer func() {
|
||||
c := recover()
|
||||
if c != nil {
|
||||
t.Fatal(c)
|
||||
}
|
||||
}()
|
||||
e := &exportTypeTest{
|
||||
Name: "Jack",
|
||||
Age: 19,
|
||||
}
|
||||
data := MustExportRaw(e)
|
||||
if string(data) != expectedExportType {
|
||||
t.Fatalf("Expected '%s', got '%s'", expectedExportType, string(data))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustExportShouldPanic(t *testing.T) {
|
||||
defer func() {
|
||||
c := recover()
|
||||
if c == nil {
|
||||
t.Fatal(c)
|
||||
}
|
||||
}()
|
||||
MustExport(2, "a.conf")
|
||||
}
|
||||
|
||||
func TestMustExportRawShouldPanic(t *testing.T) {
|
||||
defer func() {
|
||||
c := recover()
|
||||
if c == nil {
|
||||
t.Fatal(c)
|
||||
}
|
||||
}()
|
||||
MustExportRaw(2)
|
||||
}
|
||||
|
||||
type exportWithInvalidType struct {
|
||||
InvalidType []byte
|
||||
Name string
|
||||
}
|
||||
|
||||
func TestExport(t *testing.T) {
|
||||
err := Export(exportWithInvalidType{
|
||||
InvalidType: []byte("well"),
|
||||
Name: "xd",
|
||||
}, "test.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
os.Remove("test.conf")
|
||||
}
|
||||
|
||||
func TestFullChain(t *testing.T) {
|
||||
initial := exportTypeTest{
|
||||
Name: "Pisellone",
|
||||
Age: 133337,
|
||||
}
|
||||
c := MustExportRaw(initial)
|
||||
secondary := exportTypeTest{}
|
||||
MustLoadRaw(&secondary, c)
|
||||
if !reflect.DeepEqual(initial, secondary) {
|
||||
t.Fatalf("Initial struct %#v is not the same as the derivate %#v.", initial, secondary)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCRLF(t *testing.T) {
|
||||
const w = "Key1=Nice\r\nKey2=Meme"
|
||||
vals := Parse([]byte(w))
|
||||
for _, i := range vals {
|
||||
switch i.Field {
|
||||
case "Key1":
|
||||
if i.Value != "Nice" {
|
||||
t.Fatalf("Expected '%s', got '%s'", "Nice", i.Value)
|
||||
}
|
||||
case "Key2":
|
||||
if i.Value != "Meme" {
|
||||
t.Fatalf("Expected '%s', got '%s'", "Meme", i.Value)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("Unexpected key '%s'", i.Field)
|
||||
}
|
||||
}
|
||||
}
|
15
vendor/github.com/thehowl/conf/escape.go
generated
vendored
Normal file
15
vendor/github.com/thehowl/conf/escape.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Escape escapes characters for then putting it into conf field/values without issues.
|
||||
func Escape(s string) string {
|
||||
return strings.NewReplacer(
|
||||
"\n", "\\\n",
|
||||
`\`, `\\`,
|
||||
`;`, `\;`,
|
||||
`=`, `\=`,
|
||||
).Replace(s)
|
||||
}
|
21
vendor/github.com/thehowl/conf/example_test.go
generated
vendored
Normal file
21
vendor/github.com/thehowl/conf/example_test.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package conf_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/thehowl/conf"
|
||||
)
|
||||
|
||||
type myConf struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
const myConfString = `Name=Jack
|
||||
Age=19`
|
||||
|
||||
func Example() {
|
||||
c := myConf{}
|
||||
conf.LoadRaw(&c, []byte(myConfString))
|
||||
fmt.Printf("%#v\n", c)
|
||||
}
|
89
vendor/github.com/thehowl/conf/parse.go
generated
vendored
Normal file
89
vendor/github.com/thehowl/conf/parse.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package conf
|
||||
|
||||
// FieldValue is a field=value pair in the configuration.
|
||||
type FieldValue struct {
|
||||
Field string
|
||||
Value string
|
||||
}
|
||||
|
||||
const (
|
||||
currentName = iota
|
||||
currentValue
|
||||
currentComment
|
||||
)
|
||||
|
||||
// Parse converts some bytes into various FieldValue pairs.
|
||||
func Parse(data []byte) []FieldValue {
|
||||
fvs := []FieldValue{}
|
||||
var (
|
||||
fieldName string
|
||||
fieldValue string
|
||||
nextNormal bool
|
||||
current byte
|
||||
)
|
||||
|
||||
for _, c := range data {
|
||||
if current == currentComment && c != '\n' {
|
||||
continue
|
||||
}
|
||||
if nextNormal {
|
||||
switch current {
|
||||
case currentName:
|
||||
fieldName += string(c)
|
||||
case currentValue:
|
||||
fieldValue += string(c)
|
||||
}
|
||||
nextNormal = false
|
||||
continue
|
||||
}
|
||||
switch c {
|
||||
case '=':
|
||||
switch current {
|
||||
// if we are still at the name, let's switch to a value.
|
||||
case currentName:
|
||||
current = currentValue
|
||||
// if we are already at the value, treat the = character like any other sign
|
||||
case currentValue:
|
||||
fieldValue += string(c)
|
||||
}
|
||||
case ';':
|
||||
current = currentComment
|
||||
case '\n':
|
||||
if fieldName != "" && fieldValue != "" {
|
||||
fvs = append(fvs, FieldValue{
|
||||
Field: fieldName,
|
||||
Value: removeTrailingCR(fieldValue),
|
||||
})
|
||||
}
|
||||
fieldName = ""
|
||||
fieldValue = ""
|
||||
current = currentName
|
||||
case '\\':
|
||||
nextNormal = true
|
||||
default:
|
||||
switch current {
|
||||
case currentName:
|
||||
fieldName += string(c)
|
||||
case currentValue:
|
||||
fieldValue += string(c)
|
||||
}
|
||||
nextNormal = false
|
||||
}
|
||||
}
|
||||
if fieldName != "" && fieldValue != "" {
|
||||
fvs = append(fvs, FieldValue{
|
||||
Field: fieldName,
|
||||
Value: removeTrailingCR(fieldValue),
|
||||
})
|
||||
}
|
||||
return fvs
|
||||
}
|
||||
func removeTrailingCR(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
if s[len(s)-1] == '\r' {
|
||||
return s[:len(s)-1]
|
||||
}
|
||||
return s
|
||||
}
|
18
vendor/github.com/thehowl/qsql/LICENSE
generated
vendored
Normal file
18
vendor/github.com/thehowl/qsql/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
Copyright (c) 2016 Morgan Bazalgette
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
3
vendor/github.com/thehowl/qsql/README.md
generated
vendored
Normal file
3
vendor/github.com/thehowl/qsql/README.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# qsql
|
||||
|
||||
**Q**uick **SQL** queries, with maps and slices. See [godoc](https://godoc.org/github.com/thehowl/qsql).
|
17
vendor/github.com/thehowl/qsql/new.go
generated
vendored
Normal file
17
vendor/github.com/thehowl/qsql/new.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
package qsql
|
||||
|
||||
import "database/sql"
|
||||
|
||||
// New creates a new *DB having an *sql.DB.
|
||||
func New(db *sql.DB) *DB {
|
||||
if db == nil {
|
||||
return nil
|
||||
}
|
||||
return &DB{*db}
|
||||
}
|
||||
|
||||
// Open behaves the same as sql.Open, but creates an *qsql.DB instead.
|
||||
func Open(driverName, dsn string) (*DB, error) {
|
||||
db, err := sql.Open(driverName, dsn)
|
||||
return New(db), err
|
||||
}
|
97
vendor/github.com/thehowl/qsql/qsql.go
generated
vendored
Normal file
97
vendor/github.com/thehowl/qsql/qsql.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
// Package qsql implements SQL queries for the lazy, in the good ol' hashtable
|
||||
// or list of hashtable format.
|
||||
package qsql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// ErrDBIsNil is returned when the *sql.DB inside DB is nil.
|
||||
var ErrDBIsNil = errors.New("qsql: db is nil")
|
||||
|
||||
// DB wraps an sql.DB around a custom DB.
|
||||
//
|
||||
// If you're hardcore and want to create one without New(),
|
||||
// you should &qsql.DB{*db}.
|
||||
type DB struct {
|
||||
sql.DB
|
||||
}
|
||||
|
||||
// Exec behaves the same as sql.DB.Exec, however it does not wrap the last
|
||||
// insert ID and rows affected into an interface.
|
||||
func (d *DB) Exec(query string, params ...interface{}) (int, int, error) {
|
||||
res, err := d.DB.Exec(query, params...)
|
||||
lid, _ := res.LastInsertId()
|
||||
ra, _ := res.RowsAffected()
|
||||
return int(lid), int(ra), err
|
||||
}
|
||||
|
||||
// ExecNoRes returns sql.DB.Exec without Result.
|
||||
func (d *DB) ExecNoRes(query string, params ...interface{}) error {
|
||||
_, err := d.DB.Exec(query, params...)
|
||||
return err
|
||||
}
|
||||
|
||||
// Query queries the database for multiple rows. See sql.DB.Query.
|
||||
func (d *DB) Query(query string, params ...interface{}) ([]map[string]String, error) {
|
||||
return d.query(query, false, params...)
|
||||
}
|
||||
|
||||
// QueryRow queries the database for one row. See sql.DB.QueryRow.
|
||||
func (d *DB) QueryRow(query string, params ...interface{}) (map[string]String, error) {
|
||||
// sql.Row does not have .Columns(), so we can't really use db.QueryRow.
|
||||
// Instead, we use .query, telling it to return after the first row is extracted.
|
||||
m, err := d.query(query, true, params...)
|
||||
if len(m) > 0 {
|
||||
return m[0], err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (d *DB) query(query string, only1 bool, params ...interface{}) ([]map[string]String, error) {
|
||||
rows, err := d.DB.Query(query, params...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
cols, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var returnSlice []map[string]String
|
||||
for rows.Next() {
|
||||
m, args := buildMapAndArgsSlice(cols)
|
||||
err := rows.Scan(args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
returnSlice = append(returnSlice, depointify(m))
|
||||
if only1 {
|
||||
return returnSlice, rows.Err()
|
||||
}
|
||||
}
|
||||
return returnSlice, rows.Err()
|
||||
}
|
||||
|
||||
func buildMapAndArgsSlice(cols []string) (map[string]*string, []interface{}) {
|
||||
m := make(map[string]*string, len(cols))
|
||||
sl := make([]interface{}, 0, len(cols))
|
||||
for _, col := range cols {
|
||||
var newS string
|
||||
m[col] = &newS
|
||||
sl = append(sl, &newS)
|
||||
}
|
||||
return m, sl
|
||||
}
|
||||
|
||||
func depointify(from map[string]*string) map[string]String {
|
||||
m := make(map[string]String, len(from))
|
||||
for k, v := range from {
|
||||
if v == nil {
|
||||
v = new(string)
|
||||
}
|
||||
m[k] = String(*v)
|
||||
}
|
||||
return m
|
||||
}
|
72
vendor/github.com/thehowl/qsql/qsql_test.go
generated
vendored
Normal file
72
vendor/github.com/thehowl/qsql/qsql_test.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package qsql_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/thehowl/qsql"
|
||||
)
|
||||
|
||||
/*
|
||||
database:
|
||||
|
||||
CREATE DATABASE qsql;
|
||||
USE qsql;
|
||||
CREATE TABLE qsql_test(
|
||||
id INT(11) NOT NULL AUTO_INCREMENT,
|
||||
potato VARCHAR(128) NOT NULL,
|
||||
apple VARCHAR(128) NOT NULL,
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
INSERT INTO qsql_test(potato, apple) VALUES ("test", "test");
|
||||
*/
|
||||
|
||||
func TestQuery(t *testing.T) {
|
||||
db, err := qsql.Open("mysql", "root@/qsql")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
data, err := db.Query("SELECT * FROM qsql_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, row := range data {
|
||||
if row["potato"] != "test" || row["apple"] != "test" {
|
||||
t.Fatal("Expected row to have potato=test and apple=test, got", row, "instead")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryRow(t *testing.T) {
|
||||
db, err := qsql.Open("mysql", "root@/qsql")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
row, err := db.QueryRow("SELECT * FROM qsql_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if row["potato"] != "test" || row["apple"] != "test" {
|
||||
t.Fatal("Expected row to have potato=test and apple=test, got", row, "instead")
|
||||
}
|
||||
}
|
||||
|
||||
func Example() {
|
||||
db, err := qsql.Open("mysql", "root@/")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer db.Close()
|
||||
row, err := db.QueryRow("SELECT 5 AS test, 1 AS test_bool, 13.37 AS test_float")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf(
|
||||
"test: %d | test_bool: %v | test_float: %.3f\n",
|
||||
row["test"].Int(), row["test_bool"].Bool(), row["test_float"].Float64(),
|
||||
)
|
||||
// Output: test: 5 | test_bool: true | test_float: 13.370
|
||||
}
|
78
vendor/github.com/thehowl/qsql/string.go
generated
vendored
Normal file
78
vendor/github.com/thehowl/qsql/string.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package qsql
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// String is just a string, but it implements numerous functions to convert it to various types.
|
||||
type String string
|
||||
|
||||
// String is a shorthand for string(s).
|
||||
func (s String) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// Int will convert s to an int. It will return 0 if conversion failed, with no error.
|
||||
func (s String) Int() int {
|
||||
r, _ := strconv.ParseInt(string(s), 10, 0)
|
||||
return int(r)
|
||||
}
|
||||
|
||||
// Uint will convert s to an uint. It will return 0 if conversion failed, with no error.
|
||||
func (s String) Uint() uint {
|
||||
r, _ := strconv.ParseUint(string(s), 10, 0)
|
||||
return uint(r)
|
||||
}
|
||||
|
||||
// Int64 will convert s to an int64. It will return 0 if conversion failed, with no error.
|
||||
func (s String) Int64() int64 {
|
||||
r, _ := strconv.ParseInt(string(s), 10, 64)
|
||||
return r
|
||||
}
|
||||
|
||||
// Uint64 will convert s to an uint64. It will return 0 if conversion failed, with no error.
|
||||
func (s String) Uint64() uint64 {
|
||||
r, _ := strconv.ParseUint(string(s), 10, 64)
|
||||
return r
|
||||
}
|
||||
|
||||
// Float64 will convert s to a float64. It will return 0 if conversion failed, with no error.
|
||||
func (s String) Float64() float64 {
|
||||
r, _ := strconv.ParseFloat(string(s), 64)
|
||||
return r
|
||||
}
|
||||
|
||||
// Float32 will convert s to a float32. It will return 0 if conversion failed, with no error.
|
||||
func (s String) Float32() float32 {
|
||||
r, _ := strconv.ParseFloat(string(s), 32)
|
||||
return float32(r)
|
||||
}
|
||||
|
||||
var truthyValues = [...]string{
|
||||
"1",
|
||||
"t",
|
||||
"true",
|
||||
"y",
|
||||
"yes",
|
||||
}
|
||||
|
||||
// Bool converts s to a bool.
|
||||
//
|
||||
// The following values are true:
|
||||
//
|
||||
// - 1
|
||||
// - t
|
||||
// - true
|
||||
// - y
|
||||
// - yes
|
||||
//
|
||||
// All other values are false.
|
||||
// Bool is not case sensitive.
|
||||
func (s String) Bool() bool {
|
||||
for _, el := range truthyValues {
|
||||
if string(s) == el {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
Reference in New Issue
Block a user