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 5package pprof 6 7// A protobuf is a simple protocol buffer encoder. 8type protobuf struct { 9 data []byte 10 tmp [16]byte 11 nest int 12} 13 14func (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 22func (b *protobuf) length(tag int, len int) { 23 b.varint(uint64(tag)<<3 | 2) 24 b.varint(uint64(len)) 25} 26 27func (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 33func (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 53func (b *protobuf) uint64Opt(tag int, x uint64) { 54 if x == 0 { 55 return 56 } 57 b.uint64(tag, x) 58} 59 60func (b *protobuf) int64(tag int, x int64) { 61 u := uint64(x) 62 b.uint64(tag, u) 63} 64 65func (b *protobuf) int64Opt(tag int, x int64) { 66 if x == 0 { 67 return 68 } 69 b.int64(tag, x) 70} 71 72func (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 92func (b *protobuf) string(tag int, x string) { 93 b.length(tag, len(x)) 94 b.data = append(b.data, x...) 95} 96 97func (b *protobuf) strings(tag int, x []string) { 98 for _, s := range x { 99 b.string(tag, s) 100 } 101} 102 103func (b *protobuf) stringOpt(tag int, x string) { 104 if x == "" { 105 return 106 } 107 b.string(tag, x) 108} 109 110func (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 118func (b *protobuf) boolOpt(tag int, x bool) { 119 if !x { 120 return 121 } 122 b.bool(tag, x) 123} 124 125type msgOffset int 126 127func (b *protobuf) startMessage() msgOffset { 128 b.nest++ 129 return msgOffset(len(b.data)) 130} 131 132func (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