1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.compression;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.util.ByteProcessor;
20 import io.netty.util.internal.ObjectUtil;
21 import io.netty.util.internal.PlatformDependent;
22
23 import java.lang.reflect.Method;
24 import java.nio.ByteBuffer;
25 import java.util.zip.Adler32;
26 import java.util.zip.CRC32;
27 import java.util.zip.Checksum;
28
29
30
31
32
33
34
35 abstract class ByteBufChecksum implements Checksum {
36
37
38
39
40 private static class ZlibChecksumMethods {
41 private static final Method ADLER32_UPDATE_METHOD;
42 private static final Method CRC32_UPDATE_METHOD;
43
44 static {
45
46
47 ADLER32_UPDATE_METHOD = updateByteBuffer(new Adler32());
48 CRC32_UPDATE_METHOD = updateByteBuffer(new CRC32());
49 }
50 }
51
52 private final ByteProcessor updateProcessor = new ByteProcessor() {
53 @Override
54 public boolean process(byte value) throws Exception {
55 update(value);
56 return true;
57 }
58 };
59
60 private static Method updateByteBuffer(Checksum checksum) {
61 if (PlatformDependent.javaVersion() >= 8) {
62 try {
63 Method method = checksum.getClass().getDeclaredMethod("update", ByteBuffer.class);
64 method.invoke(checksum, ByteBuffer.allocate(1));
65 return method;
66 } catch (Throwable ignore) {
67 return null;
68 }
69 }
70 return null;
71 }
72
73 static ByteBufChecksum wrapChecksum(Checksum checksum) {
74 ObjectUtil.checkNotNull(checksum, "checksum");
75 if (checksum instanceof ByteBufChecksum) {
76 return (ByteBufChecksum) checksum;
77 }
78 if (checksum instanceof Adler32 && ZlibChecksumMethods.ADLER32_UPDATE_METHOD != null) {
79 return new ReflectiveByteBufChecksum(checksum, ZlibChecksumMethods.ADLER32_UPDATE_METHOD);
80 }
81 if (checksum instanceof CRC32 && ZlibChecksumMethods.CRC32_UPDATE_METHOD != null) {
82 return new ReflectiveByteBufChecksum(checksum, ZlibChecksumMethods.CRC32_UPDATE_METHOD);
83 }
84 return new SlowByteBufChecksum(checksum);
85 }
86
87
88
89
90 public void update(ByteBuf b, int off, int len) {
91 if (b.hasArray()) {
92 update(b.array(), b.arrayOffset() + off, len);
93 } else {
94 b.forEachByte(off, len, updateProcessor);
95 }
96 }
97
98 private static final class ReflectiveByteBufChecksum extends SlowByteBufChecksum {
99 private final Method method;
100
101 ReflectiveByteBufChecksum(Checksum checksum, Method method) {
102 super(checksum);
103 this.method = method;
104 }
105
106 @Override
107 public void update(ByteBuf b, int off, int len) {
108 if (b.hasArray()) {
109 update(b.array(), b.arrayOffset() + off, len);
110 } else {
111 try {
112 method.invoke(checksum, CompressionUtil.safeNioBuffer(b, off, len));
113 } catch (Throwable cause) {
114 throw new Error();
115 }
116 }
117 }
118 }
119
120 private static class SlowByteBufChecksum extends ByteBufChecksum {
121
122 protected final Checksum checksum;
123
124 SlowByteBufChecksum(Checksum checksum) {
125 this.checksum = checksum;
126 }
127
128 @Override
129 public void update(int b) {
130 checksum.update(b);
131 }
132
133 @Override
134 public void update(byte[] b, int off, int len) {
135 checksum.update(b, off, len);
136 }
137
138 @Override
139 public long getValue() {
140 return checksum.getValue();
141 }
142
143 @Override
144 public void reset() {
145 checksum.reset();
146 }
147 }
148 }