0N/A/*
553N/A * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
553N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
553N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
553N/A * or visit www.oracle.com if you need additional information or have any
553N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.tools.apt.mirror.declaration;
0N/A
0N/A
0N/Aimport java.util.Collection;
0N/A
0N/Aimport com.sun.mirror.declaration.*;
0N/Aimport com.sun.mirror.type.TypeMirror;
0N/Aimport com.sun.tools.apt.mirror.type.TypeMirrorImpl;
0N/Aimport com.sun.tools.javac.code.Type;
0N/A
0N/Aimport static com.sun.tools.javac.code.TypeTags.*;
0N/A
0N/A
0N/A/**
0N/A * Utility class for operating on constant expressions.
0N/A */
330N/A@SuppressWarnings("deprecation")
0N/Aclass Constants {
0N/A
0N/A /**
0N/A * Converts a constant in javac's internal representation (in which
0N/A * boolean, char, byte, short, and int are each represented by an Integer)
0N/A * into standard representation. Other values (including null) are
0N/A * returned unchanged.
0N/A */
0N/A static Object decodeConstant(Object value, Type type) {
0N/A if (value instanceof Integer) {
0N/A int i = ((Integer) value).intValue();
0N/A switch (type.tag) {
0N/A case BOOLEAN: return Boolean.valueOf(i != 0);
0N/A case CHAR: return Character.valueOf((char) i);
0N/A case BYTE: return Byte.valueOf((byte) i);
0N/A case SHORT: return Short.valueOf((short) i);
0N/A }
0N/A }
0N/A return value;
0N/A }
0N/A
0N/A /**
0N/A * Returns a formatter for generating the text of constant
0N/A * expressions. Equivalent to
0N/A * <tt>getFormatter(new StringBuilder())</tt>.
0N/A */
0N/A static Formatter getFormatter() {
0N/A return new Formatter(new StringBuilder());
0N/A }
0N/A
0N/A /**
0N/A * Returns a formatter for generating the text of constant
0N/A * expressions. Also generates the text of constant
0N/A * "pseudo-expressions" for annotations and array-valued
0N/A * annotation elements.
0N/A *
0N/A * @param buf where the expression is written
0N/A */
0N/A static Formatter getFormatter(StringBuilder buf) {
0N/A return new Formatter(buf);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Utility class used to generate the text of constant
0N/A * expressions. Also generates the text of constant
0N/A * "pseudo-expressions" for annotations and array-valued
0N/A * annotation elements.
0N/A */
0N/A static class Formatter {
0N/A
0N/A private StringBuilder buf; // where the output goes
0N/A
0N/A private Formatter(StringBuilder buf) {
0N/A this.buf = buf;
0N/A }
0N/A
0N/A
0N/A public String toString() {
0N/A return buf.toString();
0N/A }
0N/A
0N/A /**
0N/A * Appends a constant whose type is not statically known
0N/A * by dispatching to the appropriate overloaded append method.
0N/A */
0N/A void append(Object val) {
0N/A if (val instanceof String) {
0N/A append((String) val);
0N/A } else if (val instanceof Character) {
0N/A append((Character) val);
0N/A } else if (val instanceof Boolean) {
0N/A append((Boolean) val);
0N/A } else if (val instanceof Byte) {
0N/A append((Byte) val);
0N/A } else if (val instanceof Short) {
0N/A append((Short) val);
0N/A } else if (val instanceof Integer) {
0N/A append((Integer) val);
0N/A } else if (val instanceof Long) {
0N/A append((Long) val);
0N/A } else if (val instanceof Float) {
0N/A append((Float) val);
0N/A } else if (val instanceof Double) {
0N/A append((Double) val);
0N/A } else if (val instanceof TypeMirror) {
0N/A append((TypeMirrorImpl) val);
0N/A } else if (val instanceof EnumConstantDeclaration) {
0N/A append((EnumConstantDeclarationImpl) val);
0N/A } else if (val instanceof AnnotationMirror) {
0N/A append((AnnotationMirrorImpl) val);
183N/A } else if (val instanceof Collection<?>) {
183N/A append((Collection<?>) val);
0N/A } else {
0N/A appendUnquoted(val.toString());
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Appends a string, escaped (as needed) and quoted.
0N/A */
0N/A void append(String val) {
0N/A buf.append('"');
0N/A appendUnquoted(val);
0N/A buf.append('"');
0N/A }
0N/A
0N/A /**
0N/A * Appends a Character, escaped (as needed) and quoted.
0N/A */
0N/A void append(Character val) {
0N/A buf.append('\'');
0N/A appendUnquoted(val.charValue());
0N/A buf.append('\'');
0N/A }
0N/A
0N/A void append(Boolean val) {
0N/A buf.append(val);
0N/A }
0N/A
0N/A void append(Byte val) {
0N/A buf.append(String.format("0x%02x", val));
0N/A }
0N/A
0N/A void append(Short val) {
0N/A buf.append(val);
0N/A }
0N/A
0N/A void append(Integer val) {
0N/A buf.append(val);
0N/A }
0N/A
0N/A void append(Long val) {
0N/A buf.append(val).append('L');
0N/A }
0N/A
0N/A void append(Float val) {
0N/A if (val.isNaN()) {
0N/A buf.append("0.0f/0.0f");
0N/A } else if (val.isInfinite()) {
0N/A if (val.floatValue() < 0) {
0N/A buf.append('-');
0N/A }
0N/A buf.append("1.0f/0.0f");
0N/A } else {
0N/A buf.append(val).append('f');
0N/A }
0N/A }
0N/A
0N/A void append(Double val) {
0N/A if (val.isNaN()) {
0N/A buf.append("0.0/0.0");
0N/A } else if (val.isInfinite()) {
0N/A if (val.doubleValue() < 0) {
0N/A buf.append('-');
0N/A }
0N/A buf.append("1.0/0.0");
0N/A } else {
0N/A buf.append(val);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Appends the class literal corresponding to a type. Should
0N/A * only be invoked for types that have an associated literal.
0N/A * e.g: "java.lang.String.class"
0N/A * "boolean.class"
0N/A * "int[].class"
0N/A */
0N/A void append(TypeMirrorImpl t) {
0N/A appendUnquoted(t.type.toString());
0N/A buf.append(".class");
0N/A }
0N/A
0N/A /**
0N/A * Appends the fully qualified name of an enum constant.
0N/A * e.g: "java.math.RoundingMode.UP"
0N/A */
0N/A void append(EnumConstantDeclarationImpl e) {
0N/A appendUnquoted(e.sym.enclClass() + "." + e);
0N/A }
0N/A
0N/A /**
0N/A * Appends the text of an annotation pseudo-expression.
0N/A * e.g: "@pkg.Format(linesep='\n')"
0N/A */
0N/A void append(AnnotationMirrorImpl anno) {
0N/A appendUnquoted(anno.toString());
0N/A }
0N/A
0N/A /**
0N/A * Appends the elements of a collection, enclosed within braces
0N/A * and separated by ", ". Useful for array-valued annotation
0N/A * elements.
0N/A */
183N/A void append(Collection<?> vals) {
0N/A buf.append('{');
0N/A boolean first = true;
0N/A for (Object val : vals) {
0N/A if (first) {
0N/A first = false;
0N/A } else {
0N/A buf.append(", ");
0N/A }
0N/A append(((AnnotationValue) val).getValue());
0N/A }
0N/A buf.append('}');
0N/A }
0N/A
0N/A
0N/A /**
0N/A * For each char of a string, append using appendUnquoted(char).
0N/A */
0N/A private void appendUnquoted(String s) {
0N/A for (char c : s.toCharArray()) {
0N/A appendUnquoted(c);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Appends a char (unquoted), using escapes for those that are not
0N/A * printable ASCII. We don't know what is actually printable in
0N/A * the locale in which this result will be used, so ASCII is our
0N/A * best guess as to the least common denominator.
0N/A */
0N/A private void appendUnquoted(char c) {
0N/A switch (c) {
0N/A case '\b': buf.append("\\b"); break;
0N/A case '\t': buf.append("\\t"); break;
0N/A case '\n': buf.append("\\n"); break;
0N/A case '\f': buf.append("\\f"); break;
0N/A case '\r': buf.append("\\r"); break;
0N/A case '\"': buf.append("\\\""); break;
0N/A case '\'': buf.append("\\\'"); break;
0N/A case '\\': buf.append("\\\\"); break;
0N/A default:
0N/A if (isPrintableAscii(c)) {
0N/A buf.append(c);
0N/A } else {
0N/A buf.append(String.format("\\u%04x", (int) c));
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Is c a printable ASCII character?
0N/A */
0N/A private static boolean isPrintableAscii(char c) {
0N/A return c >= ' ' && c <= '~';
0N/A }
0N/A }
0N/A}