IOBufQueue RFC1867Codec::readToBoundary()

in proxygen/lib/http/experimental/RFC1867.cpp [220:292]


IOBufQueue RFC1867Codec::readToBoundary(bool& foundBoundary) {
  IOBufQueue result{IOBufQueue::cacheChainLength()};
  BoundaryResult boundaryResult = BoundaryResult::NO;

  while (!input_.empty() && boundaryResult != BoundaryResult::PARTIAL) {
    const IOBuf* head = input_.front();
    uint64_t len = head->length();
    const uint8_t* ptr = head->data();

    /* iterate through first character matches */
    while (len > 0 && (ptr = (const uint8_t*)memchr(ptr, boundary_[0], len))) {
      /* calculate length after match */
      uint64_t readlen = (ptr - head->data());
      len = head->length() - readlen;
      boundaryResult =
          isBoundary(*head, readlen, boundary_.data(), boundary_.length());
      if (boundaryResult == BoundaryResult::YES) {
        CHECK(readlen < head->length());
        bool hasCr = false;
        if (readlen == 0 && pendingCR_) {
          pendingCR_.reset();
        }
        if (readlen > 0) {
          // If the last read char is a CR omit from result
          Cursor c(head);
          c.skip(readlen - 1);
          uint8_t ch = c.read<uint8_t>();
          if (ch == '\r') {
            --readlen;
            hasCr = true;
          }
        }
        result.append(std::move(pendingCR_));
        result.append(input_.split(readlen));
        uint32_t trimLen = boundary_.length() + (hasCr ? 1 : 0);
        input_.trimStart(trimLen);
        bytesProcessed_ += readlen + trimLen;
        foundBoundary = true;
        return result;
      } else if (boundaryResult == BoundaryResult::PARTIAL) {
        break;
      } else if (pendingCR_) {
        // not a match, append pending CR to result
        result.append(std::move(pendingCR_));
      }

      /* next character */
      ptr++;
      len--;
    }
    uint64_t resultLen = ptr ? ptr - head->data() : head->length();
    // Put pendingCR_ in result if there was no partial match in head, or a
    // partial match starting after the first character
    if ((boundaryResult == BoundaryResult::NO || resultLen > 0) && pendingCR_) {
      result.append(std::move(pendingCR_));
    }
    // the boundary does not start through resultLen, append it
    // to result, except maybe the last char if it's a CR.
    if (resultLen > 0 && head->data()[resultLen - 1] == '\r') {
      result.append(input_.split(resultLen - 1));
      CHECK(!pendingCR_);
      pendingCR_ = input_.split(1);
    } else {
      result.append(input_.split(resultLen));
    }
    bytesProcessed_ += resultLen;
  }

  // reached the end but no boundary found
  foundBoundary = false;

  return result;
}