blob: 9c00c52030e5ca5532ff9740eec955bd080dc21c [file] [log] [blame]
/*
* 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.
*/
using System;
using TokenStream = Lucene.Net.Analysis.TokenStream;
using ArrayUtil = Lucene.Net.Util.ArrayUtil;
namespace Lucene.Net.Index
{
/// <summary> A Payload is metadata that can be stored together with each occurrence
/// of a term. This metadata is stored inline in the posting list of the
/// specific term.
/// <p/>
/// To store payloads in the index a <see cref="TokenStream"/> has to be used that
/// produces payload data.
/// <p/>
/// Use <see cref="TermPositions.PayloadLength"/> and <see cref="TermPositions.GetPayload(byte[], int)"/>
/// to retrieve the payloads from the index.<br/>
///
/// </summary>
[Serializable]
public class Payload : System.ICloneable
{
/// <summary>the byte array containing the payload data </summary>
protected internal byte[] data;
/// <summary>the offset within the byte array </summary>
protected internal int internalOffset;
/// <summary>the length of the payload data </summary>
protected internal int internalLength;
/// <summary>Creates an empty payload and does not allocate a byte array. </summary>
public Payload()
{
// nothing to do
}
/// <summary> Creates a new payload with the the given array as data.
/// A reference to the passed-in array is held, i. e. no
/// copy is made.
///
/// </summary>
/// <param name="data">the data of this payload
/// </param>
public Payload(byte[] data):this(data, 0, data.Length)
{
}
/// <summary> Creates a new payload with the the given array as data.
/// A reference to the passed-in array is held, i. e. no
/// copy is made.
///
/// </summary>
/// <param name="data">the data of this payload
/// </param>
/// <param name="offset">the offset in the data byte array
/// </param>
/// <param name="length">the length of the data
/// </param>
public Payload(byte[] data, int offset, int length)
{
if (offset < 0 || offset + length > data.Length)
{
throw new System.ArgumentException();
}
this.data = data;
this.internalOffset = offset;
this.internalLength = length;
}
/// <summary> Sets this payloads data.
/// A reference to the passed-in array is held, i. e. no
/// copy is made.
/// </summary>
public virtual void SetData(byte[] value, int offset, int length)
{
this.data = value;
this.internalOffset = offset;
this.internalLength = length;
}
/// <summary> Gets or sets a reference to the underlying byte array
/// that holds this payloads data. Data is not copied.
/// </summary>
public virtual void SetData(byte[] value)
{
SetData(value, 0, value.Length);
}
/// <summary> Gets or sets a reference to the underlying byte array
/// that holds this payloads data. Data is not copied.
/// </summary>
public virtual byte[] GetData()
{
return this.data;
}
/// <summary> Returns the offset in the underlying byte array </summary>
public virtual int Offset
{
get { return this.internalOffset; }
}
/// <summary> Returns the length of the payload data. </summary>
public virtual int Length
{
get { return this.internalLength; }
}
/// <summary> Returns the byte at the given index.</summary>
public virtual byte ByteAt(int index)
{
if (0 <= index && index < this.internalLength)
{
return this.data[this.internalOffset + index];
}
throw new System. IndexOutOfRangeException("Index of bound " + index);
}
/// <summary> Allocates a new byte array, copies the payload data into it and returns it. </summary>
public virtual byte[] ToByteArray()
{
byte[] retArray = new byte[this.internalLength];
Array.Copy(this.data, this.internalOffset, retArray, 0, this.internalLength);
return retArray;
}
/// <summary> Copies the payload data to a byte array.
///
/// </summary>
/// <param name="target">the target byte array
/// </param>
/// <param name="targetOffset">the offset in the target byte array
/// </param>
public virtual void CopyTo(byte[] target, int targetOffset)
{
if (this.internalLength > target.Length + targetOffset)
{
throw new System.IndexOutOfRangeException();
}
Array.Copy(this.data, this.internalOffset, target, targetOffset, this.internalLength);
}
/// <summary> Clones this payload by creating a copy of the underlying
/// byte array.
/// </summary>
public virtual System.Object Clone()
{
try
{
// Start with a shallow copy of data
Payload clone = (Payload) base.MemberwiseClone();
// Only copy the part of data that belongs to this Payload
if (internalOffset == 0 && internalLength == data.Length)
{
// It is the whole thing, so just clone it.
clone.data = new byte[data.Length];
data.CopyTo(clone.data, 0);
}
else
{
// Just get the part
clone.data = this.ToByteArray();
clone.internalOffset = 0;
}
return clone;
}
catch (System.Exception e)
{
throw new System.SystemException(e.Message, e); // shouldn't happen
}
}
public override bool Equals(System.Object obj)
{
if (obj == this)
return true;
if (obj is Payload)
{
Payload other = (Payload) obj;
if (internalLength == other.internalLength)
{
for (int i = 0; i < internalLength; i++)
if (data[internalOffset + i] != other.data[other.internalOffset + i])
return false;
return true;
}
else
return false;
}
else
return false;
}
public override int GetHashCode()
{
return ArrayUtil.HashCode(data, internalOffset, internalOffset + internalLength);
}
}
}