uri.h

Go to the documentation of this file.
00001 /* URI-related treasures.
00002  *
00003  * PegSoft miscellaneous library (c) 2004 PegSoft
00004  * Contact us at pegsoft@pegsoft.net
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License version 2 as
00008  * published by the Free Software Foundation.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this software (the COPYING file); if not, write to the
00017  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
00018  * USA.
00019  *
00020  */
00021 
00027 #ifndef MISC_URI_H
00028 #define MISC_URI_H
00029 
00030 /*************************************************************************/
00031 
00032 #include <map>
00033 #include <string>
00034 
00035 /*************************************************************************/
00036 
00037 namespace misc
00038 {
00039 
00040 /*************************************************************************/
00041 
00043 
00046 class URI
00047 {
00048     public:
00050         typedef std::map<std::string, std::string> parameters_t;
00051         
00053         URI() : m_uri(), m_scheme(), m_contents(), m_authority(), m_path(), 
00054                 m_query(), m_hostname(), m_port(0), m_username(), m_password(), 
00055                 m_parameters() { }
00057         URI(std::string const &uri) : m_uri(), m_scheme(), m_contents(), 
00058                 m_authority(), m_path(), m_query(), m_hostname(), m_port(0),
00059                 m_username(),  m_password(), m_parameters() { assign(uri); }
00061         URI(char const *uri) : m_uri(), m_scheme(), m_contents(), 
00062                 m_authority(), m_path(), m_query(), m_hostname(), m_port(0),
00063                 m_username(),  m_password(), m_parameters() { assign(uri); }
00065         URI(URI const &uri) : m_uri(uri.m_uri), m_scheme(uri.m_scheme), 
00066                 m_contents(uri.m_contents), m_authority(uri.m_authority),
00067                 m_path(uri.m_path), m_query(uri.m_query), 
00068                 m_hostname(uri.m_hostname), m_port(uri.m_port),
00069                 m_username(uri.m_username), m_password(uri.m_password),
00070                 m_parameters(uri.m_parameters) { }
00072         URI &operator=(URI const &right);
00074         bool operator==(URI const &right)
00075                 { return (m_uri == right.m_uri); }
00077         bool operator!=(URI const &right)
00078                 { return !(operator==(right)); }
00079         
00081 
00087         bool assign(std::string const &uri) 
00088                 { clear(); return parse_uri(uri.begin(), uri.end()); }
00090         bool assign(char const *uri) 
00091                 { clear(); return parse_uri(uri, uri + strlen(uri)); }
00092         
00094         void clear();
00095         
00097         std::string const &uri() const { return m_uri; }
00098         
00100         std::string const &scheme() const { return m_scheme; }
00102         std::string const &contents() const { return m_contents; }
00103         
00105         std::string const &authority() const { return m_authority; }
00107         std::string const &path() const { return m_path; }
00109         std::string const &query() const { return m_query; }
00110         
00112         std::string const &hostname() const { return m_hostname; }
00114         uint16_t port() const { return m_port; }
00116         std::string const &username() const { return m_username; }
00118         std::string const &password() const { return m_password; }
00119         
00121         parameters_t const &parameters() const { return m_parameters; }
00122     private:
00123         std::string m_uri;
00124         
00125         std::string m_scheme;
00126         std::string m_contents;
00127         
00128         std::string m_authority;
00129         std::string m_path;
00130         std::string m_query;
00131             
00132         std::string m_hostname;
00133         uint16_t m_port;
00134         std::string m_username;
00135         std::string m_password;
00136             
00137         parameters_t m_parameters;
00138             
00139         template <typename T> bool parse_uri(T beg, T end)
00140         {
00141             T send = end;
00142             
00143             for (T it = beg; it != end; ++it)
00144             {
00145                 if (*it == ':')
00146                 {
00147                     send = it;
00148                     
00149                     if (++it == end)
00150                         return false;
00151                     
00152                     break;
00153                 }
00154             }
00155             
00156             if (send == end)
00157                 return false;
00158             
00159             if (!parse_contents(send + 1, end))
00160                 return false;
00161             
00162             m_scheme.assign(beg, send);
00163             m_contents.assign(send + 1, end);
00164             m_uri.assign(beg, end);
00165             
00166             return true;
00167         }
00168         
00169         template <typename T> bool parse_contents(T beg, T end)
00170         {   
00171             if (*beg == '/' && (beg + 1) != end && *(beg + 1) == '/')
00172                 beg += 2;
00173             else
00174                 return true;
00175             
00176             T aend = end, pend = end;
00177             
00178             for (T it = beg; it != end; ++it)
00179             {   
00180                 if (*it == '/')
00181                 {
00182                     if (aend != end)
00183                         return false;
00184                     
00185                     aend = it;
00186                 }
00187                 else if (*it == '?')
00188                 {
00189                     if (aend == end)
00190                         return false;
00191                     
00192                     if (it + 1 == end)
00193                         pend = end = it;
00194                     else
00195                         pend = it;
00196                     break;
00197                 }
00198             }
00199             
00200             if (beg != aend && !parse_authority(beg, aend))
00201                 return false;
00202             
00203             if (pend != end && (pend + 1) != end && 
00204                     !parse_query(pend + 1, end))
00205                 return false;
00206             
00207             if (beg != aend)
00208                 m_authority.assign(beg, aend);
00209             if (aend != end)
00210                 m_path.assign(aend, pend);
00211             if (pend != end)
00212                 m_query.assign(pend + 1, end);
00213             return true;
00214         }
00215         
00216         template <typename T> bool parse_authority(T beg, T end)
00217         {   
00218             T cend = beg;
00219             
00220             for (T it = beg; it != end; ++it)
00221             {   
00222                 if (*it == '@')
00223                 {
00224                     cend = it;
00225                     
00226                     if (++it == end)
00227                         return false;
00228                     
00229                     break;
00230                 }
00231             }
00232             
00233             if (cend != beg) 
00234                 return parse_credentials(beg, cend, end);
00235             else
00236                 return parse_host(cend, end);
00237         }
00238         
00239         template <typename T> bool parse_credentials(T beg, T end,
00240                 T hend)
00241         {   
00242             T uend = end;
00243             
00244             for (T it = beg; it != end; ++it)
00245             {   
00246                 if (*it == ':')
00247                 {
00248                     if (it == beg)
00249                         return false;
00250                     
00251                     if (it + 1 == end)
00252                         uend = end = it;
00253                     else
00254                         uend = it;
00255                     break;
00256                 }
00257             }
00258             
00259             if (!parse_host(end + 1, hend))
00260                 return false;
00261             
00262             m_username.assign(beg, uend);
00263             if (uend != end)
00264                 m_password.assign(uend + 1, end);
00265             
00266             return true;
00267         }
00268         
00269         template <typename T> bool parse_host(T beg, T end)
00270         {   
00271             T nend = end;
00272             
00273             for (T it = beg; it != end; ++it)
00274             {   
00275                 if (*it == ':')
00276                 {
00277                     if (it == beg)
00278                         return false;
00279                     
00280                     if (it + 1 == end)
00281                         nend = end = it;
00282                     else
00283                         nend = it;
00284                     break;
00285                 }
00286             }
00287             
00288             m_hostname.assign(beg, nend);
00289             if (nend != end)
00290             {
00291                 std::string port(nend + 1, end);
00292                 m_port = atoi(port.c_str());
00293             }
00294             
00295             return true;
00296         }
00297         
00298         template <typename T> bool parse_query(T beg, T end)
00299         {   
00300             while (beg != end && *beg == '&')               
00301                 ++beg;
00302             
00303             T pbeg = beg;
00304             
00305             for (T it = beg; it != end; ++it)
00306             {   
00307                 if (*it == '&')
00308                 {
00309                     if (!parse_parameter(pbeg, it))
00310                         return false;
00311                     
00312                     while (it != end && *it == '&')
00313                         ++it;
00314                     
00315                     pbeg = it;
00316                     
00317                     if (it == end)
00318                         break;
00319                 }
00320             }
00321             
00322             if (end - pbeg >= 1 && !parse_parameter(pbeg, end))
00323                 return false;
00324             
00325             return true;
00326         }
00327         
00328         template <typename T> bool parse_parameter(T beg, T end)
00329         {   
00330             T nend = end;
00331             
00332             for (T it = beg; it != end; ++it)
00333             {   
00334                 if (*it == '=')
00335                 {
00336                     if (it == beg)
00337                         return false;
00338                     
00339                     if (it + 1 == end)
00340                         nend = end = it;
00341                     else
00342                         nend = it;
00343                     break;
00344                 }
00345             }
00346             
00347             if (nend != end)
00348                 m_parameters[std::string(beg, nend)] = 
00349                         std::string(nend + 1, end);
00350             else
00351                 m_parameters[std::string(beg, nend)] = "";
00352             
00353             return true;
00354         }
00355 };
00356 
00357 /*************************************************************************/
00358 
00359 } /* namespace misc */
00360 
00361 /*************************************************************************/
00362 
00363 #endif /* MISC_URI_H */

Generated on Fri Apr 18 22:03:27 2008 for Epona API by  doxygen 1.5.3