1 /*******************************************************************************
2 
3     Xml entity en/decoder.
4 
5     Example usage:
6 
7     ---
8 
9         import ocean.text.entities.XmlEntityCodec;
10 
11         scope entity_codec = new XmlEntityCodec;
12 
13         char[] test = "hello & world © >Ȱ'";
14 
15         if ( entity_codec.containsUnencoded(test) )
16         {
17             char[] encoded;
18             entity_codec.encode(test, encoded);
19         }
20 
21     ---
22 
23     Copyright:
24         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
25         All rights reserved.
26 
27     License:
28         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
29         Alternatively, this file may be distributed under the terms of the Tango
30         3-Clause BSD License (see LICENSE_BSD.txt for details).
31 
32 *******************************************************************************/
33 
34 module ocean.text.entities.XmlEntityCodec;
35 
36 
37 
38 
39 import ocean.text.entities.model.MarkupEntityCodec;
40 
41 import ocean.text.entities.XmlEntitySet;
42 
43 import ocean.meta.types.Qualifiers;
44 
45 import ocean.core.Verify;
46 
47 /*******************************************************************************
48 
49     Class to en/decode xml entities.
50 
51 *******************************************************************************/
52 
53 public alias MarkupEntityCodec!(XmlEntitySet) XmlEntityCodec;
54 
55 
56 /*******************************************************************************
57 
58     Unit test
59 
60 *******************************************************************************/
61 
62 version (unittest)
63 {
64     void encodeTest ( Char ) ( XmlEntityCodec codec, const(Char)[] str,
65         const(Char)[] expected_result )
66     {
67         Char[] encoded;
68 
69         if ( codec.containsUnencoded(str) )
70         {
71             codec.encode(str, encoded);
72             verify(codec.containsEncoded(encoded));
73         }
74         else
75         {
76             encoded = str.dup;
77         }
78 
79         verify(encoded == expected_result);
80     }
81 
82     void decodeTest ( Char ) ( XmlEntityCodec codec, const(Char)[] str,
83         const(Char)[] expected_result )
84     {
85         Char[] decoded;
86 
87         if ( codec.containsEncoded(str) )
88         {
89             codec.decode(str, decoded);
90         }
91         else
92         {
93             decoded = str.dup;
94         }
95 
96         verify(decoded == expected_result);
97     }
98 
99     // Perform tests for various char types
100     void test ( Char ) ( )
101     {
102         struct Test
103         {
104             const(Char)[] before;
105             const(Char)[] after;
106         }
107 
108         scope codec = new XmlEntityCodec;
109 
110         // Check encoding
111         Test[] encode_tests = [
112             Test("", "" ), // saftey check
113             Test("&", "&"),
114             Test("'", "'"),
115             Test("\"", """),
116             Test("<", "&lt;"),
117             Test(">", "&gt;"),
118             Test("©", "©"), // trick question
119             Test("'hello'", "&apos;hello&apos;"),
120             Test("&amp;", "&amp;") // already encoded
121         ];
122 
123         foreach ( t; encode_tests )
124         {
125             encodeTest!(Char)(codec, t.before, t.after);
126         }
127 
128         // Check decoding
129         Test[] decode_tests = [
130            Test("", ""), // saftey check
131            Test("&#80;", "P"),
132            Test("&#x50;", "P"),
133            Test("&amp;", "&"),
134            Test("&apos;", "'"),
135            Test("&quot;", "\""),
136            Test("&lt;", "<"),
137            Test("&gt;", ">"),
138            Test("©", "©"), // trick question
139            Test("&amp;#23;&#80;", "&#23;P") // double encoding
140            ];
141 
142         foreach ( t; decode_tests )
143         {
144             decodeTest!(Char)(codec, t.before, t.after);
145         }
146     }
147 }
148 
149 unittest
150 {
151     test!(char)();
152     test!(wchar)();
153     test!(dchar)();
154 }