| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| package org.apache.directory.api.util; |
| |
| |
| import static org.apache.directory.api.util.Chars.isHex; |
| import static org.apache.directory.api.util.Hex.encodeHex; |
| import static org.apache.directory.api.util.Hex.getHexValue; |
| |
| import java.io.UnsupportedEncodingException; |
| import java.nio.charset.Charset; |
| import java.nio.charset.StandardCharsets; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.UUID; |
| |
| import org.apache.directory.api.i18n.I18n; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| |
| /** |
| * Various string manipulation methods that are more efficient then chaining |
| * string operations: all is done in the same buffer without creating a bunch of |
| * string objects. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| */ |
| public final class Strings |
| { |
| /** A logger for this class */ |
| private static final Logger LOG = LoggerFactory.getLogger( Strings.class ); |
| |
| /** Hex chars */ |
| public static final byte[] HEX_CHAR = new byte[] |
| { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; |
| |
| /** A table containing booleans when the corresponding char is printable */ |
| private static final boolean[] IS_PRINTABLE_CHAR = |
| { |
| // ---, ---, ---, ---, ---, ---, ---, --- |
| false, false, false, false, false, false, false, false, |
| // ---, ---, ---, ---, ---, ---, ---, --- |
| false, false, false, false, false, false, false, false, |
| // ---, ---, ---, ---, ---, ---, ---, --- |
| false, false, false, false, false, false, false, false, |
| // ---, ---, ---, ---, ---, ---, ---, --- |
| false, false, false, false, false, false, false, false, |
| // ' ', ---, ---, ---, ---, ---, ---, "'" |
| true, false, false, false, false, false, false, true, |
| // '(', ')', ---, '+', ',', '-', '.', '/' |
| true, true, false, true, true, true, true, true, |
| // '0', '1', '2', '3', '4', '5', '6', '7', |
| true, true, true, true, true, true, true, true, |
| // '8', '9', ':', ---, ---, '=', ---, '?' |
| true, true, true, false, false, true, false, true, |
| // ---, 'A', 'B', 'C', 'D', 'E', 'F', 'G', |
| false, true, true, true, true, true, true, true, |
| // 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O' |
| true, true, true, true, true, true, true, true, |
| // 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W' |
| true, true, true, true, true, true, true, true, |
| // 'X', 'Y', 'Z', ---, ---, ---, ---, --- |
| true, true, true, false, false, false, false, false, |
| // ---, 'a', 'b', 'c', 'd', 'e', 'f', 'g' |
| false, true, true, true, true, true, true, true, |
| // 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o' |
| true, true, true, true, true, true, true, true, |
| // 'p', 'q', 'r', 's', 't', 'u', 'v', 'w' |
| true, true, true, true, true, true, true, true, |
| // 'x', 'y', 'z', ---, ---, ---, ---, --- |
| true, true, true, false, false, false, false, false |
| }; |
| |
| private static final char[] TO_LOWER_CASE = |
| { |
| 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, |
| 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, |
| ' ', 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, '\'', |
| '(', ')', 0x2A, '+', ',', '-', '.', '/', |
| '0', '1', '2', '3', '4', '5', '6', '7', |
| '8', '9', ':', 0x3B, 0x3C, '=', 0x3E, '?', |
| 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', |
| 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', |
| 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', |
| 'x', 'y', 'z', 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, |
| 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', |
| 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', |
| 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', |
| 'x', 'y', 'z', 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, |
| 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, |
| 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, |
| 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, |
| 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, |
| 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, |
| 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, |
| 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, |
| 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, |
| 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, |
| 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, |
| 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, |
| 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, |
| 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, |
| 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, |
| 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, |
| 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, |
| }; |
| |
| private static final byte[] TO_LOWER_CASE_BYTE = |
| { |
| 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, |
| 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, |
| ' ', 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, '\'', |
| '(', ')', 0x2A, '+', ',', '-', '.', '/', |
| '0', '1', '2', '3', '4', '5', '6', '7', |
| '8', '9', ':', 0x3B, 0x3C, '=', 0x3E, '?', |
| 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', |
| 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', |
| 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', |
| 'x', 'y', 'z', 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, |
| 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', |
| 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', |
| 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', |
| 'x', 'y', 'z', 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, |
| ( byte ) 0x80, ( byte ) 0x81, ( byte ) 0x82, ( byte ) 0x83, |
| ( byte ) 0x84, ( byte ) 0x85, ( byte ) 0x86, ( byte ) 0x87, |
| ( byte ) 0x88, ( byte ) 0x89, ( byte ) 0x8A, ( byte ) 0x8B, |
| ( byte ) 0x8C, ( byte ) 0x8D, ( byte ) 0x8E, ( byte ) 0x8F, |
| ( byte ) 0x90, ( byte ) 0x91, ( byte ) 0x92, ( byte ) 0x93, |
| ( byte ) 0x94, ( byte ) 0x95, ( byte ) 0x96, ( byte ) 0x97, |
| ( byte ) 0x98, ( byte ) 0x99, ( byte ) 0x9A, ( byte ) 0x9B, |
| ( byte ) 0x9C, ( byte ) 0x9D, ( byte ) 0x9E, ( byte ) 0x9F, |
| ( byte ) 0xA0, ( byte ) 0xA1, ( byte ) 0xA2, ( byte ) 0xA3, |
| ( byte ) 0xA4, ( byte ) 0xA5, ( byte ) 0xA6, ( byte ) 0xA7, |
| ( byte ) 0xA8, ( byte ) 0xA9, ( byte ) 0xAA, ( byte ) 0xAB, |
| ( byte ) 0xAC, ( byte ) 0xAD, ( byte ) 0xAE, ( byte ) 0xAF, |
| ( byte ) 0xB0, ( byte ) 0xB1, ( byte ) 0xB2, ( byte ) 0xB3, |
| ( byte ) 0xB4, ( byte ) 0xB5, ( byte ) 0xB6, ( byte ) 0xB7, |
| ( byte ) 0xB8, ( byte ) 0xB9, ( byte ) 0xBA, ( byte ) 0xBB, |
| ( byte ) 0xBC, ( byte ) 0xBD, ( byte ) 0xBE, ( byte ) 0xBF, |
| ( byte ) 0xC0, ( byte ) 0xC1, ( byte ) 0xC2, ( byte ) 0xC3, |
| ( byte ) 0xC4, ( byte ) 0xC5, ( byte ) 0xC6, ( byte ) 0xC7, |
| ( byte ) 0xC8, ( byte ) 0xC9, ( byte ) 0xCA, ( byte ) 0xCB, |
| ( byte ) 0xCC, ( byte ) 0xCD, ( byte ) 0xCE, ( byte ) 0xCF, |
| ( byte ) 0xD0, ( byte ) 0xD1, ( byte ) 0xD2, ( byte ) 0xD3, |
| ( byte ) 0xD4, ( byte ) 0xD5, ( byte ) 0xD6, ( byte ) 0xD7, |
| ( byte ) 0xD8, ( byte ) 0xD9, ( byte ) 0xDA, ( byte ) 0xDB, |
| ( byte ) 0xDC, ( byte ) 0xDD, ( byte ) 0xDE, ( byte ) 0xDF, |
| ( byte ) 0xE0, ( byte ) 0xE1, ( byte ) 0xE2, ( byte ) 0xE3, |
| ( byte ) 0xE4, ( byte ) 0xE5, ( byte ) 0xE6, ( byte ) 0xE7, |
| ( byte ) 0xE8, ( byte ) 0xE9, ( byte ) 0xEA, ( byte ) 0xEB, |
| ( byte ) 0xEC, ( byte ) 0xED, ( byte ) 0xEE, ( byte ) 0xEF, |
| ( byte ) 0xF0, ( byte ) 0xF1, ( byte ) 0xF2, ( byte ) 0xF3, |
| ( byte ) 0xF4, ( byte ) 0xF5, ( byte ) 0xF6, ( byte ) 0xF7, |
| ( byte ) 0xF8, ( byte ) 0xF9, ( byte ) 0xFA, ( byte ) 0xFB, |
| ( byte ) 0xFC, ( byte ) 0xFD, ( byte ) 0xFE, ( byte ) 0xFF |
| }; |
| |
| /** upperCase = 'A' .. 'Z', '0'..'9', '-' */ |
| private static final char[] UPPER_CASE = |
| { |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, '-', 0, 0, |
| '0', '1', '2', '3', '4', '5', '6', '7', |
| '8', '9', 0, 0, 0, 0, 0, 0, |
| 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', |
| 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', |
| 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', |
| 'X', 'Y', 'Z', 0, 0, 0, 0, 0, |
| 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', |
| 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', |
| 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', |
| 'X', 'Y', 'Z', 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| /** The ASCI chars */ |
| private static final byte[] UTF8 = new byte[] |
| { |
| 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, |
| 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, |
| 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, |
| 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, |
| 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, |
| 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, |
| 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, |
| 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, |
| 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, |
| 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, |
| 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, |
| 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, |
| 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, |
| 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F |
| }; |
| |
| /** An empty byte array */ |
| public static final byte[] EMPTY_BYTES = new byte[0]; |
| |
| /** An empty String */ |
| public static final String EMPTY_STRING = ""; |
| |
| /** An empty String array */ |
| public static final String[] EMPTY_STRING_ARRAY = new String[]{}; |
| |
| |
| /** |
| * Private constructor |
| */ |
| private Strings() |
| { |
| } |
| |
| |
| /** |
| * Helper function that dump an array of bytes in hex form |
| * |
| * @param buffer The bytes array to dump |
| * @return A string representation of the array of bytes |
| */ |
| public static String dumpBytes( byte[] buffer ) |
| { |
| if ( buffer == null ) |
| { |
| return ""; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| for ( int i = 0; i < buffer.length; i++ ) |
| { |
| sb.append( "0x" ).append( ( char ) ( HEX_CHAR[( buffer[i] & 0x00F0 ) >> 4] ) ).append( |
| ( char ) ( HEX_CHAR[buffer[i] & 0x000F] ) ).append( " " ); |
| } |
| |
| return sb.toString(); |
| } |
| |
| |
| /** |
| * Helper function that dump a byte as a double digit value |
| * |
| * @param b The byte to dump |
| * @return A string representation of byte as a string |
| */ |
| public static String byteToString( byte b ) |
| { |
| return Strings.utf8ToString( new byte[] |
| { HEX_CHAR[( b & 0x00F0 ) >> 4], HEX_CHAR[b & 0x000F] } ); |
| } |
| |
| |
| /** |
| * Helper function that dump a byte in hex form |
| * |
| * @param octet The byte to dump |
| * @return A string representation of the byte |
| */ |
| public static String dumpByte( byte octet ) |
| { |
| return Strings.utf8ToString( new byte[] |
| { '0', 'x', HEX_CHAR[( octet & 0x00F0 ) >> 4], HEX_CHAR[octet & 0x000F] } ); |
| } |
| |
| |
| /** |
| * Helper function that returns a char from an hex |
| * |
| * @param hex The hex to dump |
| * @return A char representation of the hex |
| */ |
| public static char dumpHex( byte hex ) |
| { |
| return ( char ) HEX_CHAR[hex & 0x000F]; |
| } |
| |
| |
| /** |
| * Helper function that dump an array of bytes in hex pair form, |
| * without '0x' and space chars |
| * |
| * @param buffer The bytes array to dump |
| * @return A string representation of the array of bytes |
| */ |
| public static String dumpHexPairs( byte[] buffer ) |
| { |
| if ( buffer == null ) |
| { |
| return ""; |
| } |
| |
| char[] str = new char[buffer.length << 1]; |
| int pos = 0; |
| |
| for ( int i = 0; i < buffer.length; i++ ) |
| { |
| str[pos++] = ( char ) ( HEX_CHAR[( buffer[i] & 0x00F0 ) >> 4] ); |
| str[pos++] = ( char ) ( HEX_CHAR[buffer[i] & 0x000F] ); |
| } |
| |
| return new String( str ); |
| } |
| |
| |
| /** |
| * Put common code to deepTrim(String) and deepTrimToLower here. |
| * |
| * @param str the string to deep trim |
| * @param toLowerCase how to normalize for case: upper or lower |
| * @return the deep trimmed string |
| * @see Strings#deepTrim( String ) |
| */ |
| public static String deepTrim( String str, boolean toLowerCase ) |
| { |
| if ( ( null == str ) || ( str.length() == 0 ) ) |
| { |
| return ""; |
| } |
| |
| char ch; |
| int length = str.length(); |
| char[] newbuf = new char[length]; |
| boolean wsSeen = false; |
| boolean isStart = true; |
| int pos = 0; |
| |
| for ( int i = 0; i < length; i++ ) |
| { |
| ch = str.charAt( i ); |
| |
| // filter out all uppercase characters |
| if ( toLowerCase && Character.isUpperCase( ch ) ) |
| { |
| ch = Character.toLowerCase( ch ); |
| } |
| |
| // Check to see if we should add space |
| if ( Character.isWhitespace( ch ) ) |
| { |
| // If the buffer has had characters added already check last |
| // added character. Only append a spc if last character was |
| // not whitespace. |
| if ( !wsSeen ) |
| { |
| wsSeen = true; |
| |
| if ( isStart ) |
| { |
| isStart = false; |
| } |
| else |
| { |
| newbuf[pos++] = ch; |
| } |
| } |
| } |
| else |
| { |
| // Add all non-whitespace |
| wsSeen = false; |
| isStart = false; |
| newbuf[pos++] = ch; |
| } |
| } |
| |
| return pos == 0 ? "" : new String( newbuf, 0, wsSeen ? pos - 1 : pos ); |
| } |
| |
| |
| /** |
| * This does the same thing as a trim but we also lowercase the string while |
| * performing the deep trim within the same buffer. This saves us from |
| * having to create multiple String and StringBuilder objects and is much |
| * more efficient. |
| * |
| * @see Strings#deepTrim( String ) |
| * @param string The String to modify |
| * @return The modified String |
| */ |
| public static String deepTrimToLower( String string ) |
| { |
| return deepTrim( string, true ); |
| } |
| |
| |
| /** |
| * A deep trim of a string remove whitespace from the ends as well as |
| * excessive whitespace within the inside of the string between |
| * non-whitespace characters. A deep trim reduces internal whitespace down |
| * to a single space to preserve the whitespace separated tokenization order |
| * of the String. |
| * |
| * @param string the string to deep trim. |
| * @return the trimmed string. |
| */ |
| public static String deepTrim( String string ) |
| { |
| return deepTrim( string, false ); |
| } |
| |
| |
| /** |
| * Trims several consecutive characters into one. |
| * |
| * @param str the string to trim consecutive characters of |
| * @param ch the character to trim down |
| * @return the newly trimmed down string |
| */ |
| public static String trimConsecutiveToOne( String str, char ch ) |
| { |
| if ( ( null == str ) || ( str.length() == 0 ) ) |
| { |
| return ""; |
| } |
| |
| char[] buffer = str.toCharArray(); |
| char[] newbuf = new char[buffer.length]; |
| int pos = 0; |
| boolean same = false; |
| |
| for ( int i = 0; i < buffer.length; i++ ) |
| { |
| char car = buffer[i]; |
| |
| if ( car == ch ) |
| { |
| if ( !same ) |
| { |
| same = true; |
| newbuf[pos++] = car; |
| } |
| } |
| else |
| { |
| same = false; |
| newbuf[pos++] = car; |
| } |
| } |
| |
| return new String( newbuf, 0, pos ); |
| } |
| |
| |
| /** |
| * Truncates large Strings showing a portion of the String's head and tail |
| * with the center cut out and replaced with '...'. Also displays the total |
| * length of the truncated string so size of '...' can be interpreted. |
| * Useful for large strings in UIs or hex dumps to log files. |
| * |
| * @param str the string to truncate |
| * @param head the amount of the head to display |
| * @param tail the amount of the tail to display |
| * @return the center truncated string |
| */ |
| public static String centerTrunc( String str, int head, int tail ) |
| { |
| // Return as-is if String is smaller than or equal to the head plus the |
| // tail plus the number of characters added to the trunc representation |
| // plus the number of digits in the string length. |
| if ( str.length() <= ( head + tail + 7 + str.length() / 10 ) ) |
| { |
| return str; |
| } |
| |
| StringBuilder buf = new StringBuilder(); |
| buf.append( '[' ).append( str.length() ).append( "][" ); |
| buf.append( str.substring( 0, head ) ).append( "..." ); |
| buf.append( str.substring( str.length() - tail ) ); |
| buf.append( ']' ); |
| |
| return buf.toString(); |
| } |
| |
| |
| /** |
| * Gets a hex string from byte array. |
| * |
| * @param res the byte array |
| * @return the hex string representing the binary values in the array |
| */ |
| public static String toHexString( byte[] res ) |
| { |
| StringBuilder buf = new StringBuilder( res.length << 1 ); |
| |
| for ( int ii = 0; ii < res.length; ii++ ) |
| { |
| String digit = Integer.toHexString( 0xFF & res[ii] ); |
| |
| if ( digit.length() == 1 ) |
| { |
| digit = '0' + digit; |
| } |
| |
| buf.append( digit ); |
| } |
| |
| return upperCase( buf.toString() ); |
| } |
| |
| |
| /** |
| * Get byte array from hex string |
| * |
| * @param hexString the hex string to convert to a byte array |
| * @return the byte form of the hex string. |
| */ |
| public static byte[] toByteArray( String hexString ) |
| { |
| int arrLength = hexString.length() >> 1; |
| byte[] buf = new byte[arrLength]; |
| |
| for ( int ii = 0; ii < arrLength; ii++ ) |
| { |
| int index = ii << 1; |
| |
| String digit = hexString.substring( index, index + 2 ); |
| buf[ii] = ( byte ) Integer.parseInt( digit, 16 ); |
| } |
| |
| return buf; |
| } |
| |
| |
| /** |
| * This method is used to insert HTML block dynamically |
| * |
| * @param source the HTML code to be processes |
| * @param replaceNl if true '\n' will be replaced by <br> |
| * @param replaceTag if true '<' will be replaced by < and '>' will be replaced |
| * by > |
| * @param replaceQuote if true '\"' will be replaced by " |
| * @return the formated html block |
| */ |
| public static String formatHtml( String source, boolean replaceNl, boolean replaceTag, |
| boolean replaceQuote ) |
| { |
| StringBuilder buf = new StringBuilder(); |
| int len = source.length(); |
| |
| for ( int i = 0; i < len; i++ ) |
| { |
| char ch = source.charAt( i ); |
| |
| switch ( ch ) |
| { |
| case '\"': |
| if ( replaceQuote ) |
| { |
| buf.append( """ ); |
| } |
| else |
| { |
| buf.append( ch ); |
| } |
| break; |
| |
| case '<': |
| if ( replaceTag ) |
| { |
| buf.append( "<" ); |
| } |
| else |
| { |
| buf.append( ch ); |
| } |
| break; |
| |
| case '>': |
| if ( replaceTag ) |
| { |
| buf.append( ">" ); |
| } |
| else |
| { |
| buf.append( ch ); |
| } |
| break; |
| |
| case '\n': |
| if ( replaceNl ) |
| { |
| if ( replaceTag ) |
| { |
| buf.append( "<br>" ); |
| } |
| else |
| { |
| buf.append( "<br>" ); |
| } |
| } |
| else |
| { |
| buf.append( ch ); |
| } |
| break; |
| |
| case '\r': |
| break; |
| |
| case '&': |
| buf.append( "&" ); |
| break; |
| |
| default: |
| buf.append( ch ); |
| break; |
| } |
| } |
| |
| return buf.toString(); |
| } |
| |
| |
| /** |
| * Check if a text is present at the current position in another string. |
| * |
| * @param string The string which contains the data |
| * @param index Current position in the string |
| * @param text The text we want to check |
| * @return <code>true</code> if the string contains the text. |
| */ |
| public static boolean areEquals( String string, int index, String text ) |
| { |
| if ( ( string == null ) || ( text == null ) ) |
| { |
| return false; |
| } |
| |
| int length1 = string.length(); |
| int length2 = text.length(); |
| |
| if ( ( length1 == 0 ) || ( length1 <= index ) || ( index < 0 ) |
| || ( length2 == 0 ) || ( length2 > ( length1 + index ) ) ) |
| { |
| return false; |
| } |
| else |
| { |
| return string.substring( index ).startsWith( text ); |
| } |
| } |
| |
| |
| /** |
| * Test if the current character is equal to a specific character. This |
| * function works only for character between 0 and 127, as it does compare a |
| * byte and a char (which is 16 bits wide) |
| * |
| * @param byteArray The buffer which contains the data |
| * @param index Current position in the buffer |
| * @param car The character we want to compare with the current buffer position |
| * @return <code>true</code> if the current character equals the given character. |
| */ |
| public static boolean isCharASCII( byte[] byteArray, int index, char car ) |
| { |
| if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) ) |
| { |
| return false; |
| } |
| else |
| { |
| return byteArray[index] == car; |
| } |
| } |
| |
| |
| /** |
| * Test if the current character is equal to a specific character. This |
| * function works only for character between 0 and 127, as it does compare a |
| * byte and a char (which is 16 bits wide) |
| * |
| * @param charArray The buffer which contains the data |
| * @param index Current position in the buffer |
| * @param car The character we want to compare with the current buffer position |
| * @return <code>true</code> if the current character equals the given character. |
| */ |
| public static boolean isCharASCII( char[] charArray, int index, char car ) |
| { |
| if ( ( charArray == null ) || ( charArray.length == 0 ) || ( index < 0 ) || ( index >= charArray.length ) ) |
| { |
| return false; |
| } |
| else |
| { |
| return charArray[index] == car; |
| } |
| } |
| |
| |
| /** |
| * Test if the current character is equal to a specific character. |
| * |
| * @param string The String which contains the data |
| * @param index Current position in the string |
| * @param car The character we want to compare with the current string position |
| * @return <code>true</code> if the current character equals the given character. |
| */ |
| public static boolean isCharASCII( String string, int index, char car ) |
| { |
| if ( string == null ) |
| { |
| return false; |
| } |
| |
| int length = string.length(); |
| |
| if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) ) |
| { |
| return false; |
| } |
| else |
| { |
| return string.charAt( index ) == car; |
| } |
| } |
| |
| |
| /** |
| * Return an UTF-8 encoded String |
| * |
| * @param bytes The byte array to be transformed to a String |
| * @return A String. |
| */ |
| public static String utf8ToString( byte[] bytes ) |
| { |
| if ( bytes == null ) |
| { |
| return ""; |
| } |
| |
| char[] chars = new char[bytes.length]; |
| int pos = 0; |
| |
| try |
| { |
| for ( byte b : bytes ) |
| { |
| chars[pos++] = ( char ) UTF8[b]; |
| } |
| } |
| catch ( ArrayIndexOutOfBoundsException aioobe ) |
| { |
| return new String( bytes, StandardCharsets.UTF_8 ); |
| } |
| |
| return new String( chars ); |
| } |
| |
| |
| /** |
| * Return an UTF-8 encoded String |
| * |
| * @param bytes The byte array to be transformed to a String |
| * @param length The length of the byte array to be converted |
| * @return A String. |
| */ |
| public static String utf8ToString( byte[] bytes, int length ) |
| { |
| if ( bytes == null ) |
| { |
| return ""; |
| } |
| |
| return new String( bytes, 0, length, StandardCharsets.UTF_8 ); |
| } |
| |
| |
| /** |
| * Return an UTF-8 encoded String |
| * |
| * @param bytes The byte array to be transformed to a String |
| * @param start the starting position in the byte array |
| * @param length The length of the byte array to be converted |
| * @return A String. |
| */ |
| public static String utf8ToString( byte[] bytes, int start, int length ) |
| { |
| if ( bytes == null ) |
| { |
| return ""; |
| } |
| |
| return new String( bytes, start, length, StandardCharsets.UTF_8 ); |
| } |
| |
| |
| /** |
| * Check if a text is present at the current position in a buffer. |
| * |
| * @param bytes The buffer which contains the data |
| * @param index Current position in the buffer |
| * @param text The text we want to check |
| * @return <code>true</code> if the buffer contains the text. |
| */ |
| public static int areEquals( byte[] bytes, int index, String text ) |
| { |
| if ( ( bytes == null ) || ( bytes.length == 0 ) || ( bytes.length <= index ) || ( index < 0 ) |
| || ( text == null ) ) |
| { |
| return StringConstants.NOT_EQUAL; |
| } |
| else |
| { |
| byte[] data = text.getBytes( StandardCharsets.UTF_8 ); |
| |
| return areEquals( bytes, index, data ); |
| } |
| } |
| |
| |
| /** |
| * Check if a text is present at the current position in a buffer. |
| * |
| * @param chars The buffer which contains the data |
| * @param index Current position in the buffer |
| * @param text The text we want to check |
| * @return <code>true</code> if the buffer contains the text. |
| */ |
| public static int areEquals( char[] chars, int index, String text ) |
| { |
| return areEquals( chars, index, text, true ); |
| } |
| |
| |
| /** |
| * Check if a text is present at the current position in a buffer. |
| * |
| * @param chars The buffer which contains the data |
| * @param index Current position in the buffer |
| * @param text The text we want to check |
| * @param caseSensitive If the comparison is case-sensitive |
| * @return <code>true</code> if the buffer contains the text. |
| */ |
| public static int areEquals( char[] chars, int index, String text, boolean caseSensitive ) |
| { |
| if ( ( chars == null ) || ( chars.length == 0 ) || ( chars.length <= index ) || ( index < 0 ) |
| || ( text == null ) ) |
| { |
| return StringConstants.NOT_EQUAL; |
| } |
| else |
| { |
| char[] data = text.toCharArray(); |
| |
| return areEquals( chars, index, data, caseSensitive ); |
| } |
| } |
| |
| |
| /** |
| * Check if a text is present at the current position in a buffer. |
| * |
| * @param chars The buffer which contains the data |
| * @param index Current position in the buffer |
| * @param chars2 The text we want to check |
| * @return <code>true</code> if the buffer contains the text. |
| */ |
| public static int areEquals( char[] chars, int index, char[] chars2 ) |
| { |
| return areEquals( chars, index, chars2, true ); |
| } |
| |
| |
| /** |
| * Check if a text is present at the current position in a buffer. |
| * |
| * @param chars The buffer which contains the data |
| * @param index Current position in the buffer |
| * @param chars2 The text we want to check |
| * @param caseSensitive If the comparison is case-sensitive |
| * @return <code>true</code> if the buffer contains the text. |
| */ |
| public static int areEquals( char[] chars, int index, char[] chars2, boolean caseSensitive ) |
| { |
| if ( ( chars == null ) || ( chars.length == 0 ) || ( chars.length <= index ) || ( index < 0 ) |
| || ( chars2 == null ) || ( chars2.length == 0 ) |
| || ( chars2.length > ( chars.length - index ) ) ) |
| { |
| return StringConstants.NOT_EQUAL; |
| } |
| else |
| { |
| for ( int i = 0; i < chars2.length; i++ ) |
| { |
| char c1 = chars[index++]; |
| char c2 = chars2[i]; |
| |
| if ( !caseSensitive ) |
| { |
| c1 = Character.toLowerCase( c1 ); |
| c2 = Character.toLowerCase( c2 ); |
| } |
| |
| if ( c1 != c2 ) |
| { |
| return StringConstants.NOT_EQUAL; |
| } |
| } |
| |
| return index; |
| } |
| } |
| |
| |
| /** |
| * Check if a text is present at the current position in a buffer. |
| * |
| * @param bytes The buffer which contains the data |
| * @param index Current position in the buffer |
| * @param bytes2 The text we want to check |
| * @return <code>true</code> if the buffer contains the text. |
| */ |
| public static int areEquals( byte[] bytes, int index, byte[] bytes2 ) |
| { |
| if ( ( bytes == null ) || ( bytes.length == 0 ) || ( bytes.length <= index ) || ( index < 0 ) |
| || ( bytes2 == null ) || ( bytes2.length == 0 ) |
| || ( bytes2.length > ( bytes.length - index ) ) ) |
| { |
| return StringConstants.NOT_EQUAL; |
| } |
| else |
| { |
| for ( int i = 0; i < bytes2.length; i++ ) |
| { |
| if ( bytes[index++] != bytes2[i] ) |
| { |
| return StringConstants.NOT_EQUAL; |
| } |
| } |
| |
| return index; |
| } |
| } |
| |
| |
| /** |
| * <p> |
| * Checks if a String is empty ("") or null. |
| * </p> |
| * |
| * <pre> |
| * StringUtils.isEmpty(null) = true |
| * StringUtils.isEmpty("") = true |
| * StringUtils.isEmpty(" ") = false |
| * StringUtils.isEmpty("bob") = false |
| * StringUtils.isEmpty(" bob ") = false |
| * </pre> |
| * |
| * <p> |
| * NOTE: This method changed in Lang version 2.0. It no longer trims the |
| * String. That functionality is available in isBlank(). |
| * </p> |
| * |
| * @param str the String to check, may be null |
| * @return <code>true</code> if the String is empty or null |
| */ |
| public static boolean isEmpty( String str ) |
| { |
| return ( str == null ) || ( str.length() == 0 ); |
| } |
| |
| |
| /** |
| * Checks if a bytes array is empty or null. |
| * |
| * @param bytes The bytes array to check, may be null |
| * @return <code>true</code> if the bytes array is empty or null |
| */ |
| public static boolean isEmpty( byte[] bytes ) |
| { |
| return ( bytes == null ) || ( bytes.length == 0 ); |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from both start and ends of this String, |
| * handling <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start and end characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trim(null) = null |
| * StringUtils.trim("") = "" |
| * StringUtils.trim(" ") = "" |
| * StringUtils.trim("abc") = "abc" |
| * StringUtils.trim(" abc ") = "abc" |
| * </pre> |
| * |
| * @param str the String to be trimmed, may be null |
| * @return the trimmed string, <code>null</code> if null String input |
| */ |
| public static String trim( String str ) |
| { |
| return isEmpty( str ) ? "" : str.trim(); |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from both start and ends of this bytes |
| * array, handling <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start and end characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trim(null) = null |
| * StringUtils.trim("") = "" |
| * StringUtils.trim(" ") = "" |
| * StringUtils.trim("abc") = "abc" |
| * StringUtils.trim(" abc ") = "abc" |
| * </pre> |
| * |
| * @param bytes the byte array to be trimmed, may be null |
| * |
| * @return the trimmed byte array |
| */ |
| public static byte[] trim( byte[] bytes ) |
| { |
| if ( isEmpty( bytes ) ) |
| { |
| return EMPTY_BYTES; |
| } |
| |
| int start = trimLeft( bytes, 0 ); |
| int end = trimRight( bytes, bytes.length - 1 ); |
| |
| int length = end - start + 1; |
| |
| if ( length != 0 ) |
| { |
| byte[] newBytes = new byte[end - start + 1]; |
| |
| System.arraycopy( bytes, start, newBytes, 0, length ); |
| |
| return newBytes; |
| } |
| else |
| { |
| return EMPTY_BYTES; |
| } |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from start of this String, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimLeft(null) = null |
| * StringUtils.trimLeft("") = "" |
| * StringUtils.trimLeft(" ") = "" |
| * StringUtils.trimLeft("abc") = "abc" |
| * StringUtils.trimLeft(" abc ") = "abc " |
| * </pre> |
| * |
| * @param str the String to be trimmed, may be null |
| * @return the trimmed string, <code>null</code> if null String input |
| */ |
| public static String trimLeft( String str ) |
| { |
| if ( isEmpty( str ) ) |
| { |
| return ""; |
| } |
| |
| int start = 0; |
| int end = str.length(); |
| |
| while ( ( start < end ) && ( str.charAt( start ) == ' ' ) ) |
| { |
| start++; |
| } |
| |
| return start == 0 ? str : str.substring( start ); |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from start of this array, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimLeft(null) = null |
| * StringUtils.trimLeft("") = "" |
| * StringUtils.trimLeft(" ") = "" |
| * StringUtils.trimLeft("abc") = "abc" |
| * StringUtils.trimLeft(" abc ") = "abc " |
| * </pre> |
| * |
| * @param chars the chars array to be trimmed, may be null |
| * @param pos The position in the char[] |
| * @return the position of the first char which is not a space, or the last |
| * position of the array. |
| */ |
| public static int trimLeft( char[] chars, int pos ) |
| { |
| if ( chars == null ) |
| { |
| return pos; |
| } |
| |
| while ( ( pos < chars.length ) && ( chars[pos] == ' ' ) ) |
| { |
| pos++; |
| } |
| |
| return pos; |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from a position in this array, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimLeft(null) = null |
| * StringUtils.trimLeft("",...) = "" |
| * StringUtils.trimLeft(" ",...) = "" |
| * StringUtils.trimLeft("abc",...) = "abc" |
| * StringUtils.trimLeft(" abc ",...) = "abc " |
| * </pre> |
| * |
| * @param string the string to be trimmed, may be null |
| * @param pos The position in the String |
| */ |
| public static void trimLeft( String string, Position pos ) |
| { |
| if ( string == null ) |
| { |
| return; |
| } |
| |
| int length = string.length(); |
| |
| while ( ( pos.start < length ) && ( string.charAt( pos.start ) == ' ' ) ) |
| { |
| pos.start++; |
| } |
| |
| pos.end = pos.start; |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from a position in this array, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimLeft(null) = null |
| * StringUtils.trimLeft("",...) = "" |
| * StringUtils.trimLeft(" ",...) = "" |
| * StringUtils.trimLeft("abc",...) = "abc" |
| * StringUtils.trimLeft(" abc ",...) = "abc " |
| * </pre> |
| * |
| * @param bytes the byte array to be trimmed, may be null |
| * @param pos The position in the byte[] |
| */ |
| public static void trimLeft( byte[] bytes, Position pos ) |
| { |
| if ( bytes == null ) |
| { |
| return; |
| } |
| |
| int length = bytes.length; |
| |
| while ( ( pos.start < length ) && ( bytes[pos.start] == ' ' ) ) |
| { |
| pos.start++; |
| } |
| |
| pos.end = pos.start; |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from start of this array, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimLeft(null) = null |
| * StringUtils.trimLeft("") = "" |
| * StringUtils.trimLeft(" ") = "" |
| * StringUtils.trimLeft("abc") = "abc" |
| * StringUtils.trimLeft(" abc ") = "abc " |
| * </pre> |
| * |
| * @param bytes the byte array to be trimmed, may be null |
| * @param pos The position in the byte[] |
| * @return the position of the first byte which is not a space, or the last |
| * position of the array. |
| */ |
| public static int trimLeft( byte[] bytes, int pos ) |
| { |
| if ( bytes == null ) |
| { |
| return pos; |
| } |
| |
| while ( ( pos < bytes.length ) && ( bytes[pos] == ' ' ) ) |
| { |
| pos++; |
| } |
| |
| return pos; |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from end of this String, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimRight(null) = null |
| * StringUtils.trimRight("") = "" |
| * StringUtils.trimRight(" ") = "" |
| * StringUtils.trimRight("abc") = "abc" |
| * StringUtils.trimRight(" abc ") = " abc" |
| * </pre> |
| * |
| * @param str the String to be trimmed, may be null |
| * @return the trimmed string, <code>null</code> if null String input |
| */ |
| public static String trimRight( String str ) |
| { |
| if ( isEmpty( str ) ) |
| { |
| return ""; |
| } |
| |
| int length = str.length(); |
| int end = length; |
| |
| while ( ( end > 0 ) && ( str.charAt( end - 1 ) == ' ' ) ) |
| { |
| if ( ( end > 1 ) && ( str.charAt( end - 2 ) == '\\' ) ) |
| { |
| break; |
| } |
| |
| end--; |
| } |
| |
| return end == length ? str : str.substring( 0, end ); |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from end of this String, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimRight(null) = null |
| * StringUtils.trimRight("") = "" |
| * StringUtils.trimRight(" ") = "" |
| * StringUtils.trimRight("abc") = "abc" |
| * StringUtils.trimRight(" abc ") = " abc" |
| * </pre> |
| * |
| * @param str the String to be trimmed, may be null |
| * @param escapedSpace The last escaped space, if any |
| * @return the trimmed string, <code>null</code> if null String input |
| */ |
| public static String trimRight( String str, int escapedSpace ) |
| { |
| if ( isEmpty( str ) ) |
| { |
| return ""; |
| } |
| |
| int length = str.length(); |
| int end = length; |
| |
| while ( ( end > 0 ) && ( str.charAt( end - 1 ) == ' ' ) && ( end > escapedSpace ) ) |
| { |
| if ( ( end > 1 ) && ( str.charAt( end - 2 ) == '\\' ) ) |
| { |
| break; |
| } |
| |
| end--; |
| } |
| |
| return end == length ? str : str.substring( 0, end ); |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from end of this array, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimRight(null) = null |
| * StringUtils.trimRight("") = "" |
| * StringUtils.trimRight(" ") = "" |
| * StringUtils.trimRight("abc") = "abc" |
| * StringUtils.trimRight(" abc ") = " abc" |
| * </pre> |
| * |
| * @param chars the chars array to be trimmed, may be null |
| * @param pos The position in the char[] |
| * @return the position of the first char which is not a space, or the last |
| * position of the array. |
| */ |
| public static int trimRight( char[] chars, int pos ) |
| { |
| if ( chars == null ) |
| { |
| return pos; |
| } |
| |
| while ( ( pos >= 0 ) && ( chars[pos - 1] == ' ' ) ) |
| { |
| pos--; |
| } |
| |
| return pos; |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from end of this string, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimRight(null) = null |
| * StringUtils.trimRight("") = "" |
| * StringUtils.trimRight(" ") = "" |
| * StringUtils.trimRight("abc") = "abc" |
| * StringUtils.trimRight(" abc ") = " abc" |
| * </pre> |
| * |
| * @param string the string to be trimmed, may be null |
| * @param pos The position in the String |
| * @return the position of the first char which is not a space, or the last |
| * position of the string. |
| */ |
| public static String trimRight( String string, Position pos ) |
| { |
| if ( string == null ) |
| { |
| return ""; |
| } |
| |
| while ( ( pos.end >= 0 ) && ( string.charAt( pos.end - 1 ) == ' ' ) ) |
| { |
| if ( ( pos.end > 1 ) && ( string.charAt( pos.end - 2 ) == '\\' ) ) |
| { |
| break; |
| } |
| |
| pos.end--; |
| } |
| |
| return pos.end == string.length() ? string : string.substring( 0, pos.end ); |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from end of this string, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimRight(null) = null |
| * StringUtils.trimRight("") = "" |
| * StringUtils.trimRight(" ") = "" |
| * StringUtils.trimRight("abc") = "abc" |
| * StringUtils.trimRight(" abc ") = " abc" |
| * </pre> |
| * |
| * @param bytes the byte array to be trimmed, may be null |
| * @param pos The position in the byte[] |
| * @return the position of the first char which is not a space, or the last |
| * position of the byte array. |
| */ |
| public static String trimRight( byte[] bytes, Position pos ) |
| { |
| if ( bytes == null ) |
| { |
| return ""; |
| } |
| |
| while ( ( pos.end >= 0 ) && ( bytes[pos.end - 1] == ' ' ) ) |
| { |
| if ( ( pos.end > 1 ) && ( bytes[pos.end - 2] == '\\' ) ) |
| { |
| break; |
| } |
| |
| pos.end--; |
| } |
| |
| if ( pos.end == bytes.length ) |
| { |
| return utf8ToString( bytes ); |
| } |
| else |
| { |
| return utf8ToString( bytes, pos.end ); |
| } |
| } |
| |
| |
| /** |
| * <p> |
| * Removes spaces (char <= 32) from end of this array, handling |
| * <code>null</code> by returning <code>null</code>. |
| * </p> |
| * Trim removes start characters <= 32. |
| * |
| * <pre> |
| * StringUtils.trimRight(null) = null |
| * StringUtils.trimRight("") = "" |
| * StringUtils.trimRight(" ") = "" |
| * StringUtils.trimRight("abc") = "abc" |
| * StringUtils.trimRight(" abc ") = " abc" |
| * </pre> |
| * |
| * @param bytes the byte array to be trimmed, may be null |
| * @param pos The position in the byte[] |
| * @return the position of the first char which is not a space, or the last |
| * position of the array. |
| */ |
| public static int trimRight( byte[] bytes, int pos ) |
| { |
| if ( bytes == null ) |
| { |
| return pos; |
| } |
| |
| while ( ( pos >= 0 ) && ( bytes[pos] == ' ' ) ) |
| { |
| pos--; |
| } |
| |
| return pos; |
| } |
| |
| |
| /** |
| * Get the character at a given position in a string, checking for limits |
| * |
| * @param string The string which contains the data |
| * @param index Current position in the string |
| * @return The character at the given position, or '\0' if something went wrong |
| */ |
| public static char charAt( String string, int index ) |
| { |
| if ( string == null ) |
| { |
| return '\0'; |
| } |
| |
| int length = string.length(); |
| |
| if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) ) |
| { |
| return '\0'; |
| } |
| else |
| { |
| return string.charAt( index ); |
| } |
| } |
| |
| |
| /** |
| * Get the byte at a given position in a byte array, checking for limits |
| * |
| * @param bytes The byte[] which contains the data |
| * @param index Current position in the byte[] |
| * @return The byte at the given position, or '\0' if something went wrong |
| */ |
| public static byte byteAt( byte[] bytes, int index ) |
| { |
| if ( bytes == null ) |
| { |
| return '\0'; |
| } |
| |
| int length = bytes.length; |
| |
| if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) ) |
| { |
| return '\0'; |
| } |
| else |
| { |
| return bytes[index]; |
| } |
| } |
| |
| |
| /** |
| * Get the char at a given position in a byte array, checking for limits |
| * |
| * @param chars The char[] which contains the data |
| * @param index Current position in the char[] |
| * @return The byte at the given position, or '\0' if something went wrong |
| */ |
| public static char charAt( char[] chars, int index ) |
| { |
| if ( chars == null ) |
| { |
| return '\0'; |
| } |
| |
| int length = chars.length; |
| |
| if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) ) |
| { |
| return '\0'; |
| } |
| else |
| { |
| return chars[index]; |
| } |
| } |
| |
| |
| /** |
| * Transform an array of ASCII bytes to a string. the byte array should contains |
| * only values in [0, 127]. |
| * |
| * @param bytes The byte array to transform |
| * @return The resulting string |
| */ |
| public static String asciiBytesToString( byte[] bytes ) |
| { |
| if ( ( bytes == null ) || ( bytes.length == 0 ) ) |
| { |
| return ""; |
| } |
| |
| char[] result = new char[bytes.length]; |
| |
| for ( int i = 0; i < bytes.length; i++ ) |
| { |
| result[i] = ( char ) bytes[i]; |
| } |
| |
| return new String( result ); |
| } |
| |
| |
| /** |
| * Return UTF-8 encoded byte[] representation of a String |
| * |
| * @param string The string to be transformed to a byte array |
| * @return The transformed byte array |
| */ |
| public static byte[] getBytesUtf8( String string ) |
| { |
| if ( string == null ) |
| { |
| return EMPTY_BYTES; |
| } |
| |
| return string.getBytes( StandardCharsets.UTF_8 ); |
| } |
| |
| |
| /** |
| * When the string to convert to bytes is pure ascii, this is a faster |
| * method than the getBytesUtf8. Otherwise, it's slower. |
| * |
| * @param string The string to convert to byte[] |
| * @return The bytes |
| */ |
| public static byte[] getBytesUtf8Ascii( String string ) |
| { |
| if ( string == null ) |
| { |
| return EMPTY_BYTES; |
| } |
| |
| try |
| { |
| byte[] bytes = new byte[string.length()]; |
| int pos = 0; |
| |
| for ( int i = 0; i < string.length(); i++ ) |
| { |
| bytes[pos++] = UTF8[string.charAt( i )]; |
| } |
| |
| return bytes; |
| } |
| catch ( ArrayIndexOutOfBoundsException aioobe ) |
| { |
| return string.getBytes( StandardCharsets.UTF_8 ); |
| } |
| } |
| |
| |
| /** |
| * Get the default charset |
| * |
| * @return The default charset |
| */ |
| public static String getDefaultCharsetName() |
| { |
| return Charset.defaultCharset().name(); |
| } |
| |
| |
| /** |
| * <p> |
| * Compares two Strings, returning <code>true</code> if they are equal. |
| * </p> |
| * <p> |
| * <code>null</code>s are handled without exceptions. Two |
| * <code>null</code> references are considered to be equal. The comparison |
| * is case sensitive. |
| * </p> |
| * |
| * <pre> |
| * StringUtils.equals(null, null) = true |
| * StringUtils.equals(null, "abc") = false |
| * StringUtils.equals("abc", null) = false |
| * StringUtils.equals("abc", "abc") = true |
| * StringUtils.equals("abc", "ABC") = false |
| * </pre> |
| * |
| * @see String#equals(Object) |
| * @param str1 the first String, may be null |
| * @param str2 the second String, may be null |
| * @return <code>true</code> if the Strings are equal, case sensitive, or |
| * both <code>null</code> |
| */ |
| public static boolean equals( String str1, String str2 ) |
| { |
| return str1 == null ? str2 == null : str1.equals( str2 ); |
| } |
| |
| |
| /** |
| * Utility method that return a String representation of a list |
| * |
| * @param list The list to transform to a string |
| * @return A csv string |
| */ |
| public static String listToString( List<?> list ) |
| { |
| if ( ( list == null ) || list.isEmpty() ) |
| { |
| return ""; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| boolean isFirst = true; |
| |
| for ( Object elem : list ) |
| { |
| if ( isFirst ) |
| { |
| isFirst = false; |
| } |
| else |
| { |
| sb.append( ", " ); |
| } |
| |
| sb.append( elem ); |
| } |
| |
| return sb.toString(); |
| } |
| |
| |
| /** |
| * Utility method that return a String representation of a set |
| * |
| * @param set The set to transform to a string |
| * @return A csv string |
| */ |
| public static String setToString( Set<?> set ) |
| { |
| if ( ( set == null ) || set.isEmpty() ) |
| { |
| return ""; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| boolean isFirst = true; |
| |
| for ( Object elem : set ) |
| { |
| if ( isFirst ) |
| { |
| isFirst = false; |
| } |
| else |
| { |
| sb.append( ", " ); |
| } |
| |
| sb.append( elem ); |
| } |
| |
| return sb.toString(); |
| } |
| |
| |
| /** |
| * Utility method that return a String representation of a list |
| * |
| * @param list The list to transform to a string |
| * @param tabs The tabs to add in front of the elements |
| * @return A csv string |
| */ |
| public static String listToString( List<?> list, String tabs ) |
| { |
| if ( ( list == null ) || list.isEmpty() ) |
| { |
| return ""; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| for ( Object elem : list ) |
| { |
| sb.append( tabs ); |
| sb.append( elem ); |
| sb.append( '\n' ); |
| } |
| |
| return sb.toString(); |
| } |
| |
| |
| /** |
| * Utility method that return a String representation of a map. The elements |
| * will be represented as "key = value" |
| * |
| * @param map The map to transform to a string |
| * @return A csv string |
| */ |
| public static String mapToString( Map<?, ?> map ) |
| { |
| if ( ( map == null ) || ( map.size() == 0 ) ) |
| { |
| return ""; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| boolean isFirst = true; |
| |
| for ( Map.Entry<?, ?> entry : map.entrySet() ) |
| { |
| if ( isFirst ) |
| { |
| isFirst = false; |
| } |
| else |
| { |
| sb.append( ", " ); |
| } |
| |
| sb.append( entry.getKey() ); |
| sb.append( " = '" ).append( entry.getValue() ).append( "'" ); |
| } |
| |
| return sb.toString(); |
| } |
| |
| |
| /** |
| * Utility method that return a String representation of a map. The elements |
| * will be represented as "key = value" |
| * |
| * @param map The map to transform to a string |
| * @param tabs The tabs to add in ffront of the elements |
| * @return A csv string |
| */ |
| public static String mapToString( Map<?, ?> map, String tabs ) |
| { |
| if ( ( map == null ) || ( map.size() == 0 ) ) |
| { |
| return ""; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| for ( Map.Entry<?, ?> entry : map.entrySet() ) |
| { |
| sb.append( tabs ); |
| sb.append( entry.getKey() ); |
| |
| sb.append( " = '" ).append( entry.getValue().toString() ).append( "'\n" ); |
| } |
| |
| return sb.toString(); |
| } |
| |
| |
| /** |
| * Rewrote the toLowercase method to improve performances. |
| * In Ldap, attributesType are supposed to use ASCII chars : |
| * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. |
| * <br> |
| * Deprecated : Use {@link #toLowerCaseAscii(String)} |
| * |
| * @param value The String to lowercase |
| * @return The lowercase string |
| * @deprecated Use {@link #toLowerCaseAscii(String)} |
| */ |
| @Deprecated |
| public static String toLowerCase( String value ) |
| { |
| if ( ( null == value ) || ( value.length() == 0 ) ) |
| { |
| return ""; |
| } |
| |
| char[] chars = value.toCharArray(); |
| |
| for ( int i = 0; i < chars.length; i++ ) |
| { |
| chars[i] = TO_LOWER_CASE[chars[i]]; |
| } |
| |
| return new String( chars ); |
| } |
| |
| |
| /** |
| * Rewrote the toLowercase method to improve performances. |
| * In Ldap, attributesType are supposed to use ASCII chars : |
| * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. |
| * |
| * @param value The String to lowercase |
| * @return The lowercase string |
| */ |
| public static String toLowerCaseAscii( String value ) |
| { |
| if ( ( null == value ) || ( value.length() == 0 ) ) |
| { |
| return ""; |
| } |
| |
| char[] chars = value.toCharArray(); |
| |
| for ( int i = 0; i < chars.length; i++ ) |
| { |
| chars[i] = TO_LOWER_CASE[chars[i]]; |
| } |
| |
| return new String( chars ); |
| } |
| |
| |
| /** |
| * Rewrote the toLowercase method to improve performances. |
| * In Ldap, attributesType are supposed to use ASCII chars : |
| * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. |
| * |
| * @param value The byte[] to lowercase |
| * @return The lowercase string |
| */ |
| public static String toLowerCase( byte[] value ) |
| { |
| if ( ( null == value ) || ( value.length == 0 ) ) |
| { |
| return ""; |
| } |
| |
| for ( int i = 0; i < value.length; i++ ) |
| { |
| value[i] = TO_LOWER_CASE_BYTE[value[i]]; |
| } |
| |
| return Strings.utf8ToString( value ); |
| } |
| |
| |
| /** |
| * Rewrote the toUppercase method to improve performances. |
| * In Ldap, attributesType are supposed to use ASCII chars : |
| * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. We also add the '_' char |
| * <br> |
| * Deprecated Use {@link #toUpperCaseAscii(String)} |
| * @param value The String to uppercase |
| * @return The uppercase string |
| * @deprecated Use {@link #toUpperCaseAscii(String)} |
| */ |
| @Deprecated |
| public static String toUpperCase( String value ) |
| { |
| if ( ( null == value ) || ( value.length() == 0 ) ) |
| { |
| return ""; |
| } |
| |
| char[] chars = value.toCharArray(); |
| |
| for ( int i = 0; i < chars.length; i++ ) |
| { |
| chars[i] = UPPER_CASE[chars[i]]; |
| } |
| |
| return new String( chars ); |
| } |
| |
| |
| /** |
| * Rewrote the toLowercase method to improve performances. |
| * In Ldap, attributesType are supposed to use ASCII chars : |
| * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. |
| * |
| * @param value The String to uppercase |
| * @return The uppercase string |
| */ |
| public static String toUpperCaseAscii( String value ) |
| { |
| if ( ( null == value ) || ( value.length() == 0 ) ) |
| { |
| return ""; |
| } |
| |
| char[] chars = value.toCharArray(); |
| |
| for ( int i = 0; i < chars.length; i++ ) |
| { |
| chars[i] = UPPER_CASE[chars[i]]; |
| } |
| |
| return new String( chars ); |
| } |
| |
| |
| /** |
| * <p> |
| * Converts a String to upper case as per {@link String#toUpperCase( Locale )}. |
| * </p> |
| * <p> |
| * A <code>null</code> input String returns <code>null</code>. |
| * </p> |
| * |
| * <pre> |
| * StringUtils.upperCase(null) = null |
| * StringUtils.upperCase("") = "" |
| * StringUtils.upperCase("aBc") = "ABC" |
| * </pre> |
| * |
| * @param str the String to upper case, may be null |
| * @return the upper cased String, <code>null</code> if null String input |
| */ |
| public static String upperCase( String str ) |
| { |
| if ( str == null ) |
| { |
| return null; |
| } |
| |
| return str.toUpperCase( Locale.ROOT ); |
| } |
| |
| |
| /** |
| * <p> |
| * Converts a String to lower case as per {@link String#toLowerCase()}. |
| * </p> |
| * <p> |
| * A <code>null</code> input String returns <code>null</code>. |
| * </p> |
| * |
| * <pre> |
| * StringUtils.lowerCase(null) = null |
| * StringUtils.lowerCase("") = "" |
| * StringUtils.lowerCase("aBc") = "abc" |
| * </pre> |
| * |
| * @param str the String to lower case, may be null |
| * @return the lower cased String, <code>null</code> if null String input |
| */ |
| public static String lowerCase( String str ) |
| { |
| if ( str == null ) |
| { |
| return null; |
| } |
| |
| return str.toLowerCase( Locale.ROOT ); |
| } |
| |
| |
| /** |
| * Rewrote the toLowercase method to improve performances. |
| * In Ldap, attributesType are supposed to use ASCII chars : |
| * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. We will take |
| * care of any other chars either. |
| * |
| * @param str The String to lowercase |
| * @return The lowercase string |
| */ |
| public static String lowerCaseAscii( String str ) |
| { |
| if ( str == null ) |
| { |
| return null; |
| } |
| |
| char[] chars = str.toCharArray(); |
| int pos = 0; |
| |
| for ( char c : chars ) |
| { |
| chars[pos++] = TO_LOWER_CASE[c]; |
| } |
| |
| return new String( chars ); |
| } |
| |
| |
| /** |
| * |
| * Check that a String is a valid PrintableString. A PrintableString contains only |
| * the following set of chars : |
| * { ' ', ''', '(', ')', '+', '-', '.', '/', [0-9], ':', '=', '?', [A-Z], [a-z]} |
| * |
| * @param str The String to check |
| * @return <code>true</code> if the string is a PrintableString or is empty, |
| * <code>false</code> otherwise |
| */ |
| public static boolean isPrintableString( String str ) |
| { |
| if ( ( str == null ) || ( str.length() == 0 ) ) |
| { |
| return true; |
| } |
| |
| for ( char c : str.toCharArray() ) |
| { |
| if ( ( c > 127 ) || !IS_PRINTABLE_CHAR[c] ) |
| { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| |
| /** |
| * <p> |
| * Checks if a String is not empty ("") and not null. |
| * </p> |
| * |
| * <pre> |
| * StringUtils.isNotEmpty(null) = false |
| * StringUtils.isNotEmpty("") = false |
| * StringUtils.isNotEmpty(" ") = true |
| * StringUtils.isNotEmpty("bob") = true |
| * StringUtils.isNotEmpty(" bob ") = true |
| * </pre> |
| * |
| * @param str the String to check, may be null |
| * @return <code>true</code> if the String is not empty and not null |
| */ |
| public static boolean isNotEmpty( String str ) |
| { |
| return ( str != null ) && ( str.length() > 0 ); |
| } |
| |
| |
| /** |
| * |
| * Check that a String is a valid IA5String. An IA5String contains only |
| * char which values is between [0, 7F] |
| * |
| * @param str The String to check |
| * @return <code>true</code> if the string is an IA5String or is empty, |
| * <code>false</code> otherwise |
| */ |
| public static boolean isIA5String( String str ) |
| { |
| if ( ( str == null ) || ( str.length() == 0 ) ) |
| { |
| return true; |
| } |
| |
| // All the chars must be in [0x00, 0x7F] |
| for ( char c : str.toCharArray() ) |
| { |
| if ( ( c < 0 ) || ( c > 0x7F ) ) |
| { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| |
| /** |
| * Checks to see if a String is a valid UUID. |
| * |
| * @param uuid the UUID to check for validity |
| * @return true if the UUID is valid, false otherwise |
| */ |
| public static boolean isValidUuid( String uuid ) |
| { |
| if ( uuid.length() < 36 ) |
| { |
| return false; |
| } |
| |
| if ( isHex( uuid.charAt( 0 ) ) && isHex( uuid.charAt( 1 ) ) && isHex( uuid.charAt( 2 ) ) |
| && isHex( uuid.charAt( 3 ) ) && isHex( uuid.charAt( 4 ) ) && isHex( uuid.charAt( 5 ) ) |
| && isHex( uuid.charAt( 6 ) ) && isHex( uuid.charAt( 7 ) ) && ( uuid.charAt( 8 ) == '-' ) |
| && isHex( uuid.charAt( 9 ) ) && isHex( uuid.charAt( 10 ) ) && isHex( uuid.charAt( 11 ) ) |
| && isHex( uuid.charAt( 12 ) ) && ( uuid.charAt( 13 ) == '-' ) && isHex( uuid.charAt( 14 ) ) |
| && isHex( uuid.charAt( 15 ) ) && isHex( uuid.charAt( 16 ) ) && isHex( uuid.charAt( 17 ) ) |
| && ( uuid.charAt( 18 ) == '-' ) && isHex( uuid.charAt( 19 ) ) && isHex( uuid.charAt( 20 ) ) |
| && isHex( uuid.charAt( 21 ) ) && isHex( uuid.charAt( 22 ) ) && ( uuid.charAt( 23 ) == '-' ) |
| && isHex( uuid.charAt( 24 ) ) && isHex( uuid.charAt( 25 ) ) && isHex( uuid.charAt( 26 ) ) |
| && isHex( uuid.charAt( 27 ) ) && isHex( uuid.charAt( 28 ) ) && isHex( uuid.charAt( 29 ) ) |
| && isHex( uuid.charAt( 30 ) ) && isHex( uuid.charAt( 31 ) ) && isHex( uuid.charAt( 32 ) ) |
| && isHex( uuid.charAt( 33 ) ) && isHex( uuid.charAt( 34 ) ) && isHex( uuid.charAt( 35 ) ) ) |
| { |
| // There is not that much more we can check. |
| if ( LOG.isDebugEnabled() ) |
| { |
| LOG.debug( I18n.msg( I18n.MSG_17007_SYNTAX_VALID, uuid ) ); |
| } |
| |
| return true; |
| } |
| |
| if ( LOG.isDebugEnabled() ) |
| { |
| LOG.debug( I18n.msg( I18n.MSG_17008_SYNTAX_INVALID, uuid ) ); |
| } |
| |
| return false; |
| } |
| |
| |
| /** |
| * converts the bytes of a UUID to string |
| * |
| * @param bytes bytes of a UUID |
| * @return UUID in string format |
| */ |
| public static String uuidToString( byte[] bytes ) |
| { |
| if ( ( bytes == null ) || ( bytes.length != 16 ) ) |
| { |
| return "Invalid UUID"; |
| } |
| |
| char[] hex = encodeHex( bytes ); |
| StringBuilder sb = new StringBuilder(); |
| sb.append( hex, 0, 8 ); |
| sb.append( '-' ); |
| sb.append( hex, 8, 4 ); |
| sb.append( '-' ); |
| sb.append( hex, 12, 4 ); |
| sb.append( '-' ); |
| sb.append( hex, 16, 4 ); |
| sb.append( '-' ); |
| sb.append( hex, 20, 12 ); |
| |
| return Strings.toLowerCaseAscii( sb.toString() ); |
| } |
| |
| |
| /** |
| * converts the string representation of an UUID to bytes |
| * |
| * @param string the string representation of an UUID |
| * @return the bytes, null if the the syntax is not valid |
| */ |
| public static byte[] uuidToBytes( String string ) |
| { |
| if ( !isValidUuid( string ) ) |
| { |
| return null; |
| } |
| |
| char[] chars = string.toCharArray(); |
| byte[] bytes = new byte[16]; |
| bytes[0] = getHexValue( chars[0], chars[1] ); |
| bytes[1] = getHexValue( chars[2], chars[3] ); |
| bytes[2] = getHexValue( chars[4], chars[5] ); |
| bytes[3] = getHexValue( chars[6], chars[7] ); |
| |
| bytes[4] = getHexValue( chars[9], chars[10] ); |
| bytes[5] = getHexValue( chars[11], chars[12] ); |
| |
| bytes[6] = getHexValue( chars[14], chars[15] ); |
| bytes[7] = getHexValue( chars[16], chars[17] ); |
| |
| bytes[8] = getHexValue( chars[19], chars[20] ); |
| bytes[9] = getHexValue( chars[21], chars[22] ); |
| |
| bytes[10] = getHexValue( chars[24], chars[25] ); |
| bytes[11] = getHexValue( chars[26], chars[27] ); |
| bytes[12] = getHexValue( chars[28], chars[29] ); |
| bytes[13] = getHexValue( chars[30], chars[31] ); |
| bytes[14] = getHexValue( chars[32], chars[33] ); |
| bytes[15] = getHexValue( chars[34], chars[35] ); |
| |
| return bytes; |
| } |
| |
| |
| /** |
| * Copy a byte array into a new byte array |
| * |
| * @param value the byte array to copy |
| * @return The copied byte array |
| */ |
| public static byte[] copy( byte[] value ) |
| { |
| if ( isEmpty( value ) ) |
| { |
| return EMPTY_BYTES; |
| } |
| |
| byte[] copy = new byte[value.length]; |
| System.arraycopy( value, 0, copy, 0, value.length ); |
| |
| return copy; |
| } |
| |
| |
| /** |
| * From commons-httpclients. Converts the byte array of HTTP content |
| * characters to a string. If the specified charset is not supported, |
| * default system encoding is used. |
| * |
| * @param data the byte array to be encoded |
| * @param offset the index of the first byte to encode |
| * @param length the number of bytes to encode |
| * @param charset the desired character encoding |
| * @return The result of the conversion. |
| * @since 3.0 |
| */ |
| public static String getString( final byte[] data, int offset, int length, String charset ) |
| { |
| if ( data == null ) |
| { |
| throw new IllegalArgumentException( I18n.err( I18n.ERR_17028_PARAMETER_CANT_BE_NULL ) ); |
| } |
| |
| if ( ( charset == null ) || ( charset.length() == 0 ) ) |
| { |
| throw new IllegalArgumentException( I18n.err( I18n.ERR_17029_CHARSET_CANT_BE_NULL ) ); |
| } |
| |
| try |
| { |
| return new String( data, offset, length, charset ); |
| } |
| catch ( UnsupportedEncodingException e ) |
| { |
| return new String( data, offset, length, Charset.defaultCharset() ); |
| } |
| } |
| |
| |
| /** |
| * From commons-httpclients. Converts the byte array of HTTP content |
| * characters to a string. If the specified charset is not supported, |
| * default system encoding is used. |
| * |
| * @param data the byte array to be encoded |
| * @param offset the index of the first byte to encode |
| * @param length the number of bytes to encode |
| * @param charset the desired character encoding |
| * @return The result of the conversion. |
| * @since 3.0 |
| */ |
| public static String getString( final byte[] data, int offset, int length, Charset charset ) |
| { |
| if ( data == null ) |
| { |
| throw new IllegalArgumentException( I18n.err( I18n.ERR_17028_PARAMETER_CANT_BE_NULL ) ); |
| } |
| |
| if ( charset == null ) |
| { |
| throw new IllegalArgumentException( I18n.err( I18n.ERR_17029_CHARSET_CANT_BE_NULL ) ); |
| } |
| |
| return new String( data, offset, length, charset ); |
| } |
| |
| |
| /** |
| * From commons-httpclients. Converts the byte array of HTTP content |
| * characters to a string. If the specified charset is not supported, |
| * default system encoding is used. |
| * |
| * @param data the byte array to be encoded |
| * @param charset the desired character encoding |
| * @return The result of the conversion. |
| * @since 3.0 |
| */ |
| public static String getString( final byte[] data, String charset ) |
| { |
| return getString( data, 0, data.length, charset ); |
| } |
| |
| |
| /** |
| * From commons-httpclients. Converts the byte array of HTTP content |
| * characters to a string. If the specified charset is not supported, |
| * default system encoding is used. |
| * |
| * @param data the byte array to be encoded |
| * @param charset the desired character encoding |
| * @return The result of the conversion. |
| * @since 3.0 |
| */ |
| public static String getString( final byte[] data, Charset charset ) |
| { |
| return getString( data, 0, data.length, charset ); |
| } |
| |
| |
| /** |
| * Create a new UUID using a long as the least significant bits |
| * |
| * @param value The least significant bits. |
| * @return The created UUID |
| */ |
| public static String getUUID( long value ) |
| { |
| return new UUID( 0, value ).toString(); |
| } |
| |
| |
| /** |
| * Past an ASCII String to a number |
| * |
| * @param value The string to parse |
| * @return the parsed value. |
| */ |
| public static int parseInt( String value ) |
| { |
| long res = 0; |
| |
| for ( char c : value.toCharArray() ) |
| { |
| if ( ( c >= '0' ) && ( c <= '9' ) ) |
| { |
| res = res * 10 + ( c - '0' ); |
| |
| if ( res > Integer.MAX_VALUE ) |
| { |
| throw new NumberFormatException( I18n.err( I18n.ERR_17002_INTEGER_TOO_BIG, value ) ); |
| } |
| } |
| else |
| { |
| throw new NumberFormatException( I18n.err( I18n.ERR_17003_INTEGER_INVALID, value ) ); |
| } |
| } |
| |
| return ( int ) res; |
| } |
| |
| |
| /** |
| * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) |
| * @param b1 The first byte[] to compare |
| * @param b2 The second byte[] to compare |
| * @return -1 if the first byte[] is inferior to the second one, 1 if teh first byte[] |
| * is superior to the second one, 0 if they are equal. |
| */ |
| public static int compare( byte[] b1, byte[] b2 ) |
| { |
| if ( LOG.isDebugEnabled() ) |
| { |
| LOG.debug( I18n.msg( I18n.MSG_17006_COMPARING_OBJECTSTRING, |
| Strings.dumpBytes( b1 ), Strings.dumpBytes( b2 ) ) ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // Handle some basis cases |
| // ------------------------------------------------------------------- |
| |
| if ( b1 == null ) |
| { |
| return ( b2 == null ) ? 0 : -1; |
| } |
| |
| if ( b2 == null ) |
| { |
| return 1; |
| } |
| |
| if ( b1.length == b2.length ) |
| { |
| for ( int i = 0; i < b1.length; i++ ) |
| { |
| if ( b1[i] > b2[i] ) |
| { |
| return 1; |
| } |
| else if ( b1[i] < b2[i] ) |
| { |
| return -1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| int minLength = Math.min( b1.length, b2.length ); |
| |
| for ( int i = 0; i < minLength; i++ ) |
| { |
| if ( b1[i] > b2[i] ) |
| { |
| return 1; |
| } |
| else if ( b1[i] < b2[i] ) |
| { |
| return -1; |
| } |
| } |
| |
| // b2 is longer w/ b1 as prefix |
| if ( b1.length == minLength ) |
| { |
| return -1; |
| } |
| |
| // b1 is longer w/ b2 as prefix |
| if ( b2.length == minLength ) |
| { |
| return 1; |
| } |
| |
| return 0; |
| } |
| } |