00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
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) {
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) {
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
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;
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