package tim.prune.save.xml; import java.io.IOException; import java.io.InputStream; /** * Class to slice up a gpx stream and report the found tags * back to a listener. * Used by Gpx caching to re-read and store the gpx source */ public class GpxSlicer { /** listener to receive tags */ private TagReceiver _receiver = null; // character sequences for start and end of tags private static final char[] GPX_START = "<gpx".toCharArray(); private static final char[] GPX_END = ">".toCharArray(); private static final char[] TRKPT_START = "<trkpt".toCharArray(); private static final char[] TRKPT_END = "/trkpt>".toCharArray(); private static final char[] WPT_START = "<wpt".toCharArray(); private static final char[] WPT_END = "/wpt>".toCharArray(); private static final char[] RTEPT_START = "<rtept".toCharArray(); private static final char[] RTEPT_END = "/rtept>".toCharArray(); private static final char[] CDATA_START = "<![CDATA[".toCharArray(); private static final char[] CDATA_END = "]]>".toCharArray(); /** * Constructor * @param inReceiver listener for tags */ public GpxSlicer(TagReceiver inReceiver) { _receiver = inReceiver; } /** * Begin the slicing and pass the found tags back to the listener * @param inStream input stream for reading gpx source */ public void slice(InputStream inStream) { StringBuffer beginBuffer = new StringBuffer(200); ByteBuffer byteBuffer = new ByteBuffer(); boolean insideTag = false; boolean insideCdata = false; char[] endTag = null; boolean foundHeader = false; int b = 0; try { while ((b = inStream.read()) >= 0) { // copy character byteBuffer.appendByte((byte) b); // clear buffer if necessary if (!insideTag && !insideCdata && (b == '>' || b == '\n')) { byteBuffer.clear(); continue; } // if we're still at the beginning, copy to the begin buffer as well if (beginBuffer != null) {beginBuffer.append((char) b);} if (insideCdata) { // Just look for end of cdata block if (byteBuffer.foundSequence(CDATA_END)) {insideCdata = false;} } else { if (!insideTag) { // Look for start of one of the tags if (!foundHeader && byteBuffer.foundSequence(GPX_START)) { insideTag = true; foundHeader = true; endTag = GPX_END; // Check begin buffer for utf8 encoding if (beginBuffer != null && beginBuffer.toString().toLowerCase().indexOf("encoding=\"utf-8\"") > 0) { byteBuffer.setEncodingUtf8(); } beginBuffer = null; // don't need it any more } else if (b == 't') { if (byteBuffer.foundSequence(TRKPT_START)) { insideTag = true; endTag = TRKPT_END; } else if (byteBuffer.foundSequence(WPT_START)) { insideTag = true; endTag = WPT_END; } else if (byteBuffer.foundSequence(RTEPT_START)) { insideTag = true; endTag = RTEPT_END; } } } else { // Look for end of found tag if (byteBuffer.foundSequence(endTag)) { String tag = byteBuffer.toString(); _receiver.reportTag(tag); byteBuffer.clear(); insideTag = false; } } // Look for start of cdata block if (byteBuffer.foundSequence(CDATA_START)) { insideCdata = true; } } } } catch (IOException e) {} // ignore } }