-
Notifications
You must be signed in to change notification settings - Fork 228
Expand file tree
/
Copy pathBinaryIOWrapper.java
More file actions
120 lines (99 loc) · 3.54 KB
/
BinaryIOWrapper.java
File metadata and controls
120 lines (99 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
115
116
117
118
119
120
/* Copyright (c) 2007 Jython Developers */
package org.python.core.io;
import java.nio.ByteBuffer;
import org.python.core.util.StringUtil;
/**
* A Buffered text stream in binary mode.
*
* @author Philip Jenvey
*/
public class BinaryIOWrapper extends TextIOBase {
/**
* Contruct a TextIOBase in binary mode, wrapping the given
* BufferedIOBase.
*
* @param bufferedIO {@inheritDoc}
*/
public BinaryIOWrapper(BufferedIOBase bufferedIO) {
super(bufferedIO);
}
@Override
public String read(int size) {
if (size < 0) {
return readall();
}
if (!readahead.hasRemaining()) {
return StringUtil.fromBytes(bufferedIO.read(size));
}
ByteBuffer data = ByteBuffer.allocate(size);
if (readahead.remaining() >= size) {
// Fulfill the read entirely from the readahead
int readaheadLimit = readahead.limit();
readahead.limit(readahead.position() + size);
data.put(readahead);
readahead.limit(readaheadLimit);
data.flip();
return StringUtil.fromBytes(data);
}
// Drain the readahead then request more from the buffer
data.put(readahead);
clearReadahead();
bufferedIO.readinto(data);
data.flip();
return StringUtil.fromBytes(data);
}
@Override
public String readall() {
if (!readahead.hasRemaining()) {
return StringUtil.fromBytes(bufferedIO.readall());
}
ByteBuffer remaining = bufferedIO.readall();
ByteBuffer all = ByteBuffer.allocate(readahead.remaining() + remaining.remaining());
all.put(readahead);
clearReadahead();
all.put(remaining);
all.flip();
return StringUtil.fromBytes(all);
}
@Override
public String readline(int size) {
// Avoid ByteBuffer (this.readahead) and StringBuilder
// (this.builder) method calls in the inner loop by reading
// directly from the readahead's backing array and writing to
// an interim char array (this.interimBuilder)
byte[] readaheadArray;
int readaheadPos;
int interimBuilderPos;
do {
readaheadArray = readahead.array();
readaheadPos = readahead.position();
interimBuilderPos = 0;
while (readaheadPos < readahead.limit() &&
(size < 0 || builder.length() + interimBuilderPos < size)) {
char next = (char)(readaheadArray[readaheadPos++] & 0xff);
interimBuilder[interimBuilderPos++] = next;
if (next == '\n') {
builder.append(interimBuilder, 0, interimBuilderPos);
// Reposition the readahead to where we ended
readahead.position(readaheadPos);
return drainBuilder();
}
}
builder.append(interimBuilder, 0, interimBuilderPos);
} while ((size < 0 || builder.length() < size) && readChunk() > 0);
// Reposition the readahead to where we ended. The position is
// invalid if the readahead is empty (at EOF; readChunk()
// returned 0)
if (readahead.hasRemaining()) {
readahead.position(readaheadPos);
}
return drainBuilder();
}
@Override
public int write(String buf) {
if (readahead.hasRemaining()) {
clearReadahead();
}
return bufferedIO.write(ByteBuffer.wrap(StringUtil.toBytes(buf)));
}
}