package org.eclipse.dltk.tcl.internal.debug; import org.eclipse.dltk.debug.core.model.ComplexScriptType; import org.eclipse.dltk.debug.core.model.IScriptType; import org.eclipse.dltk.debug.core.model.IScriptTypeFactory; import org.eclipse.dltk.debug.core.model.IScriptValue; import org.eclipse.dltk.debug.core.model.StringScriptType; public class TclTypeFactory implements IScriptTypeFactory { private static class TclStringScriptType extends StringScriptType { public TclStringScriptType() { super(STRING); } @Override public String formatValue(IScriptValue value) { String string = value.getRawValue(); if (string == null) { return null; } return escapeString(string, false); } @Override public String formatDetails(IScriptValue value) { String string = value.getRawValue(); if (string == null) { return null; } return escapeString(string, true); } private static String escapeString(String input, boolean allowWhitespace) { if (!isEscapeNeeded(input)) { return input; } // if (!allowWhitespace && canBraceEscape(input)) { // return "{" + input + "}"; //$NON-NLS-1$ //$NON-NLS-2$ // } final StringBuffer result = new StringBuffer(input.length() + 8); final int length = input.length(); for (int i = 0; i < length; i++) { char c = input.charAt(i); if (isEscapeNeeded(c)) { if (allowWhitespace && (c == ' ' || c == '\n' || c == '\t')) { result.append(c); } else { result.append('\\'); if (c < 32) { switch (c) { case 7: result.append('a'); break; case 8: result.append('b'); break; case 9: result.append('t'); break; case 0xB: result.append('v'); break; case 0xC: result.append('f'); break; case 0xA: result.append('n'); break; case 0xD: result.append('r'); break; default: result.append(toHexChar(c / 16)); result.append(toHexChar(c % 16)); break; } } else { result.append(c); } } } else { result.append(c); } } return result.toString(); } private static char toHexChar(int value) { if (value <= 9) { return (char) ('0' + value); } else { return (char) ('A' + (value - 10)); } } private static boolean isEscapeNeeded(String value) { final int length = value.length(); for (int i = 0; i < length; i++) { if (isEscapeNeeded(value.charAt(i))) { return true; } } return false; } private static boolean isEscapeNeeded(char c) { if (c < 32) { return true; } switch (c) { case ' ': case '{': case '}': case '\"': case '[': case '\\': case '$': return true; } return false; } } private static class TclNamespaceType extends ComplexScriptType { public TclNamespaceType() { super(NAMESPACE); } @Override public String formatValue(IScriptValue value) { return NAMESPACE; } } private final TclStringScriptType stringType = new TclStringScriptType(); private final TclNamespaceType namespaceType = new TclNamespaceType(); private static final String NAMESPACE = "namespace"; //$NON-NLS-1$ @Override public IScriptType buildType(String type) { if (STRING.equals(type)) { return stringType; } else if (NAMESPACE.equals(type)) { return namespaceType; } else { return new ComplexScriptType(type); } } }