prefer to use standard netty bytebuf.toString since now it use cache under the hood
[idea/community.git] / platform / platform-impl / src / io / netty / buffer / ByteBufUtilEx.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package io.netty.buffer;
17
18 import io.netty.util.CharsetUtil;
19 import org.jetbrains.annotations.NotNull;
20
21 // todo pull request
22 public class ByteBufUtilEx {
23   public static int writeUtf8(ByteBuf buf, CharSequence seq) {
24     return writeUtf8(buf, seq, 0, seq.length());
25   }
26
27   public static int writeUtf8(ByteBuf buf, CharSequence seq, int start, int end) {
28     if (buf == null) {
29       throw new NullPointerException("buf");
30     }
31     if (seq == null) {
32       throw new NullPointerException("seq");
33     }
34     // UTF-8 uses max. 3 bytes per char, so calculate the worst case.
35     final int len = end - start;
36     final int maxSize = len * 3;
37     buf.ensureWritable(maxSize);
38
39     int oldWriterIndex;
40     AbstractByteBuf buffer;
41     if (buf instanceof AbstractByteBuf) {
42       buffer = (AbstractByteBuf)buf;
43       oldWriterIndex = buffer.writerIndex;
44
45     }
46     else {
47       ByteBuf underlying = buf.unwrap();
48       if (underlying instanceof AbstractByteBuf) {
49         buffer = (AbstractByteBuf)underlying;
50         oldWriterIndex = buf.writerIndex();
51       }
52       else {
53         byte[] bytes = seq.toString().getBytes(CharsetUtil.UTF_8);
54         buf.writeBytes(bytes);
55         return bytes.length;
56       }
57     }
58
59     int writerIndex = oldWriterIndex;
60     // We can use the _set methods as these not need to do any index checks and reference checks.
61     // This is possible as we called ensureWritable(...) before.
62     for (int i = start; i < end; i++) {
63       writerIndex = writeChar(buffer, writerIndex, seq.charAt(i));
64     }
65
66     // update the writerIndex without any extra checks for performance reasons
67     if (buf == buffer) {
68       buffer.writerIndex = writerIndex;
69     }
70     else {
71       buf.writerIndex(writerIndex);
72     }
73     return writerIndex - oldWriterIndex;
74   }
75
76   static int writeChar(AbstractByteBuf buffer, int writerIndex, int c) {
77     if (c < 0x80) {
78       buffer._setByte(writerIndex++, (byte)c);
79     }
80     else if (c < 0x800) {
81       buffer._setByte(writerIndex++, (byte)(0xc0 | (c >> 6)));
82       buffer._setByte(writerIndex++, (byte)(0x80 | (c & 0x3f)));
83     }
84     else {
85       buffer._setByte(writerIndex++, (byte)(0xe0 | (c >> 12)));
86       buffer._setByte(writerIndex++, (byte)(0x80 | ((c >> 6) & 0x3f)));
87       buffer._setByte(writerIndex++, (byte)(0x80 | (c & 0x3f)));
88     }
89     return writerIndex;
90   }
91
92   @NotNull
93   static AbstractByteBuf getBuf(@NotNull ByteBuf buffer) {
94     if (buffer instanceof AbstractByteBuf) {
95       return (AbstractByteBuf)buffer;
96     }
97     else {
98       return (AbstractByteBuf)((WrappedByteBuf)buffer).buf;
99     }
100   }
101 }