From b8b41036db050bacacc4ff5b25dad689538c5983 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 7 Jul 2010 19:09:29 +0200 Subject: Added support for Pids, Ports, Refs and improper lists --- src/Term.vala | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- test/Test.vala | 2 +- 2 files changed, 158 insertions(+), 16 deletions(-) diff --git a/src/Term.vala b/src/Term.vala index 3a75931..a32ea1f 100644 --- a/src/Term.vala +++ b/src/Term.vala @@ -53,14 +53,13 @@ namespace Eva { 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; - + assert(Erl.decode_list_header(buffer, ref index, out size) == 0); + if(size != 0) { for(int i = 0; i < size; ++i) { - term.value.add(do_decode(buffer, ref index)); + term.list.add(do_decode(buffer, ref index)); } + + term.tail = do_decode(buffer, ref index); } return term; @@ -72,11 +71,26 @@ namespace Eva { 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); + case Erl.TermType.PID: + Erl.Pid value; + assert(Erl.decode_pid(buffer, ref index, out value) == 0); + return new Pid(value); + + case Erl.TermType.PORT: + Erl.Port value; + assert(Erl.decode_port(buffer, ref index, out value) == 0); + return new Port(value); + + case Erl.TermType.REFERENCE: + case Erl.TermType.NEW_REFERENCE: + Erl.Ref value; + assert(Erl.decode_ref(buffer, ref index, out value) == 0); + return new Ref(value); + default: assert_not_reached(); } @@ -182,18 +196,37 @@ namespace Eva { } public class List : Object, Term { - public Gee.List value {get; construct;} + private Term? _tail; + + public Gee.List list {get; construct;} + public Term? tail { + get { + return _tail; + } + set { + if(value is List) { + List l = value as List; + + list.add_all(l.list); + _tail = l._tail; + } + else { + _tail = value; + } + } + } public List() { - Gee.List list = new Gee.LinkedList(); - Object(value: list); + Gee.List list0 = new Gee.LinkedList(); + Object(list: list0); + tail = null; } public string to_string() { string ret = "["; bool first = true; - foreach(Term term in value) { + foreach(Term term in list) { if(first) { first = false; ret += term.to_string(); @@ -203,14 +236,17 @@ namespace Eva { } } + if(tail != null) + ret += "|" + tail.to_string(); + return ret + "]"; } public void encode(Erl.Buffer buffer) { - if(!value.is_empty) { - buffer.encode_list_header(value.size); + if(!list.is_empty) { + buffer.encode_list_header(list.size); - foreach(Term term in value) { + foreach(Term term in list) { term.encode(buffer); } } @@ -245,11 +281,117 @@ namespace Eva { } public string to_string() { - return "[[Binary]]"; + return "#Bin"; } public void encode(Erl.Buffer buffer) { buffer.encode_binary((char*)value, len); } } + + public class Pid : Object, Term { + public string node {get; construct;} + public uint num {get; construct;} + public uint serial {get; construct;} + public uint creation {get; construct;} + + public Pid(Erl.Pid pid) { + this.create(((string)pid.node).ndup(Erl.MAXATOMLEN), pid.num, pid.serial, pid.creation); + } + + private Pid.create(string node0, uint num0, uint serial0, uint creation0) { + Object(node: node0, num: num0, serial: serial0, creation: creation0); + } + + public string to_string() { + return "<" + node + "." + num.to_string() + "." + serial.to_string() + ">"; + } + + public void encode(Erl.Buffer buffer) { + Erl.Pid pid = Erl.Pid(); + char[] nodedata = node.to_utf8(); + + Memory.copy(pid.node, nodedata, int.min(Erl.MAXATOMLEN, nodedata.length)); + pid.node[int.min(Erl.MAXATOMLEN, nodedata.length)] = 0; + + pid.num = num; + pid.serial = serial; + pid.creation = creation; + + buffer.encode_pid(pid); + } + } + + public class Port : Object, Term { + public string node {get; construct;} + public uint id {get; construct;} + public uint creation {get; construct;} + + public Port(Erl.Port port) { + this.create(((string)port.node).ndup(Erl.MAXATOMLEN), port.id, port.creation); + } + + private Port.create(string node0, uint id0, uint creation0) { + Object(node: node0, id: id0, creation: creation0); + } + + public string to_string() { + return "#Port"; + } + + public void encode(Erl.Buffer buffer) { + Erl.Port port = Erl.Port(); + char[] nodedata = node.to_utf8(); + + Memory.copy(port.node, nodedata, int.min(Erl.MAXATOMLEN, nodedata.length)); + port.node[int.min(Erl.MAXATOMLEN, nodedata.length)] = 0; + + port.id = id; + port.creation = creation; + + buffer.encode_port(port); + } + } + + public class Ref : Object, Term { + public string node {get; construct;} + public int len {get; construct;} + public uint[] n {get; private set;} + public uint creation {get; construct;} + + public Ref(Erl.Ref reference) { + this.create(((string)reference.node).ndup(Erl.MAXATOMLEN), reference.len, reference.n, reference.creation); + } + + private Ref.create(string node0, int len0, uint* n0, uint creation0) { + Object(node: node0, len: len0, creation: creation0); + + n = new uint[len]; + for(int i = 0; i < len; ++i) { + n[i] = n0[i]; + } + } + + public string to_string() { + return "#Ref"; + } + + public void encode(Erl.Buffer buffer) { + Erl.Ref reference = Erl.Ref(); + char[] nodedata = node.to_utf8(); + + Memory.copy(reference.node, nodedata, int.min(Erl.MAXATOMLEN, nodedata.length)); + reference.node[int.min(Erl.MAXATOMLEN, nodedata.length)] = 0; + + reference.len = len; + + for(int i = 0; i < len; ++i) { + reference.n[i] = n[i]; + } + + reference.creation = creation; + + buffer.encode_ref(reference); + } + } } diff --git a/test/Test.vala b/test/Test.vala index 5d71095..86907ea 100644 --- a/test/Test.vala +++ b/test/Test.vala @@ -4,7 +4,7 @@ namespace Eva { 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.received_term.connect((term) => {stdout.printf("Received term %s\n", term.to_string()); handler.send(term); main.quit();}); handler.start(); main.run(); -- cgit v1.2.3