package org.postgresql.util;

import java.sql.*;

/**
 * Converts to and from the postgresql bytea datatype used by the backend.
 *
 * $Id: PGbytea.java,v 1.2 2001/10/25 06:00:00 momjian Exp $
 */

public class PGbytea
{

	/**
	 * Converts a PG bytea string (i.e. the text representation
	 * of the bytea data type) into a java byte[]
	 */
	public static byte[] toBytes(String s) throws SQLException
	{
		if (s == null)
			return null;
		int slength = s.length();
		byte[] buf = new byte[slength];
		int bufpos = 0;
		int thebyte;
		char nextchar;
		char secondchar;
		for (int i = 0; i < slength; i++)
		{
			nextchar = s.charAt(i);
			if (nextchar == '\\')
			{
				secondchar = s.charAt(++i);
				if (secondchar == '\\')
				{
					//escaped \
					buf[bufpos++] = (byte)'\\';
				}
				else
				{
					thebyte = (secondchar - 48) * 64 + (s.charAt(++i) - 48) * 8 + (s.charAt(++i) - 48);
					if (thebyte > 127)
						thebyte -= 256;
					buf[bufpos++] = (byte)thebyte;
				}
			}
			else
			{
				buf[bufpos++] = (byte)nextchar;
			}
		}
		byte[] l_return = new byte[bufpos];
		System.arraycopy(buf, 0, l_return, 0, bufpos);
		return l_return;
	}

	/**
	 * Converts a java byte[] into a PG bytea string (i.e. the text
	 * representation of the bytea data type)
	 */
	public static String toPGString(byte[] p_buf) throws SQLException
	{
		if (p_buf == null)
			return null;
		StringBuffer l_strbuf = new StringBuffer();
		for (int i = 0; i < p_buf.length; i++)
		{
			int l_int = (int)p_buf[i];
			if (l_int < 0)
			{
				l_int = 256 + l_int;
			}
			//we escape the same non-printable characters as the backend
			//we must escape all 8bit characters otherwise when convering
			//from java unicode to the db character set we may end up with
			//question marks if the character set is SQL_ASCII
			if (l_int < 040 || l_int > 0176)
			{
				//escape charcter with the form \000, but need two \\ because of
				//the parser
				l_strbuf.append("\\");
				l_strbuf.append((char)(((l_int >> 6) & 0x3) + 48));
				l_strbuf.append((char)(((l_int >> 3) & 0x7) + 48));
				l_strbuf.append((char)((l_int & 0x07) + 48));
			}
			else if (p_buf[i] == (byte)'\\')
			{
				//escape the backslash character as \\, but need four \\\\ because
				//of the parser
				l_strbuf.append("\\\\");
			}
			else
			{
				//other characters are left alone
				l_strbuf.append((char)p_buf[i]);
			}
		}
		return l_strbuf.toString();
	}


}
