Check-in [46da7a6ae9]
Overview
Comment:Extracted SizedWriter to a sizedWriter struct with a Write() method.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 46da7a6ae933a799da23fba4c3d096e592f39934
User & Date: spaskalev on 2014-12-25 00:26:02
Other Links: manifest | tags
Context
2014-12-25
00:43
Extracted predictor's compressor and decompressor code into separate structs that embed Sized{Writer,Reader} check-in: 50507bd510 user: spaskalev tags: trunk
00:26
Extracted SizedWriter to a sizedWriter struct with a Write() method. check-in: 46da7a6ae9 user: spaskalev tags: trunk
2014-12-24
23:58
0dev.org/ioutil/SizedReader is now as fast as bufio.Reader if not faster for a buffer of 4096 bytes. Switched pdc to use it for decompression buffering and removed profiling code from the former check-in: 2cec92909f user: spaskalev tags: trunk
Changes

Modified src/0dev.org/ioutil/ioutil.go from [9862ea3396] to [c11fdb5a53].

23
24
25
26
27
28
29


30



31




32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100






101
102
103
104
105
106
107

// Returns a writer that delegates calls to Write(...) while ensuring
// that it is never called with less bytes than the specified amount.
//
// Calls with fewer bytes are buffered while a call with a nil slice
// causes the buffer to be flushed to the underlying writer.
func SizedWriter(writer io.Writer, size int) io.Writer {


	var buffer []byte = make([]byte, 0, size)



	var write WriterFunc






	write = func(input []byte) (int, error) {
		var (
			count int
			err   error
		)

		// Flush the buffer when called with no bytes to write
		if input == nil {
			// Call the writer with whatever we have in store..
			count, err = writer.Write(buffer)

			// Advance the buffer
			buffer = buffer[:copy(buffer, buffer[count:])]

			return 0, err
		}

		// Delegate to the writer if the size is right
		if len(buffer) == 0 && len(input) >= size {
			reduced := (len(input) / size) * size
			count, err = writer.Write(input[:reduced])
			if count < reduced || err != nil {
				return count, err
			}

			// Stage any remaining data in the buffer
			buffer = append(buffer, input[count:]...)
			return len(input), nil
		}

		// Append data to the buffer
		count = copy(buffer[len(buffer):size], input)
		buffer = buffer[:len(buffer)+count]

		// Return if we don't have enough bytes to write
		if len(buffer) < size {
			return len(input), nil
		}

		// Flush the buffer as it is filled
		_, err = write(nil)
		if err != nil {
			return count, err
		}

		// Handle the rest of the input
		return write(input[count:])
	}

	return write
}

type sizedReader struct {
	reader         io.Reader
	buffer         []byte
	from, to, size int
}

// Returns a reader that delegates calls to Read(...) while ensuring
// that the output buffer is never smaller than the required size
// and is downsized to a multiple of the required size if larger.
func SizedReader(reader io.Reader, size int) io.Reader {
	var sr sizedReader
	sr.reader = reader
	sr.buffer = make([]byte, size)
	sr.size, sr.from, sr.to = size, 0, 0
	return &sr
}







func (sr *sizedReader) Read(output []byte) (int, error) {
	var (
		count int
		err   error
	)








>
>
|
>
>
>
|
>
>
>
>
|
>
|
|
|
|
|

|
|
|
|

|
|

|
|

|
|
|
|
|
|
|

|
|
|
|

|
|
|

|
|
|
|

|
|
|
|
|

|
|
<
<
<
<
<
<
<
<
<












>
>
>
>
>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89









90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

// Returns a writer that delegates calls to Write(...) while ensuring
// that it is never called with less bytes than the specified amount.
//
// Calls with fewer bytes are buffered while a call with a nil slice
// causes the buffer to be flushed to the underlying writer.
func SizedWriter(writer io.Writer, size int) io.Writer {
	var sw sizedWriter
	sw.writer = writer
	sw.buffer = make([]byte, 0, size)
	sw.size = size
	return &sw
}

type sizedWriter struct {
	writer io.Writer
	buffer []byte
	size   int
}

func (sw *sizedWriter) Write(input []byte) (int, error) {
	var (
		count int
		err   error
	)

	// Flush the buffer when called with no bytes to write
	if input == nil {
		// Call the writer with whatever we have in store..
		count, err = sw.writer.Write(sw.buffer)

		// Advance the buffer
		sw.buffer = sw.buffer[:copy(sw.buffer, sw.buffer[count:])]

		return 0, err
	}

	// Delegate to the writer if the size is right
	if len(sw.buffer) == 0 && len(input) >= sw.size {
		reduced := (len(input) / sw.size) * sw.size
		count, err = sw.writer.Write(input[:reduced])
		if count < reduced || err != nil {
			return count, err
		}

		// Stage any remaining data in the buffer
		sw.buffer = append(sw.buffer, input[count:]...)
		return len(input), nil
	}

	// Append data to the buffer
	count = copy(sw.buffer[len(sw.buffer):sw.size], input)
	sw.buffer = sw.buffer[:len(sw.buffer)+count]

	// Return if we don't have enough bytes to write
	if len(sw.buffer) < sw.size {
		return len(input), nil
	}

	// Flush the buffer as it is filled
	_, err = sw.Write(nil)
	if err != nil {
		return count, err
	}

	// Handle the rest of the input
	return sw.Write(input[count:])









}

// Returns a reader that delegates calls to Read(...) while ensuring
// that the output buffer is never smaller than the required size
// and is downsized to a multiple of the required size if larger.
func SizedReader(reader io.Reader, size int) io.Reader {
	var sr sizedReader
	sr.reader = reader
	sr.buffer = make([]byte, size)
	sr.size, sr.from, sr.to = size, 0, 0
	return &sr
}

type sizedReader struct {
	reader         io.Reader
	buffer         []byte
	from, to, size int
}

func (sr *sizedReader) Read(output []byte) (int, error) {
	var (
		count int
		err   error
	)