2 #include <msp/strings/format.h>
3 #include <msp/strings/regex.h>
4 #include <msp/strings/utils.h>
11 const char *reserved[]=
15 " !#$%&'()*+,/:;=?@[]",
18 bool is_reserved(char c, unsigned level)
20 for(const char *r=reserved[level]; *r; ++r)
31 string urlencode(const string &str, EncodeLevel level)
34 for(string::const_iterator i=str.begin(); i!=str.end(); ++i)
36 if(is_reserved(*i, level))
37 result += format("%%%02X", *i);
44 string urlencode_plus(const string &str, EncodeLevel level)
47 for(string::const_iterator i=str.begin(); i!=str.end(); ++i)
51 else if(is_reserved(*i, level))
52 result += format("%%%02X", *i);
59 string urldecode(const string &str)
62 for(unsigned i=0; i<str.size(); ++i)
68 throw invalid_argument("urldecode");
69 result += lexical_cast<unsigned char>(str.substr(i+1, 2), "x");
80 Url parse_url(const string &str)
82 static Regex r_url("^(([a-z]+)://)?([a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*(:[0-9]+)?)?(/[^?#]*)?(\\?([^#]+))?(#(.*))?$");
83 if(RegMatch m = r_url.match(str))
86 url.scheme = m[2].str;
88 url.path = urldecode(m[6].str);
90 url.fragment = m[10].str;
94 throw invalid_argument("parse_url");
97 string build_url(const Url &url)
99 if(!url.path.empty() && url.path[0]!='/')
100 throw invalid_argument("build_url");
103 if(!url.scheme.empty())
104 str += url.scheme+"://";
106 str += urlencode(url.path);
107 if(!url.query.empty())
112 if(!url.fragment.empty())
120 Query parse_query(const std::string &str)
122 vector<string> parts = split(str, '&');
124 for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
126 string::size_type equals = i->find('=');
127 string &value = query[urldecode(i->substr(0, equals))];
128 if(equals!=string::npos)
129 value = urldecode(i->substr(equals+1));
134 string build_query(const Query &query)
137 for(Query::const_iterator i=query.begin(); i!=query.end(); ++i)
141 str += urlencode_plus(i->first);
143 str += urlencode_plus(i->second);