コード例 #1
0
        /// <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);
        }
コード例 #2
0
 internal static StringBuilder StringBuilder() => InternalThreadLocalMap.Get().StringBuilder;
コード例 #3
0
        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);
        }
コード例 #4
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);
        }