snf4j / snf4j

@@ -0,0 +1,972 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2022 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core;
27 +
28 +
import java.nio.BufferUnderflowException;
29 +
import java.nio.ByteBuffer;
30 +
import java.nio.InvalidMarkException;
31 +
32 +
/**
33 +
 * A byte buffer array wrapper providing absolute and relative get methods that
34 +
 * read data from an array of the {@link ByteBuffer} objects.
35 +
 * 
36 +
 * @author <a href="http://snf4j.org">SNF4J.ORG</a>
37 +
 */
38 +
public class ByteBufferArray {
39 +
40 +
	final ByteBuffer[] array;
41 +
42 +
	final int offset;
43 +
	
44 +
	final int size;
45 +
	
46 +
	final int end;
47 +
	
48 +
	private int index;
49 +
50 +
	private long mark = -1;
51 +
52 +
	ByteBuffer buffer;
53 +
54 +
	/**
55 +
	 * Constructs a byte buffer array wrapper that will be backed by the given
56 +
	 * {@link ByteBuffer} array.
57 +
	 * 
58 +
	 * @param array The array that will back this buffer array wrapper
59 +
	 */
60 +
	ByteBufferArray(ByteBuffer[] array) {
61 +
		this.array = array;
62 +
		size = end = array.length; 
63 +
		offset = 0;
64 +
		if (size > 0) {
65 +
			buffer = this.array[offset];
66 +
		}
67 +
	}
68 +
69 +
	/**
70 +
	 * Constructs a byte buffer array wrapper that will be backed by the given
71 +
	 * {@link ByteBuffer} array.
72 +
	 * 
73 +
	 * @param array  The array that will back this buffer array wrapper
74 +
	 * @param offset The offset of the subarray to be used
75 +
	 * @param length The length of the subarray to be used
76 +
	 * @throws IndexOutOfBoundsException If the preconditions on the offset and
77 +
	 *                                   length parameters do not hold
78 +
	 */
79 +
	ByteBufferArray(ByteBuffer[] array, int offset, int length) {
80 +
		InternalSession.checkBounds(offset, length, array.length);
81 +
		this.array = array;
82 +
		if (length > 0) {
83 +
			buffer = this.array[offset];
84 +
		}
85 +
		this.offset = offset;
86 +
		this.size = length;
87 +
		end = offset + length;
88 +
		index = offset;
89 +
	}
90 +
	
91 +
	/**
92 +
	 * Wraps an array of byte buffers into a byte buffer array wrapper that will be
93 +
	 * backed by the given array.
94 +
	 * 
95 +
	 * @param array The array that will back the returned buffer array wrapper
96 +
	 * @return The new byte buffer array wrapper
97 +
	 */
98 +
	public static ByteBufferArray wrap(ByteBuffer[] array) {
99 +
		return array.length == 1 
100 +
				? new OneByteBufferArray(array) 
101 +
				: new ByteBufferArray(array);
102 +
	}
103 +
104 +
	/**
105 +
	 * Wraps an array of byte buffers into a byte buffer array wrapper that will be
106 +
	 * backed by the given array.
107 +
	 * 
108 +
	 * @param array  The array that will back the returned buffer array wrapper
109 +
	 * @param offset The offset of the subarray to be used
110 +
	 * @param length The length of the subarray to be used
111 +
	 * @return The new byte buffer array wrapper
112 +
	 * @throws IndexOutOfBoundsException If the preconditions on the offset and
113 +
	 *                                   length parameters do not hold
114 +
	 */
115 +
	public static ByteBufferArray wrap(ByteBuffer[] array, int offset, int length) {
116 +
		return length == 1 
117 +
				? new OneByteBufferArray(array, offset, length) 
118 +
				: new ByteBufferArray(array, offset, length);
119 +
	}
120 +
	
121 +
	/**
122 +
	 * Returns the {@link ByteBuffer} array that backs this buffer array wrapper.
123 +
	 * 
124 +
	 * @return The array that backs this buffer
125 +
	 */
126 +
	public ByteBuffer[] array() {
127 +
		return array;
128 +
	}
129 +
	
130 +
	/**
131 +
	 * Returns the offset within this buffer array wrapper's backing array of the
132 +
	 * first buffer.
133 +
	 * 
134 +
	 * @return The offset within this buffer array wrapper's array of the first
135 +
	 *         buffer
136 +
	 */
137 +
	public int arrayOffset() {
138 +
		return offset;
139 +
	}
140 +
	
141 +
	/**
142 +
	 * Returns the index after the last buffer in the array backing this buffer
143 +
	 * array wrapper
144 +
	 * 
145 +
	 * @return the index after the last buffer
146 +
	 */
147 +
	public int arrayEnd() {
148 +
		return end;
149 +
	}
150 +
	
151 +
	/**
152 +
	 * Returns the index of the buffer in the backing array that is pointed by this
153 +
	 * buffer array wrapper's current position. If this buffer array wrapper has no
154 +
	 * remaining bytes the return value will equals the {@code arrayEnd()}.
155 +
	 * 
156 +
	 * @return The index of the current buffer, or the size if this buffer array
157 +
	 *         wrapper has no remaining bytes
158 +
	 */
159 +
	public int arrayIndex() {
160 +
		int i = index;
161 +
		
162 +
		for (; i<end; ++i) {
163 +
			if (array[i].hasRemaining()) {
164 +
				return i;
165 +
			}
166 +
		}
167 +
		return i;
168 +
	}
169 +
	
170 +
	/**
171 +
	 * Returns the number of buffers in the the backing array.
172 +
	 * 
173 +
	 * @return The number of buffers
174 +
	 */
175 +
	public int size() {
176 +
		return size;
177 +
	}
178 +
	
179 +
	/**
180 +
	 * Tells whether there are any bytes between the current position and the limit.
181 +
	 * 
182 +
	 * @return {@code true} if, and only if, there is at least one byte remaining in
183 +
	 *         this buffer array wrapper
184 +
	 */
185 +
	public boolean hasRemaining() {
186 +
		for (int i = index; i < end; ++i) {
187 +
			if (array[i].hasRemaining()) {
188 +
				return true;
189 +
			}
190 +
		}
191 +
		return false;
192 +
	}
193 +
194 +
	/**
195 +
	 * Returns the number of bytes between the current position and the limit.
196 +
	 * 
197 +
	 * @return The number of bytes remaining in this buffer array wrapper
198 +
	 */
199 +
	public long remaining() {
200 +
		long remaining = 0;
201 +
202 +
		for (int i = index; i < end; ++i) {
203 +
			remaining += array[i].remaining();
204 +
		}
205 +
		return remaining;
206 +
	}
207 +
208 +
	/**
209 +
	 * Returns this buffer array wrapper's limit.
210 +
	 * 
211 +
	 * @return The limit of this buffer array wrapper
212 +
	 */
213 +
	public long limit() {
214 +
		long limit = 0;
215 +
216 +
		for (int i = offset; i < end; ++i) {
217 +
			limit += array[i].limit();
218 +
		}
219 +
		return limit;
220 +
	}
221 +
222 +
	/**
223 +
	 * Returns this buffer array wrapper's position.
224 +
	 * 
225 +
	 * @return The position of this buffer array wrapper
226 +
	 */
227 +
	public long position() {
228 +
		if (buffer != null) {
229 +
			long position = 0;
230 +
231 +
			for (int i=offset; i < index; ++i) {
232 +
				position += array[i].limit();
233 +
			}
234 +
			return buffer.position() + position;
235 +
		}
236 +
		return 0;
237 +
	}
238 +
239 +
	/**
240 +
	 * Sets this buffer array wrapper's position. If the mark is defined and larger
241 +
	 * than the new position then it is discarded.
242 +
	 * 
243 +
	 * @param newPosition The new position value; must be non-negative and no larger
244 +
	 *                    than the current limit
245 +
	 * @return This buffer array wrapper
246 +
	 * @throws IllegalArgumentException If the preconditions on newPosition do not
247 +
	 *                                  hold
248 +
	 */
249 +
	public ByteBufferArray position(long newPosition) {
250 +
		return position(newPosition, false);
251 +
	}
252 +
253 +
	private ByteBufferArray position(long newPosition, boolean reset) {
254 +
		if (newPosition >= 0) {
255 +
			int limit = -1, i = offset, len = end;
256 +
			long position = newPosition;
257 +
			ByteBuffer buffer = null;
258 +
			boolean positioned = false;
259 +
			
260 +
			for (; i < len; ++i) {
261 +
				buffer = array[i];
262 +
				limit = buffer.limit();
263 +
				if (position < limit) {
264 +
					buffer.position((int) position);
265 +
					index = i;
266 +
					this.buffer = buffer;
267 +
					if (mark > newPosition) {
268 +
						mark = -1;
269 +
					}
270 +
					positioned = true;
271 +
					break;
272 +
				} else {
273 +
					position -= limit;
274 +
				}
275 +
			}
276 +
			if (i == len && position == 0) {
277 +
				if (limit != -1) {
278 +
					buffer.position(limit);
279 +
					index = --i;
280 +
					this.buffer = buffer;
281 +
				}
282 +
				positioned = true;
283 +
			}
284 +
			if (positioned) {
285 +
				int j = offset;
286 +
				for (; j<i; ++j) {
287 +
					array[j].position(array[j].limit());
288 +
				}
289 +
				for (++j; j<len; ++j) {
290 +
					array[j].position(0);
291 +
				}
292 +
				return this;
293 +
			}
294 +
		}
295 +
		throw reset ? new InvalidMarkException() : new IllegalArgumentException();
296 +
	}
297 +
	
298 +
	/**
299 +
	 * Sets this buffer array wrapper's mark at its position.
300 +
	 * 
301 +
	 * @return This buffer array wrapper
302 +
	 */
303 +
	public ByteBufferArray mark() {
304 +
		mark = position();
305 +
		return this;
306 +
	}
307 +
308 +
	/**
309 +
	 * Resets this buffer array wrapper's position to the previously-marked
310 +
	 * position.
311 +
	 * <p>
312 +
	 * Invoking this method neither changes nor discards the mark's value.
313 +
	 * 
314 +
	 * @return This buffer array wrapper
315 +
	 * @throws InvalidMarkException If the mark has not been set or its value is
316 +
	 *                              invalid
317 +
	 */
318 +
	public ByteBufferArray reset() {
319 +
		long m = mark;
320 +
		if (m < 0)
321 +
			throw new InvalidMarkException();
322 +
		return position(m, true);
323 +
	}
324 +
325 +
	/**
326 +
	 * Rewinds this buffer array wrapper. The position is set to zero and the mark
327 +
	 * is discarded.
328 +
	 * 
329 +
	 * @return This buffer array wrapper
330 +
	 */
331 +
	public ByteBufferArray rewind() {
332 +
		for (int i = offset; i < end; ++i) {
333 +
			array[i].rewind();
334 +
		}
335 +
		if (size > 0) {
336 +
			buffer = this.array[offset];
337 +
		}
338 +
		index = offset;
339 +
		mark = -1;
340 +
		return this;
341 +
	}
342 +
	
343 +
	/**
344 +
	 * Creates a new byte buffer array wrapper that shares this buffer array
345 +
	 * wrapper's content.
346 +
	 * <p>
347 +
	 * The new buffer array wrapper's limit, position, and mark values will be
348 +
	 * identical to those of this buffer array wrapper and they values will be
349 +
	 * changed independently.
350 +
	 * <p>
351 +
	 * 
352 +
	 * @return The new byte buffer array wrapper
353 +
	 */
354 +
	public ByteBufferArray duplicate() {
355 +
		ByteBuffer[] dup = new ByteBuffer[array.length];
356 +
357 +
		for (int i = offset; i < end; ++i) {
358 +
			dup[i] = array[i].duplicate();
359 +
		}
360 +
		ByteBufferArray dupArray = new ByteBufferArray(dup, offset, size);
361 +
		dupArray.index = index;
362 +
		dupArray.mark = mark;
363 +
		if (buffer != null) {
364 +
			dupArray.buffer = dup[index];
365 +
		}
366 +
		return dupArray;
367 +
	}
368 +
369 +
	private ByteBuffer buffer() {
370 +
		if (buffer == null) {
371 +
			throw new BufferUnderflowException();
372 +
		}
373 +
		while (!buffer.hasRemaining()) {
374 +
			++index;
375 +
			if (index >= end) {
376 +
				throw new BufferUnderflowException();
377 +
			}
378 +
			buffer = array[index];
379 +
		}
380 +
		return buffer;
381 +
	}
382 +
383 +
	private ByteBuffer buffer(int size) {
384 +
		ByteBuffer b = buffer();
385 +
386 +
		if (b.remaining() >= size) {
387 +
			return b;
388 +
		}
389 +
		byte[] data = new byte[size];
390 +
		get(data);
391 +
		return ByteBuffer.wrap(data).order(b.order());
392 +
	}
393 +
394 +
	private ByteBuffer buffer(int size, int[] index) {
395 +
		int i = index[0];
396 +
397 +
		if (i < 0) {
398 +
			throw new IndexOutOfBoundsException();
399 +
		}
400 +
		for (int b = offset; b < end; ++b) {
401 +
			ByteBuffer buf = array[b];
402 +
			int l = buf.limit();
403 +
404 +
			if (i >= l) {
405 +
				i -= l;
406 +
			} else if (i <= l - size) {
407 +
				index[0] = i;
408 +
				return buf;
409 +
			} else {
410 +
				byte[] data = new byte[size];
411 +
412 +
				for (int j = 0; j < size; ++j) {
413 +
					if (i < l) {
414 +
						data[j] = buf.get(i++);
415 +
					} else if (++b < end) {
416 +
						buf = array[b];
417 +
						l = buf.limit();
418 +
						i = 0;
419 +
						--j;
420 +
					} else {
421 +
						throw new IndexOutOfBoundsException();
422 +
					}
423 +
				}
424 +
				index[0] = 0;
425 +
				return ByteBuffer.wrap(data).order(buf.order());
426 +
			}
427 +
		}
428 +
		throw new IndexOutOfBoundsException();
429 +
	}
430 +
431 +
	/**
432 +
	 * Relative get method that transfers bytes from this buffer array wrapper into
433 +
	 * the given destination byte array.
434 +
	 * <p>
435 +
	 * If there are fewer bytes remaining in the buffer than are required to satisfy
436 +
	 * the request then no bytes are transferred and a BufferUnderflowException is
437 +
	 * thrown. Otherwise, the bytes are copied into the given array and the position
438 +
	 * of this buffer array wrapper is incremented by number of copied bytes.
439 +
	 * 
440 +
	 * @param dst the destination byte array
441 +
	 * @return This buffer array wrapper
442 +
	 * @throws BufferUnderflowException If there are fewer than length bytes
443 +
	 *                                  remaining in this buffer buffer wrapper
444 +
	 */
445 +
	public ByteBufferArray get(byte[] dst) {
446 +
		return get(dst, 0, dst.length);
447 +
	}
448 +
449 +
	/**
450 +
	 * Relative get method that transfers bytes from this buffer array wrapper into
451 +
	 * the given destination byte array.
452 +
	 * <p>
453 +
	 * If there are fewer bytes remaining in the buffer than are required to satisfy
454 +
	 * the request then no bytes are transferred and a
455 +
	 * {@link BufferUnderflowException} is thrown. Otherwise, the bytes are copied
456 +
	 * into the given array and the position of this buffer array wrapper is
457 +
	 * incremented by number of copied bytes.
458 +
	 * 
459 +
	 * @param dst    the destination byte array
460 +
	 * @param offset the offset within the array of the first byte to be copied
461 +
	 * @param length the number of bytes to be copied into the given array
462 +
	 * @return This buffer array wrapper
463 +
	 * @throws BufferUnderflowException  If there are fewer than length bytes
464 +
	 *                                   remaining in this buffer buffer wrapper
465 +
	 * @throws IndexOutOfBoundsException If the preconditions on the offset and
466 +
	 *                                   length parameters do not hold
467 +
	 */
468 +
	public ByteBufferArray get(byte[] dst, int offset, int length) {
469 +
		InternalSession.checkBounds(offset, length, dst.length);
470 +
		if (length == 0) {
471 +
			return this;
472 +
		}
473 +
474 +
		ByteBuffer buffer = buffer();
475 +
476 +
		int remaining = buffer.remaining();
477 +
		if (length <= remaining) {
478 +
			buffer.get(dst, offset, length);
479 +
			return this;
480 +
		}
481 +
482 +
		for (int i = index + 1; i < end; ++i) {
483 +
			remaining += array[i].remaining();
484 +
			if (remaining >= length) {
485 +
				while (true) {
486 +
					int size = Math.min(length, buffer.remaining());
487 +
488 +
					buffer.get(dst, offset, size);
489 +
					offset += size;
490 +
					length -= size;
491 +
					if (length > 0) {
492 +
						buffer = buffer();
493 +
					} else {
494 +
						return this;
495 +
					}
496 +
				}
497 +
			}
498 +
		}
499 +
		throw new BufferUnderflowException();
500 +
	}
501 +
502 +
	static void checkBounds(ByteBuffer dst, int length) {
503 +
		if (length < 0 || dst.remaining() < length) {
504 +
			throw new IndexOutOfBoundsException();
505 +
		}
506 +
	}
507 +
	
508 +
	/**
509 +
	 * Relative get method that transfers bytes from this buffer array wrapper into
510 +
	 * the given destination byte buffer.
511 +
	 * <p>
512 +
	 * If there are fewer bytes remaining in the buffer than are required to satisfy
513 +
	 * the request then no bytes are transferred and a
514 +
	 * {@link BufferUnderflowException} is thrown. Otherwise, the bytes are copied
515 +
	 * into the given buffer and the position of this buffer array wrapper is
516 +
	 * incremented by number of copied bytes.
517 +
	 * 
518 +
	 * @param dst    the destination byte buffer
519 +
	 * @param length the number of bytes to be copied into the given buffer
520 +
	 * @return This buffer array wrapper
521 +
	 * @throws BufferUnderflowException  If there are fewer than length bytes
522 +
	 *                                   remaining in this buffer buffer wrapper
523 +
	 * @throws IndexOutOfBoundsException If the preconditions on the length
524 +
	 *                                   parameter do not hold
525 +
	 */
526 +
	public ByteBufferArray get(ByteBuffer dst, int length) {
527 +
		checkBounds(dst, length);
528 +
		int i = index;
529 +
		
530 +
		for (; i < end; ++i) {
531 +
			length -= array[i].remaining();
532 +
			if (length == 0) {
533 +
				break;
534 +
			}
535 +
			else if (length < 0) {
536 +
				--i;
537 +
				break;
538 +
			}
539 +
		}
540 +
		if (length > 0) {
541 +
			throw new BufferUnderflowException();
542 +
		}
543 +
		for (int j = index; j<=i; ++j) {
544 +
			dst.put(array[j]);
545 +
		}
546 +
		if (length < 0) {
547 +
			ByteBuffer dup = array[++i].duplicate();
548 +
			dup.limit(dup.limit() + length);
549 +
			dst.put(dup);
550 +
			array[i].position(dup.limit());
551 +
		}
552 +
		return this;
553 +
	}
554 +
	
555 +
	/**
556 +
	 * Relative get method that reads the byte at this buffer array wrapper's
557 +
	 * current position, and then increments the position.
558 +
	 * 
559 +
	 * @return The byte at the buffer array wrapper's current position
560 +
	 * @throws BufferUnderflowException If the buffer array wrapper's current
561 +
	 *                                  position is not smaller than its limit
562 +
	 */
563 +
	public byte get() {
564 +
		return buffer().get();
565 +
	}
566 +
567 +
	/**
568 +
	 * Absolute get method that reads the byte at the given position.
569 +
	 * 
570 +
	 * @param position The position from which the byte will be read
571 +
	 * @return The byte at the given position
572 +
	 * @throws IndexOutOfBoundsException If position is negative or not smaller than
573 +
	 *                                   the buffer array wrapper's limit
574 +
	 */
575 +
	public byte get(int position) {
576 +
		int[] indexArray = new int[] { position };
577 +
		return buffer(1, indexArray).get(indexArray[0]);
578 +
	}
579 +
580 +
	/**
581 +
	 * Relative get method for reading a char value.
582 +
	 * <p>
583 +
	 * It reads the next two bytes at this buffer array wrapper's current position,
584 +
	 * composing them into a char value according to the current byte order, and
585 +
	 * then increments the position by two.
586 +
	 * <p>
587 +
	 * NOTE: The current byte order is determined by the current byte order of the
588 +
	 * buffer pointed by the current position of this buffer array wrapper.
589 +
	 * 
590 +
	 * @return The char value at the buffer array wrapper's current position
591 +
	 * @throws BufferUnderflowException  If there are fewer than two bytes remaining
592 +
	 *                                   in this buffer array wrapper
593 +
	 */
594 +
	public char getChar() {
595 +
		return buffer(2).getChar();
596 +
	}
597 +
598 +
	/**
599 +
	 * Absolute get method for reading a char value.
600 +
	 * <p>
601 +
	 * It reads two bytes at the given position, composing them into a char value
602 +
	 * according to the current byte order.
603 +
	 * <p>
604 +
	 * NOTE: The current byte order is determined by the current byte order of the
605 +
	 * buffer pointed by the given position.
606 +
	 * 
607 +
	 * @param position The position from which the bytes will be read
608 +
	 * @return The char value at the given position
609 +
	 * @throws IndexOutOfBoundsException If position is negative or not smaller than
610 +
	 *                                   the buffer array wrapper's limit, minus one
611 +
	 */
612 +
	public char getChar(int position) {
613 +
		int[] indexArray = new int[] { position };
614 +
		return buffer(2, indexArray).getChar(indexArray[0]);
615 +
	}
616 +
617 +
	/**
618 +
	 * Relative get method for reading a short value.
619 +
	 * <p>
620 +
	 * It reads the next two bytes at this buffer array wrapper's current position,
621 +
	 * composing them into a short value according to the current byte order, and
622 +
	 * then increments the position by two.
623 +
	 * <p>
624 +
	 * NOTE: The current byte order is determined by the current byte order of the
625 +
	 * buffer pointed by the current position of this buffer array wrapper.
626 +
	 * 
627 +
	 * @return The short value at the buffer array wrapper's current position
628 +
	 * @throws BufferUnderflowException  If there are fewer than two bytes remaining
629 +
	 *                                   in this buffer array wrapper
630 +
	 */
631 +
	public short getShort() {
632 +
		return buffer(2).getShort();
633 +
	}
634 +
635 +
	/**
636 +
	 * Absolute get method for reading a short value.
637 +
	 * <p>
638 +
	 * It reads two bytes at the given position, composing them into a short value
639 +
	 * according to the current byte order.
640 +
	 * <p>
641 +
	 * NOTE: The current byte order is determined by the current byte order of the
642 +
	 * buffer pointed by the given position.
643 +
	 * 
644 +
	 * @param position The position from which the bytes will be read
645 +
	 * @return The short value at the given position
646 +
	 * @throws IndexOutOfBoundsException If position is negative or not smaller than
647 +
	 *                                   the buffer array wrapper's limit, minus one
648 +
	 */
649 +
	public short getShort(int position) {
650 +
		int[] indexArray = new int[] { position };
651 +
		return buffer(2, indexArray).getShort(indexArray[0]);
652 +
	}
653 +
654 +
	/**
655 +
	 * Relative get method for reading an int value.
656 +
	 * <p>
657 +
	 * It reads the next four bytes at this buffer array wrapper's current position,
658 +
	 * composing them into an int value according to the current byte order, and
659 +
	 * then increments the position by four.
660 +
	 * <p>
661 +
	 * NOTE: The current byte order is determined by the current byte order of the
662 +
	 * buffer pointed by the current position of this buffer array wrapper.
663 +
	 * 
664 +
	 * @return The int value at the buffer array wrapper's current position
665 +
	 * @throws BufferUnderflowException If there are fewer than four bytes remaining
666 +
	 *                                  in this buffer array wrapper
667 +
	 */
668 +
	public int getInt() {
669 +
		return buffer(4).getInt();
670 +
	}
671 +
672 +
	/**
673 +
	 * Absolute get method for reading an int value.
674 +
	 * <p>
675 +
	 * It reads four bytes at the given position, composing them into an int value
676 +
	 * according to the current byte order.
677 +
	 * <p>
678 +
	 * NOTE: The current byte order is determined by the current byte order of the
679 +
	 * buffer pointed by the given position.
680 +
	 * 
681 +
	 * @param position The position from which the bytes will be read
682 +
	 * @return The int value at the given position
683 +
	 * @throws IndexOutOfBoundsException If position is negative or not smaller than
684 +
	 *                                   the buffer array wrapper's limit, minus
685 +
	 *                                   three
686 +
	 */
687 +
	public int getInt(int position) {
688 +
		int[] indexArray = new int[] { position };
689 +
		return buffer(4, indexArray).getInt(indexArray[0]);
690 +
	}
691 +
692 +
	/**
693 +
	 * Relative get method for reading a long value.
694 +
	 * <p>
695 +
	 * It reads the next eight bytes at this buffer array wrapper's current position,
696 +
	 * composing them into a long value according to the current byte order, and
697 +
	 * then increments the position by eight.
698 +
	 * <p>
699 +
	 * NOTE: The current byte order is determined by the current byte order of the
700 +
	 * buffer pointed by the current position of this buffer array wrapper.
701 +
	 * 
702 +
	 * @return The long value at the buffer array wrapper's current position
703 +
	 * @throws BufferUnderflowException If there are fewer than eight bytes remaining
704 +
	 *                                  in this buffer array wrapper
705 +
	 */
706 +
	public long getLong() {
707 +
		return buffer(8).getLong();
708 +
	}
709 +
710 +
	/**
711 +
	 * Absolute get method for reading a long value.
712 +
	 * <p>
713 +
	 * It reads eight bytes at the given position, composing them into a long value
714 +
	 * according to the current byte order.
715 +
	 * <p>
716 +
	 * NOTE: The current byte order is determined by the current byte order of the
717 +
	 * buffer pointed by the given position.
718 +
	 * 
719 +
	 * @param position The position from which the bytes will be read
720 +
	 * @return The long value at the given position
721 +
	 * @throws IndexOutOfBoundsException If position is negative or not smaller than
722 +
	 *                                   the buffer array wrapper's limit, minus
723 +
	 *                                   seven
724 +
	 */
725 +
	public long getLong(int position) {
726 +
		int[] indexArray = new int[] { position };
727 +
		return buffer(8, indexArray).getLong(indexArray[0]);
728 +
	}
729 +
730 +
	/**
731 +
	 * Relative get method for reading a float value.
732 +
	 * <p>
733 +
	 * It reads the next four bytes at this buffer array wrapper's current position,
734 +
	 * composing them into a float value according to the current byte order, and
735 +
	 * then increments the position by four.
736 +
	 * <p>
737 +
	 * NOTE: The current byte order is determined by the current byte order of the
738 +
	 * buffer pointed by the current position of this buffer array wrapper.
739 +
	 * 
740 +
	 * @return The float value at the buffer array wrapper's current position
741 +
	 * @throws BufferUnderflowException If there are fewer than four bytes remaining
742 +
	 *                                  in this buffer array wrapper
743 +
	 */
744 +
	public float getFloat() {
745 +
		return buffer(4).getFloat();
746 +
	}
747 +
748 +
	/**
749 +
	 * Absolute get method for reading a float value.
750 +
	 * <p>
751 +
	 * It reads four bytes at the given position, composing them into a float value
752 +
	 * according to the current byte order.
753 +
	 * <p>
754 +
	 * NOTE: The current byte order is determined by the current byte order of the
755 +
	 * buffer pointed by the given position.
756 +
	 * 
757 +
	 * @param position The position from which the bytes will be read
758 +
	 * @return The float value at the given position
759 +
	 * @throws IndexOutOfBoundsException If position is negative or not smaller than
760 +
	 *                                   the buffer array wrapper's limit, minus
761 +
	 *                                   three
762 +
	 */
763 +
	public float getFloat(int position) {
764 +
		int[] indexArray = new int[] { position };
765 +
		return buffer(4, indexArray).getFloat(indexArray[0]);
766 +
	}
767 +
768 +
	/**
769 +
	 * Relative get method for reading a double value.
770 +
	 * <p>
771 +
	 * It reads the next eight bytes at this buffer array wrapper's current position,
772 +
	 * composing them into a double value according to the current byte order, and
773 +
	 * then increments the position by eight.
774 +
	 * <p>
775 +
	 * NOTE: The current byte order is determined by the current byte order of the
776 +
	 * buffer pointed by the current position of this buffer array wrapper.
777 +
	 * 
778 +
	 * @return The double value at the buffer array wrapper's current position
779 +
	 * @throws BufferUnderflowException If there are fewer than eight bytes remaining
780 +
	 *                                  in this buffer array wrapper
781 +
	 */
782 +
	public double getDouble() {
783 +
		return buffer(8).getDouble();
784 +
	}
785 +
786 +
	/**
787 +
	 * Absolute get method for reading a double value.
788 +
	 * <p>
789 +
	 * It reads eight bytes at the given position, composing them into a double value
790 +
	 * according to the current byte order.
791 +
	 * <p>
792 +
	 * NOTE: The current byte order is determined by the current byte order of the
793 +
	 * buffer pointed by the given position.
794 +
	 * 
795 +
	 * @param position The position from which the bytes will be read
796 +
	 * @return The double value at the given position
797 +
	 * @throws IndexOutOfBoundsException If position is negative or not smaller than
798 +
	 *                                   the buffer array wrapper's limit, minus
799 +
	 *                                   seven
800 +
	 */
801 +
	public double getDouble(int position) {
802 +
		int[] indexArray = new int[] { position };
803 +
		return buffer(8, indexArray).getDouble(indexArray[0]);
804 +
	}
805 +
806 +
	static class OneByteBufferArray extends ByteBufferArray {
807 +
808 +
		public OneByteBufferArray(ByteBuffer[] array) {
809 +
			super(array);
810 +
		}
811 +
812 +
		public OneByteBufferArray(ByteBuffer[] array, int off, int len) {
813 +
			super(array, off, len);
814 +
		}
815 +
816 +
		@Override
817 +
		public int arrayIndex() {
818 +
			return offset;
819 +
		}
820 +
		
821 +
		public ByteBufferArray duplicate() {
822 +
			ByteBuffer[] dup = new ByteBuffer[array.length];
823 +
			dup[offset] = array[offset].duplicate();
824 +
			return new OneByteBufferArray(dup, offset, size);
825 +
		}
826 +
		
827 +
		@Override
828 +
		public boolean hasRemaining() {
829 +
			return buffer.hasRemaining();
830 +
		}
831 +
832 +
		@Override
833 +
		public long remaining() {
834 +
			return buffer.remaining();
835 +
		}
836 +
837 +
		@Override
838 +
		public long limit() {
839 +
			return buffer.limit();
840 +
		}
841 +
842 +
		@Override
843 +
		public long position() {
844 +
			return buffer.position();
845 +
		}
846 +
847 +
		@Override
848 +
		public ByteBufferArray position(long newPosition) {
849 +
			buffer.position((int) newPosition);
850 +
			return this;
851 +
		}
852 +
		
853 +
		@Override
854 +
		public ByteBufferArray mark() {
855 +
			buffer.mark();
856 +
			return this;
857 +
		}
858 +
859 +
		@Override
860 +
		public ByteBufferArray reset() {
861 +
			buffer.reset();
862 +
			return this;
863 +
		}
864 +
865 +
		@Override
866 +
		public ByteBufferArray rewind() {
867 +
			buffer.rewind();
868 +
			return this;
869 +
		}
870 +
871 +
		@Override
872 +
		public ByteBufferArray get(byte[] dst) {
873 +
			buffer.get(dst);
874 +
			return this;
875 +
		}
876 +
877 +
		@Override
878 +
		public ByteBufferArray get(byte[] dst, int off, int len) {
879 +
			buffer.get(dst, off, len);
880 +
			return this;
881 +
		}
882 +
883 +
		public ByteBufferArray get(ByteBuffer dst, int length) {
884 +
			checkBounds(dst, length);
885 +
			length -= buffer.remaining();
886 +
			if (length > 0) {
887 +
				throw new BufferUnderflowException();
888 +
			}
889 +
			if (length == 0) {
890 +
				dst.put(buffer);
891 +
			}
892 +
			else {
893 +
				ByteBuffer dup = buffer.duplicate();
894 +
				dup.limit(dup.limit() + length);
895 +
				dst.put(dup);
896 +
				buffer.position(dup.limit());
897 +
			}
898 +
			return this;
899 +
		}
900 +
		
901 +
		@Override
902 +
		public byte get() {
903 +
			return buffer.get();
904 +
		}
905 +
906 +
		@Override
907 +
		public byte get(int position) {
908 +
			return buffer.get(position);
909 +
		}
910 +
911 +
		@Override
912 +
		public char getChar() {
913 +
			return buffer.getChar();
914 +
		}
915 +
916 +
		@Override
917 +
		public char getChar(int position) {
918 +
			return buffer.getChar(position);
919 +
		}
920 +
921 +
		@Override
922 +
		public short getShort() {
923 +
			return buffer.getShort();
924 +
		}
925 +
926 +
		@Override
927 +
		public short getShort(int position) {
928 +
			return buffer.getShort(position);
929 +
		}
930 +
931 +
		@Override
932 +
		public int getInt() {
933 +
			return buffer.getInt();
934 +
		}
935 +
936 +
		@Override
937 +
		public int getInt(int position) {
938 +
			return buffer.getInt(position);
939 +
		}
940 +
941 +
		@Override
942 +
		public long getLong() {
943 +
			return buffer.getLong();
944 +
		}
945 +
946 +
		@Override
947 +
		public long getLong(int position) {
948 +
			return buffer.getLong(position);
949 +
		}
950 +
951 +
		@Override
952 +
		public float getFloat() {
953 +
			return buffer.getFloat();
954 +
		}
955 +
956 +
		@Override
957 +
		public float getFloat(int position) {
958 +
			return buffer.getFloat(position);
959 +
		}
960 +
961 +
		@Override
962 +
		public double getDouble() {
963 +
			return buffer.getDouble();
964 +
		}
965 +
966 +
		@Override
967 +
		public double getDouble(int position) {
968 +
			return buffer.getDouble(position);
969 +
		}
970 +
		
971 +
	}
972 +
}
Files Coverage
snf4j-core-log4j2/src/main/java/org/snf4j/core/logger/impl 96.66%
snf4j-core-slf4j/src/main/java/org/snf4j/core/logger/impl 96.66%
snf4j-core/src/main/java/org/snf4j/core 98.09%
snf4j-sctp/src/main/java/org/snf4j/core 98.58%
snf4j-websocket/src/main/java/org/snf4j/websocket 99.37%
Project Totals (242 files) 98.31%
codecov-umbrella
Build #2747960053 -
1
coverage:
2
  range: "70...100"
3
  round: down
4
  precision: 2
5
  
6
  status:
7
    project:
8
      default:
9
        enabled: yes
10
        target: 94%
11
        threshold: 5%
12
        
13
    patch:
14
      default:
15
        enabled: yes
16
        target: 85%
17
        threshold: 5%
18
        
19
    changes: no
20
    
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading