using System;
using System.IO;
using System.Text;
using GisSharpBlog.NetTopologySuite.IO;
// http://java.sun.com/j2se/1.4/docs/api/java/io/StreamTokenizer.html
// a better implementation could be written. Here is a good Java implementation of StreamTokenizer.
// http://www.flex-compiler.lcs.mit.edu/Harpoon/srcdoc/java/io/StreamTokenizer.html
// a C# StringTokenizer
// http://sourceforge.net/snippet/detail.php?type=snippet&id=101171
// Diego Guidi says: for my port i have used the RTools.Util.StreamTokenized, and seems very powerful!
// this code is present only for compatibility with GeoTools.NET code.
namespace GisSharpBlog.NetTopologySuite.Utilities
{
///
/// The StreamTokenizer class takes an input stream and parses it into "tokens",
/// allowing the tokens to be read one at a time.
/// The parsing process is controlled by a table and a number of flags that can be set to various states.
/// The stream tokenizer can recognize identifiers, numbers, quoted strings, and various comment style.
///
///
/// This is a crude c# implementation of Java's
/// StreamTokenizer class.
///
[Obsolete("This class is only for GeoTools.NET code compatibility: use RTools.Util.StreamTokenizer instead.")]
public class GeoToolsStreamTokenizer
{
TokenType _currentTokenType;
TextReader _reader;
string _currentToken;
bool _ignoreWhitespace = false;
int _lineNumber=1;
int _colNumber=1;
///
/// Initializes a new instance of the StreamTokenizer class.
///
/// A TextReader with some text to read.
/// Flag indicating whether whitespace should be ignored.
public GeoToolsStreamTokenizer(TextReader reader, bool ignoreWhitespace)
{
if (reader == null)
throw new ArgumentNullException("reader");
_reader = reader;
_ignoreWhitespace = ignoreWhitespace;
}
///
/// The current line number of the stream being read.
///
public int LineNumber
{
get
{
return _lineNumber;
}
}
///
/// The current column number of the stream being read.
///
public int Column
{
get
{
return _colNumber;
}
}
///
/// If the current token is a number, this field contains the value of that number.
///
///
/// If the current token is a number, this field contains the value of that number. The current token is a number when the value of the ttype field is TT_NUMBER.
///
/// Current token is not a number in a valid format.
public double GetNumericValue()
{
string number = this.GetStringValue();
if (this.GetTokenType() == TokenType.Number)
return double.Parse(number);
throw new ParseException(String.Format("The token '{0}' is not a number at line {1} column {2}.", number, this.LineNumber, this.Column));;
}
///
/// If the current token is a word token, this field contains a string giving the characters of the word token.
///
public string GetStringValue()
{
return _currentToken;
}
///
/// Gets the token type of the current token.
///
///
public TokenType GetTokenType()
{
return _currentTokenType;
}
///
/// Returns the next token.
///
/// Determines is whitespace is ignored. True if whitespace is to be ignored.
/// The TokenType of the next token.
public TokenType NextToken(bool ignoreWhitespace)
{
TokenType nextTokenType;
if (ignoreWhitespace)
nextTokenType= NextNonWhitespaceToken();
else nextTokenType=NextTokenAny();
return nextTokenType;
}
///
/// Returns the next token.
///
/// The TokenType of the next token.
public TokenType NextToken()
{
return NextToken(_ignoreWhitespace);
}
///
///
///
///
private TokenType NextTokenAny()
{
TokenType nextTokenType = TokenType.Eof;
char[] chars = new char[1];
_currentToken=String.Empty;
_currentTokenType = TokenType.Eof;
int finished = _reader.Read(chars,0,1);
bool isNumber=false;
bool isWord=false;
byte[] ba=null;
ASCIIEncoding AE = new ASCIIEncoding();
char[] ascii=null;
Char currentCharacter;
Char nextCharacter;
while (finished != 0 )
{
// convert int to char
ba = new Byte[]{(byte)_reader.Peek()};
ascii = AE.GetChars(ba);
currentCharacter = chars[0];
nextCharacter = ascii[0];
_currentTokenType = GetType(currentCharacter);
nextTokenType = GetType(nextCharacter);
// handling of words with _
if (isWord && currentCharacter=='_')
_currentTokenType= TokenType.Word;
// handing of words ending in numbers
if (isWord && _currentTokenType==TokenType.Number)
_currentTokenType= TokenType.Word;
if (_currentTokenType==TokenType.Word && nextCharacter=='_')
{
// enable words with _ inbetween
nextTokenType = TokenType.Word;
isWord=true;
}
if (_currentTokenType==TokenType.Word && nextTokenType==TokenType.Number)
{
// enable words ending with numbers
nextTokenType = TokenType.Word;
isWord=true;
}
// handle negative numbers
if (currentCharacter=='-' && nextTokenType==TokenType.Number && isNumber ==false)
{
_currentTokenType= TokenType.Number;
nextTokenType = TokenType.Number;
}
// this handles numbers with a decimal point
if (isNumber && nextTokenType == TokenType.Number && currentCharacter=='.' )
_currentTokenType = TokenType.Number;
if (_currentTokenType == TokenType.Number && nextCharacter=='.' && isNumber ==false)
{
nextTokenType = TokenType.Number;
isNumber = true;
}
_colNumber++;
if (_currentTokenType==TokenType.Eol)
{
_lineNumber++;
_colNumber=1;
}
_currentToken = _currentToken + currentCharacter;
if (_currentTokenType!=nextTokenType)
finished = 0;
else if (_currentTokenType==TokenType.Symbol && currentCharacter!='-')
finished = 0;
else finished = _reader.Read(chars,0,1);
}
return _currentTokenType;
}
///
/// Determines a characters type (e.g. number, symbols, character).
///
/// The character to determine.
/// The TokenType the character is.
private TokenType GetType(char character)
{
if (Char.IsDigit(character))
return TokenType.Number;
else if (Char.IsLetter(character))
return TokenType.Word;
else if (character == '\n')
return TokenType.Eol;
else if (Char.IsWhiteSpace(character) || Char.IsControl(character))
return TokenType.Whitespace;
else // (Char.IsSymbol(character))
return TokenType.Symbol;
}
///
/// Returns next token that is not whitespace.
///
///
private TokenType NextNonWhitespaceToken()
{
TokenType tokentype = this.NextTokenAny();
while (tokentype== TokenType.Whitespace || tokentype== TokenType.Eol)
tokentype = this.NextTokenAny();
return tokentype;
}
}
}