From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- .../com/ericsson/otp/erlang/OtpErlangAtom.java | 284 +++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java (limited to 'lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java') diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java new file mode 100644 index 0000000000..4d53447164 --- /dev/null +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java @@ -0,0 +1,284 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2000-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +package com.ericsson.otp.erlang; + +import java.io.Serializable; + +/** + * Provides a Java representation of Erlang atoms. Atoms can be created from + * strings whose length is not more than {@link #maxAtomLength maxAtomLength} + * characters. + */ +public class OtpErlangAtom extends OtpErlangObject implements Serializable, + Cloneable { + // don't change this! + static final long serialVersionUID = -3204386396807876641L; + + /** The maximun allowed length of an atom, in characters */ + public static final int maxAtomLength = 0xff; // one byte length + + private final String atom; + + /** + * Create an atom from the given string. + * + * @param atom + * the string to create the atom from. + * + * @exception java.lang.IllegalArgumentException + * if the string is null or contains more than + * {@link #maxAtomLength maxAtomLength} characters. + */ + public OtpErlangAtom(final String atom) { + if (atom == null) { + throw new java.lang.IllegalArgumentException( + "null string value"); + } + + if (atom.length() > maxAtomLength) { + throw new java.lang.IllegalArgumentException("Atom may not exceed " + + maxAtomLength + " characters"); + } + this.atom = atom; + } + + /** + * Create an atom from a stream containing an atom encoded in Erlang + * external format. + * + * @param buf + * the stream containing the encoded atom. + * + * @exception OtpErlangDecodeException + * if the buffer does not contain a valid external + * representation of an Erlang atom. + */ + public OtpErlangAtom(final OtpInputStream buf) + throws OtpErlangDecodeException { + atom = buf.read_atom(); + } + + /** + * Create an atom whose value is "true" or "false". + */ + public OtpErlangAtom(final boolean t) { + atom = String.valueOf(t); + } + + /** + * Get the actual string contained in this object. + * + * @return the raw string contained in this object, without regard to Erlang + * quoting rules. + * + * @see #toString + */ + public String atomValue() { + return atom; + } + + /** + * The boolean value of this atom. + * + * @return the value of this atom expressed as a boolean value. If the atom + * consists of the characters "true" (independent of case) the value + * will be true. For any other values, the value will be false. + * + */ + public boolean booleanValue() { + return Boolean.valueOf(atomValue()).booleanValue(); + } + + /** + * Get the printname of the atom represented by this object. The difference + * between this method and {link #atomValue atomValue()} is that the + * printname is quoted and escaped where necessary, according to the Erlang + * rules for atom naming. + * + * @return the printname representation of this atom object. + * + * @see #atomValue + */ + @Override + public String toString() { + if (atomNeedsQuoting(atom)) { + return "'" + escapeSpecialChars(atom) + "'"; + } else { + return atom; + } + } + + /** + * Determine if two atoms are equal. + * + * @param o + * the other object to compare to. + * + * @return true if the atoms are equal, false otherwise. + */ + @Override + public boolean equals(final Object o) { + + if (!(o instanceof OtpErlangAtom)) { + return false; + } + + final OtpErlangAtom atom = (OtpErlangAtom) o; + return this.atom.compareTo(atom.atom) == 0; + } + + @Override + protected int doHashCode() { + return atom.hashCode(); + } + + /** + * Convert this atom to the equivalent Erlang external representation. + * + * @param buf + * an output stream to which the encoded atom should be + * written. + */ + @Override + public void encode(final OtpOutputStream buf) { + buf.write_atom(atom); + } + + /* the following four predicates are helpers for the toString() method */ + private boolean isErlangDigit(final char c) { + return c >= '0' && c <= '9'; + } + + private boolean isErlangUpper(final char c) { + return c >= 'A' && c <= 'Z' || c == '_'; + } + + private boolean isErlangLower(final char c) { + return c >= 'a' && c <= 'z'; + } + + private boolean isErlangLetter(final char c) { + return isErlangLower(c) || isErlangUpper(c); + } + + // true if the atom should be displayed with quotation marks + private boolean atomNeedsQuoting(final String s) { + char c; + + if (s.length() == 0) { + return true; + } + if (!isErlangLower(s.charAt(0))) { + return true; + } + + final int len = s.length(); + for (int i = 1; i < len; i++) { + c = s.charAt(i); + + if (!isErlangLetter(c) && !isErlangDigit(c) && c != '@') { + return true; + } + } + return false; + } + + /* + * Get the atom string, with special characters escaped. Note that this + * function currently does not consider any characters above 127 to be + * printable. + */ + private String escapeSpecialChars(final String s) { + char c; + final StringBuffer so = new StringBuffer(); + + final int len = s.length(); + for (int i = 0; i < len; i++) { + c = s.charAt(i); + + /* + * note that some of these escape sequences are unique to Erlang, + * which is why the corresponding 'case' values use octal. The + * resulting string is, of course, in Erlang format. + */ + + switch (c) { + // some special escape sequences + case '\b': + so.append("\\b"); + break; + + case 0177: + so.append("\\d"); + break; + + case 033: + so.append("\\e"); + break; + + case '\f': + so.append("\\f"); + break; + + case '\n': + so.append("\\n"); + break; + + case '\r': + so.append("\\r"); + break; + + case '\t': + so.append("\\t"); + break; + + case 013: + so.append("\\v"); + break; + + case '\\': + so.append("\\\\"); + break; + + case '\'': + so.append("\\'"); + break; + + case '\"': + so.append("\\\""); + break; + + default: + // some other character classes + if (c < 027) { + // control chars show as "\^@", "\^A" etc + so.append("\\^" + (char) ('A' - 1 + c)); + } else if (c > 126) { + // 8-bit chars show as \345 \344 \366 etc + so.append("\\" + Integer.toOctalString(c)); + } else { + // character is printable without modification! + so.append(c); + } + } + } + return new String(so); + } + +} -- cgit v1.2.3