示例#1
0
        public static ICharSequence[] Split(ICharSequence sequence, int startIndex, params char[] delimiters)
        {
            if (sequence is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.sequence);
            }
            if (delimiters is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.delimiters);
            }
            int  length  = sequence.Count;
            uint uLength = (uint)length;

            if (0u >= uLength)
            {
                return(new[] { sequence });
            }
            if ((uint)startIndex >= uLength)
            {
                ThrowHelper.ThrowIndexOutOfRangeException();
            }

            var delimitersSpan          = delimiters.AsSpan();
            List <ICharSequence> result = InternalThreadLocalMap.Get().CharSequenceList();

            int i = startIndex;

            while ((uint)i < uLength)
            {
                while ((uint)i < uLength && delimitersSpan.IndexOf(sequence[i]) >= 0)
                {
                    i++;
                }

                int position = i;
                if ((uint)i < uLength)
                {
                    if (delimitersSpan.IndexOf(sequence[position]) >= 0)
                    {
                        result.Add(sequence.SubSequence(position++, i + 1));
                    }
                    else
                    {
                        ICharSequence seq = null;
                        for (position++; position < length; position++)
                        {
                            if (delimitersSpan.IndexOf(sequence[position]) >= 0)
                            {
                                seq = sequence.SubSequence(i, position);
                                break;
                            }
                        }
                        result.Add(seq ?? sequence.SubSequence(i));
                    }
                    i = position;
                }
            }

            return(0u >= (uint)result.Count ? new[] { sequence } : result.ToArray());
        }
示例#2
0
        public AsciiString[] Split(char delim)
        {
            List <AsciiString> res = InternalThreadLocalMap.Get().AsciiStringList();

            int start = 0;
            int count = this.length;

            for (int i = start; i < count; i++)
            {
                if (this[i] == delim)
                {
                    if (start == i)
                    {
                        res.Add(Empty);
                    }
                    else
                    {
                        res.Add(new AsciiString(this.value, start + this.offset, i - start, false));
                    }
                    start = i + 1;
                }
            }

            if (0u >= (uint)start)
            {
                // If no delimiter was found in the value
                res.Add(this);
            }
            else
            {
                if (start != count)
                {
                    // Add the last element if it's not empty.
                    res.Add(new AsciiString(this.value, start + this.offset, count - start, false));
                }
                else
                {
                    // Truncate trailing empty elements.
                    while ((uint)res.Count > 0u)
                    {
                        int i = res.Count - 1;
                        if (!res[i].IsEmpty)
                        {
                            res.RemoveAt(i);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            var strings = new AsciiString[res.Count];

            res.CopyTo(strings);
            return(strings);
        }
        protected override void DoBeginRead()
        {
            if (this.readInProgress)
            {
                return;
            }

            IChannelPipeline pipeline      = this.Pipeline;
            IQueue <object>  inboundBuffer = this.inboundBuffer;

            if (inboundBuffer.IsEmpty)
            {
                this.readInProgress = true;
                return;
            }

            InternalThreadLocalMap threadLocals = InternalThreadLocalMap.Get();
            int stackDepth = threadLocals.LocalChannelReaderStackDepth;

            if (stackDepth < MAX_READER_STACK_DEPTH)
            {
                threadLocals.LocalChannelReaderStackDepth = stackDepth + 1;

                try
                {
                    for (;;)
                    {
                        if (!inboundBuffer.TryDequeue(out object received))
                        {
                            break;
                        }

                        pipeline.FireChannelRead(received);
                    }
                    pipeline.FireChannelReadComplete();
                }
                finally
                {
                    threadLocals.LocalChannelReaderStackDepth = stackDepth;
                }
            }
            else
            {
                try
                {
                    this.EventLoop.Execute(this.InternalRead);
                }
                catch (Exception ex)
                {
                    Logger.Warn("Closing Local channels {}-{} because exception occurred!", this, this.peer, ex);
                    this.CloseAsync();
                    this.peer.CloseAsync();
                    throw;
                }
            }
        }
示例#4
0
        protected override void DoBeginRead()
        {
            if (SharedConstants.False < (uint)Volatile.Read(ref v_readInProgress))
            {
                return;
            }

            if (_inboundBuffer.IsEmpty)
            {
                _ = Interlocked.Exchange(ref v_readInProgress, SharedConstants.True);
                return;
            }

            InternalThreadLocalMap threadLocals = InternalThreadLocalMap.Get();
            int stackDepth = threadLocals.LocalChannelReaderStackDepth;

            if (stackDepth < MAX_READER_STACK_DEPTH)
            {
                threadLocals.LocalChannelReaderStackDepth = stackDepth + 1;

                try
                {
                    ReadInbound();
                }
                finally
                {
                    threadLocals.LocalChannelReaderStackDepth = stackDepth;
                }
            }
            else
            {
                try
                {
                    EventLoop.Execute(InternalReadAction, this);
                }
                catch (Exception ex)
                {
                    Logger.Warn("Closing Local channels {}-{} because exception occurred!", this, Volatile.Read(ref v_peer), ex);
                    _ = CloseAsync();
                    _ = Volatile.Read(ref v_peer).CloseAsync();
                    throw;
                }
            }
        }
示例#5
0
        public static ICharSequence[] Split(ICharSequence sequence, int startIndex, params char[] delimiters)
        {
            Contract.Requires(sequence != null);
            Contract.Requires(delimiters != null);
            Contract.Requires(startIndex >= 0 && startIndex < sequence.Count);

            List <ICharSequence> result = InternalThreadLocalMap.Get().CharSequenceList();

            int i      = startIndex;
            int length = sequence.Count;

            while (i < length)
            {
                while (i < length && IndexOf(delimiters, sequence[i]) >= 0)
                {
                    i++;
                }

                int position = i;
                if (i < length)
                {
                    if (IndexOf(delimiters, sequence[position]) >= 0)
                    {
                        result.Add(sequence.SubSequence(position++, i + 1));
                    }
                    else
                    {
                        ICharSequence seq = null;
                        for (position++; position < length; position++)
                        {
                            if (IndexOf(delimiters, sequence[position]) >= 0)
                            {
                                seq = sequence.SubSequence(i, position);
                                break;
                            }
                        }
                        result.Add(seq ?? sequence.SubSequence(i));
                    }
                    i = position;
                }
            }

            return(result.Count == 0 ? new[] { sequence } : result.ToArray());
        }
        public static ICharSequence UnescapeCsv(ICharSequence value)
        {
            Contract.Requires(value != null);
            int length = value.Count;

            if (length == 0)
            {
                return(value);
            }
            int  last   = length - 1;
            bool quoted = IsDoubleQuote(value[0]) && IsDoubleQuote(value[last]) && length != 1;

            if (!quoted)
            {
                ValidateCsvFormat(value);
                return(value);
            }
            StringBuilder unescaped = InternalThreadLocalMap.Get().StringBuilder;

            for (int i = 1; i < last; i++)
            {
                char current = value[i];
                if (current == DoubleQuote)
                {
                    if (IsDoubleQuote(value[i + 1]) && (i + 1) != last)
                    {
                        // Followed by a double-quote but not the last character
                        // Just skip the next double-quote
                        i++;
                    }
                    else
                    {
                        // Not followed by a double-quote or the following double-quote is the last character
                        throw NewInvalidEscapedCsvFieldException(value, i);
                    }
                }
                unescaped.Append(current);
            }

            return(new StringCharSequence(unescaped.ToString()));
        }
        /// <summary>
        /// Returns a list of direct ArraySegment&lt;byte&gt;, if the currently pending messages are made of
        /// <see cref="IByteBuffer"/> instances only. <see cref="NioBufferSize"/> will return the total number of
        /// readable bytes of these buffers.
        /// <para>
        /// Note that the returned array is reused and thus should not escape
        /// <see cref="AbstractChannel.DoWrite(ChannelOutboundBuffer)"/>. Refer to
        /// <see cref="TcpSocketChannel.DoWrite(ChannelOutboundBuffer)"/> for an example.
        /// </para>
        /// </summary>
        /// <param name="maxCount">The maximum amount of buffers that will be added to the return value.</param>
        /// <param name="maxBytes">A hint toward the maximum number of bytes to include as part of the return value. Note that this value maybe exceeded because we make a best effort to include at least 1 <see cref="IByteBuffer"/> in the return value to ensure write progress is made.</param>
        /// <returns>A list of ArraySegment&lt;byte&gt; buffers.</returns>
        public List <ArraySegment <byte> > GetSharedBufferList(int maxCount, long maxBytes)
        {
            Debug.Assert(maxCount > 0);
            Debug.Assert(maxBytes > 0);

            long ioBufferSize   = 0;
            int  nioBufferCount = 0;
            InternalThreadLocalMap      threadLocalMap = InternalThreadLocalMap.Get();
            List <ArraySegment <byte> > nioBuffers     = NioBuffers.Get(threadLocalMap);
            Entry entry = this.flushedEntry;

            while (this.IsFlushedEntry(entry) && entry.Message is IByteBuffer)
            {
                if (!entry.Cancelled)
                {
                    var buf           = (IByteBuffer)entry.Message;
                    int readerIndex   = buf.ReaderIndex;
                    int readableBytes = buf.WriterIndex - readerIndex;

                    if (readableBytes > 0)
                    {
                        if (maxBytes - readableBytes < ioBufferSize && nioBufferCount != 0)
                        {
                            // If the nioBufferSize + readableBytes will overflow an Integer we stop populate the
                            // ByteBuffer array. This is done as bsd/osx don't allow to write more bytes then
                            // Integer.MAX_VALUE with one writev(...) call and so will return 'EINVAL', which will
                            // raise an IOException. On Linux it may work depending on the
                            // architecture and kernel but to be safe we also enforce the limit here.
                            // This said writing more the Integer.MAX_VALUE is not a good idea anyway.
                            //
                            // See also:
                            // - https://www.freebsd.org/cgi/man.cgi?query=write&sektion=2
                            // - http://linux.die.net/man/2/writev
                            break;
                        }
                        ioBufferSize += readableBytes;
                        int count = entry.Count;
                        if (count == -1)
                        {
                            entry.Count = count = buf.IoBufferCount;
                        }
                        if (count == 1)
                        {
                            ArraySegment <byte> nioBuf = entry.Buffer;
                            if (nioBuf.Array == null)
                            {
                                // cache ByteBuffer as it may need to create a new ByteBuffer instance if its a
                                // derived buffer
                                entry.Buffer = nioBuf = buf.GetIoBuffer(readerIndex, readableBytes);
                            }
                            nioBuffers.Add(nioBuf);
                            nioBufferCount++;
                        }
                        else
                        {
                            ArraySegment <byte>[] nioBufs = entry.Buffers;
                            if (nioBufs == null)
                            {
                                // cached ByteBuffers as they may be expensive to create in terms
                                // of Object allocation
                                entry.Buffers = nioBufs = buf.GetIoBuffers();
                            }
                            for (int i = 0; i < nioBufs.Length && nioBufferCount < maxCount; i++)
                            {
                                ArraySegment <byte> nioBuf = nioBufs[i];
                                if (nioBuf.Array == null)
                                {
                                    break;
                                }
                                else if (nioBuf.Count == 0)
                                {
                                    continue;
                                }
                                nioBuffers.Add(nioBuf);
                                nioBufferCount++;
                            }
                        }
                        if (nioBufferCount == maxCount)
                        {
                            break;
                        }
                    }
                }
                entry = entry.Next;
            }
            this.nioBufferSize = ioBufferSize;

            return(nioBuffers);
        }
示例#8
0
 internal static StringBuilder StringBuilder() => InternalThreadLocalMap.Get().StringBuilder;
        public static IList <ICharSequence> UnescapeCsvFields(ICharSequence value)
        {
            var           unescaped = new List <ICharSequence>(2);
            StringBuilder current   = InternalThreadLocalMap.Get().StringBuilder;
            bool          quoted    = false;
            int           last      = value.Count - 1;

            for (int i = 0; i <= last; i++)
            {
                char c = value[i];
                if (quoted)
                {
                    switch (c)
                    {
                    case DoubleQuote:
                        if (i == last)
                        {
                            // Add the last field and return
                            unescaped.Add((StringCharSequence)current.ToString());
                            return(unescaped);
                        }
                        char next = value[++i];
                        if (next == DoubleQuote)
                        {
                            // 2 double-quotes should be unescaped to one
                            current.Append(DoubleQuote);
                        }
                        else if (next == Comma)
                        {
                            // This is the end of a field. Let's start to parse the next field.
                            quoted = false;
                            unescaped.Add((StringCharSequence)current.ToString());
                            current.Length = 0;
                        }
                        else
                        {
                            // double-quote followed by other character is invalid
                            throw new ArgumentException($"invalid escaped CSV field: {value} index: {i - 1}");
                        }
                        break;

                    default:
                        current.Append(c);
                        break;
                    }
                }
                else
                {
                    switch (c)
                    {
                    case Comma:
                        // Start to parse the next field
                        unescaped.Add((StringCharSequence)current.ToString());
                        current.Length = 0;
                        break;

                    case DoubleQuote:
                        if (current.Length == 0)
                        {
                            quoted = true;
                        }
                        else
                        {
                            // double-quote appears without being enclosed with double-quotes
                            current.Append(c);
                        }
                        break;

                    case LineFeed:
                    case CarriageReturn:
                        // special characters appears without being enclosed with double-quotes
                        throw new ArgumentException($"invalid escaped CSV field: {value} index: {i}");

                    default:
                        current.Append(c);
                        break;
                    }
                }
            }
            if (quoted)
            {
                throw new ArgumentException($"invalid escaped CSV field: {value} index: {last}");
            }

            unescaped.Add((StringCharSequence)current.ToString());
            return(unescaped);
        }
示例#10
0
        ///
        ///Returns an array of direct NIO buffers if the currently pending messages are made of {@link ByteBuf} only.
        ///{@link #nioBufferCount()} and {@link #nioBufferSize()} will return the number of NIO buffers in the returned
        ///array and the total number of readable bytes of the NIO buffers respectively.
        ///<p>
        ///Note that the returned array is reused and thus should not escape
        ///{@link AbstractChannel#doWrite(ChannelOutboundBuffer)}.
        ///Refer to {@link NioSocketChannel#doWrite(ChannelOutboundBuffer)} for an example.
        ///</p>
        ///
        public List <ArraySegment <byte> > GetNioBuffers()
        {
            long nioBufferSize = 0;
            InternalThreadLocalMap      threadLocalMap = InternalThreadLocalMap.Get();
            List <ArraySegment <byte> > nioBuffers     = NioBuffers.Get(threadLocalMap);
            Entry entry = _flushedEntry;

            while (IsFlushedEntry(entry) && entry.Message is IByteBuf)
            {
                if (!entry.Cancelled)
                {
                    var buf           = (IByteBuf)entry.Message;
                    int readerIndex   = buf.ReaderIndex;
                    int readableBytes = buf.WriterIndex - readerIndex;

                    if (readableBytes > 0)
                    {
                        if (int.MaxValue - readableBytes < nioBufferSize)
                        {
                            // If the nioBufferSize + readableBytes will overflow an Integer we stop populate the
                            // ByteBuffer array. This is done as bsd/osx don't allow to write more bytes then
                            // Integer.MAX_VALUE with one writev(...) call and so will return 'EINVAL', which will
                            // raise an IOException. On Linux it may work depending on the
                            // architecture and kernel but to be safe we also enforce the limit here.
                            // This said writing more the Integer.MAX_VALUE is not a good idea anyway.
                            //
                            // See also:
                            // - https://www.freebsd.org/cgi/man.cgi?query=write&sektion=2
                            // - http://linux.die.net/man/2/writev
                            break;
                        }
                        nioBufferSize += readableBytes;
                        int count = entry.Count;
                        if (count == -1)
                        {
                            //noinspection ConstantValueVariableUse
                            entry.Count = count = buf.IoBufferCount;
                        }
                        if (count == 1)
                        {
                            ArraySegment <byte> nioBuf = entry.Buffer;
                            if (nioBuf.Array == null)
                            {
                                // cache ByteBuffer as it may need to create a new ByteBuffer instance if its a
                                // derived buffer
                                entry.Buffer = nioBuf = buf.GetIoBuffer(readerIndex, readableBytes);
                            }
                            nioBuffers.Add(nioBuf);
                        }
                        else
                        {
                            ArraySegment <byte>[] nioBufs = entry.Buffers;
                            if (nioBufs == null)
                            {
                                // cached ByteBuffers as they may be expensive to create in terms
                                // of Object allocation
                                entry.Buffers = nioBufs = buf.GetIoBuffers();
                            }
                            foreach (ArraySegment <byte> b in nioBufs)
                            {
                                nioBuffers.Add(b);
                            }
                        }
                    }
                }
                entry = entry.Next;
            }
            this.NioBufferSize = nioBufferSize;

            return(nioBuffers);
        }