1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.archive.util.ms;
24
25 import java.io.IOException;
26
27 import org.archive.io.Endian;
28 import org.archive.io.SeekInputStream;
29 import org.archive.io.SeekReader;
30
31
32 class PieceReader extends SeekReader {
33
34
35 private PieceTable table;
36 private SeekInputStream doc;
37
38 private boolean unicode;
39 private int charPos;
40 private int limit;
41
42
43 public PieceReader(PieceTable table, SeekInputStream doc)
44 throws IOException {
45 this.table = table;
46 this.doc = doc;
47 charPos = 0;
48 limit = -1;
49 }
50
51
52 private void seekIfNecessary() throws IOException {
53 if (doc == null) {
54 throw new IOException("Stream closed.");
55 }
56 if (charPos >= table.getMaxCharPos()) {
57 return;
58 }
59 if (charPos < limit) {
60 return;
61 }
62 Piece piece = table.next();
63 unicode = piece.isUnicode();
64 limit = piece.getCharPosLimit();
65 doc.position(piece.getFilePos());
66 }
67
68
69 public int read() throws IOException {
70 seekIfNecessary();
71 if (doc == null) {
72 throw new IOException("Stream closed.");
73 }
74 if (charPos >= table.getMaxCharPos()) {
75 return -1;
76 }
77
78 int ch;
79 if (unicode) {
80 ch = Endian.littleChar(doc);
81 } else {
82 ch = Cp1252.decode(doc.read());
83 }
84 charPos++;
85 return ch;
86 }
87
88
89 public int read(char[] buf, int ofs, int len) throws IOException {
90
91
92 seekIfNecessary();
93 if (doc == null) {
94 throw new IOException("Stream closed.");
95 }
96 if (charPos >= table.getMaxCharPos()) {
97 return 0;
98 }
99 for (int i = 0; i < len; i++) {
100 int ch = read();
101 if (ch < 0) {
102 return i;
103 }
104 buf[ofs + i] = (char)ch;
105 }
106 return len;
107 }
108
109
110 public void close() throws IOException {
111 doc.close();
112 table = null;
113 }
114
115
116 public long position() throws IOException {
117 return charPos;
118 }
119
120
121 public void position(long p) throws IOException {
122 if (p > Integer.MAX_VALUE) {
123 throw new IOException("File too large.");
124 }
125 int charPos = (int)p;
126 Piece piece = table.pieceFor(charPos);
127 if (piece == null) {
128 throw new IOException("Illegal position: " + p);
129 }
130 unicode = piece.isUnicode();
131 limit = piece.getCharPosLimit();
132
133 int ofs = charPos - piece.getCharPosStart();
134 this.charPos = charPos;
135 doc.position(piece.getFilePos() + ofs);
136 }
137 }