
com.koushikdutta.async.PushParser Maven / Gradle / Ivy
package com.koushikdutta.async;
import android.util.Log;
import com.koushikdutta.async.callback.DataCallback;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.LinkedList;
public class PushParser implements DataCallback {
public interface ParseCallback {
public void parsed(T data);
}
static abstract class Waiter {
int length;
public Waiter(int length) {
this.length = length;
}
/**
* Consumes received data, and/or returns next waiter to continue reading instead of this waiter.
* @param bb received data, bb.remaining >= length
* @return - a waiter that should continue reading right away, or null if this waiter is finished
*/
public abstract Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb);
}
static class IntWaiter extends Waiter {
ParseCallback callback;
public IntWaiter(ParseCallback callback) {
super(4);
this.callback = callback;
}
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
callback.parsed(bb.getInt());
return null;
}
}
static class ByteArrayWaiter extends Waiter {
ParseCallback callback;
public ByteArrayWaiter(int length, ParseCallback callback) {
super(length);
if (length <= 0) throw new IllegalArgumentException("length should be > 0");
this.callback = callback;
}
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
byte[] bytes = new byte[length];
bb.get(bytes);
callback.parsed(bytes);
return null;
}
}
static class LenByteArrayWaiter extends Waiter {
private final ParseCallback callback;
public LenByteArrayWaiter(ParseCallback callback) {
super(4);
this.callback = callback;
}
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
int length = bb.getInt();
return new ByteArrayWaiter(length, callback);
}
}
static class ByteBufferListWaiter extends Waiter {
ParseCallback callback;
public ByteBufferListWaiter(int length, ParseCallback callback) {
super(length);
if (length <= 0) throw new IllegalArgumentException("length should be > 0");
this.callback = callback;
}
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
callback.parsed(bb.get(length));
return null;
}
}
static class LenByteBufferListWaiter extends Waiter {
private final ParseCallback callback;
public LenByteBufferListWaiter(ParseCallback callback) {
super(4);
this.callback = callback;
}
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
int length = bb.getInt();
return new ByteBufferListWaiter(length, callback);
}
}
static class UntilWaiter extends Waiter {
byte value;
DataCallback callback;
public UntilWaiter(byte value, DataCallback callback) {
super(1);
this.value = value;
this.callback = callback;
}
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
boolean found = true;
ByteBufferList cb = new ByteBufferList();
while (bb.size() > 0) {
ByteBuffer b = bb.remove();
b.mark();
int index = 0;
while (b.remaining() > 0 && !(found = (b.get() == value))) {
index++;
}
b.reset();
if (found) {
bb.addFirst(b);
bb.get(cb, index);
// eat the one we're waiting on
bb.get();
break;
} else {
cb.add(b);
}
}
callback.onDataAvailable(emitter, cb);
if (found) {
return null;
} else {
return this;
}
}
}
private class TapWaiter extends Waiter {
private final TapCallback callback;
public TapWaiter(TapCallback callback) {
super(0);
this.callback = callback;
}
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
Method method = getTap(callback);
method.setAccessible(true);
try {
method.invoke(callback, args.toArray());
} catch (Exception e) {
Log.e("PushParser", "Error while invoking tap callback", e);
}
args.clear();
return null;
}
}
private Waiter noopArgWaiter = new Waiter(0) {
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
args.add(null);
return null;
}
};
private Waiter byteArgWaiter = new Waiter(1) {
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
args.add(bb.get());
return null;
}
};
private Waiter shortArgWaiter = new Waiter(2) {
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
args.add(bb.getShort());
return null;
}
};
private Waiter intArgWaiter = new Waiter(4) {
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
args.add(bb.getInt());
return null;
}
};
private Waiter longArgWaiter = new Waiter(8) {
@Override
public Waiter onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
args.add(bb.getLong());
return null;
}
};
private ParseCallback byteArrayArgCallback = new ParseCallback() {
@Override
public void parsed(byte[] data) {
args.add(data);
}
};
private ParseCallback byteBufferListArgCallback = new ParseCallback() {
@Override
public void parsed(ByteBufferList data) {
args.add(data);
}
};
private ParseCallback stringArgCallback = new ParseCallback() {
@Override
public void parsed(byte[] data) {
args.add(new String(data));
}
};
DataEmitter mEmitter;
private LinkedList mWaiting = new LinkedList();
private ArrayList
© 2015 - 2025 Weber Informatics LLC | Privacy Policy