aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/github/daneren2005/dsub/util/tags/Common.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/github/daneren2005/dsub/util/tags/Common.java')
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/tags/Common.java151
1 files changed, 98 insertions, 53 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/util/tags/Common.java b/app/src/main/java/github/daneren2005/dsub/util/tags/Common.java
index 51344d90..c0d661f5 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/tags/Common.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/tags/Common.java
@@ -21,18 +21,14 @@ package github.daneren2005.dsub.util.tags;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
-import java.util.Vector;
+import java.util.ArrayList;
public class Common {
- private static final long MAX_PKT_SIZE = 524288;
-
- public void xdie(String reason) throws IOException {
- throw new IOException(reason);
- }
-
- /*
- ** Returns a 32bit int from given byte offset in LE
- */
+ private static final int MAX_COMMENT_SIZE = 512;
+
+ /**
+ * Returns a 32bit int from given byte offset in LE
+ */
public int b2le32(byte[] b, int off) {
int r = 0;
for(int i=0; i<4; i++) {
@@ -40,7 +36,17 @@ public class Common {
}
return r;
}
-
+
+ /**
+ * Same as b2le32 but reads from a RandomAccessFile instead of a buffer
+ */
+ public int raf2le32(RandomAccessFile fh, long off) throws IOException {
+ byte[] scratch = new byte[4];
+ fh.seek(off);
+ fh.read(scratch);
+ return b2le32(scratch, 0);
+ }
+
public int b2be32(byte[] b, int off) {
return swap32(b2le32(b, off));
}
@@ -48,63 +54,102 @@ public class Common {
public int swap32(int i) {
return((i&0xff)<<24)+((i&0xff00)<<8)+((i&0xff0000)>>8)+((i>>24)&0xff);
}
-
- /*
- ** convert 'byte' value into unsigned int
- */
+
+ /**
+ * Returns a 16bit int from given byte offset in LE
+ */
+ public int b2le16(byte[] b, int off) {
+ return ( b2u(b[off]) | b2u(b[off+1]) << 8 );
+ }
+
+ /**
+ * convert 'byte' value into unsigned int
+ */
public int b2u(byte x) {
return (x & 0xFF);
}
- /*
- ** Printout debug message to STDOUT
- */
+ /**
+ * Printout debug message to STDOUT
+ */
public void debug(String s) {
System.out.println("DBUG "+s);
}
-
- public HashMap parse_vorbis_comment(RandomAccessFile s, long offset, long payload_len) throws IOException {
+
+ /**
+ * Throws an exception, killing the parser
+ */
+ public void xdie(String reason) throws IOException {
+ throw new IOException(reason);
+ }
+
+ public HashMap parse_vorbis_comment(RandomAccessFile fh, PageInfo.PageParser pp, long offset, long payload_len) throws IOException {
HashMap tags = new HashMap();
- int comments = 0; // number of found comments
- int xoff = 0; // offset within 'scratch'
- int can_read = (int)(payload_len > MAX_PKT_SIZE ? MAX_PKT_SIZE : payload_len);
- byte[] scratch = new byte[can_read];
-
- // seek to given position and slurp in the payload
- s.seek(offset);
- s.read(scratch);
-
- // skip vendor string in format: [LEN][VENDOR_STRING]
- xoff += 4 + b2le32(scratch, xoff); // 4 = LEN = 32bit int
- comments = b2le32(scratch, xoff);
- xoff += 4;
-
- // debug("comments count = "+comments);
- for(int i=0; i<comments; i++) {
-
- int clen = (int)b2le32(scratch, xoff);
- xoff += 4+clen;
-
- if(xoff > scratch.length)
- xdie("string out of bounds");
-
- String tag_raw = new String(scratch, xoff-clen, clen);
- String[] tag_vec = tag_raw.split("=",2);
- String tag_key = tag_vec[0].toUpperCase();
-
- addTagEntry(tags, tag_key, tag_vec[1]);
+ long last_byte = offset + payload_len;
+
+ // skip vendor string in format: [LEN][VENDOR_STRING] -> 4 = LEN = 32bit int
+ offset += 4 + raf2le32(fh, offset);
+
+ // we can now read the number of comments in this file, we will also
+ // adjust offset to point to the value after this 32bit int
+ int comments = raf2le32(fh, offset);
+ offset += 4;
+
+ for ( ; comments > 0; comments--) {
+ int comment_len = raf2le32(fh, offset);
+ offset += 4;
+ long can_read = last_byte - offset; // indicates the last byte of this page
+ int do_read = (int)(can_read > comment_len ? comment_len : can_read); // how much data is readable in this page
+
+ if (do_read >= 3) {
+ int bsize = (do_read > MAX_COMMENT_SIZE ? MAX_COMMENT_SIZE : do_read);
+ byte[] data = new byte[bsize];
+ fh.seek(offset);
+ fh.read(data);
+ String tag_raw = new String(data);
+ String[] tag_vec = tag_raw.split("=", 2);
+ String tag_key = tag_vec[0].toUpperCase();
+ addTagEntry(tags, tag_key, tag_vec[1]);
+ }
+
+ // set offset to begin of next tag (OR the end of this page!)
+ offset += do_read;
+
+ // We hit the end of a stream
+ // this is most likely due to the fact that we cropped do_read to not cross
+ // the page boundary -> we must now calculate the position of the next tag
+ if (offset == last_byte) {
+ int partial_cruft = comment_len - do_read; // how many bytes we did not read
+ while(partial_cruft > 0) {
+ PageInfo pi = pp.parse_stream_page(fh, last_byte);
+ if (pi.header_len <1 || pi.payload_len < 1)
+ xdie("Data from callback doesnt make much sense");
+
+ offset += pi.header_len; // move position behind page header
+ last_byte = offset + pi.payload_len; // and adjust the last byte to pos + payload_size
+
+ if (offset+partial_cruft < last_byte) {
+ offset += partial_cruft; // partial data ends in this block: just adjust the ofset
+ break;
+ } else {
+ // this page just contains data from the partial tag -> skip to next one
+ offset = last_byte;
+ partial_cruft -= pi.payload_len;
+ }
+ }
+ }
}
return tags;
}
-
+
public void addTagEntry(HashMap tags, String key, String value) {
if(tags.containsKey(key)) {
- ((Vector)tags.get(key)).add(value); // just add to existing vector
+ ((ArrayList)tags.get(key)).add(value); // just add to existing vector
}
else {
- Vector vx = new Vector();
- vx.add(value);
- tags.put(key, vx);
+ ArrayList l = new ArrayList<String>();
+ l.add(value);
+ tags.put(key, l);
}
}