All Downloads are FREE. Search and download functionalities are using the official Maven repository.

brut.androlib.res.xml.ResXmlEncoders Maven / Gradle / Ivy

There is a newer version: 1.4.4-5
Show newest version
/**
 *  Copyright 2011 Ryszard Wiśniewski 
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package brut.androlib.res.xml;

import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Ryszard Wiśniewski 
 */
public final class ResXmlEncoders {

    public static String escapeXmlChars(String str) {
        return str.replace("&", "&").replace("<", "<");
    }

    public static String encodeAsResXmlAttr(String str) {
        if (str.isEmpty()) {
            return str;
        }

        char[] chars = str.toCharArray();
        StringBuilder out = new StringBuilder(str.length() + 10);

        switch (chars[0]) {
            case '#':
            case '@':
            case '?':
                out.append('\\');
        }

        for (char c : chars) {
            switch (c) {
                case '\\':
                    out.append('\\');
                    break;
                case '"':
                    out.append(""");
                    continue;
                case '\n':
                    out.append("\\n");
                    continue;
                default:
                    if (!isPrintableChar(c)) {
                        out.append(String.format("\\u%04x", (int) c));
                        continue;
                    }
            }
            out.append(c);
        }

        return out.toString();
    }

    public static String encodeAsXmlValue(String str) {
        if (str.isEmpty()) {
            return str;
        }

        char[] chars = str.toCharArray();
        StringBuilder out = new StringBuilder(str.length() + 10);

        switch (chars[0]) {
            case '#':
            case '@':
            case '?':
                out.append('\\');
        }

        boolean isInStyleTag = false;
        int startPos = 0;
        boolean enclose = false;
        boolean wasSpace = true;
        for (char c : chars) {
            if (isInStyleTag) {
                if (c == '>') {
                    isInStyleTag = false;
                    startPos = out.length() + 1;
                    enclose = false;
                }
            } else if (c == ' ') {
                if (wasSpace) {
                    enclose = true;
                }
                wasSpace = true;
            } else {
                wasSpace = false;
                switch (c) {
                    case '\\':
                        out.append('\\');
                        break;
                    case '\'':
                    case '\n':
                        enclose = true;
                        break;
                    case '"':
                        out.append('\\');
                        break;
                    case '<':
                        isInStyleTag = true;
                        if (enclose) {
                            out.insert(startPos, '"').append('"');
                        }
                        break;
                    default:
                        if (!isPrintableChar(c)) {
                            out.append(String.format("\\u%04x", (int) c));
                            continue;
                        }
                }
            }
            out.append(c);
        }

        if (enclose || wasSpace) {
            out.insert(startPos, '"').append('"');
        }

        return out.toString();
    }

    public static boolean hasMultipleNonPositionalSubstitutions(String str) {
        return findNonPositionalSubstitutions(str, 2).size() > 1;
    }

    public static String enumerateNonPositionalSubstitutions(String str) {
        List subs = findNonPositionalSubstitutions(str, -1);
        if (subs.size() < 2) {
            return str;
        }

        StringBuilder out = new StringBuilder();
        int pos = 0;
        int count = 0;
        for (Integer sub : subs) {
            out.append(str.substring(pos, ++sub)).append(++count).append('$');
            pos = sub;
        }
        out.append(str.substring(pos));

        return out.toString();
    }

    /**
     * It searches for "%", but not "%%" nor "%(\d)+\$"
     */
    private static List findNonPositionalSubstitutions(String str,
            int max) {
        int pos = 0;
        int pos2 = 0;
        int count = 0;
        int length = str.length();
        List ret = new ArrayList();
        while((pos2 = (pos = str.indexOf('%', pos2)) + 1) != 0) {
            if (pos2 == length) {
                break;
            }
            char c = str.charAt(pos2++);
            if (c == '%') {
                continue;
            }
            if (c >= '0' && c <= '9' && pos2 < length) {
                do {
                    c = str.charAt(pos2++);
                } while (c >= '0' && c <= '9' && pos2 < length);
                if (c == '$') {
                    continue;
                }
            }

            ret.add(pos);
            if (max != -1 && ++count >= max) {
                break;
            }
        }

        return ret;
    }

    private static boolean isPrintableChar(char c) {
        Character.UnicodeBlock block = Character.UnicodeBlock.of(c);
        return !Character.isISOControl(c)
                && c != KeyEvent.CHAR_UNDEFINED
                && block != null
                && block != Character.UnicodeBlock.SPECIALS;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy