001: /*-------------------------------------------------------------------------
002: *
003: * Copyright (c) 2003-2005, PostgreSQL Global Development Group
004: *
005: * IDENTIFICATION
006: * $PostgreSQL: pgjdbc/org/postgresql/util/PGbytea.java,v 1.14 2006/11/06 05:49:48 jurka Exp $
007: *
008: *-------------------------------------------------------------------------
009: */
010: package org.postgresql.util;
011:
012: import java.sql.*;
013:
014: /**
015: * Converts to and from the postgresql bytea datatype used by the backend.
016: */
017: public class PGbytea {
018: private static final int MAX_3_BUFF_SIZE = 2 * 1024 * 1024;
019:
020: /*
021: * Converts a PG bytea raw value (i.e. the raw binary representation
022: * of the bytea data type) into a java byte[]
023: */
024: public static byte[] toBytes(byte[] s) throws SQLException {
025: if (s == null)
026: return null;
027: final int slength = s.length;
028: byte[] buf = null;
029: int correctSize = slength;
030: if (slength > MAX_3_BUFF_SIZE) {
031: // count backslash escapes, they will be either
032: // backslashes or an octal escape \\ or \003
033: //
034: for (int i = 0; i < slength; ++i) {
035: byte current = s[i];
036: if (current == '\\') {
037: byte next = s[++i];
038: if (next == '\\') {
039: --correctSize;
040: } else {
041: correctSize -= 3;
042: }
043: }
044: }
045: buf = new byte[correctSize];
046: } else {
047: buf = new byte[slength];
048: }
049: int bufpos = 0;
050: int thebyte;
051: byte nextbyte;
052: byte secondbyte;
053: for (int i = 0; i < slength; i++) {
054: nextbyte = s[i];
055: if (nextbyte == (byte) '\\') {
056: secondbyte = s[++i];
057: if (secondbyte == (byte) '\\') {
058: //escaped \
059: buf[bufpos++] = (byte) '\\';
060: } else {
061: thebyte = (secondbyte - 48) * 64 + (s[++i] - 48)
062: * 8 + (s[++i] - 48);
063: if (thebyte > 127)
064: thebyte -= 256;
065: buf[bufpos++] = (byte) thebyte;
066: }
067: } else {
068: buf[bufpos++] = nextbyte;
069: }
070: }
071: if (bufpos == correctSize) {
072: return buf;
073: }
074: byte[] l_return = new byte[bufpos];
075: System.arraycopy(buf, 0, l_return, 0, bufpos);
076: return l_return;
077: }
078:
079: /*
080: * Converts a java byte[] into a PG bytea string (i.e. the text
081: * representation of the bytea data type)
082: */
083: public static String toPGString(byte[] p_buf) throws SQLException {
084: if (p_buf == null)
085: return null;
086: StringBuffer l_strbuf = new StringBuffer(2 * p_buf.length);
087: for (int i = 0; i < p_buf.length; i++) {
088: int l_int = (int) p_buf[i];
089: if (l_int < 0) {
090: l_int = 256 + l_int;
091: }
092: //we escape the same non-printable characters as the backend
093: //we must escape all 8bit characters otherwise when convering
094: //from java unicode to the db character set we may end up with
095: //question marks if the character set is SQL_ASCII
096: if (l_int < 040 || l_int > 0176) {
097: //escape charcter with the form \000, but need two \\ because of
098: //the Java parser
099: l_strbuf.append("\\");
100: l_strbuf.append((char) (((l_int >> 6) & 0x3) + 48));
101: l_strbuf.append((char) (((l_int >> 3) & 0x7) + 48));
102: l_strbuf.append((char) ((l_int & 0x07) + 48));
103: } else if (p_buf[i] == (byte) '\\') {
104: //escape the backslash character as \\, but need four \\\\ because
105: //of the Java parser
106: l_strbuf.append("\\\\");
107: } else {
108: //other characters are left alone
109: l_strbuf.append((char) p_buf[i]);
110: }
111: }
112: return l_strbuf.toString();
113: }
114: }
|