add explicit event list
This commit is contained in:
parent
6905d96329
commit
1986a8c9c3
|
@ -15,6 +15,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import com.minres.scviewer.database.EventEntry;
|
||||||
import com.minres.scviewer.database.EventKind;
|
import com.minres.scviewer.database.EventKind;
|
||||||
import com.minres.scviewer.database.HierNode;
|
import com.minres.scviewer.database.HierNode;
|
||||||
import com.minres.scviewer.database.IEvent;
|
import com.minres.scviewer.database.IEvent;
|
||||||
|
@ -35,7 +36,7 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
|
||||||
|
|
||||||
private Integer maxConcurrency;
|
private Integer maxConcurrency;
|
||||||
|
|
||||||
private IEventList<Long, IEvent[]> events;
|
private IEventList events;
|
||||||
|
|
||||||
private List<RelationType> usedRelationsList;
|
private List<RelationType> usedRelationsList;
|
||||||
|
|
||||||
|
@ -71,9 +72,9 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IEventList<Long, IEvent[]> getEvents(){
|
public IEventList getEvents(){
|
||||||
if(events==null){
|
if(events==null){
|
||||||
events=new EventList<>();
|
events=new EventList();
|
||||||
for(Entry<Integer, ITx> entry:getTransactions().entrySet()){
|
for(Entry<Integer, ITx> entry:getTransactions().entrySet()){
|
||||||
putEvent(new TxEvent(EventKind.BEGIN, entry.getValue()));
|
putEvent(new TxEvent(EventKind.BEGIN, entry.getValue()));
|
||||||
putEvent(new TxEvent(EventKind.END, entry.getValue()));
|
putEvent(new TxEvent(EventKind.END, entry.getValue()));
|
||||||
|
@ -114,11 +115,11 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IEvent[] getEventsBeforeTime(Long time) {
|
public IEvent[] getEventsBeforeTime(Long time) {
|
||||||
Entry<Long, IEvent[]> e = events.floorEntry(time);
|
EventEntry e = events.floorEntry(time);
|
||||||
if(e==null)
|
if(e==null)
|
||||||
return new IEvent[]{};
|
return new IEvent[]{};
|
||||||
else
|
else
|
||||||
return events.floorEntry(time).getValue();
|
return events.floorEntry(time).events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -14,8 +14,8 @@ package com.minres.scviewer.database.text;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
|
import com.minres.scviewer.database.EventEntry;
|
||||||
import com.minres.scviewer.database.EventList;
|
import com.minres.scviewer.database.EventList;
|
||||||
import com.minres.scviewer.database.HierNode;
|
import com.minres.scviewer.database.HierNode;
|
||||||
import com.minres.scviewer.database.IEvent;
|
import com.minres.scviewer.database.IEvent;
|
||||||
|
@ -39,7 +39,7 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
|
||||||
protected TextDbLoader loader;
|
protected TextDbLoader loader;
|
||||||
|
|
||||||
/** The events. */
|
/** The events. */
|
||||||
IEventList<Long, IEvent[]> events = new EventList<Long, IEvent[]>();
|
IEventList events = new EventList();
|
||||||
|
|
||||||
/** The max concurrency. */
|
/** The max concurrency. */
|
||||||
private int rowCount = -1;
|
private int rowCount = -1;
|
||||||
|
@ -89,7 +89,7 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
|
||||||
* @return the events
|
* @return the events
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public IEventList<Long, IEvent[]> getEvents() {
|
public IEventList getEvents() {
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,11 +112,11 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public IEvent[] getEventsBeforeTime(Long time) {
|
public IEvent[] getEventsBeforeTime(Long time) {
|
||||||
Entry<Long, IEvent[]> e = events.floorEntry(time);
|
EventEntry e = events.floorEntry(time);
|
||||||
if (e == null)
|
if (e == null)
|
||||||
return new IEvent[] {};
|
return new IEvent[] {};
|
||||||
else
|
else
|
||||||
return events.floorEntry(time).getValue();
|
return events.floorEntry(time).events;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -159,8 +159,8 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
|
||||||
return;
|
return;
|
||||||
ArrayList<Long> rowEndTime = new ArrayList<>();
|
ArrayList<Long> rowEndTime = new ArrayList<>();
|
||||||
HashMap<Long, Integer> rowByTxId = new HashMap<>();
|
HashMap<Long, Integer> rowByTxId = new HashMap<>();
|
||||||
for(Entry<Long, IEvent[]> entry: events.entrySet()) {
|
for(EventEntry entry: events) {
|
||||||
for(IEvent evt:entry.getValue()) {
|
for(IEvent evt:entry.events) {
|
||||||
TxEvent txEvt = (TxEvent) evt;
|
TxEvent txEvt = (TxEvent) evt;
|
||||||
ITx tx = txEvt.getTransaction();
|
ITx tx = txEvt.getTransaction();
|
||||||
int rowIdx = 0;
|
int rowIdx = 0;
|
||||||
|
|
|
@ -12,7 +12,6 @@ package com.minres.scviewer.database.ui.swt.internal;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
@ -25,6 +24,7 @@ import org.eclipse.swt.graphics.Rectangle;
|
||||||
|
|
||||||
import com.minres.scviewer.database.BitVector;
|
import com.minres.scviewer.database.BitVector;
|
||||||
import com.minres.scviewer.database.DoubleVal;
|
import com.minres.scviewer.database.DoubleVal;
|
||||||
|
import com.minres.scviewer.database.EventEntry;
|
||||||
import com.minres.scviewer.database.IEvent;
|
import com.minres.scviewer.database.IEvent;
|
||||||
import com.minres.scviewer.database.IEventList;
|
import com.minres.scviewer.database.IEventList;
|
||||||
import com.minres.scviewer.database.IWaveform;
|
import com.minres.scviewer.database.IWaveform;
|
||||||
|
@ -37,16 +37,16 @@ public class SignalPainter extends TrackPainter {
|
||||||
IEvent value;
|
IEvent value;
|
||||||
boolean fromMap;
|
boolean fromMap;
|
||||||
|
|
||||||
public SignalChange(Entry<Long, IEvent[]> entry) {
|
public SignalChange(EventEntry entry) {
|
||||||
time = entry.getKey();
|
time = entry.timestamp;
|
||||||
value = entry.getValue()[0];
|
value = entry.events[0];
|
||||||
fromMap = true;
|
fromMap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(Entry<Long, IEvent[]> entry, Long actTime) {
|
public void set(EventEntry entry, Long actTime) {
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
time = entry.getKey();
|
time = entry.timestamp;
|
||||||
value = entry.getValue()[0];
|
value = entry.events[0];
|
||||||
fromMap = true;
|
fromMap = true;
|
||||||
} else {
|
} else {
|
||||||
time = actTime;
|
time = actTime;
|
||||||
|
@ -100,8 +100,8 @@ public class SignalPainter extends TrackPainter {
|
||||||
long beginTime = beginPos*scaleFactor;
|
long beginTime = beginPos*scaleFactor;
|
||||||
long endTime = beginTime + area.width*scaleFactor;
|
long endTime = beginTime + area.width*scaleFactor;
|
||||||
|
|
||||||
Entry<Long, IEvent[]> first = signal.getEvents().floorEntry(beginTime);
|
EventEntry first = signal.getEvents().floorEntry(beginTime);
|
||||||
Entry<Long, IEvent[]> last = signal.getEvents().floorEntry(endTime);
|
EventEntry last = signal.getEvents().floorEntry(endTime);
|
||||||
if (first == null) {
|
if (first == null) {
|
||||||
if (last == null)
|
if (last == null)
|
||||||
return;
|
return;
|
||||||
|
@ -112,7 +112,7 @@ public class SignalPainter extends TrackPainter {
|
||||||
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
|
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
|
||||||
proj.setLineStyle(SWT.LINE_SOLID);
|
proj.setLineStyle(SWT.LINE_SOLID);
|
||||||
proj.setLineWidth(1);
|
proj.setLineWidth(1);
|
||||||
IEventList<Long, IEvent[]> entries = signal.getEvents().subMap(first.getKey(), false, last.getKey(), true);
|
IEventList entries = signal.getEvents().subMap(first.timestamp, false, last.timestamp);
|
||||||
SignalChange left = new SignalChange(first);
|
SignalChange left = new SignalChange(first);
|
||||||
SignalChange right = new SignalChange(entries.size() > 0 ? entries.firstEntry() : first);
|
SignalChange right = new SignalChange(entries.size() > 0 ? entries.firstEntry() : first);
|
||||||
maxPosX = area.x + area.width;
|
maxPosX = area.x + area.width;
|
||||||
|
@ -153,15 +153,15 @@ public class SignalPainter extends TrackPainter {
|
||||||
if (xSigChangeEndPos == xSigChangeBeginPos) {
|
if (xSigChangeEndPos == xSigChangeBeginPos) {
|
||||||
multiple = true;
|
multiple = true;
|
||||||
long eTime = (xSigChangeBeginPos + 1) * this.waveCanvas.getScaleFactor();
|
long eTime = (xSigChangeBeginPos + 1) * this.waveCanvas.getScaleFactor();
|
||||||
Entry<Long, IEvent[]> entry = entries.floorEntry(eTime);
|
EventEntry entry = entries.floorEntry(eTime);
|
||||||
if(entry!=null && entry.getKey()> right.time)
|
if(entry!=null && entry.timestamp> right.time)
|
||||||
right.set(entry, endTime);
|
right.set(entry, endTime);
|
||||||
xSigChangeEndPos = getXPosEnd(eTime);
|
xSigChangeEndPos = getXPosEnd(eTime);
|
||||||
}
|
}
|
||||||
} while (left.time < endTime);
|
} while (left.time < endTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SignalStencil getStencil(GC gc, SignalChange left, IEventList<Long, IEvent[]> entries) {
|
private SignalStencil getStencil(GC gc, SignalChange left, IEventList entries) {
|
||||||
IEvent val = left.value;
|
IEvent val = left.value;
|
||||||
if(val instanceof BitVector) {
|
if(val instanceof BitVector) {
|
||||||
BitVector bv = (BitVector) val;
|
BitVector bv = (BitVector) val;
|
||||||
|
@ -253,15 +253,15 @@ public class SignalPainter extends TrackPainter {
|
||||||
private long maxVal;
|
private long maxVal;
|
||||||
private long minVal;
|
private long minVal;
|
||||||
double yRange = (yOffsetB-yOffsetT);
|
double yRange = (yOffsetB-yOffsetT);
|
||||||
public MultiBitStencilAnalog(IEventList<Long, IEvent[]> entries, Object left, boolean continous, boolean signed) {
|
public MultiBitStencilAnalog(IEventList entries, Object left, boolean continous, boolean signed) {
|
||||||
this.continous=continous;
|
this.continous=continous;
|
||||||
this.signed=signed;
|
this.signed=signed;
|
||||||
Collection<IEvent[]> values = entries.values();
|
Collection<EventEntry> ievents = entries.entrySet();
|
||||||
minVal=signed?((BitVector)left).toSignedValue():((BitVector)left).toUnsignedValue();
|
minVal=signed?((BitVector)left).toSignedValue():((BitVector)left).toUnsignedValue();
|
||||||
if(!values.isEmpty()) {
|
if(!ievents.isEmpty()) {
|
||||||
maxVal=minVal;
|
maxVal=minVal;
|
||||||
for (IEvent[] tp : entries.values())
|
for (EventEntry tp : ievents)
|
||||||
for(IEvent e: tp) {
|
for(IEvent e: tp.events) {
|
||||||
long v = signed?((BitVector)e).toSignedValue():((BitVector)e).toUnsignedValue();
|
long v = signed?((BitVector)e).toSignedValue():((BitVector)e).toUnsignedValue();
|
||||||
maxVal=Math.max(maxVal, v);
|
maxVal=Math.max(maxVal, v);
|
||||||
minVal=Math.min(minVal, v);
|
minVal=Math.min(minVal, v);
|
||||||
|
@ -358,15 +358,15 @@ public class SignalPainter extends TrackPainter {
|
||||||
|
|
||||||
boolean continous=true;
|
boolean continous=true;
|
||||||
|
|
||||||
public RealStencil(IEventList<Long, IEvent[]> entries, Object left, boolean continous) {
|
public RealStencil(IEventList entries, Object left, boolean continous) {
|
||||||
this.continous=continous;
|
this.continous=continous;
|
||||||
Collection<IEvent[]> values = entries.values();
|
Collection<EventEntry> values = entries.entrySet();
|
||||||
minVal=(Double) left;
|
minVal=(Double) left;
|
||||||
range=2.0;
|
range=2.0;
|
||||||
if(!values.isEmpty()) {
|
if(!values.isEmpty()) {
|
||||||
double maxVal=minVal;
|
double maxVal=minVal;
|
||||||
for (IEvent[] val : entries.values())
|
for (EventEntry val : values)
|
||||||
for(IEvent e:val) {
|
for(IEvent e:val.events) {
|
||||||
double v = ((DoubleVal)e).value;
|
double v = ((DoubleVal)e).value;
|
||||||
if(Double.isNaN(maxVal))
|
if(Double.isNaN(maxVal))
|
||||||
maxVal=v;
|
maxVal=v;
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.minres.scviewer.database.ui.swt.internal;
|
package com.minres.scviewer.database.ui.swt.internal;
|
||||||
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
|
@ -18,9 +17,9 @@ import org.eclipse.swt.graphics.Color;
|
||||||
import org.eclipse.swt.graphics.Point;
|
import org.eclipse.swt.graphics.Point;
|
||||||
import org.eclipse.swt.graphics.Rectangle;
|
import org.eclipse.swt.graphics.Rectangle;
|
||||||
|
|
||||||
|
import com.minres.scviewer.database.EventEntry;
|
||||||
import com.minres.scviewer.database.EventKind;
|
import com.minres.scviewer.database.EventKind;
|
||||||
import com.minres.scviewer.database.IEvent;
|
import com.minres.scviewer.database.IEvent;
|
||||||
import com.minres.scviewer.database.IEventList;
|
|
||||||
import com.minres.scviewer.database.IWaveform;
|
import com.minres.scviewer.database.IWaveform;
|
||||||
import com.minres.scviewer.database.tx.ITx;
|
import com.minres.scviewer.database.tx.ITx;
|
||||||
import com.minres.scviewer.database.tx.ITxEvent;
|
import com.minres.scviewer.database.tx.ITxEvent;
|
||||||
|
@ -72,8 +71,8 @@ public class StreamPainter extends TrackPainter{
|
||||||
long beginTime = beginPos*scaleFactor;
|
long beginTime = beginPos*scaleFactor;
|
||||||
long endTime = beginTime + area.width*scaleFactor;
|
long endTime = beginTime + area.width*scaleFactor;
|
||||||
|
|
||||||
Entry<Long, IEvent[]> firstTx=stream.getEvents().floorEntry(beginTime);
|
EventEntry firstTx=stream.getEvents().floorEntry(beginTime);
|
||||||
Entry<Long, IEvent[]> lastTx=stream.getEvents().ceilingEntry(endTime);
|
EventEntry lastTx=stream.getEvents().ceilingEntry(endTime);
|
||||||
if(firstTx==null) firstTx = stream.getEvents().firstEntry();
|
if(firstTx==null) firstTx = stream.getEvents().firstEntry();
|
||||||
if(lastTx==null) lastTx=stream.getEvents().lastEntry();
|
if(lastTx==null) lastTx=stream.getEvents().lastEntry();
|
||||||
proj.setFillRule(SWT.FILL_EVEN_ODD);
|
proj.setFillRule(SWT.FILL_EVEN_ODD);
|
||||||
|
@ -84,16 +83,15 @@ public class StreamPainter extends TrackPainter{
|
||||||
for( int y1=area.y+trackHeight/2; y1<area.y+trackEntry.height; y1+=trackHeight)
|
for( int y1=area.y+trackHeight/2; y1<area.y+trackEntry.height; y1+=trackHeight)
|
||||||
proj.drawLine(area.x, y1, area.x+area.width, y1);
|
proj.drawLine(area.x, y1, area.x+area.width, y1);
|
||||||
if(firstTx==lastTx) {
|
if(firstTx==lastTx) {
|
||||||
for(IEvent txEvent: firstTx.getValue())
|
for(IEvent txEvent: firstTx.events)
|
||||||
drawTx(proj, area, ((ITxEvent)txEvent).getTransaction(), ((ITxEvent)txEvent).getRowIndex(), false);
|
drawTx(proj, area, ((ITxEvent)txEvent).getTransaction(), ((ITxEvent)txEvent).getRowIndex(), false);
|
||||||
}else{
|
}else{
|
||||||
seenTx.clear();
|
seenTx.clear();
|
||||||
IEventList<Long, IEvent[]> entries = stream.getEvents().subMap(firstTx.getKey(), true, lastTx.getKey(), true);
|
|
||||||
ITxEvent highlighed=null;
|
ITxEvent highlighed=null;
|
||||||
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
|
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
|
||||||
long selectedId=waveCanvas.currentSelection!=null? waveCanvas.currentSelection.getId():-1;
|
long selectedId=waveCanvas.currentSelection!=null? waveCanvas.currentSelection.getId():-1;
|
||||||
for(Entry<Long, IEvent[]> entry: entries.entrySet())
|
for(EventEntry entry: stream.getEvents().subMap(firstTx.timestamp, true, lastTx.timestamp))
|
||||||
for(IEvent e:entry.getValue()){
|
for(IEvent e:entry.events){
|
||||||
ITxEvent evt = (ITxEvent) e;
|
ITxEvent evt = (ITxEvent) e;
|
||||||
ITx tx = evt.getTransaction();
|
ITx tx = evt.getTransaction();
|
||||||
if(selectedId==tx.getId())
|
if(selectedId==tx.getId())
|
||||||
|
@ -155,12 +153,12 @@ public class StreamPainter extends TrackPainter{
|
||||||
|
|
||||||
public ITx getClicked(Point point) {
|
public ITx getClicked(Point point) {
|
||||||
int lane=point.y/waveCanvas.styleProvider.getTrackHeight();
|
int lane=point.y/waveCanvas.styleProvider.getTrackHeight();
|
||||||
Entry<Long, IEvent[]> firstTx=stream.getEvents().floorEntry(point.x*waveCanvas.getScaleFactor());
|
EventEntry firstTx=stream.getEvents().floorEntry(point.x*waveCanvas.getScaleFactor());
|
||||||
if(firstTx!=null){
|
if(firstTx!=null){
|
||||||
do {
|
do {
|
||||||
ITx tx = getTxFromEntry(lane, point.x, firstTx.getValue());
|
ITx tx = getTxFromEntry(lane, point.x, firstTx.events);
|
||||||
if(tx!=null) return tx;
|
if(tx!=null) return tx;
|
||||||
firstTx=stream.getEvents().lowerEntry(firstTx.getKey());
|
firstTx=stream.getEvents().lowerEntry(firstTx.timestamp);
|
||||||
}while(firstTx!=null);
|
}while(firstTx!=null);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.eclipse.swt.widgets.Event;
|
||||||
import org.eclipse.swt.widgets.ScrollBar;
|
import org.eclipse.swt.widgets.ScrollBar;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.minres.scviewer.database.EventEntry;
|
||||||
import com.minres.scviewer.database.IEvent;
|
import com.minres.scviewer.database.IEvent;
|
||||||
import com.minres.scviewer.database.IWaveform;
|
import com.minres.scviewer.database.IWaveform;
|
||||||
import com.minres.scviewer.database.RelationType;
|
import com.minres.scviewer.database.RelationType;
|
||||||
|
@ -427,8 +428,8 @@ public class WaveformCanvas extends Canvas {
|
||||||
}
|
}
|
||||||
for (IWaveformPainter painter : wave2painterMap.values()) {
|
for (IWaveformPainter painter : wave2painterMap.values()) {
|
||||||
if (painter instanceof StreamPainter && ((StreamPainter) painter).getStream() == tx.getStream()) {
|
if (painter instanceof StreamPainter && ((StreamPainter) painter).getStream() == tx.getStream()) {
|
||||||
Entry<Long, IEvent[]> entry = tx.getStream().getEvents().floorEntry(tx.getBeginTime());
|
EventEntry entry = tx.getStream().getEvents().floorEntry(tx.getBeginTime());
|
||||||
Optional<IEvent> res = Arrays.stream(entry.getValue()).filter(e -> ((ITxEvent)e).getTransaction().equals(tx)).findFirst();
|
Optional<IEvent> res = Arrays.stream(entry.events).filter(e -> ((ITxEvent)e).getTransaction().equals(tx)).findFirst();
|
||||||
if(res.isPresent()) {
|
if(res.isPresent()) {
|
||||||
int top = painter.getVerticalOffset() + styleProvider.getTrackHeight() * ((ITxEvent)res.get()).getRowIndex();
|
int top = painter.getVerticalOffset() + styleProvider.getTrackHeight() * ((ITxEvent)res.get()).getRowIndex();
|
||||||
int bottom = top + styleProvider.getTrackHeight();
|
int bottom = top + styleProvider.getTrackHeight();
|
||||||
|
|
|
@ -76,6 +76,7 @@ import org.eclipse.wb.swt.SWTResourceManager;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.minres.scviewer.database.BitVector;
|
import com.minres.scviewer.database.BitVector;
|
||||||
import com.minres.scviewer.database.DoubleVal;
|
import com.minres.scviewer.database.DoubleVal;
|
||||||
|
import com.minres.scviewer.database.EventEntry;
|
||||||
import com.minres.scviewer.database.EventKind;
|
import com.minres.scviewer.database.EventKind;
|
||||||
import com.minres.scviewer.database.IEvent;
|
import com.minres.scviewer.database.IEvent;
|
||||||
import com.minres.scviewer.database.IEventList;
|
import com.minres.scviewer.database.IEventList;
|
||||||
|
@ -255,29 +256,29 @@ public class WaveformView implements IWaveformView {
|
||||||
long time = waveformCanvas.getTimeForOffset(p.x);
|
long time = waveformCanvas.getTimeForOffset(p.x);
|
||||||
long scaling = 5 * waveformCanvas.getScaleFactor();
|
long scaling = 5 * waveformCanvas.getScaleFactor();
|
||||||
for (Object o : waveformCanvas.getElementsAt(p)) {
|
for (Object o : waveformCanvas.getElementsAt(p)) {
|
||||||
Entry<Long, IEvent[]> floorEntry = null;
|
EventEntry floorEntry = null;
|
||||||
Entry<Long, IEvent[]> ceilEntry = null;
|
EventEntry ceilEntry = null;
|
||||||
if (o instanceof TrackEntry) {
|
if (o instanceof TrackEntry) {
|
||||||
TrackEntry entry = (TrackEntry) o;
|
TrackEntry entry = (TrackEntry) o;
|
||||||
IEventList<Long, IEvent[]> map = entry.waveform.getEvents();
|
IEventList map = entry.waveform.getEvents();
|
||||||
floorEntry = map.floorEntry(time);
|
floorEntry = map.floorEntry(time);
|
||||||
ceilEntry = map.ceilingEntry(time);
|
ceilEntry = map.ceilingEntry(time);
|
||||||
} else if (o instanceof ITx) {
|
} else if (o instanceof ITx) {
|
||||||
IEventList<Long, IEvent[]> map = ((ITx) o).getStream().getEvents();
|
IEventList map = ((ITx) o).getStream().getEvents();
|
||||||
floorEntry = map.floorEntry(time);
|
floorEntry = map.floorEntry(time);
|
||||||
ceilEntry = map.ceilingEntry(time);
|
ceilEntry = map.ceilingEntry(time);
|
||||||
}
|
}
|
||||||
if (floorEntry != null && time - floorEntry.getKey() > scaling)
|
if (floorEntry != null && time - floorEntry.timestamp > scaling)
|
||||||
floorEntry = null;
|
floorEntry = null;
|
||||||
if (ceilEntry != null && ceilEntry.getKey() - time > scaling)
|
if (ceilEntry != null && ceilEntry.timestamp - time > scaling)
|
||||||
ceilEntry = null;
|
ceilEntry = null;
|
||||||
if (ceilEntry == null && floorEntry != null) {
|
if (ceilEntry == null && floorEntry != null) {
|
||||||
time = floorEntry.getKey();
|
time = floorEntry.timestamp;
|
||||||
} else if (ceilEntry != null && floorEntry == null) {
|
} else if (ceilEntry != null && floorEntry == null) {
|
||||||
time = ceilEntry.getKey();
|
time = ceilEntry.timestamp;
|
||||||
} else if (ceilEntry != null && floorEntry != null) {
|
} else if (ceilEntry != null && floorEntry != null) {
|
||||||
time = time - floorEntry.getKey() < ceilEntry.getKey() - time ? floorEntry.getKey()
|
time = time - floorEntry.timestamp < ceilEntry.timestamp - time ? floorEntry.timestamp
|
||||||
: ceilEntry.getKey();
|
: ceilEntry.timestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return time;
|
return time;
|
||||||
|
@ -580,10 +581,10 @@ public class WaveformView implements IWaveformView {
|
||||||
}
|
}
|
||||||
} else if (entry.waveform.getType() == WaveformType.TRANSACTION) {
|
} else if (entry.waveform.getType() == WaveformType.TRANSACTION) {
|
||||||
ITx[] resultsList = new ITx[entry.waveform.getRowCount()];
|
ITx[] resultsList = new ITx[entry.waveform.getRowCount()];
|
||||||
Entry<Long, IEvent[]> firstTx = entry.waveform.getEvents().floorEntry(time);
|
EventEntry firstTx = entry.waveform.getEvents().floorEntry(time);
|
||||||
if (firstTx != null) {
|
if (firstTx != null) {
|
||||||
do {
|
do {
|
||||||
for (IEvent e : firstTx.getValue()) {
|
for (IEvent e : firstTx.events) {
|
||||||
if (e instanceof ITxEvent) {
|
if (e instanceof ITxEvent) {
|
||||||
ITxEvent evt = ((ITxEvent) e);
|
ITxEvent evt = ((ITxEvent) e);
|
||||||
ITx tx = evt.getTransaction();
|
ITx tx = evt.getTransaction();
|
||||||
|
@ -593,7 +594,7 @@ public class WaveformView implements IWaveformView {
|
||||||
resultsList[evt.getRowIndex()] = evt.getTransaction();
|
resultsList[evt.getRowIndex()] = evt.getTransaction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
firstTx = entry.waveform.getEvents().lowerEntry(firstTx.getKey());
|
firstTx = entry.waveform.getEvents().lowerEntry(firstTx.timestamp);
|
||||||
} while (firstTx != null && !isArrayFull(resultsList));
|
} while (firstTx != null && !isArrayFull(resultsList));
|
||||||
boolean separator = false;
|
boolean separator = false;
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
@ -854,11 +855,11 @@ public class WaveformView implements IWaveformView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (transaction == null) {
|
if (transaction == null) {
|
||||||
Entry<Long, IEvent[]> entry = selectedWaveform.waveform.getEvents()
|
EventEntry entry = selectedWaveform.waveform.getEvents()
|
||||||
.higherEntry(currentTxSelection.getBeginTime());
|
.higherEntry(currentTxSelection.getBeginTime());
|
||||||
if (entry != null)
|
if (entry != null)
|
||||||
do {
|
do {
|
||||||
for (IEvent evt : entry.getValue()) {
|
for (IEvent evt : entry.events) {
|
||||||
if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN
|
if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN
|
||||||
|| evt.getKind() == EventKind.SINGLE)) {
|
|| evt.getKind() == EventKind.SINGLE)) {
|
||||||
transaction = ((ITxEvent) evt).getTransaction();
|
transaction = ((ITxEvent) evt).getTransaction();
|
||||||
|
@ -866,7 +867,7 @@ public class WaveformView implements IWaveformView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (transaction == null)
|
if (transaction == null)
|
||||||
entry = selectedWaveform.waveform.getEvents().higherEntry(entry.getKey());
|
entry = selectedWaveform.waveform.getEvents().higherEntry(entry.timestamp);
|
||||||
} while (entry != null && transaction == null);
|
} while (entry != null && transaction == null);
|
||||||
}
|
}
|
||||||
} else if (direction == GotoDirection.PREV) {
|
} else if (direction == GotoDirection.PREV) {
|
||||||
|
@ -883,11 +884,11 @@ public class WaveformView implements IWaveformView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (transaction == null) {
|
if (transaction == null) {
|
||||||
Entry<Long, IEvent[]> entry = selectedWaveform.waveform.getEvents()
|
EventEntry entry = selectedWaveform.waveform.getEvents()
|
||||||
.lowerEntry(currentTxSelection.getBeginTime());
|
.lowerEntry(currentTxSelection.getBeginTime());
|
||||||
if (entry != null)
|
if (entry != null)
|
||||||
do {
|
do {
|
||||||
for (IEvent evt : Lists.reverse(Arrays.asList(entry.getValue()))) {
|
for (IEvent evt : Lists.reverse(Arrays.asList(entry.events))) {
|
||||||
if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN
|
if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN
|
||||||
|| evt.getKind() == EventKind.SINGLE)) {
|
|| evt.getKind() == EventKind.SINGLE)) {
|
||||||
transaction = ((ITxEvent) evt).getTransaction();
|
transaction = ((ITxEvent) evt).getTransaction();
|
||||||
|
@ -895,7 +896,7 @@ public class WaveformView implements IWaveformView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (transaction == null)
|
if (transaction == null)
|
||||||
entry = selectedWaveform.waveform.getEvents().lowerEntry(entry.getKey());
|
entry = selectedWaveform.waveform.getEvents().lowerEntry(entry.timestamp);
|
||||||
} while (entry != null && transaction == null);
|
} while (entry != null && transaction == null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -958,14 +959,14 @@ public class WaveformView implements IWaveformView {
|
||||||
return;
|
return;
|
||||||
TrackEntry sel = currentWaveformSelection.get(0);
|
TrackEntry sel = currentWaveformSelection.get(0);
|
||||||
long time = getCursorTime();
|
long time = getCursorTime();
|
||||||
IEventList<Long, ?> map = null;
|
IEventList map = null;
|
||||||
if (sel.waveform.getType() == WaveformType.TRANSACTION || sel.waveform.getType() == WaveformType.SIGNAL) {
|
if (sel.waveform.getType() == WaveformType.TRANSACTION || sel.waveform.getType() == WaveformType.SIGNAL) {
|
||||||
map = sel.waveform.getEvents();
|
map = sel.waveform.getEvents();
|
||||||
}
|
}
|
||||||
if (map != null) {
|
if (map != null) {
|
||||||
Entry<Long, ?> entry = direction == GotoDirection.PREV ? map.lowerEntry(time) : map.higherEntry(time);
|
EventEntry entry = direction == GotoDirection.PREV ? map.lowerEntry(time) : map.higherEntry(time);
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
time = entry.getKey();
|
time = entry.timestamp;
|
||||||
setCursorTime(time);
|
setCursorTime(time);
|
||||||
waveformCanvas.reveal(time);
|
waveformCanvas.reveal(time);
|
||||||
waveformCanvas.redraw();
|
waveformCanvas.redraw();
|
||||||
|
|
|
@ -26,7 +26,6 @@ import java.util.zip.GZIPInputStream;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.minres.scviewer.database.BitVector;
|
import com.minres.scviewer.database.BitVector;
|
||||||
import com.minres.scviewer.database.DoubleVal;
|
import com.minres.scviewer.database.DoubleVal;
|
||||||
import com.minres.scviewer.database.IEvent;
|
|
||||||
import com.minres.scviewer.database.IEventList;
|
import com.minres.scviewer.database.IEventList;
|
||||||
import com.minres.scviewer.database.IWaveform;
|
import com.minres.scviewer.database.IWaveform;
|
||||||
import com.minres.scviewer.database.IWaveformDb;
|
import com.minres.scviewer.database.IWaveformDb;
|
||||||
|
@ -117,16 +116,16 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
|
||||||
if(!res) throw new InputFormatException("Could not parse VCD file");
|
if(!res) throw new InputFormatException("Could not parse VCD file");
|
||||||
// calculate max time of this database
|
// calculate max time of this database
|
||||||
for(IWaveform waveform:signals) {
|
for(IWaveform waveform:signals) {
|
||||||
IEventList<Long, IEvent[]> events =waveform.getEvents();
|
IEventList events =waveform.getEvents();
|
||||||
if(!events.isEmpty())
|
if(!events.isEmpty())
|
||||||
maxTime= Math.max(maxTime, events.lastKey());
|
maxTime= Math.max(maxTime, events.lastKey());
|
||||||
}
|
}
|
||||||
// extend signals to have a last value set at max time
|
// extend signals to have a last value set at max time
|
||||||
for(IWaveform s:signals){
|
for(IWaveform s:signals){
|
||||||
if(s instanceof VCDSignal<?>) {
|
if(s instanceof VCDSignal<?>) {
|
||||||
IEventList<Long, IEvent[]> events = ((VCDSignal<?>)s).getEvents();
|
IEventList events = ((VCDSignal<?>)s).getEvents();
|
||||||
if(events.size()>0 && events.lastKey()<maxTime){
|
if(events.size()>0 && events.lastKey()<maxTime){
|
||||||
Object val = events.lastEntry().getValue();
|
Object val = events.lastEntry().events[0];
|
||||||
if(val instanceof BitVector) {
|
if(val instanceof BitVector) {
|
||||||
((VCDSignal<BitVector>)s).addSignalChange(maxTime, (BitVector) val);
|
((VCDSignal<BitVector>)s).addSignalChange(maxTime, (BitVector) val);
|
||||||
} else if(val instanceof DoubleVal)
|
} else if(val instanceof DoubleVal)
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.minres.scviewer.database.vcd;
|
package com.minres.scviewer.database.vcd;
|
||||||
|
|
||||||
import java.util.Map.Entry;
|
import com.minres.scviewer.database.EventEntry;
|
||||||
|
|
||||||
import com.minres.scviewer.database.EventList;
|
import com.minres.scviewer.database.EventList;
|
||||||
import com.minres.scviewer.database.HierNode;
|
import com.minres.scviewer.database.HierNode;
|
||||||
import com.minres.scviewer.database.IEvent;
|
import com.minres.scviewer.database.IEvent;
|
||||||
|
@ -27,7 +26,7 @@ public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform {
|
||||||
|
|
||||||
private final int width;
|
private final int width;
|
||||||
|
|
||||||
private IEventList<Long, IEvent[]> values;
|
private IEventList values;
|
||||||
|
|
||||||
public VCDSignal(String name) {
|
public VCDSignal(String name) {
|
||||||
this(0, name, 1);
|
this(0, name, 1);
|
||||||
|
@ -42,7 +41,7 @@ public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform {
|
||||||
fullName=name;
|
fullName=name;
|
||||||
this.id=id;
|
this.id=id;
|
||||||
this.width=width;
|
this.width=width;
|
||||||
this.values=new EventList<>();
|
this.values=new EventList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public VCDSignal(VCDSignal<T> o, int id, String name) {
|
public VCDSignal(VCDSignal<T> o, int id, String name) {
|
||||||
|
@ -80,7 +79,7 @@ public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IEventList<Long, IEvent[]> getEvents() {
|
public IEventList getEvents() {
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,11 +90,11 @@ public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IEvent[] getEventsBeforeTime(Long time) {
|
public IEvent[] getEventsBeforeTime(Long time) {
|
||||||
Entry<Long, IEvent[]> e = values.floorEntry(time);
|
EventEntry e = values.floorEntry(time);
|
||||||
if(e==null)
|
if(e==null)
|
||||||
return new IEvent[] {};
|
return new IEvent[] {};
|
||||||
else
|
else
|
||||||
return values.floorEntry(time).getValue();
|
return values.floorEntry(time).events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -10,3 +10,4 @@ Export-Package: com.minres.scviewer.database,
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Service-Component: OSGI-INF/component.xml,OSGI-INF/component2.xml
|
Service-Component: OSGI-INF/component.xml,OSGI-INF/component2.xml
|
||||||
Automatic-Module-Name: com.minres.scviewer.database
|
Automatic-Module-Name: com.minres.scviewer.database
|
||||||
|
Require-Bundle: org.eclipse.collections;bundle-version="10.4.0"
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.minres.scviewer.database;
|
||||||
|
|
||||||
|
public class EventEntry implements Comparable<EventEntry>{
|
||||||
|
public long timestamp; // unsigned
|
||||||
|
public IEvent[] events = null;
|
||||||
|
|
||||||
|
|
||||||
|
public EventEntry(long timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public EventEntry(long timestamp, IEvent[] events) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(EventEntry o) {
|
||||||
|
return Long.compareUnsigned(timestamp, o.timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("e.%d@%d", events.length,timestamp);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,100 +1,196 @@
|
||||||
package com.minres.scviewer.database;
|
package com.minres.scviewer.database;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map.Entry;
|
import java.util.Collections;
|
||||||
import java.util.NavigableMap;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
public class EventList<K,V> implements IEventList<K,V>{
|
public class EventList implements IEventList {
|
||||||
|
|
||||||
NavigableMap<K,V> backing ;
|
ArrayList<EventEntry> store = new ArrayList<>();
|
||||||
|
int start = 0;
|
||||||
|
int end = store.size();
|
||||||
|
boolean unmodifiable = false;
|
||||||
|
|
||||||
|
public class Iterator implements java.util.Iterator<EventEntry> {
|
||||||
|
|
||||||
|
EventList list;
|
||||||
|
|
||||||
|
private int pos;
|
||||||
|
|
||||||
|
public Iterator(EventList list) {
|
||||||
|
this.list=list;
|
||||||
|
this.pos=-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return pos<(list.end-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventEntry next() {
|
||||||
|
if(hasNext()) {
|
||||||
|
pos++;
|
||||||
|
return list.store.get(pos);
|
||||||
|
} else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
list.store.remove(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public EventList() {
|
public EventList() {
|
||||||
backing=new TreeMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventList(NavigableMap<K, V> subMap) {
|
private EventList(ArrayList<EventEntry> store , int start, int end) {
|
||||||
backing=subMap;
|
this.store=store;
|
||||||
|
this.start=start;
|
||||||
|
this.end=end;
|
||||||
|
this.unmodifiable=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Entry<K, V> floorEntry(K key) {
|
public IEventList subMap(long from, boolean includeFrom, long to) {
|
||||||
return backing.floorEntry(key);
|
//the index of the first element greater than the key, or list.size()
|
||||||
|
int beginIndex = Collections.binarySearch(store, new EventEntry(from));
|
||||||
|
int startIndex = beginIndex < 0? -(beginIndex + 1): beginIndex;
|
||||||
|
int endIndex = Collections.binarySearch(store, new EventEntry(to));
|
||||||
|
endIndex = endIndex < 0? -(endIndex + 1): endIndex+1;
|
||||||
|
if(beginIndex>0 && !includeFrom)
|
||||||
|
return new EventList(store, startIndex+1, endIndex);
|
||||||
|
else
|
||||||
|
return new EventList(store, startIndex, endIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entry<K, V> ceilingEntry(K key) {
|
|
||||||
return backing.ceilingEntry(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entry<K, V> firstEntry() {
|
|
||||||
return backing.firstEntry();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entry<K, V> lastEntry() {
|
|
||||||
return backing.lastEntry();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public V get(K key) {
|
|
||||||
return backing.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entry<K, V> higherEntry(K key) {
|
|
||||||
return backing.higherEntry(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entry<K, V> lowerEntry(K key) {
|
|
||||||
return backing.lowerEntry(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IEventList<K, V> subMap(K key, boolean b, K key2, boolean c) {
|
|
||||||
return new EventList<K,V>( backing.subMap(key, b, key2, c));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return backing.size();
|
return end-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<K> keys() {
|
public boolean containsKey(long key) {
|
||||||
return backing.keySet();
|
int index = Collections.binarySearch(store, new EventEntry(key));
|
||||||
|
return index>=0 && index>=start && index<end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<V> values() {
|
public IEvent[] get(long key) {
|
||||||
return backing.values();
|
int index = Collections.binarySearch(store, new EventEntry(key));
|
||||||
|
if(index<0) return null;
|
||||||
|
return index>=start && index<end? store.get(index).events: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsKey(K key) {
|
public IEvent[] put(long key, IEvent[] value) {
|
||||||
return backing.containsKey(key);
|
if(unmodifiable) throw new UnsupportedOperationException();
|
||||||
|
EventEntry e = new EventEntry(key, value);
|
||||||
|
if(store.size()==0 || store.get(store.size()-1).timestamp < key) {
|
||||||
|
store.add(e);
|
||||||
|
} else {
|
||||||
|
int index = Collections.binarySearch(store, new EventEntry(key));
|
||||||
|
// < 0 if element is not in the list, see Collections.binarySearch
|
||||||
|
if (index < 0) {
|
||||||
|
index = -(index + 1);
|
||||||
|
store.add(index, e);
|
||||||
|
} else {
|
||||||
|
// Insertion index is index of existing element, to add new element behind it increase index
|
||||||
|
store.set(index, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end=store.size();
|
||||||
|
return e.events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V put(K key, V value) {
|
public Collection<EventEntry> entrySet() {
|
||||||
return backing.put(key, value);
|
if(start != 0 || end != store.size())
|
||||||
}
|
return Collections.unmodifiableList(store.subList(start, end));
|
||||||
|
else
|
||||||
@Override
|
return Collections.unmodifiableList(store);
|
||||||
public Collection<Entry<K, V>> entrySet() {
|
|
||||||
return backing.entrySet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return backing.isEmpty();
|
return start==end || store.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public K lastKey() {
|
public long firstKey() {
|
||||||
return backing.lastKey();
|
return store.get(start).timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long lastKey() {
|
||||||
|
return store.get(end-1).timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigable map functions
|
||||||
|
@Override
|
||||||
|
public EventEntry firstEntry() {
|
||||||
|
return store.get(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventEntry lastEntry() {
|
||||||
|
return store.get(end-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventEntry floorEntry(long key) {
|
||||||
|
int index = Collections.binarySearch(store, new EventEntry(key));
|
||||||
|
if(index==-1) return null;
|
||||||
|
// < 0 if element is not in the list, see Collections.binarySearch
|
||||||
|
if (index < 0) {
|
||||||
|
index = -(index + 2);
|
||||||
|
}
|
||||||
|
if(index>=end)
|
||||||
|
return store.get(end-1);
|
||||||
|
return index<start? null: store.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventEntry ceilingEntry(long key) {
|
||||||
|
int index = Collections.binarySearch(store, new EventEntry(key));
|
||||||
|
// < 0 if element is not in the list, see Collections.binarySearch
|
||||||
|
if (index < 0)
|
||||||
|
index = -(index + 1);
|
||||||
|
if(index<start)
|
||||||
|
return store.get(start);
|
||||||
|
return index>=end? null: store.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventEntry lowerEntry(long key) {
|
||||||
|
int index = Collections.binarySearch(store, new EventEntry(key));
|
||||||
|
// < 0 if element is not in the list, see Collections.binarySearch
|
||||||
|
if (index < 0)
|
||||||
|
index = -(index + 1);
|
||||||
|
index--;
|
||||||
|
if(index>=end)
|
||||||
|
return store.get(end-1);
|
||||||
|
return index>=end || index<start ?null:store.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventEntry higherEntry(long key) {
|
||||||
|
int index = Collections.binarySearch(store, new EventEntry(key));
|
||||||
|
// < 0 if element is not in the list, see Collections.binarySearch
|
||||||
|
if (index < 0)
|
||||||
|
index = -(index + 1);
|
||||||
|
else
|
||||||
|
index++;
|
||||||
|
if(index<start)
|
||||||
|
return store.get(start);
|
||||||
|
return index>=end || index<start ?null:store.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.util.Iterator<EventEntry> iterator() {
|
||||||
|
return new Iterator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +1,84 @@
|
||||||
package com.minres.scviewer.database;
|
package com.minres.scviewer.database;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
public interface IEventList<K,V> {
|
public interface IEventList extends Iterable<EventEntry> {
|
||||||
|
|
||||||
Entry<K, V> floorEntry(K key);
|
|
||||||
|
|
||||||
Entry<K, V> ceilingEntry(K key);
|
|
||||||
|
|
||||||
Entry<K, V> firstEntry();
|
|
||||||
|
|
||||||
Entry<K, V> lastEntry();
|
|
||||||
|
|
||||||
V get(K key);
|
|
||||||
|
|
||||||
Entry<K, V> higherEntry(K key);
|
|
||||||
|
|
||||||
Entry<K, V> lowerEntry(K key);
|
|
||||||
|
|
||||||
IEventList<K, V> subMap(K key, boolean b, K key2, boolean c);
|
|
||||||
|
|
||||||
int size();
|
int size();
|
||||||
|
|
||||||
Collection<K> keys();
|
Collection<EventEntry> entrySet();
|
||||||
|
|
||||||
Collection<V> values();
|
|
||||||
|
|
||||||
boolean containsKey(K key);
|
boolean containsKey(long key);
|
||||||
|
|
||||||
V put(K key, V value);
|
IEvent[] get(long key);
|
||||||
|
|
||||||
Collection<Entry<K, V>> entrySet();
|
IEvent[] put(long key, IEvent[] value);
|
||||||
|
|
||||||
|
long firstKey();
|
||||||
|
|
||||||
|
long lastKey();
|
||||||
|
|
||||||
boolean isEmpty();
|
boolean isEmpty();
|
||||||
|
/**
|
||||||
K lastKey();
|
* Returns a key-value mapping associated with the greatest key less
|
||||||
|
* than or equal to the given key, or null if there is no such key.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
EventEntry floorEntry(long key);
|
||||||
|
/**
|
||||||
|
* Returns a key-value mapping associated with the least key greater
|
||||||
|
* than or equal to the given key, or null if there is no such key.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
EventEntry ceilingEntry(long key);
|
||||||
|
/**
|
||||||
|
* Returns a key-value mapping associated with the least key in this map,
|
||||||
|
* or null if the map is empty.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
EventEntry firstEntry();
|
||||||
|
/**
|
||||||
|
* Returns a key-value mapping associated with the least key in this map,
|
||||||
|
* or null if the map is empty.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
EventEntry lastEntry();
|
||||||
|
/**
|
||||||
|
* Returns a key-value mapping associated with the least key strictly greater
|
||||||
|
* than the given key, or null if there is no such key.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
EventEntry higherEntry(long key);
|
||||||
|
/**
|
||||||
|
* Returns a key-value mapping associated with the greatest key strictly less
|
||||||
|
* than the given key, or null if there is no such key.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
EventEntry lowerEntry(long key);
|
||||||
|
/**
|
||||||
|
* Returns a view of the portion of this map whose keys range from
|
||||||
|
* {@code fromKey} to {@code toKey}. If {@code fromKey} and
|
||||||
|
* {@code toKey} are equal, the returned map is empty unless
|
||||||
|
* {@code fromInclusive} is true. The
|
||||||
|
* returned map is backed by this map, so changes in the returned map are
|
||||||
|
* reflected in this map, and vice-versa. The returned map supports all
|
||||||
|
* optional map operations that this map supports.
|
||||||
|
*
|
||||||
|
* @param fromKey low endpoint of the keys in the returned map
|
||||||
|
* @param fromInclusive {@code true} if the low endpoint
|
||||||
|
* is to be included in the returned view
|
||||||
|
* @param toKey high endpoint of the keys in the returned map (inclusive)
|
||||||
|
*/
|
||||||
|
IEventList subMap(long key, boolean b, long key2);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public interface IWaveform extends IHierNode {
|
||||||
*
|
*
|
||||||
* @return the events
|
* @return the events
|
||||||
*/
|
*/
|
||||||
public IEventList<Long, IEvent[]> getEvents();
|
public IEventList getEvents();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the events at time.
|
* Gets the events at time.
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class WaveformPopupMenuContribution {
|
||||||
if(elem instanceof TrackEntry) {
|
if(elem instanceof TrackEntry) {
|
||||||
TrackEntry e = (TrackEntry) elem;
|
TrackEntry e = (TrackEntry) elem;
|
||||||
if(e.waveform.getType() == WaveformType.SIGNAL) {
|
if(e.waveform.getType() == WaveformType.SIGNAL) {
|
||||||
Object o = e.waveform.getEvents().firstEntry().getValue()[0];
|
Object o = e.waveform.getEvents().firstEntry().events[0];
|
||||||
if(checkForDouble && o instanceof DoubleVal)
|
if(checkForDouble && o instanceof DoubleVal)
|
||||||
return true;
|
return true;
|
||||||
else if(o instanceof BitVector && ((BitVector)o).getWidth()>1)
|
else if(o instanceof BitVector && ((BitVector)o).getWidth()>1)
|
||||||
|
|
|
@ -32,8 +32,8 @@ import org.eclipse.swt.widgets.TableColumn;
|
||||||
import org.eclipse.swt.widgets.Text;
|
import org.eclipse.swt.widgets.Text;
|
||||||
|
|
||||||
import com.minres.scviewer.database.DataType;
|
import com.minres.scviewer.database.DataType;
|
||||||
|
import com.minres.scviewer.database.EventEntry;
|
||||||
import com.minres.scviewer.database.EventKind;
|
import com.minres.scviewer.database.EventKind;
|
||||||
import com.minres.scviewer.database.IEvent;
|
|
||||||
import com.minres.scviewer.database.IWaveform;
|
import com.minres.scviewer.database.IWaveform;
|
||||||
import com.minres.scviewer.database.WaveformType;
|
import com.minres.scviewer.database.WaveformType;
|
||||||
import com.minres.scviewer.database.tx.ITx;
|
import com.minres.scviewer.database.tx.ITx;
|
||||||
|
@ -249,8 +249,10 @@ public class TransactionList extends Composite {
|
||||||
}catch(SecurityException e){}
|
}catch(SecurityException e){}
|
||||||
updateThread = new Thread(()-> {
|
updateThread = new Thread(()-> {
|
||||||
final ConcurrentHashMap<String, DataType> propNames=new ConcurrentHashMap<>();
|
final ConcurrentHashMap<String, DataType> propNames=new ConcurrentHashMap<>();
|
||||||
Collection<IEvent[]> values = stream.getEvents().values();
|
Collection<EventEntry> values = stream.getEvents().entrySet();
|
||||||
final List<ITx> txList = values.parallelStream().map(Arrays::asList)
|
final List<ITx> txList = values.parallelStream()
|
||||||
|
.map(e->e.events)
|
||||||
|
.map(Arrays::asList)
|
||||||
.flatMap(List::stream)
|
.flatMap(List::stream)
|
||||||
.filter(evt -> evt.getKind()==EventKind.BEGIN || evt.getKind()==EventKind.SINGLE)
|
.filter(evt -> evt.getKind()==EventKind.BEGIN || evt.getKind()==EventKind.SINGLE)
|
||||||
.map(evt-> {
|
.map(evt-> {
|
||||||
|
|
|
@ -815,9 +815,18 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis
|
||||||
String trackentryName = state.get(SELECTED_TRACKENTRY_NAME);
|
String trackentryName = state.get(SELECTED_TRACKENTRY_NAME);
|
||||||
//get TrackEntry Object based on name and TX Object by id and put into selectionList
|
//get TrackEntry Object based on name and TX Object by id and put into selectionList
|
||||||
trackEntries.stream().filter(e->trackentryName.equals(e.waveform.getFullName())).forEach(trackEntry ->
|
trackEntries.stream().filter(e->trackentryName.equals(e.waveform.getFullName())).forEach(trackEntry ->
|
||||||
trackEntry.waveform.getEvents().values().stream().filter(Objects::nonNull).forEach(entries->
|
trackEntry.waveform.getEvents().entrySet().stream()
|
||||||
Arrays.stream(entries).filter(e->e instanceof ITxEvent && txId.equals(((ITxEvent)e).getTransaction().getId())).forEach(event ->
|
.map(e->e.events)
|
||||||
waveformPane.setSelection(new StructuredSelection(new Object[] {((ITxEvent)event).getTransaction(), trackEntry})))));
|
.filter(Objects::nonNull)
|
||||||
|
.forEach(entries->
|
||||||
|
Arrays.stream(entries)
|
||||||
|
.filter(e->e instanceof ITxEvent && txId.equals(((ITxEvent)e).getTransaction().getId()))
|
||||||
|
.forEach(event ->
|
||||||
|
waveformPane.setSelection(new StructuredSelection(
|
||||||
|
new Object[] {((ITxEvent)event).getTransaction(), trackEntry}))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,12 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.minres.scviewer.database.IEvent;
|
import com.minres.scviewer.database.EventEntry;
|
||||||
import com.minres.scviewer.database.IWaveform;
|
import com.minres.scviewer.database.IWaveform;
|
||||||
import com.minres.scviewer.database.IWaveformDb;
|
import com.minres.scviewer.database.IWaveformDb;
|
||||||
|
|
||||||
|
@ -50,11 +49,11 @@ public class DatabaseServicesTest {
|
||||||
assertEquals(14, waves.size());
|
assertEquals(14, waves.size());
|
||||||
assertEquals(2, waveformDb.getChildNodes().size());
|
assertEquals(2, waveformDb.getChildNodes().size());
|
||||||
IWaveform bus_data_wave = waves.get(0);
|
IWaveform bus_data_wave = waves.get(0);
|
||||||
Entry<Long, IEvent[]> bus_data_entry = bus_data_wave.getEvents().floorEntry(1400000000L);
|
EventEntry bus_data_entry = bus_data_wave.getEvents().floorEntry(1400000000L);
|
||||||
assertEquals("01111000", bus_data_entry.getValue()[0].toString());
|
assertEquals("01111000", bus_data_entry.events[0].toString());
|
||||||
IWaveform rw_wave = waves.get(2);
|
IWaveform rw_wave = waves.get(2);
|
||||||
Entry<Long, IEvent[]> rw_entry = rw_wave.getEvents().floorEntry(2360000000L);
|
EventEntry rw_entry = rw_wave.getEvents().floorEntry(2360000000L);
|
||||||
assertEquals("1", rw_entry.getValue()[0].toString());
|
assertEquals("1", rw_entry.events[0].toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
package com.minres.scviewer.database.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.minres.scviewer.database.EventList;
|
||||||
|
import com.minres.scviewer.database.IEvent;
|
||||||
|
import com.minres.scviewer.database.IEventList;
|
||||||
|
|
||||||
|
public class EventListTest {
|
||||||
|
|
||||||
|
EventList createList(int[] times) {
|
||||||
|
EventList list = new EventList();
|
||||||
|
for(int time: times)
|
||||||
|
list.put(time, new IEvent[] {});
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long[] getTimestamps(IEventList list) {
|
||||||
|
return list.entrySet().stream().map(e->e.timestamp).collect(Collectors.toList()).toArray(new Long[] {});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsertion() throws Exception {
|
||||||
|
IEventList list = createList(new int[] {5, 7, 3, 6, 2, 0});
|
||||||
|
assertEquals(6, list.size());
|
||||||
|
assertArrayEquals(new Long[]{0L, 2L, 3L, 5L, 6L, 7L}, getTimestamps(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSublist() throws Exception {
|
||||||
|
IEventList list = createList(new int[] {5, 7, 3, 8, 2, 0});
|
||||||
|
{
|
||||||
|
IEventList subList = list.subMap(3, true, 5);
|
||||||
|
assertEquals(2, subList.size());
|
||||||
|
assertArrayEquals(new Long[]{3L, 5L}, getTimestamps(subList));
|
||||||
|
} {
|
||||||
|
IEventList subList = list.subMap(3, false, 5);
|
||||||
|
assertEquals(1, subList.size());
|
||||||
|
assertArrayEquals(new Long[]{5L}, getTimestamps(subList));
|
||||||
|
} {
|
||||||
|
IEventList subList = list.subMap(4, true, 6);
|
||||||
|
assertEquals(1, subList.size());
|
||||||
|
assertArrayEquals(new Long[]{5L}, getTimestamps(subList));
|
||||||
|
} {
|
||||||
|
IEventList subList = list.subMap(4, false, 6);
|
||||||
|
assertEquals(1, subList.size());
|
||||||
|
assertArrayEquals(new Long[]{5L}, getTimestamps(subList));
|
||||||
|
} {
|
||||||
|
IEventList subList = list.subMap(4, true, 9);
|
||||||
|
assertEquals(3, subList.size());
|
||||||
|
assertArrayEquals(new Long[]{5L, 7L, 8L}, getTimestamps(subList));
|
||||||
|
} {
|
||||||
|
IEventList subList = list.subMap(4, false, 9);
|
||||||
|
assertEquals(3, subList.size());
|
||||||
|
assertArrayEquals(new Long[]{5L, 7L, 8L}, getTimestamps(subList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEntries() throws Exception {
|
||||||
|
IEventList list = createList(new int[] {2, 5, 8, 11});
|
||||||
|
assertEquals(2, list.firstEntry().timestamp);
|
||||||
|
assertEquals(11, list.lastEntry().timestamp);
|
||||||
|
|
||||||
|
assertNull(list.floorEntry(1));
|
||||||
|
assertEquals(2, list.floorEntry(2).timestamp);
|
||||||
|
assertEquals(2, list.floorEntry(3).timestamp);
|
||||||
|
assertEquals(2, list.floorEntry(4).timestamp);
|
||||||
|
assertEquals(5, list.floorEntry(5).timestamp);
|
||||||
|
assertEquals(5, list.floorEntry(6).timestamp);
|
||||||
|
assertEquals(8, list.floorEntry(10).timestamp);
|
||||||
|
assertEquals(11, list.floorEntry(11).timestamp);
|
||||||
|
assertEquals(11, list.floorEntry(12).timestamp);
|
||||||
|
|
||||||
|
assertEquals(2, list.ceilingEntry(1).timestamp);
|
||||||
|
assertEquals(2, list.ceilingEntry(2).timestamp);
|
||||||
|
assertEquals(5, list.ceilingEntry(3).timestamp);
|
||||||
|
assertEquals(5, list.ceilingEntry(4).timestamp);
|
||||||
|
assertEquals(5, list.ceilingEntry(5).timestamp);
|
||||||
|
assertEquals(8, list.ceilingEntry(6).timestamp);
|
||||||
|
assertEquals(11, list.ceilingEntry(10).timestamp);
|
||||||
|
assertEquals(11, list.ceilingEntry(11).timestamp);
|
||||||
|
assertNull(list.ceilingEntry(12));
|
||||||
|
|
||||||
|
assertNull(list.lowerEntry(1));
|
||||||
|
assertNull(list.lowerEntry(2));
|
||||||
|
assertEquals(2, list.lowerEntry(3).timestamp);
|
||||||
|
assertEquals(2, list.lowerEntry(4).timestamp);
|
||||||
|
assertEquals(2, list.lowerEntry(5).timestamp);
|
||||||
|
assertEquals(5, list.lowerEntry(6).timestamp);
|
||||||
|
assertEquals(8, list.lowerEntry(10).timestamp);
|
||||||
|
assertEquals(8, list.lowerEntry(11).timestamp);
|
||||||
|
assertEquals(11, list.lowerEntry(12).timestamp);
|
||||||
|
|
||||||
|
assertEquals(2, list.higherEntry(1).timestamp);
|
||||||
|
assertEquals(5, list.higherEntry(2).timestamp);
|
||||||
|
assertEquals(5, list.higherEntry(3).timestamp);
|
||||||
|
assertEquals(5, list.higherEntry(4).timestamp);
|
||||||
|
assertEquals(8, list.higherEntry(5).timestamp);
|
||||||
|
assertEquals(8, list.higherEntry(6).timestamp);
|
||||||
|
assertEquals(11, list.higherEntry(10).timestamp);
|
||||||
|
assertNull(list.higherEntry(11));
|
||||||
|
assertNull(list.higherEntry(12));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubListEntries() throws Exception {
|
||||||
|
IEventList fullList = createList(new int[] {2, 5, 8, 11});
|
||||||
|
IEventList list = fullList.subMap(5, true, 8);
|
||||||
|
|
||||||
|
assertEquals(5, list.firstEntry().timestamp);
|
||||||
|
assertEquals(8, list.lastEntry().timestamp);
|
||||||
|
|
||||||
|
assertNull(list.floorEntry(1));
|
||||||
|
assertNull(list.floorEntry(2));
|
||||||
|
assertNull(list.floorEntry(3));
|
||||||
|
assertNull(list.floorEntry(4));
|
||||||
|
assertEquals(5, list.floorEntry(5).timestamp);
|
||||||
|
assertEquals(5, list.floorEntry(6).timestamp);
|
||||||
|
assertEquals(8, list.floorEntry(10).timestamp);
|
||||||
|
assertEquals(8, list.floorEntry(11).timestamp);
|
||||||
|
assertEquals(8, list.floorEntry(12).timestamp);
|
||||||
|
|
||||||
|
assertEquals(5, list.ceilingEntry(1).timestamp);
|
||||||
|
assertEquals(5, list.ceilingEntry(2).timestamp);
|
||||||
|
assertEquals(5, list.ceilingEntry(3).timestamp);
|
||||||
|
assertEquals(5, list.ceilingEntry(4).timestamp);
|
||||||
|
assertEquals(5, list.ceilingEntry(5).timestamp);
|
||||||
|
assertEquals(8, list.ceilingEntry(6).timestamp);
|
||||||
|
assertEquals(8, list.ceilingEntry(8).timestamp);
|
||||||
|
assertNull(list.ceilingEntry(10));
|
||||||
|
assertNull(list.ceilingEntry(11));
|
||||||
|
assertNull(list.ceilingEntry(12));
|
||||||
|
|
||||||
|
assertNull(list.lowerEntry(1));
|
||||||
|
assertNull(list.lowerEntry(2));
|
||||||
|
assertNull(list.lowerEntry(3));
|
||||||
|
assertNull(list.lowerEntry(4));
|
||||||
|
assertNull(list.lowerEntry(5));
|
||||||
|
assertEquals(5, list.lowerEntry(6).timestamp);
|
||||||
|
assertEquals(8, list.lowerEntry(10).timestamp);
|
||||||
|
assertEquals(8, list.lowerEntry(11).timestamp);
|
||||||
|
assertEquals(8, list.lowerEntry(12).timestamp);
|
||||||
|
|
||||||
|
assertEquals(5, list.higherEntry(1).timestamp);
|
||||||
|
assertEquals(5, list.higherEntry(2).timestamp);
|
||||||
|
assertEquals(5, list.higherEntry(3).timestamp);
|
||||||
|
assertEquals(5, list.higherEntry(4).timestamp);
|
||||||
|
assertEquals(8, list.higherEntry(5).timestamp);
|
||||||
|
assertEquals(8, list.higherEntry(6).timestamp);
|
||||||
|
assertNull(list.higherEntry(8));
|
||||||
|
assertNull(list.higherEntry(10));
|
||||||
|
assertNull(list.higherEntry(11));
|
||||||
|
assertNull(list.higherEntry(12));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterface() throws Exception {
|
||||||
|
EventList emptyList = new EventList();
|
||||||
|
IEventList populatedList = createList(new int[] {0, 2, 3, 5, 6, 7});
|
||||||
|
assertEquals(0, emptyList.size());
|
||||||
|
assertEquals(6, populatedList.size());
|
||||||
|
assertTrue(emptyList.isEmpty());
|
||||||
|
assertFalse(populatedList.isEmpty());
|
||||||
|
assertFalse(emptyList.containsKey(5));
|
||||||
|
assertTrue(populatedList.containsKey(5));
|
||||||
|
assertFalse(populatedList.containsKey(8));
|
||||||
|
assertNull(emptyList.get(5));
|
||||||
|
assertNotNull(populatedList.get(5));
|
||||||
|
assertNull(populatedList.get(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterfaceSublist() throws Exception {
|
||||||
|
IEventList fullList = createList(new int[] {0, 2, 3, 5, 6, 7});
|
||||||
|
IEventList emptyList = fullList.subMap(3, false, 4);
|
||||||
|
IEventList populatedList = fullList.subMap(2, true, 6);
|
||||||
|
assertEquals(0, emptyList.size());
|
||||||
|
assertEquals(4, populatedList.size());
|
||||||
|
assertTrue(emptyList.isEmpty());
|
||||||
|
assertFalse(populatedList.isEmpty());
|
||||||
|
assertFalse(emptyList.containsKey(5));
|
||||||
|
assertTrue(populatedList.containsKey(5));
|
||||||
|
assertFalse(populatedList.containsKey(8));
|
||||||
|
assertNull(emptyList.get(5));
|
||||||
|
assertNotNull(populatedList.get(5));
|
||||||
|
assertNull(populatedList.get(7));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue