void URLStreamHandler::parseURL()

in activemq-cpp/src/main/decaf/net/URLStreamHandler.cpp [185:294]


void URLStreamHandler::parseURL(URL& url, const String& spec, int start, int limit) {

    if (limit < start || limit < 0) {
        if ((limit <= Integer::MIN_VALUE + 1 && (start >= spec.length() || start < 0)) ||
            (spec.startsWith("//", start) && spec.indexOf('/', start + 2) == -1)) {
            throw StringIndexOutOfBoundsException(__FILE__, __LINE__, limit);
        }
        if (this != url.getURLStreamHandler()) {
            throw SecurityException(__FILE__, __LINE__, "Only the URL's stream handler can modify");
        }
        return;
    }

    int fileStart;
    String authority;
    String userInfo;
    String host;
    int port = -1;
    String path;
    String query;
    String ref;

    if (spec.regionMatches(start, "//", 0, 2)) {
        // Parse the authority from the spec.
        int authorityStart = start + 2;
        fileStart = URLUtils::findFirstOf(spec, "/?#", authorityStart, limit);
        authority = spec.substring(authorityStart, fileStart);

        int userInfoEnd = URLUtils::findFirstOf(spec, "@", authorityStart, fileStart);
        int hostStart;
        if (userInfoEnd != fileStart) {
            userInfo = spec.substring(authorityStart, userInfoEnd);
            hostStart = userInfoEnd + 1;
        } else {
            userInfo = "";
            hostStart = authorityStart;
        }

        /*
         * Extract the host and port. The host may be an IPv6 address with
         * colons like "[::1]", in which case we look for the port delimiter
         * colon after the ']' character.
         */
        int colonSearchFrom = hostStart;
        int ipv6End = URLUtils::findFirstOf(spec, "]", hostStart, fileStart);
        if (ipv6End != fileStart) {
            if (URLUtils::findFirstOf(spec, ":", hostStart, ipv6End) == ipv6End) {
                throw IllegalArgumentException(__FILE__, __LINE__,
                    (std::string("Expected an IPv6 address: ") +
                     spec.substring(hostStart, ipv6End + 1).toString()).c_str());
            }
            colonSearchFrom = ipv6End;
        }
        int hostEnd = URLUtils::findFirstOf(spec, ":", colonSearchFrom, fileStart);
        host = spec.substring(hostStart, hostEnd);
        int portStart = hostEnd + 1;
        if (portStart < fileStart) {
            port = Integer::parseInt(spec.substring(portStart, fileStart).toString());
            if (port < 0) {
                throw IllegalArgumentException(__FILE__, __LINE__, "port < 0: %d", port);
            }
        }
        path = "";
        query = "";
        ref = "";
    } else {
        // Get the authority from the context URL.
        fileStart = start;
        authority = url.getAuthority();
        userInfo = url.getUserInfo();
        host = url.getHost();
        port = url.getPort();
        path = url.getPath();
        query = url.getQuery();
        ref = url.getRef();
    }

    /*
     * Extract the path, query and fragment. Each part has its own leading
     * delimiter character. The query can contain slashes and the fragment
     * can contain slashes and question marks.
     *    / path ? query # fragment
     */
    int pos = fileStart;
    while (pos < limit) {
        int nextPos;
        switch (spec.charAt(pos)) {
        case '#':
            nextPos = limit;
            ref = spec.substring(pos + 1, nextPos);
            break;
        case '?':
            nextPos = URLUtils::findFirstOf(spec, "#", pos, limit);
            query = spec.substring(pos + 1, nextPos);
            ref = "";
            break;
        default:
            nextPos = URLUtils::findFirstOf(spec, "?#", pos, limit);
            path = relativePath(path, spec.substring(pos, nextPos));
            query = "";
            ref = "";
            break;
        }
        pos = nextPos;
    }

    path = URLUtils::authoritySafePath(authority, path);

    setURL(url, url.getProtocol(), host, port, authority, userInfo, path, query, ref);
}