/* HistoryListTripleton.java
Copyright 2003, Bil Lewis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.lambda.Debugger;
// HistoryList/HistoryList.java
/*
*/
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
public class HistoryListTripleton extends HistoryList {
private static int nCreated = 0;
private static int nUpgraded = 0;
private int time0=-1, time1=-1, time2=-1; // TimeStamp
private Object value0, value1, value2; // Object
public void reset(int time) {
Object currentValue = valueOn(time, false);
time0 = 0;
value0 = currentValue;
time1 = -1;
}
public boolean compact(int eot) {
if (Debugger.BUG) return compactB(eot);
int f;
if (time2 > -1) {
f = TimeStamp.forward(time2);
if (f >= 0) {
time2 = f;
if (time2 > eot)
throw new DebuggerException("HLM.compact() failed on " + this +" ["+time2+">"+eot+"] = "+value2);
}
else {
time0 = 0;
time1 = time2 = -1;
value0 = value2;
value1 = value2 = null;
verify(eot);
return true;
}
}
if (time1 > -1) {
f = TimeStamp.forward(time1);
if (f >= 0) {
time1 = f;
if (time1 > eot)
throw new DebuggerException("HLM.compact() failed on " + this +" ["+time1+">"+eot+"] = "+value1);
}
else {
if (time2 > -1) { time0 = time2; value0 = value2; }
else { time0 = 0; value0 = value1;}
time1 = time2 = -1;
value1 = value2 = null;
verify(eot);
return true;
}
}
if (time0 > -1) {
f = TimeStamp.forward(time0);
if (f >= 0) {
time0 = f;
if (time0 > eot)
throw new DebuggerException("HLM.compact() failed on " + this +" ["+time0+">"+eot+"] = "+value0);
}
else {
if (time1 > -1) { time0 = time1; value0 = value1; time1 = time2; value1 = value2; }
else { time0 = 0; }
time2 = -1;
value2 = null;
verify(eot);
return (time1 == -1);
}
}
verify(eot);
return (time1 == -1); // Is there more than 1 valid value?
}
public boolean compactB(int eot) {
int f;
f = TimeStamp.forward(time2);
if (f >= 0) {
time2 = f;
if (time2 > eot)
throw new DebuggerException("HLM.compact() failed on " + this +" ["+time2+">"+eot+"] = "+value2);
}
else {
time0 = 0;
time1 = time2 = -1;
value0 = value2;
value1 = value2 = null;
verify(eot);
return true;
}
if (time1 > -1) {
f = TimeStamp.forward(time1);
if (f >= 0) {
time1 = f;
if (time1 > eot)
throw new DebuggerException("HLM.compact() failed on " + this +" ["+time1+">"+eot+"] = "+value1);
}
else {
if (time2 > -1) { time0 = time2; value0 = value2; }
else { time0 = 0; value0 = value1;}
time1 = time2 = -1;
value1 = value2 = null;
verify(eot);
return true;
}
}
if (time0 > -1) {
f = TimeStamp.forward(time0);
if (f >= 0) {
time0 = f;
if (time0 > eot)
throw new DebuggerException("HLM.compact() failed on " + this +" ["+time0+">"+eot+"] = "+value0);
}
else {
if (time1 > -1) { time0 = time1; value0 = value1; time1 = time2; value1 = value2; }
else { time0 = 0; }
time2 = -1;
value2 = null;
verify(eot);
return (time1 == -1);
}
}
verify(eot);
return (time1 == -1); // Is there more than 1 valid value?
}
public void verify(int eot) {
int time=0;
for (int i = 0; i < size(); i++) {
if (i == 0) time = time0;
if (i == 1) time = time1;
if (i == 2) time = time2;
if (time == 0) continue;
if (time > eot)
throw new DebuggerException("HLM.compact() failed on " + this +" ["+time+">"+eot+"] = ");
}
}
public void setValue(Object obj, String varName, Object value) throws NoSuchFieldException, SecurityException, CompletionException {
if (obj instanceof int[]) {
if (value instanceof Integer) {
value = ShadowInt.createShadowInt(((Integer)value).intValue());
this.value0 = value; // CHANGE THIS CURRENT TIME
return;
}
throw new CompletionException("Wrong type. " + value + " is not an int");
}
if (obj instanceof Object[]) { // Check exact type somehow
this.value0 = value; // CHANGE THIS CURRENT TIME
return;
}
Field f = obj.getClass().getField(varName);
Class fieldClass = f.getType();
if (value instanceof Integer) {
if (fieldClass.equals(int.class)) {
value = new ShadowInt(((Integer)value).intValue());
this.value0 = value; // CHANGE THIS CURRENT TIME
return;
}
else
throw new CompletionException("Wrong type. " + value + " is not a " + fieldClass);
}
if (value instanceof Boolean) {
if (fieldClass.equals(boolean.class)) {
if (((Boolean)value).booleanValue())
value = ShadowBoolean.TRUE;
else
value = ShadowBoolean.FALSE;
this.value0 = value; // CHANGE THIS CURRENT TIME
return;
}
else
throw new CompletionException("Wrong type. " + value + " is not a " + fieldClass);
}
if ( (value != null) && (!Subtype.subtype(value.getClass(), fieldClass)) )
throw new CompletionException("Wrong type. " + value + " is not a " + fieldClass);
this.value0 = value; // CHANGE THIS CURRENT TIME
}
/*
public void setValue(Object o, Class c) throws NoSuchFieldException, SecurityException, CompletionException {
if (Subtype.subtype(c, int[].class)) {
if (o instanceof Integer) {
o = ShadowInt.createShadowInt(((Integer)o).intValue());
value = o; // CHANGE THIS CURRENT TIME
return;
}
throw new CompletionException("Wrong type. " + o + " is not an int");
}
if (Subtype.subtype(c, Object[].class)) { // Check exact type somehow
value = o; // CHANGE THIS CURRENT TIME
return;
}
Field f = c.getField(varName);
Class fieldClass = f.getType();
if (o instanceof Integer) {
if (fieldClass.equals(int.class)) {
o = new ShadowInt(((Integer)o).intValue());
value = o; // CHANGE THIS CURRENT TIME
return;
}
else
throw new CompletionException("Wrong type. " + o + " is not a " + fieldClass);
}
if ( (o != null) && (!Subtype.subtype(o.getClass(), fieldClass)) )
throw new CompletionException("Wrong type. " + o + " is not a " + fieldClass);
value = o; // CHANGE THIS CURRENT TIME
}
*/
public static int getNCreated() {
return nCreated;
}
public static int getNUpgraded() {
return nUpgraded;
}
public HistoryList dup(int time) {
HistoryListTripleton hls = new HistoryListTripleton(0, valueOn(time, false));
return hls;
}
public TVPair[] getValues() {
int size = size();
TVPair[] values = new TVPair[size];
if (size > 0) values[0] = new TVPair(time0, value0);
if (size > 1) values[1] = new TVPair(time1, value1);
if (size > 2) values[2] = new TVPair(time2, value2);
return(values);
}
public int size() {
if (time0 == -1) return 0;
if (time1 == -1) return 1;
if (time2 == -1) return 2;
return 3;
}
public int getTime(int i) {
if (i == 0) return(time0);
if (i == 1) return(time1);
if (i == 2) return(time2);
throw new DebuggerException("Cannot get(i>2) HistoryListTripleton " + this);
}
public TimeStamp getTS(int i) {
if (i == 0) return(TimeStamp.lookup(time0));
if (i == 1) return(TimeStamp.lookup(time1));
if (i == 2) return(TimeStamp.lookup(time2));
throw new DebuggerException("Cannot get(i>2) HistoryListTripleton " + this);
}
public Object getValue(int i) {
if (i == 0) return((value0));
if (i == 1) return((value1));
if (i == 2) return((value2));
throw new DebuggerException("Cannot get(i>2) HistoryListTripleton " + this);
}
public HistoryList upgrade(int time, Object value) {
nUpgraded++;
HistoryList hl = new HistoryListMultiple(time0, value0, time1, value1, time2, value2, time, value);
return hl;
}
public static void printStatistics() {}
// Constructors
public HistoryListTripleton() {}
public HistoryListTripleton(int time, Object initialValue) {
nEntries++;
nCreated++;
this.time0 = time;
value0 = initialValue;
}
public HistoryListTripleton(int time, Object initialValue, int time1, Object value1) {
nEntries++;
nCreated++;
this.time0 = time;
value0 = initialValue;
this.time1 = time1;
this.value1 = value1;
}
public HistoryList add(int time, Object o) {
int size = size();
if (size == 0) {time0=time; value0 = o; return null;}
if (size == 1) {time1=time; value1 = o; return null;}
if (size == 2) {time2=time; value2 = o; return null;}
return upgrade(time, o);
}
public HistoryList add(int time, int i) {
return add(time, ShadowInt.createShadowInt(i));
}
public void print() {
for (int i = 0; i<3; i++) {
System.out.println("\t" + getTime(i) + " \t" + getValue(i));
}
}
public String toString(int i) {
return("<HistoryListTripleton " + " " + 1 + ">");
}
public String toString() {
return( "XYY " + valueOn(TimeStamp.currentTime(), false));// Don't i need spaces here?
}
public TimeStamp getFirst() {
if (size() == 0) return null;
TimeStamp ts = TimeStamp.lookup(time0);
return(ts);
}
public TimeStamp getLast() {
int size = size();
if (size == 0) return null;
TimeStamp ts;
if (size == 1) return TimeStamp.lookup(time0);
if (size == 2) return TimeStamp.lookup(time1);
if (size == 3) return TimeStamp.lookup(time2);
return(null);
}
public int getLastTime() {
int size = size();
if (size == 1) return time0;
if (size == 2) return time1;
if (size == 3) return time2;
return 0;
}
public Object getLastValue() {
int size = size();
if (size == 0) return(null);
if (size == 1) return(value0);
if (size == 2) return(value1);
if (size == 3) return(value2);
throw new DebuggerException("Impossible1 HistoryListTripleton " + this);
}
public TimeStamp getPrevious() {
int size = size();
int time00 = TimeStamp.currentTime().time;
if (time00 == TimeStamp.bott()) return(null);
if (size > 2) {
if (!TimeStamp.laterThan(time2, time00)) {
TimeStamp ts2 = getTS(2);
TimeStamp prev = ts2.getPreviousThisThread();
if (prev == null) return(ts2);
return(prev);
}
}
if (size > 1) {
if (!TimeStamp.laterThan(time1, time00)) {
TimeStamp ts2 = getTS(1);
TimeStamp prev = ts2.getPreviousThisThread();
if (prev == null) return(ts2);
return(prev);
}
}
if (size > 0) {
if (!TimeStamp.laterThan(time0, time00)) {
TimeStamp ts2 = getTS(0);
TimeStamp prev = ts2.getPreviousThisThread();
if (prev == null) return(ts2);
return(prev);
}
}
return(null);
}
public TimeStamp getNext() {
int size = size();
int time00 = TimeStamp.currentTime().time;
if (size > 0) {
if (TimeStamp.laterThan(time0, time00)) {
return(getTS(0));
}
}
if (size > 1) {
if (TimeStamp.laterThan(time1, time00)) {
return(getTS(1));
}
}
if (size > 2) {
if (TimeStamp.laterThan(time2, time00)) {
return(getTS(2));
}
}
return(null);
}
public Object valueOn(TimeStamp ts, boolean foreign) {
return valueOn(ts.time, foreign);
}
public Object valueOn(int time, boolean foreign) {
int size = size();
if (size == 0) return(null);
if (TimeStamp.laterThan(time0, time)) {
if (foreign) return(getValue(0)); // Let caller know we don't have valid entries for ts
return(Dashes.DASHES);
}
if (size > 1) {
if (TimeStamp.laterThan(time1, time)) {
if (foreign) return(getValue(0)); // Let caller know we don't have valid entries for ts
return(getValue(0));
}
}
else {
if (foreign) return(getValue(0)); // Let caller know we don't have valid entries for ts
return(getValue(0));
}
if (size > 2) {
if (TimeStamp.laterThan(time2, time)) {
if (foreign) return(getValue(1)); // Let caller know we don't have valid entries for ts
return(getValue(1));
}
}
else {
if (foreign) return(getValue(1)); // Let caller know we don't have valid entries for ts
return(getValue(1));
}
if (foreign) return(getValue(2)); // Let caller know we don't have valid entries for ts
return(getValue(2));
}
public void removeLast() {
int size = size();
if (size == 1) {time0 = -1; return;}
if (size == 2) {time1 = -1; return;}
if (size == 3) {time2 = -1; return;}
}
public static void main(String[] args) {
System.out.println("----------------------HistoryList----------------------\n");
System.out.println("----------------------HistoryList----------------------\n");
}
}