diff --git a/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java b/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java
index 8f049fac5a..3e231285a0 100644
--- a/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java
+++ b/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java
@@ -507,12 +507,26 @@ public final class ByteBufUtil {
* is allocated via the {@link ByteBufAllocator}.
*/
public static ByteBuf encodeString(ByteBufAllocator alloc, CharBuffer src, Charset charset) {
- return encodeString0(alloc, false, src, charset);
+ return encodeString0(alloc, false, src, charset, 0);
}
- static ByteBuf encodeString0(ByteBufAllocator alloc, boolean enforceHeap, CharBuffer src, Charset charset) {
+ /**
+ * Encode the given {@link CharBuffer} using the given {@link Charset} into a new {@link ByteBuf} which
+ * is allocated via the {@link ByteBufAllocator}.
+ *
+ * @param alloc The {@link ByteBufAllocator} to allocate {@link ByteBuf}.
+ * @param src The {@link CharBuffer} to encode.
+ * @param charset The specified {@link Charset}.
+ * @param extraCapacity the extra capacity to alloc except the space for decoding.
+ */
+ public static ByteBuf encodeString(ByteBufAllocator alloc, CharBuffer src, Charset charset, int extraCapacity) {
+ return encodeString0(alloc, false, src, charset, extraCapacity);
+ }
+
+ static ByteBuf encodeString0(ByteBufAllocator alloc, boolean enforceHeap, CharBuffer src, Charset charset,
+ int extraCapacity) {
final CharsetEncoder encoder = CharsetUtil.encoder(charset);
- int length = (int) ((double) src.remaining() * encoder.maxBytesPerChar());
+ int length = (int) ((double) src.remaining() * encoder.maxBytesPerChar()) + extraCapacity;
boolean release = true;
final ByteBuf dst;
if (enforceHeap) {
diff --git a/buffer/src/main/java/io/netty/buffer/Unpooled.java b/buffer/src/main/java/io/netty/buffer/Unpooled.java
index 0532c0c6a1..c2b45752ca 100644
--- a/buffer/src/main/java/io/netty/buffer/Unpooled.java
+++ b/buffer/src/main/java/io/netty/buffer/Unpooled.java
@@ -666,7 +666,7 @@ public final class Unpooled {
}
private static ByteBuf copiedBuffer(CharBuffer buffer, Charset charset) {
- return ByteBufUtil.encodeString0(ALLOC, true, buffer, charset);
+ return ByteBufUtil.encodeString0(ALLOC, true, buffer, charset, 0);
}
/**
diff --git a/codec/src/main/java/io/netty/handler/codec/string/LineEncoder.java b/codec/src/main/java/io/netty/handler/codec/string/LineEncoder.java
new file mode 100644
index 0000000000..4b605567f5
--- /dev/null
+++ b/codec/src/main/java/io/netty/handler/codec/string/LineEncoder.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.handler.codec.string;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPipeline;
+import io.netty.handler.codec.LineBasedFrameDecoder;
+import io.netty.handler.codec.MessageToMessageEncoder;
+import io.netty.util.CharsetUtil;
+import io.netty.util.internal.ObjectUtil;
+
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.List;
+
+/**
+ * Apply a line separator to the requested {@link String} and encode it into a {@link ByteBuf}.
+ * A typical setup for a text-based line protocol in a TCP/IP socket would be:
+ *
+ */
+@Sharable
+public class LineEncoder extends MessageToMessageEncoder {
+
+ private final Charset charset;
+ private final byte[] lineSeparator;
+
+ /**
+ * Creates a new instance with the current system line separator and UTF-8 charset encoding.
+ */
+ public LineEncoder() {
+ this(LineSeparator.DEFAULT, CharsetUtil.UTF_8);
+ }
+
+ /**
+ * Creates a new instance with the specified line separator and UTF-8 charset encoding.
+ */
+ public LineEncoder(LineSeparator lineSeparator) {
+ this(lineSeparator, CharsetUtil.UTF_8);
+ }
+
+ /**
+ * Creates a new instance with the specified character set.
+ */
+ public LineEncoder(Charset charset) {
+ this(LineSeparator.DEFAULT, charset);
+ }
+
+ /**
+ * Creates a new instance with the specified line separator and character set.
+ */
+ public LineEncoder(LineSeparator lineSeparator, Charset charset) {
+ this.charset = ObjectUtil.checkNotNull(charset, "charset");
+ this.lineSeparator = ObjectUtil.checkNotNull(lineSeparator, "lineSeparator").value().getBytes(charset);
+ }
+
+ @Override
+ protected void encode(ChannelHandlerContext ctx, CharSequence msg, List