1 11 12 package org.eclipse.debug.internal.ui.views.memory.renderings; 13 14 import java.math.BigInteger ; 15 import java.util.ArrayList ; 16 import java.util.Enumeration ; 17 import java.util.Hashtable ; 18 import java.util.List ; 19 import java.util.Vector ; 20 21 import org.eclipse.core.runtime.Assert; 22 import org.eclipse.core.runtime.IProgressMonitor; 23 import org.eclipse.core.runtime.IStatus; 24 import org.eclipse.core.runtime.Status; 25 import org.eclipse.core.runtime.jobs.Job; 26 import org.eclipse.debug.core.model.IMemoryBlock; 27 import org.eclipse.debug.core.model.IMemoryBlockExtension; 28 import org.eclipse.debug.core.model.MemoryByte; 29 import org.eclipse.debug.internal.ui.memory.provisional.AbstractAsyncTableRendering; 30 import org.eclipse.debug.internal.ui.memory.provisional.MemoryViewPresentationContext; 31 import org.eclipse.debug.internal.ui.viewers.AsynchronousTableViewer; 32 import org.eclipse.debug.internal.ui.viewers.ModelNode; 33 import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil; 34 import org.eclipse.debug.ui.memory.IMemoryRendering; 35 36 37 public class TableRenderingModel extends AbstractVirtualContentTableModel 38 implements IContentChangeComputer { 39 40 41 private Hashtable fCache; 42 private Vector fOrderedCache; 44 private boolean fMBSupportsChangeManagement; 45 private IMemoryBlock fMemoryBlock; 46 47 class SupportsChangeMgmtJob extends Job { 48 49 SupportsChangeMgmtJob() 50 { 51 super("Support Change Management"); setSystem(true); 53 } 54 55 protected IStatus run(IProgressMonitor monitor) { 56 IMemoryBlock mb = getMemoryBlock(); 57 if (mb instanceof IMemoryBlockExtension) 58 { 59 IMemoryBlockExtension mbExt = (IMemoryBlockExtension)mb; 60 fMBSupportsChangeManagement = mbExt.supportsChangeManagement(); 61 } 62 return Status.OK_STATUS; 63 } 64 65 } 66 67 68 public TableRenderingModel(AsynchronousTableViewer viewer) { 69 super(viewer); 70 fCache = new Hashtable (); 71 fOrderedCache = new Vector (); 72 } 73 74 public int indexOfKey(Object key) 75 { 76 if (key instanceof BigInteger ) 77 { 78 BigInteger address = (BigInteger )key; 79 Object items[] = getElements(); 80 81 for (int i=0; i<items.length; i++){ 82 if (items[i] != null && items[i] instanceof MemorySegment) 83 { 84 MemorySegment line = (MemorySegment)items[i]; 85 if (line.containsAddress(address)) 86 return i; 87 } 88 } 89 } 90 91 return -1; 92 } 93 94 public int columnOf(Object element, Object key) 95 { 96 if (element instanceof MemorySegment && key instanceof BigInteger ) 97 { 98 BigInteger address = (BigInteger )key; 99 MemorySegment line = (MemorySegment)element; 100 if (line.containsAddress(address)) 101 { 102 if (getAddressableUnitsPerColumn() > 0) 103 { 104 BigInteger offset = address.subtract(line.getAddress()); 105 106 int colAddressableUnit = getAddressableUnitsPerColumn(); 108 int col = ((offset.intValue()/colAddressableUnit)+1); 109 110 if (col == 0) 111 col = 1; 112 113 return col; 114 } 115 } 116 } 117 118 return -1; 119 } 120 121 public Object getKey(int idx) 122 { 123 Object elmt = getElement(idx); 124 if (elmt instanceof MemorySegment) 125 { 126 return ((MemorySegment)elmt).getAddress(); 127 } 128 129 return null; 130 } 131 132 public Object getKey(Object element) { 133 int idx = indexOfElement(element); 134 if (idx >= 0) 135 { 136 return getKey(idx); 137 } 138 return null; 139 } 140 141 public Object getKey(int idx, int col) { 142 Object element = getElement(idx); 143 if (element != null && element instanceof MemorySegment) 144 { 145 MemorySegment segment = (MemorySegment)element; 146 BigInteger rowAddress = segment.getAddress(); 147 148 int offset; 149 if (col > 0) 150 { 151 int addressableUnit = getAddressableUnitsPerColumn(); 153 offset = (col-1) * addressableUnit; 154 } 155 else 156 { 157 offset = 0; 158 } 159 return rowAddress.add(BigInteger.valueOf(offset)); 160 } 161 return null; 162 } 163 164 private int getAddressableUnitsPerColumn() 165 { 166 AsynchronousTableViewer viewer = getTableViewer(); 167 if (viewer.getPresentationContext() instanceof MemoryViewPresentationContext) 168 { 169 MemoryViewPresentationContext context = (MemoryViewPresentationContext)viewer.getPresentationContext(); 170 if (getTableRendering(context)!= null) 171 { 172 return getTableRendering(context).getAddressableUnitPerColumn(); 173 } 174 } 175 return -1; 176 } 177 178 public void cache(Object [] elements) { 179 for (int i=0; i<elements.length; i++) 180 { 181 Object obj = elements[i]; 182 if (obj instanceof MemorySegment) 183 { 184 cache(((MemorySegment)obj).getAddress(), obj); 185 } 186 } 187 188 } 189 190 private void cache(Object key, Object element) 191 { 192 fCache.put(key, element); 193 fOrderedCache.add(element); 194 } 195 196 public Object [] compare(Object [] newElements) { 197 198 if (fCache.isEmpty()) 199 return newElements; 200 201 for (int j=0; j<newElements.length; j++) 202 { 203 Object obj = newElements[j]; 204 if (obj instanceof MemorySegment) 205 { 206 MemorySegment newSegment = (MemorySegment)obj; 207 MemorySegment oldSegment = (MemorySegment)fCache.get(newSegment.getAddress()); 208 209 if (oldSegment != null) 210 { 211 if (oldSegment.getNumAddressableUnits() == newSegment.getNumAddressableUnits()) 212 { 213 MemoryByte[] newBytes = newSegment.getBytes(); 214 MemoryByte[] oldBytes = oldSegment.getBytes(); 215 216 for (int i=0; i<newBytes.length; i++) 217 { 218 newBytes[i].setHistoryKnown(true); 219 220 if (newBytes[i].isReadable() != oldBytes[i].isReadable()) 221 { 222 newBytes[i].setChanged(true); 223 continue; 224 } 225 226 if (newBytes[i].isReadable() && oldBytes[i].isReadable() && 227 (newBytes[i].getValue() != oldBytes[i].getValue())) 228 newBytes[i].setChanged(true); 229 } 230 } 231 } 232 } 233 } 234 return newElements; 235 } 236 237 public void clearCache() 238 { 239 fCache.clear(); 240 fOrderedCache.clear(); 241 } 242 243 public boolean isEmpty() { 244 return fCache.isEmpty(); 245 } 246 247 public void handleViewerChanged() { 248 rebuildCache(); 250 rebuildContent(); 251 } 252 253 private void rebuildCache() 254 { 255 if (isEmpty()) 256 return; 257 258 MemoryViewPresentationContext context = (MemoryViewPresentationContext)getTableViewer().getPresentationContext(); 259 AbstractAsyncTableRendering rendering = getTableRendering(context); 260 261 if (rendering == null) 262 return; 263 264 ArrayList segments = new ArrayList (); 265 Enumeration enumeration = fOrderedCache.elements(); 266 267 BigInteger address = ((MemorySegment)fOrderedCache.get(0)).getAddress(); 268 while (enumeration.hasMoreElements()) 269 { 270 Object element = enumeration.nextElement(); 271 if (element instanceof MemorySegment) 272 { 273 274 segments.add(element); 275 } 276 } 277 278 MemoryByte[] bytes = convertSegmentsToBytes((MemorySegment[])segments.toArray(new MemorySegment[0])); 279 280 int bytesPerLine = rendering.getBytesPerLine(); 281 int numAddressableUnitPerLine = rendering.getAddressableUnitPerLine(); 282 283 int addressableSize = rendering.getAddressableSize(); 284 285 clearCache(); 286 287 TableRenderingContentDescriptor descriptor = (TableRenderingContentDescriptor)rendering.getAdapter(TableRenderingContentDescriptor.class); 288 boolean alignAddress = true; 289 if (descriptor != null && !descriptor.isAlignAddressToBoundary()) 290 { 291 alignAddress = descriptor.isAlignAddressToBoundary(); 292 } 293 294 MemorySegment[] newSegments = convertMemoryBytesToSegments(address, bytes, bytesPerLine, numAddressableUnitPerLine, addressableSize, alignAddress); 295 for (int i=0; i<newSegments.length; i++) 296 { 297 cache(newSegments[i].getAddress(), newSegments[i]); 298 } 299 } 300 301 private void rebuildContent() 302 { 303 MemoryViewPresentationContext context = (MemoryViewPresentationContext)getTableViewer().getPresentationContext(); 304 AbstractAsyncTableRendering rendering = getTableRendering(context); 305 306 if (rendering == null) 307 return; 308 309 ArrayList segments = new ArrayList (); 310 Object [] elements = getElements(); 311 for (int i=0; i<elements.length; i++) 312 { 313 Object element = elements[i]; 314 if (element instanceof MemorySegment) 315 { 316 segments.add(element); 317 } 318 } 319 320 MemoryByte[] bytes = convertSegmentsToBytes((MemorySegment[])segments.toArray(new MemorySegment[segments.size()])); 321 322 int bytesPerLine = rendering.getBytesPerLine(); 323 int numAddressableUnitPerLine = rendering.getAddressableUnitPerLine(); 324 BigInteger address = (BigInteger )getKey(0); 325 326 int addressableSize = rendering.getAddressableSize(); 327 328 TableRenderingContentDescriptor descriptor = (TableRenderingContentDescriptor)rendering.getAdapter(TableRenderingContentDescriptor.class); 329 boolean alignAddress = true; 330 if (descriptor != null && !descriptor.isAlignAddressToBoundary()) 331 { 332 alignAddress = descriptor.isAlignAddressToBoundary(); 333 } 334 335 MemorySegment[] newSegments = convertMemoryBytesToSegments(address, bytes, bytesPerLine, numAddressableUnitPerLine, addressableSize, alignAddress); 336 remove(getElements()); 337 add(newSegments); 338 } 339 340 341 private MemoryByte[] convertSegmentsToBytes(MemorySegment[] segments) 342 { 343 ArrayList toReturn = new ArrayList (); 344 for (int i=0; i<segments.length; i++) 345 { 346 MemoryByte[] temp = segments[i].getBytes(); 347 for (int j=0; j<temp.length; j++) 348 { 349 toReturn.add(temp[j]); 350 } 351 } 352 return (MemoryByte[])toReturn.toArray(new MemoryByte[0]); 353 } 354 355 private MemorySegment[] convertMemoryBytesToSegments(BigInteger address, MemoryByte[] bytes, int bytesPerLine, int numAddressableUnitPerLine, int addressableSize, boolean alignAddress) { 356 357 Assert.isTrue(bytesPerLine > 0); 358 Assert.isTrue(numAddressableUnitPerLine > 0); 359 360 ArrayList segments = new ArrayList (); 361 MemoryByte[] temp = bytes; 362 363 if (alignAddress) 364 { 365 BigInteger alignedAddress = MemoryViewUtil.alignToBoundary(address, numAddressableUnitPerLine); 366 367 if (!address.subtract(alignedAddress).equals(BigInteger.ZERO)) 369 { 370 BigInteger unitsToSetBack = address.subtract(alignedAddress); 371 BigInteger tempAddress = address.subtract(unitsToSetBack); 372 if (tempAddress.compareTo(BigInteger.ZERO) >= 0) 375 { 376 address = alignedAddress; 377 int numBytesNeeded = unitsToSetBack.intValue() * addressableSize; 378 temp = new MemoryByte[bytes.length + numBytesNeeded]; 379 380 for (int i=0; i<numBytesNeeded; i++) 381 { 382 temp[i] = new MemoryByte(); 383 temp[i].setReadable(false); 384 temp[i].setWritable(false); 385 temp[i].setEndianessKnown(false); 386 } 387 388 System.arraycopy(bytes, 0, temp, numBytesNeeded, bytes.length); 389 bytes = temp; 390 } 391 } 392 } 393 394 if (bytes.length % bytesPerLine != 0) 395 { 396 int numBytesNeeded = bytesPerLine - (bytes.length % bytesPerLine); 397 temp = new MemoryByte[bytes.length + numBytesNeeded]; 398 System.arraycopy(bytes, 0, temp, 0, bytes.length); 399 400 for (int i=bytes.length; i<temp.length; i++) 401 { 402 temp[i] = new MemoryByte(); 403 temp[i].setReadable(false); 404 temp[i].setWritable(false); 405 temp[i].setEndianessKnown(false); 406 } 407 bytes = temp; 408 } 409 410 int idx = 0; 411 while (idx < bytes.length && (idx + bytesPerLine)<= bytes.length) 412 { 413 MemoryByte[] newBytes = new MemoryByte[bytesPerLine]; 414 System.arraycopy(bytes, idx, newBytes, 0, bytesPerLine); 415 416 MemorySegment segment = new MemorySegment(address, newBytes, numAddressableUnitPerLine); 417 segments.add(segment); 418 419 address = address.add(BigInteger.valueOf(numAddressableUnitPerLine)); 420 idx += bytesPerLine; 421 } 422 423 return (MemorySegment[])segments.toArray(new MemorySegment[segments.size()]); 424 } 425 426 private AsynchronousTableViewer getTableViewer() 427 { 428 return (AsynchronousTableViewer)getViewer(); 429 } 430 431 protected void setChildren(ModelNode parentNode, List kids) { 432 433 if (computeChanges()) 434 { 435 Object [] newContent = compare(kids.toArray()); 436 ArrayList newList = new ArrayList (); 437 for (int i=0; i<newContent.length; i++) 438 { 439 newList.add(newContent[i]); 440 } 441 super.setChildren(parentNode, newList); 442 } 443 else 444 super.setChildren(parentNode, kids); 445 } 446 447 private boolean computeChanges() 448 { 449 if (isEmpty()) 450 return false; 451 452 if (fMBSupportsChangeManagement) 453 { 454 return false; 455 } 456 457 return true; 458 } 459 460 private IMemoryBlock getMemoryBlock() 461 { 462 return fMemoryBlock; 463 } 464 465 466 public void init(Object root) { 467 if (root instanceof IMemoryBlock) 468 { 469 fMemoryBlock = (IMemoryBlock)root; 470 new SupportsChangeMgmtJob().schedule(); 471 } 472 super.init(root); 473 } 474 475 private AbstractAsyncTableRendering getTableRendering(MemoryViewPresentationContext context) 476 { 477 IMemoryRendering memRendering = context.getRendering(); 478 if (memRendering != null && memRendering instanceof AbstractAsyncTableRendering) 479 { 480 return (AbstractAsyncTableRendering)memRendering; 481 } 482 return null; 483 } 484 } 485 | Popular Tags |