core/play/src/main/java/play/core/cookie/encoding/ClientCookieDecoder.java
public Cookie decode(String header) {
    if (header == null) {
      throw new NullPointerException("header");
    }
    final int headerLen = header.length();

    if (headerLen == 0) {
      return null;
    }

    CookieBuilder cookieBuilder = null;

    loop:
    for (int i = 0; ; ) {

      // Skip spaces and separators.
      for (; ; ) {
        if (i == headerLen) {
          break loop;
        }
        char c = header.charAt(i);
        if (c == ',') {
          // Having multiple cookies in a single Set-Cookie header is
          // deprecated, modern browsers only parse the first one
          break loop;

        } else if (c == '\t' || c == '\n' || c == 0x0b || c == '\f' || c == '\r' || c == ' '
            || c == ';') {
          i++;
          continue;
        }
        break;
      }

      int nameBegin = i;
      int nameEnd = i;
      int valueBegin = -1;
      int valueEnd = -1;

      if (i != headerLen) {
        keyValLoop:
        for (; ; ) {

          char curChar = header.charAt(i);
          if (curChar == ';') {
            // NAME; (no value till ';')
            nameEnd = i;
            valueBegin = valueEnd = -1;
            break keyValLoop;

          } else if (curChar == '=') {
            // NAME=VALUE
            nameEnd = i;
            i++;
            if (i == headerLen) {
              // NAME= (empty value, i.e. nothing after '=')
              valueBegin = valueEnd = 0;
              break keyValLoop;
            }

            valueBegin = i;
            // NAME=VALUE;
            int semiPos = header.indexOf(';', i);
            valueEnd = i = semiPos > 0 ? semiPos : headerLen;
            break keyValLoop;
          } else {
            i++;
          }

          if (i == headerLen) {
            // NAME (no value till the end of string)
            nameEnd = headerLen;
            valueBegin = valueEnd = -1;
            break;
          }
        }
      }

      if (valueEnd > 0 && header.charAt(valueEnd - 1) == ',') {
        // old multiple cookies separator, skipping it
        valueEnd--;
      }

      if (cookieBuilder == null) {
        // cookie name-value pair
        DefaultCookie cookie = initCookie(header, nameBegin, nameEnd, valueBegin, valueEnd);

        if (cookie == null) {
          return null;
        }

        cookieBuilder = new CookieBuilder(cookie);
      } else {
        // cookie attribute
        String attrValue = valueBegin == -1 ? null : header.substring(valueBegin, valueEnd);
        cookieBuilder.appendAttribute(header, nameBegin, nameEnd, attrValue);
      }
    }
    return cookieBuilder.cookie();
  }
public Cookie decode(String header) {
    if (header == null) {
      throw new NullPointerException("header");
    }
    final int headerLen = header.length();

    if (headerLen == 0) {
      return null;
    }

    CookieBuilder cookieBuilder = null;

    loop:
    for (int i = 0; ; ) {

      // Skip spaces and separators.
      for (; ; ) {
        if (i == headerLen) {
          break loop;
        }
        char c = header.charAt(i);
        if (c == ',') {
          // Having multiple cookies in a single Set-Cookie header is
          // deprecated, modern browsers only parse the first one
          break loop;

        } else if (c == '\t' || c == '\n' || c == 0x0b || c == '\f' || c == '\r' || c == ' '
            || c == ';') {
          i++;
          continue;
        }
        break;
      }

      int nameBegin = i;
      int nameEnd = i;
      int valueBegin = -1;
      int valueEnd = -1;

      if (i != headerLen) {
        keyValLoop:
        for (; ; ) {

          char curChar = header.charAt(i);
          if (curChar == ';') {
            // NAME; (no value till ';')
            nameEnd = i;
            valueBegin = valueEnd = -1;
            break keyValLoop;

          } else if (curChar == '=') {
            // NAME=VALUE
            nameEnd = i;
            i++;
            if (i == headerLen) {
              // NAME= (empty value, i.e. nothing after '=')
              valueBegin = valueEnd = 0;
              break keyValLoop;
            }

            valueBegin = i;
            // NAME=VALUE;
            int semiPos = header.indexOf(';', i);
            valueEnd = i = semiPos > 0 ? semiPos : headerLen;
            break keyValLoop;
          } else {
            i++;
          }

          if (i == headerLen) {
            // NAME (no value till the end of string)
            nameEnd = headerLen;
            valueBegin = valueEnd = -1;
            break;
          }
        }
      }

      if (valueEnd > 0 && header.charAt(valueEnd - 1) == ',') {
        // old multiple cookies separator, skipping it
        valueEnd--;
      }

      if (cookieBuilder == null) {
        // cookie name-value pair
        DefaultCookie cookie = initCookie(header, nameBegin, nameEnd, valueBegin, valueEnd);

        if (cookie == null) {
          return null;
        }

        cookieBuilder = new CookieBuilder(cookie);
      } else {
        // cookie attribute
        String attrValue = valueBegin == -1 ? null : header.substring(valueBegin, valueEnd);
        cookieBuilder.appendAttribute(header, nameBegin, nameEnd, attrValue);
      }
    }
    return cookieBuilder.cookie();
  }
Decodes the specified Set-Cookie HTTP header value into a {@link Cookie}.

@param header the Set-Cookie header.
@return the decoded {@link Cookie}