Copyright (c) 2015, 2016 Google, Inc and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: Stefan Xenos (Google) - Initial implementation
/******************************************************************************* * Copyright (c) 2015, 2016 Google, Inc and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * Stefan Xenos (Google) - Initial implementation *******************************************************************************/
package org.eclipse.jdt.internal.core.nd; import org.eclipse.jdt.internal.core.nd.db.Database; import org.eclipse.jdt.internal.core.nd.db.IndexException; import org.eclipse.jdt.internal.core.nd.field.FieldShort; import org.eclipse.jdt.internal.core.nd.field.StructDef;
This is a basic polymorphic node in the network database. Pointers to NdNode or any of their subclasses will be resolved to the correct subclass of NdNode such that the correct version of an overloaded method will be invoked.
/** * This is a basic polymorphic node in the network database. Pointers to NdNode or any of their * subclasses will be resolved to the correct subclass of NdNode such that the correct version of an * overloaded method will be invoked. */
public abstract class NdNode extends NdStruct implements IDestructable { public static final FieldShort NODE_TYPE; @SuppressWarnings("hiding") public static final StructDef<NdNode> type; static { type = StructDef.create(NdNode.class, NdStruct.type); NODE_TYPE = type.addShort(); type.done(); }
Load a node from the specified address in the given database. Return null if a node cannot be loaded.
Params:
  • nd – The Nd from which to load the node.
  • address – The address of the node in the given Nd.
Returns:The NdNode at the specified location or null if a node cannot be loaded.
@Whenthere is a problem reading the given Nd's Database
/** * Load a node from the specified address in the given database. Return null if a node cannot * be loaded. * * @param nd The {@link Nd} from which to load the node. * @param address The address of the node in the given {@link Nd}. * @return The {@link NdNode} at the specified location or null if a node cannot be loaded. * @When there is a problem reading the given {@link Nd}'s Database */
public static NdNode load(Nd nd, long address) { if (address == 0) { return null; } try { return nd.getNode(address, NODE_TYPE.get(nd, address)); } catch (IndexException e) { // Add metadata to the exception describing where we obtained the node type from nd.describeProblem().addProblemAddress(NODE_TYPE, address).attachTo(e); throw e; } } @SuppressWarnings("unchecked") public static <T extends INdStruct> T load(Nd nd, long address, StructDef<T> typeToLoad) { if (address == 0) { return null; } NdNode result; try { // Polymorphic types (that subclass NdNode) store a header with their type ID result = nd.getNode(address, NODE_TYPE.get(nd, address)); } catch (IndexException e) { // Add metadata to the exception describing where we obtained the node type from nd.describeProblem().addProblemAddress(NODE_TYPE, address).attachTo(e); throw e; } Class<T> clazz = typeToLoad.getStructClass(); if (!clazz.isAssignableFrom(result.getClass())) { throw nd.describeProblem() .addProblemAddress(NODE_TYPE, address) .build("Found wrong data type at address " + address + ". Expected a subclass of " + //$NON-NLS-1$//$NON-NLS-2$ clazz + " but found " + result.getClass()); //$NON-NLS-1$ } return (T) result; }
Invokes the destructor on this node and frees up its memory
/** * Invokes the destructor on this node and frees up its memory */
public final void delete() { getNd().delete(this.address); } protected NdNode(Nd nd, long address) { super(nd, address); } protected NdNode(Nd nd) { super(nd, 0); Database db = nd.getDB(); short nodeType = nd.getNodeType(getClass()); ITypeFactory<? extends NdNode> factory1 = nd.getTypeFactory(nodeType); this.address = db.malloc(factory1.getRecordSize(), (short)(Database.POOL_FIRST_NODE_TYPE + nodeType)); NODE_TYPE.put(nd, this.address, nodeType); }
Return a value to uniquely identify the node within the factory that is responsible for loading instances of this node from the Nd.
/** * Return a value to uniquely identify the node within the factory that is responsible for loading * instances of this node from the {@link Nd}. * <b> */
public short getNodeType() { return this.nd.getNodeType(getClass()); } @Override public final long getAddress() { return this.address; } public final long getBindingID() { return this.address; } @Override public final boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof NdNode) { NdNode other = (NdNode) obj; return getNd() == other.getNd() && this.address == other.address; } return super.equals(obj); } @Override public final int hashCode() { return (int) (this.address >> Database.BLOCK_SIZE_DELTA_BITS); }
Return an value to globally identify the given node within the given linkage. This value can be used for comparison with other NdNodes.
/** * Return an value to globally identify the given node within the given linkage. This value * can be used for comparison with other {@link NdNode}s. */
public static int getNodeId(int linkageID, int nodeType) { return (linkageID << 16) | (nodeType & 0xffff); }
Convenience method for fetching a byte from the database.
Params:
  • offset – Location of the byte.
Returns:a byte from the database.
/** * Convenience method for fetching a byte from the database. * @param offset Location of the byte. * @return a byte from the database. */
protected byte getByte(long offset) { return getDB().getByte(offset); }
Returns the bit at the specified offset in a bit vector.
Params:
  • bitVector – Bits.
  • offset – The position of the desired bit.
Returns:the bit at the specified offset.
/** * Returns the bit at the specified offset in a bit vector. * @param bitVector Bits. * @param offset The position of the desired bit. * @return the bit at the specified offset. */
protected static boolean getBit(int bitVector, int offset) { int mask = 1 << offset; return (bitVector & mask) != 0; }
Dispose this NdNode. Subclasses should extend this method to perform any high-level node-specific cleanup. This will be invoked prior to disposing the fields. Implementations must invoke their parent's destruct method and should not destruct the fields.

If an external object wants to destroy a node, they should invoke delete rather than this method.

/** * Dispose this {@link NdNode}. Subclasses should extend this method to perform any high-level node-specific cleanup. * This will be invoked prior to disposing the fields. Implementations must invoke their parent's destruct method * and should not destruct the fields. * <p> * If an external object wants to destroy a node, they should invoke {@link NdNode#delete} rather than this * method. */
@Override public void destruct() { // Nothing to do by default. Subclasses will provide an implementation if necessary. } }