package hep.io.root.reps;
import hep.io.root.core.AbstractRootObject;
import hep.io.root.core.NameMangler;
import hep.io.root.core.RootInput;
import hep.io.root.interfaces.TBasket;
import hep.io.root.interfaces.TBranch;
import hep.io.root.interfaces.TLeaf;
import hep.io.root.interfaces.TObjArray;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.HashMap;
/**
* @author Tony Johnson (tonyj@slac.stanford.edu)
* @version $Id: TBranchRep.java 8584 2006-08-10 23:06:37Z duns $
*/
public abstract class TBranchRep extends AbstractRootObject implements hep.io.root.interfaces.TBranch
{
private HashMap mangledMap;
private HashMap map;
private RootInput rin;
private TBasket curBasket;
private int curIndex;
private int fWriteBasket;
private int[] cBasketBytes;
private long[] cBasketEntry;
private long[] cBasketSeek;
public int[] getBasketBytes()
{
return cBasketBytes;
}
public long[] getBasketEntry()
{
return cBasketEntry;
}
public long[] getBasketSeek()
{
return cBasketSeek;
}
private int[] saveIntSpace(String source, int size)
{
try
{
if (size == 0) return null;
int[] result = new int[size];
Field field = getClass().getDeclaredField(source);
Object array = field.get(this);
for (int i=0; i<size; i++) result[i] = Array.getInt(array,i);
return result;
}
catch (NoSuchFieldException x) // Seems to happen for TBranchClones
{
return null;
}
catch (Exception x)
{
throw new RuntimeException("Wierd error while compressing "+source,x);
}
}
private long[] saveLongSpace(String source, int size)
{
try
{
if (size == 0) return null;
long[] result = new long[size];
Field field = getClass().getDeclaredField(source);
Object array = field.get(this);
for (int i=0; i<size; i++) result[i] = Array.getLong(array,i);
return result;
}
catch (NoSuchFieldException x) // Seems to happen for TBranchClones
{
return null;
}
catch (Exception x)
{
throw new RuntimeException("Wierd error while compressing "+source,x);
}
}
public TBranch getBranchForMangledName(String name)
{
if (map == null)
buildMap();
return (TBranch) mangledMap.get(name);
}
public TBranch getBranchForName(String name)
{
if (map == null)
buildMap();
return (TBranch) map.get(name);
}
public RootInput setPosition(TLeaf leaf, long index) throws IOException
{
int i = findBasketForIndex(index);
TBasket basket = getBasket(i);
return basket.setPosition(index, i == 0 ? 0 : getBasketEntry()[i], leaf);
}
public void read(RootInput in) throws IOException
{
super.read(in);
// Clean-up unnecessarily large arrays
cBasketBytes = saveIntSpace("fBasketBytes",fWriteBasket);
cBasketEntry = saveLongSpace("fBasketEntry",fWriteBasket+1);
cBasketSeek = saveLongSpace("fBasketSeek",fWriteBasket);
rin = in.getTop();
// The leaves need to know which branch they are on
TObjArray leaves = getLeaves();
if (leaves != null)
{
for (int i = 0; i < leaves.size(); i++)
{
TLeaf leaf = (TLeaf) leaves.get(i);
leaf.setBranch(this);
}
}
curIndex = -1;
}
private TBasket getBasket(int index) throws IOException
{
try
{
TObjArray baskets = getBaskets();
TBasket basket = (TBasket) baskets.get(index);
if (basket != null) return basket;
if (index == curIndex) return curBasket;
// Ok read the TBasket
rin.setPosition(getBasketSeek()[index]);
basket = (TBasket) rin.readObject("TBasket");
int len = getEntryOffsetLen();
if (len > 0) basket.readEntryOffsets(len);
curIndex = index;
return curBasket = basket;
}
catch (IOException x)
{
curIndex = -1;
throw x;
}
}
private void buildMap()
{
NameMangler nameMangler = NameMangler.instance();
map = new HashMap();
mangledMap = new HashMap();
TObjArray branches = getBranches();
int size = branches.size();
for (int i = 0; i < size; i++)
{
TBranch b = (TBranch) branches.get(i);
String bName = b.getName();
int pos = bName.indexOf('[');
if (pos > 0)
bName = bName.substring(0, pos);
pos = bName.lastIndexOf('.');
if (pos > 0)
bName = bName.substring(pos + 1);
map.put(bName, b);
mangledMap.put(nameMangler.mangleMember(bName), b);
}
}
private int findBasketForIndex(long index)
{
// Figure out which basket the entry is in
if ((index < 0) || (index >= getEntries()))
throw new ArrayIndexOutOfBoundsException("index=" + index);
long[] entries = getBasketEntry();
if (entries == null) return 0;
// TODO: we should do a binary search here
int n = getWriteBasket();
for (int i = 0; i < n; i++)
{
if ((index >= entries[i]) && (index < entries[i + 1])) return i;
}
return n;
// binary search has problems if arrays contain trailing zeros
// int result = Arrays.binarySearch(entries,index);
// if (result < 0) result = - result - 2;
// return result;
}
}