/*
* Copyright 2016 Skynav, Inc. All rights reserved.
* Portions Copyright 2009 Extensible Formatting Systems, Inc (XFSI).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY SKYNAV, INC. AND ITS CONTRIBUTORS “AS IS” AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL SKYNAV, INC. OR ITS CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.xfsi.xav.util.property;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
/**
* Tokenizer class for XML message keys
*/
public class PropertyMessageKeyTokenizer {
private static class TableEntry {
public boolean isNumeric = false;
public boolean isAlphabetic = false;
public boolean isFraction = false;
}
final public static int TT_EOF = -1;
final public static int TT_NUMBER = -2;
final public static int TT_WORD = -3;
final public static int TT_FRACTION = -4;
public int ttype;
public String sval;
public int nval;
public int tokenLen;
private PushbackReader pushIn = null;
private TableEntry[] lookup = new TableEntry[257];
private boolean pushBack = false;
public PropertyMessageKeyTokenizer() {
for (int pos = 0; pos < lookup.length; pos++) {
lookup[pos] = new TableEntry();
}
reset();
}
public void setReader(Reader r) {
pushIn = new PushbackReader(r);
}
private int chrRead() throws IOException {
int chr = pushIn.read();
if (chr == -1)
chr = 256; /* EOF as invalid char */
return chr;
}
public int nextToken() throws IOException {
if (pushBack == true) {
/* Do nothing */
pushBack = false;
return (ttype);
} else {
return (nextTokenType());
}
}
private int nextTokenType() throws IOException {
int chr = chrRead();
sval = null; // Reset
tokenLen = 1;
if (lookup[chr].isFraction) {
// Return fraction token
ttype = TT_FRACTION;
} else if (lookup[chr].isNumeric) {
/* Parse the number and return */
StringBuffer buffer = new StringBuffer(4);
while (lookup[chr].isNumeric) {
buffer.append((char) (chr & 0xFF));
chr = chrRead();
}
/* For next token */
pushIn.unread(chr);
ttype = TT_NUMBER;
try {
tokenLen = buffer.length();
nval = Integer.parseInt(buffer.toString());
} catch (NumberFormatException e) {
nval = 0;
}
} else if (lookup[chr].isAlphabetic) {
/* Parse the word and return */
StringBuffer buffer = new StringBuffer(4);
// Words may NOT contain numeric chars
while (lookup[chr].isAlphabetic) {
buffer.append((char) (chr & 0xFF));
chr = chrRead();
}
/* For next token */
pushIn.unread(chr);
ttype = TT_WORD;
tokenLen = buffer.length();
sval = buffer.toString();
} else {
/* Just return it as a token */
if (chr == 256)
ttype = TT_EOF;
else
ttype = chr & 0xFF;
}
return (ttype);
}
private void parseNumbers() {
for (int letter = '0'; letter <= '9'; letter++) {
lookup[letter].isNumeric = true;
}
}
public void invalidChar(int ch) {
lookup[ch].isAlphabetic = false;
lookup[ch].isNumeric = false;
lookup[ch].isFraction = false;
}
public void fractionChar(int ch) {
lookup[ch].isAlphabetic = false;
lookup[ch].isNumeric = false;
lookup[ch].isFraction = true;
}
public void invalidChars(int low, int hi) {
for (int letter = low; letter <= hi; letter++) {
invalidChar(letter);
}
}
public void pushBack() {
pushBack = true;
}
public void reset() {
wordChars('A', 'Z');
wordChars('a', 'z');
invalidChar(256); /* EOF */
fractionChar('.');
parseNumbers();
}
public String toString() {
if (ttype == TT_EOF) {
return ("EOF");
} else if (ttype == TT_NUMBER) {
return ("Token[n=" + nval + "]");
} else {
return ("Token[s=" + sval + "]");
}
}
public void wordChars(int low, int hi) {
for (int letter = low; letter <= hi; letter++) {
lookup[letter].isAlphabetic = true;
}
}
}