/** * Read the pairs table for an MVD from a byte array * * @param data the byte array containing the version definitions * @param p the start offset of the versions within data * @param dataTableOffset offset within data of the pairs data * @param mvd an mvd to add the version definitions to */ private static void readPairsTable(byte[] data, int p, int dataTableOffset, MVD mvd) throws Exception { // record any pairs declaring themselves as parents HashMap<Integer, Pair> parents = new HashMap<Integer, Pair>(); HashMap<Integer, LinkedList<Pair>> orphans = new HashMap<Integer, LinkedList<Pair>>(); int nPairs = readInt(data, p); p += 4; if (nPairs < 0) throw new MVDException("Invalid number of pairs: " + nPairs); for (int i = 0; i < nPairs; i++) { byte[] copy; Pair pair; BitSet versions = readVersionSet(mvd.versionSetSize, data, p); p += mvd.versionSetSize; int offset = readInt(data, p); p += 4; int len = readInt(data, p); int flag = len & Pair.TRANSPOSE_MASK; // clear top two bits len &= Pair.INVERSE_MASK; p += 4; if (flag == Pair.PARENT_FLAG) { // read special parent id field int pId = readInt(data, p); p += 4; // transpose parent copy = copyData(len, dataTableOffset + offset, data); pair = new Pair(versions, toChars(copy, mvd.encoding)); Integer key = new Integer(pId); // check for orphans of this parent LinkedList<Pair> children = orphans.get(key); if (children != null) { ListIterator<Pair> iter = children.listIterator(); // match them up with this parent while (iter.hasNext()) { Pair child = iter.next(); child.setParent(pair); pair.addChild(child); } // now they're not orphans any more orphans.remove(key); } // always do this in case more children turn up parents.put(key, pair); } else if (flag == Pair.CHILD_FLAG) { // read special parent id field int pId = readInt(data, p); p += 4; // transpose child Integer key = new Integer(pId); Pair parent = parents.get(key); if (parent == null) { LinkedList<Pair> children = orphans.get(key); if (children == null) { children = new LinkedList<Pair>(); orphans.put(key, children); } pair = new Pair(versions, null); children.add(pair); } else // parent available { pair = new Pair(versions, null); pair.setParent(parent); parent.addChild(pair); } } else { // no transposition copy = copyData(len, dataTableOffset + offset, data); pair = new Pair(versions, toChars(copy, mvd.encoding)); } mvd.addPair(pair); } }