123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- // 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.
- // +build ignore
- // encgen writes the helper functions for encoding. Intended to be
- // used with go generate; see the invocation in encode.go.
- // TODO: We could do more by being unsafe. Add a -unsafe flag?
- package main
- import (
- "bytes"
- "flag"
- "fmt"
- "go/format"
- "log"
- "os"
- )
- var output = flag.String("output", "dec_helpers.go", "file name to write")
- type Type struct {
- lower string
- upper string
- decoder string
- }
- var types = []Type{
- {
- "bool",
- "Bool",
- `slice[i] = state.decodeUint() != 0`,
- },
- {
- "complex64",
- "Complex64",
- `real := float32FromBits(state.decodeUint(), ovfl)
- imag := float32FromBits(state.decodeUint(), ovfl)
- slice[i] = complex(float32(real), float32(imag))`,
- },
- {
- "complex128",
- "Complex128",
- `real := float64FromBits(state.decodeUint())
- imag := float64FromBits(state.decodeUint())
- slice[i] = complex(real, imag)`,
- },
- {
- "float32",
- "Float32",
- `slice[i] = float32(float32FromBits(state.decodeUint(), ovfl))`,
- },
- {
- "float64",
- "Float64",
- `slice[i] = float64FromBits(state.decodeUint())`,
- },
- {
- "int",
- "Int",
- `x := state.decodeInt()
- // MinInt and MaxInt
- if x < ^int64(^uint(0)>>1) || int64(^uint(0)>>1) < x {
- error_(ovfl)
- }
- slice[i] = int(x)`,
- },
- {
- "int16",
- "Int16",
- `x := state.decodeInt()
- if x < math.MinInt16 || math.MaxInt16 < x {
- error_(ovfl)
- }
- slice[i] = int16(x)`,
- },
- {
- "int32",
- "Int32",
- `x := state.decodeInt()
- if x < math.MinInt32 || math.MaxInt32 < x {
- error_(ovfl)
- }
- slice[i] = int32(x)`,
- },
- {
- "int64",
- "Int64",
- `slice[i] = state.decodeInt()`,
- },
- {
- "int8",
- "Int8",
- `x := state.decodeInt()
- if x < math.MinInt8 || math.MaxInt8 < x {
- error_(ovfl)
- }
- slice[i] = int8(x)`,
- },
- {
- "string",
- "String",
- `u := state.decodeUint()
- n := int(u)
- if n < 0 || uint64(n) != u || n > state.b.Len() {
- errorf("length of string exceeds input size (%d bytes)", u)
- }
- if n > state.b.Len() {
- errorf("string data too long for buffer: %d", n)
- }
- // Read the data.
- data := make([]byte, n)
- if _, err := state.b.Read(data); err != nil {
- errorf("error decoding string: %s", err)
- }
- slice[i] = string(data)`,
- },
- {
- "uint",
- "Uint",
- `x := state.decodeUint()
- /*TODO if math.MaxUint32 < x {
- error_(ovfl)
- }*/
- slice[i] = uint(x)`,
- },
- {
- "uint16",
- "Uint16",
- `x := state.decodeUint()
- if math.MaxUint16 < x {
- error_(ovfl)
- }
- slice[i] = uint16(x)`,
- },
- {
- "uint32",
- "Uint32",
- `x := state.decodeUint()
- if math.MaxUint32 < x {
- error_(ovfl)
- }
- slice[i] = uint32(x)`,
- },
- {
- "uint64",
- "Uint64",
- `slice[i] = state.decodeUint()`,
- },
- {
- "uintptr",
- "Uintptr",
- `x := state.decodeUint()
- if uint64(^uintptr(0)) < x {
- error_(ovfl)
- }
- slice[i] = uintptr(x)`,
- },
- // uint8 Handled separately.
- }
- func main() {
- log.SetFlags(0)
- log.SetPrefix("decgen: ")
- flag.Parse()
- if flag.NArg() != 0 {
- log.Fatal("usage: decgen [--output filename]")
- }
- var b bytes.Buffer
- fmt.Fprintf(&b, "// Created by decgen --output %s; DO NOT EDIT\n", *output)
- fmt.Fprint(&b, header)
- printMaps(&b, "Array")
- fmt.Fprint(&b, "\n")
- printMaps(&b, "Slice")
- for _, t := range types {
- fmt.Fprintf(&b, arrayHelper, t.lower, t.upper)
- fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.decoder)
- }
- source, err := format.Source(b.Bytes())
- if err != nil {
- log.Fatal("source format error:", err)
- }
- fd, err := os.Create(*output)
- _, err = fd.Write(source)
- if err != nil {
- log.Fatal(err)
- }
- }
- func printMaps(b *bytes.Buffer, upperClass string) {
- fmt.Fprintf(b, "var dec%sHelper = map[reflect.Kind]decHelper{\n", upperClass)
- for _, t := range types {
- fmt.Fprintf(b, "reflect.%s: dec%s%s,\n", t.upper, t.upper, upperClass)
- }
- fmt.Fprintf(b, "}\n")
- }
- const header = `
- // Copyright 2014 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 gob
- import (
- "math"
- "reflect"
- )
- `
- const arrayHelper = `
- func dec%[2]sArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
- // Can only slice if it is addressable.
- if !v.CanAddr() {
- return false
- }
- return dec%[2]sSlice(state, v.Slice(0, v.Len()), length, ovfl)
- }
- `
- const sliceHelper = `
- func dec%[2]sSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
- slice, ok := v.Interface().([]%[1]s)
- if !ok {
- // It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely.
- return false
- }
- for i := 0; i < length; i++ {
- if state.b.Len() == 0 {
- errorf("decoding %[1]s array or slice: length exceeds input size (%%d elements)", length)
- }
- %[3]s
- }
- return true
- }
- `
|