/** Return atom as a string literal */ @Pure public synchronized String toUnicodeString() throws java.io.UTFDataFormatException { if (unicodeStringOrJTOCoffset == null) { String s = UTF8Convert.fromUTF8(val); if (VM.runningVM) { s = InternedStrings.internUnfoundString(s); unicodeStringOrJTOCoffset = s; } else if (!VM.writingImage) { s = s.intern(); int offset = Statics.findOrCreateObjectLiteral(s); unicodeStringOrJTOCoffset = offset; } return s; } else if (unicodeStringOrJTOCoffset instanceof String) { return (String) unicodeStringOrJTOCoffset; } else { if (VM.runningVM) { return (String) Statics.getSlotContentsAsObject( Offset.fromIntSignExtend((Integer) unicodeStringOrJTOCoffset)); } else { return UTF8Convert.fromUTF8(val).intern(); } } }
/** Create atom from the key that maps to it. */ private Atom(byte[] val, int id, String str) { this.id = id; this.unicodeStringOrJTOCoffset = str; if ((val == null) && (id != -1)) { this.val = UTF8Convert.toUTF8(str); } else { this.val = val; } }
/** * Outside of this class atoms are canonical and should be compared using ==. This method is used * to maintain atoms in internal hash tables and shouldn't be used externally. */ @Override @Pure public boolean equals(Object other) { // quick test as atoms are generally canonical if (this == other) { return true; } else { if (other instanceof Atom) { Atom that = (Atom) other; // if the atoms are well formed then their identifiers are unique if ((that.id != -1) && (this.id != -1)) { return that.id == this.id; } // one atom isn't well formed, can we do a string comparison to work out equality? if ((this.unicodeStringOrJTOCoffset != null) && (that.unicodeStringOrJTOCoffset != null)) { return toUnicodeStringInternal().equals(that.toUnicodeStringInternal()); } try { // perform byte by byte comparison byte[] val1; if (that.val != null) { val1 = that.val; } else { val1 = UTF8Convert.toUTF8(that.toUnicodeString()); } byte[] val2; if (this.val != null) { val2 = this.val; } else { val2 = UTF8Convert.toUTF8(toUnicodeString()); } if (val1.length == val2.length) { for (int i = 0; i < val1.length; i++) { if (val1[i] != val2[i]) return false; } return true; } } catch (UTFDataFormatException e) { throw new Error("Error in UTF data encoding: ", e); } } return false; } }
/** Return the hashCode of an atom, this equals the unicode string encoding of the atom */ @Override public int hashCode() { try { if (unicodeStringOrJTOCoffset != null) { return toUnicodeStringInternal().hashCode(); } else { return UTF8Convert.computeStringHashCode(val); } } catch (UTFDataFormatException e) { return 0; } }
/** * Offset of an atom's string in the JTOC, for string literals * * @return Offset of string literal in JTOC * @throws java.io.UTFDataFormatException */ public synchronized int getStringLiteralOffset() throws java.io.UTFDataFormatException { if (unicodeStringOrJTOCoffset == null) { String s = UTF8Convert.fromUTF8(val); if (VM.runningVM) { s = InternedStrings.internUnfoundString(s); } else { s = s.intern(); } int offset = Statics.findOrCreateObjectLiteral(s); unicodeStringOrJTOCoffset = offset; return offset; } else if (unicodeStringOrJTOCoffset instanceof String) { int offset = Statics.findOrCreateObjectLiteral(unicodeStringOrJTOCoffset); unicodeStringOrJTOCoffset = offset; return offset; } else { return (Integer) unicodeStringOrJTOCoffset; } }
/** Atom as string literal or null if atom hasn't been converted */ private synchronized String toUnicodeStringInternal() { if (unicodeStringOrJTOCoffset == null) { return null; } else if (unicodeStringOrJTOCoffset instanceof String) { return (String) unicodeStringOrJTOCoffset; } else { if (VM.runningVM) { Object result = Statics.getSlotContentsAsObject( Offset.fromIntSignExtend((Integer) unicodeStringOrJTOCoffset)); return (String) result; } else { try { return UTF8Convert.fromUTF8(val).intern(); } catch (UTFDataFormatException e) { throw new Error("Error in UTF data encoding: ", e); } } } }