Exemplo n.º 1
0
        public ProcessorState(Stream source, Stream target, int bufferSize, int flushThreshold, IEngineConfig config, IReadOnlyList <IOperationProvider> operationProviders)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            if (operationProviders == null)
            {
                throw new ArgumentNullException(nameof(operationProviders));
            }

            if (source.CanSeek)
            {
                try
                {
                    if (source.Length < bufferSize)
                    {
                        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
                }
            }
            //Buffer has to be at least as large as the largest BOM we could expect
            else if (bufferSize < 4)
            {
                bufferSize = 4;
            }

            _source             = source;
            _target             = target;
            Config              = config;
            _flushThreshold     = flushThreshold;
            CurrentBuffer       = new byte[bufferSize];
            CurrentBufferLength = ReadExactBytes(source, CurrentBuffer, 0, CurrentBuffer.Length);

            Encoding encoding = EncodingUtil.Detect(CurrentBuffer, CurrentBufferLength, out byte[] bom);

            EncodingConfig        = new EncodingConfig(Config, encoding);
            _bomSize              = bom.Length;
            CurrentBufferPosition = _bomSize;
            CurrentSequenceNumber = _bomSize;
            target.Write(bom, 0, _bomSize);

            bool explicitOnConfigurationRequired = false;
            Dictionary <Encoding, Trie <OperationTerminal> > byEncoding = TrieLookup.GetOrAdd(operationProviders, x => new Dictionary <Encoding, Trie <OperationTerminal> >());
            List <string> turnOnByDefault = OperationsToExplicitlySetOnByDefault.GetOrAdd(operationProviders, x =>
            {
                explicitOnConfigurationRequired = true;
                return(new List <string>());
            });

            if (!byEncoding.TryGetValue(encoding, out Trie <OperationTerminal> trie))
            {
                trie = new Trie <OperationTerminal>();

                for (int i = 0; i < operationProviders.Count; ++i)
                {
                    IOperation op = operationProviders[i].GetOperation(encoding, this);

                    if (op != null)
                    {
                        for (int j = 0; j < op.Tokens.Count; ++j)
                        {
                            if (op.Tokens[j] != null)
                            {
                                trie.AddPath(op.Tokens[j].Value, new OperationTerminal(op, j, op.Tokens[j].Length, op.Tokens[j].Start, op.Tokens[j].End));
                            }
                        }

                        if (explicitOnConfigurationRequired && op.IsInitialStateOn && !string.IsNullOrEmpty(op.Id))
                        {
                            turnOnByDefault.Add(op.Id);
                        }
                    }
                }

                byEncoding[encoding] = trie;
            }

            foreach (string state in turnOnByDefault)
            {
                config.Flags[state] = true;
            }

            _trie = new TrieEvaluator <OperationTerminal>(trie);

            if (bufferSize < _trie.MaxLength + 1)
            {
                byte[] tmp = new byte[_trie.MaxLength + 1];
                Buffer.BlockCopy(CurrentBuffer, CurrentBufferPosition, tmp, 0, CurrentBufferLength - CurrentBufferPosition);
                int nRead = ReadExactBytes(_source, tmp, CurrentBufferLength - CurrentBufferPosition, tmp.Length - CurrentBufferLength);
                CurrentBuffer         = tmp;
                CurrentBufferLength  += nRead - _bomSize;
                CurrentBufferPosition = 0;
                CurrentSequenceNumber = 0;
            }
        }