001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.codec.digest; 019 020import java.util.Objects; 021import java.util.function.Supplier; 022import java.util.zip.Checksum; 023 024/** 025 * CRC-16 checksum implementations you can customize with a table and init value. 026 * <p> 027 * Since there are so many CRC-16 variants, we do not pick a default. 028 * </p> 029 * <p> 030 * For example, to create a create a custom variant of CRC16-MODBUS with an init value of {@code 0x0000}, use: 031 * </p> 032 * 033 * <pre> 034 * Checksum crc16 = CRC16.builder().setTable(CRC16.getModbusTable()).setInit(0x0000).get(); 035 * </pre> 036 * 037 * @see <a href="https://en.wikipedia.org/wiki/Cyclic_redundancy_check">Cyclic redundancy check</a> 038 * @see <a href="https://reveng.sourceforge.io/crc-catalogue/16.htm">Catalogue of parametrised CRC algorithms with 16 bits</a> 039 * @see <a href="https://www.lammertbies.nl/comm/info/crc-calculation">On-line CRC calculation and free library</a> 040 * @see <a href="https://crccalc.com/?crc=123456789&method=&datatype=ascii&outtype=hex">crccalc</a> 041 * @since 1.20.0 042 */ 043public final class Crc16 implements Checksum { 044 045 /** 046 * Builds {@link Crc16} instances. 047 */ 048 public static final class Builder implements Supplier<Crc16> { 049 050 private int init; 051 private int[] table; 052 private int xorOut; 053 054 /** 055 * Constructs a new instance. 056 */ 057 public Builder() { 058 // empty 059 } 060 061 /** 062 * Creates a new {@link Crc16} instance. 063 */ 064 @Override 065 public Crc16 get() { 066 return new Crc16(this); 067 } 068 069 /** 070 * Sets the initial value. 071 * 072 * @param init the initial value. 073 * @return {@code this} instance. 074 */ 075 public Builder setInit(final int init) { 076 this.init = init; 077 return this; 078 } 079 080 /** 081 * Sets the lookup table. 082 * 083 * @param table the lookup table, making a clone of the input array, must not be null. 084 * @return {@code this} instance. 085 */ 086 public Builder setTable(final int[] table) { 087 return table(Objects.requireNonNull(table, "table").clone()); 088 } 089 090 /** 091 * Sets the XorOut value to XOR to the current checksum returned by {@link Crc16#getValue()}. 092 * 093 * @param xorOut the XorOut value. 094 * @return {@code this} instance. 095 */ 096 public Builder setXorOut(final int xorOut) { 097 this.xorOut = xorOut; 098 return this; 099 } 100 101 /** 102 * Sets the lookup table without making a clone. 103 * 104 * @param table the lookup table, must not be null. 105 * @return {@code this} instance. 106 */ 107 private Builder table(final int[] table) { 108 this.table = Objects.requireNonNull(table, "table"); 109 return this; 110 } 111 } 112 113 // @formatter:off 114 private static final int[] ARC = { 115 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 116 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 117 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 118 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 119 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 120 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 121 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 122 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 123 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 124 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 125 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 126 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 127 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 128 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 129 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 130 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 131 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 132 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 133 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 134 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 135 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 136 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 137 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 138 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 139 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 140 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 141 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 142 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 143 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 144 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 145 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 146 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 147 }; 148 private static final int ARC_INIT = 0x0000; 149 private static final int[] CCITT = { 150 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 151 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, 152 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, 153 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, 154 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, 155 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, 156 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, 157 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, 158 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, 159 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, 160 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, 161 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, 162 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, 163 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, 164 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, 165 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, 166 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, 167 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, 168 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, 169 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, 170 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, 171 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, 172 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, 173 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, 174 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, 175 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, 176 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, 177 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, 178 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, 179 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, 180 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, 181 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 182 }; 183 private static final int CCITT_INIT = 0x0000; 184 private static final int[] DNP = { 185 0x0000, 0x365E, 0x6CBC, 0x5AE2, 0xD978, 0xEF26, 0xB5C4, 0x839A, 186 0xFF89, 0xC9D7, 0x9335, 0xA56B, 0x26F1, 0x10AF, 0x4A4D, 0x7C13, 187 0xB26B, 0x8435, 0xDED7, 0xE889, 0x6B13, 0x5D4D, 0x07AF, 0x31F1, 188 0x4DE2, 0x7BBC, 0x215E, 0x1700, 0x949A, 0xA2C4, 0xF826, 0xCE78, 189 0x29AF, 0x1FF1, 0x4513, 0x734D, 0xF0D7, 0xC689, 0x9C6B, 0xAA35, 190 0xD626, 0xE078, 0xBA9A, 0x8CC4, 0x0F5E, 0x3900, 0x63E2, 0x55BC, 191 0x9BC4, 0xAD9A, 0xF778, 0xC126, 0x42BC, 0x74E2, 0x2E00, 0x185E, 192 0x644D, 0x5213, 0x08F1, 0x3EAF, 0xBD35, 0x8B6B, 0xD189, 0xE7D7, 193 0x535E, 0x6500, 0x3FE2, 0x09BC, 0x8A26, 0xBC78, 0xE69A, 0xD0C4, 194 0xACD7, 0x9A89, 0xC06B, 0xF635, 0x75AF, 0x43F1, 0x1913, 0x2F4D, 195 0xE135, 0xD76B, 0x8D89, 0xBBD7, 0x384D, 0x0E13, 0x54F1, 0x62AF, 196 0x1EBC, 0x28E2, 0x7200, 0x445E, 0xC7C4, 0xF19A, 0xAB78, 0x9D26, 197 0x7AF1, 0x4CAF, 0x164D, 0x2013, 0xA389, 0x95D7, 0xCF35, 0xF96B, 198 0x8578, 0xB326, 0xE9C4, 0xDF9A, 0x5C00, 0x6A5E, 0x30BC, 0x06E2, 199 0xC89A, 0xFEC4, 0xA426, 0x9278, 0x11E2, 0x27BC, 0x7D5E, 0x4B00, 200 0x3713, 0x014D, 0x5BAF, 0x6DF1, 0xEE6B, 0xD835, 0x82D7, 0xB489, 201 0xA6BC, 0x90E2, 0xCA00, 0xFC5E, 0x7FC4, 0x499A, 0x1378, 0x2526, 202 0x5935, 0x6F6B, 0x3589, 0x03D7, 0x804D, 0xB613, 0xECF1, 0xDAAF, 203 0x14D7, 0x2289, 0x786B, 0x4E35, 0xCDAF, 0xFBF1, 0xA113, 0x974D, 204 0xEB5E, 0xDD00, 0x87E2, 0xB1BC, 0x3226, 0x0478, 0x5E9A, 0x68C4, 205 0x8F13, 0xB94D, 0xE3AF, 0xD5F1, 0x566B, 0x6035, 0x3AD7, 0x0C89, 206 0x709A, 0x46C4, 0x1C26, 0x2A78, 0xA9E2, 0x9FBC, 0xC55E, 0xF300, 207 0x3D78, 0x0B26, 0x51C4, 0x679A, 0xE400, 0xD25E, 0x88BC, 0xBEE2, 208 0xC2F1, 0xF4AF, 0xAE4D, 0x9813, 0x1B89, 0x2DD7, 0x7735, 0x416B, 209 0xF5E2, 0xC3BC, 0x995E, 0xAF00, 0x2C9A, 0x1AC4, 0x4026, 0x7678, 210 0x0A6B, 0x3C35, 0x66D7, 0x5089, 0xD313, 0xE54D, 0xBFAF, 0x89F1, 211 0x4789, 0x71D7, 0x2B35, 0x1D6B, 0x9EF1, 0xA8AF, 0xF24D, 0xC413, 212 0xB800, 0x8E5E, 0xD4BC, 0xE2E2, 0x6178, 0x5726, 0x0DC4, 0x3B9A, 213 0xDC4D, 0xEA13, 0xB0F1, 0x86AF, 0x0535, 0x336B, 0x6989, 0x5FD7, 214 0x23C4, 0x159A, 0x4F78, 0x7926, 0xFABC, 0xCCE2, 0x9600, 0xA05E, 215 0x6E26, 0x5878, 0x029A, 0x34C4, 0xB75E, 0x8100, 0xDBE2, 0xEDBC, 216 0x91AF, 0xA7F1, 0xFD13, 0xCB4D, 0x48D7, 0x7E89, 0x246B, 0x1235 217 }; 218 private static final int DNP_INIT = 0x0000; 219 private static final int DNP_XOROUT = 0xFFFF; 220 private static final int[] IBM_SDLC = CCITT; 221 private static final int IBM_SDLC_INIT = 0xFFFF; 222 private static final int IBM_SDLC_XOROUT = 0xFFFF; 223 private static final int[] MAXIM = ARC; 224 private static final int MAXIM_INIT = 0x0000; 225 private static final int MAXIM_XOROUT = 0xFFFF; 226 private static final int[] MCRF4XX = CCITT; 227 private static final int MCRF4XX_INIT = 0xFFFF; 228 private static final int[] MODBUS = ARC; 229 private static final int MODBUS_INIT = 0xFFFF; 230 private static final int[] NRSC5 = { 231 0x0000, 0x35A4, 0x6B48, 0x5EEC, 0xD690, 0xE334, 0xBDD8, 0x887C, 232 0x0D01, 0x38A5, 0x6649, 0x53ED, 0xDB91, 0xEE35, 0xB0D9, 0x857D, 233 0x1A02, 0x2FA6, 0x714A, 0x44EE, 0xCC92, 0xF936, 0xA7DA, 0x927E, 234 0x1703, 0x22A7, 0x7C4B, 0x49EF, 0xC193, 0xF437, 0xAADB, 0x9F7F, 235 0x3404, 0x01A0, 0x5F4C, 0x6AE8, 0xE294, 0xD730, 0x89DC, 0xBC78, 236 0x3905, 0x0CA1, 0x524D, 0x67E9, 0xEF95, 0xDA31, 0x84DD, 0xB179, 237 0x2E06, 0x1BA2, 0x454E, 0x70EA, 0xF896, 0xCD32, 0x93DE, 0xA67A, 238 0x2307, 0x16A3, 0x484F, 0x7DEB, 0xF597, 0xC033, 0x9EDF, 0xAB7B, 239 0x6808, 0x5DAC, 0x0340, 0x36E4, 0xBE98, 0x8B3C, 0xD5D0, 0xE074, 240 0x6509, 0x50AD, 0x0E41, 0x3BE5, 0xB399, 0x863D, 0xD8D1, 0xED75, 241 0x720A, 0x47AE, 0x1942, 0x2CE6, 0xA49A, 0x913E, 0xCFD2, 0xFA76, 242 0x7F0B, 0x4AAF, 0x1443, 0x21E7, 0xA99B, 0x9C3F, 0xC2D3, 0xF777, 243 0x5C0C, 0x69A8, 0x3744, 0x02E0, 0x8A9C, 0xBF38, 0xE1D4, 0xD470, 244 0x510D, 0x64A9, 0x3A45, 0x0FE1, 0x879D, 0xB239, 0xECD5, 0xD971, 245 0x460E, 0x73AA, 0x2D46, 0x18E2, 0x909E, 0xA53A, 0xFBD6, 0xCE72, 246 0x4B0F, 0x7EAB, 0x2047, 0x15E3, 0x9D9F, 0xA83B, 0xF6D7, 0xC373, 247 0xD010, 0xE5B4, 0xBB58, 0x8EFC, 0x0680, 0x3324, 0x6DC8, 0x586C, 248 0xDD11, 0xE8B5, 0xB659, 0x83FD, 0x0B81, 0x3E25, 0x60C9, 0x556D, 249 0xCA12, 0xFFB6, 0xA15A, 0x94FE, 0x1C82, 0x2926, 0x77CA, 0x426E, 250 0xC713, 0xF2B7, 0xAC5B, 0x99FF, 0x1183, 0x2427, 0x7ACB, 0x4F6F, 251 0xE414, 0xD1B0, 0x8F5C, 0xBAF8, 0x3284, 0x0720, 0x59CC, 0x6C68, 252 0xE915, 0xDCB1, 0x825D, 0xB7F9, 0x3F85, 0x0A21, 0x54CD, 0x6169, 253 0xFE16, 0xCBB2, 0x955E, 0xA0FA, 0x2886, 0x1D22, 0x43CE, 0x766A, 254 0xF317, 0xC6B3, 0x985F, 0xADFB, 0x2587, 0x1023, 0x4ECF, 0x7B6B, 255 0xB818, 0x8DBC, 0xD350, 0xE6F4, 0x6E88, 0x5B2C, 0x05C0, 0x3064, 256 0xB519, 0x80BD, 0xDE51, 0xEBF5, 0x6389, 0x562D, 0x08C1, 0x3D65, 257 0xA21A, 0x97BE, 0xC952, 0xFCF6, 0x748A, 0x412E, 0x1FC2, 0x2A66, 258 0xAF1B, 0x9ABF, 0xC453, 0xF1F7, 0x798B, 0x4C2F, 0x12C3, 0x2767, 259 0x8C1C, 0xB9B8, 0xE754, 0xD2F0, 0x5A8C, 0x6F28, 0x31C4, 0x0460, 260 0x811D, 0xB4B9, 0xEA55, 0xDFF1, 0x578D, 0x6229, 0x3CC5, 0x0961, 261 0x961E, 0xA3BA, 0xFD56, 0xC8F2, 0x408E, 0x752A, 0x2BC6, 0x1E62, 262 0x9B1F, 0xAEBB, 0xF057, 0xC5F3, 0x4D8F, 0x782B, 0x26C7, 0x1363 263 }; 264 // @formatter:off 265 private static final int NRSC5_INIT = 0xFFFF; 266 private static final int[] USB = ARC; 267 private static final int USB_INIT = 0xFFFF; 268 private static final int USB_XOROUT = 0xFFFF; 269 270 /** 271 * Creates a new CRC16-CCITT Checksum. 272 * 273 * <ul> 274 * <li>The init value is {@code 0x0000}.</li> 275 * <li>The XorOut value is {@code 0x0000}.</li> 276 * </ul> 277 * <p> 278 * Also known as: 279 * </p> 280 * <ul> 281 * <li>CRC-16/ARC</li> 282 * <li>ARC</li> 283 * <li>CRC-16</li> 284 * <li>CRC-16/LHA</li> 285 * <li>CRC-IBM</li> 286 * </ul> 287 * 288 * @return a new CRC16-CCITT Checksum. 289 */ 290 public static Crc16 arc() { 291 return builder().setInit(ARC_INIT).table(ARC).get(); 292 } 293 294 /** 295 * Creates a new builder. 296 * 297 * <p> 298 * Since there are so many CRC-16 variants, we do not pick a default. 299 * </p> 300 * 301 * @return a new builder. 302 */ 303 public static Builder builder() { 304 return new Builder(); 305 } 306 307 /** 308 * Creates a new CRC16-CCITT Checksum. 309 * <ul> 310 * <li>The init value is {@code 0x0000}.</li> 311 * <li>The XorOut value is {@code 0x0000}.</li> 312 * </ul> 313 * <p> 314 * Also known as: 315 * </p> 316 * <ul> 317 * <li>CRC-16/KERMIT</li> 318 * <li>CRC-16/BLUETOOTH</li> 319 * <li>CRC-16/CCITT</li> 320 * <li>CRC-16/CCITT-TRUE</li> 321 * <li>CRC-16/V-41-LSB</li> 322 * <li>CRC-CCITT</li> 323 * <li>KERMIT</li> 324 * </ul> 325 * 326 * @return a new CRC16-CCITT Checksum. 327 */ 328 public static Crc16 ccitt() { 329 return builder().setInit(CCITT_INIT).table(CCITT).get(); 330 } 331 332 /** 333 * Creates a new CRC16-DNP Checksum. 334 * 335 * <ul> 336 * <li>The init value is {@code 0x0000}.</li> 337 * <li>The XorOut value is {@code 0xFFFF}.</li> 338 * </ul> 339 * 340 * @return a new CRC16-DNP Checksum. 341 */ 342 public static Crc16 dnp() { 343 return builder().setInit(DNP_INIT).setXorOut(DNP_XOROUT).table(DNP).get(); 344 } 345 346 /** 347 * Gets a copy of the CRC16-CCITT table. 348 * 349 * @return a copy of the CCRC16-CITT table. 350 */ 351 public static int[] getArcTable() { 352 return ARC.clone(); 353 } 354 355 /** 356 * Gets a copy of the CRC16-CCITT table. 357 * 358 * @return a copy of the CCRC16-CITT table. 359 */ 360 public static int[] getCcittTable() { 361 return CCITT.clone(); 362 } 363 364 /** 365 * Gets a copy of the CRC16-DNP table. 366 * 367 * @return a copy of the CCRC16-DNP table. 368 */ 369 public static int[] getDnpTable() { 370 return DNP.clone(); 371 } 372 373 /** 374 * Gets a copy of the CRC16-IBM-SDLC table. 375 * 376 * @return a copy of the CRC16-IBM-SDLC table. 377 */ 378 public static int[] getIbmSdlcTable() { 379 return IBM_SDLC.clone(); 380 } 381 382 /** 383 * Gets a copy of the CRC16-MAXIM table. 384 * 385 * @return a copy of the CRC16-MAXIM table. 386 */ 387 public static int[] getMaximTable() { 388 return MAXIM.clone(); 389 } 390 391 /** 392 * Gets a copy of the CRC16-MCRF4XX table. 393 * 394 * @return a copy of the CRC16-MCRF4XX table. 395 */ 396 public static int[] getMcrf4xxTable() { 397 return MCRF4XX.clone(); 398 } 399 400 /** 401 * Gets a copy of the CRC16-MODBUS table. 402 * 403 * @return a copy of the CRC16-MODBUS table. 404 */ 405 public static int[] getModbusTable() { 406 return MODBUS.clone(); 407 } 408 409 /** 410 * Gets a copy of the CRC16-NRSC-5 table. 411 * 412 * @return a copy of the CRC16-NRSC-5 table. 413 */ 414 public static int[] getNrsc5Table() { 415 return NRSC5.clone(); 416 } 417 418 /** 419 * Creates a new CRC16-IBM-SDLC Checksum. 420 * 421 * <ul> 422 * <li>The init value is {@code 0xFFFF}.</li> 423 * <li>The XorOut value is {@code 0xFFFF}.</li> 424 * </ul> 425 * <p> 426 * Also known as: 427 * </p> 428 * <ul> 429 * <li>CRC-16/IBM-SDLC</li> 430 * <li>CRC-16/ISO-HDLC</li> 431 * <li>CRC-16/ISO-IEC-14443-3-B</li> 432 * <li>CRC-16/X-25</li> 433 * <li>CRC-B</li> 434 * <li>X-25</li> 435 * </ul> 436 * 437 * @return a new CRC16-IBM-SDLC Checksum. 438 */ 439 public static Crc16 ibmSdlc() { 440 return builder().setInit(IBM_SDLC_INIT).setXorOut(IBM_SDLC_XOROUT).table(IBM_SDLC).get(); 441 } 442 443 /** 444 * Creates a new instance for CRC16-MAXIM Checksum. 445 * 446 * <p> 447 * CRC-16 checksum implementation based on polynomial {@code x<sup>16</spu> + x^15 + x^2 + 1 (0x8005)}. 448 * </p> 449 * <ul> 450 * <li>The init value is {@code 0xFFFF}.</li> 451 * <li>The XorOut value is {@code 0xFFFF}.</li> 452 * </ul> 453 * <p> 454 * Also known as: 455 * </p> 456 * <ul> 457 * <li>CRC-16/MAXIM-DOW</li> 458 * </ul> 459 * 460 * @return a new CRC16-MAXIM Checksum. 461 */ 462 public static Crc16 maxim() { 463 return builder().setInit(MAXIM_INIT).setXorOut(MAXIM_XOROUT).table(MAXIM).get(); 464 } 465 466 /** 467 * Creates a new instance for CRC16-MCRF4XX Checksum. 468 * 469 * <ul> 470 * <li>The init value is {@code 0xFFFF}.</li> 471 * <li>The XorOut value is {@code 0x0000}.</li> 472 * </ul> 473 * 474 * @return a new CRC16-MCRF4XX Checksum. 475 */ 476 public static Crc16 mcrf4xx() { 477 return builder().setInit(MCRF4XX_INIT).table(MCRF4XX).get(); 478 } 479 480 /** 481 * Creates a new instance for CRC16-MODBUS Checksum. 482 * 483 * <p> 484 * CRC-16 checksum implementation based on polynomial {@code x<sup>16</spu> + x^15 + x^2 + 1 (0x8005)}. 485 * </p> 486 * <ul> 487 * <li>The init value is {@code 0xFFFF}.</li> 488 * <li>The XorOut value is {@code 0x0000}.</li> 489 * </ul> 490 * <p> 491 * Also known as: 492 * </p> 493 * <ul> 494 * <li>CRC-16/MODBUST</li> 495 * <li>MODBUST</li> 496 * </ul> 497 * 498 * @return a new CRC16-MODBUS Checksum. 499 */ 500 public static Crc16 modbus() { 501 return builder().setInit(MODBUS_INIT).table(MODBUS).get(); 502 } 503 504 /** 505 * Creates a new instance for CRC16-NRSC-5 Checksum. 506 * 507 * <ul> 508 * <li>The init value is {@code 0xFFFF}.</li> 509 * <li>The XorOut value is {@code 0x0000}.</li> 510 * </ul> 511 * 512 * @return a new CRC16-NRSC-5 Checksum. 513 */ 514 public static Crc16 nrsc5() { 515 return builder().setInit(NRSC5_INIT).table(NRSC5).get(); 516 } 517 518 /** 519 * Creates a new instance for CRC16-USB Checksum. 520 * 521 * <ul> 522 * <li>The init value is {@code 0xFFFF}.</li> 523 * <li>The XorOut value is {@code 0xFFFF}.</li> 524 * </ul> 525 * 526 * @return a new CRC16-USB Checksum. 527 */ 528 public static Crc16 usb() { 529 return builder().setInit(USB_INIT).setXorOut(USB_XOROUT).table(USB).get(); 530 } 531 532 /** 533 * CRC. 534 */ 535 private int crc; 536 private final int init; 537 private final int[] table; 538 private final int xorOut; 539 540 /** 541 * Constructs a new instance. 542 */ 543 private Crc16(final Builder builder) { 544 this.init = builder.init; 545 this.xorOut = builder.xorOut; 546 this.crc = builder.init; 547 this.table = Objects.requireNonNull(builder.table, "table"); 548 } 549 550 @Override 551 public long getValue() { 552 return crc ^ xorOut; 553 } 554 555 @Override 556 public void reset() { 557 crc = init; 558 } 559 560 @Override 561 public String toString() { 562 return String.format("%s [init=0x%04X, crc=0x%04X, xorOut=0x%04X, crc^xorOut=0x%04X]", getClass().getSimpleName(), init, crc, xorOut, getValue()); 563 } 564 565 @Override 566 public void update(final byte[] b, final int off, final int len) { 567 final int end = len + off; 568 for (int i = off; i < end; i++) { 569 update(b[i]); 570 } 571 } 572 573 @Override 574 public void update(final int b) { 575 crc = crc >>> 8 ^ table[(crc ^ b) & 0xff]; 576 } 577}