Skip to content

Instantly share code, notes, and snippets.

@aneury1
Last active April 6, 2023 11:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aneury1/29fd21faa1a3d8e16cccc14c789ec601 to your computer and use it in GitHub Desktop.
Save aneury1/29fd21faa1a3d8e16cccc14c789ec601 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <map>
#include <string>
#include <vector>
std::vector<std::string> split(const std::string& s, char sep) {
std::vector<std::string> ret;
std::string test;
for (char c : s) {
if (c == sep) {
if (!test.empty()) {
ret.push_back(test);
test.clear();
}
} else {
test += c;
}
}
if (!test.empty()) {
ret.push_back(test);
}
return ret;
}
std::vector<std::string> split_url(const std::string& s, const std::string& sep) {
std::vector<std::string> ret;
for (char c : sep) {
std::vector<std::string> temp = split(s, c);
for (const std::string& t : temp) {
ret.push_back(t);
}
}
return ret;
}
bool is_dynamic_entry(const std::string& s) {
return s.find(":str") != std::string::npos || s.find(":int") != std::string::npos;
}
bool exists_this_route(const std::map<std::string, std::string>& routes, const std::string& url) {
auto test = routes.find(url);
if (test == routes.end()) {
auto org = split(url, '/');
for (const auto& it : routes) {
auto spl = split(it.first, '/');
if (spl.size() != org.size()) {
continue;
}
bool match = true;
for (size_t i = 0; i < spl.size(); ++i) {
if (!is_dynamic_entry(spl[i])) {
if (org[i] != spl[i]) {
match = false;
break;
}
} else {
bool is_num = true;
for (char c : org[i]) {
if (!isdigit(c)) {
is_num = false;
break;
}
}
if (spl[i].find(":int") != std::string::npos && !is_num) {
match = false;
break;
}
}
}
if (match) {
return true;
}
}
return false;
}
return true;
}
int main() {
std::map<std::string, std::string> routes = {
{"/", "home1"},
{"/{id}", "home2"},
{"/{id:str}/profile", "home3"},
{"/{id:int}/profile", "home4"},
};
std::cout << exists_this_route(routes, "/") << "\n";
std::cout << exists_this_route(routes, "/134/profilej") << "\n";
std::cout << exists_this_route(routes, "/dfd1/profile") << "\n";
return 0;
}
///second version
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;
std::vector<std::string> split(std::string s, char sep)
{
std::vector<std::string> ret;
std::string test;
for (auto it : s) {
if (it == sep) {
if (test.length() > 0)
{
ret.emplace_back(test);
test = "";
}
}
else
test += it;
}
if (test.length() > 0)
ret.emplace_back(test);
return ret;
}
std::vector<std::string> split_url(std::string s, std::string sep)
{
std::vector<std::string> ret;
for (auto it : sep)
{
std::vector<std::string> temp = split(s, it);
for (auto t : temp)
{
ret.emplace_back(t);
}
}
return ret;
}
bool is_dynamic_entry(std::string s)
{
if (s.find(":str") != std::string::npos || s.find(":int") != std::string::npos)
return true;
return false;
}
bool exist_this_route(std::map<string, std::string> routes, std::string url)
{
auto test = routes[url];
if (!test.empty())
{
return true;
}
std::vector<std::string> url_parts = split_url(url, "/?&");
for (auto it : routes)
{
std::vector<std::string> route_parts = split_url(it.first, "/");
if (url_parts.size() != route_parts.size())
continue;
bool match_found = true;
for (int i = 0; i < route_parts.size(); i++)
{
if (is_dynamic_entry(route_parts[i]))
{
if (route_parts[i].find(":int") != std::string::npos)
{
bool is_number = std::all_of(url_parts[i].begin(), url_parts[i].end(), ::isdigit);
if (!is_number)
{
match_found = false;
break;
}
}
continue;
}
if (route_parts[i] != url_parts[i])
{
match_found = false;
break;
}
}
if (match_found)
{
return true;
}
}
return false;
}
int main()
{
std::map<std::string, std::string> routes;
routes["/"] = "home1";
routes["/{id}"] = "home2";
routes["/{id:str}/profile"] = "home3";
routes["/{id:int}/profile"] = "home4";
std::cout << exist_this_route(routes, "/") << std::endl;
std::cout << exist_this_route(routes, "/134/profilej") << std::endl;
std::cout << exist_this_route(routes, "/dfd1/profile") << std::endl;
std::cout << exist_this_route(routes, "/123/profile?query=string") << std::endl;
std::cout << exist_this_route(routes, "/123/profile?query=string&another=parameter") << std::endl;
return 0;
}
///third version
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
using namespace std;
vector<string> split(const string& s, char sep) {
vector<string> ret;
stringstream ss(s);
string item;
while (getline(ss, item, sep)) {
if (!item.empty()) {
ret.push_back(item);
}
}
return ret;
}
vector<string> split_url(const string& url, const string& separators = "/?&") {
vector<string> ret;
size_t pos = 0;
while (pos < url.length()) {
size_t next_pos = url.find_first_of(separators, pos);
if (next_pos == string::npos) {
next_pos = url.length();
}
if (next_pos > pos) {
ret.push_back(url.substr(pos, next_pos - pos));
}
pos = next_pos + 1;
}
return ret;
}
bool is_dynamic_entry(const string& s) {
return (s.find(":str") != string::npos || s.find(":int") != string::npos);
}
bool exist_this_route(const map<string, string>& routes, const string& url) {
vector<string> url_parts = split_url(url);
for (auto it : routes) {
vector<string> route_parts = split_url(it.first);
if (url_parts.size() != route_parts.size()) {
continue;
}
bool matched = true;
map<string, string> query_params;
for (size_t i = 0; i < url_parts.size(); i++) {
if (route_parts[i].empty()) {
continue;
}
if (is_dynamic_entry(route_parts[i])) {
if (route_parts[i].find(":int") != string::npos) {
if (any_of(url_parts[i].begin(), url_parts[i].end(), [](char c) { return !isdigit(c); })) {
matched = false;
break;
}
}
query_params[route_parts[i].substr(1)] = url_parts[i];
} else if (url_parts[i] != route_parts[i]) {
matched = false;
break;
}
}
if (matched) {
it.second = url;
for (auto p : query_params) {
it.second += (it.second.find("?") == string::npos) ? "?" : "&";
it.second += p.first + "=" + p.second;
}
return true;
}
}
return false;
}
int main() {
map<string, string> routes;
routes["/"] = "home1";
routes["/{id}"] = "home2";
routes["/{id:str}/profile"] = "home3";
routes["/{id:int}/profile"] = "home4";
string url1 = "http://www.example.com";
string url2 = "http://www.example.com/123";
string url3 = "http://www.example.com/abc/profile";
string url4 = "http://www.example.com/456/profile?foo=bar&baz=qux";
string url5 = "http://www.example.com/789/profile?foo=bar";
vector<string> urls = {url1, url2, url3, url4, url5};
for (const string& url : urls) {
if (exist_this_route(routes, url)) {
cout << url << " => " << routes[url] << endl;
} else {
cout <<
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment