docs: public boolean parseLine(WsByteBuffer buff) throws Exception {
          final boolean bTrace = TraceComponent.isAnyTracingEnabled();
          if (bTrace && tc.isDebugEnabled()) {
              Tr.debug(tc, "parseLine called for " + this);
          }
  
          //PI34161 - Record the start of the request at the time of parsing
          if ((this instanceof HttpRequestMessageImpl) && ((HttpRequestMessageImpl) this).getServiceContext().getHttpConfig().isAccessLoggingEnabled()) {
              this.startTime = System.nanoTime();
          }
  
          boolean rc = false;
          int startpos = (bTrace && tc.isDebugEnabled()) ? buff.position() : 0;
          TokenCodes tcRC = TokenCodes.TOKEN_RC_MOREDATA;
  
          // stop parsing the FirstLine when we either hit the end of it (CRLF)
          // or we hit the end of the buffer and need to read more
          while (!rc) {
              if (0 == this.numFirstLineTokensRead) {
                  // first token, skip leading CRLFs (up to 16 blank lines)
                  tcRC = skipCRLFs(buff);
                  if (TokenCodes.TOKEN_RC_DELIM.equals(tcRC)) {
                      try {
                          tcRC = parseTokenExtract(buff, SPACE, false, LOG_FULL);
                          if (!tcRC.equals(TokenCodes.TOKEN_RC_MOREDATA)) {
                              setParsedFirstToken(getParsedToken());
                          }
                      } catch (MalformedMessageException mme) {
                          // no FFDC required
  
                          // debug print this failing first token to help figure
                          // out why the error happened, usually buffer corruption
                          // Note: if this was discrimination, then it should just
                          // mean it wasn't our data, but we can't tell here which
                          // path it was (i.e. should it have worked)
                          if (bTrace && tc.isDebugEnabled()) {
                              int curpos = buff.position();
                              buff.position(startpos);
                              byte[] data;
                              int offset = 0;
                              if (null != getParsedToken()) {
                                  offset = getParsedToken().length;
                                  data = new byte[(curpos - startpos) + offset];
                                  System.arraycopy(getParsedToken(), 0, data, 0, offset);
                              } else {
                                  data = new byte[(curpos - startpos)];
                              }
                              buff.get(data, offset, data.length - offset);
                              Tr.debug(tc, "Initial parse of message failed, (128) of buffer: \n"
                                           + GenericUtils.getHexDump(data, 128));
                          }
                          throw mme;
                      }
                  } else if (TokenCodes.TOKEN_RC_MOREDATA.equals(tcRC)) {
                      // ran out of data
                      resetByteCache();
                      break; // out of while
                  } else if (TokenCodes.TOKEN_RC_CRLF.equals(tcRC)) {
                      throw new MalformedMessageException("Too many leading CRLFs");
                  }
              } else if (1 == this.numFirstLineTokensRead) {
                  // second token
                  tcRC = parseTokenExtract(buff, SPACE, true, LOG_PARTIAL);
                  if (!tcRC.equals(TokenCodes.TOKEN_RC_MOREDATA)) {
                      setParsedSecondToken(getParsedToken());
                      if (tcRC.equals(TokenCodes.TOKEN_RC_CRLF)) {
                          if (bTrace && tc.isDebugEnabled()) {
                              Tr.debug(tc, "Received CRLF after second token");
                          }
                          rc = true;
                      }
                  }
              } else if (2 == this.numFirstLineTokensRead) {
                  // third token
                  tcRC = parseCRLFTokenExtract(buff, LOG_FULL);
                  if (!tcRC.equals(TokenCodes.TOKEN_RC_MOREDATA)) {
                      setParsedThirdToken(getParsedToken());
                      rc = true;
                  }
              } else {
                  // stop coming here
                  rc = true;
              }
  
              // scenarios where we need more data result in the MOREDATA RC above
              if (tcRC.equals(TokenCodes.TOKEN_RC_MOREDATA)) {
                  resetByteCache();
                  break; // out of while
              }
  
              // otherwise we finished parsing a single token
              setParsedToken(null);
              this.numFirstLineTokensRead++;
          } // end of while loop
  
          if (rc) {
              parsingComplete();
              setFirstLineComplete(true);
              // PK15898
              // go back one from the delimiter, unless it was an LF (if first
              // line ends with just an LF and not CRLF then we don't want to
              // change position as the header parsing above would consider it the
              // end of headers)
              decrementBytePositionIgnoringLFs();
          }
  
          if (bTrace && tc.isDebugEnabled()) {
              Tr.debug(tc, "parseLine returning " + rc + " for " + this);
          }
          return rc;
      }