blob: 709a1602f33d38d445603fe048d7bc5562a1e547 [file] [log] [blame]
using System;
using System.IO;
using Console = Lucene.Net.Util.SystemConsole;
namespace Lucene.Net.QueryParsers.Classic
{
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// <summary>
/// An efficient implementation of JavaCC's <see cref="ICharStream"/> interface.
/// <para/>
/// Note that
/// this does not do line-number counting, but instead keeps track of the
/// character position of the token in the input, as required by Lucene's <see cref="Lucene.Net.Analysis.Token" />
/// API.
/// </summary>
public sealed class FastCharStream : ICharStream
{
internal char[] buffer = null;
internal int bufferLength = 0; // end of valid chars
internal int bufferPosition = 0; // next char to read
internal int tokenStart = 0; // offset in buffer
internal int bufferStart = 0; // position in file of buffer
internal TextReader input; // source of chars
/// <summary>
/// Constructs from a <see cref="TextReader"/>.
/// </summary>
public FastCharStream(TextReader r)
{
input = r;
}
public char ReadChar()
{
if (bufferPosition >= bufferLength)
Refill();
return buffer[bufferPosition++];
}
private void Refill()
{
int newPosition = bufferLength - tokenStart;
if (tokenStart == 0)
{
// token won't fit in buffer
if (buffer == null)
{
// first time: alloc buffer
buffer = new char[2048];
}
else if (bufferLength == buffer.Length)
{
// grow buffer
char[] newBuffer = new char[buffer.Length * 2];
Array.Copy(buffer, 0, newBuffer, 0, bufferLength);
buffer = newBuffer;
}
}
else
{
// shift token to front
Array.Copy(buffer, tokenStart, buffer, 0, newPosition);
}
bufferLength = newPosition; // update state
bufferPosition = newPosition;
bufferStart += tokenStart;
tokenStart = 0;
int charsRead = input.Read(buffer, newPosition, buffer.Length - newPosition);
if (charsRead <= 0)
throw new IOException("read past eof");
else
bufferLength += charsRead;
}
public char BeginToken()
{
tokenStart = bufferPosition;
return ReadChar();
}
public void BackUp(int amount)
{
bufferPosition -= amount;
}
public string Image => new string(buffer, tokenStart, bufferPosition - tokenStart);
public char[] GetSuffix(int len)
{
char[] value = new char[len];
Array.Copy(buffer, bufferPosition - len, value, 0, len);
return value;
}
public void Done()
{
try
{
input.Dispose();
}
catch (IOException e)
{
Console.Error.WriteLine("Caught: " + e + "; ignoring.");
}
}
public int Column => bufferStart + bufferPosition;
public int Line => 1;
public int EndColumn => bufferStart + bufferPosition;
public int EndLine => 1;
public int BeginColumn => bufferStart + tokenStart;
public int BeginLine => 1;
}
}