package net.contrapunctus.rngzip; import java.io.File; import java.io.IOException; import java.util.Stack; import org.kohsuke.bali.automaton.*; import org.kohsuke.bali.datatype.Value; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import net.contrapunctus.rngzip.util.BaliAutomaton; import net.contrapunctus.rngzip.io.ChoiceDecoder; import net.contrapunctus.rngzip.io.ChoiceDecoderFactory; import net.contrapunctus.rngzip.io.RNGZInputInterface; import net.contrapunctus.rngzip.io.RNGZInputStream; import net.contrapunctus.rngzip.io.InteractiveInput; import java.net.MalformedURLException; class GenericDecompressor extends Decompressor implements AlphabetVisitor { private final BaliAutomaton au; private final ChoiceDecoder[] cds; private Stack<Integer> stack = new Stack<Integer>(); private RNGZInputInterface in; private SAXException exn_sax; private IOException exn_io; public GenericDecompressor(String filename, RNGZInputInterface in, ContentHandler ch) throws MalformedURLException, IOException, SAXException { this(BaliAutomaton.fromRNG(new File(filename)), in, ch); } public GenericDecompressor(BaliAutomaton _au, RNGZInputInterface in, ContentHandler h) throws IOException, SAXException { au = _au; cds = new ChoiceDecoder[au.countStates()]; for(int i = 0; i < au.countStates(); i++) { int n = au.countChoices(i); if(n > 1) { cds[i] = in.makeChoiceDecoder(n, i); } } run(in, h); } public void run(RNGZInputInterface in, ContentHandler h) throws IOException, SAXException { initialize(h); this.in = in; stack.clear(); stack.push(au.initialState()); while(!stack.isEmpty()) { int state = stack.pop(); if(au.isNull(state)) continue; ChoiceDecoder cd = cds[state]; int n = au.countChoices(state); int i = 0; if(cd != null) { i = in.readChoice(cd); assert i >= 0 && i < n; } if(au.isFinal(state) && i == n-1) { epsilon(); continue; } au.visitAlphabet(state, i, this); if(exn_io != null) throw exn_io; if(exn_sax != null) throw exn_sax; stack.push(au.siblingOf(state, i)); int k = au.childOf(state, i); if(k >= 0) { stack.push(k); } } } public Object attribute (AttributeAlphabet al) { addAttribute(al.name.nameClass.toString()); return null; } public Object nonExistentAttribute (NonExistentAttributeAlphabet al) { return null; } public Object element (ElementAlphabet al) { try { startElement(al.name.nameClass.toString()); } catch(SAXException e) { exn_sax = e; } return null; } public Object interleave (InterleaveAlphabet al) { assert false; return null; } public Object list (ListAlphabet al) { assert false; return null; } public Object data (DataAlphabet al) { try { chars(in.readContent(eltStack)); } catch(IOException e) { exn_io = e; } catch(SAXException e) { exn_sax = e; } return null; } public Object value (ValueAlphabet al) { //System.err.printf(" *** ValueAlphabet >%s< (%s)%n", al.value, // al.value.getClass()); try { Value v = (Value) al.value; // should work? chars(v.value.trim()); } catch(SAXException e) { exn_sax = e; } return null; } }