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

org.pitest.process.ArgLineParser Maven / Gradle / Ivy

There is a newer version: 1.17.1
Show newest version
package org.pitest.process;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.StringTokenizer;

import static org.pitest.process.ArgLineParser.State.START;

/**
 * Simple state machine to split arglines into sections. Arglines may
 * contain single or double quotes, which might be escaped.
 */
public class ArgLineParser {

    private static final String ESCAPE_CHAR = "\\";
    private static final String SINGLE_QUOTE = "\'";
    public static final String DOUBLE_QUOTE = "\"";

    public static List split(String in) {
        return process(stripWhiteSpace(in));
    }

    private static List process(String in) {
        if (in.isEmpty()) {
            return Collections.emptyList();
        }

        final StringTokenizer tokenizer = new StringTokenizer(in, "\"\' \\", true);
        List tokens = new ArrayList<>();

        Deque state = new ArrayDeque<>();
        state.push(START);
        StringBuilder current = new StringBuilder();
        while (tokenizer.hasMoreTokens()) {
            String token = tokenizer.nextToken();
            switch (state.peek()) {
                case START:
                    if (token.equals(SINGLE_QUOTE)) {
                        state.push(State.IN_QUOTE);
                    } else if (token.equals(DOUBLE_QUOTE)) {
                        state.push(State.IN_DOUBLE_QUOTE);
                    } else if (token.equals(" ")) {
                        if (current.length() != 0) {
                            tokens.add(current.toString());
                            current = new StringBuilder();
                        }
                    } else {
                        current.append(token);
                        if (token.equals(ESCAPE_CHAR)) {
                            state.push(State.IN_ESCAPE);
                        }
                    }
                    break;
                case IN_QUOTE:
                    if (token.equals(SINGLE_QUOTE)) {
                        state.pop();
                    } else {
                        current.append(token);
                        if (token.equals(ESCAPE_CHAR)) {
                            state.push(State.IN_ESCAPE);
                        }
                    }
                    break;
                case IN_DOUBLE_QUOTE:
                    if (token.equals(DOUBLE_QUOTE)) {
                        state.pop();
                    } else {
                        current.append(token);
                        if (token.equals(ESCAPE_CHAR)) {
                            state.push(State.IN_ESCAPE);
                        }
                    }
                    break;
                case IN_ESCAPE:
                    current.append(token);
                    if (!token.equals(ESCAPE_CHAR)) {
                        state.pop();
                    }
                    break;
            }
        }

        if (current.length() != 0) {
            tokens.add(current.toString());
        }

        if (state.size() != 1) {
            throw new RuntimeException("Unclosed quote in " + in);
        }

        return tokens;
    }

    private static String stripWhiteSpace(String in) {
        if (in == null) {
            return "";
        }
        return in.replaceAll("\\s", " ").trim();
    }

    enum State {
        START, IN_ESCAPE, IN_QUOTE, IN_DOUBLE_QUOTE
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy