Skip to content

Commit b4c3eac

Browse files
XsodaXsoda
Xsoda
authored and
Xsoda
committed
first commit
0 parents  commit b4c3eac

File tree

6 files changed

+427
-0
lines changed

6 files changed

+427
-0
lines changed

.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.sdf
2+
*.suo
3+
*.user
4+
_UpgradeReport_Files/
5+
UpgradeLog*.XML
6+
Debug
7+
Release
8+
ipch

url.c

+228
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/* -*- encoding: utf-8; -*- */
2+
/* -*- c-mode -*- */
3+
/* File-name: <url.c> */
4+
/* Author: <Xsoda> */
5+
/* Create: <Friday December 20 12:38:02 2013> */
6+
/* Time-stamp: <Friday December 20, 15:4:16 2013> */
7+
/* Mail: <[email protected]> */
8+
9+
#include "url.h"
10+
#include <stdlib.h>
11+
#include <stdio.h>
12+
#include <string.h>
13+
14+
static char *strndup(const char *str, int n)
15+
{
16+
char *dst;
17+
if (n < 0) n = strlen(str);
18+
if (n == 0) return NULL;
19+
if ((dst = (char *)malloc(n + 1)) == NULL)
20+
return NULL;
21+
memcpy(dst, str, n);
22+
dst[n] = 0;
23+
return dst;
24+
}
25+
26+
url_field_t *url_parse (const char *str)
27+
{
28+
const char *pch;
29+
url_field_t *url;
30+
if ((url = (url_field_t *)malloc(sizeof(url_field_t))) == NULL)
31+
return NULL;
32+
memset(url, 0, sizeof(url_field_t));
33+
if (str && str[0])
34+
{
35+
url->href = strndup(str, -1);
36+
pch = strchr(str, ':'); /* parse schema */
37+
if (pch && pch[1] == '/' && pch[2] == '/')
38+
{
39+
url->schema = strndup(str, pch - str);
40+
str = pch + 3;
41+
}
42+
else
43+
goto __fail;
44+
pch = strchr(str, '@'); /* parse user info */
45+
if (pch)
46+
{
47+
pch = strchr(str, ':');
48+
if (pch)
49+
{
50+
url->username = strndup(str, pch - str);
51+
str = pch + 1;
52+
pch = strchr(str, '@');
53+
if (pch)
54+
{
55+
url->password = strndup(str, pch - str);
56+
str = pch + 1;
57+
}
58+
else
59+
goto __fail;
60+
}
61+
else
62+
goto __fail;
63+
}
64+
if (str[0] == '[') /* parse host info */
65+
{
66+
str++;
67+
pch = strchr(str, ']');
68+
if (pch)
69+
{
70+
url->host = strndup(str, pch - str);
71+
str = pch + 1;
72+
if (str[0] == ':')
73+
{
74+
str++;
75+
pch = strchr(str, '/');
76+
if (pch)
77+
{
78+
url->port = strndup(str, pch - str);
79+
str = pch + 1;
80+
}
81+
else
82+
{
83+
url->port = strndup(str, -1);
84+
str = str + strlen(str);
85+
}
86+
}
87+
}
88+
else
89+
goto __fail;
90+
}
91+
else
92+
{
93+
pch = strchr(str, ':');
94+
if (pch)
95+
{
96+
url->host = strndup(str, pch - str);
97+
str = pch + 1;
98+
pch = strchr(str, '/');
99+
if (pch)
100+
{
101+
url->port = strndup(str, pch - str);
102+
str = pch + 1;
103+
}
104+
else
105+
{
106+
url->port = strndup(str, -1);
107+
str = str + strlen(str);
108+
}
109+
}
110+
else
111+
{
112+
pch = strchr(str, '/');
113+
if (pch)
114+
{
115+
url->host = strndup(str, pch - str);
116+
str = pch + 1;
117+
}
118+
else
119+
{
120+
url->host = strndup(str, -1);
121+
str = str + strlen(str);
122+
}
123+
}
124+
}
125+
if (str[0]) /* parse path, parament and fragment */
126+
{
127+
pch = strchr(str, '?');
128+
if (pch)
129+
{
130+
url->path = strndup(str, pch - str);
131+
str = pch + 1;
132+
pch = strchr(str, '#');
133+
if (pch)
134+
{
135+
url->parament = strndup(str, pch - str);
136+
str = pch + 1;
137+
url->fragment = strndup(str, -1);
138+
}
139+
else
140+
{
141+
url->parament = strndup(str, -1);
142+
str = str + strlen(str);
143+
}
144+
}
145+
else
146+
{
147+
pch = strchr(str, '#');
148+
if (pch)
149+
{
150+
url->path = strndup(str, pch - str);
151+
str = pch + 1;
152+
url->fragment = strndup(str, -1);
153+
str = str + strlen(str);
154+
}
155+
else
156+
{
157+
url->path = strndup(str, -1);
158+
str = str + strlen(str);
159+
}
160+
}
161+
}
162+
}
163+
else
164+
{
165+
__fail:
166+
url_free(url);
167+
return NULL;
168+
}
169+
return url;
170+
}
171+
172+
void url_free(url_field_t *url)
173+
{
174+
if (!url) return;
175+
if (url->href) free(url->href);
176+
if (url->schema) free(url->schema);
177+
if (url->username) free(url->username);
178+
if (url->password) free(url->password);
179+
if (url->host) free(url->host);
180+
if (url->port) free(url->port);
181+
if (url->path) free(url->path);
182+
if (url->parament) free(url->parament);
183+
if (url->fragment) free(url->fragment);
184+
free(url);
185+
}
186+
187+
void url_field_print(url_field_t *url)
188+
{
189+
if (!url) return;
190+
fprintf(stdout, "\nuri field:\n");
191+
fprintf(stdout, " - href: '%s'\n", url->href);
192+
fprintf(stdout, " - schema: '%s'\n", url->schema);
193+
if (url->username)
194+
fprintf(stdout, " - username: '%s'\n", url->username);
195+
if (url->password)
196+
fprintf(stdout, " - password: '%s'\n", url->password);
197+
fprintf(stdout, " - host: '%s'\n", url->host);
198+
if (url->port)
199+
fprintf(stdout, " - port: '%s'\n", url->port);
200+
if (url->path)
201+
fprintf(stdout, " - path: '%s'\n", url->path);
202+
if (url->parament)
203+
fprintf(stdout, " - parament: '%s'\n", url->parament);
204+
if (url->fragment)
205+
fprintf(stdout, " - fragment: '%s'\n", url->fragment);
206+
}
207+
208+
int main()
209+
{
210+
char *str[] = {
211+
"scheme://host",
212+
"http://[::1]:8080/index.html",
213+
"scheme://username:password@host",
214+
"scheme://host:port",
215+
"scheme://host:port/path?id=1&method=get#fragment",
216+
"scheme://host/path/to/subpath#fragment",
217+
"scheme://username:password@host/path?name=test#fragment",
218+
"scheme://username:password@host:port/path?name=test#fragment",
219+
NULL
220+
};
221+
for (int i = 0; str[i]; i++)
222+
{
223+
url_field_t *url = url_parse(str[i]);
224+
url_field_print(url);
225+
url_free(url);
226+
}
227+
return 0;
228+
}

url.h

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* -*- encoding: utf-8; -*- */
2+
/* -*- c-mode -*- */
3+
/* File-name: <url.h> */
4+
/* Author: <Xsoda> */
5+
/* Create: <Friday December 20 12:47:08 2013> */
6+
/* Time-stamp: <Friday December 20, 14:29:56 2013> */
7+
/* Mail: <[email protected]> */
8+
9+
#ifndef __URL_H__
10+
#define __URL_H__
11+
12+
/*
13+
* parse url like this
14+
*
15+
* schema://username:password@host:port/path?key=value#fragment
16+
* \____/ \______/ \______/ \__/ \__/ \__/ \_______/ \______/
17+
* | | | | | | | |
18+
* schema | password | port | parament fragment
19+
* username host path
20+
*
21+
* note:
22+
* - username, password, port, path, query, fragment is optional.
23+
* - scheme, host must be setting.
24+
* - username and password must be paired.
25+
*
26+
*/
27+
28+
typedef struct _url_field {
29+
char *href;
30+
char *schema;
31+
char *username;
32+
char *password;
33+
char *host;
34+
char *port;
35+
char *path;
36+
char *parament;
37+
char *fragment;
38+
} url_field_t;
39+
40+
#ifdef __cplusplus
41+
extern "C" {
42+
#endif
43+
44+
url_field_t *url_parse(const char *str);
45+
46+
void url_free(url_field_t *url);
47+
48+
void url_field_print(url_field_t *url);
49+
50+
#ifdef __cplusplus
51+
}
52+
#endif
53+
54+
#endif /* !__URI_H__ */

url.sln

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 2012
4+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "url", "url.vcxproj", "{76D25320-2ACC-4A4F-A75C-4136DC3A8DFF}"
5+
EndProject
6+
Global
7+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8+
Debug|Win32 = Debug|Win32
9+
Release|Win32 = Release|Win32
10+
EndGlobalSection
11+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
12+
{76D25320-2ACC-4A4F-A75C-4136DC3A8DFF}.Debug|Win32.ActiveCfg = Debug|Win32
13+
{76D25320-2ACC-4A4F-A75C-4136DC3A8DFF}.Debug|Win32.Build.0 = Debug|Win32
14+
{76D25320-2ACC-4A4F-A75C-4136DC3A8DFF}.Release|Win32.ActiveCfg = Release|Win32
15+
{76D25320-2ACC-4A4F-A75C-4136DC3A8DFF}.Release|Win32.Build.0 = Release|Win32
16+
EndGlobalSection
17+
GlobalSection(SolutionProperties) = preSolution
18+
HideSolutionNode = FALSE
19+
EndGlobalSection
20+
EndGlobal

0 commit comments

Comments
 (0)