...

Source file src/pkg/encoding/gob/decgen.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// +build ignore
     6	
     7	// encgen writes the helper functions for encoding. Intended to be
     8	// used with go generate; see the invocation in encode.go.
     9	
    10	// TODO: We could do more by being unsafe. Add a -unsafe flag?
    11	
    12	package main
    13	
    14	import (
    15		"bytes"
    16		"flag"
    17		"fmt"
    18		"go/format"
    19		"log"
    20		"os"
    21	)
    22	
    23	var output = flag.String("output", "dec_helpers.go", "file name to write")
    24	
    25	type Type struct {
    26		lower   string
    27		upper   string
    28		decoder string
    29	}
    30	
    31	var types = []Type{
    32		{
    33			"bool",
    34			"Bool",
    35			`slice[i] = state.decodeUint() != 0`,
    36		},
    37		{
    38			"complex64",
    39			"Complex64",
    40			`real := float32FromBits(state.decodeUint(), ovfl)
    41			imag := float32FromBits(state.decodeUint(), ovfl)
    42			slice[i] = complex(float32(real), float32(imag))`,
    43		},
    44		{
    45			"complex128",
    46			"Complex128",
    47			`real := float64FromBits(state.decodeUint())
    48			imag := float64FromBits(state.decodeUint())
    49			slice[i] = complex(real, imag)`,
    50		},
    51		{
    52			"float32",
    53			"Float32",
    54			`slice[i] = float32(float32FromBits(state.decodeUint(), ovfl))`,
    55		},
    56		{
    57			"float64",
    58			"Float64",
    59			`slice[i] = float64FromBits(state.decodeUint())`,
    60		},
    61		{
    62			"int",
    63			"Int",
    64			`x := state.decodeInt()
    65			// MinInt and MaxInt
    66			if x < ^int64(^uint(0)>>1) || int64(^uint(0)>>1) < x {
    67				error_(ovfl)
    68			}
    69			slice[i] = int(x)`,
    70		},
    71		{
    72			"int16",
    73			"Int16",
    74			`x := state.decodeInt()
    75			if x < math.MinInt16 || math.MaxInt16 < x {
    76				error_(ovfl)
    77			}
    78			slice[i] = int16(x)`,
    79		},
    80		{
    81			"int32",
    82			"Int32",
    83			`x := state.decodeInt()
    84			if x < math.MinInt32 || math.MaxInt32 < x {
    85				error_(ovfl)
    86			}
    87			slice[i] = int32(x)`,
    88		},
    89		{
    90			"int64",
    91			"Int64",
    92			`slice[i] = state.decodeInt()`,
    93		},
    94		{
    95			"int8",
    96			"Int8",
    97			`x := state.decodeInt()
    98			if x < math.MinInt8 || math.MaxInt8 < x {
    99				error_(ovfl)
   100			}
   101			slice[i] = int8(x)`,
   102		},
   103		{
   104			"string",
   105			"String",
   106			`u := state.decodeUint()
   107			n := int(u)
   108			if n < 0 || uint64(n) != u || n > state.b.Len() {
   109				errorf("length of string exceeds input size (%d bytes)", u)
   110			}
   111			if n > state.b.Len() {
   112				errorf("string data too long for buffer: %d", n)
   113			}
   114			// Read the data.
   115			data := state.b.Bytes()
   116			if len(data) < n {
   117				errorf("invalid string length %d: exceeds input size %d", n, len(data))
   118			}
   119			slice[i] = string(data[:n])
   120			state.b.Drop(n)`,
   121		},
   122		{
   123			"uint",
   124			"Uint",
   125			`x := state.decodeUint()
   126			/*TODO if math.MaxUint32 < x {
   127				error_(ovfl)
   128			}*/
   129			slice[i] = uint(x)`,
   130		},
   131		{
   132			"uint16",
   133			"Uint16",
   134			`x := state.decodeUint()
   135			if math.MaxUint16 < x {
   136				error_(ovfl)
   137			}
   138			slice[i] = uint16(x)`,
   139		},
   140		{
   141			"uint32",
   142			"Uint32",
   143			`x := state.decodeUint()
   144			if math.MaxUint32 < x {
   145				error_(ovfl)
   146			}
   147			slice[i] = uint32(x)`,
   148		},
   149		{
   150			"uint64",
   151			"Uint64",
   152			`slice[i] = state.decodeUint()`,
   153		},
   154		{
   155			"uintptr",
   156			"Uintptr",
   157			`x := state.decodeUint()
   158			if uint64(^uintptr(0)) < x {
   159				error_(ovfl)
   160			}
   161			slice[i] = uintptr(x)`,
   162		},
   163		// uint8 Handled separately.
   164	}
   165	
   166	func main() {
   167		log.SetFlags(0)
   168		log.SetPrefix("decgen: ")
   169		flag.Parse()
   170		if flag.NArg() != 0 {
   171			log.Fatal("usage: decgen [--output filename]")
   172		}
   173		var b bytes.Buffer
   174		fmt.Fprintf(&b, "// Code generated by go run decgen.go -output %s; DO NOT EDIT.\n", *output)
   175		fmt.Fprint(&b, header)
   176		printMaps(&b, "Array")
   177		fmt.Fprint(&b, "\n")
   178		printMaps(&b, "Slice")
   179		for _, t := range types {
   180			fmt.Fprintf(&b, arrayHelper, t.lower, t.upper)
   181			fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.decoder)
   182		}
   183		source, err := format.Source(b.Bytes())
   184		if err != nil {
   185			log.Fatal("source format error:", err)
   186		}
   187		fd, err := os.Create(*output)
   188		if err != nil {
   189			log.Fatal(err)
   190		}
   191		if _, err := fd.Write(source); err != nil {
   192			log.Fatal(err)
   193		}
   194	}
   195	
   196	func printMaps(b *bytes.Buffer, upperClass string) {
   197		fmt.Fprintf(b, "var dec%sHelper = map[reflect.Kind]decHelper{\n", upperClass)
   198		for _, t := range types {
   199			fmt.Fprintf(b, "reflect.%s: dec%s%s,\n", t.upper, t.upper, upperClass)
   200		}
   201		fmt.Fprintf(b, "}\n")
   202	}
   203	
   204	const header = `
   205	// Copyright 2014 The Go Authors. All rights reserved.
   206	// Use of this source code is governed by a BSD-style
   207	// license that can be found in the LICENSE file.
   208	
   209	package gob
   210	
   211	import (
   212		"math"
   213		"reflect"
   214	)
   215	
   216	`
   217	
   218	const arrayHelper = `
   219	func dec%[2]sArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
   220		// Can only slice if it is addressable.
   221		if !v.CanAddr() {
   222			return false
   223		}
   224		return dec%[2]sSlice(state, v.Slice(0, v.Len()), length, ovfl)
   225	}
   226	`
   227	
   228	const sliceHelper = `
   229	func dec%[2]sSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
   230		slice, ok := v.Interface().([]%[1]s)
   231		if !ok {
   232			// It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely.
   233			return false
   234		}
   235		for i := 0; i < length; i++ {
   236			if state.b.Len() == 0 {
   237				errorf("decoding %[1]s array or slice: length exceeds input size (%%d elements)", length)
   238			}
   239			%[3]s
   240		}
   241		return true
   242	}
   243	`
   244	

View as plain text