summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt6
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/PacketHandler.vala77
-rw-r--r--src/Term.vala192
-rw-r--r--test/CMakeLists.txt6
-rw-r--r--test/Test.vala8
6 files changed, 286 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9dddf9a..844570d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,11 +11,9 @@ ensure_vala_version("0.8" MINIMUM)
find_package(PkgConfig)
pkg_check_modules(GEE REQUIRED gee-1.0)
+pkg_check_modules(GIO REQUIRED gio-2.0)
+pkg_check_modules(GIO_UNIX REQUIRED gio-unix-2.0)
pkg_check_modules(ERL REQUIRED erl_interface)
-add_definitions(${GEE_CFLAGS} ${GEE_CFLAGS_OTHER} ${ERL_CFLAGS} ${ERL_CFLAGS_OTHER})
-link_libraries(${GEE_LIBRARIES} ${ERL_LIBRARIES})
-link_directories(${GEE_LIBRARY_DIRS} ${ERL_LIBRARY_DIRS})
-
add_subdirectory(src)
add_subdirectory(test)
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);
+ }
+ }
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2c11d3b..bad2b58 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,7 +1,13 @@
+add_definitions(${GEE_CFLAGS} ${GEE_CFLAGS_OTHER} ${GIO_CFLAGS} ${GIO_CFLAGS_OTHER} ${GIO_UNIX_CFLAGS} ${GIO_UNIX_CFLAGS_OTHER} ${ERL_CFLAGS} ${ERL_CFLAGS_OTHER})
+link_libraries(${GEE_LIBRARIES} ${GIO_LIBRARIES} ${GIO_UNIX_LIBRARIES} ${ERL_LIBRARIES})
+link_directories(${GEE_LIBRARY_DIRS} ${GIO_LIBRARY_DIRS} ${GIO_UNIX_LIBRARY_DIRS} ${ERL_LIBRARY_DIRS})
+
vala_precompile(TEST_C
Test.vala
PACKAGES
gee-1.0
+ gio-2.0
+ gio-unix-2.0
erl_interface
CUSTOM_VAPIS
${eva_BINARY_DIR}/src/eva.vapi
diff --git a/test/Test.vala b/test/Test.vala
index ce5da6d..5d71095 100644
--- a/test/Test.vala
+++ b/test/Test.vala
@@ -1,7 +1,13 @@
namespace Eva {
class Test {
public static int main(string[] args) {
- Eva.Long term = new Eva.Long(42);
+ MainLoop main = new MainLoop();
+
+ Eva.PacketHandler handler = new Eva.PacketHandler(new UnixInputStream(3, true), new UnixOutputStream(4, true), 4);
+ handler.received_term.connect((term) => {stdout.printf("%s\n", term.to_string()); handler.send(term); main.quit();});
+ handler.start();
+
+ main.run();
return 0;
}