001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdi.internal.jdwp;
011:
012: import java.io.DataInputStream;
013: import java.io.DataOutputStream;
014: import java.io.IOException;
015: import java.io.UTFDataFormatException;
016:
017: /**
018: * This class implements the corresponding Java Debug Wire Protocol (JDWP) ID
019: * declared by the JDWP specification.
020: *
021: */
022: public class JdwpString {
023: /**
024: * Reads String from Jdwp stream.
025: * Read a UTF where length has 4 bytes, and not just 2.
026: * This code was based on the OTI Retysin source for readUTF.
027: */
028: public static String read(DataInputStream in) throws IOException {
029: int utfSize = in.readInt();
030: byte utfBytes[] = new byte[utfSize];
031: in.readFully(utfBytes);
032: /* Guess at buffer size */
033: StringBuffer strBuffer = new StringBuffer(utfSize / 3 * 2);
034: for (int i = 0; i < utfSize;) {
035: int a = utfBytes[i] & 0xFF;
036: if ((a >> 4) < 12) {
037: strBuffer.append((char) a);
038: i++;
039: } else {
040: int b = utfBytes[i + 1] & 0xFF;
041: if ((a >> 4) < 14) {
042: if ((b & 0xBF) == 0) {
043: throw new UTFDataFormatException(
044: JDWPMessages.JdwpString_Second_byte_input_does_not_match_UTF_Specification_1);
045: }
046: strBuffer
047: .append((char) (((a & 0x1F) << 6) | (b & 0x3F)));
048: i += 2;
049: } else {
050: int c = utfBytes[i + 2] & 0xFF;
051: if ((a & 0xEF) > 0) {
052: if (((b & 0xBF) == 0) || ((c & 0xBF) == 0)) {
053: throw new UTFDataFormatException(
054: JDWPMessages.JdwpString_Second_or_third_byte_input_does_not_mach_UTF_Specification_2);
055: }
056: strBuffer.append((char) (((a & 0x0F) << 12)
057: | ((b & 0x3F) << 6) | (c & 0x3F)));
058: i += 3;
059: } else {
060: throw new UTFDataFormatException(
061: JDWPMessages.JdwpString_Input_does_not_match_UTF_Specification_3);
062: }
063: }
064: }
065: }
066: return strBuffer.toString();
067: }
068:
069: /**
070: * Writes String to Jdwp stream.
071: * Write a UTF where length has 4 bytes, and not just 2.
072: * This code was based on OTI Retsin source for writeUTF.
073: */
074: public static void write(String str, DataOutputStream out)
075: throws IOException {
076: if (str == null)
077: throw new NullPointerException(
078: JDWPMessages.JdwpString_str_is_null_4);
079: int utfCount = 0;
080: for (int i = 0; i < str.length(); i++) {
081: int charValue = str.charAt(i);
082: if (charValue > 0 && charValue <= 127)
083: utfCount += 1;
084: else if (charValue <= 2047)
085: utfCount += 2;
086: else
087: utfCount += 3;
088: }
089: byte utfBytes[] = new byte[utfCount];
090: int utfIndex = 0;
091: for (int i = 0; i < str.length(); i++) {
092: int charValue = str.charAt(i);
093: if (charValue > 0 && charValue <= 127)
094: utfBytes[utfIndex++] = (byte) charValue;
095: else if (charValue <= 2047) {
096: utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
097: utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
098: } else {
099: utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
100: utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
101: utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
102: }
103: }
104: out.writeInt(utfCount);
105: if (utfCount > 0)
106: out.write(utfBytes);
107: }
108: }
|