1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 using System; 19 20 using TokenStream = Lucene.Net.Analysis.TokenStream; 21 using ArrayUtil = Lucene.Net.Util.ArrayUtil; 22 23 namespace Lucene.Net.Index 24 { 25 26 /// <summary> A Payload is metadata that can be stored together with each occurrence 27 /// of a term. This metadata is stored inline in the posting list of the 28 /// specific term. 29 /// <p/> 30 /// To store payloads in the index a <see cref="TokenStream"/> has to be used that 31 /// produces payload data. 32 /// <p/> 33 /// Use <see cref="TermPositions.PayloadLength"/> and <see cref="TermPositions.GetPayload(byte[], int)"/> 34 /// to retrieve the payloads from the index.<br/> 35 /// 36 /// </summary> 37 [Serializable] 38 public class Payload : System.ICloneable 39 { 40 /// <summary>the byte array containing the payload data </summary> 41 protected internal byte[] data; 42 43 /// <summary>the offset within the byte array </summary> 44 protected internal int internalOffset; 45 46 /// <summary>the length of the payload data </summary> 47 protected internal int internalLength; 48 49 /// <summary>Creates an empty payload and does not allocate a byte array. </summary> Payload()50 public Payload() 51 { 52 // nothing to do 53 } 54 55 /// <summary> Creates a new payload with the the given array as data. 56 /// A reference to the passed-in array is held, i. e. no 57 /// copy is made. 58 /// 59 /// </summary> 60 /// <param name="data">the data of this payload 61 /// </param> Payload(byte[] data)62 public Payload(byte[] data):this(data, 0, data.Length) 63 { 64 } 65 66 /// <summary> Creates a new payload with the the given array as data. 67 /// A reference to the passed-in array is held, i. e. no 68 /// copy is made. 69 /// 70 /// </summary> 71 /// <param name="data">the data of this payload 72 /// </param> 73 /// <param name="offset">the offset in the data byte array 74 /// </param> 75 /// <param name="length">the length of the data 76 /// </param> Payload(byte[] data, int offset, int length)77 public Payload(byte[] data, int offset, int length) 78 { 79 if (offset < 0 || offset + length > data.Length) 80 { 81 throw new System.ArgumentException(); 82 } 83 this.data = data; 84 this.internalOffset = offset; 85 this.internalLength = length; 86 } 87 88 /// <summary> Sets this payloads data. 89 /// A reference to the passed-in array is held, i. e. no 90 /// copy is made. 91 /// </summary> SetData(byte[] value, int offset, int length)92 public virtual void SetData(byte[] value, int offset, int length) 93 { 94 this.data = value; 95 this.internalOffset = offset; 96 this.internalLength = length; 97 } 98 99 /// <summary> Gets or sets a reference to the underlying byte array 100 /// that holds this payloads data. Data is not copied. 101 /// </summary> SetData(byte[] value)102 public virtual void SetData(byte[] value) 103 { 104 SetData(value, 0, value.Length); 105 } 106 107 /// <summary> Gets or sets a reference to the underlying byte array 108 /// that holds this payloads data. Data is not copied. 109 /// </summary> GetData()110 public virtual byte[] GetData() 111 { 112 return this.data; 113 } 114 115 /// <summary> Returns the offset in the underlying byte array </summary> 116 public virtual int Offset 117 { 118 get { return this.internalOffset; } 119 } 120 121 /// <summary> Returns the length of the payload data. </summary> 122 public virtual int Length 123 { 124 get { return this.internalLength; } 125 } 126 127 /// <summary> Returns the byte at the given index.</summary> ByteAt(int index)128 public virtual byte ByteAt(int index) 129 { 130 if (0 <= index && index < this.internalLength) 131 { 132 return this.data[this.internalOffset + index]; 133 } 134 throw new System. IndexOutOfRangeException("Index of bound " + index); 135 } 136 137 /// <summary> Allocates a new byte array, copies the payload data into it and returns it. </summary> ToByteArray()138 public virtual byte[] ToByteArray() 139 { 140 byte[] retArray = new byte[this.internalLength]; 141 Array.Copy(this.data, this.internalOffset, retArray, 0, this.internalLength); 142 return retArray; 143 } 144 145 /// <summary> Copies the payload data to a byte array. 146 /// 147 /// </summary> 148 /// <param name="target">the target byte array 149 /// </param> 150 /// <param name="targetOffset">the offset in the target byte array 151 /// </param> CopyTo(byte[] target, int targetOffset)152 public virtual void CopyTo(byte[] target, int targetOffset) 153 { 154 if (this.internalLength > target.Length + targetOffset) 155 { 156 throw new System.IndexOutOfRangeException(); 157 } 158 Array.Copy(this.data, this.internalOffset, target, targetOffset, this.internalLength); 159 } 160 161 /// <summary> Clones this payload by creating a copy of the underlying 162 /// byte array. 163 /// </summary> Clone()164 public virtual System.Object Clone() 165 { 166 try 167 { 168 // Start with a shallow copy of data 169 Payload clone = (Payload) base.MemberwiseClone(); 170 // Only copy the part of data that belongs to this Payload 171 if (internalOffset == 0 && internalLength == data.Length) 172 { 173 // It is the whole thing, so just clone it. 174 clone.data = new byte[data.Length]; 175 data.CopyTo(clone.data, 0); 176 } 177 else 178 { 179 // Just get the part 180 clone.data = this.ToByteArray(); 181 clone.internalOffset = 0; 182 } 183 return clone; 184 } 185 catch (System.Exception e) 186 { 187 throw new System.SystemException(e.Message, e); // shouldn't happen 188 } 189 } 190 Equals(System.Object obj)191 public override bool Equals(System.Object obj) 192 { 193 if (obj == this) 194 return true; 195 if (obj is Payload) 196 { 197 Payload other = (Payload) obj; 198 if (internalLength == other.internalLength) 199 { 200 for (int i = 0; i < internalLength; i++) 201 if (data[internalOffset + i] != other.data[other.internalOffset + i]) 202 return false; 203 return true; 204 } 205 else 206 return false; 207 } 208 else 209 return false; 210 } 211 GetHashCode()212 public override int GetHashCode() 213 { 214 return ArrayUtil.HashCode(data, internalOffset, internalOffset + internalLength); 215 } 216 } 217 }