private ulong NextNumber() { if (indxInBuffer >= dataInBuffer) { var toRead = buffer.Length; if (listEndOffset - readOffset < toRead) { checked { toRead = (int)(listEndOffset - readOffset); } } if (toRead == 0) { isEof = true; return(0); } persistentStorage.ReadAll(readOffset, buffer, 0, toRead); for (int i = toRead; i < buffer.Length; ++i) { buffer[i] = 0; } readOffset += toRead; dataInBuffer = toRead; indxInBuffer = 0; } indxInBuffer += VarInt.ReadVUInt64(buffer, indxInBuffer, out var result); return(result); }
public bool MoveNext() { while (true) { if (state == 0) { if (isEof) { return(false); } var header = new byte[HeaderLength]; persistentStorage.ReadAll(readOffset, header, 0, header.Length); if (header[0] != (byte)'L') { throw new Exception("Invalid List Header"); } var listLength = BitConverter.ToInt32(header, 1); var recordCount = BitConverter.ToInt32(header, 1 + sizeof(int)); listEndOffset = readOffset + HeaderLength + listLength; readOffset += header.Length; state = 17; } if (state == 17) { // Seek state var left = (listEndOffset - readOffset) / buffer.Length; if (left < SkipSearchBlocksThreshold || !(current < firstValue)) { state = 1; } else { // Allocate space for two blocks, find two consecutive blocks that contain // occurrence that is requested var t = new byte[buffer.Length * 2]; var a = 0L; var b = left; var mid = a; while (a != b) { mid = (a + b) >> 1; // Read two blocks var midOffset = readOffset + buffer.Length * mid; var inList = (listEndOffset - midOffset - buffer.Length); var toRead = inList > t.Length ? t.Length : (int)inList; persistentStorage.ReadAll(midOffset, t, 0, toRead); // Block 1: Full value var j = 0; j += VarInt.ReadVUInt64(t, j, out var v1); // Block 2: Full value j = buffer.Length; j += VarInt.ReadVUInt64(t, j, out var v2); if (v1 < firstValue) { if (v2 >= firstValue) { break; } else { a = mid + 1; } } else { b = mid; } } state = 1; indxInBuffer = 0; dataInBuffer = 0; readOffset = readOffset + buffer.Length * mid; } } if (state == 1) { current = NextNumber(); state = 2; if (!(current < firstValue)) { return(true); } } if (state == 2) { if (indxInBuffer >= dataInBuffer) { if (readOffset < listEndOffset) { // Next block state = 1; continue; } } var delta = NextNumber(); if (delta == 0) { if (readOffset < listEndOffset) { if (indxInBuffer < dataInBuffer) { // Case when buffer is filled with zeros at the end indxInBuffer = dataInBuffer; } state = 1; // Next block } else { state = 0; // EOF } continue; } current += delta; if (!(current < firstValue)) { return(true); } } } }
public bool MoveNext() { while (true) { if (state == 0) { if (continuationOffset > 0) { readOffset = continuationOffset; isEof = false; dataInBuffer = 0; indxInBuffer = 0; } if (isEof) { return(false); } var header = new byte[HeaderLength]; persistentStorage.ReadAll(readOffset, header, 0, header.Length); continuationOffset = BitConverter.ToInt64(header, 0); listEndOffset = readOffset + HeaderLength + BitConverter.ToInt32(header, sizeof(long)); readOffset += header.Length; state = 17; } if (state == 17) { // Seek state var left = (listEndOffset - readOffset) / buffer.Length; if (left < SkipSearchBlocksThreshold || !(current < firstOccurrence)) { state = 1; } else { // Allocate space for two blocks, find two consecutive blocks that contain // occurrence that is requested var t = new byte[buffer.Length * 2]; var a = 0L; var b = left; var mid = a; while (a != b) { mid = (a + b) >> 1; // Read two blocks var midOffset = readOffset + buffer.Length * mid; var inList = (listEndOffset - midOffset - buffer.Length); var toRead = inList > t.Length ? t.Length : (int)inList; persistentStorage.ReadAll(midOffset, t, 0, toRead); // Block 1: Full occurrence var j = 0; j += VarInt.ReadVUInt64(t, j, out var o1_1); j += VarInt.ReadVUInt64(t, j, out var o1_2); j += VarInt.ReadVUInt64(t, j, out var o1_3); // Block 2: Full occurrence j = buffer.Length; j += VarInt.ReadVUInt64(t, j, out var o2_1); j += VarInt.ReadVUInt64(t, j, out var o2_2); j += VarInt.ReadVUInt64(t, j, out var o2_3); if (Occurrence.O(o1_1, o1_2, o1_3).CompareTo(firstOccurrence) < 0) { if (Occurrence.O(o2_1, o2_2, o2_3).CompareTo(firstOccurrence) >= 0) { break; } else { a = mid + 1; } } else { b = mid; } } state = 1; indxInBuffer = 0; dataInBuffer = 0; readOffset = readOffset + buffer.Length * mid; } } if (state == 1) { current = Occurrence.O(NextNumber(), NextNumber(), NextNumber()); state = 2; if (!(current < firstOccurrence)) { return(true); } } if (state == 2) { if (indxInBuffer >= dataInBuffer) { if (readOffset < listEndOffset) { // Next block state = 1; continue; } } int delta = (int)NextNumber(); switch (delta) { case 0: { if (readOffset < listEndOffset) { if (indxInBuffer < dataInBuffer) { // Case when buffer is filled with zeros at the end indxInBuffer = dataInBuffer; } state = 1; // Next block } else { state = 0; // Continuation or EOF } continue; } case 1: { // Next is the same as current break; } case 2: { var deltaToken = NextNumber(); current = Occurrence.O(current.DocumentId, current.FieldId, current.TokenId + deltaToken); break; } case 3: { var deltaFieldId = NextNumber(); var token = NextNumber(); current = Occurrence.O(current.DocumentId, current.FieldId + deltaFieldId, token); break; } case 4: { var deltaDocId = NextNumber(); var fieldId = NextNumber(); var token = NextNumber(); current = Occurrence.O(current.DocumentId + deltaDocId, fieldId, token); break; } default: { throw new Exception("Something wrong"); } } if (!(current < firstOccurrence)) { return(true); } } } }