Modest/source/myurl/path.c
2017-03-03 09:20:23 +03:00

287 lines
8.0 KiB
C

/*
Copyright (C) 2016-2017 Alexander Borisov
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Author: lex.borisov@gmail.com (Alexander Borisov)
*/
#include "myurl/path.h"
#include "myurl/url.h"
myurl_path_t * myurl_path_create(myurl_t* url)
{
myurl_path_t *path = url->callback_malloc(sizeof(myurl_path_t), url->callback_ctx);
if(path)
memset(path, 0, sizeof(myurl_path_t));
return path;
}
mystatus_t myurl_path_init(myurl_t* url, myurl_path_t* path, size_t begin_size)
{
if(begin_size == 0)
return MyURL_STATUS_ERROR;
path->length = 0;
path->size = begin_size;
path->list = url->callback_malloc(sizeof(myurl_path_entry_t) * path->size, url->callback_ctx);
if(path->list == NULL)
return MyURL_STATUS_ERROR_MEMORY_ALLOCATION;
memset(path->list, 0, sizeof(myurl_path_entry_t) * path->size);
return MyURL_STATUS_OK;
}
void myurl_path_clean(myurl_t* url, myurl_path_t* path)
{
for(size_t i = 0; i < path->length; i++) {
if(path->list[i].data) {
url->callback_free(path->list[i].data, url->callback_ctx);
}
}
path->length = 0;
}
myurl_path_entry_t * myurl_path_entry_destroy(myurl_t* url, myurl_path_entry_t* path, bool destroy_self)
{
if(path == NULL)
return NULL;
if(path->data)
url->callback_free(path->data, url->callback_ctx);
if(destroy_self) {
url->callback_free(path, url->callback_ctx);
return NULL;
}
return path;
}
myurl_path_t * myurl_path_destroy(myurl_t* url, myurl_path_t* path, bool destroy_self)
{
if(path == NULL)
return NULL;
if(path->list) {
myurl_path_clean(url, path);
url->callback_free(path->list, url->callback_ctx);
}
if(destroy_self && path) {
return url->callback_free(path, url->callback_ctx);
}
return path;
}
myurl_path_entry_t * myurl_path_append(myurl_t* url, myurl_path_t* path, const char* data, size_t length)
{
if(path->length >= path->size) {
size_t new_size = path->length + 1024;
myurl_path_entry_t *tmp = url->callback_realloc(path->list, sizeof(myurl_path_entry_t) * new_size, url->callback_ctx);
if(tmp) {
memset(&tmp[path->length], 0, sizeof(myurl_path_entry_t) * (new_size - path->length));
path->list = tmp;
path->size = new_size;
}
else
return NULL;
}
myurl_path_entry_t *entry = &path->list[ path->length ];
path->length++;
if(length) {
entry->data = url->callback_malloc(sizeof(char) * length, url->callback_ctx);
if(entry->data == NULL)
return NULL;
memcpy(entry->data, data, sizeof(char) * length);
}
else
entry->data = NULL;
entry->length = length;
return entry;
}
myurl_path_entry_t * myurl_path_push(myurl_t* url, myurl_path_t* path, char* data, size_t length)
{
if(path->length >= path->size) {
size_t new_size = path->length + 32;
myurl_path_entry_t *tmp = url->callback_realloc(path->list, sizeof(myurl_path_entry_t) * new_size, url->callback_ctx);
if(tmp) {
memset(&tmp[path->length], 0, sizeof(myurl_path_entry_t) * (new_size - path->length));
path->list = tmp;
path->size = new_size;
}
else
return NULL;
}
myurl_path_entry_t *entry = &path->list[ path->length ];
path->length++;
entry->data = data;
entry->length = length;
return entry;
}
myurl_path_entry_t * myurl_path_push_to_index(myurl_t* url, myurl_path_t* path, size_t index, char* data, size_t length)
{
if(index >= path->size) {
myurl_path_entry_t *tmp = url->callback_realloc(path->list, sizeof(myurl_path_entry_t) * index, url->callback_ctx);
if(tmp) {
memset(&tmp[path->length], 0, sizeof(myurl_path_entry_t) * (index - path->length));
path->list = tmp;
path->size = index;
}
else
return NULL;
}
if(index > path->length)
path->length = index;
if(path->list[ index ].data)
url->callback_free(path->list[ index ].data, url->callback_ctx);
path->list[ index ].data = data;
path->list[ index ].length = length;
return &path->list[ index ];
}
myurl_path_entry_t * myurl_path_current(myurl_path_t* path)
{
if(path->length == 0)
return NULL;
return &path->list[ (path->length - 1) ];
}
myurl_path_entry_t * myurl_path_pop(myurl_path_t* path)
{
if(path->length == 0)
return NULL;
path->length--;
return &path->list[path->length];
}
void myurl_path_remove_by_index(myurl_t* url, myurl_path_t* path, size_t index)
{
if(path->length == 0 || index >= path->length || path->list == NULL)
return;
myurl_path_entry_destroy(url, &path->list[index], false);
if((path->length - 1) > index) {
memmove(&path->list[index], &path->list[index + 1], sizeof(myurl_path_entry_t) * (path->length - (path->length - index)));
}
path->length--;
}
mystatus_t myurl_path_copy(myurl_t* url, myurl_path_t* path_from, myurl_path_t* path_to)
{
if(path_from->length >= path_to->size) {
size_t new_size = path_from->length + 2;
myurl_path_entry_t* tmp = url->callback_realloc(path_to->list, sizeof(myurl_path_entry_t) * new_size, url->callback_ctx);
if(tmp) {
memset(&tmp[path_to->length], 0, sizeof(myurl_path_entry_t) * (new_size - path_to->length));
path_to->list = tmp;
path_to->size = new_size;
}
else
return MyURL_STATUS_ERROR_MEMORY_ALLOCATION;
}
myurl_path_entry_t *list_to = path_to->list;
myurl_path_entry_t *list_from = path_from->list;
if(path_to->length > path_from->length)
{
while(path_to->length > path_from->length) {
path_to->length--;
if(list_to[path_to->length].data)
url->callback_free( list_to[path_to->length].data, url->callback_ctx );
}
}
path_to->length = path_from->length;
for(size_t i = 0; i < path_from->length; i++)
{
if(list_to[i].data)
{
if(list_to[i].length < list_from[i].length)
list_to[i].data = url->callback_realloc(list_to[i].data, (list_from[i].length + 1), url->callback_ctx);
}
else {
list_to[i].data = url->callback_malloc((list_from[i].length + 1), url->callback_ctx);
}
if(list_to[i].data == NULL)
return MyURL_STATUS_ERROR_MEMORY_ALLOCATION;
list_to[i].length = list_from[i].length;
list_to[i].data[ list_to[i].length ] = '\0';
if(list_from[i].length) {
memcpy(list_to[i].data, list_from[i].data, sizeof(char) * list_from[i].length);
}
}
return MyURL_STATUS_OK;
}
void myurl_path_shorten(myurl_path_t* path, myurl_scheme_id_t scheme_id)
{
if(path->length == 0)
return;
if(scheme_id == MyURL_SCHEME_ID_FILE) {
if(path->length == 1 && myurl_utils_is_windows_drive_letter(path->list[0].data, 0, path->list[0].length))
return;
}
myurl_path_pop(path);
}