int URI::SetHttpURL()

in src/brpc/uri.cpp [158:245]


int URI::SetHttpURL(const char* url) {
    Clear();
    
    const char* p = url;
    // skip heading blanks
    if (*p == ' ') {
        for (++p; *p == ' '; ++p) {}
    }
    const char* start = p;
    // Find end of host, locate scheme and user_info during the searching
    bool need_scheme = true;
    bool need_user_info = true;
    for (; true; ++p) {
        const char action = g_url_parsing_fast_action_map[(int)*p];
        if (action == URI_PARSE_CONTINUE) {
            continue;
        }
        if (action == URI_PARSE_BREAK) {
            break;
        }
        if (!is_valid_char(*p)) {
            _st.set_error(EINVAL, "invalid character in url");
            return -1;
        } else if (*p == ':') {
            if (p[1] == '/' && p[2] == '/' && need_scheme) {
                need_scheme = false;
                _scheme.assign(start, p - start);
                p += 2;
                start = p + 1;
            }
        } else if (*p == '@') {
            if (need_user_info) {
                need_user_info = false;
                _user_info.assign(start, p - start);
                start = p + 1;
            }
        } else if (*p == ' ') {
            if (!is_all_spaces(p + 1)) {
                _st.set_error(EINVAL, "Invalid space in url");
                return -1;
            }
            break;
        }
    }
    const char* host_end = SplitHostAndPort(start, p, &_port);
    _host.assign(start, host_end - start);
    if (*p == '/') {
        start = p; //slash pointed by p is counted into _path
        ++p;
        for (; *p && *p != '?' && *p != '#'; ++p) {
            if (*p == ' ') {
                if (!is_all_spaces(p + 1)) {
                    _st.set_error(EINVAL, "Invalid space in path");
                    return -1;
                }
                break;
            }
        }
        _path.assign(start, p - start);
    }
    if (*p == '?') {
        start = ++p;
        for (; *p && *p != '#'; ++p) {
            if (*p == ' ') {
                if (!is_all_spaces(p + 1)) {
                    _st.set_error(EINVAL, "Invalid space in query");
                    return -1;
                }
                break;
            }
        }
        _query.assign(start, p - start);
    }
    if (*p == '#') {
        start = ++p;
        for (; *p; ++p) {
            if (*p == ' ') {
                if (!is_all_spaces(p + 1)) {
                    _st.set_error(EINVAL, "Invalid space in fragment");
                    return -1;
                }
                break;
            }
        }
        _fragment.assign(start, p - start);
    }
    return 0;
}