1 /*
2 * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
24 */
25
26 package java.util.zip;
27
28 import java.nio.ByteBuffer;
29 import sun.nio.ch.DirectBuffer;
30
31 /**
32 * A class that can be used to compute the Adler-32 checksum of a data
33 * stream. An Adler-32 checksum is almost as reliable as a CRC-32 but
34 * can be computed much faster.
35 *
36 * <p> Passing a {@code null} argument to a method in this class will cause
37 * a {@link NullPointerException} to be thrown.
38 *
39 * @see Checksum
40 * @author David Connelly
41 */
42 public
43 class Adler32 implements Checksum {
44
45 private int adler = 1;
46
47 /**
48 * Creates a new Adler32 object.
49 */
50 public Adler32() {
51 }
52
53 /**
54 * Updates the checksum with the specified byte (the low eight
55 * bits of the argument b).
56 *
57 * @param b the byte to update the checksum with
58 */
59 public void update(int b) {
60 adler = update(adler, b);
61 }
62
63 /**
64 * Updates the checksum with the specified array of bytes.
65 */
66 public void update(byte[] b, int off, int len) {
67 if (b == null) {
68 throw new NullPointerException();
69 }
70 if (off < 0 || len < 0 || off > b.length - len) {
71 throw new ArrayIndexOutOfBoundsException();
72 }
73 adler = updateBytes(adler, b, off, len);
74 }
75
76 /**
77 * Updates the checksum with the specified array of bytes.
78 *
79 * @param b the byte array to update the checksum with
80 */
81 public void update(byte[] b) {
82 adler = updateBytes(adler, b, 0, b.length);
83 }
84
85
86 /**
87 * Updates the checksum with the bytes from the specified buffer.
88 *
89 * The checksum is updated using
90 * buffer.{@link java.nio.Buffer#remaining() remaining()}
91 * bytes starting at
92 * buffer.{@link java.nio.Buffer#position() position()}
93 * Upon return, the buffer's position will be updated to its
94 * limit; its limit will not have been changed.
95 *
96 * @param buffer the ByteBuffer to update the checksum with
97 * @since 1.8
98 */
99 public void update(ByteBuffer buffer) {
100 int pos = buffer.position();
101 int limit = buffer.limit();
102 assert (pos <= limit);
103 int rem = limit - pos;
104 if (rem <= 0)
105 return;
106 if (buffer instanceof DirectBuffer) {
107 adler = updateByteBuffer(adler, ((DirectBuffer)buffer).address(), pos, rem);
108 } else if (buffer.hasArray()) {
109 adler = updateBytes(adler, buffer.array(), pos + buffer.arrayOffset(), rem);
110 } else {
111 byte[] b = new byte[rem];
112 buffer.get(b);
113 adler = updateBytes(adler, b, 0, b.length);
114 }
115 buffer.position(limit);
116 }
117
118 /**
119 * Resets the checksum to initial value.
120 */
121 public void reset() {
122 adler = 1;
123 }
124
125 /**
126 * Returns the checksum value.
127 */
128 public long getValue() {
129 return (long)adler & 0xffffffffL;
130 }
131
132 private native static int update(int adler, int b);
133 private native static int updateBytes(int adler, byte[] b, int off,
134 int len);
135 private native static int updateByteBuffer(int adler, long addr,
136 int off, int len);
137 }
|
1 /*
2 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
24 */
25
26 package java.util.zip;
27
28 import java.nio.ByteBuffer;
29 import sun.nio.ch.DirectBuffer;
30
31 /**
32 * A class that can be used to compute the Adler-32 checksum of a data
33 * stream. An Adler-32 checksum is almost as reliable as a CRC-32 but
34 * can be computed much faster.
35 *
36 * <p> Passing a {@code null} argument to a method in this class will cause
37 * a {@link NullPointerException} to be thrown.
38 *
39 * @see Checksum
40 * @author David Connelly
41 */
42 public
43 class Adler32 implements Checksum {
44 /*
45 * The Adler calculation is regarded as
46 * taking an input text T of length N = |T|,
47 * and computing two quantities, A(T) and B(T),
48 * where A(T) = 1 + sum_{0 <= i < |T|}(T_i)
49 * and B(T) = |T| + sum_{0 <= i < |T|}((|T| - i) * T_i),
50 * both modulo 65521.
51 *
52 * However, with sufficient algebraic manipulation, one can derive
53 * that A(U||V) = A(U) + A(V) - 1
54 * and B(U||V) = B(U) + B(V) + |V| (A(U) - 1).
55 *
56 * This allows recursive subdivision, if that is considered desirable.
57 */
58
59 /**
60 * The modulo operation can be deferred for MAX_SLOP bytes of input, permitting
61 * faster byte-by-byte Adler computations. 1024 is plenty conservative.
62 */
63 private final static int MAX_SLOP = 1024;
64
65 /**
66 * For inputs smaller than JAVA_ADLER_BELOW JNI overheads make it faster
67 * to compute on the Java side. (This may change as overheads and compiler
68 * quality change).
69 */
70 private final static int JAVA_ADLER_BELOW = 32;
71
72 private int adler = 1;
73 private int aa = 1;
74 private int bb = 0;
75 private int slop = 0;
76
77 /**
78 * Creates a new Adler32 object.
79 */
80 public Adler32() {
81 }
82
83 /**
84 * Updates the checksum with the specified byte (the low eight
85 * bits of the argument b).
86 *
87 * @param b the byte to update the checksum with
88 */
89 public void update(int b) {
90 int la = aa + (b & 0xFF);
91 bb = bb + la;
92 aa = la;
93 slop++;
94 if (slop == MAX_SLOP) {
95 getValueI();
96 }
97 }
98
99 /**
100 * Updates the checksum with the specified array of bytes.
101 */
102 public void update(byte[] b, int off, int len) {
103 if (b == null) {
104 throw new NullPointerException();
105 }
106 if (off < 0 || len < 0 || off > b.length - len) {
107 throw new ArrayIndexOutOfBoundsException();
108 }
109 if (len < JAVA_ADLER_BELOW) {
110 for (int i = 0; i < len; i++)
111 update(b[i+off]);
112 } else {
113 setValue(updateBytes(getValueI(), b, off, len));
114 }
115 }
116
117 /**
118 * Updates the checksum with the specified array of bytes.
119 *
120 * @param b the byte array to update the checksum with
121 */
122 public void update(byte[] b) {
123 if (b.length < JAVA_ADLER_BELOW) {
124 for (int i = 0; i < b.length; i++)
125 update(b[i]);
126 } else {
127 setValue(updateBytes(getValueI(), b, 0, b.length));
128 }
129 }
130
131 /**
132 * Updates the checksum with the bytes from the specified buffer.
133 *
134 * The checksum is updated using
135 * buffer.{@link java.nio.Buffer#remaining() remaining()}
136 * bytes starting at
137 * buffer.{@link java.nio.Buffer#position() position()}
138 * Upon return, the buffer's position will be updated to its
139 * limit; its limit will not have been changed.
140 *
141 * @param buffer the ByteBuffer to update the checksum with
142 * @since 1.8
143 */
144 public void update(ByteBuffer buffer) {
145 int pos = buffer.position();
146 int limit = buffer.limit();
147 assert (pos <= limit);
148 int rem = limit - pos;
149 if (rem <= 0)
150 return;
151 if (buffer instanceof DirectBuffer) {
152 setValue(updateByteBuffer(getValueI(), ((DirectBuffer)buffer).address(), pos, rem));
153 } else if (buffer.hasArray()) {
154 setValue(updateBytes(getValueI(), buffer.array(), pos + buffer.arrayOffset(), rem));
155 } else {
156 byte[] b = new byte[rem];
157 buffer.get(b);
158 setValue(updateBytes(getValueI(), b, 0, b.length));
159 }
160 buffer.position(limit);
161 }
162
163 /**
164 * Resets the checksum to initial value.
165 */
166 public void reset() {
167 aa = 1;
168 bb = 0;
169 adler = 1;
170 slop = 0;
171 }
172
173 /**
174 * Returns the checksum value.
175 */
176 public long getValue() {
177 return getValueI() & 0xffffffffL;
178 }
179
180 private int getValueI() {
181 if (slop > 0) {
182 aa = aa % 65521;
183 bb = bb % 65521;
184 adler = (bb << 16) + aa;
185 slop = 0;
186 }
187 return adler;
188 }
189
190 private void setValue(int newValue) {
191 aa = newValue & 0xffff;
192 bb = newValue >>> 16;
193 adler = newValue;
194 slop = 0;
195 }
196
197 private native static int update(int adler, int b);
198 private native static int updateBytes(int adler, byte[] b, int off,
199 int len);
200 private native static int updateByteBuffer(int adler, long addr,
201 int off, int len);
202 }
|