Browse Source

rewrite SliceBySize

pull/1435/head
Darien Raymond 6 years ago
parent
commit
5c4e33f759
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
  1. 57
      common/buf/multi_buffer.go
  2. 2
      common/buf/multi_buffer_test.go
  3. 3
      common/buf/reader.go
  4. 3
      common/crypto/chunk.go
  5. 2
      common/mux/writer.go

57
common/buf/multi_buffer.go

@ -3,7 +3,6 @@ package buf
import ( import (
"io" "io"
"v2ray.com/core/common"
"v2ray.com/core/common/errors" "v2ray.com/core/common/errors"
"v2ray.com/core/common/serial" "v2ray.com/core/common/serial"
) )
@ -127,6 +126,39 @@ func SplitFirst(mb MultiBuffer) (MultiBuffer, *Buffer) {
return mb, b return mb, b
} }
// SplitSize splits the beginning of the MultiBuffer into another one, for at most size bytes.
func SplitSize(mb MultiBuffer, size int32) (MultiBuffer, MultiBuffer) {
if len(mb) == 0 {
return mb, nil
}
if mb[0].Len() > size {
b := New()
copy(b.Extend(size), mb[0].BytesTo(size))
mb[0].Advance(size)
return mb, MultiBuffer{b}
}
totalBytes := int32(0)
var r MultiBuffer
endIndex := 0
for i := range mb {
if totalBytes+mb[i].Len() > size {
endIndex = i
break
}
r = append(r, mb[i])
mb[i] = nil
}
if endIndex == len(mb) {
// To reuse mb array
mb = mb[:0]
} else {
mb = mb[endIndex:]
}
return mb, r
}
// Len returns the total number of bytes in the MultiBuffer. // Len returns the total number of bytes in the MultiBuffer.
func (mb MultiBuffer) Len() int32 { func (mb MultiBuffer) Len() int32 {
if mb == nil { if mb == nil {
@ -159,29 +191,6 @@ func (mb MultiBuffer) String() string {
return serial.Concat(v...) return serial.Concat(v...)
} }
// SliceBySize splits the beginning of this MultiBuffer into another one, for at most size bytes.
func (mb *MultiBuffer) SliceBySize(size int32) MultiBuffer {
slice := make(MultiBuffer, 0, 10)
sliceSize := int32(0)
endIndex := len(*mb)
for i, b := range *mb {
if b.Len()+sliceSize > size {
endIndex = i
break
}
sliceSize += b.Len()
slice = append(slice, b)
(*mb)[i] = nil
}
*mb = (*mb)[endIndex:]
if endIndex == 0 && len(*mb) > 0 {
b := New()
common.Must2(b.ReadFullFrom((*mb)[0], size))
return MultiBuffer{b}
}
return slice
}
// MultiBufferContainer is a ReadWriteCloser wrapper over MultiBuffer. // MultiBufferContainer is a ReadWriteCloser wrapper over MultiBuffer.
type MultiBufferContainer struct { type MultiBufferContainer struct {
MultiBuffer MultiBuffer

2
common/buf/multi_buffer_test.go

@ -44,6 +44,6 @@ func TestMultiBufferSliceBySizeLarge(t *testing.T) {
mb := MergeBytes(nil, lb) mb := MergeBytes(nil, lb)
mb2 := mb.SliceBySize(1024) mb, mb2 := SplitSize(mb, 1024)
assert(mb2.Len(), Equals, int32(1024)) assert(mb2.Len(), Equals, int32(1024))
} }

3
common/buf/reader.go

@ -87,7 +87,8 @@ func (r *BufferedReader) ReadAtMost(size int32) (MultiBuffer, error) {
r.Buffer = mb r.Buffer = mb
} }
mb := r.Buffer.SliceBySize(size) rb, mb := SplitSize(r.Buffer, size)
r.Buffer = rb
if r.Buffer.IsEmpty() { if r.Buffer.IsEmpty() {
r.Buffer = nil r.Buffer = nil
} }

3
common/crypto/chunk.go

@ -143,7 +143,8 @@ func (w *ChunkStreamWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
mb2Write := make(buf.MultiBuffer, 0, mbLen/buf.Size+mbLen/sliceSize+2) mb2Write := make(buf.MultiBuffer, 0, mbLen/buf.Size+mbLen/sliceSize+2)
for { for {
slice := mb.SliceBySize(sliceSize) mb2, slice := buf.SplitSize(mb, sliceSize)
mb = mb2
b := buf.New() b := buf.New()
w.sizeEncoder.Encode(uint16(slice.Len()), b.Extend(w.sizeEncoder.SizeBytes())) w.sizeEncoder.Encode(uint16(slice.Len()), b.Extend(w.sizeEncoder.SizeBytes()))

2
common/mux/writer.go

@ -94,7 +94,7 @@ func (w *Writer) WriteMultiBuffer(mb buf.MultiBuffer) error {
for !mb.IsEmpty() { for !mb.IsEmpty() {
var chunk buf.MultiBuffer var chunk buf.MultiBuffer
if w.transferType == protocol.TransferTypeStream { if w.transferType == protocol.TransferTypeStream {
chunk = mb.SliceBySize(8 * 1024) mb, chunk = buf.SplitSize(mb, 8*1024)
} else { } else {
mb2, b := buf.SplitFirst(mb) mb2, b := buf.SplitFirst(mb)
mb = mb2 mb = mb2

Loading…
Cancel
Save