Check-in [46da7a6ae9]
Overview
SHA1:46da7a6ae933a799da23fba4c3d096e592f39934
Date: 2014-12-25 00:26:02
User: spaskalev
Comment:Extracted SizedWriter to a sizedWriter struct with a Write() method.
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | folders | manifest
Tags And Properties
Context
2014-12-25
00:43
[50507bd510] Extracted predictor's compressor and decompressor code into separate structs that embed Sized{Writer,Reader} (user: spaskalev, tags: trunk)
00:26
[46da7a6ae9] Extracted SizedWriter to a sizedWriter struct with a Write() method. (user: spaskalev, tags: trunk)
2014-12-24
23:58
[2cec92909f] 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 (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
	)