001    /*
002     * Copyright 2005,2009 Ivan SZKIBA
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.ini4j.spi;
017    
018    public class EscapeTool
019    {
020        private static final char[] HEX = "0123456789abcdef".toCharArray();
021        private static final EscapeTool INSTANCE = ServiceFinder.findService(EscapeTool.class);
022        private static final char ASCII_MIN = 0x20;
023        private static final char ASCII_MAX = 0x7e;
024        private static final int HEX_DIGIT_MASK = 0x0f;
025        private static final int DIGIT_3_OFFSET = 4;
026        private static final int DIGIT_2_OFFSET = 8;
027        private static final int DIGIT_1_OFFSET = 12;
028        private static final int HEX_RADIX = 16;
029        private static final int UNICODE_HEX_DIGITS = 4;
030    
031        public static EscapeTool getInstance()
032        {
033            return INSTANCE;
034        }
035    
036        public String escape(String line)
037        {
038            int len = line.length();
039            StringBuilder buffer = new StringBuilder(len * 2);
040    
041            for (int i = 0; i < len; i++)
042            {
043                char c = line.charAt(i);
044                int idx = "\\\t\n\f".indexOf(c);
045    
046                if (idx >= 0)
047                {
048                    buffer.append('\\');
049                    buffer.append("\\tnf".charAt(idx));
050                }
051                else
052                {
053                    if ((c < ASCII_MIN) || (c > ASCII_MAX))
054                    {
055                        buffer.append("\\u");
056                        buffer.append(HEX[(c >>> DIGIT_1_OFFSET) & HEX_DIGIT_MASK]);
057                        buffer.append(HEX[(c >>> DIGIT_2_OFFSET) & HEX_DIGIT_MASK]);
058                        buffer.append(HEX[(c >>> DIGIT_3_OFFSET) & HEX_DIGIT_MASK]);
059                        buffer.append(HEX[c & HEX_DIGIT_MASK]);
060                    }
061                    else
062                    {
063                        buffer.append(c);
064                    }
065                }
066            }
067    
068            return buffer.toString();
069        }
070    
071        public String unescape(String line)
072        {
073            int n = line.length();
074            StringBuilder buffer = new StringBuilder(n);
075            int i = 0;
076    
077            while (i < n)
078            {
079                char c = line.charAt(i++);
080    
081                if (c == '\\')
082                {
083                    c = line.charAt(i++);
084                    if (c == 'u')
085                    {
086                        try
087                        {
088                            c = (char) Integer.parseInt(line.substring(i, i + UNICODE_HEX_DIGITS), HEX_RADIX);
089                            i += UNICODE_HEX_DIGITS;
090                        }
091                        catch (Exception x)
092                        {
093                            throw new IllegalArgumentException("Malformed \\uxxxx encoding.", x);
094                        }
095                    }
096                    else
097                    {
098                        int idx = "\\tnf".indexOf(c);
099    
100                        if (idx >= 0)
101                        {
102                            c = "\\\t\n\f".charAt(idx);
103                        }
104                    }
105                }
106    
107                buffer.append(c);
108            }
109    
110            return buffer.toString();
111        }
112    }