From 46c0f539112cd19628dc0305d3556111099a04da Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 9 Jul 2010 08:53:03 +0200 Subject: Fixed unicode handling --- src/CMakeLists.txt | 1 + src/Term.vala | 68 +++++++++++++++++++++++++++++++++++++++++++----------- src/Util.vala | 45 ++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 src/Util.vala diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index af9fafe..4e7f0b2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,7 @@ link_directories(${GEE_LIBRARY_DIRS} ${GIO_LIBRARY_DIRS} ${ERL_LIBRARY_DIRS}) vala_precompile(EVA_C PacketHandler.vala Term.vala + Util.vala PACKAGES gee-1.0 gio-2.0 diff --git a/src/Term.vala b/src/Term.vala index 7037e48..46c03b3 100644 --- a/src/Term.vala +++ b/src/Term.vala @@ -37,7 +37,7 @@ namespace Eva { 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)); + return new Atom(array_to_string(value, size)); case Erl.TermType.SMALL_TUPLE: case Erl.TermType.LARGE_TUPLE: @@ -68,7 +68,7 @@ namespace Eva { 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)); + return new String(array_to_string(value, size)); case Erl.TermType.BINARY: char[] value = new char[size]; @@ -184,11 +184,33 @@ namespace Eva { public string value {get; construct;} public Atom(string v) { + assert(v.validate()); Object(value: v); } public string to_string() { - return value.to_string(); + if(value.length == 0) + return "''"; + + bool special = false; + unichar c = value.get_char(); + + if(!c.islower()) + special = true; + + for(unowned string rest = value.next_char(); rest.length != 0 && !special; rest = rest.next_char()) { + c = rest.get_char(); + + if(!(c == '_' || c.isalnum())) + special = true; + } + + if(!special) { + return value; + } + else { + return "'" + value.replace("\\", "\\\\").replace("'", "\\'") + "'"; + } } public bool equals(Term o) { @@ -201,7 +223,9 @@ namespace Eva { } public void encode(Erl.Buffer buffer) { - buffer.encode_atom(value.to_utf8()); + char[]? array = string_to_array(value); + assert(array != null); + buffer.encode_atom(array); } } @@ -312,23 +336,30 @@ namespace Eva { string s = ""; foreach(Term t in list) { + unichar c; + if(t is Int) { Int i = t as Int; if(i.value < 0 || i.value > 255) return false; - s += i.value.to_string("%c"); + c = (unichar)i.value; } else if(t is UInt) { UInt i = t as UInt; if(i.value > 255) return false; - s += i.value.to_string("%c"); + c = (unichar)i.value; } else { return false; } + + string buf = string.nfill(6, 0); + c.to_utf8(buf); + + s += buf; } return (s == (o as String).value); @@ -382,7 +413,7 @@ namespace Eva { } public string to_string() { - return value.to_string(); + return "\"" + value.replace("\\", "\\\\").replace("\"", "\\\"") + "\""; } public bool equals(Term o) { @@ -398,7 +429,13 @@ namespace Eva { } public void encode(Erl.Buffer buffer) { - buffer.encode_string(value.to_utf8()); + char[]? array = string_to_array(value); + if(array != null) { + buffer.encode_string(array); + } + else { + string_to_list(value).encode(buffer); + } } } @@ -442,7 +479,7 @@ namespace Eva { public uint creation {get; construct;} public Pid(Erl.Pid pid) { - this.create(((string)pid.node).ndup(Erl.MAXATOMLEN), pid.num, pid.serial, pid.creation); + this.create(array_to_string(pid.node, Erl.MAXATOMLEN), pid.num, pid.serial, pid.creation); } private Pid.create(string node0, uint num0, uint serial0, uint creation0) { @@ -464,7 +501,8 @@ namespace Eva { public void encode(Erl.Buffer buffer) { Erl.Pid pid = Erl.Pid(); - char[] nodedata = node.to_utf8(); + char[]? nodedata = string_to_array(node); + assert(nodedata != null); Memory.copy(pid.node, nodedata, int.min(Erl.MAXATOMLEN, nodedata.length)); pid.node[int.min(Erl.MAXATOMLEN, nodedata.length)] = 0; @@ -483,7 +521,7 @@ namespace Eva { public uint creation {get; construct;} public Port(Erl.Port port) { - this.create(((string)port.node).ndup(Erl.MAXATOMLEN), port.id, port.creation); + this.create(array_to_string(port.node, Erl.MAXATOMLEN), port.id, port.creation); } private Port.create(string node0, uint id0, uint creation0) { @@ -505,7 +543,8 @@ namespace Eva { public void encode(Erl.Buffer buffer) { Erl.Port port = Erl.Port(); - char[] nodedata = node.to_utf8(); + char[]? nodedata = string_to_array(node); + assert(nodedata != null); Memory.copy(port.node, nodedata, int.min(Erl.MAXATOMLEN, nodedata.length)); port.node[int.min(Erl.MAXATOMLEN, nodedata.length)] = 0; @@ -524,7 +563,7 @@ namespace Eva { public uint creation {get; construct;} public Ref(Erl.Ref reference) { - this.create(((string)reference.node).ndup(Erl.MAXATOMLEN), reference.len, reference.n, reference.creation); + this.create(array_to_string(reference.node, Erl.MAXATOMLEN), reference.len, reference.n, reference.creation); } private Ref.create(string node0, int len0, uint* n0, uint creation0) { @@ -560,7 +599,8 @@ namespace Eva { public void encode(Erl.Buffer buffer) { Erl.Ref reference = Erl.Ref(); - char[] nodedata = node.to_utf8(); + char[]? nodedata = string_to_array(node); + assert(nodedata != null); Memory.copy(reference.node, nodedata, int.min(Erl.MAXATOMLEN, nodedata.length)); reference.node[int.min(Erl.MAXATOMLEN, nodedata.length)] = 0; diff --git a/src/Util.vala b/src/Util.vala new file mode 100644 index 0000000..3666f96 --- /dev/null +++ b/src/Util.vala @@ -0,0 +1,45 @@ +namespace Eva { + private string array_to_string(uchar* array, ulong len) { + string ret = ""; + + for(ulong i = 0; i < len; ++i) { + if(array[i] == 0) + break; + + string buf = string.nfill(6, 0); + ((unichar)array[i]).to_utf8(buf); + + ret += buf; + } + + return ret; + } + + private char[]? string_to_array(string str) { + char[] ret = new char[str.len()]; + int index = 0; + + for(unowned string rest = str; rest.length > 0; rest = rest.next_char()) { + unichar c = rest.get_char(); + + if(c > 255) + return null; + + ret[index++] = (char)c; + } + + return ret; + } + + private List string_to_list(string str) { + List ret = new List(); + + for(unowned string rest = str; rest.length > 0; rest = rest.next_char()) { + unichar c = rest.get_char(); + + ret.list.add(new UInt(c)); + } + + return ret; + } +} -- cgit v1.2.3