nanouri.h Source File

- Main Page
- Files

# nanouri.h

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 2009, tokuhiro matsuno
    00003  * All rights reserved.
    00004  *
    00005  * Redistribution and use in source and binary forms, with or without
    00006  * modification, are permitted provided that the following conditions are met:
    00007  *
    00008  * * Redistributions of source code must retain the above copyright notice,
    00009  *   this list of conditions and the following disclaimer.
    00010  * * Redistributions in binary form must reproduce the above copyright notice,
    00011  *   this list of conditions and the following disclaimer in the documentation
    00012  *   and/or other materials provided with the distribution.
    00013  * * Neither the name of the <ORGANIZATION> nor the names of its contributors
    00014  *   may be used to endorse or promote products derived from this software
    00015  *   without specific prior written permission.
    00016  *
    00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    00027  * POSSIBILITY OF SUCH DAMAGE.
    00028  */
    00029 #ifndef PICOURI_H
    00030 #define PICOURI_H
    00031
    00032 #include <stddef.h>
    00033 #include <assert.h>
    00034
    00035 #ifdef __GNUC__
    00036 #define NANOURI_DECLARE static __attribute__((__used__))
    00037 #else
    00038 #define NANOURI_DECLARE static
    00039 #endif
    00040
    00041 static char nu_uric_map[256] =
    00042 /*  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
    00043 {
    00044     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    00045     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    00046     1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1,
    00047     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
    00048     1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    00049     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
    00050     1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    00051     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1,
    00052     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    00053     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    00054     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    00055     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    00056     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    00057     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    00058     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    00059     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
    00060 };
    00061
    00062 #ifdef __cplusplus
    00063 # define NU_INLINE inline
    00064 #else
    00065 # define NU_INLINE __inline__
    00066 #endif
    00067
    00068 NANOURI_DECLARE NU_INLINE int nu_isuric(unsigned char c) {
    00069     return nu_uric_map[c];
    00070 }
    00071
    00072 /* private method */
    00073 NANOURI_DECLARE NU_INLINE char nu_hex_char(unsigned int n) {
    00074     assert(n < 16);
    00075
    00076     if (n < 10) {
    00077         return '0'+n;
    00078     } else {
    00079         return 'a'+n-10;
    00080     }
    00081 }
    00082
    00083
    00084 #ifdef __cplusplus
    00085
    00086 #include <string>
    00087
    00088 NANOURI_DECLARE std::string nu_escape_uri(const std::string &src) {
    00089     std::string dst;
    00090     dst.reserve(src.size()*3+1);
    00091     for (unsigned int i=0; i<src.size(); i++) {
    00092         if (nu_isuric((unsigned char)src[i])) {
    00093             dst += '%';
    00094             dst += nu_hex_char((src[i]>>4)&0x0f);
    00095             dst += nu_hex_char(src[i]&0x0f);
    00096         } else {
    00097             dst += src[i];
    00098         }
    00099     }
    00100     return dst;
    00101 }
    00102
    00103 static int nu_unhex( unsigned char c ) {
    00104     return   ( c >= '0' && c <= '9' ) ? c - '0'
    00105            : ( c >= 'A' && c <= 'F' ) ? c - 'A' + 10
    00106                                       : c - 'a' + 10;
    00107 }
    00108
    00109 NANOURI_DECLARE std::string nu_unescape_uri(const std::string &src) {
    00110     std::string dst;
    00111     dst.reserve(src.size()*3+1);
    00112     for (unsigned int i=0; i<src.size(); i++) {
    00113         if (src[i] == '%') {
    00114             unsigned char c;
    00115             if (src[++i] != '\0') {
    00116                 c = nu_unhex(src[i]) << 4;
    00117             }
    00118             if (src[++i] != '\0') {
    00119                 c += nu_unhex(src[i]);
    00120             }
    00121             dst += c;
    00122         } else {
    00123             dst += src[i];
    00124         }
    00125     }
    00126     return dst;
    00127 }
    00128
    00129 #endif
    00130
    00131 #define CHECK_EOF() \
    00132   if (buf == buf_end) { \
    00133     return -2;      \
    00134   }
    00135
    00136 #define EXPECT(ch)    \
    00137   CHECK_EOF();        \
    00138   if (*buf++ != ch) { \
    00139     return -1;        \
    00140   }
    00141
    00142 NANOURI_DECLARE int nu_parse_uri(const char* _buf, size_t len, const char** scheme, size_t *scheme_len, const char **host, size_t *host_len, int *port, const char **path_query, int*path_query_len) {
    00143     const char * buf = _buf, * buf_end = buf + len;
    00144
    00145     *scheme = buf;
    00146     for (;;++buf) {
    00147         CHECK_EOF();
    00148         if (':' == *buf) {
    00149             break;
    00150         }
    00151     }
    00152     *scheme_len = buf - *scheme;
    00153
    00154     EXPECT(':'); EXPECT('/'); EXPECT('/');
    00155
    00156     *host = buf;
    00157     *port = 0;
    00158     *host_len = 0;
    00159     *path_query_len = 0;
    00160     for (;;++buf) {
    00161         if (buf == buf_end) {
    00162             *host_len = buf - *host;
    00163             return 0;
    00164         }
    00165         if (':' == *buf) { /* with port */
    00166             *host_len = buf - *host;
    00167             buf++;
    00168
    00169             *port = 0;
    00170             for (;'0' <= *buf && *buf <= '9';buf++) {
    00171                 if (buf == buf_end) {
    00172                     return 0;
    00173                 }
    00174                 *port = *port * 10 + (*buf - '0');
    00175             }
    00176             if (buf == buf_end) {
    00177                 return 0;
    00178             }
    00179             break;
    00180         }
    00181         if ('/' == *buf) { /* no port */
    00182             *host_len = buf - *host;
    00183             break;
    00184         }
    00185     }
    00186
    00187     *path_query = buf;
    00188     *path_query_len = buf_end - buf;
    00189     return 0;
    00190 }
    00191
    00192 #ifdef __cplusplus
    00193 #include <string>
    00194 #include <cstdlib>
    00195
    00196 namespace nanouri {
    00197     class Uri {
    00198     private:
    00199         std::string uri_;
    00200         std::string host_;
    00201         std::string scheme_;
    00202         int port_;
    00203         std::string path_query_;
    00204     public:
    00205         Uri() { }
    00206         ~Uri() { }
    00207
    00208         /**
    00209          * @return true if valid url
    00210          */
    00211         inline bool parse(const std::string &src) {
    00212             return this->parse(src.c_str(), src.size());
    00213         }
    00214         bool parse(const char*src, size_t src_len) {
    00215             const char * scheme;
    00216             size_t scheme_len;
    00217             const char * host;
    00218             size_t host_len;
    00219             const char *path_query;
    00220             int path_query_len;
    00221             int ret = nu_parse_uri(src, src_len, &scheme, &scheme_len, &host, &host_len, &port_, &path_query, &path_query_len);
    00222             if (ret != 0) {
    00223                 return false; // parse error
    00224             }
    00225             uri_.assign(src, src_len);
    00226             host_.assign(host, host_len);
    00227             path_query_.assign(path_query, path_query_len);
    00228             scheme_.assign(scheme, scheme_len);
    00229             return true;
    00230         }
    00231         inline std::string host() { return host_; }
    00232         inline std::string scheme() { return scheme_; }
    00233         inline int port() { return port_; }
    00234         inline std::string path_query() { return path_query_; }
    00235         inline std::string as_string() { return uri_; }
    00236         operator bool() const {
    00237             return !this->uri_.empty();
    00238         }
    00239     };
    00240 };
    00241
    00242 #endif
    00243
    00244
    00245 #undef NANOURI_DECLARE
    00246 #undef NU_INLINE
    00247 #undef EXPECT
    00248 #undef CHECK_EOF
    00249 #endif /* PICOURI_H */