package SQLite;

/**
 * String encoder/decoder for SQLite.
 *
 * This module was kindly donated by Eric van der Maarel of Nedap N.V.
 *
 * This encoder was implemented based on an original idea from an anonymous
 * author in the source code of the SQLite distribution.
 * I feel obliged to provide a quote from the original C-source code:
 *
 * "The author disclaims copyright to this source code.  In place of
 *  a legal notice, here is a blessing:
 *
 *     May you do good and not evil.
 *     May you find forgiveness for yourself and forgive others.
 *     May you share freely, never taking more than you give."
 *
 */

public class StringEncoder {

    /**
     * Encodes the given byte array into a string that can be used by
     * the SQLite database. The database cannot handle null (0x00) and
     * the character '\'' (0x27). The encoding consists of escaping
     * these characters with a reserved character (0x01). The escaping
     * is applied after determining and applying a shift that minimizes
     * the number of escapes required.
     * With this encoding the data of original size n is increased to a
     * maximum of 1+(n*257)/254.
     * For sufficiently large n the overhead is thus less than 1.2%.
     * @param a the byte array to be encoded. A null reference is handled as
     *     an empty array.
     * @return the encoded bytes as a string. When an empty array is
     *     provided a string of length 1 is returned, the value of
     *     which is bogus.
     *     When decoded with this class' <code>decode</code> method
     *     a string of size 1 will return an empty byte array.
     */

    public static String encode(byte[] a) {
	// check input
	if (a == null || a.length == 0) {
	    // bogus shift, no data
	    return "x";
	}
	// determine count
	int[] cnt = new int[256];
	for (int i = 0 ; i < a.length; i++) {
	    cnt[a[i] & 0xff]++;
	}
	// determine shift for minimum number of escapes
	int shift = 1;
	int nEscapes = a.length;
	for (int i = 1; i < 256; i++) {
	    if (i == '\'') {
		continue;
	    }
	    int sum = cnt[i] + cnt[(i + 1) & 0xff] + cnt[(i + '\'') & 0xff];
	    if (sum < nEscapes) {
		nEscapes = sum;
		shift = i;
		if (nEscapes == 0) {
		    // cannot become smaller
		    break;
		}
	    }
	}
	// construct encoded output
	int outLen = a.length + nEscapes + 1;
	StringBuffer out = new StringBuffer(outLen);
	out.append((char)shift);
	for (int i = 0; i < a.length; i++) {
	    // apply shift
	    char c = (char)((a[i] - shift)&0xff);
	    // insert escapes
	    if (c == 0) { // forbidden
		out.append((char)1);
		out.append((char)1);
	    } else if (c == 1) { // escape character
		out.append((char)1);
		out.append((char)2);
	    } else if (c == '\'') { // forbidden
		out.append((char)1);
		out.append((char)3);
	    } else {
		out.append(c);
	    }
	}
	return out.toString();
    }

    /**
     * Decodes the given string that is assumed to be a valid encoding
     * of a byte array. Typically the given string is generated by
     * this class' <code>encode</code> method.
     * @param s the given string encoding.
     * @return the byte array obtained from the decoding.
     * @throws IllegalArgumentException when the string given is not
     *    a valid encoded string for this encoder.
     */

    public static byte[] decode(String s) {
	char[] a = s.toCharArray();
	if (a.length > 2 && a[0] == 'X' &&
	    a[1] == '\'' && a[a.length-1] == '\'') {
	    // SQLite3 BLOB syntax
	    byte[] result = new byte[(a.length-3)/2];
	    for (int i = 2, k = 0; i < a.length - 1; i += 2, k++) {
		byte tmp;
		switch (a[i]) {
		case '0': tmp = 0; break;
		case '1': tmp = 1; break;
		case '2': tmp = 2; break;
		case '3': tmp = 3; break;
		case '4': tmp = 4; break;
		case '5': tmp = 5; break;
		case '6': tmp = 6; break;
		case '7': tmp = 7; break;
		case '8': tmp = 8; break;
		case '9': tmp = 9; break;
		case 'A':
		case 'a': tmp = 10; break;
		case 'B':
		case 'b': tmp = 11; break;
		case 'C':
		case 'c': tmp = 12; break;
		case 'D':
		case 'd': tmp = 13; break;
		case 'E':
		case 'e': tmp = 14; break;
		case 'F':
		case 'f': tmp = 15; break;
		default:  tmp = 0; break;
		}
		result[k] = (byte) (tmp << 4);
		switch (a[i+1]) {
		case '0': tmp = 0; break;
		case '1': tmp = 1; break;
		case '2': tmp = 2; break;
		case '3': tmp = 3; break;
		case '4': tmp = 4; break;
		case '5': tmp = 5; break;
		case '6': tmp = 6; break;
		case '7': tmp = 7; break;
		case '8': tmp = 8; break;
		case '9': tmp = 9; break;
		case 'A':
		case 'a': tmp = 10; break;
		case 'B':
		case 'b': tmp = 11; break;
		case 'C':
		case 'c': tmp = 12; break;
		case 'D':
		case 'd': tmp = 13; break;
		case 'E':
		case 'e': tmp = 14; break;
		case 'F':
		case 'f': tmp = 15; break;
		default:  tmp = 0; break;
		}
		result[k] |= tmp;
	    }
	    return result;
	}
	// first element is the shift
	byte[] result = new byte[a.length-1];
	int i = 0;
	int shift = s.charAt(i++);
	int j = 0;
	while (i < s.length()) {
	    int c;
	    if ((c = s.charAt(i++)) == 1) { // escape character found
		if ((c = s.charAt(i++)) == 1) {
		    c = 0;
		} else if (c == 2) {
		    c = 1;
		} else if (c == 3) {
		    c = '\'';
		} else {
		    throw new IllegalArgumentException(
			"invalid string passed to decoder: " + j);
		}
	    }
	    // do shift
	    result[j++] = (byte)((c + shift) & 0xff);
	}
	int outLen = j;
	// provide array of correct length
	if (result.length != outLen) {
	    result = byteCopy(result, 0, outLen, new byte[outLen]);
	}
	return result;
    }

    /**
     * Copies count elements from source, starting at element with
     * index offset, to the given target.
     * @param source the source.
     * @param offset the offset.
     * @param count the number of elements to be copied.
     * @param target the target to be returned.
     * @return the target being copied to.
     */

    private static byte[] byteCopy(byte[] source, int offset,
				   int count, byte[] target) {
	for (int i = offset, j = 0; i < offset + count; i++, j++) {
	    target[j] = source[i];
	}
	return target;
    }


    static final char[] xdigits = {
	'0', '1', '2', '3', '4', '5', '6', '7',
	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    };

    /**
     * Encodes the given byte array into SQLite3 blob notation, ie X'..'
     * @param a the byte array to be encoded. A null reference is handled as
     *     an empty array.
     * @return the encoded bytes as a string.
     */

    public static String encodeX(byte[] a) {
	// check input
	if (a == null || a.length == 0) {
	    return "X''";
	}
	int outLen = a.length * 2 + 3;
	StringBuffer out = new StringBuffer(outLen);
	out.append('X');
	out.append('\'');
	for (int i = 0; i < a.length; i++) {
	    out.append(xdigits[(a[i] >> 4) & 0x0F]);
	    out.append(xdigits[a[i] & 0x0F]);
	}
	out.append('\'');
	return out.toString();
    }
}
