]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - src/tim/prune/save/xml/GpxSlicer.java
Moved source into separate src directory due to popular request
[GpsPrune.git] / src / tim / prune / save / xml / GpxSlicer.java
diff --git a/src/tim/prune/save/xml/GpxSlicer.java b/src/tim/prune/save/xml/GpxSlicer.java
new file mode 100644 (file)
index 0000000..d18d760
--- /dev/null
@@ -0,0 +1,122 @@
+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
+       }
+}