⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uri.cpp

📁 This software aims to create an applet and panel tools to manage a wireless interface card, such as
💻 CPP
📖 第 1 页 / 共 2 页
字号:


bool URI::operator == (const std::string& uri) const
{
	URI parsedURI(uri);
	return equals(parsedURI);
}


bool URI::operator != (const URI& uri) const
{
	return !equals(uri);
}


bool URI::operator != (const std::string& uri) const
{
	URI parsedURI(uri);
	return !equals(parsedURI);
}


bool URI::equals(const URI& uri) const
{
	return _scheme   == uri._scheme
	    && _userInfo == uri._userInfo
	    && _host     == uri._host
	    && getPort() == uri.getPort()
	    && _path     == uri._path
	    && _query    == uri._query
	    && _fragment == uri._fragment;
}

	
void URI::normalize()
{
	removeDotSegments(!isRelative());
}


void URI::removeDotSegments(bool removeLeading)
{
	if (_path.empty()) return;
	
	bool leadingSlash  = *(_path.begin()) == '/';
	bool trailingSlash = *(_path.rbegin()) == '/';
	std::vector<std::string> segments;
	std::vector<std::string> normalizedSegments;
	getPathSegments(segments);
	for (std::vector<std::string>::const_iterator it = segments.begin(); it != segments.end(); ++it)
	{
		if (*it == "..")
		{
			if (!normalizedSegments.empty())
			{
				if (normalizedSegments.back() == "..")
					normalizedSegments.push_back(*it);
				else
					normalizedSegments.pop_back();
			}
			else if (!removeLeading)
			{
				normalizedSegments.push_back(*it);
			}
		}
		else if (*it != ".")
		{
			normalizedSegments.push_back(*it);
		}
	}
	buildPath(normalizedSegments, leadingSlash, trailingSlash);
}


void URI::getPathSegments(std::vector<std::string>& segments)
{
	getPathSegments(_path, segments);
}


void URI::getPathSegments(const std::string& path, std::vector<std::string>& segments)
{
	std::string::const_iterator it  = path.begin();
	std::string::const_iterator end = path.end();
	std::string seg;
	while (it != end)
	{
		if (*it == '/')
		{
			if (!seg.empty())
			{
				segments.push_back(seg);
				seg.clear();
			}
		}
		else seg += *it;
		++it;
	}
	if (!seg.empty())
		segments.push_back(seg);
}


void URI::encode(const std::string& str, const std::string& reserved, std::string& encodedStr)
{
	for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
	{
		char c = *it;
		if (c >= 'a' && c <= 'z' || 
		    c >= 'A' && c <= 'Z' || 
		    c >= '0' && c <= '9' ||
		    c == '-' || c == '_' || 
		    c == '.' || c == '~')
		{
			encodedStr += c;
		}
		else if (c <= 0x20 || c >= 0x7F || ILLEGAL.find(c) != std::string::npos || reserved.find(c) != std::string::npos)
		{
			encodedStr += '%';
			encodedStr += NumberFormatter::formatHex((unsigned) (unsigned char) c, 2);
		}
		else encodedStr += c;
	}
}

	
void URI::decode(const std::string& str, std::string& decodedStr)
{
	std::string::const_iterator it  = str.begin();
	std::string::const_iterator end = str.end();
	while (it != end)
	{
		char c = *it++;
		if (c == '%')
		{
			if (it == end) throw SyntaxException("URI encoding: no hex digit following percent sign", str);
			char hi = *it++;
			if (it == end) throw SyntaxException("URI encoding: two hex digits must follow percent sign", str);
			char lo = *it++;
			if (hi >= '0' && hi <= '9')
				c = hi - '0';
			else if (hi >= 'A' && hi <= 'F')
				c = hi - 'A' + 10;
			else if (hi >= 'a' && hi <= 'f')
				c = hi - 'a' + 10;
			else throw SyntaxException("URI encoding: not a hex digit");
			c *= 16;
			if (lo >= '0' && lo <= '9')
				c += lo - '0';
			else if (lo >= 'A' && lo <= 'F')
				c += lo - 'A' + 10;
			else if (lo >= 'a' && lo <= 'f')
				c += lo - 'a' + 10;
			else throw SyntaxException("URI encoding: not a hex digit");
		}
		decodedStr += c;
	}
}


bool URI::isWellKnownPort() const
{
	return _port == getWellKnownPort();
}


unsigned short URI::getWellKnownPort() const
{
	if (_scheme == "ftp")
		return 21;
	else if (_scheme == "ssh")
		return 22;
	else if (_scheme == "telnet")
		return 23;
	else if (_scheme == "http")
		return 80;
	else if (_scheme == "nntp")
		return 119;
	else if (_scheme == "ldap")
		return 389;
	else if (_scheme == "https")
		return 443;
	else
		return 0;
}


void URI::parse(const std::string& uri)
{
	std::string::const_iterator it  = uri.begin();
	std::string::const_iterator end = uri.end();
	if (it == end) return;
	if (*it != '/' && *it != '.' && *it != '?' && *it != '#')
	{
		std::string scheme;
		while (it != end && *it != ':' && *it != '?' && *it != '#' && *it != '/') scheme += *it++;
		if (it != end && *it == ':')
		{
			++it;
			if (it == end) throw SyntaxException("URI scheme must be followed by authority or path", uri);
			setScheme(scheme);
			if (*it == '/')
			{
				++it;
				if (it != end && *it == '/')
				{
					++it;
					parseAuthority(it, end);
				}
				else --it;
			}
			parsePathEtc(it, end);
		}
		else 
		{
			it = uri.begin();
			parsePathEtc(it, end);
		}
	}
	else parsePathEtc(it, end);
}


void URI::parseAuthority(std::string::const_iterator& it, const std::string::const_iterator& end)
{
	std::string userInfo;
	std::string part;
	while (it != end && *it != '/' && *it != '?' && *it != '#')
	{
		if (*it == '@')
		{
			userInfo = part;
			part.clear();
		}
		else part += *it;
		++it;
	}
	std::string::const_iterator pbeg = part.begin();
	std::string::const_iterator pend = part.end();
	parseHostAndPort(pbeg, pend);
	_userInfo = userInfo;
}


void URI::parseHostAndPort(std::string::const_iterator& it, const std::string::const_iterator& end)
{
	if (it == end) return;
	std::string host;
	if (*it == '[')
	{
		// IPv6 address
		while (it != end && *it != ']') host += *it++;
		if (it == end) throw SyntaxException("unterminated IPv6 address");
		host += *it++;
	}
	else
	{
		while (it != end && *it != ':') host += *it++;
	}
	if (it != end && *it == ':')
	{
		++it;
		std::string port;
		while (it != end) port += *it++;
		if (!port.empty())
		{
			int nport = 0;
			if (NumberParser::tryParse(port, nport) && nport > 0 && nport < 65536)
				_port = (unsigned short) nport;
			else
				throw SyntaxException("bad or invalid port number", port);
		}
		else _port = getWellKnownPort();
	}
	else _port = getWellKnownPort();
	_host = host;
	toLowerInPlace(_host);
}


void URI::parsePath(std::string::const_iterator& it, const std::string::const_iterator& end)
{
	std::string path;
	while (it != end && *it != '?' && *it != '#') path += *it++;
	decode(path, _path);
}


void URI::parsePathEtc(std::string::const_iterator& it, const std::string::const_iterator& end)
{
	if (it == end) return;
	if (*it != '?' && *it != '#')
		parsePath(it, end);
	if (it != end && *it == '?')
	{
		++it;
		parseQuery(it, end);
	}
	if (it != end && *it == '#')
	{
		++it;
		parseFragment(it, end);
	}	
}


void URI::parseQuery(std::string::const_iterator& it, const std::string::const_iterator& end)
{
	std::string query;
	while (it != end && *it != '#') query += *it++;
	decode(query, _query);
}


void URI::parseFragment(std::string::const_iterator& it, const std::string::const_iterator& end)
{
	std::string fragment;
	while (it != end) fragment += *it++;
	decode(fragment, _fragment);
}


void URI::mergePath(const std::string& path)
{
	std::vector<std::string> segments;
	std::vector<std::string> normalizedSegments;
	bool addLeadingSlash = false;
	if (!_path.empty())
	{
		getPathSegments(segments);
		bool endsWithSlash = *(_path.rbegin()) == '/';
		if (!endsWithSlash && !segments.empty())
			segments.pop_back();
		addLeadingSlash = _path[0] == '/';
	}
	getPathSegments(path, segments);
	addLeadingSlash = addLeadingSlash || !path.empty() && path[0] == '/';
	bool hasTrailingSlash = !path.empty() && *(path.rbegin()) == '/';
	bool addTrailingSlash = false;
	for (std::vector<std::string>::const_iterator it = segments.begin(); it != segments.end(); ++it)
	{
		if (*it == "..")
		{
			addTrailingSlash = true;
			if (!normalizedSegments.empty())
				normalizedSegments.pop_back();
		}
		else if (*it != ".")
		{
			addTrailingSlash = false;
			normalizedSegments.push_back(*it);
		}
		else addTrailingSlash = true;
	}
	buildPath(normalizedSegments, addLeadingSlash, hasTrailingSlash || addTrailingSlash);
}


void URI::buildPath(const std::vector<std::string>& segments, bool leadingSlash, bool trailingSlash)
{
	_path.clear();
	bool first = true;
	for (std::vector<std::string>::const_iterator it = segments.begin(); it != segments.end(); ++it)
	{
		if (first)
		{
			first = false;
			if (leadingSlash)
				_path += '/';
			else if (_scheme.empty() && (*it).find(':') != std::string::npos)
				_path.append("./");
		}
		else _path += '/';
		_path.append(*it);
	}
	if (trailingSlash) 
		_path += '/';
}


Foundation_END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -