19 using Lucene.Net.Support;
25 namespace Lucene.Net.Util
57 private static readonly CodingCase[] CODING_CASES =
new CodingCase[]{
new CodingCase(7, 1),
new CodingCase(14, 6, 2),
new CodingCase(13, 5, 3),
new CodingCase(12, 4, 4),
new CodingCase(11, 3, 5),
new CodingCase(10, 2, 6),
new CodingCase(9, 1, 7),
new CodingCase(8, 0)};
72 public static int GetEncodedLength(System.Collections.Generic.List<byte> original)
74 return (original.Count == 0) ? 0 : ((original.Count * 8 + 14) / 15) + 1;
85 public static int GetDecodedLength(System.Collections.Generic.List<
char> encoded)
87 int numChars = encoded.Count - 1;
94 int numFullBytesInFinalChar = encoded[encoded.Count - 1];
95 int numEncodedChars = numChars - 1;
96 return ((numEncodedChars * 15 + 7) / 8 + numFullBytesInFinalChar);
113 public static void Encode(System.Collections.Generic.List<byte> input, System.Collections.Generic.List<
char> output)
115 int outputLength = GetEncodedLength(input);
117 if (output.Capacity < outputLength)
119 output.Capacity = outputLength;
123 if (output.Count < outputLength)
125 for (
int i = output.Count; i < outputLength; i++)
127 output.Add(Char.MinValue);
133 int inputByteNum = 0;
135 int outputCharNum = 0;
136 CodingCase codingCase;
137 for (; inputByteNum + CODING_CASES[caseNum].numBytes <= input.Count; ++outputCharNum)
139 codingCase = CODING_CASES[caseNum];
140 if (2 == codingCase.numBytes)
142 output[outputCharNum] = (char)(((input[inputByteNum] & 0xFF) << codingCase.initialShift) + ((
Number.
URShift((input[inputByteNum + 1] & 0xFF), codingCase.finalShift)) & codingCase.finalMask) & (short)0x7FFF);
147 output[outputCharNum] = (char)(((input[inputByteNum] & 0xFF) << codingCase.initialShift) + ((input[inputByteNum + 1] & 0xFF) << codingCase.middleShift) + ((
Number.
URShift((input[inputByteNum + 2] & 0xFF), codingCase.finalShift)) & codingCase.finalMask) & (short)0x7FFF);
149 inputByteNum += codingCase.advanceBytes;
150 if (++caseNum == CODING_CASES.Length)
156 codingCase = CODING_CASES[caseNum];
158 if (inputByteNum + 1 < input.Count)
161 output[outputCharNum++] = (char) ((((input[inputByteNum] & 0xFF) << codingCase.initialShift) + ((input[inputByteNum + 1] & 0xFF) << codingCase.middleShift)) & (short) 0x7FFF);
163 output[outputCharNum++] = (char) 1;
165 else if (inputByteNum < input.Count)
167 output[outputCharNum++] = (char) (((input[inputByteNum] & 0xFF) << codingCase.initialShift) & (
short) 0x7FFF);
169 output[outputCharNum++] = caseNum == 0?(char) 1:(
char) 0;
175 output[outputCharNum++] = (char) 1;
193 public static void Decode(System.Collections.Generic.List<
char> input, System.Collections.Generic.List<byte> output)
195 int numOutputBytes = GetDecodedLength(input);
196 if (output.Capacity < numOutputBytes)
198 output.Capacity = numOutputBytes;
202 if (output.Count < numOutputBytes)
204 for (
int i = output.Count; i < numOutputBytes; i++)
206 output.Add(Byte.MinValue);
213 int outputByteNum = 0;
214 int inputCharNum = 0;
216 CodingCase codingCase;
217 for (; inputCharNum < input.Count - 2; ++inputCharNum)
219 codingCase = CODING_CASES[caseNum];
220 inputChar = (short) input[inputCharNum];
221 if (2 == codingCase.numBytes)
225 output[outputByteNum] = (byte) (
Number.
URShift(inputChar, codingCase.initialShift));
229 output[outputByteNum] = (byte) (output[outputByteNum] + (byte) (
Number.
URShift(inputChar, codingCase.initialShift)));
231 output[outputByteNum + 1] = (byte) ((inputChar & codingCase.finalMask) << codingCase.finalShift);
236 output[outputByteNum] = (byte) (output[outputByteNum] + (byte) (
Number.
URShift(inputChar, codingCase.initialShift)));
237 output[outputByteNum + 1] = (byte) (
Number.
URShift((inputChar & codingCase.middleMask), codingCase.middleShift));
238 output[outputByteNum + 2] = (byte) ((inputChar & codingCase.finalMask) << codingCase.finalShift);
240 outputByteNum += codingCase.advanceBytes;
241 if (++caseNum == CODING_CASES.Length)
247 inputChar = (short) input[inputCharNum];
248 codingCase = CODING_CASES[caseNum];
251 output[outputByteNum] = 0;
253 output[outputByteNum] = (byte) (output[outputByteNum] + (byte) (
Number.
URShift(inputChar, codingCase.initialShift)));
254 long bytesLeft = numOutputBytes - outputByteNum;
257 if (2 == codingCase.numBytes)
259 output[outputByteNum + 1] = (byte) (
Number.
URShift((inputChar & codingCase.finalMask), codingCase.finalShift));
264 output[outputByteNum + 1] = (byte) (
Number.
URShift((inputChar & codingCase.middleMask), codingCase.middleShift));
267 output[outputByteNum + 2] = (byte) ((inputChar & codingCase.finalMask) << codingCase.finalShift);
287 public static System.Collections.Generic.List<byte> Decode(System.Collections.Generic.List<
char> input)
289 System.Collections.Generic.List<byte> output =
290 new System.Collections.Generic.List<byte>(
new byte[GetDecodedLength(input)]);
291 Decode(input, output);
306 public static System.Collections.Generic.List<
char> Encode(System.Collections.Generic.List<byte> input)
308 System.Collections.Generic.List<
char> output =
309 new System.Collections.Generic.List<
char>(
new char[GetEncodedLength(input)]);
310 Encode(input, output);
314 internal class CodingCase
316 internal int numBytes, initialShift, middleShift, finalShift, advanceBytes = 2;
317 internal short middleMask, finalMask;
319 internal CodingCase(
int initialShift,
int middleShift,
int finalShift)
322 this.initialShift = initialShift;
323 this.middleShift = middleShift;
324 this.finalShift = finalShift;
325 this.finalMask = (short) (
Number.
URShift((
short) 0xFF, finalShift));
326 this.middleMask = (short) ((
short) 0xFF << middleShift);
329 internal CodingCase(
int initialShift,
int finalShift)
332 this.initialShift = initialShift;
333 this.finalShift = finalShift;
334 this.finalMask = (short) (
Number.
URShift((
short) 0xFF, finalShift));