// -----------------------------------------------------------------------
//
//
// 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.
//
//
// -----------------------------------------------------------------------
namespace Lucene.Net.Analysis.TokenAttributes
{
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Support;
using Util;
///
/// The term text of a Token
///
///
///
///
/// Java File:
/// lucene/src/java/org/apache/lucene/analysis/tokenattributes/CharTermAttributeImpl.java
///
///
///
/// C# File:
/// src/Lucene.Net/Analysis/TokenAttributes/CharTermAttribute.cs
///
///
///
/// C# Tests:
/// test/Lucene.Net.Test/Analysis/TokenAttributes/CharTermAttributeTest.cs
///
///
///
///
/// The java version has extra methods to work with Java's
/// CharSequence.
/// Java's version of string, StringBuilder, StringBuffer, and CharBuffer
/// all implement this interface. C# does not have a known equivalent.
///
///
[SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix",
Justification = "The class was called Attribute in Java. It would be fun to call it Annotation. However, " +
"its probably best to try to honor the correlating names when possible.")]
public class CharTermAttribute : AttributeBase, ICharTermAttribute
{
private const int MinBufferSize = 10;
private int termLength;
private char[] buffer;
///
/// Initializes a new instance of the class.
///
public CharTermAttribute()
{
this.buffer = CreateBuffer(MinBufferSize);
}
///
/// Gets or sets the internal termBuffer character array which you can then
/// directly alter.
///
/// The buffer.
///
///
/// You may cast this to a char[] rather than calling the ToArray()
/// on .
///
///
/// If the array is too small for the token, use
/// to increase the size. After altering the buffer be sure to call
/// to record the valid characters that
/// were placed into the termBuffer.
///
///
public IEnumerable Buffer
{
get
{
return this.buffer;
}
protected set
{
this.buffer = value.ToArray();
}
}
///
/// Gets or sets the number of valid characters, the length of the term, in
/// the termBuffer array.
///
///
///
///
/// Use this to truncate the termBuffer or to synchronize any external
/// manipulation of the termBuffer.
///
///
/// To grow the size of the array, use first.
///
///
public int Length
{
get { return this.termLength; }
set { this.SetLength(value); }
}
///
/// Appends the specified value.
///
/// The value.
///
/// An instance of for fluent interface
/// chaining purposes.
///
public ICharTermAttribute Append(char value)
{
int newLength = this.termLength + 1;
this.ResizeBuffer(newLength);
this.buffer[newLength] = value;
return this;
}
///
/// Appends the specified to internal buffer or character sequence.
///
/// The value.
///
/// An instance of for fluent interface
/// chaining purposes.
///
public ICharTermAttribute Append(string value)
{
return Append(value, 0, value == null ? 0 : value.Length);
}
///
/// Appends the specified to internal buffer or character sequence.
///
/// The value.
/// the index of string to start the copy.
/// The length of the string that is to be copied.
///
/// An instance of for fluent interface
/// chaining purposes.
///
public ICharTermAttribute Append(string value, int startingIndex, int length)
{
if (value == null)
return this.AppendNull();
value.CopyTo(startingIndex, this.InternalResizeBuffer(this.termLength + length), this.termLength, length);
this.Length += length;
return this;
}
///
/// Appends the specified .
///
/// The value.
///
/// An instance of for fluent interface
/// chaining purposes.
///
public ICharTermAttribute Append(StringBuilder value)
{
if (value == null)
return this.AppendNull();
return this.Append(value.ToString());
}
///
/// Appends the specified .
///
/// The value.
///
/// An instance of for fluent interface
/// chaining purposes.
///
public ICharTermAttribute Append(ICharTermAttribute value)
{
if (value == null)
return this.AppendNull();
int length = value.Length;
CharTermAttribute innerValue = value as CharTermAttribute;
char[] array = (innerValue == null) ? value.Buffer.ToArray() : innerValue.buffer;
Array.Copy(array, 0, this.InternalResizeBuffer(this.termLength + length), this.termLength, length);
this.termLength += length;
return this;
}
///
/// Returns the character at the specified index index.
///
/// The position of the character.
/// An instance of .
///
/// Throws when the index is equal or greater than the current buffer length
///
public char CharAt(int index)
{
if (index >= this.termLength)
throw new ArgumentOutOfRangeException("index");
return this.buffer[index];
}
///
/// Clears the instance.
///
public override void Clear()
{
this.termLength = 0;
}
///
/// Creates a clone of the object, generally shallow.
///
/// an the clone of the current instance.
public override AttributeBase Clone()
{
CharTermAttribute clone = (CharTermAttribute)this.MemberwiseClone();
clone.Buffer = new char[this.termLength];
Array.Copy(this.buffer, 0, clone.buffer, 0, this.termLength);
return clone;
}
///
/// Copies the contents of the buffer, starting at the offset to the specified length.
///
/// The buffer to copy.
/// The index of the first character to copy inside the buffer.
/// The number of characters to copy.
public void CopyBuffer(char[] buffer, int offset = 0, int length = -1)
{
if (length == -1)
length = buffer.Length;
this.GrowBuffer(length);
Array.Copy(buffer, offset, this.buffer, 0, length);
this.termLength = length;
}
///
/// Copies to.
///
/// The attribute base.
public override void CopyTo(AttributeBase attributeBase)
{
ICharTermAttribute attribute = (ICharTermAttribute)attributeBase;
attribute.CopyBuffer(this.buffer, 0, this.termLength);
}
///
/// Sets the length of the internal buffer to zero. User this
/// method before appending content using Append methods.
///
///
/// An instance of for fluent interface
/// chaining purposes.
///
public ICharTermAttribute Empty()
{
this.termLength = 0;
return this;
}
///
/// Determines whether the specified is equal to this instance.
///
/// The to compare with this instance.
///
/// true if the specified is equal to this instance; otherwise, false.
///
public override bool Equals(object obj)
{
if (this == obj)
return true;
CharTermAttribute attribute = obj as CharTermAttribute;
if (attribute == null)
return false;
if (this.termLength != attribute.termLength)
return false;
for (int i = 0; i < this.termLength; i++)
{
if (this.buffer[i] != attribute.buffer[i])
return false;
}
return true;
}
///
/// Returns a hash code for this instance.
///
///
/// A hash code for this instance, suitable for use in
/// hashing algorithms and data structures like a hash table.
///
public override int GetHashCode()
{
int code = this.termLength;
code = (code * 31) + this.buffer.CreateHashCode();
return code;
}
///
/// Resizes the length of the internal buffer to the new value and preserves the
/// existing content.
///
/// The length to re-buffer to.
/// The array.
public IEnumerable ResizeBuffer(int length)
{
return this.InternalResizeBuffer(length);
}
///
/// Gets or sets the number of valid characters, the length of the term, in
/// the termBuffer array.
///
/// The length.
///
///
/// Use this to truncate the termBuffer or to synchronize any external
/// manipulation of the termBuffer.
///
///
/// To grow the size of the array, use first.
///
///
///
/// An instance of for fluent interface
/// chaining purposes.
///
public ICharTermAttribute SetLength(int length)
{
if (length > this.buffer.Length)
{
string message =
"The given length '{0}' needs to be less than current the internal buffer length '{1}'"
.Inject(length, this.buffer.Length);
throw new ArgumentOutOfRangeException("length", message);
}
this.termLength = length;
return this;
}
///
/// Returns a that represents this instance.
///
///
/// A that represents this instance.
///
public override string ToString()
{
return new string(this.buffer).Substring(0, this.termLength);
}
private static char[] CreateBuffer(int length)
{
return new char[ArrayUtil.Oversize(length, RamUsageEstimator.NumberOfBytesChar)];
}
private CharTermAttribute AppendNull()
{
this.ResizeBuffer(this.termLength + 4);
this.buffer[this.termLength++] = 'n';
this.buffer[this.termLength++] = 'u';
this.buffer[this.termLength++] = 'l';
this.buffer[this.termLength++] = 'l';
return this;
}
private void GrowBuffer(int length)
{
if (this.buffer.Length < length)
this.Buffer = CreateBuffer(length);
}
private char[] InternalResizeBuffer(int length)
{
if (this.buffer.Length < length)
{
char[] newBuffer = CreateBuffer(length);
Array.Copy(this.buffer, 0, newBuffer, 0, this.buffer.Length);
this.buffer = newBuffer;
}
return this.buffer;
}
}
}