Enable sorting of negative numbers and floats

This commit is contained in:
Tobie Morgan Hitchcock 2016-10-14 07:14:34 +01:00
parent fdb639e517
commit 40a52dfbf1
3 changed files with 90 additions and 101 deletions

View file

@ -220,10 +220,10 @@ func TestMain(t *testing.T) {
IB: true, IB: true,
IF: false, IF: false,
IT: clock, IT: clock,
II: float64(19387), II: float64(19387.1),
ID: float64(183784.13413), ID: float64(183784.13413),
INA: []interface{}{true, false, nil, "Test", clock, float64(192), 1.1, 1.2, 1.3}, INA: []interface{}{true, false, nil, "Test", clock, int64(192), 1.1, 1.2, 1.3},
AIN: []interface{}{true, false, nil, "Test", clock, float64(192), float64(MaxNumber), 1.1, 1.2, 1.3, []interface{}{"Test"}}, AIN: []interface{}{true, false, nil, "Test", clock, int64(192), 1.1, 1.2, 1.3, []interface{}{"Test"}},
}, },
}, },
} }
@ -236,12 +236,12 @@ func TestMain(t *testing.T) {
&Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: nil}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: nil},
&Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: false}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: false},
&Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: true}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: true},
// &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -9223372036854775807}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -9223372036854775807},
// &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -2147483647}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -2147483647},
// &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -32767}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -32767},
// &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -12}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -12},
// &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -2}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -2},
// &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -1}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -1},
&Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: 0}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: 0},
&Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: 1}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: 1},
&Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: 2}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: 2},

View file

@ -18,6 +18,7 @@ import (
"bufio" "bufio"
"encoding/binary" "encoding/binary"
"io" "io"
"math"
"time" "time"
) )
@ -122,66 +123,84 @@ func (r *reader) FindString() (val string) {
return return
} }
func (r *reader) FindNumber() (val float64) { func (r *reader) FindNumber() (val interface{}) {
if r.ReadNext(cNUMBER) { var dec uint64
if r.ReadNext(cNILL) { var num float64
binary.Read(r.Reader, binary.BigEndian, &val) if r.ReadNext(cNEG) {
val = 0 - val binary.Read(r.Reader, binary.BigEndian, &dec)
r.ReadNext(cTERM) num = math.Float64frombits(^dec)
} else if r.ReadNext(cBOOL) { r.ReadNext(cEND)
binary.Read(r.Reader, binary.BigEndian, &val) } else if r.ReadNext(cPOS) {
r.ReadNext(cTERM) binary.Read(r.Reader, binary.BigEndian, &dec)
num = math.Float64frombits(dec)
r.ReadNext(cEND)
} }
if math.Trunc(num) == num {
return int64(math.Trunc(num))
}
return num
}
func (r *reader) FindDouble() (val float64) {
var dec uint64
if r.ReadNext(cNEG) {
binary.Read(r.Reader, binary.BigEndian, &dec)
val = math.Float64frombits(^dec)
r.ReadNext(cEND)
} else if r.ReadNext(cPOS) {
binary.Read(r.Reader, binary.BigEndian, &dec)
val = math.Float64frombits(dec)
r.ReadNext(cEND)
} }
return return
} }
func (r *reader) FindNumberInt() (val int) { func (r *reader) FindNumberInt() (val int) {
return int(r.FindNumber()) return int(r.FindDouble())
} }
func (r *reader) FindNumberInt8() (val int8) { func (r *reader) FindNumberInt8() (val int8) {
return int8(r.FindNumber()) return int8(r.FindDouble())
} }
func (r *reader) FindNumberInt16() (val int16) { func (r *reader) FindNumberInt16() (val int16) {
return int16(r.FindNumber()) return int16(r.FindDouble())
} }
func (r *reader) FindNumberInt32() (val int32) { func (r *reader) FindNumberInt32() (val int32) {
return int32(r.FindNumber()) return int32(r.FindDouble())
} }
func (r *reader) FindNumberInt64() (val int64) { func (r *reader) FindNumberInt64() (val int64) {
return int64(r.FindNumber()) return int64(r.FindDouble())
} }
func (r *reader) FindNumberUint() (val uint) { func (r *reader) FindNumberUint() (val uint) {
return uint(r.FindNumber()) return uint(r.FindDouble())
} }
func (r *reader) FindNumberUint8() (val uint8) { func (r *reader) FindNumberUint8() (val uint8) {
return uint8(r.FindNumber()) return uint8(r.FindDouble())
} }
func (r *reader) FindNumberUint16() (val uint16) { func (r *reader) FindNumberUint16() (val uint16) {
return uint16(r.FindNumber()) return uint16(r.FindDouble())
} }
func (r *reader) FindNumberUint32() (val uint32) { func (r *reader) FindNumberUint32() (val uint32) {
return uint32(r.FindNumber()) return uint32(r.FindDouble())
} }
func (r *reader) FindNumberUint64() (val uint64) { func (r *reader) FindNumberUint64() (val uint64) {
return uint64(r.FindNumber()) return uint64(r.FindDouble())
} }
func (r *reader) FindNumberFloat32() (val float32) { func (r *reader) FindNumberFloat32() (val float32) {
return float32(r.FindNumber()) return float32(r.FindDouble())
} }
func (r *reader) FindNumberFloat64() (val float64) { func (r *reader) FindNumberFloat64() (val float64) {
return float64(r.FindNumber()) return float64(r.FindDouble())
} }
func (r *reader) FindArray() (val []interface{}) { func (r *reader) FindArray() (val []interface{}) {

View file

@ -17,7 +17,10 @@ package keys
import ( import (
"encoding/binary" "encoding/binary"
"io" "io"
"math"
"reflect"
"time" "time"
"unsafe"
) )
type writer struct { type writer struct {
@ -38,94 +41,61 @@ func (w *writer) Write(i interface{}) {
w.Writer.Write(v) w.Writer.Write(v)
case string: case string:
w.Writer.Write([]byte(v)) w.writeString(v)
case time.Time: case time.Time:
binary.Write(w.Writer, binary.BigEndian, v.UnixNano()) w.writeTime(v)
case uint: case uint:
w.Write(bBOOL) w.writeNumber(float64(v))
binary.Write(w.Writer, binary.BigEndian, float64(v))
case uint8: case uint8:
w.Write(bBOOL) w.writeNumber(float64(v))
binary.Write(w.Writer, binary.BigEndian, float64(v))
case uint16: case uint16:
w.Write(bBOOL) w.writeNumber(float64(v))
binary.Write(w.Writer, binary.BigEndian, float64(v))
case uint32: case uint32:
w.Write(bBOOL) w.writeNumber(float64(v))
binary.Write(w.Writer, binary.BigEndian, float64(v))
case uint64: case uint64:
w.Write(bBOOL) w.writeNumber(float64(v))
binary.Write(w.Writer, binary.BigEndian, float64(v))
case int: case int:
if v < 0 { w.writeNumber(float64(v))
w.Write(bNILL)
binary.Write(w.Writer, binary.BigEndian, 0-float64(v))
} else {
w.Write(bBOOL)
binary.Write(w.Writer, binary.BigEndian, float64(v))
}
case int8: case int8:
if v < 0 { w.writeNumber(float64(v))
w.Write(bNILL)
binary.Write(w.Writer, binary.BigEndian, 0-float64(v))
} else {
w.Write(bBOOL)
binary.Write(w.Writer, binary.BigEndian, float64(v))
}
case int16: case int16:
if v < 0 { w.writeNumber(float64(v))
w.Write(bNILL)
binary.Write(w.Writer, binary.BigEndian, 0-float64(v))
} else {
w.Write(bBOOL)
binary.Write(w.Writer, binary.BigEndian, float64(v))
}
case int32: case int32:
if v < 0 { w.writeNumber(float64(v))
w.Write(bNILL)
binary.Write(w.Writer, binary.BigEndian, 0-float64(v))
} else {
w.Write(bBOOL)
binary.Write(w.Writer, binary.BigEndian, float64(v))
}
case int64: case int64:
if v < 0 { w.writeNumber(float64(v))
w.Write(bNILL)
binary.Write(w.Writer, binary.BigEndian, 0-float64(v))
} else {
w.Write(bBOOL)
binary.Write(w.Writer, binary.BigEndian, float64(v))
}
case float32: case float32:
if v < 0 { w.writeNumber(float64(v))
w.Write(bNILL)
binary.Write(w.Writer, binary.BigEndian, 0-float64(v))
} else {
w.Write(bBOOL)
binary.Write(w.Writer, binary.BigEndian, float64(v))
}
case float64: case float64:
w.writeNumber(float64(v))
}
}
func (w *writer) writeString(v string) {
b := *(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&v))))
w.Write(b)
}
func (w *writer) writeTime(v time.Time) {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, uint64(v.UTC().UnixNano()))
w.Write(b)
}
func (w *writer) writeNumber(v float64) {
b := make([]byte, 8)
if v < 0 { if v < 0 {
w.Write(bNILL) w.Write(bNEG)
binary.Write(w.Writer, binary.BigEndian, 0-float64(v)) binary.BigEndian.PutUint64(b, ^math.Float64bits(v))
} else { } else {
w.Write(bBOOL) w.Write(bPOS)
binary.Write(w.Writer, binary.BigEndian, float64(v)) binary.BigEndian.PutUint64(b, math.Float64bits(v))
} }
w.Write(b)
}
} }