/*******************************************************************************
 * Copyright (c) 2004, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.debug.internal.ui.views.memory.renderings;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IDebugElement;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IMemoryBlockExtension;
import org.eclipse.debug.core.model.MemoryByte;
import org.eclipse.debug.internal.ui.DebugUIMessages;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.internal.ui.memory.IMemoryRenderingUpdater;
import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.memory.AbstractTableRendering;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.Viewer;

/**
 * Content Provider used by AbstractTableRendering
 *
 * @since 3.0
 */
public class TableRenderingContentProvider extends BasicDebugViewContentProvider {

	// lines currently being displayed by the table rendering
	protected Vector<TableRenderingLine> lineCache;

	// Cache to allow the content provider to comppute change information
	// Cache is taken by copying the lineCache after a suspend event
	// or change event from the the memory block.
	protected Hashtable<String, TableRenderingLine> contentCache;

	// cache in the form of MemoryByte
	// needed for reorganizing cache when the row size changes
	private MemoryByte[] fContentCacheInBytes;
	private String fContentCacheStartAddress;

	private BigInteger fBufferTopAddress;

	private TableRenderingContentInput fInput;
	private BigInteger fBufferEndAddress;

	private boolean fDynamicLoad;

	/**
	 * @param memoryBlock
	 * @param newTab
	 */
	public TableRenderingContentProvider()
	{
		lineCache = new Vector<TableRenderingLine>();
		contentCache = new Hashtable<String, TableRenderingLine>();
		initializeDynamicLoad();

		DebugPlugin.getDefault().addDebugEventListener(this);
	}

	/**
	 * @param viewer
	 */
	public void setViewer(StructuredViewer viewer)
	{
		fViewer = viewer;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
	 */
	@Override
	public void inputChanged(Viewer v, Object oldInput, Object newInput) {
		try {
			if (newInput instanceof TableRenderingContentInput)
			{
				fInput = (TableRenderingContentInput)newInput;
				if (fInput.getMemoryBlock() instanceof IMemoryBlockExtension) {
					loadContentForExtendedMemoryBlock();
				} else {
					loadContentForSimpleMemoryBlock();
				}

				// tell rendering to display table if the loading is successful
				getTableRendering(fInput).displayTable();
			}
		} catch (DebugException e) {
			getTableRendering(fInput).displayError(e);
		}
	}

	@Override
	public void dispose() {
		DebugPlugin.getDefault().removeDebugEventListener(this);
		super.dispose();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
	 */
	@Override
	public Object[] getElements(Object parent) {

		// if cache is empty, get memory
		if (lineCache.isEmpty()) {

			try {
				getMemoryFromMemoryBlock();
			} catch (DebugException e) {
				DebugUIPlugin.log(e.getStatus());
				getTableRendering(fInput).displayError(e);
				return lineCache.toArray();
			}
		}

		if (lineCache.isEmpty()) {
			return lineCache.toArray();
		}

		// check to see if the row size has changed
		TableRenderingLine line = lineCache.get(0);
		int currentRowSize = line.getByteArray().length;
		int renderingRowSize = getTableRendering(fInput).getBytesPerLine();

		if (renderingRowSize != currentRowSize)
		{
			try {
				reorganizeContentCache(renderingRowSize);
				reorganizeLines(lineCache, renderingRowSize);
			} catch (DebugException e) {
				DebugUIPlugin.log(e.getStatus());
				getTableRendering(fInput).displayError(e);
				return lineCache.toArray();
			}
		}
		return lineCache.toArray();
	}

	private void getMemoryFromMemoryBlock() throws DebugException {
		IMemoryBlock memoryBlock = fInput.getMemoryBlock();
		if (memoryBlock instanceof IMemoryBlockExtension)
		{
			loadContentForExtendedMemoryBlock();
			getTableRendering(fInput).displayTable();
		}
		else
		{
			loadContentForSimpleMemoryBlock();
			getTableRendering(fInput).displayTable();
		}
	}

	/**
	 * @throws DebugException
	 */
	public void loadContentForSimpleMemoryBlock() throws DebugException {
		// get as much memory as the memory block can handle
		fInput.setPreBuffer(0);
		fInput.setPostBuffer(0);
		long startAddress = fInput.getMemoryBlock().getStartAddress();
		BigInteger address = BigInteger.valueOf(startAddress);
		long length = fInput.getMemoryBlock().getLength();
		long numLines = length / getTableRendering(fInput).getBytesPerLine();
		getMemoryToFitTable(address, numLines, fInput.isUpdateDelta());
	}

	/**
	 * @throws DebugException
	 */
	public void loadContentForExtendedMemoryBlock() throws DebugException {

		// do not load if number of lines needed is < 0
		if (fInput.getNumLines() <= 0) {
			return;
		}

		// calculate top buffered address
		BigInteger loadAddress = fInput.getLoadAddress();
		if (loadAddress == null)
		{
			loadAddress = new BigInteger("0"); //$NON-NLS-1$
		}

		BigInteger mbStart = fInput.getStartAddress();
		BigInteger mbEnd = fInput.getEndAddress();

		// check that the load address is within range
		if (loadAddress.compareTo(mbStart) < 0 || loadAddress.compareTo(mbEnd) > 0)
		{
			// default load address to memory block base address
			loadAddress = ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress();
			fInput.setLoadAddress(loadAddress);
		}

		// if address is still out of range, throw an exception
		if (loadAddress.compareTo(mbStart) < 0 || loadAddress.compareTo(mbEnd) > 0)
		{
			throw new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.TableRenderingContentProvider_0 + loadAddress.toString(16), null));
		}

		int addressableUnitsPerLine = getTableRendering(fInput).getAddressableUnitPerLine();
		BigInteger bufferStart = loadAddress.subtract(BigInteger.valueOf(fInput.getPreBuffer()*addressableUnitsPerLine));
		BigInteger bufferEnd = loadAddress.add(BigInteger.valueOf(fInput.getPostBuffer()*addressableUnitsPerLine));
		bufferEnd = bufferEnd.add(BigInteger.valueOf(fInput.getNumLines()*addressableUnitsPerLine));

		if (isDynamicLoad())
		{
			if (bufferStart.compareTo(mbStart) < 0) {
				bufferStart = mbStart;
			}

			if (bufferEnd.compareTo(mbEnd) > 0)
			{
				bufferEnd = mbEnd;

				int numLines = bufferEnd.subtract(bufferStart).divide(BigInteger.valueOf(addressableUnitsPerLine)).intValue();
				if (numLines < fInput.getNumLines())
				{
					// re-calculate buffer start since we may not have enough lines to popoulate the view
					bufferStart = bufferEnd.subtract(BigInteger.valueOf(fInput.getNumLines()*addressableUnitsPerLine));
					bufferStart = bufferStart.subtract(BigInteger.valueOf(fInput.getPreBuffer()*addressableUnitsPerLine));
				}

				// if after adjusting buffer start, it goes before the memory block start
				// address, adjust it back
				if (bufferStart.compareTo(mbStart) < 0) {
					bufferStart = mbStart;
				}
			}

			// buffer end must be greater than buffer start
			if (bufferEnd.compareTo(bufferStart) <= 0) {
				throw new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.TableRenderingContentProvider_1, null));
			}

			int numLines = bufferEnd.subtract(bufferStart).divide(BigInteger.valueOf(addressableUnitsPerLine)).intValue()+1;
			// get stoarage to fit the memory view tab size
			getMemoryToFitTable(bufferStart, numLines, fInput.isUpdateDelta());
		}
		else
		{
			if (bufferStart.compareTo(mbStart) < 0) {
				bufferStart = mbStart;
			}

			if (bufferEnd.compareTo(mbEnd) > 0)
			{
				bufferStart = mbEnd.subtract(BigInteger.valueOf((fInput.getNumLines()-1)*addressableUnitsPerLine));
				bufferEnd = mbEnd;

				// after adjusting buffer start, check if it's smaller than memory block's start address
				if (bufferStart.compareTo(mbStart) < 0) {
					bufferStart = mbStart;
				}
			}

			// buffer end must be greater than buffer start
			if (bufferEnd.compareTo(bufferStart) <= 0) {
				throw new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.TableRenderingContentProvider_2, null));
			}

			int numLines = fInput.getNumLines();
			int bufferNumLines = bufferEnd.subtract(bufferStart).divide(BigInteger.valueOf(addressableUnitsPerLine)).intValue()+1;

			if (bufferNumLines < numLines) {
				numLines = bufferNumLines;
			}

			// get stoarage to fit the memory view tab size
			getMemoryToFitTable(bufferStart, numLines, fInput.isUpdateDelta());
		}
	}

	/**
	 * @return the memroy block
	 */
	public IMemoryBlock getMemoryBlock() {
		return fInput.getMemoryBlock();
	}

	/**
	 * Get memory to fit table
	 * @param startingAddress
	 * @param numberOfLines
	 * @param updateDelta
	 * @throws DebugException
	 */
	public void getMemoryToFitTable(BigInteger startingAddress, long numberOfLines, boolean updateDelta) throws DebugException
	{
		// do not ask for memory from memory block if the debug target
		// is already terminated
		IDebugTarget target = fInput.getMemoryBlock().getDebugTarget();

		if (target.isDisconnected() || target.isTerminated()) {
			return;
		}

		DebugException dbgEvt = null;

		// calculate address size
		String adjustedAddress = startingAddress.toString(16);

		int addressSize;
		try {
			addressSize = getAddressSize(startingAddress);
		} catch (DebugException e1) {
			dbgEvt = e1;
			addressSize = 4;
		}

		int addressLength = addressSize * IInternalDebugUIConstants.CHAR_PER_BYTE;

		// align to the closest boundary based on addressable size per line
		if ( getMemoryBlock() instanceof IMemoryBlockExtension)
		{
			startingAddress = MemoryViewUtil.alignToBoundary(startingAddress, getTableRendering(fInput).getAddressableUnitPerLine());
		}

		IMemoryBlockExtension extMemoryBlock = null;
		MemoryByte[] memoryBuffer = null;

		String paddedString = DebugUIPlugin.getDefault().getPreferenceStore().getString(IDebugUIConstants.PREF_PADDED_STR);

		long reqNumBytes = 0;
		try
		{
			if (fInput.getMemoryBlock() instanceof IMemoryBlockExtension)
			{
				reqNumBytes = getTableRendering(fInput).getBytesPerLine() * numberOfLines;
				// get memory from memory block
				extMemoryBlock = (IMemoryBlockExtension) fInput.getMemoryBlock();

				long reqNumberOfUnits = getTableRendering(fInput).getAddressableUnitPerLine() * numberOfLines;

				memoryBuffer =	extMemoryBlock.getBytesFromAddress(startingAddress,	reqNumberOfUnits);

				if(memoryBuffer == null)
				{
					DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.MemoryViewContentProvider_Unable_to_retrieve_content, null));
					throw e;
				}
			}
			else
			{
				// get memory from memory block
				byte[] memory = fInput.getMemoryBlock().getBytes();

				if (memory == null)
				{
					DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.MemoryViewContentProvider_Unable_to_retrieve_content, null));
					throw e;
				}

				int prefillNumBytes = 0;

				// number of bytes need to prefill
				if (!startingAddress.toString(16).endsWith("0")) //$NON-NLS-1$
				{
					adjustedAddress = startingAddress.toString(16).substring(0, adjustedAddress.length() - 1);
					adjustedAddress += "0"; //$NON-NLS-1$
					BigInteger adjustedStart = new BigInteger(adjustedAddress, 16);
					prefillNumBytes = startingAddress.subtract(adjustedStart).intValue();
					startingAddress = adjustedStart;
				}
				reqNumBytes = fInput.getMemoryBlock().getLength() + prefillNumBytes;

				// figure out number of dummy bytes to append
				while (reqNumBytes % getTableRendering(fInput).getBytesPerLine() != 0)
				{
					reqNumBytes ++;
				}

				numberOfLines = reqNumBytes / getTableRendering(fInput).getBytesPerLine();

				// create memory byte for IMemoryBlock
				memoryBuffer = new MemoryByte[(int)reqNumBytes];

				// prefill buffer to ensure double-word alignment
				for (int i=0; i<prefillNumBytes; i++)
				{
					MemoryByte tmp = new MemoryByte();
					tmp.setValue((byte)0);
					tmp.setWritable(false);
					tmp.setReadable(false);
					tmp.setEndianessKnown(false);
					memoryBuffer[i] = tmp;
				}

				// fill buffer with memory returned by debug adapter
				int j = prefillNumBytes; 							// counter for memoryBuffer
				for (int i=0; i<memory.length; i++)
				{
					MemoryByte tmp = new MemoryByte();
					tmp.setValue(memory[i]);
					tmp.setReadable(true);
					tmp.setWritable(true);
					tmp.setEndianessKnown(false);
					memoryBuffer[j] = tmp;
					j++;
				}

				// append to buffer to fill up the entire line
				for (int i=j; i<memoryBuffer.length; i++)
				{
					MemoryByte tmp = new MemoryByte();
					tmp.setValue((byte)0);
					tmp.setWritable(false);
					tmp.setReadable(false);
					tmp.setEndianessKnown(false);
					memoryBuffer[i] = tmp;
				}
			}
		}
		catch (DebugException e)
		{
			memoryBuffer = makeDummyContent(numberOfLines);

			// finish creating the content provider before throwing an event
			dbgEvt = e;
		}
		catch (Throwable e)
		{
			// catch all errors from this process just to be safe
			memoryBuffer = makeDummyContent(numberOfLines);

			// finish creating the content provider before throwing an event
			dbgEvt = new DebugException(DebugUIPlugin.newErrorStatus(e.getMessage(), e));
		}

		// if debug adapter did not return enough memory, create dummy memory
		if (memoryBuffer.length < reqNumBytes)
		{
			ArrayList<MemoryByte> newBuffer = new ArrayList<MemoryByte>();

			for (int i=0; i<memoryBuffer.length; i++)
			{
				newBuffer.add(memoryBuffer[i]);
			}

			for (int i=memoryBuffer.length; i<reqNumBytes; i++)
			{
				MemoryByte mb = new MemoryByte();
				mb.setReadable(false);
				mb.setWritable(false);
				mb.setEndianessKnown(false);
				newBuffer.add(mb);
			}

			memoryBuffer = newBuffer.toArray(new MemoryByte[newBuffer.size()]);

		}

		// clear line cache
		if (!lineCache.isEmpty())
		{
			lineCache.clear();
		}
		String address = startingAddress.toString(16);
		// save address of the top of buffer
		fBufferTopAddress = startingAddress;

		boolean manageDelta = true;

		// If change information is not managed by the memory block
		// The view tab will manage it and calculate delta information
		// for its content cache.
		if (fInput.getMemoryBlock() instanceof IMemoryBlockExtension)
		{
			manageDelta = !((IMemoryBlockExtension)fInput.getMemoryBlock()).supportsChangeManagement();
		}

		// put memory information into MemoryViewLine
		organizeLines(numberOfLines, updateDelta, addressLength, memoryBuffer, paddedString, address, manageDelta);

		if (dbgEvt != null){
			throw dbgEvt;
		}
	}

	private void organizeLines(long numberOfLines, boolean updateDelta, int addressLength, MemoryByte[] memoryBuffer, String paddedString, String address, boolean manageDelta)
	{
		for (int i = 0; i < numberOfLines; i++)
		{   //chop the raw memory up
			String tmpAddress = address.toUpperCase();
			if (tmpAddress.length() < addressLength)
			{
				while  (tmpAddress.length() < addressLength)
				{
					tmpAddress = "0" + tmpAddress; //$NON-NLS-1$
				}
			}
			int bytesPerLine = getTableRendering(fInput).getBytesPerLine();
			MemoryByte[] memory = new MemoryByte[bytesPerLine];
			boolean isMonitored = true;

			// counter for memory, starts from 0 to number of bytes per line
			int k = 0;
			// j is the counter for memArray, memory returned by debug adapter
			for (int j = i * bytesPerLine;
				j < i * bytesPerLine + bytesPerLine;
				j++)
			{

				byte changeFlag = memoryBuffer[j].getFlags();
				if (manageDelta)
				{
					// turn off both change and known bits to make sure that
					// the change bits returned by debug adapters do not take
					// any effect

					changeFlag |= MemoryByte.HISTORY_KNOWN;
					changeFlag ^= MemoryByte.HISTORY_KNOWN;

					changeFlag |= MemoryByte.CHANGED;
					changeFlag ^= MemoryByte.CHANGED;
				}

				MemoryByte newByteObj = new MemoryByte(memoryBuffer[j].getValue(), changeFlag);
				memory[k] =  newByteObj;
				k++;


				if (!manageDelta)
				{
					// If the byte is marked as unknown, the line is not monitored
					if (!memoryBuffer[j].isHistoryKnown())
					{
						isMonitored = false;
					}
				}
			}

			TableRenderingLine newLine = new TableRenderingLine(tmpAddress, memory, lineCache.size(), paddedString);

			TableRenderingLine oldLine = contentCache.get(newLine.getAddress());

			if (manageDelta)
			{
				if (oldLine != null) {
					newLine.isMonitored = true;
				} else {
					newLine.isMonitored = false;
				}
			}
			else
			{
				// check the byte for information
				newLine.isMonitored = isMonitored;
			}

			// calculate delta info for the memory view line
			if (manageDelta && !getTableRendering(fInput).isDisplayingError())
			{
				if (updateDelta)
				{
					if (oldLine != null)
					{
						newLine.markDeltas(oldLine);
					}
				}
				else
				{
					if (oldLine != null)
					{
						// deltas can only be reused if the line has not been changed
						// otherwise, force a refresh
						if (newLine.isLineChanged(oldLine))
						{
							newLine.markDeltas(oldLine);
						}
						else
						{
							newLine.copyDeltas(oldLine);
						}
					}
				}
			}
			else if (manageDelta && getTableRendering(fInput).isDisplayingError())
			{
				// show as unmonitored if the view tab is previoulsy displaying error
				newLine.isMonitored = false;
			}
			lineCache.add(newLine);


			// increment row address
			BigInteger bigInt = new BigInteger(address, 16);
			fBufferEndAddress = bigInt;
			int addressableUnit = getTableRendering(fInput).getBytesPerLine()/getTableRendering(fInput).getAddressableSize();
			address = bigInt.add(BigInteger.valueOf(addressableUnit)).toString(16);
		}
	}

	/**
	 * @param numberOfLines
	 * @return an array of dummy MemoryByte
	 */
	private MemoryByte[] makeDummyContent(long numberOfLines) {
		MemoryByte[] memoryBuffer;
		// make up dummy memory, needed for recovery in case the debug adapter
		// is capable of retrieving memory again

		int numBytes = (int)(getTableRendering(fInput).getBytesPerLine() * numberOfLines);
		memoryBuffer = new MemoryByte[numBytes];

		for (int i=0; i<memoryBuffer.length; i++){
			memoryBuffer[i] = new MemoryByte();
			memoryBuffer[i].setValue((byte)0);
			memoryBuffer[i].setWritable(false);
			memoryBuffer[i].setReadable(false);
			memoryBuffer[i].setEndianessKnown(false);
		}
		return memoryBuffer;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.ui.internal.views.BasicDebugViewContentProvider#doHandleDebugEvent(org.eclipse.debug.core.DebugEvent)
	 */
	@Override
	protected void doHandleDebugEvent(DebugEvent event) {

		if (getTableRendering(fInput).isVisible())
		{
			// only do this if it's visible
			// still need to clear content cache if the rendering
			// is not visible
			if (isUpdateManagedByMB()) {
				return;
			}
		}

		// do nothing if the debug event did not come from a debug element comes from non-debug element
		if (!(event.getSource() instanceof IDebugElement)) {
			return;
		}

		// do not try to recover if the content input has not been created
		if (fInput == null) {
			return;
		}

		IDebugElement src = (IDebugElement)event.getSource();

		// if a debug event happens from the memory block
		// invoke contentChanged to get content of the memory block updated
		if (event.getKind() == DebugEvent.CHANGE && event.getSource() == fInput.getMemoryBlock())
		{
			if (event.getDetail() == DebugEvent.STATE){
				getTableRendering(fInput).updateLabels();
			}
			else
			{
				updateContent();
			}
		}

		// if the suspend evnet happens from the debug target that the
		// memory block belongs to
		if (event.getKind() == DebugEvent.SUSPEND && src.getDebugTarget() == fInput.getMemoryBlock().getDebugTarget())
		{
			updateContent();
		}

	}

	/**
	 * Update content of the view tab if the content of the memory block has changed
	 * or if its base address has changed
	 * Update will not be performed if the memory block has not been changed or
	 * if the rendering is not visible
	 */
	public void updateContent()
	{
		IDebugTarget dt = fInput.getMemoryBlock().getDebugTarget();

		// no need to update if debug target is disconnected or terminated
		if (dt.isDisconnected() || dt.isTerminated())
		{
			return;
		}

		takeContentSnapshot();

		//do not handle event if the rendering is not visible
		if (!getTableRendering(fInput).isVisible()) {
			return;
		}

		getTableRendering(fInput).refresh();

	}

	/**
	 *  Take a snapshot on the content, marking the lines as monitored
	 */
	public void takeContentSnapshot()
	{
		// cache content before getting new ones
		TableRenderingLine[] lines =lineCache.toArray(new TableRenderingLine[lineCache.size()]);
		fContentCacheInBytes = convertLinesToBytes(lines);
		fContentCacheStartAddress = lines[0].getAddress();

		if (contentCache != null)
		{
			contentCache.clear();
		}

		//do not handle event if the rendering is not visible
		if (!getTableRendering(fInput).isVisible()) {
			return;
		}

		// use existing lines as cache is the rendering is not currently displaying
		// error.  Otherwise, leave contentCache empty as we do not have updated
		// content.
		if (!getTableRendering(fInput).isDisplayingError())
		{
			for (int i=0; i<lines.length; i++)
			{
				contentCache.put(lines[i].getAddress(), lines[i]);
				lines[i].isMonitored = true;
			}
		}

		// reset all the deltas currently stored in contentCache
		// This will ensure that changes will be recomputed when user scrolls
		// up or down the memory view.
		resetDeltas();
	}

	/**
	 * @return buffer's top address
	 */
	public BigInteger getBufferTopAddress()
	{
		return fBufferTopAddress;
	}

	public BigInteger getBufferEndAddress()
	{
		return fBufferEndAddress;
	}

	/**
	 * Calculate address size of the given address
	 * @param address
	 * @return size of address from the debuggee
	 */
	public int getAddressSize(BigInteger address) throws DebugException
	{
		// calculate address size
		 String adjustedAddress = address.toString(16);

		 int addressSize = 0;
		 if (fInput.getMemoryBlock() instanceof IMemoryBlockExtension)
		 {
			 addressSize = ((IMemoryBlockExtension)fInput.getMemoryBlock()).getAddressSize();
		 }

		 // handle IMemoryBlock and invalid address size returned by IMemoryBlockExtension
		 if (addressSize <= 0)
		 {
			 if (adjustedAddress.length() > 8)
			 {
				 addressSize = 8;
			 }
			 else
			 {
				 addressSize = 4;
			 }
		 }

		 return addressSize;
	}

	/**
	 * @return base address of memory block
	 */
	public BigInteger getContentBaseAddress()
	{
		return fInput.getContentBaseAddress();
	}

	/**
	 * Clear all delta information in the lines
	 */
	public void resetDeltas()
	{
		Enumeration<TableRenderingLine> enumeration = contentCache.elements();

		while (enumeration.hasMoreElements())
		{
			TableRenderingLine line = enumeration.nextElement();
			line.unmarkDeltas();
		}
	}

	/**
	 * Check if address is out of buffered range
	 * @param address
	 * @return true if address is out of bufferred range, false otherwise
	 */
	public boolean isAddressOutOfRange(BigInteger address)
	{
		if (lineCache != null && !lineCache.isEmpty())
		{
			TableRenderingLine first = lineCache.firstElement();
			TableRenderingLine last = lineCache.lastElement();

			if (first == null ||last == null) {
				return true;
			}

			BigInteger startAddress = new BigInteger(first.getAddress(), 16);
			BigInteger lastAddress = new BigInteger(last.getAddress(), 16);
			int addressableUnit = getTableRendering(fInput).getAddressableUnitPerLine();
			lastAddress = lastAddress.add(BigInteger.valueOf(addressableUnit)).subtract(BigInteger.valueOf(1));

			if (startAddress.compareTo(address) <= 0 &&
				lastAddress.compareTo(address) >= 0)
			{
				return false;
			}
			return true;
		}
		return true;
	}

	public void clearContentCache()
	{
		fContentCacheInBytes = new MemoryByte[0];
		fContentCacheStartAddress = null;
		contentCache.clear();
	}

	/**
	 * @return if the memory block would manage its own update.
	 */
	private boolean isUpdateManagedByMB()
	{
		IMemoryBlock memoryBlock = getMemoryBlock();

		IMemoryRenderingUpdater managedMB = null;
		if (memoryBlock instanceof IMemoryRenderingUpdater)
		{
			managedMB = (IMemoryRenderingUpdater)memoryBlock;
		}

		if (managedMB == null) {
			managedMB = memoryBlock.getAdapter(IMemoryRenderingUpdater.class);
		}

		// do not handle event if if the memory block wants to do its
		// own update
		if (managedMB != null && managedMB.supportsManagedUpdate(getTableRendering(fInput))) {
			return true;
		}

		return false;
	}

	public boolean isDynamicLoad()
	{
		return fDynamicLoad;
	}

	private void initializeDynamicLoad()
	{
		fDynamicLoad = DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM);
	}

	public void setDynamicLoad(boolean dynamicLoad)
	{
		fDynamicLoad = dynamicLoad;
	}

	private void reorganizeLines(Vector<TableRenderingLine> lines, int numBytesPerLine) throws DebugException
	{
		if (lines == null || lines.isEmpty()) {
			return;
		}

		Object[] objs = lines.toArray();

		if (objs.length > 0)
		{
			TableRenderingLine[] renderingLines = lines.toArray(new TableRenderingLine[lines.size()]);
			MemoryByte[] buffer = convertLinesToBytes(renderingLines);
			BigInteger lineAddress = new BigInteger(renderingLines[0].getAddress(), 16);
			int numberOfLines = buffer.length / numBytesPerLine;
			boolean updateDelta = false;
			int addressLength = getAddressSize(lineAddress) * IInternalDebugUIConstants.CHAR_PER_BYTE;
			MemoryByte[] memoryBuffer = buffer;
			String address =renderingLines[0].getAddress();
			String paddedString = DebugUITools.getPreferenceStore().getString(IDebugUIConstants.PREF_PADDED_STR);

			// set to false to preserve information delta information
			boolean manageDelta = true;

			// If change information is not managed by the memory block
			// The view tab will manage it and calculate delta information
			// for its content cache.
			if (fInput.getMemoryBlock() instanceof IMemoryBlockExtension)
			{
				manageDelta = !((IMemoryBlockExtension)fInput.getMemoryBlock()).supportsChangeManagement();
			}
			lineCache.clear();

			organizeLines(numberOfLines, updateDelta, addressLength, memoryBuffer, paddedString, address, manageDelta);
		}
	}

	private void reorganizeContentCache(int bytesPerLine)
	{
		// if content cache is empty, do nothing
		if (contentCache == null || contentCache.isEmpty()
			|| fContentCacheInBytes.length == 0 || fContentCacheStartAddress == null) {
			return;
		}

		MemoryByte[] bytes = fContentCacheInBytes;
		TableRenderingLine[] convertedLines = convertBytesToLines(bytes, bytesPerLine, new BigInteger(fContentCacheStartAddress, 16));

		contentCache.clear();
		for (int i=0; i<convertedLines.length; i++)
		{
			contentCache.put(convertedLines[i].getAddress(), convertedLines[i]);
		}
	}

	private MemoryByte[] convertLinesToBytes(TableRenderingLine[] lines)
	{
		// convert the lines back to a buffer of MemoryByte
		TableRenderingLine temp = lines[0];
		int lineLength = temp.getLength();

		MemoryByte[] buffer = new MemoryByte[lines.length * lineLength];
		for (int i=0; i<lines.length; i++)
		{
			TableRenderingLine line = lines[i];
			MemoryByte[] bytes = line.getBytes();
			System.arraycopy(bytes, 0, buffer, i*lineLength, lineLength);
		}
		return buffer;
	}

	private TableRenderingLine[] convertBytesToLines(MemoryByte[] bytes, int bytesPerLine, BigInteger startAddress)
	{
		int numOfLines = bytes.length / bytesPerLine;
		String address = startAddress.toString(16);
		int addressLength;
		try {
			addressLength = getAddressSize(startAddress) * IInternalDebugUIConstants.CHAR_PER_BYTE;
		} catch (DebugException e) {
			DebugUIPlugin.log(e);
			addressLength = 4 * IInternalDebugUIConstants.CHAR_PER_BYTE;
		}
		ArrayList<TableRenderingLine> lines = new ArrayList<TableRenderingLine>();
		String paddedString = DebugUITools.getPreferenceStore().getString(IDebugUIConstants.PREF_PADDED_STR);

		for (int i=0; i<numOfLines; i++)
		{
			MemoryByte[] temp = new MemoryByte[bytesPerLine];
			System.arraycopy(bytes, i*bytesPerLine, temp, 0, bytesPerLine);

			String tmpAddress = address.toUpperCase();
			if (tmpAddress.length() < addressLength)
			{
				while (tmpAddress.length() < addressLength)
				{
					tmpAddress = "0" + tmpAddress; //$NON-NLS-1$
				}
			}

			TableRenderingLine newLine = new TableRenderingLine(tmpAddress, temp, lines.size(), paddedString);
			lines.add(newLine);

			// increment row address
			BigInteger bigInt = new BigInteger(address, 16);
			fBufferEndAddress = bigInt;
			int addressableUnit = getTableRendering(fInput).getBytesPerLine()/getTableRendering(fInput).getAddressableSize();
			address = bigInt.add(BigInteger.valueOf(addressableUnit)).toString(16);
		}

		return lines.toArray(new TableRenderingLine[lines.size()]);
	}

	private AbstractTableRendering getTableRendering(TableRenderingContentInput input)
	{
		return input.getAdapter(AbstractTableRendering.class);
	}
}
