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