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()); }
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; } } }
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; } } }
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<byte>, 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<byte> 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); }
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); }
/// ///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); }