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.java; import java.util.HashMap; import java.util.Map; import org.eclipse.jdt.internal.core.nd.Nd; import org.eclipse.jdt.internal.core.nd.db.Database; import org.eclipse.jdt.internal.core.nd.db.IndexException; public abstract class TagTreeReader { public static final int[] UNUSED_RESULT = new int[1]; public static abstract class TagHandler<T> { abstract public T read(Nd nd, long address, TagTreeReader reader, int[] bytesRead); abstract public void write(Nd nd, long address, TagTreeReader reader, T toWrite, int[] bytesWritten); abstract public int getSize(Nd nd, T object, TagTreeReader reader); public void destruct(Nd nd, long address, TagTreeReader reader) { // Nothing to do by default } } public static abstract class FixedSizeTagHandler<T> extends TagHandler<T> { protected abstract T read(Nd nd, long address); protected abstract void write(Nd nd, long address, T value); protected abstract int getSize(); protected void destruct(Nd nd, long address) { // Nothing to do by default } @Override public final T read(Nd nd, long address, TagTreeReader reader, int[] bytesRead) { bytesRead[0] = getSize(); return read(nd, address); } @Override public final void write(Nd nd, long address, TagTreeReader reader, T value, int[] bytesWritten) { bytesWritten[0] = getSize(); write(nd, address, value); } @Override public final int getSize(Nd nd, T object, TagTreeReader reader) { return getSize(); } @Override public final void destruct(Nd nd, long address, TagTreeReader reader) { destruct(nd, address); } } private TagHandler<?> readers[] = new TagHandler[256]; private Map<TagHandler<?>, Integer> values = new HashMap<>(); public final void add(byte key, TagHandler<?> reader) { this.readers[key] = reader; this.values.put(reader, (int) key); } public final Object read(Nd nd, long address) { return read(nd, address, UNUSED_RESULT); } public final Object read(Nd nd, long address, int[] bytesRead) { long readAddress = address; Database db = nd.getDB(); byte nextByte = db.getByte(address); readAddress += Database.BYTE_SIZE; TagHandler<?> reader = this.readers[nextByte]; if (reader == null) { throw nd.describeProblem() .addProblemAddress("tag", address, 1) //$NON-NLS-1$ .build("Found unknown tag with value " + nextByte + " at address " + address); //$NON-NLS-1$//$NON-NLS-2$ } return reader.read(nd, readAddress, this, bytesRead); } protected abstract byte getKeyFor(Object toWrite); public final void write(Nd nd, long address, Object toWrite) { write(nd, address, toWrite, UNUSED_RESULT); } @SuppressWarnings("unchecked") public final void write(Nd nd, long address, Object toWrite, int[] bytesWritten) { byte key = getKeyFor(toWrite); @SuppressWarnings("rawtypes") TagHandler handler = this.readers[key]; if (handler == null) { throw nd.describeProblem().build("Invalid key " + key + " returned from getKeyFor(...)"); //$NON-NLS-1$//$NON-NLS-2$ } handler.write(nd, address, this, toWrite, bytesWritten); } public final void destruct(Nd nd, long address) { Database db = nd.getDB(); long readAddress = address; byte nextByte = db.getByte(readAddress); readAddress += Database.BYTE_SIZE; TagHandler<?> handler = this.readers[nextByte]; if (handler == null) { throw nd.describeProblem() .addProblemAddress("tag", address, 1) //$NON-NLS-1$ .build("Found unknown tag with value " + nextByte + " at address " + address); //$NON-NLS-1$//$NON-NLS-2$ } handler.destruct(nd, readAddress, this); } @SuppressWarnings("unchecked") public final int getSize(Nd nd, Object toMeasure) { byte key = getKeyFor(toMeasure); @SuppressWarnings("rawtypes") TagHandler handler = this.readers[key]; if (handler == null) { throw new IndexException("Attempted to get size of object " + toMeasure.toString() + " with unknown key " //$NON-NLS-1$//$NON-NLS-2$ + key); } return handler.getSize(nd, toMeasure, this); } }