View Javadoc

1   /*
2    * Copyright 2005,2009 Ivan SZKIBA
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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 }