1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.io;
18
19 import java.io.Serializable;
20 import java.nio.charset.StandardCharsets;
21 import java.util.Locale;
22 import java.util.Objects;
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class ByteOrderMark implements Serializable {
48
49 private static final long serialVersionUID = 1L;
50
51
52
53
54
55
56
57
58
59
60 public static final ByteOrderMark UTF_8 = new ByteOrderMark(StandardCharsets.UTF_8.name(), 0xEF, 0xBB, 0xBF);
61
62
63
64
65
66
67
68
69
70
71 public static final ByteOrderMark UTF_16BE = new ByteOrderMark(StandardCharsets.UTF_16BE.name(), 0xFE, 0xFF);
72
73
74
75
76
77
78
79
80
81
82 public static final ByteOrderMark UTF_16LE = new ByteOrderMark(StandardCharsets.UTF_16LE.name(), 0xFF, 0xFE);
83
84
85
86
87
88
89
90
91
92
93
94
95 public static final ByteOrderMark UTF_32BE = new ByteOrderMark("UTF-32BE", 0x00, 0x00, 0xFE, 0xFF);
96
97
98
99
100
101
102
103
104
105
106
107
108 public static final ByteOrderMark UTF_32LE = new ByteOrderMark("UTF-32LE", 0xFF, 0xFE, 0x00, 0x00);
109
110
111
112
113
114
115
116 public static final char UTF_BOM = '\uFEFF';
117
118
119
120
121 private final String charsetName;
122
123
124
125
126 private final int[] bytes;
127
128
129
130
131
132
133
134
135
136 public ByteOrderMark(final String charsetName, final int... bytes) {
137 Objects.requireNonNull(charsetName, "charsetName");
138 Objects.requireNonNull(bytes, "bytes");
139 if (charsetName.isEmpty()) {
140 throw new IllegalArgumentException("No charsetName specified");
141 }
142 if (bytes.length == 0) {
143 throw new IllegalArgumentException("No bytes specified");
144 }
145 this.charsetName = charsetName;
146 this.bytes = bytes.clone();
147 }
148
149
150
151
152
153
154
155
156 @Override
157 public boolean equals(final Object obj) {
158 if (!(obj instanceof ByteOrderMark)) {
159 return false;
160 }
161 final ByteOrderMark bom = (ByteOrderMark) obj;
162 if (bytes.length != bom.length()) {
163 return false;
164 }
165 for (int i = 0; i < bytes.length; i++) {
166 if (bytes[i] != bom.get(i)) {
167 return false;
168 }
169 }
170 return true;
171 }
172
173
174
175
176
177
178
179 public int get(final int pos) {
180 return bytes[pos];
181 }
182
183
184
185
186
187
188 public byte[] getBytes() {
189 final byte[] copy = IOUtils.byteArray(bytes.length);
190 for (int i = 0; i < bytes.length; i++) {
191 copy[i] = (byte) bytes[i];
192 }
193 return copy;
194 }
195
196
197
198
199
200
201 public String getCharsetName() {
202 return charsetName;
203 }
204
205
206
207
208
209
210
211 @Override
212 public int hashCode() {
213 int hashCode = getClass().hashCode();
214 for (final int b : bytes) {
215 hashCode += b;
216 }
217 return hashCode;
218 }
219
220
221
222
223
224
225 public int length() {
226 return bytes.length;
227 }
228
229
230
231
232
233
234 @Override
235 public String toString() {
236 final StringBuilder builder = new StringBuilder();
237 builder.append(getClass().getSimpleName());
238 builder.append('[');
239 builder.append(charsetName);
240 builder.append(": ");
241 for (int i = 0; i < bytes.length; i++) {
242 if (i > 0) {
243 builder.append(",");
244 }
245 builder.append("0x");
246 builder.append(Integer.toHexString(0xFF & bytes[i]).toUpperCase(Locale.ROOT));
247 }
248 builder.append(']');
249 return builder.toString();
250 }
251
252 }