Browse Source
* commit 'fd605607209ab993a6605b4541ade561adb4af28': KERNEL-9224 refactor: 升级Jodd到5.0.4以上版本bugfix/10.0
superman
3 years ago
278 changed files with 15559 additions and 16216 deletions
@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code boolean} buffer. |
||||
*/ |
||||
public class FastBooleanBuffer { |
||||
|
||||
private boolean[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code boolean} buffer. The buffer capacity is |
||||
* initially 64 booleans, though its size increases if necessary. |
||||
*/ |
||||
public FastBooleanBuffer() { |
||||
this.buffer = new boolean[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code boolean} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastBooleanBuffer(final int size) { |
||||
this.buffer = new boolean[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code boolean} to buffer. |
||||
*/ |
||||
public void append(final boolean element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code boolean} array to buffer. |
||||
*/ |
||||
public FastBooleanBuffer append(final boolean[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code boolean} array to buffer. |
||||
*/ |
||||
public FastBooleanBuffer append(final boolean[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastBooleanBuffer append(final FastBooleanBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code boolean} array from buffered content. |
||||
*/ |
||||
public boolean[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code boolean} subarray from buffered content. |
||||
*/ |
||||
public boolean[] toArray(final int start, final int len) { |
||||
final boolean[] array = new boolean[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code boolean} element at given index. |
||||
*/ |
||||
public boolean get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code byte} buffer. Works faster for smaller buffer sizes. |
||||
* After eg. length of 2048 the performances are practically the same. |
||||
*/ |
||||
public class FastByteBuffer { |
||||
|
||||
private byte[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code byte} buffer. The buffer capacity is |
||||
* initially 64 bytes, though its size increases if necessary. |
||||
*/ |
||||
public FastByteBuffer() { |
||||
this.buffer = new byte[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code byte} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastByteBuffer(final int size) { |
||||
this.buffer = new byte[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code byte} to buffer. |
||||
*/ |
||||
public void append(final byte element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code byte} array to buffer. |
||||
*/ |
||||
public FastByteBuffer append(final byte[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code byte} array to buffer. |
||||
*/ |
||||
public FastByteBuffer append(final byte[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastByteBuffer append(final FastByteBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code byte} array from buffered content. |
||||
*/ |
||||
public byte[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code byte} subarray from buffered content. |
||||
*/ |
||||
public byte[] toArray(final int start, final int len) { |
||||
final byte[] array = new byte[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code byte} element at given index. |
||||
*/ |
||||
public byte get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,211 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import com.fr.third.jodd.util.CharArraySequence; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code char} buffer. |
||||
*/ |
||||
public class FastCharBuffer implements CharSequence, Appendable { |
||||
|
||||
private char[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code char} buffer. The buffer capacity is |
||||
* initially 64 chars, though its size increases if necessary. |
||||
*/ |
||||
public FastCharBuffer() { |
||||
this.buffer = new char[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code char} buffer, with a buffer capacity of |
||||
* the specified size, in chars. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastCharBuffer(final int size) { |
||||
this.buffer = new char[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code char} to buffer. |
||||
*/ |
||||
@Override |
||||
public FastCharBuffer append(final char element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code char} array to buffer. |
||||
*/ |
||||
public FastCharBuffer append(final char[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code char} array to buffer. |
||||
*/ |
||||
public FastCharBuffer append(final char[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastCharBuffer append(final FastCharBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
@Override |
||||
public int length() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code char} array from buffered content. |
||||
*/ |
||||
public char[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code char} subarray from buffered content. |
||||
*/ |
||||
public char[] toArray(final int start, final int len) { |
||||
final char[] array = new char[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code char} element at given index. |
||||
*/ |
||||
public char get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
/** |
||||
* Appends character sequence to buffer. |
||||
*/ |
||||
@Override |
||||
public FastCharBuffer append(final CharSequence csq) { |
||||
append(csq, 0, csq.length()); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends character sequence to buffer. |
||||
*/ |
||||
@Override |
||||
public FastCharBuffer append(final CharSequence csq, final int start, final int end) { |
||||
for (int i = start; i < end; i++) { |
||||
append(csq.charAt(i)); |
||||
} |
||||
return this; |
||||
} |
||||
@Override |
||||
public char charAt(final int index) { |
||||
return get(index); |
||||
} |
||||
|
||||
@Override |
||||
public CharSequence subSequence(final int start, final int end) { |
||||
return new CharArraySequence(buffer, start, end - start); |
||||
} |
||||
|
||||
/** |
||||
* Returns a String of the char buffer. |
||||
* Please use {@code StringBuilder} instead, it is faster. |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new String(toArray()); |
||||
} |
||||
} |
@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code double} buffer. |
||||
*/ |
||||
public class FastDoubleBuffer { |
||||
|
||||
private double[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code double} buffer. The buffer capacity is |
||||
* initially 64 doubles, though its size increases if necessary. |
||||
*/ |
||||
public FastDoubleBuffer() { |
||||
this.buffer = new double[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code double} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastDoubleBuffer(final int size) { |
||||
this.buffer = new double[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code double} to buffer. |
||||
*/ |
||||
public void append(final double element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code double} array to buffer. |
||||
*/ |
||||
public FastDoubleBuffer append(final double[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code double} array to buffer. |
||||
*/ |
||||
public FastDoubleBuffer append(final double[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastDoubleBuffer append(final FastDoubleBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code double} array from buffered content. |
||||
*/ |
||||
public double[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code double} subarray from buffered content. |
||||
*/ |
||||
public double[] toArray(final int start, final int len) { |
||||
final double[] array = new double[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code double} element at given index. |
||||
*/ |
||||
public double get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,165 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code float} buffer. |
||||
*/ |
||||
public class FastFloatBuffer { |
||||
|
||||
private float[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code float} buffer. The buffer capacity is |
||||
* initially 64 floats, though its size increases if necessary. |
||||
*/ |
||||
public FastFloatBuffer() { |
||||
this.buffer = new float[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code float} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastFloatBuffer(final int size) { |
||||
this.buffer = new float[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code float} to buffer. |
||||
*/ |
||||
public void append(final float element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code float} array to buffer. |
||||
*/ |
||||
public FastFloatBuffer append(final float[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code float} array to buffer. |
||||
*/ |
||||
public FastFloatBuffer append(final float[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastFloatBuffer append(final FastFloatBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code float} array from buffered content. |
||||
*/ |
||||
public float[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code float} subarray from buffered content. |
||||
*/ |
||||
public float[] toArray(final int start, final int len) { |
||||
final float[] array = new float[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code float} element at given index. |
||||
*/ |
||||
public float get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code int} buffer. |
||||
*/ |
||||
public class FastIntBuffer { |
||||
|
||||
private int[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code int} buffer. The buffer capacity is |
||||
* initially 64 ints, though its size increases if necessary. |
||||
*/ |
||||
public FastIntBuffer() { |
||||
this.buffer = new int[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code int} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastIntBuffer(final int size) { |
||||
this.buffer = new int[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code int} to buffer. |
||||
*/ |
||||
public void append(final int element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code int} array to buffer. |
||||
*/ |
||||
public FastIntBuffer append(final int[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code int} array to buffer. |
||||
*/ |
||||
public FastIntBuffer append(final int[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastIntBuffer append(final FastIntBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code int} array from buffered content. |
||||
*/ |
||||
public int[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code int} subarray from buffered content. |
||||
*/ |
||||
public int[] toArray(final int start, final int len) { |
||||
final int[] array = new int[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code int} element at given index. |
||||
*/ |
||||
public int get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code long} buffer. |
||||
*/ |
||||
public class FastLongBuffer { |
||||
|
||||
private long[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code long} buffer. The buffer capacity is |
||||
* initially 64 longs, though its size increases if necessary. |
||||
*/ |
||||
public FastLongBuffer() { |
||||
this.buffer = new long[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code long} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastLongBuffer(final int size) { |
||||
this.buffer = new long[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code long} to buffer. |
||||
*/ |
||||
public void append(final long element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code long} array to buffer. |
||||
*/ |
||||
public FastLongBuffer append(final long[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code long} array to buffer. |
||||
*/ |
||||
public FastLongBuffer append(final long[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastLongBuffer append(final FastLongBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code long} array from buffered content. |
||||
*/ |
||||
public long[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code long} subarray from buffered content. |
||||
*/ |
||||
public long[] toArray(final int start, final int len) { |
||||
final long[] array = new long[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code long} element at given index. |
||||
*/ |
||||
public long get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,165 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code short} buffer. |
||||
*/ |
||||
public class FastShortBuffer { |
||||
|
||||
private short[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code short} buffer. The buffer capacity is |
||||
* initially 64 shorts, though its size increases if necessary. |
||||
*/ |
||||
public FastShortBuffer() { |
||||
this.buffer = new short[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code short} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastShortBuffer(final int size) { |
||||
this.buffer = new short[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code short} to buffer. |
||||
*/ |
||||
public void append(final short element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code short} array to buffer. |
||||
*/ |
||||
public FastShortBuffer append(final short[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code short} array to buffer. |
||||
*/ |
||||
public FastShortBuffer append(final short[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastShortBuffer append(final FastShortBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code short} array from buffered content. |
||||
*/ |
||||
public short[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code short} subarray from buffered content. |
||||
*/ |
||||
public short[] toArray(final int start, final int len) { |
||||
final short[] array = new short[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code short} element at given index. |
||||
*/ |
||||
public short get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,153 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import com.fr.third.jodd.io.FileUtil; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Base in-memory files cache. |
||||
*/ |
||||
public abstract class FileCache { |
||||
|
||||
protected final Cache<File, byte[]> cache; |
||||
protected final int maxSize; |
||||
protected final int maxFileSize; |
||||
protected final long timeout; |
||||
|
||||
protected int usedSize; |
||||
|
||||
/** |
||||
* Creates new File LFU cache. |
||||
* @param maxSize total cache size in bytes |
||||
* @param maxFileSize max available file size in bytes, may be 0 |
||||
* @param timeout timeout, may be 0 |
||||
*/ |
||||
protected FileCache(final int maxSize, final int maxFileSize, final long timeout) { |
||||
this.maxSize = maxSize; |
||||
this.maxFileSize = maxFileSize; |
||||
this.timeout = timeout; |
||||
this.cache = createCache(); |
||||
} |
||||
|
||||
/** |
||||
* Creates new cache instance for files content. |
||||
*/ |
||||
protected abstract Cache<File, byte[]> createCache(); |
||||
|
||||
/** |
||||
* Creates CacheObject that updates last access time based on files last modification. |
||||
*/ |
||||
protected AbstractCacheMap.CacheObject<File, byte[]> createFileCacheObject(File fileKey, byte[] object, long timeout) { |
||||
return new AbstractCacheMap.CacheObject<File, byte[]>(fileKey, object, timeout) { |
||||
@Override |
||||
boolean isExpired() { |
||||
if (fileKey.lastModified() > this.lastAccess) { |
||||
this.lastAccess = fileKey.lastModified(); |
||||
} |
||||
return super.isExpired(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns max cache size in bytes. |
||||
*/ |
||||
public int maxSize() { |
||||
return maxSize; |
||||
} |
||||
|
||||
/** |
||||
* Returns actually used size in bytes. |
||||
*/ |
||||
public int usedSize() { |
||||
return usedSize; |
||||
} |
||||
|
||||
/** |
||||
* Returns maximum allowed file size that can be added to the cache. |
||||
* Files larger than this value will be not added, even if there is |
||||
* enough room. |
||||
*/ |
||||
public int maxFileSize() { |
||||
return maxFileSize; |
||||
} |
||||
|
||||
/** |
||||
* Returns number of cached files. |
||||
*/ |
||||
public int cachedFilesCount() { |
||||
return cache.size(); |
||||
} |
||||
|
||||
/** |
||||
* Returns timeout. |
||||
*/ |
||||
public long cacheTimeout() { |
||||
return cache.timeout(); |
||||
} |
||||
|
||||
/** |
||||
* Clears the cache. |
||||
*/ |
||||
public void clear() { |
||||
cache.clear(); |
||||
usedSize = 0; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns cached file bytes. If file is not cached it will be |
||||
* read and put in the cache (if all the rules are satisfied). |
||||
*/ |
||||
public byte[] getFileBytes(final File file) throws IOException { |
||||
byte[] bytes = cache.get(file); |
||||
if (bytes != null) { |
||||
return bytes; |
||||
} |
||||
|
||||
// add file
|
||||
bytes = FileUtil.readBytes(file); |
||||
|
||||
if ((maxFileSize != 0) && (file.length() > maxFileSize)) { |
||||
// don't cache files that size exceed max allowed file size
|
||||
return bytes; |
||||
} |
||||
|
||||
usedSize += bytes.length; |
||||
|
||||
// put file into cache
|
||||
// if used size > total, purge() will be invoked
|
||||
cache.put(file, bytes); |
||||
|
||||
return bytes; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,205 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.AbstractMap; |
||||
import java.util.Collections; |
||||
import java.util.IdentityHashMap; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.WeakHashMap; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.function.Consumer; |
||||
import java.util.function.Function; |
||||
|
||||
/** |
||||
* Types cache. Provides several implementations depending on what you need to be addressed. |
||||
* There are two things you should take care off: |
||||
* <ul> |
||||
* <li>synchronization - especially on storing items. If not synchronized, one instance of an item may be put |
||||
* more then once into the map. This is usually fine, as it happens only during the initialization and makes not |
||||
* harm if something is created twice</li> |
||||
* <li>weak - if your key classes are replaced during the runtime, you should use weak map, in order to automatically |
||||
* remove obsolete keys.</li> |
||||
* </ul> |
||||
*/ |
||||
public class TypeCache<T> { |
||||
|
||||
// ---------------------------------------------------------------- builder
|
||||
|
||||
/** |
||||
* Creates a type cache by using a builder. |
||||
*/ |
||||
public static <A> Builder<A> create() { |
||||
return new Builder<>(); |
||||
} |
||||
|
||||
/** |
||||
* Creates default implementation of the type cache. |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public static <A> TypeCache<A> createDefault() { |
||||
return TypeCache.<A>create().get(); |
||||
} |
||||
|
||||
public static class Builder<A> { |
||||
private boolean threadsafe; |
||||
private boolean weak; |
||||
private boolean none; |
||||
|
||||
/** |
||||
* No cache will be used. |
||||
* Setting other properties will not have any affect. |
||||
*/ |
||||
public Builder<A> noCache() { |
||||
none = true; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Cache keys will be weak. |
||||
*/ |
||||
public Builder<A> weak(final boolean weak) { |
||||
this.weak = weak; |
||||
return this; |
||||
} |
||||
/** |
||||
* Cache will be thread-safe. |
||||
*/ |
||||
public Builder<A> threadsafe(final boolean threadsafe) { |
||||
this.threadsafe = threadsafe; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Builds a type cache. |
||||
*/ |
||||
public TypeCache<A> get() { |
||||
final Map<Class<?>, A> map; |
||||
if (none) { |
||||
map = new AbstractMap<Class<?>, A>() { |
||||
@Override |
||||
public A put(final Class<?> key, final A value) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public A get(final Object key) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public Set<Entry<Class<?>, A>> entrySet() { |
||||
return Collections.emptySet(); |
||||
} |
||||
}; |
||||
} |
||||
else if (weak) { |
||||
if (threadsafe) { |
||||
map = Collections.synchronizedMap(new WeakHashMap<>()); |
||||
} else { |
||||
map = new WeakHashMap<>(); |
||||
} |
||||
} else { |
||||
if (threadsafe) { |
||||
map = new ConcurrentHashMap<>(); |
||||
} else { |
||||
map = new IdentityHashMap<>(); |
||||
} |
||||
} |
||||
|
||||
return new TypeCache<>(map); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- map
|
||||
|
||||
private final Map<Class<?>, T> map; |
||||
|
||||
private TypeCache(final Map<Class<?>, T> backedMap) { |
||||
this.map = backedMap; |
||||
} |
||||
|
||||
/** |
||||
* Add values to the map. |
||||
*/ |
||||
public T put(final Class<?> type, final T value) { |
||||
return map.put(type, value); |
||||
} |
||||
|
||||
/** |
||||
* Returns value from the map or {@code null} if value does not exist. |
||||
*/ |
||||
public T get(final Class<?> key) { |
||||
return map.get(key); |
||||
} |
||||
|
||||
/** |
||||
* Returns existing value or add default supplied one. |
||||
* Use this method instead of {@code get-nullcheck-put} block when |
||||
* thread-safety is of importance. |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public <K> T get(final Class<K> key, final Function<Class<K>, ? extends T> mappingFunction) { |
||||
return map.computeIfAbsent(key, aClass -> mappingFunction.apply((Class<K>) aClass)); |
||||
} |
||||
|
||||
/** |
||||
* Removes element from the type cache. |
||||
*/ |
||||
public T remove(final Class<?> type) { |
||||
return map.remove(type); |
||||
} |
||||
|
||||
/** |
||||
* Clears complete cache. |
||||
*/ |
||||
public void clear() { |
||||
map.clear(); |
||||
} |
||||
|
||||
/** |
||||
* Returns cache size. |
||||
*/ |
||||
public int size() { |
||||
return map.size(); |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code true} if cache is empty. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return map.isEmpty(); |
||||
} |
||||
|
||||
/** |
||||
* Iterates all cached values. |
||||
*/ |
||||
public void forEachValue(final Consumer<? super T> valueConsumer) { |
||||
map.values().forEach(valueConsumer); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,298 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.chalk; |
||||
|
||||
import com.fr.third.jodd.util.StringPool; |
||||
|
||||
/** |
||||
* Chalk allows you to color output going to console. |
||||
* @see Chalk256 |
||||
*/ |
||||
public class Chalk<T extends Chalk<T>> { |
||||
|
||||
/** |
||||
* Global flag that disables all the chalks. |
||||
* Useful for windows platforms :) |
||||
*/ |
||||
public static boolean enabled = true; |
||||
|
||||
protected static final String RESET = "0"; |
||||
|
||||
protected static final String BOLD = "1"; |
||||
protected static final String UNBOLD = "22"; // 21 isn't widely supported and 22 does the same thing
|
||||
protected static final String DIM = "2"; |
||||
protected static final String UNDIM = "22"; |
||||
protected static final String ITALIC = "3"; |
||||
protected static final String UNITALIC = "23"; |
||||
protected static final String UNDERLINE = "4"; |
||||
protected static final String UNUNDERLINE = "24"; |
||||
protected static final String INVERSE = "7"; |
||||
protected static final String UNINVERSE = "27"; |
||||
protected static final String HIDDEN = "8"; |
||||
protected static final String UNHIDDEN = "28"; |
||||
protected static final String STRIKETHROUGH = "9"; |
||||
protected static final String UNSTRIKETHROUGH = "29"; |
||||
|
||||
protected static final String COLOR_RESET = "39"; |
||||
protected static final String BLACK = "30"; |
||||
protected static final String RED = "31"; |
||||
protected static final String GREEN = "32"; |
||||
protected static final String YELLOW = "33"; |
||||
protected static final String BLUE = "34"; |
||||
protected static final String MAGENTA = "35"; |
||||
protected static final String CYAN = "36"; |
||||
protected static final String WHITE = "37"; |
||||
protected static final String GRAY = "90"; |
||||
|
||||
protected static final String BGCOLOR_RESET = "49"; |
||||
protected static final String BGBLACK = "40"; |
||||
protected static final String BGRED = "41"; |
||||
protected static final String BGGREEN = "42"; |
||||
protected static final String BGYELLOW = "43"; |
||||
protected static final String BGBLUE = "44"; |
||||
protected static final String BGMAGENTA = "45"; |
||||
protected static final String BGCYAN = "46"; |
||||
protected static final String BGWHITE = "47"; |
||||
|
||||
protected StringBuilder prefix; |
||||
protected StringBuilder suffix; |
||||
protected String text; |
||||
|
||||
/** |
||||
* Creates new chalk. |
||||
*/ |
||||
public static Chalk chalk() { |
||||
return new Chalk(); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
protected T _this() { |
||||
return (T) this; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- style
|
||||
|
||||
public T bold() { |
||||
startSequence(BOLD); |
||||
endSequence(UNBOLD); |
||||
return _this(); |
||||
} |
||||
|
||||
public T italic() { |
||||
startSequence(ITALIC); |
||||
endSequence(UNITALIC); |
||||
return _this(); |
||||
} |
||||
|
||||
public T dim() { |
||||
startSequence(DIM); |
||||
endSequence(UNDIM); |
||||
return _this(); |
||||
} |
||||
|
||||
public T underline() { |
||||
startSequence(UNDERLINE); |
||||
endSequence(UNUNDERLINE); |
||||
return _this(); |
||||
} |
||||
|
||||
public T inverse() { |
||||
startSequence(INVERSE); |
||||
endSequence(UNINVERSE); |
||||
return _this(); |
||||
} |
||||
|
||||
public T hidden() { |
||||
startSequence(HIDDEN); |
||||
endSequence(UNHIDDEN); |
||||
return _this(); |
||||
} |
||||
public T strikeThrough() { |
||||
startSequence(STRIKETHROUGH); |
||||
endSequence(UNSTRIKETHROUGH); |
||||
return _this(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- colors
|
||||
|
||||
public T black() { |
||||
startSequence(BLACK); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T red() { |
||||
startSequence(RED); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T green() { |
||||
startSequence(GREEN); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T yellow() { |
||||
startSequence(YELLOW); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T blue() { |
||||
startSequence(BLUE); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T magenta() { |
||||
startSequence(MAGENTA); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T cyan() { |
||||
startSequence(CYAN); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T white() { |
||||
startSequence(WHITE); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T gray() { |
||||
startSequence(GRAY); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T grey() { |
||||
return gray(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- bg colors
|
||||
|
||||
public T bgBlack() { |
||||
startSequence(BGBLACK); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgRed() { |
||||
startSequence(BGRED); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgGreen() { |
||||
startSequence(BGGREEN); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgYellow() { |
||||
startSequence(BGYELLOW); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgBlue() { |
||||
startSequence(BGBLUE); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgMagenta() { |
||||
startSequence(BGMAGENTA); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgCyan() { |
||||
startSequence(BGCYAN); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgWhite() { |
||||
startSequence(BGWHITE); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- internal
|
||||
|
||||
protected void startSequence(final String value) { |
||||
if (prefix == null) { |
||||
prefix = new StringBuilder(); |
||||
prefix.append("\u001B["); |
||||
} |
||||
else { |
||||
prefix.append(StringPool.SEMICOLON); |
||||
} |
||||
|
||||
prefix.append(value); |
||||
} |
||||
|
||||
protected void endSequence(final String value) { |
||||
if (suffix == null) { |
||||
suffix = new StringBuilder(); |
||||
suffix |
||||
.append("\u001B[") |
||||
.append(value); |
||||
} |
||||
else { |
||||
suffix.insert(2, value + StringPool.SEMICOLON); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- out
|
||||
|
||||
/** |
||||
* Returns chalked string. |
||||
*/ |
||||
public String on(final String string) { |
||||
if (!enabled) { |
||||
return string; |
||||
} |
||||
|
||||
final StringBuilder sb = new StringBuilder(); |
||||
|
||||
if (prefix != null) { |
||||
sb.append(prefix).append("m"); |
||||
} |
||||
|
||||
sb.append(string); |
||||
|
||||
if (suffix != null) { |
||||
sb.append(suffix).append("m"); |
||||
} |
||||
|
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Prints chalked string to system output. |
||||
*/ |
||||
public void print(final String string) { |
||||
System.out.print(on(string)); |
||||
} |
||||
|
||||
/** |
||||
* Prints chalked string to system output. |
||||
*/ |
||||
public void println(final String string) { |
||||
System.out.println(on(string)); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,123 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.chalk; |
||||
|
||||
/** |
||||
* Chalk256 allows you to color output going to ansi-256 console. |
||||
* @see Chalk |
||||
*/ |
||||
public class Chalk256 extends Chalk<Chalk256> { |
||||
|
||||
private static final String[] FG_CODES = new String[256]; |
||||
private static final String[] BG_CODES = new String[256]; |
||||
|
||||
static { |
||||
for (int i = 0; i < FG_CODES.length; i++) { |
||||
FG_CODES[i] = "38;5;" + i; |
||||
} |
||||
for (int i = 0; i < BG_CODES.length; i++) { |
||||
BG_CODES[i] = "48;5;" + i; |
||||
} |
||||
} |
||||
|
||||
public static Chalk256 chalk() { |
||||
return new Chalk256(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- fg codes
|
||||
|
||||
public Chalk256 standard(final int index) { |
||||
startSequence(FG_CODES[index(index, 0, 8)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bright(final int index) { |
||||
startSequence(FG_CODES[index(index, 8, 16)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 rgb(final int index) { |
||||
startSequence(FG_CODES[index(index, 16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Colors with red-green-blue value, in the range 0 to 6. |
||||
*/ |
||||
public Chalk256 rgb(final int r, final int b, final int g) { |
||||
startSequence(FG_CODES[index(36*r + 6*g + b,16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 grayscale(final int index) { |
||||
startSequence(FG_CODES[index(index, 232, 256)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
// ---------------------------------------------------------------- bg codes
|
||||
|
||||
public Chalk256 bgStandard(final int index) { |
||||
startSequence(BG_CODES[index(index, 0, 8)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bgBright(final int index) { |
||||
startSequence(BG_CODES[index(index, 8, 16)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bgRgb(final int index) { |
||||
startSequence(BG_CODES[index(index, 16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Colors with red-green-blue value, in the range 0 to 6. |
||||
*/ |
||||
public Chalk256 bgRgb(final int r, final int b, final int g) { |
||||
startSequence(BG_CODES[index(36*r + 6*g + b,16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bgGrayscale(final int index) { |
||||
startSequence(BG_CODES[index(index, 232, 256)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- bgcolors
|
||||
|
||||
private int index(int index, final int from, final int to) { |
||||
index += from; |
||||
if ((index < from) || (index >= to)) { |
||||
throw new IllegalArgumentException("Color index not in range: [0, " + (to - from) + "]"); |
||||
} |
||||
return index; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,233 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.function.Consumer; |
||||
|
||||
public class Cli implements Consumer<String[]> { |
||||
|
||||
private final List<Option> options = new ArrayList<>(); |
||||
private final List<Param> params = new ArrayList<>(); |
||||
|
||||
public Option option() { |
||||
final Option option = new Option(); |
||||
options.add(option); |
||||
return option; |
||||
} |
||||
|
||||
public Param param() { |
||||
final Param param = new Param(); |
||||
params.add(param); |
||||
return param; |
||||
} |
||||
|
||||
private boolean consumeOptionWithLongName(final String input, final String valueToConsume) { |
||||
for (final Option option : options) { |
||||
if (input.equals(option.longName)) { |
||||
if (option.hasArg && valueToConsume == null) { |
||||
throw new CliException("Option value not provided for: " + input); |
||||
} |
||||
option.consumer.accept(option.hasArg ? valueToConsume : input); |
||||
return option.hasArg; |
||||
} |
||||
|
||||
if (option.longName != null && input.startsWith(option.longName + "=")) { |
||||
option.consumer.accept(input.substring(option.longName.length() + 1)); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
throw new CliException("Unknown option: " + input); |
||||
} |
||||
|
||||
private boolean consumeOptionWithShortName(final String input, final String valueToConsume) { |
||||
for (final Option option : options) { |
||||
if (input.equals(option.shortName)) { |
||||
if (option.hasArg) { |
||||
if (valueToConsume == null) { |
||||
throw new CliException("Option value not provided for: " + input); |
||||
} |
||||
option.consumer.accept(valueToConsume); |
||||
return true; |
||||
} |
||||
else { |
||||
option.consumer.accept(input); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
if (option.shortName != null && input.startsWith(option.shortName + "=")) { |
||||
option.consumer.accept(input.substring(option.shortName.length() + 1)); |
||||
return false; |
||||
} |
||||
} |
||||
throw new CliException("Unknown option: " + input); |
||||
} |
||||
|
||||
private void consumeOptionWithShortNameAndNoArguments(final String shortName) { |
||||
for (final Option option : options) { |
||||
if (shortName.equals(option.shortName) && !option.hasArg) { |
||||
option.consumer.accept(shortName); |
||||
return; |
||||
} |
||||
} |
||||
throw new CliException("Unknown option: " + shortName); |
||||
} |
||||
|
||||
@Override |
||||
public void accept(final String... args) { |
||||
assertConfigurationIsValid(); |
||||
|
||||
boolean dontParseOptionsAnyMore = false; |
||||
int i; |
||||
int paramsIndex = 0; |
||||
|
||||
for (i = 0; i < args.length; i++) { |
||||
final String arg = args[i]; |
||||
if (arg.isEmpty()) { |
||||
continue; |
||||
} |
||||
final String value = (i + 1 < args.length) ? args[i + 1] : null; |
||||
|
||||
if (arg.equals("--")) { |
||||
dontParseOptionsAnyMore = true; |
||||
continue; |
||||
} |
||||
|
||||
if (!dontParseOptionsAnyMore) { |
||||
// long names
|
||||
if (arg.startsWith("--")) { |
||||
final String argLongName = arg.substring(2); |
||||
|
||||
consumeOptionWithLongName(argLongName, value); |
||||
|
||||
args[i] = null; |
||||
continue; |
||||
} |
||||
|
||||
// short names
|
||||
if (arg.startsWith("-")) { |
||||
final String argShortName = arg.substring(1); |
||||
|
||||
if (argShortName.length() > 1 && argShortName.charAt(1) != '=') { |
||||
// compressed options
|
||||
final char[] allShortNames = argShortName.toCharArray(); |
||||
for (final char c : allShortNames) { |
||||
final String argName = String.valueOf(c); |
||||
consumeOptionWithShortNameAndNoArguments(argName); |
||||
} |
||||
args[i] = null; |
||||
continue; |
||||
} |
||||
|
||||
final boolean valueConsumed = consumeOptionWithShortName(argShortName, value); |
||||
|
||||
// mark argument as consumed
|
||||
args[i] = null; |
||||
if (valueConsumed) { |
||||
// mark value as consumed, too
|
||||
i++; |
||||
args[i] = null; |
||||
} |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
// params
|
||||
|
||||
if (paramsIndex == params.size()) { |
||||
// we are done here
|
||||
break; |
||||
} |
||||
final Param param = params.get(paramsIndex++); |
||||
|
||||
final List<String> paramArguments = new ArrayList<>(); |
||||
|
||||
int from = 0; |
||||
final int to = param.required + param.optional; |
||||
|
||||
for (; from < to; from++, i++) { |
||||
final String paramValue = (i < args.length) ? args[i] : null; |
||||
if (paramValue == null) { |
||||
break; |
||||
} |
||||
paramArguments.add(paramValue); |
||||
} |
||||
i--; |
||||
|
||||
if (paramArguments.size() < param.required) { |
||||
throw new CliException("Parameter required: " + param.label); |
||||
} |
||||
|
||||
if (paramArguments.isEmpty()) { |
||||
// parameter not found
|
||||
continue; |
||||
} |
||||
|
||||
param.consumer.accept(paramArguments.toArray(new String[0])); |
||||
} |
||||
|
||||
// must check if remaining parameters are not satisfied
|
||||
while (paramsIndex < params.size()) { |
||||
final Param param = params.get(paramsIndex++); |
||||
if (param.required > 0) { |
||||
throw new CliException("Parameter required: " + param.label); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void assertConfigurationIsValid() { |
||||
for (final Option option : options) { |
||||
if (option.consumer == null) { |
||||
throw new CliException("Option has no registered consumer: " + option); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Prints the usage line. |
||||
*/ |
||||
public void printUsage(final String commandName) { |
||||
final StringBuilder usage = new StringBuilder(commandName); |
||||
|
||||
for (final Option option : options) { |
||||
if (option.shortName != null) { |
||||
usage.append(" [-").append(option.shortName).append("]"); |
||||
} else if (option.longName != null) { |
||||
usage.append(" [--").append(option.longName).append("]"); |
||||
} |
||||
} |
||||
|
||||
for (final Param param : params) { |
||||
usage.append(" ").append(param.label); |
||||
} |
||||
|
||||
System.out.println(usage); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import java.util.function.Consumer; |
||||
|
||||
public class Option { |
||||
|
||||
String label; |
||||
String shortName; |
||||
String longName; |
||||
String description; |
||||
boolean hasArg; |
||||
String argLabel; |
||||
Consumer<String> consumer; |
||||
|
||||
public Option shortName(final String shortName) { |
||||
this.shortName = shortName; |
||||
return this; |
||||
} |
||||
|
||||
public Option longName(final String longName) { |
||||
this.longName = longName; |
||||
return this; |
||||
} |
||||
|
||||
public Option names(final String shortName, final String longName) { |
||||
this.shortName = shortName; |
||||
this.longName = longName; |
||||
return this; |
||||
} |
||||
|
||||
public Option description(final String description) { |
||||
this.description = description; |
||||
return this; |
||||
} |
||||
|
||||
public Option hasArg() { |
||||
this.hasArg = true; |
||||
return this; |
||||
} |
||||
|
||||
public Option hasArg(final String argLabel) { |
||||
this.hasArg = true; |
||||
this.argLabel = argLabel; |
||||
return this; |
||||
} |
||||
|
||||
public Option label(final String label) { |
||||
this.label = label; |
||||
return this; |
||||
} |
||||
|
||||
public Option with(final Consumer<String> consumer) { |
||||
this.consumer = consumer; |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
String out = ""; |
||||
if (shortName != null) { |
||||
out += "-" + shortName; |
||||
} |
||||
if (longName != null) { |
||||
if (!out.isEmpty()) { |
||||
out += " | "; |
||||
} |
||||
out += "--" + longName; |
||||
} |
||||
return out; |
||||
} |
||||
} |
@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import java.util.function.Consumer; |
||||
|
||||
public class Param { |
||||
String label; |
||||
int required = 0; |
||||
int optional = 1; |
||||
String description; |
||||
Consumer<String[]> consumer; |
||||
|
||||
public Param required(final int required) { |
||||
this.required = required; |
||||
return this; |
||||
} |
||||
|
||||
public Param optional(final int optional) { |
||||
this.optional = optional; |
||||
return this; |
||||
} |
||||
|
||||
public Param required() { |
||||
this.required = 1; |
||||
this.optional = 0; |
||||
return this; |
||||
} |
||||
|
||||
public Param optional() { |
||||
this.required = 0; |
||||
this.optional = 1; |
||||
return this; |
||||
} |
||||
|
||||
public Param all() { |
||||
this.optional = 1_000_000; // magic number indicating *ALL* parameters
|
||||
return this; |
||||
} |
||||
|
||||
public Param range(final int required, final int max) { |
||||
this.required = required; |
||||
this.optional = max - required; |
||||
return this; |
||||
} |
||||
|
||||
public Param label(final String label) { |
||||
this.label = label; |
||||
return this; |
||||
} |
||||
|
||||
public Param description(final String description) { |
||||
this.description = description; |
||||
return this; |
||||
} |
||||
|
||||
public Param with(final Consumer<String[]> consumer) { |
||||
this.consumer = consumer; |
||||
return this; |
||||
} |
||||
} |
@ -1,113 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.format; |
||||
|
||||
/** |
||||
* Printf. |
||||
* @see PrintfFormat |
||||
*/ |
||||
public class Printf { |
||||
|
||||
// ---------------------------------------------------------------- primitives
|
||||
|
||||
/** |
||||
* @see PrintfFormat#form(byte) |
||||
*/ |
||||
public static String str(String format, byte value) { |
||||
return new PrintfFormat(format).form(value); |
||||
} |
||||
|
||||
/** |
||||
* @see PrintfFormat#form(char) |
||||
*/ |
||||
public static String str(String format, char value) { |
||||
return new PrintfFormat(format).form(value); |
||||
} |
||||
|
||||
/** |
||||
* @see PrintfFormat#form(short) |
||||
*/ |
||||
public static String str(String format, short value) { |
||||
return new PrintfFormat(format).form(value); |
||||
} |
||||
|
||||
/** |
||||
* @see PrintfFormat#form(int) |
||||
*/ |
||||
public static String str(String format, int value) { |
||||
return new PrintfFormat(format).form(value); |
||||
} |
||||
|
||||
/** |
||||
* @see PrintfFormat#form(long) |
||||
*/ |
||||
public static String str(String format, long value) { |
||||
return new PrintfFormat(format).form(value); |
||||
} |
||||
|
||||
/** |
||||
* @see PrintfFormat#form(double) |
||||
*/ |
||||
public static String str(String format, float value) { |
||||
return new PrintfFormat(format).form(value); |
||||
} |
||||
|
||||
/** |
||||
* @see PrintfFormat#form(double) |
||||
*/ |
||||
public static String str(String format, double value) { |
||||
return new PrintfFormat(format).form(value); |
||||
} |
||||
|
||||
/** |
||||
* @see PrintfFormat#form(boolean) |
||||
*/ |
||||
public static String str(String format, boolean value) { |
||||
return new PrintfFormat(format).form(value); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- objects
|
||||
|
||||
public static String str(String format, String value) { |
||||
return new PrintfFormat(format).form(value); |
||||
} |
||||
|
||||
public static String str(String format, Object param) { |
||||
return new PrintfFormat(format).form(param); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- multiple objects
|
||||
|
||||
public static String str(String format, Object... params) { |
||||
PrintfFormat pf = new PrintfFormat(); |
||||
for (Object param : params) { |
||||
pf.reinit(format); |
||||
format = pf.form(param); |
||||
} |
||||
return format; |
||||
} |
||||
|
||||
} |
@ -1,766 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.format; |
||||
|
||||
import com.fr.third.jodd.util.StringPool; |
||||
|
||||
import java.math.BigInteger; |
||||
|
||||
/** |
||||
* Fast simple and yet useful formatting. |
||||
*/ |
||||
public class PrintfFormat { |
||||
|
||||
protected int width; |
||||
protected int precision; |
||||
protected StringBuilder pre; |
||||
protected StringBuilder post; |
||||
protected boolean leadingZeroes; |
||||
protected boolean showPlus; |
||||
protected boolean alternate; |
||||
protected boolean showSpace; |
||||
protected boolean leftAlign; |
||||
protected boolean groupDigits; |
||||
protected char fmt; // one of cdeEfgGiosxXos...
|
||||
protected boolean countSignInLen; |
||||
private static final BigInteger bgInt = new BigInteger("9223372036854775808"); // 2^63
|
||||
|
||||
/** |
||||
* Formats a number in a printf format, like C. |
||||
* |
||||
* @param s the format string following printf format string |
||||
* The string has a prefix, a format code and a suffix. The prefix and suffix |
||||
* become part of the formatted output. The format code directs the |
||||
* formatting of the (single) parameter to be formatted. The code has the |
||||
* following structure |
||||
* <ul> |
||||
* <li> a <b>%</b> (required) |
||||
* |
||||
* <li> a modifier (optional) |
||||
* <dl> |
||||
* <dt> + <dd> forces display of + for positive numbers |
||||
* <dt> ~ <dd> do not count leading + or - in length |
||||
* <dt> 0 <dd> show leading zeroes |
||||
* <dt> - <dd> align left in the field |
||||
* <dt> space <dd> prepend a space in front of positive numbers |
||||
* <dt> # <dd> use "alternate" format. Add 0 or 0x for octal or hexadecimal numbers; |
||||
* add 0b for binary numbers. Don't suppress trailing zeroes in general floating |
||||
* point format. |
||||
* <dt> , <dd> groups decimal values by thousands (for 'diuxXb' formats) |
||||
* </dl> |
||||
* |
||||
* <li> an integer denoting field width (optional) |
||||
* |
||||
* <li> a period (<b>.</b>) followed by an integer denoting precision (optional) |
||||
* |
||||
* <li> a format descriptor (required) |
||||
* <dl> |
||||
* <dt>f <dd> floating point number in fixed format, |
||||
* <dt>e, E <dd> floating point number in exponential notation (scientific format). |
||||
* The E format results in an uppercase E for the exponent (1.14130E+003), the e |
||||
* format in a lowercase e, |
||||
* <dt>g, G <dd> floating point number in general format (fixed format for small |
||||
* numbers, exponential format for large numbers). Trailing zeroes are suppressed. |
||||
* The G format results in an uppercase E for the exponent (if any), the g format |
||||
* in a lowercase e,. |
||||
* <dt>d, i <dd> signed long and integer in decimal, |
||||
* <dt>u <dd> unsigned long or integer in decimal, |
||||
* <dt>x <dd> unsigned long or integer in hexadecimal, |
||||
* <dt>o <dd> unsigned long or integer in octal, |
||||
* <dt>b <dd> unsigned long or integer in binary, |
||||
* <dt>s <dd> string (actually, <code>toString()</code> value of an object), |
||||
* <dt>c <dd> character, |
||||
* <dt>l, L <dd> boolean in lower or upper case (for booleans and int/longs), |
||||
* <dt>p <dd> identity hash code of an object (pointer :). |
||||
* </dl> |
||||
* </ul> |
||||
*/ |
||||
public PrintfFormat(String s) { |
||||
init(s, 0); |
||||
} |
||||
|
||||
/** |
||||
* For internal use with {@link #init(String, int)} and {@link #reinit(String)}. |
||||
*/ |
||||
protected PrintfFormat() { |
||||
} |
||||
|
||||
protected PrintfFormat reinit(String s) { |
||||
if (pre == null) { |
||||
init(s, 0); |
||||
} else { |
||||
init(s, pre.length()); |
||||
} |
||||
return this; |
||||
} |
||||
|
||||
protected void init(String s, int i) { |
||||
width = 0; |
||||
precision = -1; |
||||
pre = (i == 0 ? new StringBuilder() : new StringBuilder(s.substring(0, i))); |
||||
post = new StringBuilder(); |
||||
leadingZeroes = false; |
||||
showPlus = false; |
||||
alternate = false; |
||||
showSpace = false; |
||||
leftAlign = false; |
||||
countSignInLen = true; |
||||
fmt = ' '; |
||||
|
||||
int length = s.length(); |
||||
int parseState; // 0 = prefix, 1 = flags, 2 = width, 3 = precision, 4 = format, 5 = end
|
||||
|
||||
// 0: parse string prefix upto first '%'.
|
||||
while (true) { |
||||
if (i >= length) { |
||||
throw new IllegalArgumentException("Format string requires '%'."); |
||||
} |
||||
char c = s.charAt(i); |
||||
if (c != '%') { |
||||
pre.append(c); |
||||
i++; |
||||
continue; |
||||
} |
||||
if (i >= length - 1) { |
||||
throw new IllegalArgumentException("Format string can not end with '%'."); |
||||
} |
||||
if (s.charAt(i + 1) == '%') { // double '%%'
|
||||
pre.append('%'); |
||||
i += 2; |
||||
continue; |
||||
} |
||||
//parseState = 1; // single $ founded
|
||||
i++; |
||||
break; |
||||
} |
||||
|
||||
// 1: parse flags
|
||||
flagsloop: |
||||
//while (parseState == 1) {
|
||||
while (true) { |
||||
if (i >= length) { |
||||
parseState = 5; |
||||
break; |
||||
} |
||||
char c = s.charAt(i); |
||||
switch (c) { |
||||
case ' ': showSpace = true; break; |
||||
case '-': leftAlign = true; break; |
||||
case '+': showPlus = true; break; |
||||
case '0': leadingZeroes = true; break; |
||||
case '#': alternate = true; break; |
||||
case '~': countSignInLen = false; break; |
||||
case ',': groupDigits = true; break; |
||||
default: |
||||
parseState = 2; |
||||
break flagsloop; |
||||
} |
||||
i++; |
||||
} |
||||
|
||||
// 2: parse width
|
||||
while (parseState == 2) { |
||||
if (i >= length) { |
||||
parseState = 5; |
||||
break; |
||||
} |
||||
char c = s.charAt(i); |
||||
if ((c >= '0') && (c <= '9')) { |
||||
width = (width * 10) + s.charAt(i) - '0'; |
||||
i++; |
||||
continue; |
||||
} |
||||
if (s.charAt(i) == '.') { |
||||
parseState = 3; |
||||
precision = 0; |
||||
i++; |
||||
} else { |
||||
parseState = 4; |
||||
} |
||||
break; |
||||
} |
||||
|
||||
// 3: parse precision
|
||||
while (parseState == 3) { |
||||
if (i >= length) { |
||||
parseState = 5; |
||||
break; |
||||
} |
||||
char c = s.charAt(i); |
||||
if ((c >= '0') && (c <= '9')) { |
||||
precision = (precision * 10) + s.charAt(i) - '0'; |
||||
i++; |
||||
continue; |
||||
} |
||||
parseState = 4; |
||||
break; |
||||
} |
||||
|
||||
// 4: parse format
|
||||
if (parseState == 4) { |
||||
if (i < length) { |
||||
fmt = s.charAt(i); |
||||
i++; |
||||
// } else {
|
||||
// parseState = 5;
|
||||
} |
||||
} |
||||
|
||||
// append suffix
|
||||
if (i < length) { |
||||
post.append(s.substring(i, length)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Formats a double with exp format. |
||||
*/ |
||||
protected String expFormat(double d) { |
||||
StringBuilder f = new StringBuilder(); |
||||
int e = 0; |
||||
double dd = d; |
||||
double factor = 1; |
||||
|
||||
if (d != 0) { |
||||
while (dd > 10) { |
||||
e++; |
||||
factor /= 10; |
||||
dd /= 10; |
||||
} |
||||
while (dd < 1) { |
||||
e--; |
||||
factor *= 10; |
||||
dd *= 10; |
||||
} |
||||
} |
||||
if (((fmt == 'g') || (fmt == 'G')) && (e >= -4) && (e < precision)) { |
||||
return fixedFormat(d); |
||||
} |
||||
|
||||
d *= factor; |
||||
f.append(fixedFormat(d)); |
||||
|
||||
if (fmt == 'e' || fmt == 'g') { |
||||
f.append('e'); |
||||
} else { |
||||
f.append('E'); |
||||
} |
||||
|
||||
StringBuilder p = new StringBuilder("000"); |
||||
if (e >= 0) { |
||||
f.append('+'); |
||||
p.append(e); |
||||
} else { |
||||
f.append('-'); |
||||
p.append(-e); |
||||
} |
||||
|
||||
char[] data = new char[3]; |
||||
p.getChars(p.length() - 3, p.length(), data, 0); |
||||
return f.append(data).toString(); |
||||
} |
||||
|
||||
/** |
||||
* Formats a double with fixed format. |
||||
*/ |
||||
protected String fixedFormat(double d) { |
||||
boolean removeTrailing = (fmt == 'G' || fmt == 'g') && !alternate; |
||||
|
||||
// remove trailing zeroes and decimal point
|
||||
if (d > 0x7FFFFFFFFFFFFFFFL) { |
||||
return expFormat(d); |
||||
} |
||||
if (precision == 0) { |
||||
return Long.toString(Math.round(d)); |
||||
} |
||||
|
||||
long whole = (long) d; |
||||
double fr = d - whole; // fractional part
|
||||
|
||||
if (fr >= 1 || fr < 0) { |
||||
return expFormat(d); |
||||
} |
||||
|
||||
double factor = 1; |
||||
StringBuilder leadingZeroesStr = new StringBuilder(); |
||||
|
||||
for (int i = 1; i <= precision && factor <= 0x7FFFFFFFFFFFFFFFL; i++) { |
||||
factor *= 10; |
||||
leadingZeroesStr.append('0'); |
||||
} |
||||
|
||||
long l = Math.round(factor * fr); |
||||
if (l >= factor) { |
||||
l = 0; |
||||
whole++; |
||||
} |
||||
|
||||
String z = leadingZeroesStr.toString() + l; |
||||
z = '.' + z.substring(z.length() - precision, z.length()); |
||||
|
||||
if (removeTrailing) { |
||||
int t = z.length() - 1; |
||||
while (t >= 0 && z.charAt(t) == '0') { |
||||
t--; |
||||
} |
||||
if (t >= 0 && z.charAt(t) == '.') { |
||||
t--; |
||||
} |
||||
z = z.substring(0, t + 1); |
||||
} |
||||
return whole + z; |
||||
} |
||||
|
||||
/** |
||||
* Pads the value with spaces and adds prefix and suffix. |
||||
*/ |
||||
protected String pad(String value) { |
||||
String spaces = repeat(' ', width - value.length()); |
||||
if (leftAlign) { |
||||
return pre + value + spaces + post; |
||||
} else { |
||||
return pre + spaces + value + post; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns new string created by repeating a single character. |
||||
*/ |
||||
protected static String repeat(char c, int n) { |
||||
if (n <= 0) { |
||||
return (StringPool.EMPTY); |
||||
} |
||||
char[] buffer = new char[n]; |
||||
for (int i = 0; i < n; i++) { |
||||
buffer[i] = c; |
||||
} |
||||
return new String(buffer); |
||||
} |
||||
|
||||
private String getAltPrefixFor(char fmt, String currentPrefix) { |
||||
switch(fmt) { |
||||
case 'x': |
||||
return "0x"; |
||||
case 'X': |
||||
return "0X"; |
||||
case 'b': |
||||
return "0b"; |
||||
case 'B': |
||||
return "0B"; |
||||
default: |
||||
return currentPrefix; |
||||
} |
||||
} |
||||
|
||||
protected String sign(int s, String r) { |
||||
String p = StringPool.EMPTY; |
||||
|
||||
if (s < 0) { |
||||
p = StringPool.DASH; |
||||
} else if (s > 0) { |
||||
if (showPlus) { |
||||
p = StringPool.PLUS; |
||||
} else if (showSpace) { |
||||
p = StringPool.SPACE; |
||||
} |
||||
} else { |
||||
if (alternate) { |
||||
if (fmt == 'o' && r.length() > 0 && r.charAt(0) != '0') { |
||||
p = "0"; |
||||
} else { |
||||
p = getAltPrefixFor(fmt, p); |
||||
} |
||||
} |
||||
} |
||||
|
||||
int w = 0; |
||||
|
||||
if (leadingZeroes) { |
||||
w = width; |
||||
} else if ((fmt == 'u' || fmt == 'd' || fmt == 'i' || fmt == 'x' || fmt == 'X' || fmt == 'o') && precision > 0) { |
||||
w = precision; |
||||
} |
||||
|
||||
if (countSignInLen) { |
||||
return p + repeat('0', w - p.length() - r.length()) + r; |
||||
} else { |
||||
return p + repeat('0', w - r.length()) + r; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Groups numbers by inserting 'separator' after every group of 'size' digits, |
||||
* starting from the right. |
||||
*/ |
||||
protected String groupDigits(String value, int size, char separator) { |
||||
if (!groupDigits) { |
||||
return value; |
||||
} |
||||
StringBuilder r = new StringBuilder(value.length() + 10); |
||||
int ndx = 0; |
||||
int len = value.length() - 1; |
||||
int mod = len % size; |
||||
while (ndx < len) { |
||||
r.append(value.charAt(ndx)); |
||||
if (mod == 0) { |
||||
r.append(separator); |
||||
mod = size; |
||||
} |
||||
mod--; |
||||
ndx++; |
||||
} |
||||
r.append(value.charAt(ndx)); |
||||
return r.toString(); |
||||
} |
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------- public form methods
|
||||
|
||||
/** |
||||
* Formats a character into a string (like sprintf in C). |
||||
*/ |
||||
public String form(char value) { |
||||
switch(fmt) { |
||||
case 'c': |
||||
return alternate ? "\\u" + Integer.toHexString((int) value & 0xFFFF) : pad(String.valueOf(value)); |
||||
case 'C': |
||||
return alternate ? "\\u" + Integer.toHexString((int) value & 0xFFFF).toUpperCase() : pad(String.valueOf(value)); |
||||
case 'd': |
||||
case 'i': |
||||
case 'u': |
||||
case 'o': |
||||
case 'x': |
||||
case 'X': |
||||
case 'b': |
||||
case 'l': |
||||
case 'L': |
||||
return form((short) value); |
||||
default: |
||||
throw newIllegalArgumentException("cCdiuoxXblL"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Formats a boolean into a string (like sprintf in C). |
||||
*/ |
||||
public String form(boolean value) { |
||||
if (fmt == 'l') { |
||||
return pad(value ? "true" : "false"); |
||||
} |
||||
if (fmt == 'L') { |
||||
return pad(value ? "TRUE" : "FALSE"); |
||||
} |
||||
throw newIllegalArgumentException("lL"); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Formats a double into a string (like sprintf in C). |
||||
*/ |
||||
public String form(double x) { |
||||
String r; |
||||
|
||||
if (precision < 0) { |
||||
precision = 6; |
||||
} |
||||
|
||||
int s = 1; |
||||
if (x < 0) { |
||||
x = -x; |
||||
s = -1; |
||||
} |
||||
if (fmt == 'f') { |
||||
r = fixedFormat(x); |
||||
} else if (fmt == 'e' || fmt == 'E' || fmt == 'g' || fmt == 'G') { |
||||
r = expFormat(x); |
||||
} else { |
||||
throw newIllegalArgumentException("feEgG"); |
||||
} |
||||
return pad(sign(s, r)); |
||||
} |
||||
|
||||
/** |
||||
* Formats a long integer into a string (like sprintf in C). |
||||
*/ |
||||
public String form(long x) { |
||||
String r; |
||||
int s = 0; |
||||
|
||||
switch (fmt) { |
||||
case 'c': |
||||
return form((char) x); |
||||
case 'd': |
||||
if (x < 0) { |
||||
r = Long.toString(x).substring(1); |
||||
s = -1; |
||||
} else { |
||||
r = Long.toString(x); |
||||
s = 1; |
||||
} |
||||
r = groupDigits(r, 3, ','); |
||||
break; |
||||
case 'i': |
||||
int xx = (int) x; |
||||
if (xx < 0) { |
||||
r = Integer.toString(xx).substring(1); |
||||
s = -1; |
||||
} else { |
||||
r = Integer.toString(xx); |
||||
s = 1; |
||||
} |
||||
r = groupDigits(r, 3, ','); |
||||
break; |
||||
case 'u': |
||||
if (x < 0) { |
||||
long xl = x & 0x7FFFFFFFFFFFFFFFL; |
||||
r = Long.toString(xl); |
||||
BigInteger bi = new BigInteger(r); |
||||
r = bi.add(bgInt).toString(); |
||||
} else { |
||||
r = Long.toString(x); |
||||
} |
||||
r = groupDigits(r, 3, ','); |
||||
s = 1; |
||||
break; |
||||
case 'o': |
||||
r = Long.toOctalString(x); |
||||
break; |
||||
case 'x': |
||||
r = Long.toHexString(x); |
||||
r = groupDigits(r, 4, ' '); |
||||
break; |
||||
case 'X': |
||||
r = Long.toHexString(x).toUpperCase(); |
||||
r = groupDigits(r, 4, ' '); |
||||
break; |
||||
case 'b': |
||||
case 'B': |
||||
r = Long.toBinaryString(x); |
||||
r = groupDigits(r, 8, ' '); |
||||
break; |
||||
case 'l': |
||||
r = (x == 0 ? "false" : "true"); |
||||
break; |
||||
case 'L': |
||||
r = (x == 0 ? "FALSE" : "TRUE"); |
||||
break; |
||||
default: |
||||
throw new IllegalArgumentException("cdiuoxXbBlL"); |
||||
} |
||||
|
||||
return pad(sign(s, r)); |
||||
} |
||||
|
||||
/** |
||||
* Formats an integer into a string (like sprintf in C). |
||||
*/ |
||||
public String form(int x) { |
||||
String r; |
||||
int s = 0; |
||||
|
||||
switch (fmt) { |
||||
case 'c': |
||||
return form((char) x); |
||||
case 'd': |
||||
case 'i': |
||||
if (x < 0) { |
||||
r = Integer.toString(x).substring(1); |
||||
s = -1; |
||||
} else { |
||||
r = Integer.toString(x); |
||||
s = 1; |
||||
} |
||||
r = groupDigits(r, 3, ','); |
||||
break; |
||||
case 'u': |
||||
long xl = x & 0x00000000FFFFFFFFL; |
||||
r = Long.toString(xl); |
||||
r = groupDigits(r, 3, ','); |
||||
s = 1; |
||||
break; |
||||
case 'o': |
||||
r = Integer.toOctalString(x); |
||||
break; |
||||
case 'x': |
||||
r = Integer.toHexString(x); |
||||
r = groupDigits(r, 4, ' '); |
||||
break; |
||||
case 'X': |
||||
r = Integer.toHexString(x).toUpperCase(); |
||||
r = groupDigits(r, 4, ' '); |
||||
break; |
||||
case 'b': |
||||
case 'B': |
||||
r = Integer.toBinaryString(x); |
||||
r = groupDigits(r, 8, ' '); |
||||
break; |
||||
case 'l': |
||||
r = (x == 0 ? "false" : "true"); |
||||
break; |
||||
case 'L': |
||||
r = (x == 0 ? "FALSE" : "TRUE"); |
||||
break; |
||||
default: |
||||
throw newIllegalArgumentException("cdiuoxXbBlL"); |
||||
} |
||||
return pad(sign(s, r)); |
||||
} |
||||
|
||||
/** |
||||
* Formats a byte into a string (like sprintf in C). |
||||
*/ |
||||
public String form(byte b) { |
||||
return formInt(b, 0xFF); |
||||
} |
||||
|
||||
/** |
||||
* Formats a short into a string (like sprintf in C). |
||||
*/ |
||||
public String form(short s) { |
||||
return formInt(s, 0xFFFF); |
||||
} |
||||
|
||||
/** |
||||
* Formatter for both <code>byte</code> and <code>short</code> values. |
||||
*/ |
||||
private String formInt(int value, int unsignedMask) { |
||||
String r; |
||||
int s = 0; |
||||
|
||||
switch (fmt) { |
||||
case 'c': |
||||
return form((char) value); |
||||
case 'd': |
||||
case 'i': |
||||
if (value < 0) { |
||||
r = Integer.toString(value).substring(1); |
||||
s = -1; |
||||
} else { |
||||
r = Integer.toString(value); |
||||
s = 1; |
||||
} |
||||
r = groupDigits(r, 3, ','); |
||||
break; |
||||
case 'u': |
||||
int xl = value & unsignedMask; |
||||
r = Integer.toString(xl); |
||||
r = groupDigits(r, 3, ','); |
||||
s = 1; |
||||
break; |
||||
case 'o': |
||||
r = Integer.toOctalString(value & unsignedMask); |
||||
break; |
||||
case 'x': |
||||
r = Integer.toHexString(value & unsignedMask); |
||||
r = groupDigits(r, 4, ' '); |
||||
break; |
||||
case 'X': |
||||
r = Integer.toHexString(value & unsignedMask).toUpperCase(); |
||||
r = groupDigits(r, 4, ' '); |
||||
break; |
||||
case 'b': |
||||
case 'B': |
||||
r = Integer.toBinaryString(value & unsignedMask); |
||||
r = groupDigits(r, 8, ' '); |
||||
break; |
||||
case 'l': |
||||
r = (value == 0 ? "false" : "true"); |
||||
break; |
||||
case 'L': |
||||
r = (value == 0 ? "FALSE" : "TRUE"); |
||||
break; |
||||
default: |
||||
throw newIllegalArgumentException("cdiuoxXblL"); |
||||
} |
||||
return pad(sign(s, r)); |
||||
} |
||||
|
||||
/** |
||||
* Formats a object into a string depending on format (like sprintf in C). |
||||
* If object is a numeric type and format is not one object formats (like 's' or 'p') |
||||
* it will be converted to primitive and formatted as such. |
||||
*/ |
||||
public String form(Object object) { |
||||
if (object == null) { |
||||
return StringPool.NULL; |
||||
} |
||||
|
||||
switch (fmt) { |
||||
case 's' : |
||||
String s = object.toString(); |
||||
if (precision >= 0 && precision < s.length()) { |
||||
s = s.substring(0, precision); |
||||
} |
||||
return pad(s); |
||||
case 'p' : |
||||
return Integer.toString(System.identityHashCode(object)); |
||||
} |
||||
|
||||
// check for numeric type
|
||||
if (object instanceof Number) { |
||||
Number number = (Number) object; |
||||
if (object instanceof Integer) { |
||||
return form(number.intValue()); |
||||
} |
||||
if (object instanceof Long) { |
||||
return form(number.longValue()); |
||||
} |
||||
if (object instanceof Double) { |
||||
return form(number.doubleValue()); |
||||
} |
||||
if (object instanceof Float) { |
||||
return form(number.floatValue()); |
||||
} |
||||
if (object instanceof Byte) { |
||||
return form(number.byteValue()); |
||||
} |
||||
if (object instanceof Short) { |
||||
return form(number.shortValue()); |
||||
} |
||||
else { |
||||
return form(number.intValue()); |
||||
} |
||||
} |
||||
else if (object instanceof Character) { |
||||
return form(((Character) object).charValue()); |
||||
} |
||||
else if (object instanceof Boolean) { |
||||
return form(((Boolean)object).booleanValue()); |
||||
} |
||||
|
||||
// throw exception about invalid 'object'-formats
|
||||
throw newIllegalArgumentException("sp"); |
||||
} |
||||
|
||||
/** |
||||
* Creates <code>IllegalArgumentException</code> with message. |
||||
*/ |
||||
protected IllegalArgumentException newIllegalArgumentException(String allowedFormats) { |
||||
return new IllegalArgumentException("Invalid format: '" + fmt + "' is not one of '" + allowedFormats + "'"); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import java.util.function.Function; |
||||
|
||||
/** |
||||
* Mapper function allows object to be converted before actually used - usually before injected using |
||||
* {@link com.fr.third.jodd.bean.BeanUtil}. |
||||
*/ |
||||
@FunctionalInterface |
||||
public interface MapperFunction<IN, OUT> extends Function<IN, OUT> { |
||||
|
||||
} |
@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.cache.TypeCache; |
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
/** |
||||
* Simple cache of {@link MapperFunction} instances. |
||||
*/ |
||||
public class MapperFunctionInstances { |
||||
|
||||
private static final MapperFunctionInstances MAPPER_FUNCTION_INSTANCES = new MapperFunctionInstances(); |
||||
|
||||
/** |
||||
* Returns the instance. |
||||
*/ |
||||
public static MapperFunctionInstances get() { |
||||
return MAPPER_FUNCTION_INSTANCES; |
||||
} |
||||
|
||||
protected TypeCache<MapperFunction> typeCache = TypeCache.createDefault(); |
||||
|
||||
public MapperFunction lookup(final Class<? extends MapperFunction> mapperFunctionClass) { |
||||
return typeCache.get(mapperFunctionClass, (c) -> { |
||||
try { |
||||
return ClassUtil.newInstance(mapperFunctionClass); |
||||
} catch (final Exception ex) { |
||||
throw new IllegalArgumentException("Invalid mapper class " + c, ex); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,121 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import java.io.Closeable; |
||||
import java.io.Flushable; |
||||
import java.io.IOException; |
||||
import java.io.Writer; |
||||
import java.nio.CharBuffer; |
||||
|
||||
/** |
||||
* Appendable writer adapter. |
||||
*/ |
||||
public class AppendableWriter extends Writer { |
||||
|
||||
private final Appendable appendable; |
||||
private final boolean flushable; |
||||
private boolean closed; |
||||
|
||||
public AppendableWriter(final Appendable appendable) { |
||||
this.appendable = appendable; |
||||
this.flushable = appendable instanceof Flushable; |
||||
this.closed = false; |
||||
} |
||||
|
||||
@Override |
||||
public void write(final char[] cbuf, final int off, final int len) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(CharBuffer.wrap(cbuf), off, off + len); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final int c) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append((char) c); |
||||
} |
||||
|
||||
@Override |
||||
public Writer append(final char c) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(c); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public Writer append(final CharSequence csq, final int start, final int end) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(csq, start, end); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public Writer append(final CharSequence csq) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(csq); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public void write(final String str, final int off, final int len) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(str, off, off + len); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final String str) throws IOException { |
||||
appendable.append(str); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final char[] cbuf) throws IOException { |
||||
appendable.append(CharBuffer.wrap(cbuf)); |
||||
} |
||||
|
||||
@Override |
||||
public void flush() throws IOException { |
||||
checkNotClosed(); |
||||
if (flushable) { |
||||
((Flushable) appendable).flush(); |
||||
} |
||||
} |
||||
|
||||
private void checkNotClosed() throws IOException { |
||||
if (closed) { |
||||
throw new IOException("Cannot write to closed writer " + this); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
if (!closed) { |
||||
flush(); |
||||
if (appendable instanceof Closeable) { |
||||
((Closeable) appendable).close(); |
||||
} |
||||
closed = true; |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,100 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import com.fr.third.jodd.core.JoddCore; |
||||
import com.fr.third.jodd.core.JoddCore; |
||||
|
||||
/** |
||||
* {@link FileUtil File utilities} parameters. |
||||
*/ |
||||
public class FileUtilParams implements Cloneable { |
||||
|
||||
protected boolean preserveDate = true; // should destination file have the same timestamp as source
|
||||
protected boolean overwrite = true; // overwrite existing destination
|
||||
protected boolean createDirs = true; // create missing subdirectories of destination
|
||||
protected boolean recursive = true; // use recursive directory copying and deleting
|
||||
protected boolean continueOnError = true; // don't stop on error and continue job as much as possible
|
||||
protected String encoding = JoddCore.encoding; // default encoding for reading/writing strings
|
||||
|
||||
|
||||
public boolean isPreserveDate() { |
||||
return preserveDate; |
||||
} |
||||
public FileUtilParams setPreserveDate(boolean preserveDate) { |
||||
this.preserveDate = preserveDate; |
||||
return this; |
||||
} |
||||
|
||||
public boolean isOverwrite() { |
||||
return overwrite; |
||||
} |
||||
public FileUtilParams setOverwrite(boolean overwrite) { |
||||
this.overwrite = overwrite; |
||||
return this; |
||||
} |
||||
|
||||
public boolean isCreateDirs() { |
||||
return createDirs; |
||||
} |
||||
public FileUtilParams setCreateDirs(boolean createDirs) { |
||||
this.createDirs = createDirs; |
||||
return this; |
||||
} |
||||
|
||||
public boolean isRecursive() { |
||||
return recursive; |
||||
} |
||||
public FileUtilParams setRecursive(boolean recursive) { |
||||
this.recursive = recursive; |
||||
return this; |
||||
} |
||||
|
||||
public boolean isContinueOnError() { |
||||
return continueOnError; |
||||
} |
||||
public FileUtilParams setContinueOnError(boolean continueOnError) { |
||||
this.continueOnError = continueOnError; |
||||
return this; |
||||
} |
||||
|
||||
|
||||
public String getEncoding() { |
||||
return encoding; |
||||
} |
||||
public FileUtilParams setEncoding(String encoding) { |
||||
this.encoding = encoding; |
||||
return this; |
||||
} |
||||
|
||||
// ------------------------------------------------------------ clone
|
||||
|
||||
@Override |
||||
public FileUtilParams clone() throws CloneNotSupportedException { |
||||
return (FileUtilParams) super.clone(); |
||||
} |
||||
|
||||
} |
@ -1,584 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io.findfile; |
||||
|
||||
import com.fr.third.jodd.util.ArraysUtil; |
||||
import com.fr.third.jodd.util.ClassLoaderUtil; |
||||
import com.fr.third.jodd.util.InExRuleMatcher; |
||||
import com.fr.third.jodd.util.InExRules; |
||||
import com.fr.third.jodd.util.Wildcard; |
||||
import com.fr.third.jodd.io.FileNameUtil; |
||||
import com.fr.third.jodd.util.ClassLoaderUtil; |
||||
import com.fr.third.jodd.util.InExRules; |
||||
import com.fr.third.jodd.util.StringUtil; |
||||
import com.fr.third.jodd.util.Wildcard; |
||||
import com.fr.third.jodd.util.ArraysUtil; |
||||
import com.fr.third.jodd.io.FileUtil; |
||||
import com.fr.third.jodd.io.StreamUtil; |
||||
import com.fr.third.jodd.io.ZipUtil; |
||||
|
||||
import java.net.URL; |
||||
import java.util.zip.ZipFile; |
||||
import java.util.zip.ZipEntry; |
||||
import java.util.Enumeration; |
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.FileNotFoundException; |
||||
|
||||
import static com.fr.third.jodd.util.InExRuleMatcher.WILDCARD_PATH_RULE_MATCHER; |
||||
import static com.fr.third.jodd.util.InExRuleMatcher.WILDCARD_RULE_MATCHER; |
||||
|
||||
/** |
||||
* Simple utility that scans <code>URL</code>s for classes. |
||||
* Its purpose is to help scanning class paths for some classes. |
||||
* Content of Jar files is also examined. |
||||
* <p> |
||||
* Scanning starts in included all mode (blacklist mode) for both jars and lists. |
||||
* User can set explicit excludes. Of course, mode can be changed. |
||||
* <p> |
||||
* All paths are matched using {@link Wildcard#matchPath(String, String) path-style} |
||||
* wildcard matcher. All entries are matched using {@link Wildcard#match(CharSequence, CharSequence)} common-style} |
||||
* wildcard matcher. |
||||
* |
||||
* @see ClassScanner |
||||
*/ |
||||
public abstract class ClassFinder { |
||||
|
||||
private static final String CLASS_FILE_EXT = ".class"; |
||||
private static final String JAR_FILE_EXT = ".jar"; |
||||
|
||||
// ---------------------------------------------------------------- excluded jars
|
||||
|
||||
/** |
||||
* Array of system jars that are excluded from the search. |
||||
* By default, these paths are common for linux, windows and mac. |
||||
*/ |
||||
protected static String[] systemJars = new String[] { |
||||
"**/jre/lib/*.jar", |
||||
"**/jre/lib/ext/*.jar", |
||||
"**/Java/Extensions/*.jar", |
||||
"**/Classes/*.jar" |
||||
}; |
||||
|
||||
protected final InExRules<String, String> rulesJars = createJarRules(); |
||||
|
||||
/** |
||||
* Creates JAR rules. By default, excludes all system jars. |
||||
*/ |
||||
protected InExRules<String, String> createJarRules() { |
||||
InExRules<String, String> rulesJars = new InExRules<String, String>(InExRuleMatcher.WILDCARD_PATH_RULE_MATCHER); |
||||
|
||||
for (String systemJar : systemJars) { |
||||
rulesJars.exclude(systemJar); |
||||
} |
||||
|
||||
return rulesJars; |
||||
} |
||||
|
||||
/** |
||||
* Returns system jars. |
||||
*/ |
||||
public static String[] getSystemJars() { |
||||
return systemJars; |
||||
} |
||||
|
||||
/** |
||||
* Specify excluded jars. |
||||
*/ |
||||
public void setExcludedJars(String... excludedJars) { |
||||
for (String excludedJar : excludedJars) { |
||||
rulesJars.exclude(excludedJar); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Specify included jars. |
||||
*/ |
||||
public void setIncludedJars(String... includedJars) { |
||||
for (String includedJar : includedJars) { |
||||
rulesJars.include(includedJar); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets white/black list mode for jars. |
||||
*/ |
||||
public void setIncludeAllJars(boolean blacklist) { |
||||
if (blacklist) { |
||||
rulesJars.blacklist(); |
||||
} else { |
||||
rulesJars.whitelist(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets white/black list mode for jars. |
||||
*/ |
||||
public void setExcludeAllJars(boolean whitelist) { |
||||
if (whitelist) { |
||||
rulesJars.whitelist(); |
||||
} else { |
||||
rulesJars.blacklist(); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- included entries
|
||||
|
||||
protected final InExRules<String, String> rulesEntries = createEntriesRules(); |
||||
|
||||
protected InExRules<String, String> createEntriesRules() { |
||||
return new InExRules<String, String>(InExRuleMatcher.WILDCARD_RULE_MATCHER); |
||||
} |
||||
|
||||
/** |
||||
* Sets included set of names that will be considered during configuration. |
||||
* @see InExRules |
||||
*/ |
||||
public void setIncludedEntries(String... includedEntries) { |
||||
for (String includedEntry : includedEntries) { |
||||
rulesEntries.include(includedEntry); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets white/black list mode for entries. |
||||
*/ |
||||
public void setIncludeAllEntries(boolean blacklist) { |
||||
if (blacklist) { |
||||
rulesEntries.blacklist(); |
||||
} else { |
||||
rulesEntries.whitelist(); |
||||
} |
||||
} |
||||
/** |
||||
* Sets white/black list mode for entries. |
||||
*/ |
||||
public void setExcludeAllEntries(boolean whitelist) { |
||||
if (whitelist) { |
||||
rulesEntries.whitelist(); |
||||
} else { |
||||
rulesEntries.blacklist(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets excluded names that narrows included set of packages. |
||||
* @see InExRules |
||||
*/ |
||||
public void setExcludedEntries(String... excludedEntries) { |
||||
for (String excludedEntry : excludedEntries) { |
||||
rulesEntries.exclude(excludedEntry); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- implementation
|
||||
|
||||
/** |
||||
* If set to <code>true</code> all files will be scanned and not only classes. |
||||
*/ |
||||
protected boolean includeResources; |
||||
/** |
||||
* If set to <code>true</code> exceptions for entry scans are ignored. |
||||
*/ |
||||
protected boolean ignoreException; |
||||
|
||||
|
||||
public boolean isIncludeResources() { |
||||
return includeResources; |
||||
} |
||||
|
||||
public void setIncludeResources(boolean includeResources) { |
||||
this.includeResources = includeResources; |
||||
} |
||||
|
||||
public boolean isIgnoreException() { |
||||
return ignoreException; |
||||
} |
||||
|
||||
/** |
||||
* Sets if exceptions during scanning process should be ignored or not. |
||||
*/ |
||||
public void setIgnoreException(boolean ignoreException) { |
||||
this.ignoreException = ignoreException; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- scan
|
||||
|
||||
/** |
||||
* Scans several URLs. If (#ignoreExceptions} is set, exceptions |
||||
* per one URL will be ignored and loops continues. |
||||
*/ |
||||
protected void scanUrls(URL... urls) { |
||||
for (URL path : urls) { |
||||
scanUrl(path); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Scans single URL for classes and jar files. |
||||
* Callback {@link #onEntry(EntryData)} is called on |
||||
* each class name. |
||||
*/ |
||||
protected void scanUrl(URL url) { |
||||
File file = FileUtil.toFile(url); |
||||
if (file == null) { |
||||
if (!ignoreException) { |
||||
throw new FindFileException("URL is not a valid file: " + url); |
||||
} |
||||
} |
||||
scanPath(file); |
||||
} |
||||
|
||||
|
||||
protected void scanPaths(File... paths) { |
||||
for (File path : paths) { |
||||
scanPath(path); |
||||
} |
||||
} |
||||
|
||||
protected void scanPaths(String... paths) { |
||||
for (String path : paths) { |
||||
scanPath(path); |
||||
} |
||||
} |
||||
|
||||
protected void scanPath(String path) { |
||||
scanPath(new File(path)); |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if some JAR file has to be accepted. |
||||
*/ |
||||
protected boolean acceptJar(File jarFile) { |
||||
String path = jarFile.getAbsolutePath(); |
||||
path = FileNameUtil.separatorsToUnix(path); |
||||
|
||||
return rulesJars.match(path); |
||||
} |
||||
|
||||
/** |
||||
* Scans single path. |
||||
*/ |
||||
protected void scanPath(File file) { |
||||
String path = file.getAbsolutePath(); |
||||
|
||||
if (StringUtil.endsWithIgnoreCase(path, JAR_FILE_EXT)) { |
||||
|
||||
if (!acceptJar(file)) { |
||||
return; |
||||
} |
||||
scanJarFile(file); |
||||
} else if (file.isDirectory()) { |
||||
scanClassPath(file); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- internal
|
||||
|
||||
/** |
||||
* Scans classes inside single JAR archive. Archive is scanned as a zip file. |
||||
* @see #onEntry(EntryData) |
||||
*/ |
||||
protected void scanJarFile(File file) { |
||||
ZipFile zipFile; |
||||
try { |
||||
zipFile = new ZipFile(file); |
||||
} catch (IOException ioex) { |
||||
if (!ignoreException) { |
||||
throw new FindFileException("Invalid zip: " + file.getName(), ioex); |
||||
} |
||||
return; |
||||
} |
||||
Enumeration entries = zipFile.entries(); |
||||
while (entries.hasMoreElements()) { |
||||
ZipEntry zipEntry = (ZipEntry) entries.nextElement(); |
||||
String zipEntryName = zipEntry.getName(); |
||||
try { |
||||
if (StringUtil.endsWithIgnoreCase(zipEntryName, CLASS_FILE_EXT)) { |
||||
String entryName = prepareEntryName(zipEntryName, true); |
||||
EntryData entryData = new EntryData(entryName, zipFile, zipEntry); |
||||
try { |
||||
scanEntry(entryData); |
||||
} finally { |
||||
entryData.closeInputStreamIfOpen(); |
||||
} |
||||
} else if (includeResources) { |
||||
String entryName = prepareEntryName(zipEntryName, false); |
||||
EntryData entryData = new EntryData(entryName, zipFile, zipEntry); |
||||
try { |
||||
scanEntry(entryData); |
||||
} finally { |
||||
entryData.closeInputStreamIfOpen(); |
||||
} |
||||
} |
||||
} catch (RuntimeException rex) { |
||||
if (!ignoreException) { |
||||
ZipUtil.close(zipFile); |
||||
throw rex; |
||||
} |
||||
} |
||||
} |
||||
ZipUtil.close(zipFile); |
||||
} |
||||
|
||||
/** |
||||
* Scans single classpath directory. |
||||
* @see #onEntry(EntryData) |
||||
*/ |
||||
protected void scanClassPath(File root) { |
||||
String rootPath = root.getAbsolutePath(); |
||||
if (!rootPath.endsWith(File.separator)) { |
||||
rootPath += File.separatorChar; |
||||
} |
||||
|
||||
FindFile ff = new FindFile().setIncludeDirs(false).setRecursive(true).searchPath(rootPath); |
||||
File file; |
||||
while ((file = ff.nextFile()) != null) { |
||||
String filePath = file.getAbsolutePath(); |
||||
try { |
||||
if (StringUtil.endsWithIgnoreCase(filePath, CLASS_FILE_EXT)) { |
||||
scanClassFile(filePath, rootPath, file, true); |
||||
} else if (includeResources) { |
||||
scanClassFile(filePath, rootPath, file, false); |
||||
} |
||||
} catch (RuntimeException rex) { |
||||
if (!ignoreException) { |
||||
throw rex; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected void scanClassFile(String filePath, String rootPath, File file, boolean isClass) { |
||||
if (StringUtil.startsWithIgnoreCase(filePath, rootPath)) { |
||||
String entryName = prepareEntryName(filePath.substring(rootPath.length()), isClass); |
||||
EntryData entryData = new EntryData(entryName, file); |
||||
try { |
||||
scanEntry(entryData); |
||||
} finally { |
||||
entryData.closeInputStreamIfOpen(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Prepares resource and class names. For classes, it strips '.class' from the end and converts |
||||
* all (back)slashes to dots. For resources, it replaces all backslashes to slashes. |
||||
*/ |
||||
protected String prepareEntryName(String name, boolean isClass) { |
||||
String entryName = name; |
||||
if (isClass) { |
||||
entryName = name.substring(0, name.length() - 6); // 6 == ".class".length()
|
||||
entryName = StringUtil.replaceChar(entryName, '/', '.'); |
||||
entryName = StringUtil.replaceChar(entryName, '\\', '.'); |
||||
} else { |
||||
entryName = '/' + StringUtil.replaceChar(entryName, '\\', '/'); |
||||
} |
||||
return entryName; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if some entry name has to be accepted. |
||||
* @see #prepareEntryName(String, boolean) |
||||
* @see #scanEntry(EntryData) |
||||
*/ |
||||
protected boolean acceptEntry(String entryName) { |
||||
return rulesEntries.match(entryName); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* If entry name is {@link #acceptEntry(String) accepted} invokes {@link #onEntry(EntryData)} a callback}. |
||||
*/ |
||||
protected void scanEntry(EntryData entryData) { |
||||
if (!acceptEntry(entryData.getName())) { |
||||
return; |
||||
} |
||||
try { |
||||
onEntry(entryData); |
||||
} catch (Exception ex) { |
||||
throw new FindFileException("Scan entry error: " + entryData, ex); |
||||
} |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- callback
|
||||
|
||||
/** |
||||
* Called during classpath scanning when class or resource is found. |
||||
* <ul> |
||||
* <li>Class name is java-alike class name (pk1.pk2.class) that may be immediately used |
||||
* for dynamic loading.</li> |
||||
* <li>Resource name starts with '\' and represents either jar path (\pk1/pk2/res) or relative file path (\pk1\pk2\res).</li> |
||||
* </ul> |
||||
* |
||||
* <code>InputStream</code> is provided by InputStreamProvider and opened lazy. |
||||
* Once opened, input stream doesn't have to be closed - this is done by this class anyway. |
||||
*/ |
||||
protected abstract void onEntry(EntryData entryData) throws Exception; |
||||
|
||||
// ---------------------------------------------------------------- utilities
|
||||
|
||||
/** |
||||
* Returns type signature bytes used for searching in class file. |
||||
*/ |
||||
protected byte[] getTypeSignatureBytes(Class type) { |
||||
String name = 'L' + type.getName().replace('.', '/') + ';'; |
||||
return name.getBytes(); |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if class contains {@link #getTypeSignatureBytes(Class) type signature}. |
||||
* It searches the class content for bytecode signature. This is the fastest way of finding if come |
||||
* class uses some type. Please note that if signature exists it still doesn't means that class uses |
||||
* it in expected way, therefore, class should be loaded to complete the scan. |
||||
*/ |
||||
protected boolean isTypeSignatureInUse(InputStream inputStream, byte[] bytes) { |
||||
try { |
||||
byte[] data = StreamUtil.readBytes(inputStream); |
||||
int index = ArraysUtil.indexOf(data, bytes); |
||||
return index != -1; |
||||
} catch (IOException ioex) { |
||||
throw new FindFileException("Read error", ioex); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- class loading
|
||||
|
||||
/** |
||||
* Loads class by its name. If {@link #ignoreException} is set, |
||||
* no exception is thrown, but <code>null</code> is returned. |
||||
*/ |
||||
protected Class loadClass(String className) throws ClassNotFoundException { |
||||
try { |
||||
return ClassLoaderUtil.loadClass(className); |
||||
} catch (ClassNotFoundException cnfex) { |
||||
if (ignoreException) { |
||||
return null; |
||||
} |
||||
throw cnfex; |
||||
} catch (Error error) { |
||||
if (ignoreException) { |
||||
return null; |
||||
} |
||||
throw error; |
||||
} |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- provider
|
||||
|
||||
/** |
||||
* Provides input stream on demand. Input stream is not open until get(). |
||||
*/ |
||||
protected static class EntryData { |
||||
|
||||
private final File file; |
||||
private final ZipFile zipFile; |
||||
private final ZipEntry zipEntry; |
||||
private final String name; |
||||
|
||||
EntryData(String name, ZipFile zipFile, ZipEntry zipEntry) { |
||||
this.name = name; |
||||
this.zipFile = zipFile; |
||||
this.zipEntry = zipEntry; |
||||
this.file = null; |
||||
inputStream = null; |
||||
} |
||||
EntryData(String name, File file) { |
||||
this.name = name; |
||||
this.file = file; |
||||
this.zipEntry = null; |
||||
this.zipFile = null; |
||||
inputStream = null; |
||||
} |
||||
|
||||
private InputStream inputStream; |
||||
|
||||
/** |
||||
* Returns entry name. |
||||
*/ |
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if archive. |
||||
*/ |
||||
public boolean isArchive() { |
||||
return zipFile != null; |
||||
} |
||||
|
||||
/** |
||||
* Returns archive name or <code>null</code> if entry is not inside archived file. |
||||
*/ |
||||
public String getArchiveName() { |
||||
if (zipFile != null) { |
||||
return zipFile.getName(); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Opens zip entry or plain file and returns its input stream. |
||||
*/ |
||||
public InputStream openInputStream() { |
||||
if (zipFile != null) { |
||||
try { |
||||
inputStream = zipFile.getInputStream(zipEntry); |
||||
return inputStream; |
||||
} catch (IOException ioex) { |
||||
throw new FindFileException("Input stream error: '" + zipFile.getName() |
||||
+ "', entry: '" + zipEntry.getName() + "'." , ioex); |
||||
} |
||||
} |
||||
try { |
||||
inputStream = new FileInputStream(file); |
||||
return inputStream; |
||||
} catch (FileNotFoundException fnfex) { |
||||
throw new FindFileException("Unable to open: " + file.getAbsolutePath(), fnfex); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Closes input stream if opened. |
||||
*/ |
||||
void closeInputStreamIfOpen() { |
||||
if (inputStream == null) { |
||||
return; |
||||
} |
||||
StreamUtil.close(inputStream); |
||||
inputStream = null; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "EntryData{" + name + '\'' +'}'; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io.findfile; |
||||
|
||||
import com.fr.third.jodd.io.FileNameUtil; |
||||
|
||||
import java.io.File; |
||||
import java.io.Serializable; |
||||
import java.util.Comparator; |
||||
|
||||
public class FileExtensionComparator implements Comparator<File>, Serializable { |
||||
protected final int order; |
||||
|
||||
public FileExtensionComparator(final boolean ascending) { |
||||
if (ascending) { |
||||
order = 1; |
||||
} else { |
||||
order = -1; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int compare(final File file1, final File file2) { |
||||
String ext1 = FileNameUtil.getExtension(file1.getName()); |
||||
String ext2 = FileNameUtil.getExtension(file2.getName()); |
||||
long diff = ext1.compareToIgnoreCase(ext2); |
||||
if (diff == 0) { |
||||
return 0; |
||||
} |
||||
if (diff > 0) { |
||||
return order; |
||||
} |
||||
return -order; |
||||
} |
||||
} |
@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io.findfile; |
||||
|
||||
import java.io.File; |
||||
import java.io.Serializable; |
||||
import java.util.Comparator; |
||||
|
||||
public class FileLastModifiedTimeComparator implements Comparator<File>, Serializable { |
||||
protected final int order; |
||||
|
||||
public FileLastModifiedTimeComparator(final boolean ascending) { |
||||
if (ascending) { |
||||
order = 1; |
||||
} else { |
||||
order = -1; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int compare(final File file1, final File file2) { |
||||
long diff = file1.lastModified() - file2.lastModified(); |
||||
if (diff == 0) { |
||||
return 0; |
||||
} |
||||
if (diff > 0) { |
||||
return order; |
||||
} |
||||
return -order; |
||||
} |
||||
} |
@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io.findfile; |
||||
|
||||
import com.fr.third.jodd.util.NaturalOrderComparator; |
||||
|
||||
import java.io.File; |
||||
import java.io.Serializable; |
||||
import java.util.Comparator; |
||||
|
||||
public class FileNameComparator implements Comparator<File>, Serializable { |
||||
protected final int order; |
||||
protected NaturalOrderComparator<String> naturalOrderComparator = new NaturalOrderComparator<>(true, true, true); |
||||
|
||||
public FileNameComparator(final boolean ascending) { |
||||
if (ascending) { |
||||
order = 1; |
||||
} else { |
||||
order = -1; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int compare(final File file1, final File file2) { |
||||
int result = naturalOrderComparator.compare(file1.getName(), file2.getName()); |
||||
if (result == 0) { |
||||
return result; |
||||
} |
||||
if (result > 0) { |
||||
return order; |
||||
} |
||||
return -order; |
||||
} |
||||
} |
@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io.findfile; |
||||
|
||||
import java.io.File; |
||||
import java.io.Serializable; |
||||
import java.util.Comparator; |
||||
|
||||
public class FolderFirstComparator implements Comparator<File>, Serializable { |
||||
protected final int order; |
||||
|
||||
public FolderFirstComparator(final boolean foldersFirst) { |
||||
if (foldersFirst) { |
||||
order = 1; |
||||
} else { |
||||
order = -1; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int compare(final File file1, final File file2) { |
||||
if (file1.isFile() && file2.isDirectory()) { |
||||
return order; |
||||
} |
||||
if (file1.isDirectory() && file2.isFile()) { |
||||
return -order; |
||||
} |
||||
return 0; |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue