summaryrefslogtreecommitdiff
path: root/libgo/go/encoding/json
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-12-13 19:16:27 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-12-13 19:16:27 +0000
commit43eb1b72e5730064410a2d81e3f8d78ab62776cb (patch)
treec5132538d5da85ed816c7e1f9d93c4a503b838ab /libgo/go/encoding/json
parente27d80f7754f29f038c29ddcb2decd894d3e4aa4 (diff)
downloadgcc-43eb1b72e5730064410a2d81e3f8d78ab62776cb.tar.gz
libgo: Update to weekly.2011-12-02.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182295 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/encoding/json')
-rw-r--r--libgo/go/encoding/json/encode.go89
1 files changed, 66 insertions, 23 deletions
diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go
index 35964c5d9c2..14284f50e47 100644
--- a/libgo/go/encoding/json/encode.go
+++ b/libgo/go/encoding/json/encode.go
@@ -16,6 +16,7 @@ import (
"runtime"
"sort"
"strconv"
+ "sync"
"unicode"
"unicode/utf8"
)
@@ -295,28 +296,10 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
case reflect.Struct:
e.WriteByte('{')
- t := v.Type()
- n := v.NumField()
first := true
- for i := 0; i < n; i++ {
- f := t.Field(i)
- if f.PkgPath != "" {
- continue
- }
- tag, omitEmpty, quoted := f.Name, false, false
- if tv := f.Tag.Get("json"); tv != "" {
- if tv == "-" {
- continue
- }
- name, opts := parseTag(tv)
- if isValidTag(name) {
- tag = name
- }
- omitEmpty = opts.Contains("omitempty")
- quoted = opts.Contains("string")
- }
- fieldValue := v.Field(i)
- if omitEmpty && isEmptyValue(fieldValue) {
+ for _, ef := range encodeFields(v.Type()) {
+ fieldValue := v.Field(ef.i)
+ if ef.omitEmpty && isEmptyValue(fieldValue) {
continue
}
if first {
@@ -324,9 +307,9 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
} else {
e.WriteByte(',')
}
- e.string(tag)
+ e.string(ef.tag)
e.WriteByte(':')
- e.reflectValueQuoted(fieldValue, quoted)
+ e.reflectValueQuoted(fieldValue, ef.quoted)
}
e.WriteByte('}')
@@ -470,3 +453,63 @@ func (e *encodeState) string(s string) (int, error) {
e.WriteByte('"')
return e.Len() - len0, nil
}
+
+// encodeField contains information about how to encode a field of a
+// struct.
+type encodeField struct {
+ i int // field index in struct
+ tag string
+ quoted bool
+ omitEmpty bool
+}
+
+var (
+ typeCacheLock sync.RWMutex
+ encodeFieldsCache = make(map[reflect.Type][]encodeField)
+)
+
+// encodeFields returns a slice of encodeField for a given
+// struct type.
+func encodeFields(t reflect.Type) []encodeField {
+ typeCacheLock.RLock()
+ fs, ok := encodeFieldsCache[t]
+ typeCacheLock.RUnlock()
+ if ok {
+ return fs
+ }
+
+ typeCacheLock.Lock()
+ defer typeCacheLock.Unlock()
+ fs, ok = encodeFieldsCache[t]
+ if ok {
+ return fs
+ }
+
+ v := reflect.Zero(t)
+ n := v.NumField()
+ for i := 0; i < n; i++ {
+ f := t.Field(i)
+ if f.PkgPath != "" {
+ continue
+ }
+ var ef encodeField
+ ef.i = i
+ ef.tag = f.Name
+
+ tv := f.Tag.Get("json")
+ if tv != "" {
+ if tv == "-" {
+ continue
+ }
+ name, opts := parseTag(tv)
+ if isValidTag(name) {
+ ef.tag = name
+ }
+ ef.omitEmpty = opts.Contains("omitempty")
+ ef.quoted = opts.Contains("string")
+ }
+ fs = append(fs, ef)
+ }
+ encodeFieldsCache[t] = fs
+ return fs
+}