Skip to content

Commit 0cdef7d

Browse files
author
Douglas Crockford
committed
JSONzip
1 parent 327e9a5 commit 0cdef7d

14 files changed

+2706
-0
lines changed

zip/BitInputStream.java

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package org.json.zip;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
6+
/*
7+
Copyright (c) 2013 JSON.org
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in all
17+
copies or substantial portions of the Software.
18+
19+
The Software shall be used for Good, not Evil.
20+
21+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27+
SOFTWARE.
28+
*/
29+
30+
/**
31+
* This is a big endian bit reader. It reads its bits from an InputStream.
32+
*
33+
* @version 2013-04-18
34+
*
35+
*/
36+
public class BitInputStream implements BitReader {
37+
/**
38+
* 2^n - 1
39+
*/
40+
static final int[] mask = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
41+
42+
/**
43+
* The number of bits remaining in the current byte.
44+
*/
45+
private int available = 0;
46+
47+
/**
48+
* Up to a byte's worth of unread bits.
49+
*/
50+
private int unread = 0;
51+
52+
/**
53+
* The source of the bits.
54+
*/
55+
private InputStream in;
56+
57+
/**
58+
* The number of bits read so far. This is used in padding.
59+
*/
60+
private long nrBits = 0;
61+
62+
/**
63+
* Make a BitReader from an InputStream. The BitReader will take bytes from
64+
* the InputStream and unpack them into bits.
65+
*
66+
* @param in
67+
* An InputStream.
68+
*/
69+
public BitInputStream(InputStream in) {
70+
this.in = in;
71+
}
72+
73+
/**
74+
* Make a BitReader. The first byte is passed in explicitly, the remaining
75+
* bytes are obtained from the InputStream. This makes it possible to look
76+
* at the first byte of a stream before deciding that it should be read as
77+
* bits.
78+
*
79+
* @param in
80+
* An InputStream
81+
* @param firstByte
82+
* The first byte, which was probably read from in.
83+
*/
84+
public BitInputStream(InputStream in, int firstByte) {
85+
this.in = in;
86+
this.unread = firstByte;
87+
this.available = 8;
88+
}
89+
90+
/**
91+
* Read one bit.
92+
*
93+
* @return true if it is a 1 bit.
94+
*/
95+
public boolean bit() throws IOException {
96+
return read(1) != 0;
97+
}
98+
99+
/**
100+
* Get the number of bits that have been read from this BitInputStream.
101+
* This includes pad bits that have been skipped, but might not include
102+
* bytes that have been read from the underlying InputStream that have not
103+
* yet been delivered as bits.
104+
*
105+
* @return The number of bits read so far.
106+
*/
107+
public long nrBits() {
108+
return this.nrBits;
109+
}
110+
111+
/**
112+
* Check that the rest of the block has been padded with zeroes.
113+
*
114+
* @param factor
115+
* The size of the block to pad. This will typically be 8, 16,
116+
* 32, 64, 128, 256, etc.
117+
* @return true if the block was zero padded, or false if the the padding
118+
* contains any one bits.
119+
* @throws IOException
120+
*/
121+
public boolean pad(int factor) throws IOException {
122+
int padding = factor - (int) (this.nrBits % factor);
123+
boolean result = true;
124+
125+
for (int i = 0; i < padding; i += 1) {
126+
if (bit()) {
127+
result = false;
128+
}
129+
}
130+
return result;
131+
}
132+
133+
/**
134+
* Read some bits.
135+
*
136+
* @param width
137+
* The number of bits to read. (0..32)
138+
* @throws IOException
139+
* @return the bits
140+
*/
141+
public int read(int width) throws IOException {
142+
if (width == 0) {
143+
return 0;
144+
}
145+
if (width < 0 || width > 32) {
146+
throw new IOException("Bad read width.");
147+
}
148+
int result = 0;
149+
while (width > 0) {
150+
if (this.available == 0) {
151+
this.unread = this.in.read();
152+
if (this.unread < 0) {
153+
throw new IOException("Attempt to read past end.");
154+
}
155+
this.available = 8;
156+
}
157+
int take = width;
158+
if (take > this.available) {
159+
take = this.available;
160+
}
161+
result |= ((this.unread >>> (this.available - take)) & mask[take])
162+
<< (width - take);
163+
this.nrBits += take;
164+
this.available -= take;
165+
width -= take;
166+
}
167+
return result;
168+
}
169+
}

zip/BitOutputStream.java

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package org.json.zip;
2+
3+
import java.io.IOException;
4+
import java.io.OutputStream;
5+
6+
/*
7+
Copyright (c) 2013 JSON.org
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in all
17+
copies or substantial portions of the Software.
18+
19+
The Software shall be used for Good, not Evil.
20+
21+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27+
SOFTWARE.
28+
*/
29+
30+
/**
31+
* This is a big endian bit writer. It writes its bits to an OutputStream.
32+
*
33+
* @version 2013-04-18
34+
*
35+
*/
36+
public class BitOutputStream implements BitWriter {
37+
38+
/**
39+
* The number of bits written.
40+
*/
41+
private long nrBits = 0;
42+
43+
/**
44+
* The destination of the bits.
45+
*/
46+
private OutputStream out;
47+
48+
/**
49+
* Holder of bits not yet written.
50+
*/
51+
private int unwritten;
52+
53+
/**
54+
* The number of unused bits in this.unwritten.
55+
*/
56+
private int vacant = 8;
57+
58+
/**
59+
* Use an OutputStream to produce a BitWriter. The BitWriter will send its
60+
* bits to the OutputStream as each byte is filled.
61+
*
62+
* @param out
63+
* An Output Stream
64+
*/
65+
public BitOutputStream(OutputStream out) {
66+
this.out = out;
67+
}
68+
69+
/**
70+
* Returns the number of bits that have been written to this
71+
* bitOutputStream. This may include bits that have not yet been written
72+
* to the underlying outputStream.
73+
*/
74+
public long nrBits() {
75+
return this.nrBits;
76+
}
77+
78+
/**
79+
* Write a 1 bit.
80+
*
81+
* @throws IOException
82+
*/
83+
public void one() throws IOException {
84+
write(1, 1);
85+
}
86+
87+
/**
88+
* Pad the rest of the block with zeroes and flush. pad(8) flushes the last
89+
* unfinished byte. The underlying OutputStream will be flushed.
90+
*
91+
* @param factor
92+
* The size of the block to pad. This will typically be 8, 16,
93+
* 32, 64, 128, 256, etc.
94+
* @return this
95+
* @throws IOException
96+
*/
97+
public void pad(int factor) throws IOException {
98+
int padding = factor - (int) (nrBits % factor);
99+
int excess = padding & 7;
100+
if (excess > 0) {
101+
this.write(0, excess);
102+
padding -= excess;
103+
}
104+
while (padding > 0) {
105+
this.write(0, 8);
106+
padding -= 8;
107+
}
108+
this.out.flush();
109+
}
110+
111+
/**
112+
* Write some bits. Up to 32 bits can be written at a time.
113+
*
114+
* @param bits
115+
* The bits to be written.
116+
* @param width
117+
* The number of bits to write. (0..32)
118+
* @throws IOException
119+
*/
120+
public void write(int bits, int width) throws IOException {
121+
if (bits == 0 && width == 0) {
122+
return;
123+
}
124+
if (width <= 0 || width > 32) {
125+
throw new IOException("Bad write width.");
126+
}
127+
while (width > 0) {
128+
int actual = width;
129+
if (actual > this.vacant) {
130+
actual = this.vacant;
131+
}
132+
this.unwritten |= ((bits >>> (width - actual)) &
133+
BitInputStream.mask[actual]) << (this.vacant - actual);
134+
width -= actual;
135+
nrBits += actual;
136+
this.vacant -= actual;
137+
if (this.vacant == 0) {
138+
this.out.write(this.unwritten);
139+
this.unwritten = 0;
140+
this.vacant = 8;
141+
}
142+
}
143+
}
144+
145+
/**
146+
* Write a 0 bit.
147+
*
148+
* @throws IOException
149+
*/
150+
public void zero() throws IOException {
151+
write(0, 1);
152+
153+
}
154+
}

zip/BitReader.java

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.json.zip;
2+
3+
import java.io.IOException;
4+
5+
public interface BitReader {
6+
/**
7+
* Read one bit.
8+
*
9+
* @return true if it is a 1 bit.
10+
*/
11+
public boolean bit() throws IOException;
12+
13+
/**
14+
* Returns the number of bits that have been read from this bitreader.
15+
*
16+
* @return The number of bits read so far.
17+
*/
18+
public long nrBits();
19+
20+
/**
21+
* Check that the rest of the block has been padded with zeroes.
22+
*
23+
* @param factor
24+
* The size in bits of the block to pad. This will typically be
25+
* 8, 16, 32, 64, 128, 256, etc.
26+
* @return true if the block was zero padded, or false if the the padding
27+
* contained any one bits.
28+
* @throws IOException
29+
*/
30+
public boolean pad(int factor) throws IOException;
31+
32+
/**
33+
* Read some bits.
34+
*
35+
* @param width
36+
* The number of bits to read. (0..32)
37+
* @throws IOException
38+
* @return the bits
39+
*/
40+
public int read(int width) throws IOException;
41+
}

0 commit comments

Comments
 (0)