2018-03-28 00:30:51 +00:00
|
|
|
package influx
|
2016-11-22 12:51:57 +00:00
|
|
|
|
|
|
|
import (
|
2018-03-28 00:30:51 +00:00
|
|
|
"bytes"
|
2016-11-22 12:51:57 +00:00
|
|
|
"reflect"
|
|
|
|
"strconv"
|
2018-03-28 00:30:51 +00:00
|
|
|
"strings"
|
2016-11-22 12:51:57 +00:00
|
|
|
"unsafe"
|
|
|
|
)
|
|
|
|
|
2018-03-28 00:30:51 +00:00
|
|
|
const (
|
|
|
|
escapes = " ,="
|
|
|
|
nameEscapes = " ,"
|
|
|
|
stringFieldEscapes = `\"`
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
unescaper = strings.NewReplacer(
|
|
|
|
`\,`, `,`,
|
|
|
|
`\"`, `"`, // ???
|
|
|
|
`\ `, ` `,
|
|
|
|
`\=`, `=`,
|
|
|
|
)
|
|
|
|
|
|
|
|
nameUnescaper = strings.NewReplacer(
|
|
|
|
`\,`, `,`,
|
|
|
|
`\ `, ` `,
|
|
|
|
)
|
|
|
|
|
|
|
|
stringFieldUnescaper = strings.NewReplacer(
|
|
|
|
`\"`, `"`,
|
|
|
|
`\\`, `\`,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
func unescape(b []byte) string {
|
|
|
|
if bytes.ContainsAny(b, escapes) {
|
|
|
|
return unescaper.Replace(unsafeBytesToString(b))
|
|
|
|
} else {
|
|
|
|
return string(b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func nameUnescape(b []byte) string {
|
|
|
|
if bytes.ContainsAny(b, nameEscapes) {
|
|
|
|
return nameUnescaper.Replace(unsafeBytesToString(b))
|
|
|
|
} else {
|
|
|
|
return string(b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func stringFieldUnescape(b []byte) string {
|
|
|
|
if bytes.ContainsAny(b, stringFieldEscapes) {
|
|
|
|
return stringFieldUnescaper.Replace(unsafeBytesToString(b))
|
|
|
|
} else {
|
|
|
|
return string(b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-22 12:51:57 +00:00
|
|
|
// parseIntBytes is a zero-alloc wrapper around strconv.ParseInt.
|
|
|
|
func parseIntBytes(b []byte, base int, bitSize int) (i int64, err error) {
|
|
|
|
s := unsafeBytesToString(b)
|
|
|
|
return strconv.ParseInt(s, base, bitSize)
|
|
|
|
}
|
|
|
|
|
|
|
|
// parseFloatBytes is a zero-alloc wrapper around strconv.ParseFloat.
|
|
|
|
func parseFloatBytes(b []byte, bitSize int) (float64, error) {
|
|
|
|
s := unsafeBytesToString(b)
|
|
|
|
return strconv.ParseFloat(s, bitSize)
|
|
|
|
}
|
|
|
|
|
|
|
|
// parseBoolBytes is a zero-alloc wrapper around strconv.ParseBool.
|
|
|
|
func parseBoolBytes(b []byte) (bool, error) {
|
|
|
|
return strconv.ParseBool(unsafeBytesToString(b))
|
|
|
|
}
|
|
|
|
|
|
|
|
// unsafeBytesToString converts a []byte to a string without a heap allocation.
|
|
|
|
//
|
|
|
|
// It is unsafe, and is intended to prepare input to short-lived functions
|
|
|
|
// that require strings.
|
|
|
|
func unsafeBytesToString(in []byte) string {
|
|
|
|
src := *(*reflect.SliceHeader)(unsafe.Pointer(&in))
|
|
|
|
dst := reflect.StringHeader{
|
|
|
|
Data: src.Data,
|
|
|
|
Len: src.Len,
|
|
|
|
}
|
|
|
|
s := *(*string)(unsafe.Pointer(&dst))
|
|
|
|
return s
|
|
|
|
}
|