Moved URL class into fr namespace

It should not have been in the global namespace, as it's a part of the library.
This commit is contained in:
Fred Nicolson 2017-05-24 09:54:19 +01:00
parent c110fb6c81
commit 431f646bae
2 changed files with 215 additions and 208 deletions

View File

@ -8,116 +8,118 @@
#include <unordered_map>
//Note, a URL looks like this: scheme:[//host[:port]][/path][?query][#fragment]
class URL
namespace fr
{
public:
enum Scheme
class URL
{
HTTP = 0,
HTTPS = 1,
FTP = 2,
MAILTO = 3,
IRC = 4,
SFTP = 5,
Unknown = 6,
public:
enum Scheme
{
HTTP = 0,
HTTPS = 1,
FTP = 2,
MAILTO = 3,
IRC = 4,
SFTP = 5,
Unknown = 6,
};
/*!
* Constructors
*/
URL() = default;
URL(const std::string &url);
/*!
* Parses a given URL, extracting its various components
*
* @param url The URL to parse
*/
void parse(std::string url);
/*!
* Get the URL scheme
*/
inline Scheme get_scheme()
{
return scheme;
}
/*
* Get the URL host
*/
inline const std::string &get_host()
{
return host;
}
/*
* Get the URL port
*/
inline const std::string &get_port()
{
return port;
}
/*
* Get the URL path
*/
inline const std::string &get_path()
{
return path;
}
/*
* Get the URL query
*/
inline const std::string &get_query()
{
return query;
}
/*
* Get the URL fragment
*/
inline const std::string &get_fragment()
{
return fragment;
}
/*!
* Converts a string to a scheme enum.
*
* @param scheme The string scheme to convert
* @return The associated scheme enum value. Scheme::Unknown on failure.
*/
static Scheme string_to_scheme(const std::string &scheme);
/*!
* Converts a scheme enum value to a string
*
* @param scheme The scheme value to convert
* @return The string version
*/
static const std::string &scheme_to_string(Scheme scheme);
private:
/*!
* Converts a string to lower case
*
* @param str The string to convert
* @return The converted string
*/
static std::string to_lower(const std::string &str);
//State
Scheme scheme;
std::string host;
std::string port;
std::string path;
std::string query;
std::string fragment;
static std::unordered_map<std::string, URL::Scheme> scheme_string_map;
};
/*!
* Constructors
*/
URL() = default;
URL(const std::string &url);
/*!
* Parses a given URL, extracting its various components
*
* @param url The URL to parse
*/
void parse(std::string url);
/*!
* Get the URL scheme
*/
inline Scheme get_scheme()
{
return scheme;
}
/*
* Get the URL host
*/
inline const std::string &get_host()
{
return host;
}
/*
* Get the URL port
*/
inline const std::string &get_port()
{
return port;
}
/*
* Get the URL path
*/
inline const std::string &get_path()
{
return path;
}
/*
* Get the URL query
*/
inline const std::string &get_query()
{
return query;
}
/*
* Get the URL fragment
*/
inline const std::string &get_fragment()
{
return fragment;
}
/*!
* Converts a string to a scheme enum.
*
* @param scheme The string scheme to convert
* @return The associated scheme enum value. Scheme::Unknown on failure.
*/
static Scheme string_to_scheme(const std::string &scheme);
/*!
* Converts a scheme enum value to a string
*
* @param scheme The scheme value to convert
* @return The string version
*/
static const std::string &scheme_to_string(Scheme scheme);
private:
/*!
* Converts a string to lower case
*
* @param str The string to convert
* @return The converted string
*/
static std::string to_lower(const std::string &str);
//State
Scheme scheme;
std::string host;
std::string port;
std::string path;
std::string query;
std::string fragment;
static std::unordered_map<std::string, URL::Scheme> scheme_string_map;
};
}
#endif //FRNETLIB_URLPARSER_H

View File

@ -7,121 +7,126 @@
#include <iostream>
#include "frnetlib/URL.h"
std::unordered_map<std::string, URL::Scheme> URL::scheme_string_map = {
{"http", URL::HTTP},
{"https", URL::HTTPS},
{"sftp", URL::FTP},
{"mailto", URL::MAILTO},
{"irc", URL::IRC},
{"sftp", URL::SFTP},
{"unknown", URL::Unknown}
};
URL::URL(const std::string &url)
namespace fr
{
parse(url);
}
std::unordered_map<std::string, URL::Scheme> URL::scheme_string_map = {
{"http", URL::HTTP},
{"https", URL::HTTPS},
{"sftp", URL::FTP},
{"mailto", URL::MAILTO},
{"irc", URL::IRC},
{"sftp", URL::SFTP},
{"unknown", URL::Unknown}
};
void URL::parse(std::string url)
{
size_t parse_offset = 0;
size_t pos = 0;
//Check to see if a scheme exists
pos = url.find("://");
if(pos != std::string::npos)
URL::URL(const std::string &url)
{
auto scheme_pos = scheme_string_map.find(to_lower(url.substr(0, pos)));
scheme = (scheme_pos == scheme_string_map.end()) ? URL::Unknown : scheme_pos->second;
parse_offset = pos + 3;
parse(url);
}
//Check to see if there's a port
pos = url.find(":", parse_offset);
if(pos != std::string::npos)
{
//Store host
host = url.substr(parse_offset, pos - parse_offset);
parse_offset += host.size();
//Find end of port
size_t port_end = url.find("/", parse_offset);
port_end = (port_end == std::string::npos) ? url.size() : port_end;
port = url.substr(pos + 1, port_end - pos - 1);
parse_offset = port_end + 1;
}
else
void URL::parse(std::string url)
{
//Store host
pos = url.find("/", parse_offset);
pos = (pos != std::string::npos) ? pos : url.find("?", parse_offset);
pos = (pos != std::string::npos) ? pos : url.find("#", parse_offset);
pos = (pos != std::string::npos) ? pos : url.size();
host = url.substr(parse_offset, pos - parse_offset);
parse_offset = pos + 1;
}
size_t parse_offset = 0;
size_t pos = 0;
//Exit if done
if(parse_offset >= url.size())
return;
//Check to see if a scheme exists
pos = url.find("://");
if(pos != std::string::npos)
{
auto scheme_pos = scheme_string_map.find(to_lower(url.substr(0, pos)));
scheme = (scheme_pos == scheme_string_map.end()) ? URL::Unknown : scheme_pos->second;
parse_offset = pos + 3;
}
//Extract the path
pos = url.find("?", parse_offset);
if(pos != std::string::npos)
{
path = url.substr(parse_offset, pos - parse_offset);
parse_offset = pos + 1;
}
else
{
pos = url.find("#", parse_offset);
pos = (pos != std::string::npos) ? pos : url.find("?", parse_offset);
pos = (pos != std::string::npos) ? pos : url.size();
path = url.substr(parse_offset, pos - parse_offset);
parse_offset = pos + 1;
}
//Check to see if there's a port
pos = url.find(":", parse_offset);
if(pos != std::string::npos)
{
//Store host
host = url.substr(parse_offset, pos - parse_offset);
parse_offset += host.size();
//Extract the query
pos = url.find("#", parse_offset - 1);
if(pos != std::string::npos)
{
if(pos + 1 != parse_offset)
query = url.substr(parse_offset, pos - parse_offset);
fragment = url.substr(pos + 1, url.size() - pos - 1);
}
else
{
//Find end of port
size_t port_end = url.find("/", parse_offset);
port_end = (port_end == std::string::npos) ? url.size() : port_end;
port = url.substr(pos + 1, port_end - pos - 1);
parse_offset = port_end + 1;
}
else
{
//Store host
pos = url.find("/", parse_offset);
pos = (pos != std::string::npos) ? pos : url.find("?", parse_offset);
pos = (pos != std::string::npos) ? pos : url.find("#", parse_offset);
pos = (pos != std::string::npos) ? pos : url.size();
host = url.substr(parse_offset, pos - parse_offset);
parse_offset = pos + 1;
}
//Exit if done
if(parse_offset >= url.size())
return;
query = url.substr(parse_offset, url.size() - parse_offset);
//Extract the path
pos = url.find("?", parse_offset);
if(pos != std::string::npos)
{
path = url.substr(parse_offset, pos - parse_offset);
parse_offset = pos + 1;
}
else
{
pos = url.find("#", parse_offset);
pos = (pos != std::string::npos) ? pos : url.find("?", parse_offset);
pos = (pos != std::string::npos) ? pos : url.size();
path = url.substr(parse_offset, pos - parse_offset);
parse_offset = pos + 1;
}
//Extract the query
pos = url.find("#", parse_offset - 1);
if(pos != std::string::npos)
{
if(pos + 1 != parse_offset)
query = url.substr(parse_offset, pos - parse_offset);
fragment = url.substr(pos + 1, url.size() - pos - 1);
}
else
{
if(parse_offset >= url.size())
return;
query = url.substr(parse_offset, url.size() - parse_offset);
}
return;
}
return;
}
URL::Scheme URL::string_to_scheme(const std::string &scheme)
{
auto iter = scheme_string_map.find(to_lower(scheme));
if(iter == scheme_string_map.end())
return URL::Unknown;
return iter->second;
}
URL::Scheme URL::string_to_scheme(const std::string &scheme)
{
auto iter = scheme_string_map.find(to_lower(scheme));
if(iter == scheme_string_map.end())
return URL::Unknown;
return iter->second;
}
std::string URL::to_lower(const std::string &str)
{
std::string out = str;
std::transform(out.begin(), out.end(), out.begin(), ::tolower);
return out;
}
std::string URL::to_lower(const std::string &str)
{
std::string out = str;
std::transform(out.begin(), out.end(), out.begin(), ::tolower);
return out;
}
const std::string &URL::scheme_to_string(URL::Scheme scheme)
{
auto iter = std::find_if(scheme_string_map.begin(), scheme_string_map.end(), [&](const auto &i)
{
return i.second == scheme;
});
const std::string &URL::scheme_to_string(URL::Scheme scheme)
{
auto iter = std::find_if(scheme_string_map.begin(), scheme_string_map.end(), [&](const auto &i){
return i.second == scheme;
});
if(iter == scheme_string_map.end())
throw std::logic_error("Unknown URL::Scheme value " + std::to_string(scheme));
return iter->first;
}
if(iter == scheme_string_map.end())
throw std::logic_error("Unknown URL::Scheme value " + std::to_string(scheme));
return iter->first;
}
}