Susumu Yata
null+****@clear*****
Tue Jun 20 23:55:39 JST 2017
Susumu Yata 2017-06-20 23:55:39 +0900 (Tue, 20 Jun 2017) New Revision: ab8e4cf41dab919572ef747db06d7fb35af6371e https://github.com/groonga/grnci/commit/ab8e4cf41dab919572ef747db06d7fb35af6371e Message: Improve encoding in v2. Modified files: v2/db.go v2/db_test.go v2/type.go Modified: v2/db.go (+7 -68) =================================================================== --- v2/db.go 2017-06-19 11:40:35 +0900 (0709b5b) +++ v2/db.go 2017-06-20 23:55:39 +0900 (ba8ae4a) @@ -6,8 +6,8 @@ import ( "fmt" "io" "io/ioutil" + "log" "reflect" - "strconv" "strings" "time" ) @@ -450,51 +450,6 @@ func (db *DB) Load(tbl string, values io.Reader, options *DBLoadOptions) (int, R return db.recvInt(resp) } -// encodeValue encodes a value. -func (db *DB) encodeValue(body []byte, v reflect.Value) []byte { - for v.Kind() == reflect.Ptr { - if v.IsNil() { - return append(body, "null"...) - } - v = v.Elem() - } - switch v := v.Interface().(type) { - case bool: - return strconv.AppendBool(body, v) - case int: - return strconv.AppendInt(body, int64(v), 10) - case int8: - return strconv.AppendInt(body, int64(v), 10) - case int16: - return strconv.AppendInt(body, int64(v), 10) - case int32: - return strconv.AppendInt(body, int64(v), 10) - case int64: - return strconv.AppendInt(body, v, 10) - case uint: - return strconv.AppendUint(body, uint64(v), 10) - case uint8: - return strconv.AppendUint(body, uint64(v), 10) - case uint16: - return strconv.AppendUint(body, uint64(v), 10) - case uint32: - return strconv.AppendUint(body, uint64(v), 10) - case uint64: - return strconv.AppendUint(body, v, 10) - case float32: - return strconv.AppendFloat(body, float64(v), 'e', -1, 32) - case float64: - return strconv.AppendFloat(body, v, 'e', -1, 64) - case string: - b, _ := json.Marshal(v) - return append(body, b...) - case time.Time: - return strconv.AppendFloat(body, float64(v.UnixNano())/1000000000.0, 'f', -1, 64) - default: - return body - } -} - // encodeRow encodes a row. func (db *DB) encodeRow(body []byte, row reflect.Value, fis []*StructFieldInfo) []byte { body = append(body, '[') @@ -502,27 +457,7 @@ func (db *DB) encodeRow(body []byte, row reflect.Value, fis []*StructFieldInfo) if i != 0 { body = append(body, ',') } - v := row.Field(fi.Index) - if v.Kind() == reflect.Ptr { - if v.IsNil() { - body = append(body, "null"...) - continue - } - v = v.Elem() - } - switch v.Kind() { - case reflect.Array, reflect.Slice: - body = append(body, '[') - for i := 0; i < v.Len(); i++ { - if i != 0 { - body = append(body, ',') - } - body = db.encodeValue(body, v.Index(i)) - } - body = append(body, ']') - default: - body = db.encodeValue(body, v) - } + body = encodeValue(body, row.Field(fi.Index)) } body = append(body, ']') return body @@ -538,6 +473,7 @@ func (db *DB) encodeRows(body []byte, rows reflect.Value, fis []*StructFieldInfo row := rows.Index(i) body = db.encodeRow(body, row, fis) } + log.Printf("body = %s", body) return body } @@ -1419,7 +1355,10 @@ func (db *DB) SelectRows(tbl string, rows interface{}, options *DBSelectOptions) defer resp.Close() data, err := ioutil.ReadAll(resp) if err != nil { - return 0, nil, err + return 0, resp, err + } + if resp.Err() != nil { + return 0, resp, err } n, err := db.parseRows(rows, data, fis) return n, resp, err Modified: v2/db_test.go (+32 -32) =================================================================== --- v2/db_test.go 2017-06-19 11:40:35 +0900 (7033029) +++ v2/db_test.go 2017-06-20 23:55:39 +0900 (d8baf09) @@ -135,47 +135,47 @@ func TestDBLoadRows(t *testing.T) { defer db.Close() type Row struct { - Key string `grnci:"_key"` - Bool bool `grnci:"bool"` - Int int `grnci:"int"` - Int8 int8 `grnci:"int8"` - Int16 int16 `grnci:"int16"` - Int32 int32 `grnci:"int32"` - Int64 int64 `grnci:"int64"` - UInt uint `grnci:"uint"` - UInt8 uint8 `grnci:"uint8"` - UInt16 uint16 `grnci:"uint16"` - UInt32 uint32 `grnci:"uint32"` - UInt64 uint64 `grnci:"uint64"` - Float32 float32 `grnci:"float32"` - Float64 float64 `grnci:"float64"` - String string `grnci:"string"` - Time time.Time `grnci:"time"` - BoolSlice []bool `grnci:"bool_slice"` - IntSlice []int `grnci:"int_slice"` - Int8Slice []int8 `grnci:"int8_slice"` - Int16Slice []int16 `grnci:"int16_slice"` - Int32Slice []int32 `grnci:"int32_slice"` - Int64Slice []int64 `grnci:"int64_slice"` - UIntSlice []uint `grnci:"uint_slice"` - UInt8Slice []uint8 `grnci:"uint8_slice"` - UInt16Slice []uint16 `grnci:"uint16_slice"` - UInt32Slice []uint32 `grnci:"uint32_slice"` - UInt64Slice []uint64 `grnci:"uint64_slice"` - Float32Slice []float32 `grnci:"float32_slice"` - Float64Slice []float64 `grnci:"float64_slice"` - StringSlice []string `grnci:"string_slice"` - TimeSlice []time.Time `grnci:"time_slice"` + Key string `grnci:"_key"` + Bool bool `grnci:"bool"` + Int int `grnci:"int"` + Int8 int8 `grnci:"int8"` + Int16 int16 `grnci:"int16"` + Int32 int32 `grnci:"int32"` + Int64 int64 `grnci:"int64"` + UInt uint `grnci:"uint"` + UInt8 uint8 `grnci:"uint8"` + UInt16 uint16 `grnci:"uint16"` + UInt32 uint32 `grnci:"uint32"` + UInt64 uint64 `grnci:"uint64"` + Float float64 `grnci:"float64"` + String string `grnci:"string"` + Time time.Time `grnci:"time"` + BoolSlice []bool `grnci:"bool_slice"` + IntSlice []int `grnci:"int_slice"` + Int8Slice []int8 `grnci:"int8_slice"` + Int16Slice []int16 `grnci:"int16_slice"` + Int32Slice []int32 `grnci:"int32_slice"` + Int64Slice []int64 `grnci:"int64_slice"` + UIntSlice []uint `grnci:"uint_slice"` + UInt8Slice []uint8 `grnci:"uint8_slice"` + UInt16Slice []uint16 `grnci:"uint16_slice"` + UInt32Slice []uint32 `grnci:"uint32_slice"` + UInt64Slice []uint64 `grnci:"uint64_slice"` + FloatSlice []float64 `grnci:"float64_slice"` + StringSlice []string `grnci:"string_slice"` + TimeSlice []time.Time `grnci:"time_slice"` } rows := []Row{ Row{ - Key: "Appke", + Key: "Apple", Time: time.Now(), + Float: 1.23, StringSlice: []string{"iOS", "Safari"}, }, Row{ Key: "Microsoft", Time: time.Now(), + Float: 4.56, StringSlice: []string{"Windows", "Edge"}, }, } Modified: v2/type.go (+182 -1) =================================================================== --- v2/type.go 2017-06-19 11:40:35 +0900 (86ab078) +++ v2/type.go 2017-06-20 23:55:39 +0900 (3c6d48f) @@ -1,7 +1,188 @@ package grnci -// Geo represents TokyoGeoPoint and WGS84GeoPoint. +import ( + "reflect" + "strconv" + "time" +) + +// Geo represents a TokyoGeoPoint or WGS84GeoPoint. type Geo struct { Lat int32 // Latitude in milliseconds. Long int32 // Longitude in milliseconds. } + +// encodeBool encodes the JSON-encoded v to buf and returns the extended buffer. +func encodeBool(buf []byte, v bool) []byte { + return strconv.AppendBool(buf, v) +} + +// encodeInt encodes the JSON-encoded v to buf and returns the extended buffer. +func encodeInt(buf []byte, v int64) []byte { + return strconv.AppendInt(buf, v, 10) +} + +// encodeUint encodes the JSON-encoded v to buf and returns the extended buffer. +func encodeUint(buf []byte, v uint64) []byte { + return strconv.AppendUint(buf, v, 10) +} + +// encodeFloat encodes the JSON-encoded v to buf and returns the extended buffer. +func encodeFloat(buf []byte, v float64) []byte { + return strconv.AppendFloat(buf, v, 'g', -1, 64) +} + +// encodeString encodes the JSON-encoded v to buf and returns the extended buffer. +func encodeString(buf []byte, v string) []byte { + buf = append(buf, '"') + for i := 0; i < len(v); i++ { + switch v[i] { + case '\b', '\t', '\n', '\f', '\r', '"', '\\': + buf = append(buf, '\\') + } + buf = append(buf, v[i]) + } + return append(buf, '"') +} + +// encodeTime encodes the JSON-encoded v to buf and returns the extended buffer. +func encodeTime(buf []byte, v time.Time) []byte { + buf = strconv.AppendInt(buf, v.Unix(), 10) + usec := v.Nanosecond() / 1000 + if usec != 0 { + buf = append(buf, '.') + n := len(buf) + if cap(buf) < n+6 { + newBuf := make([]byte, n+6, cap(buf)*2) + copy(newBuf, buf) + buf = newBuf + } else { + buf = buf[:n+6] + } + for i := 0; i < 6; i++ { + buf[n+5-i] = byte('0' + usec%10) + usec /= 10 + } + } + return buf +} + +// encodeGeo encodes the JSON-encoded v to buf and returns the extended buffer. +func encodeGeo(buf []byte, v Geo) []byte { + buf = append(buf, '"') + buf = strconv.AppendInt(buf, int64(v.Lat), 10) + buf = append(buf, ',') + buf = strconv.AppendInt(buf, int64(v.Long), 10) + return append(buf, '"') +} + +// encodeValue encodes the JSON-encoded v to buf and returns the extended buffer. +func encodeValue(buf []byte, v reflect.Value) []byte { + switch v.Kind() { + case reflect.Bool: + return encodeBool(buf, v.Bool()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return encodeInt(buf, v.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return encodeUint(buf, v.Uint()) + case reflect.Float64: + return encodeFloat(buf, v.Float()) + case reflect.String: + return encodeString(buf, v.String()) + case reflect.Struct: + switch v := v.Interface().(type) { + case time.Time: + return encodeTime(buf, v) + case Geo: + return encodeGeo(buf, v) + default: + return append(buf, "null"...) + } + case reflect.Ptr: + if v.IsNil() { + return append(buf, "null"...) + } + return encodeValue(buf, v.Elem()) + case reflect.Array: + buf = append(buf, '[') + n := v.Len() + for i := 0; i < n; i++ { + if i != 0 { + buf = append(buf, ',') + } + buf = encodeValue(buf, v.Index(i)) + } + return append(buf, ']') + case reflect.Slice: + if v.IsNil() { + return append(buf, "null"...) + } + buf = append(buf, '[') + n := v.Len() + for i := 0; i < n; i++ { + if i != 0 { + buf = append(buf, ',') + } + buf = encodeValue(buf, v.Index(i)) + } + return append(buf, ']') + default: + return append(buf, "null"...) + } +} + +// // encodeBoolPtr encodes the JSON-encoded v to buf and returns the extended buffer. +// func encodeBoolPtr(buf []byte, v *bool) []byte { +// if v == nil { +// return append(buf, "null"...) +// } +// return encodeBool(buf, *v) +// } + +// // encodeIntPtr encodes the JSON-encoded v to buf and returns the extended buffer. +// func encodeIntPtr(buf []byte, v *int64) []byte { +// if v == nil { +// return append(buf, "null"...) +// } +// return encodeInt(buf, *v) +// } + +// // encodeUintPtr encodes the JSON-encoded v to buf and returns the extended buffer. +// func encodeUintPtr(buf []byte, v *uint64) []byte { +// if v == nil { +// return append(buf, "null"...) +// } +// return encodeUint(buf, *v) +// } + +// // encodeFloatPtr encodes the JSON-encoded v to buf and returns the extended buffer. +// func encodeFloatPtr(buf []byte, v *float64) []byte { +// if v == nil { +// return append(buf, "null"...) +// } +// return encodeFloat(buf, *v) +// } + +// // encodeStringPtr encodes the JSON-encoded v to buf and returns the extended buffer. +// func encodeStringPtr(buf []byte, v *string) []byte { +// if v == nil { +// return append(buf, "null"...) +// } +// return encodeString(buf, *v) +// } + +// // encodeTimePtr encodes the JSON-encoded v to buf and returns the extended buffer. +// func encodeTimePtr(buf []byte, v *time.Time) []byte { +// if v == nil { +// return append(buf, "null"...) +// } +// return encodeTime(buf, *v) +// } + +// // encodeGeoPtr encodes the JSON-encoded v to buf and returns the extended buffer. +// func encodeGeoPtr(buf []byte, v *Geo) []byte { +// if v == nil { +// return append(buf, "null"...) +// } +// return encodeGeo(buf, *v) +// } -------------- next part -------------- HTML����������������������������...Download