diff options
author | mhutch <m.j.hutchinson@gmail.com> | 2015-12-16 01:31:47 +0300 |
---|---|---|
committer | mhutch <m.j.hutchinson@gmail.com> | 2015-12-16 01:32:19 +0300 |
commit | e85c81fcc09c4af6e502615422d83006694fd617 (patch) | |
tree | 1ed5e37afc35ddf4eebfe93a49854f6d9c4a9d7e /main | |
parent | 8db8f6bb5018b55135469b4c6118e5fd2f1be62c (diff) |
[Gettext] Implement unicode unescaping
Diffstat (limited to 'main')
-rw-r--r-- | main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/StringEscaping.cs | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/StringEscaping.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/StringEscaping.cs index 8ae6882391..efe8b973e1 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/StringEscaping.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/StringEscaping.cs @@ -237,11 +237,21 @@ namespace MonoDevelop.Gettext sb.Append ('\t'); break; case 'U': - //FIXME UNICODE - //break; + uint Uc; + if (!TryParseHex (text, i + 1, 8, out Uc) || NeedsEscaping (Uc)) { + throw new FormatException ("Invalid escape '\\" + text.Substring (i, 9) + "' in translatable string."); + } + sb.Append (char.ConvertFromUtf32 ((int)Uc)); + i += 8; + break; case 'u': - //FIXME unicode - //break; + uint uc; + if (!TryParseHex (text, i + 1, 4, out uc) || NeedsEscaping (uc)) { + throw new FormatException ("Invalid escape '\\" + text.Substring (i, 5) + "' in translatable string."); + } + sb.Append ((char)uc); + i += 4; + break; case 'x': //FIXME hex unicode //break; @@ -259,6 +269,44 @@ namespace MonoDevelop.Gettext } return sb.ToString (); } + + static bool NeedsEscaping (uint c) + { + //TODO: there are other chars we should error on? + if (c > char.MaxValue) + return false; + return char.IsControl ((char)c); + } + + static bool TryParseHex (string str, int offset, int length, out uint val) + { + val = 0x0; + + for (int i = offset; i < offset + length; i++) { + uint bits; + switch (str[i]) { + case '0': bits = 0; break; + case '1': bits = 1; break; + case '2': bits = 2; break; + case '3': bits = 3; break; + case '4': bits = 4; break; + case '5': bits = 5; break; + case '6': bits = 6; break; + case '7': bits = 7; break; + case '8': bits = 8; break; + case '9': bits = 9; break; + case 'A': case 'a': bits = 10; break; + case 'B': case 'b': bits = 11; break; + case 'C': case 'c': bits = 12; break; + case 'D': case 'd': bits = 13; break; + case 'E': case 'e': bits = 14; break; + case 'F': case 'f': bits = 15; break; + default: return false; + } + val = (val << 4) | bits; + } + return true; + } public enum EscapeMode { |