summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/PacketHandler.vala77
-rw-r--r--src/Term.vala192
3 files changed, 271 insertions, 4 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a725dd3..af9fafe 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,7 +1,13 @@
+add_definitions(${GEE_CFLAGS} ${GEE_CFLAGS_OTHER} ${GIO_CFLAGS} ${GIO_CFLAGS_OTHER} ${ERL_CFLAGS} ${ERL_CFLAGS_OTHER})
+link_libraries(${GEE_LIBRARIES} ${GIO_LIBRARIES} ${ERL_LIBRARIES})
+link_directories(${GEE_LIBRARY_DIRS} ${GIO_LIBRARY_DIRS} ${ERL_LIBRARY_DIRS})
+
vala_precompile(EVA_C
+ PacketHandler.vala
Term.vala
PACKAGES
gee-1.0
+ gio-2.0
erl_interface
GENERATE_VAPI
eva
diff --git a/src/PacketHandler.vala b/src/PacketHandler.vala
new file mode 100644
index 0000000..0f5cd3c
--- /dev/null
+++ b/src/PacketHandler.vala
@@ -0,0 +1,77 @@
+namespace Eva {
+ public class PacketHandler {
+ private DataInputStream istream;
+ private DataOutputStream ostream;
+ private int sizeLength;
+
+ public signal void received_term(Term term);
+
+ public PacketHandler(InputStream input, OutputStream output, int length) {
+ assert(length == 1 || length == 2 || length == 4);
+
+ istream = new DataInputStream(input);
+ ostream = new DataOutputStream(output);
+ sizeLength = length;
+
+ istream.byte_order = DataStreamByteOrder.BIG_ENDIAN;
+ ostream.byte_order = DataStreamByteOrder.BIG_ENDIAN;
+ }
+
+ public void send(Term term) throws Error {
+ Erl.Buffer buffer = Erl.Buffer.with_version();
+ term.encode(buffer);
+
+ switch(sizeLength) {
+ case 1:
+ ostream.put_byte((uchar)buffer.buff.length, null);
+ break;
+ case 2:
+ ostream.put_uint16((uint16)buffer.buff.length, null);
+ break;
+ case 4:
+ ostream.put_uint32((uint32)buffer.buff.length, null);
+ break;
+ }
+
+ ostream.write(buffer.buff, buffer.buff.length, null);
+ }
+
+ private async void receive() throws Error {
+ while(true) {
+ while(istream.get_available() < sizeLength) {
+ yield istream.fill_async((ssize_t)(sizeLength - istream.get_available()), 0, null);
+ }
+
+ int length = 0;
+ switch(sizeLength) {
+ case 1:
+ length = istream.read_byte(null);
+ break;
+ case 2:
+ length = istream.read_uint16(null);
+ break;
+ case 4:
+ length = (int)istream.read_uint32(null);
+ break;
+ }
+
+ uint8[] buffer = new uint8[length];
+ size_t received = 0;
+
+ while(received < length) {
+ size_t ret = yield istream.read_async(&(buffer[received]), length-received, 0, null);
+ assert(ret > 0);
+
+ received += ret;
+ }
+
+ Term term = Term.decode(buffer);
+ Idle.add(() => {received_term(term); return false;});
+ }
+ }
+
+ public void start() {
+ receive.begin();
+ }
+ }
+}
diff --git a/src/Term.vala b/src/Term.vala
index 2a9cca8..3a75931 100644
--- a/src/Term.vala
+++ b/src/Term.vala
@@ -3,12 +3,90 @@ namespace Eva {
public abstract string to_string();
public abstract void encode(Erl.Buffer buffer);
+
+ public static Term decode(void *buffer) {
+ int index = 0;
+ int version;
+
+ Erl.decode_version(buffer, ref index, out version);
+
+ return do_decode(buffer, ref index);
+ }
+
+ private static Term do_decode(void *buffer, ref int index) {
+ int type, size;
+ assert(Erl.get_type(buffer, ref index, out type, out size) == 0);
+
+ switch(type) {
+ case Erl.TermType.SMALL_INTEGER:
+ char value;
+ assert(Erl.decode_char(buffer, ref index, out value) == 0);
+ return new Int((uchar)value);
+
+ case Erl.TermType.INTEGER:
+ long value;
+ assert(Erl.decode_long(buffer, ref index, out value) == 0);
+ return new Int(value);
+
+ case Erl.TermType.FLOAT:
+ double value;
+ assert(Erl.decode_double(buffer, ref index, out value) == 0);
+ return new Double(value);
+
+ case Erl.TermType.ATOM:
+ char[] value = new char[size+1];
+ assert(Erl.decode_atom(buffer, ref index, value) == 0);
+ return new Atom(((string)value).ndup(size));
+
+ case Erl.TermType.SMALL_TUPLE:
+ case Erl.TermType.LARGE_TUPLE:
+ assert(Erl.decode_tuple_header(buffer, ref index, out size) == 0);
+ Tuple term = new Tuple();
+
+ for(int i = 0; i < size; ++i) {
+ term.value.add(do_decode(buffer, ref index));
+ }
+
+ return term;
+
+ case Erl.TermType.NIL:
+ case Erl.TermType.LIST:
+ List term = new List();
+
+ while(true) {
+ assert(Erl.decode_list_header(buffer, ref index, out size) == 0);
+ if(size == 0)
+ break;
+
+ for(int i = 0; i < size; ++i) {
+ term.value.add(do_decode(buffer, ref index));
+ }
+ }
+
+ return term;
+
+ case Erl.TermType.STRING:
+ char[] value = new char[size+1];
+ assert(Erl.decode_string(buffer, ref index, value) == 0);
+ return new String(((string)value).ndup(size));
+
+ case Erl.TermType.BINARY:
+ char[] value = new char[size];
+ stdout.printf("Size: %i\n", size);
+ long l;
+ assert(Erl.decode_binary(buffer, ref index, value, out l) == 0);
+ return new Binary(value);
+
+ default:
+ assert_not_reached();
+ }
+ }
}
- public class Long : Object, Term {
+ public class Int : Object, Term {
public long value {get; construct;}
- public Long(long v) {
+ public Int(long v) {
Object(value: v);
}
@@ -21,10 +99,10 @@ namespace Eva {
}
}
- public class ULong : Object, Term {
+ public class UInt : Object, Term {
public ulong value {get; construct;}
- public ULong(ulong v) {
+ public UInt(ulong v) {
Object(value: v);
}
@@ -68,4 +146,110 @@ namespace Eva {
buffer.encode_atom(value.to_utf8());
}
}
+
+ public class Tuple : Object, Term {
+ public Gee.List<Term?> value {get; construct;}
+
+ public Tuple() {
+ Gee.List<Term?> list = new Gee.ArrayList<Term?>();
+ Object(value: list);
+ }
+
+ public string to_string() {
+ string ret = "{";
+ bool first = true;
+
+ foreach(Term term in value) {
+ if(first) {
+ first = false;
+ ret += term.to_string();
+ }
+ else {
+ ret += "," + term.to_string();
+ }
+ }
+
+ return ret + "}";
+ }
+
+ public void encode(Erl.Buffer buffer) {
+ buffer.encode_tuple_header(value.size);
+
+ foreach(Term term in value) {
+ term.encode(buffer);
+ }
+ }
+ }
+
+ public class List : Object, Term {
+ public Gee.List<Term?> value {get; construct;}
+
+ public List() {
+ Gee.List<Term?> list = new Gee.LinkedList<Term?>();
+ Object(value: list);
+ }
+
+ public string to_string() {
+ string ret = "[";
+ bool first = true;
+
+ foreach(Term term in value) {
+ if(first) {
+ first = false;
+ ret += term.to_string();
+ }
+ else {
+ ret += "," + term.to_string();
+ }
+ }
+
+ return ret + "]";
+ }
+
+ public void encode(Erl.Buffer buffer) {
+ if(!value.is_empty) {
+ buffer.encode_list_header(value.size);
+
+ foreach(Term term in value) {
+ term.encode(buffer);
+ }
+ }
+
+ buffer.encode_empty_list();
+ }
+ }
+
+ public class String : Object, Term {
+ public string value {get; construct;}
+
+ public String(string v) {
+ Object(value: v);
+ }
+
+ public string to_string() {
+ return value.to_string();
+ }
+
+ public void encode(Erl.Buffer buffer) {
+ buffer.encode_string(value.to_utf8());
+ }
+ }
+
+ public class Binary : Object, Term {
+ public void* value {get; private set;}
+ public long len {get; private set;}
+
+ public Binary(char[] v) {
+ value = Memory.dup(v, (uint)(sizeof(char)*v.length));
+ len = v.length;
+ }
+
+ public string to_string() {
+ return "[[Binary]]";
+ }
+
+ public void encode(Erl.Buffer buffer) {
+ buffer.encode_binary((char*)value, len);
+ }
+ }
}