/*
 * Copyright (c) 2014-2021 by Wen Yu
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License, v. 2.0 are satisfied: GNU General Public License, version 2
 * or any later version.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
 *
 * Change History - most recent changes go on top of previous changes
 *
 * StringUtils.java
 *
 * Who   Date       Description
 * ====  =========  ==============================================================
 * WY    03May2015  Added rationalToString()
 * WY    04Mar2015  Added toHexString()
 * WY    04Mar2015  Added generateMD5()
 * WY    07Feb201   Added decimalToDMS() and DMSToDecimal()
 * WY    23Jan2015  Moved XML related methods to XMLUtils
 * WY    10Jan2015  Added showXML() and printNode() to show XML document
 * WY    28Dec2014  Added isInCharset() to test if a String can be encoded with
 * 					certain character set.
 */

package pixy.string;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.regex.*;

/**
 * String utility class  
 *
 * @author Wen Yu, yuwen_66@yahoo.com
 * @version 1.0 09/18/2012
 */
public class StringUtils {
	
	private static final char[] HEXES = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
	
	/**
	 * Formats byte array.
	 * 
	 * @param bytes an array of byte.
	 * @return a hex string representation of the byte array.
	 */
	public static String byteArrayToHexString(byte[] bytes) {	    
	    return byteArrayToHexString(bytes, 0, bytes.length);
	}
	
	public static String byteArrayToHexString(byte[] bytes, int offset, int length) {		
		if ( bytes == null )
			return null;
		
		if(bytes.length == 0) return "[]";
	    
	    if(offset < 0 || offset >= bytes.length)
	    	throw new IllegalArgumentException("Offset out of array bound!");
	    
	    int endOffset = offset + Math.min(length, bytes.length);
		 
	    if(endOffset > bytes.length)
	    	length = bytes.length - offset;
	    
	    StringBuilder hex = new StringBuilder(5*length + 2);	    
	    hex.append("[");
	    
	    for (int i = offset; i < endOffset; i++) {
	    	hex.append("0x").append(HEXES[(bytes[i] & 0xf0) >> 4])
	         .append(HEXES[bytes[i] & 0x0f]).append(",");
	    }
	    
	    // Remove the last ","
	    if(hex.length() > 1)
	    	hex.deleteCharAt(hex.length()-1);
	    
	    if(endOffset < bytes.length)
	    	hex.append(" ..."); // Partial output
	    
	    hex.append("]");
	    
	    return hex.toString();
	}
	
	public static String byteToHexString(byte b) {
	    return String.format("0x%02X ", b);
	}
	
	/**
	 * Capitalizes the first character of the words in a string.
	 * 
	 * @param s the input string
	 * @return a string with the first character of all words capitalized
	 */
	public static String capitalize(String s) {   
		StringBuffer myStringBuffer = new StringBuffer();
		Pattern p = Pattern.compile("\\b(\\w)(\\w*)");
		Matcher m = p.matcher(s);
		
        while (m.find()) {
			if(!Character.isUpperCase(m.group().charAt(0)))
               m.appendReplacement(myStringBuffer, m.group(1).toUpperCase()+"$2");
        }
        
        return m.appendTail(myStringBuffer).toString();
	}
	
	public static String capitalizeFully(String s) {   
		return capitalize(s.toLowerCase());
	}
	
	public static String concat(Iterable<? extends CharSequence> strings, String delimiter) {
        int capacity = 0;
        int delimLength = delimiter.length();

        Iterator<? extends CharSequence> iter = strings.iterator();
        
        while (iter.hasNext()) {
        	CharSequence next = iter.next();
        	
        	if(!isNullOrEmpty(next))
        		capacity += next.length() + delimLength;
        }

        StringBuilder buffer = new StringBuilder(capacity);
        iter = strings.iterator();
        
        while (iter.hasNext()) {
            CharSequence next = iter.next();
            
            if(!isNullOrEmpty(next)) {
            	buffer.append(next);
            	buffer.append(delimiter);
            }
        }
        
        int lastIndexOfDelimiter = buffer.lastIndexOf(delimiter);
        buffer.delete(lastIndexOfDelimiter, buffer.length());
        
        return buffer.toString();
    }
	
	public static String concat(String first, String second) {
		if(first == null) return second;
		if(second == null) return first;
		
		StringBuilder sb = new StringBuilder(first.length() + second.length());
		sb.append(first);
		sb.append(second);
		
		return sb.toString();
	}
	
	public static String concat(String first, String... strings) {
		StringBuilder sb;
		
		if(first != null) sb = new StringBuilder(first);
		else sb = new StringBuilder();
		
		for (String s: strings) {		
			if(!isNullOrEmpty(s))
				sb.append(s);
	 	}
		
		return sb.toString();
	}
		
	public static <T extends CharSequence> String concat(T[] strings, String delimiter) {
        int capacity = 0;
        int delimLength = delimiter.length();
        
        for (T value : strings) {
        	if(!isNullOrEmpty(value))
        		capacity += value.length() + delimLength;
        }
        
        StringBuilder buffer = new StringBuilder(capacity);
              
        for (T value : strings) {
        	if(!isNullOrEmpty(value)) {
        		buffer.append(value);
            	buffer.append(delimiter);
        	}
        }
        
        int lastIndexOfDelimiter = buffer.lastIndexOf(delimiter);
        buffer.delete(lastIndexOfDelimiter, buffer.length());
        
        return buffer.toString();
    }
	
	/**
	 * Regular expression version of the String contains method.
	 * If used with a match from start or match from end regular expression,
	 * it becomes the regular expression version of the {@link String#
	 * startsWith(String prefix)} or {@link String#endsWith(String suffix)}
	 * methods.
	 * 
	 * @param input the input string
	 * @param regex the regular expression to which this string is to be matched
	 * @return true if a match is found, otherwise false
	 */
	public static boolean contains(String input, String regex) {
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(input);
        
		if (m.find()) {
			return true;
        }
		
		return false;
	}
	
	// From http://stackoverflow.com/questions/15547329/how-to-prettily-format-gps-data-in-java-android
	// Input a double latitude or longitude in the decimal format
	public static String decimalToDMS(double coord) {
		String output;
		int degrees, minutes, seconds;
	    // gets the modulus the coordinate divided by one (MOD1).
	    // in other words gets all the numbers after the decimal point.
	    // e.g. mod = 87.728056 % 1 == 0.728056
	    //
	    // next get the integer part of the coord. In other words the, whole number part.
	    // e.g. intPart = 87
	    double mod = coord % 1;
	    degrees = (int)coord;
	    // next times the MOD1 of degrees by 60 so we can find the integer part for minutes.
	    // get the MOD1 of the new coord to find the numbers after the decimal point.
	    // e.g. coord = 0.728056 * 60 == 43.68336
	    //      mod = 43.68336 % 1 == 0.68336
	    //
	    // next get the value of the integer part of the coord.
	    // e.g. intPart = 43
	    coord = mod * 60;
	    mod = coord % 1;
	    minutes = (int)coord;
	    //do the same again for minutes
	    //e.g. coord = 0.68336 * 60 == 41.0016
	    //e.g. intPart = 41
	    coord = mod * 60;
	    seconds = (int)coord;
	    //Standard output of D°M'S"
	    output = degrees + '\u00B0' + minutes + "'" + seconds + "\"";

	    return output;
	}

	/**
	 * Converts DMS to decimal 
	 *
	 * Input: latitude or longitude in the DMS format ( example: N 43° 36' 15.894")
	 * @param hemisphereOUmeridien => {W,E,S,N}
	 * @return latitude or longitude in decimal format
	 */
	public double DMSToDecimal(String hemisphereOUmeridien, double degrees, double minutes, double seconds) {
		double LatOrLon = 0;
		double sign = 1.0;

		if((hemisphereOUmeridien == "W")||(hemisphereOUmeridien == "S")) {
			sign = -1.0;
		}              
		
		LatOrLon = sign*(Math.floor(degrees) + Math.floor(minutes)/60.0 + seconds/3600.0);

		return LatOrLon;               
    }
	
	/**
	 * From www.javapractices.com EscapeChars.java
	 * 
	 * @param url URL string to be encoded
	 * @return a encoded URL string
	 */	
	public static String encodeURL(String url) {
		String result = null;
	    
		try {
	       result = URLEncoder.encode(url, "UTF-8");
	    }
	    catch (UnsupportedEncodingException ex){
	       throw new RuntimeException("UTF-8 not supported", ex);
	    }
	    
		return result;
	}
		
	/**
	 * Escapes HTML reserved characters and other characters which might cause Cross Site Scripting
	 * (XSS) hacks
	 *
	 * The following table comes from www.javapractice.com EscapeChars.java
	 * 
	 * <P>The following characters are replaced with corresponding HTML character entities:
	 * 
     * <table border='1' cellpadding='3' cellspacing='0'>
     *  <tr><th> Character </th><th>Replacement</th></tr>
     *  <tr><td> < </td><td> &lt; </td></tr>
     *  <tr><td> > </td><td> &gt; </td></tr>
     *  <tr><td> & </td><td> &amp; </td></tr>
     *  <tr><td> " </td><td> &quot;</td></tr>
     *  <tr><td> \t </td><td> &#009;</td></tr>
     *  <tr><td> ! </td><td> &#033;</td></tr>
     *  <tr><td> # </td><td> &#035;</td></tr>
     *  <tr><td> $ </td><td> &#036;</td></tr>
     *  <tr><td> % </td><td> &#037;</td></tr>
     *  <tr><td> ' </td><td> &#039;</td></tr>
     *  <tr><td> ( </td><td> &#040;</td></tr> 
     *  <tr><td> ) </td><td> &#041;</td></tr>
     *  <tr><td> * </td><td> &#042;</td></tr>
     *  <tr><td> + </td><td> &#043; </td></tr>
     *  <tr><td> , </td><td> &#044; </td></tr>
     *  <tr><td> - </td><td> &#045; </td></tr>
     *  <tr><td> . </td><td> &#046; </td></tr>
     *  <tr><td> / </td><td> &#047; </td></tr>
     *  <tr><td> : </td><td> &#058;</td></tr>
     *  <tr><td> ; </td><td> &#059;</td></tr>
     *  <tr><td> = </td><td> &#061;</td></tr>
     *  <tr><td> ? </td><td> &#063;</td></tr>
     *  <tr><td> @ </td><td> &#064;</td></tr>
     *  <tr><td> [ </td><td> &#091;</td></tr>
     *  <tr><td> \ </td><td> &#092;</td></tr>
     *  <tr><td> ] </td><td> &#093;</td></tr>
     *  <tr><td> ^ </td><td> &#094;</td></tr>
     *  <tr><td> _ </td><td> &#095;</td></tr>
     *  <tr><td> ` </td><td> &#096;</td></tr>
     *  <tr><td> { </td><td> &#123;</td></tr>
     *  <tr><td> | </td><td> &#124;</td></tr>
     *  <tr><td> } </td><td> &#125;</td></tr>
     *  <tr><td> ~ </td><td> &#126;</td></tr>
     * </table>
     *
	 * @return a string with the specified characters replaced by HTML entities
	 */
	public static String escapeHTML(String input) {
		Iterator<Character> itr = stringIterator(input);
		StringBuilder result = new StringBuilder();		
		
		while (itr.hasNext())
		{
			Character c = itr.next();
			
			switch (c)
			{				
				case '<':
					result.append("&lt;");
					break;
				case '>':
					result.append("&gt;");
					break;
				case '&':
					result.append("&amp;");
					break;
				case '"':
					result.append("&quot;");
					break;
				case '\t':
					result.append("&#009;");
					break;
				case '!':
					result.append("&#033;");
					break;
				case '#':
					result.append("&#035;");
					break;
				case '$':
					result.append("&#036;");
					break;
				case '%':
					result.append("&#037;");
					break;
				case '\'':
					result.append("&#039;");
					break;
				case '(':
					result.append("&#040;");
					break;
				case ')':
					result.append("&#041;");
					break;
				case '*':
					result.append("&#042;");
					break;
				case '+':
					result.append("&#043;");
					break;
				case ',':
					result.append("&#044;");
					break;
				case '-':
					result.append("&#045;");
					break;
				case '.':
					result.append("&#046;");
					break;
				case '/':
					result.append("&#047;");
					break;
				case ':':
					result.append("&#058;");
					break;
				case ';':
					result.append("&#059;");
					break;
				case '=':
					result.append("&#061;");
					break;
				case '?':
					result.append("&#063;");
					break;
				case '@':
					result.append("&#064;");
					break;
				case '[':
					result.append("&#091;");
					break;
				case '\\':
					result.append("&#092;");
					break;
				case ']':
					result.append("&#093;");
					break;
				case '^':
					result.append("&#094;");
					break;
				case '_':
					result.append("&#095;");
					break;
				case '`':
					result.append("&#096;");
					break;
				case '{':
					result.append("&#123;");
					break;
				case '|':
					result.append("&#124;");
					break;
				case '}':
					result.append("&#125;");
					break;
				case '~':
					result.append("&#126;");
					break;
				default:
					result.append(c);
			}
		}
		
		return result.toString();
	}
	
	/**
	 * Replaces "&" with its entity "&amp;" to make it a valid HTML link
	 * 
	 * @param queryString a URL string with a query string attached
	 * @return a valid URL string to be used as a link
	 */
	public static String escapeQueryStringAmp(String queryString) {
		return queryString.replace("&", "&amp;");
	}
	
	public static String escapeRegex(String input) {
		Iterator<Character> itr = stringIterator(input);
		StringBuilder result = new StringBuilder();		
		
		while (itr.hasNext())
		{
			Character c = itr.next();
			
			switch (c)
			{
				case '.':
				case '^':
				case '$':
				case '*':
				case '+':
				case '?':
				case '(':
				case ')':
				case '[':
				case '{':
					result.append("\\").append(c);
					break;
				case '\\':
					result.append("\\\\");
				    break;
				default:
					result.append(c);
			}
		}
		
		return result.toString();
	}
	
	/**
	 * Generate MD5 digest from a byte array
	 * 
	 * @param message byte array to generate MD5
	 * @return MD5 string
	 */
	public static String generateMD5(byte[] message) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("No such algorithm: MD5");
		}
		
		return toHexString(md.digest(message));
    }
   
	public static String intToHexString(int value) {
		StringBuilder buffer = new StringBuilder(10);
		
		buffer.append("0x");		
		
		buffer.append(HEXES[(value & 0x0000000F)]);
		buffer.append(HEXES[(value & 0x000000F0) >>> 4]);
		buffer.append(HEXES[(value & 0x00000F00) >>> 8]);
		buffer.append(HEXES[(value & 0x0000F000) >>> 12]);
		buffer.append(HEXES[(value & 0x000F0000) >>> 16]);
		buffer.append(HEXES[(value & 0x00F00000) >>> 20]);
		buffer.append(HEXES[(value & 0x0F000000) >>> 24]);
		buffer.append(HEXES[(value & 0xF0000000) >>> 28]);
		
		return buffer.toString();
	}

	public static String intToHexStringMM(int value) {
		
		StringBuilder buffer = new StringBuilder(10);
		
		buffer.append("0x");
		
		buffer.append(HEXES[(value & 0xF0000000) >>> 28]);
		buffer.append(HEXES[(value & 0x0F000000) >>> 24]);
		buffer.append(HEXES[(value & 0x00F00000) >>> 20]);
		buffer.append(HEXES[(value & 0x000F0000) >>> 16]);
		buffer.append(HEXES[(value & 0x0000F000) >>> 12]);
		buffer.append(HEXES[(value & 0x00000F00) >>> 8]);
		buffer.append(HEXES[(value & 0x000000F0) >>> 4]);
		buffer.append(HEXES[(value & 0x0000000F)]);
		
		return buffer.toString();
	}
	
	public static boolean isInCharset(String input, String encoding) {
		Charset charset = null;
		try {
			// May throw different unchecked exceptions
			charset = Charset.forName(encoding);
		} catch(Exception ex) {
			ex.printStackTrace();
			return false;
		}
	    // Convert input into byte array and encode it again using the
	    // same character set and see if we get the same string
	    String output = new String(input.getBytes(charset), charset);
	    
	    return output.equals(input);
	}
	
	/**
	 * Checks if a string is null, empty, or consists only of white spaces
	 * 
	 * @param str the input CharSequence to check
	 * @return true if the input string is null, empty, or contains only white
	 * spaces, otherwise false
	 */
	public static boolean isNullOrEmpty(CharSequence str) {
		return ((str == null) || (str.length() == 0));
	}
	
	/**
	 * Formats TIFF long data field.
	 * 
	 * @param data an array of int.
	 * @param unsigned true if the int value should be treated as unsigned,
	 * 		  otherwise false 
	 * @return a string representation of the int array.
	 */
	public static String longArrayToString(int[] data, boolean unsigned) {
		
		return longArrayToString(data, 0, data.length, unsigned);
	}
	
	public static String longArrayToString(int[] data, int offset, int length, boolean unsigned) {
		if ( data == null ) {
		      return null;
		}
			
		if(data.length == 0) return "[]";
	    
	    if(offset < 0 || offset >= data.length)
	    	throw new IllegalArgumentException("Offset out of array bound!");
	    
	    int endOffset = offset + Math.min(length, data.length);
		 
	    if(endOffset > data.length)
	    	length = data.length - offset;
	    
	    StringBuilder longs = new StringBuilder();	    
	    longs.append("[");
		    
	    for (int i = offset; i < endOffset; i++)
		{
	    	if(unsigned) {
				// Convert it to unsigned integer
				longs.append(data[i]&0xffffffffL);
			} else {
				longs.append(data[i]);
			}
			longs.append(",");
		}
	    
	    // Remove the last ","
	    if(longs.length() > 1)
	    	longs.deleteCharAt(longs.length()-1);
	    
	    if(endOffset < data.length)
	    	longs.append(" ..."); // Partial output
	    
	    longs.append("]");
	    
	    return longs.toString();	    
	}
	
	public static boolean parseBoolean(String s) {
		return Boolean.parseBoolean(s);
	}
	
	public static byte parseByte(String s) {
		return Byte.parseByte(s);
	}
	
	public static byte parseByte(String s, int radix) {
		return Byte.parseByte(s, radix);
	}
	
	public static double parseDouble(String s) {
		return Double.parseDouble(s);
	}
	
	public static float parseFloat(String s) {
		return Float.parseFloat(s);
	}
	
	public static int parseInt(String s) {
		return Integer.parseInt(s);
	}
	
	public static int parseInt(String s, int radix) {
		return Integer.parseInt(s, radix);
	}		
	
	public static long parseLong(String s) {
		return Long.parseLong(s);
	}
	
	public static long parseLong(String s, int radix) {
		return Long.parseLong(s, radix);
	}
	
	public static short parseShort(String s) {
		return Short.parseShort(s);
	}
	
	public static short parseShort(String s, int radix) {
		return Short.parseShort(s, radix);
	}	
	
	public static String quoteRegexReplacement(String replacement)
	{
		return Matcher.quoteReplacement(replacement);
	}
	
	/**
	 * Formats TIFF rational data field.
	 * 
	 * @param data an array of int.
	 * @param unsigned true if the int value should be treated as unsigned,
	 * 		  otherwise false 
	 * @return a string representation of the int array.
	 */
	public static String rationalArrayToString(int[] data, boolean unsigned) {
		if(data.length%2 != 0)
			throw new IllegalArgumentException("Data length is odd number, expect even!");

		StringBuilder rational = new StringBuilder();
		rational.append("[");
		
		for (int i=0; i<data.length; i+=2)
		{
			long  numerator = data[i], denominator = data[i+1];
			
			//if(denominator == 0) throw new ArithmeticException("Divided by zero");
			
			if (unsigned) {
				// Converts it to unsigned integer
				numerator = (data[i]&0xffffffffL);
				denominator = (data[i+1]&0xffffffffL);
			}
			
			rational.append(numerator);			
			rational.append("/");
			rational.append(denominator);
			
			rational.append(",");
		}
		
		rational.deleteCharAt(rational.length()-1);
		rational.append("]");
		
		return rational.toString();
	}
	
	public static String rationalToString(DecimalFormat df, boolean unsigned, int ... rational) {
		if(rational.length < 2) throw new IllegalArgumentException("Input data length is too short");
		if(rational[1] == 0) throw new ArithmeticException("Divided by zero");
		
		long numerator = rational[0];
		long denominator= rational[1];
		
		if (unsigned) {
			// Converts it to unsigned integer
			numerator = (numerator&0xffffffffL);
			denominator = (denominator&0xffffffffL);
		}
		
		return df.format(1.0*numerator/denominator);
	}
	
	/**
	 * Replaces the last occurrence of the string represented by the regular expression
	 *  
	 * @param input input string
 	 * @param regex the regular expression to which this string is to be matched
	 * @param replacement the string to be substituted for the match
	 * @return the resulting String
	 */
	public static String replaceLast(String input, String regex, String replacement) {
		return input.replaceAll(regex+"(?!.*"+regex+")", replacement); // Using negative look ahead
	}
	
	public static String reverse(String s) {
		if(s == null) return null;
		
		return new StringBuilder(s).reverse().toString();
	}
	
	// This method will not work for surrogate pairs
	public static String reverse2(String s) {
		if(s == null) return null;
		
		int i, len = s.length();
	    StringBuilder dest = new StringBuilder(len);

	    for (i = (len - 1); i >= 0; i--)
	       dest.append(s.charAt(i));
	    
	    return dest.toString();
	}
	
	public static String reverse(String str, String delimiter) {	
		if(isNullOrEmpty(delimiter)) {
			return str;
		}
		
		StringBuilder sb = new StringBuilder(str.length());
		reverseIt(str, delimiter, sb);
		
		return sb.toString();
	}
	
	public static String reverse2(String str, String delimiter) {
		if(isNullOrEmpty(delimiter) || isNullOrEmpty(str) || (str.trim().length() == 0) || (str.indexOf(delimiter) < 0)) {
			return str;
		} 			
	
		String escaptedDelimiter = escapeRegex(delimiter);
		// Keep the trailing white spaces by setting limit to -1	
		String[] stringArray = str.split(escaptedDelimiter, -1);
		StringBuilder sb = new StringBuilder(str.length() + delimiter.length());
			
		for (int i = stringArray.length-1; i >= 0; i--)
		{
			sb.append(stringArray[i]).append(delimiter);
		}

		return sb.substring(0, sb.lastIndexOf(delimiter));
	}
	
	private static void reverseIt(String str, String delimiter, StringBuilder sb) {
		if(isNullOrEmpty(str) || (str.trim().length() == 0) || str.indexOf(delimiter) < 0) {
			sb.append(str);
			return;
		}	
		// Recursion
		reverseIt(str.substring(str.indexOf(delimiter)+delimiter.length()), delimiter, sb);
		sb.append(delimiter);
		sb.append(str.substring(0, str.indexOf(delimiter)));
	}
		
	public static String reverseWords(String s) {
		String[] stringArray = s.split("\\b");
		StringBuilder sb = new StringBuilder(s.length());
		
		for (int i = stringArray.length-1; i >= 0; i--)
		{
			sb.append(stringArray[i]);
		}
		
		return sb.toString();
	}
	
	/**
	 * Formats TIFF short data field.
	 * 
	 * @param data an array of short.
	 * @param unsigned true if the short value should be treated as unsigned,
	 * 		  otherwise false 
	 * @return a string representation of the short array.
	 */
	public static String shortArrayToString(short[] data, boolean unsigned) {
		return shortArrayToString(data, 0, data.length, unsigned);
	}
	
	public static String shortArrayToString(short[] data, int offset, int length, boolean unsigned) {
		if ( data == null ) {
		      return null;
		}
			
		if(data.length == 0) return "[]";
	    
	    if(offset < 0 || offset >= data.length)
	    	throw new IllegalArgumentException("Offset out of array bound!");
	    
	    int endOffset = offset + Math.min(length, data.length);
		 
	    if(endOffset > data.length)
	    	length = data.length - offset;
	    
	    StringBuilder shorts = new StringBuilder();	    
	    shorts.append("[");
		    
	    for (int i = offset; i < endOffset; i++)
		{
			if(unsigned) {
				// Convert it to unsigned short
				shorts.append(data[i]&0xffff);
			} else {
				shorts.append(data[i]);
			}
			shorts.append(",");
		}
	    
	    // Remove the last ","
	    if(shorts.length() > 1)
	    	shorts.deleteCharAt(shorts.length()-1);
	    
	    if(endOffset < data.length)
	    	shorts.append(" ..."); // Partial output
	    
	    shorts.append("]");
		
		return shorts.toString();
	}
	
	public static String shortToHexString(short value) {
		StringBuilder buffer = new StringBuilder(6);
		
		buffer.append("0x");		
		
		buffer.append(HEXES[(value & 0x000F)]);
		buffer.append(HEXES[(value & 0x00F0) >>> 4]);
		buffer.append(HEXES[(value & 0x0F00) >>> 8]);
		buffer.append(HEXES[(value & 0xF000) >>> 12]);
		
		return buffer.toString();
	}
	
	public static String shortToHexStringMM(short value) {
		
		StringBuilder buffer = new StringBuilder(6);
		
		buffer.append("0x");
		
		buffer.append(HEXES[(value & 0xF000) >>> 12]);
		buffer.append(HEXES[(value & 0x0F00) >>> 8]);
		buffer.append(HEXES[(value & 0x00F0) >>> 4]);
		buffer.append(HEXES[(value & 0x000F)]);
		
		return buffer.toString();
	}
	
	/**
	 *  Converts stack trace to string
	 */
    public static String stackTraceToString(Throwable e) {  
        StringWriter sw = new StringWriter();  
        e.printStackTrace(new PrintWriter(sw));
        
        return sw.toString();   
    }
	
	/**
	 * A read-only String iterator from stackoverflow.com
	 * 
	 * @param string input string to be iterated
	 * @return an iterator for the input string
	 */
	public static Iterator<Character> stringIterator(final String string) {
		// Ensure the error is found as soon as possible.
		if (string == null)
			throw new NullPointerException();

		return new Iterator<Character>() {
			private int index = 0;

			public boolean hasNext() {
				return index < string.length();
			}

			public Character next() {
				/*
				 * Throw NoSuchElementException as defined by the Iterator contract,
				 * not IndexOutOfBoundsException.
				 */
				if (!hasNext())
					throw new NoSuchElementException();
				return string.charAt(index++);
			}

			public void remove() {
				throw new UnsupportedOperationException();
			}
		};
	}
	
	public static String toHexString(byte[] bytes) {
		return toHexString(bytes, 0, bytes.length);
	}
	
	/**
	 * Convert byte array to hex string
	 * 
	 * @param bytes input byte array
	 * @param offset start offset
	 * @param length number of items to include
	 *  
	 * @return a hex string representation for the byte array without 0x prefix
	 */
	public static String toHexString(byte[] bytes, int offset, int length) {		
		if ( bytes == null )
			return null;
	    
		if(bytes.length == 0) return "";
	    
	    if(offset < 0 || offset >= bytes.length)
	    	throw new IllegalArgumentException("Offset out of array bound!");
	    
	    int endOffset = offset + Math.min(length, bytes.length);
		 
	    if(endOffset > bytes.length)
	    	length = bytes.length - offset;
	    
	    StringBuilder hex = new StringBuilder(5*length + 2);	    
		    
	    for (int i = offset; i < endOffset; i++) {
	    	hex.append(HEXES[(bytes[i] & 0xf0) >> 4])
	         .append(HEXES[bytes[i] & 0x0f]);
	    }
	    
	    return hex.toString();
	}
	
	public static String toUTF16BE(byte[] data, int start, int length) {
		String retVal = "";
		
		 try {
			 retVal = new String(data, start, length, "UTF-16BE");
		 } catch (UnsupportedEncodingException e) {
			 e.printStackTrace();
		 }
		
		 return retVal;		 
	}
	
	private StringUtils(){} // Prevents instantiation	
}
