public IOperation GetOperation(byte[] buffer, int bufferLength, ref int currentBufferPosition, out int token) { //If a match couldn't fit in what's left of the buffer if (MinLength > bufferLength - currentBufferPosition) { token = -1; return(null); } int i = currentBufferPosition; OperationTrie current = this; IOperation operation = null; int index = -1; int offsetToMatch = 0; while (i < bufferLength) { if (!current._map.TryGetValue(buffer[i], out current)) { // the current byte doesn't match in the context of the current trie state token = index; if (index != -1) { // a full token match was encountered along the way - return its operation currentBufferPosition = i - offsetToMatch; return(operation); } // no token match return(null); } if (current.HandlerTokenIndex != -1) { // a full token was matched, note its operation index = current.HandlerTokenIndex; operation = current.End; offsetToMatch = 0; } else { ++offsetToMatch; } ++i; } if (index != -1) { // matched to the end of the buffer currentBufferPosition = i; } // end of buffer, but a full token matched along the way - return its operation token = index; return(operation); }
public static OperationTrie Create(IReadOnlyList <IOperation> modifiers) { OperationTrie root = new OperationTrie(); OperationTrie current = root; int length = 0; int minLength = 0; for (int i = 0; i < modifiers.Count; ++i) { for (int k = 0; k < modifiers[i].Tokens.Count; ++k) { if (modifiers[i].Tokens[k] == null) { continue; } length = Math.Max(length, modifiers[i].Tokens[k].Length); if (modifiers[i].Tokens[k].Length > 0) { minLength = minLength == 0 ? modifiers[i].Tokens[k].Length : Math.Min(minLength, modifiers[i].Tokens[k].Length); } for (int j = 0; j < modifiers[i].Tokens[k].Length; ++j) { OperationTrie child; if (!current._map.TryGetValue(modifiers[i].Tokens[k][j], out child)) { child = new OperationTrie(); current._map[modifiers[i].Tokens[k][j]] = child; } current = child; } current.HandlerTokenIndex = k; current.End = modifiers[i]; current = root; } } root.MaxLength = length; root.MinLength = minLength; return(root); }
public ProcessorState(Stream source, Stream target, int bufferSize, int flushThreshold, IEngineConfig config, IReadOnlyList <IOperationProvider> operationProviders) { bool sizedToStream = false; //Buffer has to be at least as large as the largest BOM we could expect if (bufferSize < 4) { bufferSize = 4; } else { try { if (source.Length < bufferSize) { sizedToStream = true; bufferSize = (int)source.Length; } } catch { //The stream may not support getting the length property (in NetworkStream for instance, which throw a NotSupportedException), suppress any errors in // accessing the property and continue with the specified buffer size } } _source = source; _target = target; Config = config; _flushThreshold = flushThreshold; CurrentBuffer = new byte[bufferSize]; CurrentBufferLength = source.Read(CurrentBuffer, 0, CurrentBuffer.Length); byte[] bom; Encoding encoding = EncodingUtil.Detect(CurrentBuffer, CurrentBufferLength, out bom); Encoding = encoding; CurrentBufferPosition = bom.Length; target.Write(bom, 0, bom.Length); Dictionary <Encoding, OperationTrie> byEncoding; if (!TrieLookup.TryGetValue(operationProviders, out byEncoding)) { TrieLookup[operationProviders] = byEncoding = new Dictionary <Encoding, OperationTrie>(); } if (!byEncoding.TryGetValue(encoding, out _trie)) { List <IOperation> operations = new List <IOperation>(operationProviders.Count); for (int i = 0; i < operationProviders.Count; ++i) { IOperation op = operationProviders[i].GetOperation(encoding, this); if (op != null) { operations.Add(op); } } byEncoding[encoding] = _trie = OperationTrie.Create(operations); } if (bufferSize < _trie.MaxLength && !sizedToStream) { byte[] tmp = new byte[_trie.MaxLength]; Buffer.BlockCopy(CurrentBuffer, CurrentBufferPosition, tmp, 0, CurrentBufferLength - CurrentBufferPosition); int nRead = _source.Read(tmp, CurrentBufferLength - CurrentBufferPosition, tmp.Length - CurrentBufferLength); CurrentBuffer = tmp; CurrentBufferLength += nRead; CurrentBufferPosition = 0; } }