[Groonga-commit] groonga/grnci at ab8e4cf [master] Improve encoding in v2.

Back to archive index

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 



More information about the Groonga-commit mailing list
Back to archive index