1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.ini4j.spi;
17
18 public class EscapeTool
19 {
20 private static final String ESCAPE_LETTERS = "\\tnfbr";
21 private static final String ESCAPEABLE_CHARS = "\\\t\n\f\b\r";
22 private static final char ESCAPE_CHAR = '\\';
23 static final char[] HEX = "0123456789abcdef".toCharArray();
24 private static final EscapeTool INSTANCE = ServiceFinder.findService(EscapeTool.class);
25 private static final char ASCII_MIN = 0x20;
26 private static final char ASCII_MAX = 0x7e;
27 static final int HEX_DIGIT_MASK = 0x0f;
28 static final int HEX_DIGIT_3_OFFSET = 4;
29 static final int HEX_DIGIT_2_OFFSET = 8;
30 static final int HEX_DIGIT_1_OFFSET = 12;
31 static final int HEX_RADIX = 16;
32 private static final int UNICODE_HEX_DIGITS = 4;
33 static final char DOUBLE_QUOTE = '"';
34
35 public static EscapeTool getInstance()
36 {
37 return INSTANCE;
38 }
39
40 public String escape(String line)
41 {
42 int len = line.length();
43 StringBuilder buffer = new StringBuilder(len * 2);
44
45 for (int i = 0; i < len; i++)
46 {
47 char c = line.charAt(i);
48 int idx = ESCAPEABLE_CHARS.indexOf(c);
49
50 if (idx >= 0)
51 {
52 buffer.append(ESCAPE_CHAR);
53 buffer.append(ESCAPE_LETTERS.charAt(idx));
54 }
55 else
56 {
57 if ((c < ASCII_MIN) || (c > ASCII_MAX))
58 {
59 escapeBinary(buffer, c);
60 }
61 else
62 {
63 buffer.append(c);
64 }
65 }
66 }
67
68 return buffer.toString();
69 }
70
71 public String quote(String value)
72 {
73 String ret = value;
74
75 if ((value != null) && (value.length() != 0))
76 {
77 StringBuilder buff = new StringBuilder();
78
79 buff.append(DOUBLE_QUOTE);
80 for (int i = 0; i < value.length(); i++)
81 {
82 char c = value.charAt(i);
83
84 if ((c == ESCAPE_CHAR) || (c == DOUBLE_QUOTE))
85 {
86 buff.append(ESCAPE_CHAR);
87 }
88
89 buff.append(c);
90 }
91
92 buff.append(DOUBLE_QUOTE);
93 ret = buff.toString();
94 }
95
96 return ret;
97 }
98
99 public String unescape(String line)
100 {
101 int n = line.length();
102 StringBuilder buffer = new StringBuilder(n);
103 int i = 0;
104
105 while (i < n)
106 {
107 char c = line.charAt(i++);
108
109 if (c == ESCAPE_CHAR)
110 {
111 c = line.charAt(i++);
112 int next = unescapeBinary(buffer, c, line, i);
113
114 if (next == i)
115 {
116 int idx = ESCAPE_LETTERS.indexOf(c);
117
118 if (idx >= 0)
119 {
120 c = ESCAPEABLE_CHARS.charAt(idx);
121 }
122
123 buffer.append(c);
124 }
125 else
126 {
127 i = next;
128 }
129 }
130 else
131 {
132 buffer.append(c);
133 }
134 }
135
136 return buffer.toString();
137 }
138
139 public String unquote(String value)
140 {
141 StringBuilder buff = new StringBuilder();
142 boolean escape = false;
143
144 for (int i = 1; i < (value.length() - 1); i++)
145 {
146 char c = value.charAt(i);
147
148 if (c == ESCAPE_CHAR)
149 {
150 if (!escape)
151 {
152 escape = true;
153
154 continue;
155 }
156
157 escape = false;
158 }
159
160 buff.append(c);
161 }
162
163 return buff.toString();
164 }
165
166 void escapeBinary(StringBuilder buff, char c)
167 {
168 buff.append("\\u");
169 buff.append(HEX[(c >>> HEX_DIGIT_1_OFFSET) & HEX_DIGIT_MASK]);
170 buff.append(HEX[(c >>> HEX_DIGIT_2_OFFSET) & HEX_DIGIT_MASK]);
171 buff.append(HEX[(c >>> HEX_DIGIT_3_OFFSET) & HEX_DIGIT_MASK]);
172 buff.append(HEX[c & HEX_DIGIT_MASK]);
173 }
174
175 int unescapeBinary(StringBuilder buff, char escapeType, String line, int index)
176 {
177 int ret = index;
178
179 if (escapeType == 'u')
180 {
181 try
182 {
183 buff.append((char) Integer.parseInt(line.substring(index, index + UNICODE_HEX_DIGITS), HEX_RADIX));
184 ret = index + UNICODE_HEX_DIGITS;
185 }
186 catch (Exception x)
187 {
188 throw new IllegalArgumentException("Malformed \\uxxxx encoding.", x);
189 }
190 }
191
192 return ret;
193 }
194 }