1 package org.jetbrains.io;
3 import io.netty.buffer.ByteBuf;
4 import io.netty.channel.ChannelHandlerContext;
5 import io.netty.util.CharsetUtil;
6 import org.jetbrains.annotations.NotNull;
7 import org.jetbrains.annotations.Nullable;
9 import java.nio.CharBuffer;
10 import java.nio.charset.CharacterCodingException;
11 import java.nio.charset.CharsetDecoder;
13 public abstract class MessageDecoder extends Decoder {
14 protected int contentLength;
15 protected final StringBuilder builder = new StringBuilder(64);
17 private CharBuffer chunkedContent;
18 private int consumedContentByteCount = 0;
20 private final CharsetDecoder charsetDecoder = CharsetUtil.getDecoder(CharsetUtil.UTF_8);
22 protected final int parseContentLength() {
23 return parseInt(builder, 0, false, 10);
27 protected final CharSequence readChars(@NotNull ByteBuf input) throws CharacterCodingException {
28 if (!input.isReadable()) {
32 int required = contentLength - consumedContentByteCount;
33 if (input.readableBytes() < required) {
34 if (chunkedContent == null) {
35 chunkedContent = CharBuffer.allocate((int)((float)contentLength * charsetDecoder.maxCharsPerByte()));
38 int count = input.readableBytes();
39 ChannelBufferToString.readIntoCharBuffer(charsetDecoder, input, count, chunkedContent);
40 consumedContentByteCount += count;
44 CharBuffer charBuffer = chunkedContent;
45 if (charBuffer != null) {
46 chunkedContent = null;
47 consumedContentByteCount = 0;
49 return new ChannelBufferToString.MyCharArrayCharSequence(ChannelBufferToString.readIntoCharBuffer(charsetDecoder, input, required, charBuffer));
54 public void channelInactive(ChannelHandlerContext context) throws Exception {
56 chunkedContent = null;
59 super.channelInactive(context);
63 public static boolean readUntil(char what, @NotNull ByteBuf buffer, @NotNull StringBuilder builder) {
64 int i = buffer.readerIndex();
65 //noinspection ForLoopThatDoesntUseLoopVariable
66 for (int n = buffer.writerIndex(); i < n; i++) {
67 char c = (char)buffer.getByte(i);
69 buffer.readerIndex(i + 1);
76 buffer.readerIndex(i);
80 public static void skipWhitespace(@NotNull ByteBuf buffer) {
81 int i = buffer.readerIndex();
82 int n = buffer.writerIndex();
84 char c = (char)buffer.getByte(i);
86 buffer.readerIndex(i);
90 buffer.readerIndex(n);
94 * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
95 * Copyright (C) 2006 - Javolution (http://javolution.org/)
96 * All rights reserved.
98 * Permission to use, copy, modify, and distribute this software is
99 * freely granted, provided that this notice is preserved.
101 public static int parseInt(@NotNull CharSequence value, int start, boolean isNegative, int radix) {
102 final int end = value.length();
103 int result = 0; // Accumulates negatively (avoid MIN_VALUE overflow).
105 for (; i < end; i++) {
106 char c = value.charAt(i);
107 int digit = (c <= '9') ? c - '0'
108 : ((c <= 'Z') && (c >= 'A')) ? c - 'A' + 10
109 : ((c <= 'z') && (c >= 'a')) ? c - 'a' + 10 : -1;
110 if ((digit >= 0) && (digit < radix)) {
111 int newResult = result * radix - digit;
112 if (newResult > result) {
113 throw new NumberFormatException("Overflow parsing " + value.subSequence(start, end));
121 // Requires one valid digit character and checks for opposite overflow.
122 if ((result == 0) && ((end == 0) || (value.charAt(i - 1) != '0'))) {
123 throw new NumberFormatException("Invalid integer representation for " + value.subSequence(start, end));
125 if ((result == Integer.MIN_VALUE) && !isNegative) {
126 throw new NumberFormatException("Overflow parsing " + value.subSequence(start, end));
128 return isNegative ? result : -result;