2 * Copyright 2015 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <folly/wangle/codec/LineBasedFrameDecoder.h>
18 namespace folly { namespace wangle {
20 using folly::io::Cursor;
22 LineBasedFrameDecoder::LineBasedFrameDecoder(uint32_t maxLength,
24 TerminatorType terminatorType)
25 : maxLength_(maxLength)
26 , stripDelimiter_(stripDelimiter)
27 , terminatorType_(terminatorType) {}
29 std::unique_ptr<IOBuf> LineBasedFrameDecoder::decode(
30 Context* ctx, IOBufQueue& buf, size_t&) {
31 int64_t eol = findEndOfLine(buf);
35 Cursor c(buf.front());
37 auto delimLength = c.read<char>() == '\r' ? 2 : 1;
38 if (eol > maxLength_) {
39 buf.split(eol + delimLength);
40 fail(ctx, folly::to<std::string>(eol));
44 std::unique_ptr<folly::IOBuf> frame;
46 if (stripDelimiter_) {
47 frame = buf.split(eol);
48 buf.trimStart(delimLength);
50 frame = buf.split(eol + delimLength);
53 return std::move(frame);
55 auto len = buf.chainLength();
56 if (len > maxLength_) {
57 discardedBytes_ = len;
60 fail(ctx, "over " + folly::to<std::string>(len));
66 Cursor c(buf.front());
68 auto delimLength = c.read<char>() == '\r' ? 2 : 1;
69 buf.trimStart(eol + delimLength);
73 discardedBytes_ = buf.chainLength();
81 void LineBasedFrameDecoder::fail(Context* ctx, std::string len) {
82 ctx->fireReadException(
83 folly::make_exception_wrapper<std::runtime_error>(
84 "frame length" + len +
85 " exeeds max " + folly::to<std::string>(maxLength_)));
88 int64_t LineBasedFrameDecoder::findEndOfLine(IOBufQueue& buf) {
89 Cursor c(buf.front());
90 for (uint32_t i = 0; i < maxLength_ && i < buf.chainLength(); i++) {
91 auto b = c.read<char>();
92 if (b == '\n' && terminatorType_ != TerminatorType::CARRIAGENEWLINE) {
94 } else if (terminatorType_ != TerminatorType::NEWLINE &&
95 b == '\r' && !c.isAtEnd() && c.read<char>() == '\n') {