package janala.interpreters; import java.util.ArrayList; import java.util.LinkedList; import java.util.Set; import java.util.Map; public final class SymbolicStringExpression { private final LinkedList list; // either String or SymbolicStringVar public SymbolicStringExpression(int sym, IntValue length) { this.list = new LinkedList(); this.list.addLast(new SymbolicStringVar(sym, length)); } public SymbolicStringExpression(SymbolicStringExpression sym) { this.list = new LinkedList(); this.list.addAll(sym.list); } public boolean equals(Object o) { if (o == null) { return false; } else if (this == o) { return true; } else if (o instanceof SymbolicStringExpression) { SymbolicStringExpression other = (SymbolicStringExpression)o; return list.equals(other.list); } else { return false; } } public SymbolicStringExpression concatStr(String str) { SymbolicStringExpression ret = new SymbolicStringExpression(this); ret.addLast(str); return ret; } private void addLast(String entry) { Object last = list.getLast(); if (last instanceof String) { list.removeLast(); list.addLast(last + entry); } else { list.addLast(entry); } } public SymbolicStringExpression concat(SymbolicStringExpression expr) { SymbolicStringExpression ret = new SymbolicStringExpression(this); Object last = ret.list.getLast(); Object first = expr.list.getFirst(); if (first instanceof String) { ret.addLast((String)first); } else { ret.list.addLast(first); } ret.list.addAll(expr.list.subList(1, expr.list.size())); return ret; } public SymbolicStringExpression concatToStr(String str) { SymbolicStringExpression ret = new SymbolicStringExpression(this); Object first = ret.list.getFirst(); if (first instanceof String) { ret.list.removeFirst(); ret.list.addFirst(str + first); } else { ret.list.addFirst(str); } return ret; } public boolean isCompound() { return this.list.size() > 1; } public String toString() { StringBuilder sb = new StringBuilder(); boolean flag = true; for (Object elem : this.list) { if (flag) { flag = false; } else { sb.append('+'); } if (elem instanceof SymbolicStringVar) { sb.append(elem.toString()); } else { sb.append('"'); sb.append((String)elem); sb.append('"'); } } return sb.toString(); } public SymbolicStringExpression substitute(ArrayList<Value> assignments) { return this; } public IntValue getField(String offset) { if (offset.equals("length")) { IntValue ret = null, len; for (Object val : this.list) { if (val instanceof String) { len = new IntValue(((String) val).length()); } else if (val instanceof SymbolicStringVar) { len = (IntValue) ((SymbolicStringVar) val).getField("length"); } else { throw new RuntimeException("Unsupported string type."); } if (ret == null) { ret = len; } else { ret = ret.IADD(len); } } return ret; } throw new RuntimeException("Not implemented"); } public SymOrInt getExprAt(int i, Set<String> freeVars, Map<String, Long> assignments) { for (Object s : list) { if (s instanceof String) { if (i < ((String) s).length()) { return new SymOrInt(((String) s).charAt(i)); } else { i = i - ((String) s).length(); } } else { String idx = s.toString(); int length = (int) ((SymbolicStringVar) s) .getField("length").substituteInLinear(assignments); if (i < length) { freeVars.add("x" + idx + "__" + i); return new SymOrInt("x" + idx + "__" + i); } else { i = i - length; } } } throw new RuntimeException("Cannot find the exp"); } }