diff options
Diffstat (limited to 'src/lib/json')
| -rw-r--r-- | src/lib/json/Makefile | 69 | ||||
| -rw-r--r-- | src/lib/json/generic.go | 331 | ||||
| -rw-r--r-- | src/lib/json/generic_test.go | 76 | ||||
| -rw-r--r-- | src/lib/json/parse.go | 419 | ||||
| -rw-r--r-- | src/lib/json/struct.go | 269 | ||||
| -rw-r--r-- | src/lib/json/struct_test.go | 82 |
6 files changed, 0 insertions, 1246 deletions
diff --git a/src/lib/json/Makefile b/src/lib/json/Makefile deleted file mode 100644 index 2d70c2cf8..000000000 --- a/src/lib/json/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# DO NOT EDIT. Automatically generated by gobuild. -# gobuild -m >Makefile - -D= - -include $(GOROOT)/src/Make.$(GOARCH) -AR=gopack - -default: packages - -clean: - rm -rf *.[$(OS)] *.a [$(OS)].out _obj - -test: packages - gotest - -coverage: packages - gotest - 6cov -g `pwd` | grep -v '_test\.go:' - -%.$O: %.go - $(GC) -I_obj $*.go - -%.$O: %.c - $(CC) $*.c - -%.$O: %.s - $(AS) $*.s - -O1=\ - parse.$O\ - -O2=\ - generic.$O\ - struct.$O\ - - -phases: a1 a2 -_obj$D/json.a: phases - -a1: $(O1) - $(AR) grc _obj$D/json.a parse.$O - rm -f $(O1) - -a2: $(O2) - $(AR) grc _obj$D/json.a generic.$O struct.$O - rm -f $(O2) - - -newpkg: clean - mkdir -p _obj$D - $(AR) grc _obj$D/json.a - -$(O1): newpkg -$(O2): a1 -$(O3): a2 - -nuke: clean - rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/json.a - -packages: _obj$D/json.a - -install: packages - test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D - cp _obj$D/json.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/json.a diff --git a/src/lib/json/generic.go b/src/lib/json/generic.go deleted file mode 100644 index e3194eb17..000000000 --- a/src/lib/json/generic.go +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Generic representation of JSON objects. - -package json - -import ( - "container/vector"; - "fmt"; - "json"; - "math"; - "strconv"; - "strings"; -) - -// Integers identifying the data type in the Json interface. -const ( - StringKind = iota; - NumberKind; - MapKind; // JSON term is "Object", but in Go, it's a map - ArrayKind; - BoolKind; - NullKind; -) - -// The Json interface is implemented by all JSON objects. -type Json interface { - Kind() int; // StringKind, NumberKind, etc. - String() string; // a string form (any kind) - Number() float64; // numeric form (NumberKind) - Bool() bool; // boolean (BoolKind) - Get(s string) Json; // field lookup (MapKind) - Elem(i int) Json; // element lookup (ArrayKind) - Len() int; // length (ArrayKind, MapKind) -} - -// JsonToString returns the textual JSON syntax representation -// for the JSON object j. -// -// JsonToString differs from j.String() in the handling -// of string objects. If j represents the string abc, -// j.String() == `abc`, but JsonToString(j) == `"abc"`. -func JsonToString(j Json) string { - if j == nil { - return "null" - } - if j.Kind() == StringKind { - return Quote(j.String()) - } - return j.String() -} - -type _Null struct { } - -// Null is the JSON object representing the null data object. -var Null Json = &_Null{} - -func (*_Null) Kind() int { return NullKind } -func (*_Null) String() string { return "null" } -func (*_Null) Number() float64 { return 0 } -func (*_Null) Bool() bool { return false } -func (*_Null) Get(s string) Json { return Null } -func (*_Null) Elem(int) Json { return Null } -func (*_Null) Len() int { return 0 } - -type _String struct { s string; _Null } -func (j *_String) Kind() int { return StringKind } -func (j *_String) String() string { return j.s } - -type _Number struct { f float64; _Null } -func (j *_Number) Kind() int { return NumberKind } -func (j *_Number) Number() float64 { return j.f } -func (j *_Number) String() string { - if math.Floor(j.f) == j.f { - return fmt.Sprintf("%.0f", j.f); - } - return fmt.Sprintf("%g", j.f); -} - -type _Array struct { a *vector.Vector; _Null } -func (j *_Array) Kind() int { return ArrayKind } -func (j *_Array) Len() int { return j.a.Len() } -func (j *_Array) Elem(i int) Json { - if i < 0 || i >= j.a.Len() { - return Null - } - return j.a.At(i).(Json) -} -func (j *_Array) String() string { - s := "["; - for i := 0; i < j.a.Len(); i++ { - if i > 0 { - s += ","; - } - s += JsonToString(j.a.At(i).(Json)); - } - s += "]"; - return s; -} - -type _Bool struct { b bool; _Null } -func (j *_Bool) Kind() int { return BoolKind } -func (j *_Bool) Bool() bool { return j.b } -func (j *_Bool) String() string { - if j.b { - return "true" - } - return "false" -} - -type _Map struct { m map[string]Json; _Null } -func (j *_Map) Kind() int { return MapKind } -func (j *_Map) Len() int { return len(j.m) } -func (j *_Map) Get(s string) Json { - if j.m == nil { - return Null - } - v, ok := j.m[s]; - if !ok { - return Null - } - return v; -} -func (j *_Map) String() string { - s := "{"; - first := true; - for k,v := range j.m { - if first { - first = false; - } else { - s += ","; - } - s += Quote(k); - s += ":"; - s += JsonToString(v); - } - s += "}"; - return s; -} - -// Walk evaluates path relative to the JSON object j. -// Path is taken as a sequence of slash-separated field names -// or numbers that can be used to index into JSON map and -// array objects. -// -// For example, if j is the JSON object for -// {"abc": [true, false]}, then Walk(j, "abc/1") returns the -// JSON object for true. -func Walk(j Json, path string) Json { - for len(path) > 0 { - var elem string; - if i := strings.Index(path, "/"); i >= 0 { - elem = path[0:i]; - path = path[i+1:len(path)]; - } else { - elem = path; - path = ""; - } - switch j.Kind() { - case ArrayKind: - indx, err := strconv.Atoi(elem); - if err != nil { - return Null - } - j = j.Elem(indx); - case MapKind: - j = j.Get(elem); - default: - return Null - } - } - return j -} - -// Equal returns whether a and b are indistinguishable JSON objects. -func Equal(a, b Json) bool { - switch { - case a == nil && b == nil: - return true; - case a == nil || b == nil: - return false; - case a.Kind() != b.Kind(): - return false; - } - - switch a.Kind() { - case NullKind: - return true; - case StringKind: - return a.String() == b.String(); - case NumberKind: - return a.Number() == b.Number(); - case BoolKind: - return a.Bool() == b.Bool(); - case ArrayKind: - if a.Len() != b.Len() { - return false; - } - for i := 0; i < a.Len(); i++ { - if !Equal(a.Elem(i), b.Elem(i)) { - return false; - } - } - return true; - case MapKind: - m := a.(*_Map).m; - if len(m) != len(b.(*_Map).m) { - return false; - } - for k,v := range m { - if !Equal(v, b.Get(k)) { - return false; - } - } - return true; - } - - // invalid kind - return false; -} - - -// Parse builder for JSON objects. - -type _JsonBuilder struct { - // either writing to *ptr - ptr *Json; - - // or to a[i] (can't set ptr = &a[i]) - a *vector.Vector; - i int; - - // or to m[k] (can't set ptr = &m[k]) - m map[string] Json; - k string; -} - -func (b *_JsonBuilder) Put(j Json) { - switch { - case b.ptr != nil: - *b.ptr = j; - case b.a != nil: - b.a.Set(b.i, j); - case b.m != nil: - b.m[b.k] = j; - } -} - -func (b *_JsonBuilder) Get() Json { - switch { - case b.ptr != nil: - return *b.ptr; - case b.a != nil: - return b.a.At(b.i).(Json); - case b.m != nil: - return b.m[b.k]; - } - return nil -} - -func (b *_JsonBuilder) Float64(f float64) { - b.Put(&_Number{f, _Null{}}) -} - -func (b *_JsonBuilder) Int64(i int64) { - b.Float64(float64(i)) -} - -func (b *_JsonBuilder) Uint64(i uint64) { - b.Float64(float64(i)) -} - -func (b *_JsonBuilder) Bool(tf bool) { - b.Put(&_Bool{tf, _Null{}}) -} - -func (b *_JsonBuilder) Null() { - b.Put(Null) -} - -func (b *_JsonBuilder) String(s string) { - b.Put(&_String{s, _Null{}}) -} - - -func (b *_JsonBuilder) Array() { - b.Put(&_Array{vector.New(0), _Null{}}) -} - -func (b *_JsonBuilder) Map() { - b.Put(&_Map{make(map[string]Json), _Null{}}) -} - -func (b *_JsonBuilder) Elem(i int) Builder { - bb := new(_JsonBuilder); - bb.a = b.Get().(*_Array).a; - bb.i = i; - for i >= bb.a.Len() { - bb.a.Push(Null) - } - return bb -} - -func (b *_JsonBuilder) Key(k string) Builder { - bb := new(_JsonBuilder); - bb.m = b.Get().(*_Map).m; - bb.k = k; - bb.m[k] = Null; - return bb -} - -// StringToJson parses the string s as a JSON-syntax string -// and returns the generic JSON object representation. -// On success, StringToJson returns with ok set to true and errtok empty. -// If StringToJson encounters a syntax error, it returns with -// ok set to false and errtok set to a fragment of the offending syntax. -func StringToJson(s string) (json Json, ok bool, errtok string) { - var errindx int; - var j Json; - b := new(_JsonBuilder); - b.ptr = &j; - ok, errindx, errtok = Parse(s, b); - if !ok { - return nil, false, errtok - } - return j, true, "" -} - -// BUG(rsc): StringToJson should return an os.Error instead of a bool. diff --git a/src/lib/json/generic_test.go b/src/lib/json/generic_test.go deleted file mode 100644 index 68868d7a5..000000000 --- a/src/lib/json/generic_test.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "json"; - "testing"; -) - -var jsontests = []string { - `null`, - `true`, - `false`, - `"abc"`, - `123`, - `0.1`, - `1e-10`, - `[]`, - `[1,2,3,4]`, - `[1,2,"abc",null,true,false]`, - `{}`, - `{"a":1}`, -} - -func TestJson(t *testing.T) { - for i := 0; i < len(jsontests); i++ { - val, ok, errtok := StringToJson(jsontests[i]); - if !ok { - t.Errorf("StringToJson(%#q) => error near %v", jsontests[i], errtok); - continue; - } - str := JsonToString(val); - if str != jsontests[i] { - t.Errorf("JsonToString(StringToJson(%#q)) = %#q", jsontests[i], str); - continue; - } - } -} - -func TestJsonMap(t *testing.T) { - values := make(map[string]Json); - mapstr := "{"; - for i := 0; i < len(jsontests); i++ { - val, ok, errtok := StringToJson(jsontests[i]); - if !ok { - t.Errorf("StringToJson(%#q) => error near %v", jsontests[i], errtok); - } - if i > 0 { - mapstr += ","; - } - values[jsontests[i]] = val; - mapstr += Quote(jsontests[i]); - mapstr += ":"; - mapstr += JsonToString(val); - } - mapstr += "}"; - - mapv, ok, errtok := StringToJson(mapstr); - if !ok { - t.Fatalf("StringToJson(%#q) => error near %v", mapstr, errtok); - } - if mapv == nil { - t.Fatalf("StringToJson(%#q) => nil, %v, %v", mapstr, ok, errtok); - } - if cnt := mapv.Len(); cnt != len(jsontests) { - t.Errorf("StringToJson(%#q).Len() => %v, want %v", mapstr, cnt, - len(jsontests)); - } - for k,v := range values { - if v1 := mapv.Get(k); !Equal(v1, v) { - t.Errorf("MapTest: Walk(%#q) => %v, want %v", k, v1, v); - } - } -} diff --git a/src/lib/json/parse.go b/src/lib/json/parse.go deleted file mode 100644 index e33b9dbc1..000000000 --- a/src/lib/json/parse.go +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// JSON (JavaScript Object Notation) parser. -// See http://www.json.org/ - -// The json package implements a simple parser and -// representation for JSON (JavaScript Object Notation), -// as defined at http://www.json.org/. -package json - -import ( - "fmt"; - "io"; - "math"; - "strconv"; - "strings"; - "utf8"; -) - -// Strings -// -// Double quoted with escapes: \" \\ \/ \b \f \n \r \t \uXXXX. -// No literal control characters, supposedly. -// Have also seen \' and embedded newlines. - -func _UnHex(p string, r, l int) (v int, ok bool) { - v = 0; - for i := r; i < l; i++ { - if i >= len(p) { - return 0, false - } - v *= 16; - switch { - case '0' <= p[i] && p[i] <= '9': - v += int(p[i] - '0'); - case 'a' <= p[i] && p[i] <= 'f': - v += int(p[i] - 'a' + 10); - case 'A' <= p[i] && p[i] <= 'F': - v += int(p[i] - 'A' + 10); - default: - return 0, false; - } - } - return v, true; -} - -// Unquote unquotes the JSON-quoted string s, -// returning a raw string t. If s is not a valid -// JSON-quoted string, Unquote returns with ok set to false. -func Unquote(s string) (t string, ok bool) { - if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { - return - } - b := make([]byte, len(s)); - w := 0; - for r := 1; r < len(s)-1; { - switch { - case s[r] == '\\': - r++; - if r >= len(s)-1 { - return - } - switch s[r] { - default: - return; - case '"', '\\', '/', '\'': - b[w] = s[r]; - r++; - w++; - case 'b': - b[w] = '\b'; - r++; - w++; - case 'f': - b[w] = '\f'; - r++; - w++; - case 'n': - b[w] = '\n'; - r++; - w++; - case 'r': - b[w] = '\r'; - r++; - w++; - case 't': - b[w] = '\t'; - r++; - w++; - case 'u': - r++; - rune, ok := _UnHex(s, r, 4); - if !ok { - return - } - r += 4; - w += utf8.EncodeRune(rune, b[w:len(b)]); - } - // Control characters are invalid, but we've seen raw \n. - case s[r] < ' ' && s[r] != '\n': - if s[r] == '\n' { - b[w] = '\n'; - r++; - w++; - break; - } - return; - // ASCII - case s[r] < utf8.RuneSelf: - b[w] = s[r]; - r++; - w++; - // Coerce to well-formed UTF-8. - default: - rune, size := utf8.DecodeRuneInString(s[r:len(s)]); - r += size; - w += utf8.EncodeRune(rune, b[w:len(b)]); - } - } - return string(b[0:w]), true -} - -// Quote quotes the raw string s using JSON syntax, -// so that Unquote(Quote(s)) = s, true. -func Quote(s string) string { - chr := make([]byte, utf8.UTFMax); - chr0 := chr[0:1]; - b := new(io.ByteBuffer); - chr[0] = '"'; - b.Write(chr0); - for i := 0; i < len(s); i++ { - switch { - case s[i]=='"' || s[i]=='\\': - chr[0] = '\\'; - chr[1] = s[i]; - b.Write(chr[0:2]); - - case s[i] == '\b': - chr[0] = '\\'; - chr[1] = 'b'; - b.Write(chr[0:2]); - - case s[i] == '\f': - chr[0] = '\\'; - chr[1] = 'f'; - b.Write(chr[0:2]); - - case s[i] == '\n': - chr[0] = '\\'; - chr[1] = 'n'; - b.Write(chr[0:2]); - - case s[i] == '\r': - chr[0] = '\\'; - chr[1] = 'r'; - b.Write(chr[0:2]); - - case s[i] == '\t': - chr[0] = '\\'; - chr[1] = 't'; - b.Write(chr[0:2]); - - case 0x20 <= s[i] && s[i] < utf8.RuneSelf: - chr[0] = s[i]; - b.Write(chr0); - } - } - chr[0] = '"'; - b.Write(chr0); - return string(b.Data()); -} - - -// _Lexer - -type _Lexer struct { - s string; - i int; - kind int; - token string; -} - -func punct(c byte) bool { - return c=='"' || c=='[' || c==']' || c==':' || c=='{' || c=='}' || c==',' -} - -func white(c byte) bool { - return c==' ' || c=='\t' || c=='\n' || c=='\v' -} - -func skipwhite(p string, i int) int { - for i < len(p) && white(p[i]) { - i++ - } - return i -} - -func skiptoken(p string, i int) int { - for i < len(p) && !punct(p[i]) && !white(p[i]) { - i++ - } - return i -} - -func skipstring(p string, i int) int { - for i++; i < len(p) && p[i] != '"'; i++ { - if p[i] == '\\' { - i++ - } - } - if i >= len(p) { - return i - } - return i+1 -} - -func (t *_Lexer) Next() { - i, s := t.i, t.s; - i = skipwhite(s, i); - if i >= len(s) { - t.kind = 0; - t.token = ""; - t.i = len(s); - return; - } - - c := s[i]; - switch { - case c == '-' || '0' <= c && c <= '9': - j := skiptoken(s, i); - t.kind = '1'; - t.token = s[i:j]; - i = j; - - case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z': - j := skiptoken(s, i); - t.kind = 'a'; - t.token = s[i:j]; - i = j; - - case c == '"': - j := skipstring(s, i); - t.kind = '"'; - t.token = s[i:j]; - i = j; - - case c == '[', c == ']', c == ':', c == '{', c == '}', c == ',': - t.kind = int(c); - t.token = s[i:i+1]; - i++; - - default: - t.kind = '?'; - t.token = s[i:i+1]; - } - - t.i = i; -} - - -// Parser -// -// Implements parsing but not the actions. Those are -// carried out by the implementation of the Builder interface. -// A Builder represents the object being created. -// Calling a method like Int64(i) sets that object to i. -// Calling a method like Elem(i) or Key(s) creates a -// new builder for a subpiece of the object (logically, -// an array element or a map key). -// -// There are two Builders, in other files. -// The JsonBuilder builds a generic Json structure -// in which maps are maps. -// The StructBuilder copies data into a possibly -// nested data structure, using the "map keys" -// as struct field names. - -type _Value interface {} - -// BUG(rsc): The json Builder interface needs to be -// reconciled with the xml Builder interface. - -// A Builder is an interface implemented by clients and passed -// to the JSON parser. It gives clients full control over the -// eventual representation returned by the parser. -type Builder interface { - // Set value - Int64(i int64); - Uint64(i uint64); - Float64(f float64); - String(s string); - Bool(b bool); - Null(); - Array(); - Map(); - - // Create sub-Builders - Elem(i int) Builder; - Key(s string) Builder; -} - -func parse(lex *_Lexer, build Builder) bool { - ok := false; -Switch: - switch lex.kind { - case 0: - break; - case '1': - // If the number is exactly an integer, use that. - if i, err := strconv.Atoi64(lex.token); err == nil { - build.Int64(i); - ok = true; - } - else if i, err := strconv.Atoui64(lex.token); err == nil { - build.Uint64(i); - ok = true; - } - // Fall back to floating point. - else if f, err := strconv.Atof64(lex.token); err == nil { - build.Float64(f); - ok = true; - } - - case 'a': - switch lex.token { - case "true": - build.Bool(true); - ok = true; - case "false": - build.Bool(false); - ok = true; - case "null": - build.Null(); - ok = true; - } - - case '"': - if str, ok1 := Unquote(lex.token); ok1 { - build.String(str); - ok = true; - } - - case '[': - // array - build.Array(); - lex.Next(); - n := 0; - for lex.kind != ']' { - if n > 0 { - if lex.kind != ',' { - break Switch; - } - lex.Next(); - } - if !parse(lex, build.Elem(n)) { - break Switch; - } - n++; - } - ok = true; - - case '{': - // map - lex.Next(); - build.Map(); - n := 0; - for lex.kind != '}' { - if n > 0 { - if lex.kind != ',' { - break Switch; - } - lex.Next(); - } - if lex.kind != '"' { - break Switch; - } - key, ok := Unquote(lex.token); - if !ok { - break Switch; - } - lex.Next(); - if lex.kind != ':' { - break Switch; - } - lex.Next(); - if !parse(lex, build.Key(key)) { - break Switch; - } - n++; - } - ok = true; - } - - if ok { - lex.Next(); - } - return ok; -} - -// Parse parses the JSON syntax string s and makes calls to -// the builder to construct a parsed representation. -// On success, it returns with ok set to true. -// On error, it returns with ok set to false, errindx set -// to the byte index in s where a syntax error occurred, -// and errtok set to the offending token. -func Parse(s string, builder Builder) (ok bool, errindx int, errtok string) { - lex := new(_Lexer); - lex.s = s; - lex.Next(); - if parse(lex, builder) { - if lex.kind == 0 { // EOF - return true, 0, "" - } - } - return false, lex.i, lex.token -} - diff --git a/src/lib/json/struct.go b/src/lib/json/struct.go deleted file mode 100644 index ac2689557..000000000 --- a/src/lib/json/struct.go +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Marshalling and unmarshalling of -// JSON data into Go structs using reflection. - -package json - -import ( - "json"; - "reflect"; -) - -type _StructBuilder struct { - val reflect.Value -} - -var nobuilder *_StructBuilder - -func setfloat(v reflect.Value, f float64) { - switch v.Kind() { - case reflect.FloatKind: - v.(reflect.FloatValue).Set(float(f)); - case reflect.Float32Kind: - v.(reflect.Float32Value).Set(float32(f)); - case reflect.Float64Kind: - v.(reflect.Float64Value).Set(float64(f)); - } -} - -func setint(v reflect.Value, i int64) { - switch v.Kind() { - case reflect.IntKind: - v.(reflect.IntValue).Set(int(i)); - case reflect.Int8Kind: - v.(reflect.Int8Value).Set(int8(i)); - case reflect.Int16Kind: - v.(reflect.Int16Value).Set(int16(i)); - case reflect.Int32Kind: - v.(reflect.Int32Value).Set(int32(i)); - case reflect.Int64Kind: - v.(reflect.Int64Value).Set(int64(i)); - case reflect.UintKind: - v.(reflect.UintValue).Set(uint(i)); - case reflect.Uint8Kind: - v.(reflect.Uint8Value).Set(uint8(i)); - case reflect.Uint16Kind: - v.(reflect.Uint16Value).Set(uint16(i)); - case reflect.Uint32Kind: - v.(reflect.Uint32Value).Set(uint32(i)); - case reflect.Uint64Kind: - v.(reflect.Uint64Value).Set(uint64(i)); - } -} - -func (b *_StructBuilder) Int64(i int64) { - if b == nil { - return - } - v := b.val; - switch v.Kind() { - case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind: - setfloat(v, float64(i)); - default: - setint(v, i); - } -} - -func (b *_StructBuilder) Uint64(i uint64) { - if b == nil { - return - } - v := b.val; - switch v.Kind() { - case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind: - setfloat(v, float64(i)); - default: - setint(v, int64(i)); - } -} - -func (b *_StructBuilder) Float64(f float64) { - if b == nil { - return - } - v := b.val; - switch v.Kind() { - case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind: - setfloat(v, f); - default: - setint(v, int64(f)); - } -} - -func (b *_StructBuilder) Null() { -} - -func (b *_StructBuilder) String(s string) { - if b == nil { - return - } - if v := b.val; v.Kind() == reflect.StringKind { - v.(reflect.StringValue).Set(s); - } -} - -func (b *_StructBuilder) Bool(tf bool) { - if b == nil { - return - } - if v := b.val; v.Kind() == reflect.BoolKind { - v.(reflect.BoolValue).Set(tf); - } -} - -func (b *_StructBuilder) Array() { - if b == nil { - return - } - if v := b.val; v.Kind() == reflect.PtrKind { - pv := v.(reflect.PtrValue); - psubtype := pv.Type().(reflect.PtrType).Sub(); - if pv.Get() == nil && psubtype.Kind() == reflect.ArrayKind { - av := reflect.NewSliceValue(psubtype.(reflect.ArrayType), 0, 8); - pv.SetSub(av); - } - } -} - -func (b *_StructBuilder) Elem(i int) Builder { - if b == nil || i < 0 { - return nobuilder - } - v := b.val; - if v.Kind() == reflect.PtrKind { - // If we have a pointer to an array, allocate or grow - // the array as necessary. Then set v to the array itself. - pv := v.(reflect.PtrValue); - psub := pv.Sub(); - if psub.Kind() == reflect.ArrayKind { - av := psub.(reflect.ArrayValue); - if i > av.Cap() { - n := av.Cap(); - if n < 8 { - n = 8 - } - for n <= i { - n *= 2 - } - av1 := reflect.NewSliceValue(av.Type().(reflect.ArrayType), av.Len(), n); - av1.CopyFrom(av, av.Len()); - pv.SetSub(av1); - av = av1; - } - } - v = psub; - } - if v.Kind() == reflect.ArrayKind { - // Array was grown above, or is fixed size. - av := v.(reflect.ArrayValue); - if av.Len() <= i && i < av.Cap() { - av.SetLen(i+1); - } - if i < av.Len() { - return &_StructBuilder{ av.Elem(i) } - } - } - return nobuilder -} - -func (b *_StructBuilder) Map() { - if b == nil { - return - } - if v := b.val; v.Kind() == reflect.PtrKind { - pv := v.(reflect.PtrValue); - if pv.Get() == nil { - pv.SetSub(reflect.NewZeroValue(pv.Type().(reflect.PtrType).Sub())) - } - } -} - -func (b *_StructBuilder) Key(k string) Builder { - if b == nil { - return nobuilder - } - v := b.val; - if v.Kind() == reflect.PtrKind { - v = v.(reflect.PtrValue).Sub(); - } - if v.Kind() == reflect.StructKind { - sv := v.(reflect.StructValue); - t := v.Type().(reflect.StructType); - for i := 0; i < t.Len(); i++ { - name, typ, tag, off := t.Field(i); - if k == name { - return &_StructBuilder{ sv.Field(i) } - } - } - } - return nobuilder -} - -// Unmarshal parses the JSON syntax string s and fills in -// an arbitrary struct or array pointed at by val. -// It uses the reflection library to assign to fields -// and arrays embedded in val. Well-formed data that does not fit -// into the struct is discarded. -// -// For example, given the following definitions: -// -// type Email struct { -// where string; -// addr string; -// } -// -// type Result struct { -// name string; -// phone string; -// emails []Email -// } -// -// var r = Result{ "name", "phone", nil } -// -// unmarshalling the JSON syntax string -// -// { -// "email": [ -// { -// "where": "home", -// "addr": "gre@example.com" -// }, -// { -// "where": "work", -// "addr": "gre@work.com" -// } -// ], -// "name": "Grace R. Emlin", -// "address": "123 Main Street" -// } -// -// via Unmarshal(s, &r) is equivalent to assigning -// -// r = Result{ -// "Grace R. Emlin", // name -// "phone", // no phone given -// []Email{ -// Email{ "home", "gre@example.com" }, -// Email{ "work", "gre@work.com" } -// } -// } -// -// Note that the field r.phone has not been modified and -// that the JSON field "address" was discarded. -// -// On success, Unmarshal returns with ok set to true. -// On a syntax error, it returns with ok set to false and errtok -// set to the offending token. -func Unmarshal(s string, val interface{}) (ok bool, errtok string) { - var errindx int; - var val1 interface{}; - b := &_StructBuilder{ reflect.NewValue(val) }; - ok, errindx, errtok = Parse(s, b); - if !ok { - return false, errtok - } - return true, "" -} diff --git a/src/lib/json/struct_test.go b/src/lib/json/struct_test.go deleted file mode 100644 index 88d9e9ec4..000000000 --- a/src/lib/json/struct_test.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "json"; - "testing"; -) - -type _MyStruct struct { - t bool; - f bool; - s string; - i8 int8; - i16 int16; - i32 int32; - i64 int64; - u8 uint8; - u16 uint16; - u32 uint32; - u64 uint64; - i int; - u uint; - fl float; - fl32 float32; - fl64 float64; - a *[]string; // TODO(rsc): Should be able to use []string. - my *_MyStruct; -}; - -const _Encoded = - `{"t":true,"f":false,"s":"abc","i8":1,"i16":2,"i32":3,"i64":4,` - ` "u8":5,"u16":6,"u32":7,"u64":8,` - ` "i":-9,"u":10,"bogusfield":"should be ignored",` - ` "fl":11.5,"fl32":12.25,"fl64":13.75,` - ` "a":["x","y","z"],"my":{"s":"subguy"}}`; - - -func _Check(t *testing.T, ok bool, name string, v interface{}) { - if !ok { - t.Errorf("%s = %v (BAD)", name, v); - } else { - t.Logf("%s = %v (good)", name, v); - } -} - -func TestUnmarshal(t *testing.T) { - var m _MyStruct; - m.f = true; - ok, errtok := Unmarshal(_Encoded, &m); - if !ok { - t.Fatalf("Unmarshal failed near %s", errtok); - } - _Check(t, m.t==true, "t", m.t); - _Check(t, m.f==false, "f", m.f); - _Check(t, m.s=="abc", "s", m.s); - _Check(t, m.i8==1, "i8", m.i8); - _Check(t, m.i16==2, "i16", m.i16); - _Check(t, m.i32==3, "i32", m.i32); - _Check(t, m.i64==4, "i64", m.i64); - _Check(t, m.u8==5, "u8", m.u8); - _Check(t, m.u16==6, "u16", m.u16); - _Check(t, m.u32==7, "u32", m.u32); - _Check(t, m.u64==8, "u64", m.u64); - _Check(t, m.i==-9, "i", m.i); - _Check(t, m.u==10, "u", m.u); - _Check(t, m.fl==11.5, "fl", m.fl); - _Check(t, m.fl32==12.25, "fl32", m.fl32); - _Check(t, m.fl64==13.75, "fl64", m.fl64); - _Check(t, m.a!=nil, "a", m.a); - if m.a != nil { - _Check(t, m.a[0]=="x", "a[0]", m.a[0]); - _Check(t, m.a[1]=="y", "a[1]", m.a[1]); - _Check(t, m.a[2]=="z", "a[2]", m.a[2]); - } - _Check(t, m.my!=nil, "my", m.my); - if m.my != nil { - _Check(t, m.my.s=="subguy", "my.s", m.my.s); - } -} |
