github.com/evanw/esbuild@v0.21.4/internal/helpers/joiner.go (about) 1 package helpers 2 3 import ( 4 "bytes" 5 "strings" 6 ) 7 8 // This provides an efficient way to join lots of big string and byte slices 9 // together. It avoids the cost of repeatedly reallocating as the buffer grows 10 // by measuring exactly how big the buffer should be and then allocating once. 11 // This is a measurable speedup. 12 type Joiner struct { 13 strings []joinerString 14 bytes []joinerBytes 15 length uint32 16 lastByte byte 17 } 18 19 type joinerString struct { 20 data string 21 offset uint32 22 } 23 24 type joinerBytes struct { 25 data []byte 26 offset uint32 27 } 28 29 func (j *Joiner) AddString(data string) { 30 if len(data) > 0 { 31 j.lastByte = data[len(data)-1] 32 } 33 j.strings = append(j.strings, joinerString{data, j.length}) 34 j.length += uint32(len(data)) 35 } 36 37 func (j *Joiner) AddBytes(data []byte) { 38 if len(data) > 0 { 39 j.lastByte = data[len(data)-1] 40 } 41 j.bytes = append(j.bytes, joinerBytes{data, j.length}) 42 j.length += uint32(len(data)) 43 } 44 45 func (j *Joiner) LastByte() byte { 46 return j.lastByte 47 } 48 49 func (j *Joiner) Length() uint32 { 50 return j.length 51 } 52 53 func (j *Joiner) EnsureNewlineAtEnd() { 54 if j.length > 0 && j.lastByte != '\n' { 55 j.AddString("\n") 56 } 57 } 58 59 func (j *Joiner) Done() []byte { 60 if len(j.strings) == 0 && len(j.bytes) == 1 && j.bytes[0].offset == 0 { 61 // No need to allocate if there was only a single byte array written 62 return j.bytes[0].data 63 } 64 buffer := make([]byte, j.length) 65 for _, item := range j.strings { 66 copy(buffer[item.offset:], item.data) 67 } 68 for _, item := range j.bytes { 69 copy(buffer[item.offset:], item.data) 70 } 71 return buffer 72 } 73 74 func (j *Joiner) Contains(s string, b []byte) bool { 75 for _, item := range j.strings { 76 if strings.Contains(item.data, s) { 77 return true 78 } 79 } 80 for _, item := range j.bytes { 81 if bytes.Contains(item.data, b) { 82 return true 83 } 84 } 85 return false 86 }