1 /*
2 Copyright (C) 2016-2017 Alexander Borisov
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18 Author: lex.borisov@gmail.com (Alexander Borisov)
19 */
20
21 #include "myurl/path.h"
22 #include "myurl/url.h"
23
myurl_path_create(myurl_t * url)24 myurl_path_t * myurl_path_create(myurl_t* url)
25 {
26 myurl_path_t *path = url->callback_malloc(sizeof(myurl_path_t), url->callback_ctx);
27
28 if(path)
29 memset(path, 0, sizeof(myurl_path_t));
30
31 return path;
32 }
33
myurl_path_init(myurl_t * url,myurl_path_t * path,size_t begin_size)34 mystatus_t myurl_path_init(myurl_t* url, myurl_path_t* path, size_t begin_size)
35 {
36 if(begin_size == 0)
37 return MyURL_STATUS_ERROR;
38
39 path->length = 0;
40 path->size = begin_size;
41 path->list = url->callback_malloc(sizeof(myurl_path_entry_t) * path->size, url->callback_ctx);
42
43 if(path->list == NULL)
44 return MyURL_STATUS_ERROR_MEMORY_ALLOCATION;
45
46 memset(path->list, 0, sizeof(myurl_path_entry_t) * path->size);
47
48 return MyURL_STATUS_OK;
49 }
50
myurl_path_clean(myurl_t * url,myurl_path_t * path)51 void myurl_path_clean(myurl_t* url, myurl_path_t* path)
52 {
53 for(size_t i = 0; i < path->length; i++) {
54 if(path->list[i].data) {
55 url->callback_free(path->list[i].data, url->callback_ctx);
56 }
57 }
58
59 path->length = 0;
60 }
61
myurl_path_entry_destroy(myurl_t * url,myurl_path_entry_t * path,bool destroy_self)62 myurl_path_entry_t * myurl_path_entry_destroy(myurl_t* url, myurl_path_entry_t* path, bool destroy_self)
63 {
64 if(path == NULL)
65 return NULL;
66
67 if(path->data)
68 url->callback_free(path->data, url->callback_ctx);
69
70 if(destroy_self) {
71 url->callback_free(path, url->callback_ctx);
72 return NULL;
73 }
74
75 return path;
76 }
77
myurl_path_destroy(myurl_t * url,myurl_path_t * path,bool destroy_self)78 myurl_path_t * myurl_path_destroy(myurl_t* url, myurl_path_t* path, bool destroy_self)
79 {
80 if(path == NULL)
81 return NULL;
82
83 if(path->list) {
84 myurl_path_clean(url, path);
85 url->callback_free(path->list, url->callback_ctx);
86 }
87
88 if(destroy_self && path) {
89 return url->callback_free(path, url->callback_ctx);
90 }
91
92 return path;
93 }
94
myurl_path_append(myurl_t * url,myurl_path_t * path,const char * data,size_t length)95 myurl_path_entry_t * myurl_path_append(myurl_t* url, myurl_path_t* path, const char* data, size_t length)
96 {
97 if(path->length >= path->size) {
98 size_t new_size = path->length + 1024;
99
100 myurl_path_entry_t *tmp = url->callback_realloc(path->list, sizeof(myurl_path_entry_t) * new_size, url->callback_ctx);
101
102 if(tmp) {
103 memset(&tmp[path->length], 0, sizeof(myurl_path_entry_t) * (new_size - path->length));
104
105 path->list = tmp;
106 path->size = new_size;
107 }
108 else
109 return NULL;
110 }
111
112 myurl_path_entry_t *entry = &path->list[ path->length ];
113 path->length++;
114
115 if(length) {
116 entry->data = url->callback_malloc(sizeof(char) * length, url->callback_ctx);
117
118 if(entry->data == NULL)
119 return NULL;
120
121 memcpy(entry->data, data, sizeof(char) * length);
122 }
123 else
124 entry->data = NULL;
125
126 entry->length = length;
127 return entry;
128 }
129
myurl_path_push(myurl_t * url,myurl_path_t * path,char * data,size_t length)130 myurl_path_entry_t * myurl_path_push(myurl_t* url, myurl_path_t* path, char* data, size_t length)
131 {
132 if(path->length >= path->size) {
133 size_t new_size = path->length + 32;
134
135 myurl_path_entry_t *tmp = url->callback_realloc(path->list, sizeof(myurl_path_entry_t) * new_size, url->callback_ctx);
136
137 if(tmp) {
138 memset(&tmp[path->length], 0, sizeof(myurl_path_entry_t) * (new_size - path->length));
139
140 path->list = tmp;
141 path->size = new_size;
142 }
143 else
144 return NULL;
145 }
146
147 myurl_path_entry_t *entry = &path->list[ path->length ];
148 path->length++;
149
150 entry->data = data;
151 entry->length = length;
152
153 return entry;
154 }
155
myurl_path_push_to_index(myurl_t * url,myurl_path_t * path,size_t index,char * data,size_t length)156 myurl_path_entry_t * myurl_path_push_to_index(myurl_t* url, myurl_path_t* path, size_t index, char* data, size_t length)
157 {
158 if(index >= path->size) {
159 myurl_path_entry_t *tmp = url->callback_realloc(path->list, sizeof(myurl_path_entry_t) * index, url->callback_ctx);
160
161 if(tmp) {
162 memset(&tmp[path->length], 0, sizeof(myurl_path_entry_t) * (index - path->length));
163
164 path->list = tmp;
165 path->size = index;
166 }
167 else
168 return NULL;
169 }
170
171 if(index > path->length)
172 path->length = index;
173
174 if(path->list[ index ].data)
175 url->callback_free(path->list[ index ].data, url->callback_ctx);
176
177 path->list[ index ].data = data;
178 path->list[ index ].length = length;
179
180 return &path->list[ index ];
181 }
182
myurl_path_current(myurl_path_t * path)183 myurl_path_entry_t * myurl_path_current(myurl_path_t* path)
184 {
185 if(path->length == 0)
186 return NULL;
187
188 return &path->list[ (path->length - 1) ];
189 }
190
myurl_path_pop(myurl_path_t * path)191 myurl_path_entry_t * myurl_path_pop(myurl_path_t* path)
192 {
193 if(path->length == 0)
194 return NULL;
195
196 path->length--;
197
198 return &path->list[path->length];
199 }
200
myurl_path_remove_by_index(myurl_t * url,myurl_path_t * path,size_t index)201 void myurl_path_remove_by_index(myurl_t* url, myurl_path_t* path, size_t index)
202 {
203 if(path->length == 0 || index >= path->length || path->list == NULL)
204 return;
205
206 myurl_path_entry_destroy(url, &path->list[index], false);
207
208 if((path->length - 1) > index) {
209 memmove(&path->list[index], &path->list[index + 1], sizeof(myurl_path_entry_t) * (path->length - (path->length - index)));
210 }
211
212 path->length--;
213 }
214
myurl_path_copy(myurl_t * url,myurl_path_t * path_from,myurl_path_t * path_to)215 mystatus_t myurl_path_copy(myurl_t* url, myurl_path_t* path_from, myurl_path_t* path_to)
216 {
217 if(path_from->length >= path_to->size) {
218 size_t new_size = path_from->length + 2;
219
220 myurl_path_entry_t* tmp = url->callback_realloc(path_to->list, sizeof(myurl_path_entry_t) * new_size, url->callback_ctx);
221
222 if(tmp) {
223 memset(&tmp[path_to->length], 0, sizeof(myurl_path_entry_t) * (new_size - path_to->length));
224
225 path_to->list = tmp;
226 path_to->size = new_size;
227 }
228 else
229 return MyURL_STATUS_ERROR_MEMORY_ALLOCATION;
230 }
231
232 myurl_path_entry_t *list_to = path_to->list;
233 myurl_path_entry_t *list_from = path_from->list;
234
235 if(path_to->length > path_from->length)
236 {
237 while(path_to->length > path_from->length) {
238 path_to->length--;
239
240 if(list_to[path_to->length].data)
241 url->callback_free( list_to[path_to->length].data, url->callback_ctx );
242 }
243 }
244
245 path_to->length = path_from->length;
246
247 for(size_t i = 0; i < path_from->length; i++)
248 {
249 if(list_to[i].data)
250 {
251 if(list_to[i].length < list_from[i].length)
252 list_to[i].data = url->callback_realloc(list_to[i].data, (list_from[i].length + 1), url->callback_ctx);
253 }
254 else {
255 list_to[i].data = url->callback_malloc((list_from[i].length + 1), url->callback_ctx);
256 }
257
258 if(list_to[i].data == NULL)
259 return MyURL_STATUS_ERROR_MEMORY_ALLOCATION;
260
261 list_to[i].length = list_from[i].length;
262 list_to[i].data[ list_to[i].length ] = '\0';
263
264 if(list_from[i].length) {
265 memcpy(list_to[i].data, list_from[i].data, sizeof(char) * list_from[i].length);
266 }
267 }
268
269 return MyURL_STATUS_OK;
270 }
271
myurl_path_shorten(myurl_path_t * path,myurl_scheme_id_t scheme_id)272 void myurl_path_shorten(myurl_path_t* path, myurl_scheme_id_t scheme_id)
273 {
274 if(path->length == 0)
275 return;
276
277 if(scheme_id == MyURL_SCHEME_ID_FILE) {
278 if(path->length == 1 && myurl_utils_is_windows_drive_letter(path->list[0].data, 0, path->list[0].length))
279 return;
280 }
281
282 myurl_path_pop(path);
283 }
284
285
286
287