...

Source file src/runtime/pprof/protobuf.go

     1	// Copyright 2014 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	package pprof
     6	
     7	// A protobuf is a simple protocol buffer encoder.
     8	type protobuf struct {
     9		data []byte
    10		tmp  [16]byte
    11		nest int
    12	}
    13	
    14	func (b *protobuf) varint(x uint64) {
    15		for x >= 128 {
    16			b.data = append(b.data, byte(x)|0x80)
    17			x >>= 7
    18		}
    19		b.data = append(b.data, byte(x))
    20	}
    21	
    22	func (b *protobuf) length(tag int, len int) {
    23		b.varint(uint64(tag)<<3 | 2)
    24		b.varint(uint64(len))
    25	}
    26	
    27	func (b *protobuf) uint64(tag int, x uint64) {
    28		// append varint to b.data
    29		b.varint(uint64(tag)<<3 | 0)
    30		b.varint(x)
    31	}
    32	
    33	func (b *protobuf) uint64s(tag int, x []uint64) {
    34		if len(x) > 2 {
    35			// Use packed encoding
    36			n1 := len(b.data)
    37			for _, u := range x {
    38				b.varint(u)
    39			}
    40			n2 := len(b.data)
    41			b.length(tag, n2-n1)
    42			n3 := len(b.data)
    43			copy(b.tmp[:], b.data[n2:n3])
    44			copy(b.data[n1+(n3-n2):], b.data[n1:n2])
    45			copy(b.data[n1:], b.tmp[:n3-n2])
    46			return
    47		}
    48		for _, u := range x {
    49			b.uint64(tag, u)
    50		}
    51	}
    52	
    53	func (b *protobuf) uint64Opt(tag int, x uint64) {
    54		if x == 0 {
    55			return
    56		}
    57		b.uint64(tag, x)
    58	}
    59	
    60	func (b *protobuf) int64(tag int, x int64) {
    61		u := uint64(x)
    62		b.uint64(tag, u)
    63	}
    64	
    65	func (b *protobuf) int64Opt(tag int, x int64) {
    66		if x == 0 {
    67			return
    68		}
    69		b.int64(tag, x)
    70	}
    71	
    72	func (b *protobuf) int64s(tag int, x []int64) {
    73		if len(x) > 2 {
    74			// Use packed encoding
    75			n1 := len(b.data)
    76			for _, u := range x {
    77				b.varint(uint64(u))
    78			}
    79			n2 := len(b.data)
    80			b.length(tag, n2-n1)
    81			n3 := len(b.data)
    82			copy(b.tmp[:], b.data[n2:n3])
    83			copy(b.data[n1+(n3-n2):], b.data[n1:n2])
    84			copy(b.data[n1:], b.tmp[:n3-n2])
    85			return
    86		}
    87		for _, u := range x {
    88			b.int64(tag, u)
    89		}
    90	}
    91	
    92	func (b *protobuf) string(tag int, x string) {
    93		b.length(tag, len(x))
    94		b.data = append(b.data, x...)
    95	}
    96	
    97	func (b *protobuf) strings(tag int, x []string) {
    98		for _, s := range x {
    99			b.string(tag, s)
   100		}
   101	}
   102	
   103	func (b *protobuf) stringOpt(tag int, x string) {
   104		if x == "" {
   105			return
   106		}
   107		b.string(tag, x)
   108	}
   109	
   110	func (b *protobuf) bool(tag int, x bool) {
   111		if x {
   112			b.uint64(tag, 1)
   113		} else {
   114			b.uint64(tag, 0)
   115		}
   116	}
   117	
   118	func (b *protobuf) boolOpt(tag int, x bool) {
   119		if x == false {
   120			return
   121		}
   122		b.bool(tag, x)
   123	}
   124	
   125	type msgOffset int
   126	
   127	func (b *protobuf) startMessage() msgOffset {
   128		b.nest++
   129		return msgOffset(len(b.data))
   130	}
   131	
   132	func (b *protobuf) endMessage(tag int, start msgOffset) {
   133		n1 := int(start)
   134		n2 := len(b.data)
   135		b.length(tag, n2-n1)
   136		n3 := len(b.data)
   137		copy(b.tmp[:], b.data[n2:n3])
   138		copy(b.data[n1+(n3-n2):], b.data[n1:n2])
   139		copy(b.data[n1:], b.tmp[:n3-n2])
   140		b.nest--
   141	}
   142	

View as plain text