/** Read bytes from the previous buffer. */
  protected int readBytes() throws IOException {

    int nRead = buffer.doRead(readChunk, null);
    pos = readChunk.getStart();
    lastValid = pos + nRead;
    buf = readChunk.getBytes();

    return nRead;
  }
  private boolean parseHeader() throws IOException {

    MimeHeaders headers = request.getMimeHeaders();

    byte chr = 0;
    while (true) {
      // Read new bytes if needed
      if (pos >= lastValid) {
        if (readBytes() < 0)
          throw new EOFException(
              "Unexpected end of stream whilst reading trailer headers for chunked request");
      }

      chr = buf[pos];

      if ((chr == Constants.CR) || (chr == Constants.LF)) {
        if (chr == Constants.LF) {
          pos++;
          return false;
        }
      } else {
        break;
      }

      pos++;
    }

    // Mark the current buffer position
    int start = trailingHeaders.getEnd();

    //
    // Reading the header name
    // Header name is always US-ASCII
    //

    boolean colon = false;
    while (!colon) {

      // Read new bytes if needed
      if (pos >= lastValid) {
        if (readBytes() < 0)
          throw new EOFException(
              "Unexpected end of stream whilst reading trailer headers for chunked request");
      }

      chr = buf[pos];
      if ((chr >= Constants.A) && (chr <= Constants.Z)) {
        chr = (byte) (chr - Constants.LC_OFFSET);
      }

      if (chr == Constants.COLON) {
        colon = true;
      } else {
        trailingHeaders.append(chr);
      }

      pos++;
    }
    MessageBytes headerValue =
        headers.addValue(trailingHeaders.getBytes(), start, trailingHeaders.getEnd() - start);

    // Mark the current buffer position
    start = trailingHeaders.getEnd();

    //
    // Reading the header value (which can be spanned over multiple lines)
    //

    boolean eol = false;
    boolean validLine = true;
    int lastSignificantChar = 0;

    while (validLine) {

      boolean space = true;

      // Skipping spaces
      while (space) {

        // Read new bytes if needed
        if (pos >= lastValid) {
          if (readBytes() < 0)
            throw new EOFException(
                "Unexpected end of stream whilst reading trailer headers for chunked request");
        }

        chr = buf[pos];
        if ((chr == Constants.SP) || (chr == Constants.HT)) {
          pos++;
        } else {
          space = false;
        }
      }

      // Reading bytes until the end of the line
      while (!eol) {

        // Read new bytes if needed
        if (pos >= lastValid) {
          if (readBytes() < 0)
            throw new EOFException(
                "Unexpected end of stream whilst reading trailer headers for chunked request");
        }

        chr = buf[pos];
        if (chr == Constants.CR) {
          // Skip
        } else if (chr == Constants.LF) {
          eol = true;
        } else if (chr == Constants.SP) {
          trailingHeaders.append(chr);
        } else {
          trailingHeaders.append(chr);
          lastSignificantChar = trailingHeaders.getEnd();
        }

        pos++;
      }

      // Checking the first character of the new line. If the character
      // is a LWS, then it's a multiline header

      // Read new bytes if needed
      if (pos >= lastValid) {
        if (readBytes() < 0)
          throw new EOFException(
              "Unexpected end of stream whilst reading trailer headers for chunked request");
      }

      chr = buf[pos];
      if ((chr != Constants.SP) && (chr != Constants.HT)) {
        validLine = false;
      } else {
        eol = false;
        // Copying one extra space in the buffer (since there must
        // be at least one space inserted between the lines)
        trailingHeaders.append(chr);
      }
    }

    // Set the header value
    headerValue.setBytes(trailingHeaders.getBytes(), start, lastSignificantChar - start);

    return true;
  }