diff options
Diffstat (limited to 'src/pkg/json/encode.go')
| -rw-r--r-- | src/pkg/json/encode.go | 369 | 
1 files changed, 0 insertions, 369 deletions
| diff --git a/src/pkg/json/encode.go b/src/pkg/json/encode.go deleted file mode 100644 index adc0f0f37..000000000 --- a/src/pkg/json/encode.go +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright 2010 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 implements encoding and decoding of JSON objects as defined in -// RFC 4627. -package json - -import ( -	"bytes" -	"encoding/base64" -	"os" -	"reflect" -	"runtime" -	"sort" -	"strconv" -	"unicode" -	"utf8" -) - -// Marshal returns the JSON encoding of v. -// -// Marshal traverses the value v recursively. -// If an encountered value implements the Marshaler interface, -// Marshal calls its MarshalJSON method to produce JSON. -// -// Otherwise, Marshal uses the following type-dependent default encodings: -// -// Boolean values encode as JSON booleans. -// -// Floating point and integer values encode as JSON numbers. -// -// String values encode as JSON strings, with each invalid UTF-8 sequence -// replaced by the encoding of the Unicode replacement character U+FFFD. -// -// Array and slice values encode as JSON arrays, except that -// []byte encodes as a base64-encoded string. -// -// Struct values encode as JSON objects.  Each exported struct field -// becomes a member of the object.  By default the object's key string -// is the struct field name.  If the struct field's tag has a "json" key with a -// value that is a non-empty string consisting of only Unicode letters, -// digits, and underscores, that value will be used as the object key. -// For example, the field tag `json:"myName"` says to use "myName" -// as the object key. -// -// Map values encode as JSON objects. -// The map's key type must be string; the object keys are used directly -// as map keys. -// -// Pointer values encode as the value pointed to. -// A nil pointer encodes as the null JSON object. -// -// Interface values encode as the value contained in the interface. -// A nil interface value encodes as the null JSON object. -// -// Channel, complex, and function values cannot be encoded in JSON. -// Attempting to encode such a value causes Marshal to return -// an InvalidTypeError. -// -// JSON cannot represent cyclic data structures and Marshal does not -// handle them.  Passing cyclic structures to Marshal will result in -// an infinite recursion. -// -func Marshal(v interface{}) ([]byte, os.Error) { -	e := &encodeState{} -	err := e.marshal(v) -	if err != nil { -		return nil, err -	} -	return e.Bytes(), nil -} - -// MarshalIndent is like Marshal but applies Indent to format the output. -func MarshalIndent(v interface{}, prefix, indent string) ([]byte, os.Error) { -	b, err := Marshal(v) -	if err != nil { -		return nil, err -	} -	var buf bytes.Buffer -	err = Indent(&buf, b, prefix, indent) -	if err != nil { -		return nil, err -	} -	return buf.Bytes(), nil -} - -// MarshalForHTML is like Marshal but applies HTMLEscape to the output. -func MarshalForHTML(v interface{}) ([]byte, os.Error) { -	b, err := Marshal(v) -	if err != nil { -		return nil, err -	} -	var buf bytes.Buffer -	HTMLEscape(&buf, b) -	return buf.Bytes(), nil -} - -// HTMLEscape appends to dst the JSON-encoded src with <, >, and & -// characters inside string literals changed to \u003c, \u003e, \u0026 -// so that the JSON will be safe to embed inside HTML <script> tags. -// For historical reasons, web browsers don't honor standard HTML -// escaping within <script> tags, so an alternative JSON encoding must -// be used. -func HTMLEscape(dst *bytes.Buffer, src []byte) { -	// < > & can only appear in string literals, -	// so just scan the string one byte at a time. -	start := 0 -	for i, c := range src { -		if c == '<' || c == '>' || c == '&' { -			if start < i { -				dst.Write(src[start:i]) -			} -			dst.WriteString(`\u00`) -			dst.WriteByte(hex[c>>4]) -			dst.WriteByte(hex[c&0xF]) -			start = i + 1 -		} -	} -	if start < len(src) { -		dst.Write(src[start:]) -	} -} - -// Marshaler is the interface implemented by objects that -// can marshal themselves into valid JSON. -type Marshaler interface { -	MarshalJSON() ([]byte, os.Error) -} - -type UnsupportedTypeError struct { -	Type reflect.Type -} - -func (e *UnsupportedTypeError) String() string { -	return "json: unsupported type: " + e.Type.String() -} - -type InvalidUTF8Error struct { -	S string -} - -func (e *InvalidUTF8Error) String() string { -	return "json: invalid UTF-8 in string: " + strconv.Quote(e.S) -} - -type MarshalerError struct { -	Type  reflect.Type -	Error os.Error -} - -func (e *MarshalerError) String() string { -	return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Error.String() -} - -type interfaceOrPtrValue interface { -	IsNil() bool -	Elem() reflect.Value -} - -var hex = "0123456789abcdef" - -// An encodeState encodes JSON into a bytes.Buffer. -type encodeState struct { -	bytes.Buffer // accumulated output -} - -func (e *encodeState) marshal(v interface{}) (err os.Error) { -	defer func() { -		if r := recover(); r != nil { -			if _, ok := r.(runtime.Error); ok { -				panic(r) -			} -			err = r.(os.Error) -		} -	}() -	e.reflectValue(reflect.ValueOf(v)) -	return nil -} - -func (e *encodeState) error(err os.Error) { -	panic(err) -} - -var byteSliceType = reflect.TypeOf([]byte(nil)) - -func (e *encodeState) reflectValue(v reflect.Value) { -	if !v.IsValid() { -		e.WriteString("null") -		return -	} - -	if j, ok := v.Interface().(Marshaler); ok { -		b, err := j.MarshalJSON() -		if err == nil { -			// copy JSON into buffer, checking validity. -			err = Compact(&e.Buffer, b) -		} -		if err != nil { -			e.error(&MarshalerError{v.Type(), err}) -		} -		return -	} - -	switch v.Kind() { -	case reflect.Bool: -		x := v.Bool() -		if x { -			e.WriteString("true") -		} else { -			e.WriteString("false") -		} - -	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: -		e.WriteString(strconv.Itoa64(v.Int())) - -	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: -		e.WriteString(strconv.Uitoa64(v.Uint())) - -	case reflect.Float32, reflect.Float64: -		e.WriteString(strconv.FtoaN(v.Float(), 'g', -1, v.Type().Bits())) - -	case reflect.String: -		e.string(v.String()) - -	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 -			} -			if first { -				first = false -			} else { -				e.WriteByte(',') -			} -			if tag := f.Tag.Get("json"); tag != "" && isValidTag(tag) { -				e.string(tag) -			} else { -				e.string(f.Name) -			} -			e.WriteByte(':') -			e.reflectValue(v.Field(i)) -		} -		e.WriteByte('}') - -	case reflect.Map: -		if v.Type().Key().Kind() != reflect.String { -			e.error(&UnsupportedTypeError{v.Type()}) -		} -		if v.IsNil() { -			e.WriteString("null") -			break -		} -		e.WriteByte('{') -		var sv stringValues = v.MapKeys() -		sort.Sort(sv) -		for i, k := range sv { -			if i > 0 { -				e.WriteByte(',') -			} -			e.string(k.String()) -			e.WriteByte(':') -			e.reflectValue(v.MapIndex(k)) -		} -		e.WriteByte('}') - -	case reflect.Array, reflect.Slice: -		if v.Type() == byteSliceType { -			e.WriteByte('"') -			s := v.Interface().([]byte) -			if len(s) < 1024 { -				// for small buffers, using Encode directly is much faster. -				dst := make([]byte, base64.StdEncoding.EncodedLen(len(s))) -				base64.StdEncoding.Encode(dst, s) -				e.Write(dst) -			} else { -				// for large buffers, avoid unnecessary extra temporary -				// buffer space. -				enc := base64.NewEncoder(base64.StdEncoding, e) -				enc.Write(s) -				enc.Close() -			} -			e.WriteByte('"') -			break -		} -		e.WriteByte('[') -		n := v.Len() -		for i := 0; i < n; i++ { -			if i > 0 { -				e.WriteByte(',') -			} -			e.reflectValue(v.Index(i)) -		} -		e.WriteByte(']') - -	case reflect.Interface, reflect.Ptr: -		if v.IsNil() { -			e.WriteString("null") -			return -		} -		e.reflectValue(v.Elem()) - -	default: -		e.error(&UnsupportedTypeError{v.Type()}) -	} -	return -} - -func isValidTag(s string) bool { -	if s == "" { -		return false -	} -	for _, c := range s { -		if c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) { -			return false -		} -	} -	return true -} - -// stringValues is a slice of reflect.Value holding *reflect.StringValue. -// It implements the methods to sort by string. -type stringValues []reflect.Value - -func (sv stringValues) Len() int           { return len(sv) } -func (sv stringValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] } -func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) } -func (sv stringValues) get(i int) string   { return sv[i].String() } - -func (e *encodeState) string(s string) { -	e.WriteByte('"') -	start := 0 -	for i := 0; i < len(s); { -		if b := s[i]; b < utf8.RuneSelf { -			if 0x20 <= b && b != '\\' && b != '"' { -				i++ -				continue -			} -			if start < i { -				e.WriteString(s[start:i]) -			} -			if b == '\\' || b == '"' { -				e.WriteByte('\\') -				e.WriteByte(b) -			} else { -				e.WriteString(`\u00`) -				e.WriteByte(hex[b>>4]) -				e.WriteByte(hex[b&0xF]) -			} -			i++ -			start = i -			continue -		} -		c, size := utf8.DecodeRuneInString(s[i:]) -		if c == utf8.RuneError && size == 1 { -			e.error(&InvalidUTF8Error{s}) -		} -		i += size -	} -	if start < len(s) { -		e.WriteString(s[start:]) -	} -	e.WriteByte('"') -} | 
