Last active
April 6, 2023 11:58
-
-
Save aneury1/29fd21faa1a3d8e16cccc14c789ec601 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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