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 );
		}
	}