protected List expandBraces()

in gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Expander.java [238:492]


    protected List<? extends CharSequence> expandBraces(CharSequence arg) throws Exception
    {
        int braces = 0;
        boolean escaped = false;
        boolean doubleQuoted = false;
        boolean singleQuoted = false;
        List<CharSequence> parts = new ArrayList<>();
        int start = 0;
        for (int i = 0; i < arg.length(); i++)
        {
            char c = arg.charAt(i);
            if (doubleQuoted && escaped)
            {
                escaped = false;
            }
            else if (escaped)
            {
                escaped = false;
            }
            else if (singleQuoted)
            {
                if (c == '\'')
                {
                    singleQuoted = false;
                }
            }
            else if (doubleQuoted)
            {
                if (c == '\\')
                {
                    escaped = true;
                }
                else if (c == '\"')
                {
                    doubleQuoted = false;
                }
            }
            else if (c == '\\')
            {
                escaped = true;
            }
            else if (c == '\'')
            {
                singleQuoted = true;
            }
            else if (c == '"')
            {
                doubleQuoted = true;
            }
            else
            {
                if (c == '{')
                {
                    if (braces++ == 0)
                    {
                        if (i > start)
                        {
                            parts.add(arg.subSequence(start, i));
                        }
                        start = i;
                    }
                }
                else if (c == '}')
                {
                    if (--braces == 0)
                    {
                        parts.add(arg.subSequence(start, i + 1));
                        start = i + 1;
                    }
                }
            }
        }
        if (start < arg.length())
        {
            parts.add(arg.subSequence(start, arg.length()));
        }
        if (start == 0)
        {
            return Collections.singletonList(arg);
        }
        List<CharSequence> generated = new ArrayList<>();
        Pattern pattern = Pattern.compile(
                "\\{(((?<intstart>\\-?[0-9]+)\\.\\.(?<intend>\\-?[0-9]+)(\\.\\.(?<intinc>\\-?0*[1-9][0-9]*))?)" +
                "|((?<charstart>\\S)\\.\\.(?<charend>\\S)))\\}");
        for (CharSequence part : parts)
        {
            List<CharSequence> generators = new ArrayList<>();
            Matcher matcher = pattern.matcher(part);
            if (matcher.matches())
            {
                if (matcher.group("intstart") != null)
                {
                    int intstart = Integer.parseInt(matcher.group("intstart"));
                    int intend = Integer.parseInt(matcher.group("intend"));
                    int intinc = matcher.group("intinc") != null ? Integer.parseInt(matcher.group("intinc")) : 1;
                    if (intstart > intend)
                    {
                        if (intinc < 0)
                        {
                            int k = intstart;
                            intstart = intend;
                            intend = k;
                        }
                        intinc = -intinc;
                    }
                    else
                    {
                        if (intinc < 0)
                        {
                            int k = intstart;
                            intstart = intend;
                            intend = k;
                        }
                    }
                    if (intinc > 0)
                    {
                        for (int k = intstart; k <= intend; k += intinc)
                        {
                            generators.add(Integer.toString(k));
                        }
                    }
                    else
                    {
                        for (int k = intstart; k >= intend; k += intinc)
                        {
                            generators.add(Integer.toString(k));
                        }
                    }
                }
                else
                {
                    char charstart = matcher.group("charstart").charAt(0);
                    char charend = matcher.group("charend").charAt(0);
                    if (charstart < charend)
                    {
                        for (char c = charstart; c <= charend; c++)
                        {
                            generators.add(Character.toString(c));
                        }
                    }
                    else
                    {
                        for (char c = charstart; c >= charend; c--)
                        {
                            generators.add(Character.toString(c));
                        }
                    }
                }
            }
            else if (part.charAt(0) == '{' && part.charAt(part.length() - 1) == '}')
            {
                // Split on commas
                braces = 0;
                escaped = false;
                doubleQuoted = false;
                singleQuoted = false;
                start = 1;
                for (int i = 1; i < part.length() - 1; i++)
                {
                    char c = part.charAt(i);
                    if (doubleQuoted && escaped)
                    {
                        escaped = false;
                    }
                    else if (escaped)
                    {
                        escaped = false;
                    }
                    else if (singleQuoted)
                    {
                        if (c == '\'')
                        {
                            singleQuoted = false;
                        }
                    }
                    else if (doubleQuoted)
                    {
                        if (c == '\\')
                        {
                            escaped = true;
                        }
                        else if (c == '\"')
                        {
                            doubleQuoted = false;
                        }
                    }
                    else if (c == '\\')
                    {
                        escaped = true;
                    }
                    else if (c == '\'')
                    {
                        singleQuoted = true;
                    }
                    else if (c == '"')
                    {
                        doubleQuoted = true;
                    }
                    else
                    {
                        if (c == '}')
                        {
                            braces--;
                        }
                        else if (c == '{')
                        {
                            braces++;
                        }
                        else if (c == ',' && braces == 0)
                        {
                            generators.add(part.subSequence(start, i));
                            start = i + 1;
                        }
                    }
                }
                if (start < part.length() - 1)
                {
                    generators.add(part.subSequence(start, part.length() - 1));
                }
                List<CharSequence> l = new ArrayList<>();
                for (CharSequence cs : generators) {
                    Object o1 = expand(cs, false, false, false);
                    for (Object o2 : toCollection(o1)) {
                        l.add(String.valueOf(o2));
                    }
                }
                generators = l;

                // If there's no splitting comma, expand with the braces
                if (generators.size() < 2)
                {
                    generators = Collections.<CharSequence>singletonList(part.toString());
                }
            }
            else
            {
                generators.add(part.toString());
            }
            if (generated.isEmpty())
            {
                generated.addAll(generators);
            }
            else
            {
                List<CharSequence> prevGenerated = generated;
                generated = new ArrayList<>();
                for (CharSequence s : generators) {
                    for (Object cs : prevGenerated) {
                        generated.add(String.valueOf(cs) + s);
                    }
                }
            }
        }
        return generated;
    }