/*******************************************************************************
 * Copyright (c) 2004, 2009 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 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 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();
		contentCache = new Hashtable();
		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)
	 */
	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);
		}
	}

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

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
	 */
	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 = (TableRenderingLine)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 newBuffer = new ArrayList();
			
			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 = (MemoryByte[])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)
			{
				for (int j = 0; tmpAddress.length() < addressLength; j++)
				{
					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 = (TableRenderingLine)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)
	 */
	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 =(TableRenderingLine[]) 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 enumeration = contentCache.elements();
		
		while (enumeration.hasMoreElements())
		{
			TableRenderingLine line = (TableRenderingLine)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 = (TableRenderingLine)lineCache.firstElement();
			TableRenderingLine last = (TableRenderingLine) 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 = (IMemoryRenderingUpdater)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 lines, int numBytesPerLine) throws DebugException
	{
		if (lines == null || lines.isEmpty())
			return;
		
		Object[] objs = lines.toArray();
		
		if (objs.length > 0)
		{
			TableRenderingLine[] renderingLines = (TableRenderingLine[])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 lines = new ArrayList();
		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)
			{
				for (int j = 0; tmpAddress.length() < addressLength; j++)
				{
					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 (TableRenderingLine[])lines.toArray(new TableRenderingLine[lines.size()]);
	}
	
	private AbstractTableRendering getTableRendering(TableRenderingContentInput input)
	{
		return (AbstractTableRendering)input.getAdapter(AbstractTableRendering.class);
	}
}
