...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ioutil
16
17 import (
18 "fmt"
19 "io"
20 )
21
22 var defaultBufferBytes = 128 * 1024
23
24
25
26 type PageWriter struct {
27 w io.Writer
28
29 pageOffset int
30
31 pageBytes int
32
33 bufferedBytes int
34
35 buf []byte
36
37
38
39 bufWatermarkBytes int
40 }
41
42
43
44 func NewPageWriter(w io.Writer, pageBytes, pageOffset int) *PageWriter {
45 if pageBytes <= 0 {
46 panic(fmt.Sprintf("assertion failed: invalid pageBytes (%d) value, it must be greater than 0", pageBytes))
47 }
48 return &PageWriter{
49 w: w,
50 pageOffset: pageOffset,
51 pageBytes: pageBytes,
52 buf: make([]byte, defaultBufferBytes+pageBytes),
53 bufWatermarkBytes: defaultBufferBytes,
54 }
55 }
56
57 func (pw *PageWriter) Write(p []byte) (n int, err error) {
58 if len(p)+pw.bufferedBytes <= pw.bufWatermarkBytes {
59
60 copy(pw.buf[pw.bufferedBytes:], p)
61 pw.bufferedBytes += len(p)
62 return len(p), nil
63 }
64
65 slack := pw.pageBytes - ((pw.pageOffset + pw.bufferedBytes) % pw.pageBytes)
66 if slack != pw.pageBytes {
67 partial := slack > len(p)
68 if partial {
69
70 slack = len(p)
71 }
72
73 copy(pw.buf[pw.bufferedBytes:], p[:slack])
74 pw.bufferedBytes += slack
75 n = slack
76 p = p[slack:]
77 if partial {
78
79 return n, nil
80 }
81 }
82
83 if err = pw.Flush(); err != nil {
84 return n, err
85 }
86
87 if len(p) > pw.pageBytes {
88 pages := len(p) / pw.pageBytes
89 c, werr := pw.w.Write(p[:pages*pw.pageBytes])
90 n += c
91 if werr != nil {
92 return n, werr
93 }
94 p = p[pages*pw.pageBytes:]
95 }
96
97 c, werr := pw.Write(p)
98 n += c
99 return n, werr
100 }
101
102
103 func (pw *PageWriter) Flush() error {
104 _, err := pw.flush()
105 return err
106 }
107
108
109 func (pw *PageWriter) FlushN() (int, error) {
110 return pw.flush()
111 }
112
113 func (pw *PageWriter) flush() (int, error) {
114 if pw.bufferedBytes == 0 {
115 return 0, nil
116 }
117 n, err := pw.w.Write(pw.buf[:pw.bufferedBytes])
118 pw.pageOffset = (pw.pageOffset + pw.bufferedBytes) % pw.pageBytes
119 pw.bufferedBytes = 0
120 return n, err
121 }
122
View as plain text