📄 clargsparser.java
字号:
* @param array
* the original array
* @param index
* the cut-point in array
* @param charIndex
* the cut-point in element of array
* @return the result array
*/
private final String[] subArray(final String[] array, final int index, final int charIndex) {
final int remaining = array.length - index;
final String[] result = new String[remaining];
if (remaining > 1) {
System.arraycopy(array, index + 1, result, 1, remaining - 1);
}
result[0] = array[index].substring(charIndex - 1);
return result;
}
/**
* Actually parse arguments
*/
private final void parse() throws ParseException {
if (0 == m_args.length) {
return;
}
m_stringLength = m_args[m_argIndex].length();
while (true) {
m_ch = peekAtChar();
if (m_argIndex >= m_args.length) {
break;
}
if (null != m_control && m_control.isFinished(m_lastOptionId)) {
// this may need mangling due to peeks
m_unparsedArgs = subArray(m_args, m_argIndex, m_stringIndex);
return;
}
if (STATE_OPTION_MODE == m_state) {
// if get to an arg barrier then return to normal mode
// else continue accumulating options
if (0 == m_ch) {
getChar(); // strip the null
m_state = STATE_NORMAL;
} else {
parseShortOption();
}
} else if (STATE_NORMAL == m_state) {
parseNormal();
} else if (STATE_NO_OPTIONS == m_state) {
// should never get to here when stringIndex != 0
addOption(new CLOption(m_args[m_argIndex++]));
} else {
parseArguments();
}
}
// Reached end of input arguments - perform final processing
if (m_option != null) {
if (STATE_OPTIONAL_ARG == m_state) {
m_options.addElement(m_option);
} else if (STATE_REQUIRE_ARG == m_state) {
final CLOptionDescriptor descriptor = getDescriptorFor(m_option.getDescriptor().getId());
final String message = "Missing argument to option " + getOptionDescription(descriptor);
throw new ParseException(message, 0);
} else if (STATE_REQUIRE_2ARGS == m_state) {
if (1 == m_option.getArgumentCount()) {
m_option.addArgument("");
m_options.addElement(m_option);
} else {
final CLOptionDescriptor descriptor = getDescriptorFor(m_option.getDescriptor().getId());
final String message = "Missing argument to option " + getOptionDescription(descriptor);
throw new ParseException(message, 0);
}
} else {
throw new ParseException("IllegalState " + m_state + ": " + m_option, 0);
}
}
}
private final String getOptionDescription(final CLOptionDescriptor descriptor) {
if (m_isLong) {
return "--" + descriptor.getName();
} else {
return "-" + (char) descriptor.getId();
}
}
private final char peekAtChar() {
if (INVALID == m_lastChar) {
m_lastChar = readChar();
}
return (char) m_lastChar;
}
private final char getChar() {
if (INVALID != m_lastChar) {
final char result = (char) m_lastChar;
m_lastChar = INVALID;
return result;
} else {
return readChar();
}
}
private final char readChar() {
if (m_stringIndex >= m_stringLength) {
m_argIndex++;
m_stringIndex = 0;
if (m_argIndex < m_args.length) {
m_stringLength = m_args[m_argIndex].length();
} else {
m_stringLength = 0;
}
return 0;
}
if (m_argIndex >= m_args.length) {
return 0;
}
return m_args[m_argIndex].charAt(m_stringIndex++);
}
private char m_tokesep; // Keep track of token separator
private final Token nextToken(final char[] separators) {
m_ch = getChar();
if (isSeparator(m_ch, separators)) {
m_tokesep=m_ch;
m_ch = getChar();
return new Token(TOKEN_SEPARATOR, null);
}
final StringBuffer sb = new StringBuffer();
do {
sb.append(m_ch);
m_ch = getChar();
} while (!isSeparator(m_ch, separators));
m_tokesep=m_ch;
return new Token(TOKEN_STRING, sb.toString());
}
private final boolean isSeparator(final char ch, final char[] separators) {
for (int i = 0; i < separators.length; i++) {
if (ch == separators[i]) {
return true;
}
}
return false;
}
private final void addOption(final CLOption option) {
m_options.addElement(option);
m_lastOptionId = option.getDescriptor().getId();
m_option = null;
}
private final void parseOption(final CLOptionDescriptor descriptor, final String optionString)
throws ParseException {
if (null == descriptor) {
throw new ParseException("Unknown option " + optionString, 0);
}
m_state = getStateFor(descriptor);
m_option = new CLOption(descriptor);
if (STATE_NORMAL == m_state) {
addOption(m_option);
}
}
private final void parseShortOption() throws ParseException {
m_ch = getChar();
final CLOptionDescriptor descriptor = getDescriptorFor(m_ch);
m_isLong = false;
parseOption(descriptor, "-" + m_ch);
if (STATE_NORMAL == m_state) {
m_state = STATE_OPTION_MODE;
}
}
private final void parseArguments() throws ParseException {
if (STATE_REQUIRE_ARG == m_state) {
if ('=' == m_ch || 0 == m_ch) {
getChar();
}
final Token token = nextToken(NULL_SEPARATORS);
m_option.addArgument(token.getValue());
addOption(m_option);
m_state = STATE_NORMAL;
} else if (STATE_OPTIONAL_ARG == m_state) {
if ('-' == m_ch || 0 == m_ch) {
getChar(); // consume stray character
addOption(m_option);
m_state = STATE_NORMAL;
return;
}
if (m_isLong && '=' != m_tokesep){ // Long optional arg must have = as separator
addOption(m_option);
m_state = STATE_NORMAL;
return;
}
if ('=' == m_ch) {
getChar();
}
final Token token = nextToken(NULL_SEPARATORS);
m_option.addArgument(token.getValue());
addOption(m_option);
m_state = STATE_NORMAL;
} else if (STATE_REQUIRE_2ARGS == m_state) {
if (0 == m_option.getArgumentCount()) {
/*
* Fix bug: -D arg1=arg2 was causing parse error; however
* --define arg1=arg2 is OK This seems to be because the parser
* skips the terminator for the long options, but was not doing
* so for the short options.
*/
if (!m_isLong) {
if (0 == peekAtChar()) {
getChar();
}
}
final Token token = nextToken(ARG_SEPARATORS);
if (TOKEN_SEPARATOR == token.getType()) {
final CLOptionDescriptor descriptor = getDescriptorFor(m_option.getDescriptor().getId());
final String message = "Unable to parse first argument for option "
+ getOptionDescription(descriptor);
throw new ParseException(message, 0);
} else {
m_option.addArgument(token.getValue());
}
// Are we about to start a new option?
if (0 == m_ch && '-' == peekAtChar()) {
// Yes, so the second argument is missing
m_option.addArgument("");
m_options.addElement(m_option);
m_state = STATE_NORMAL;
}
} else // 2nd argument
{
final StringBuffer sb = new StringBuffer();
m_ch = getChar();
while (!isSeparator(m_ch, NULL_SEPARATORS)) {
sb.append(m_ch);
m_ch = getChar();
}
final String argument = sb.toString();
// System.out.println( "Arguement:" + argument );
m_option.addArgument(argument);
addOption(m_option);
m_option = null;
m_state = STATE_NORMAL;
}
}
}
/**
* Parse Options from Normal mode.
*/
private final void parseNormal() throws ParseException {
if ('-' != m_ch) {
// Parse the arguments that are not options
final String argument = nextToken(NULL_SEPARATORS).getValue();
addOption(new CLOption(argument));
m_state = STATE_NORMAL;
} else {
getChar(); // strip the -
if (0 == peekAtChar()) {
throw new ParseException("Malformed option -", 0);
} else {
m_ch = peekAtChar();
// if it is a short option then parse it else ...
if ('-' != m_ch) {
parseShortOption();
} else {
getChar(); // strip the -
// -- sequence .. it can either mean a change of state
// to STATE_NO_OPTIONS or else a long option
if (0 == peekAtChar()) {
getChar();
m_state = STATE_NO_OPTIONS;
} else {
// its a long option
final String optionName = nextToken(ARG_SEPARATORS).getValue();
final CLOptionDescriptor descriptor = getDescriptorFor(optionName);
m_isLong = true;
parseOption(descriptor, "--" + optionName);
}
}
}
}
}
/**
* Build the m_optionIndex lookup map for the parsed options.
*/
private final void buildOptionIndex() {
final int size = m_options.size();
m_optionIndex = new Hashtable(size * 2);
for (int i = 0; i < size; i++) {
final CLOption option = (CLOption) m_options.get(i);
final CLOptionDescriptor optionDescriptor = getDescriptorFor(option.getDescriptor().getId());
m_optionIndex.put(new Integer(option.getDescriptor().getId()), option);
if (null != optionDescriptor && null != optionDescriptor.getName()) {
m_optionIndex.put(optionDescriptor.getName(), option);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -