2018-01-17 19:22:57 +01:00
|
|
|
#include "fort_impl.h"
|
2018-05-06 12:12:28 +02:00
|
|
|
#ifdef FT_HAVE_WCHAR
|
2018-03-05 19:08:14 +01:00
|
|
|
#include <wchar.h>
|
2018-05-06 12:12:28 +02:00
|
|
|
#endif
|
2018-01-17 19:22:57 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* LIBFORT helpers
|
|
|
|
*****************************************************************************/
|
2018-04-04 21:13:37 +02:00
|
|
|
|
2018-04-16 21:46:53 +02:00
|
|
|
#ifndef FT_MICROSOFT_COMPILER
|
2018-04-04 21:13:37 +02:00
|
|
|
void *(*fort_malloc)(size_t size) = &malloc;
|
|
|
|
void (*fort_free)(void *ptr) = &free;
|
|
|
|
void *(*fort_calloc)(size_t nmemb, size_t size) = &calloc;
|
|
|
|
void *(*fort_realloc)(void *ptr, size_t size) = &realloc;
|
2018-04-16 21:46:53 +02:00
|
|
|
#else
|
|
|
|
static void *local_malloc(size_t size)
|
|
|
|
{
|
|
|
|
return malloc(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void local_free(void *ptr)
|
|
|
|
{
|
|
|
|
free(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *local_calloc(size_t nmemb, size_t size)
|
|
|
|
{
|
|
|
|
return calloc(nmemb, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *local_realloc(void *ptr, size_t size)
|
|
|
|
{
|
|
|
|
return realloc(ptr, size);
|
|
|
|
}
|
2018-04-04 21:13:37 +02:00
|
|
|
|
2018-04-16 21:46:53 +02:00
|
|
|
void *(*fort_malloc)(size_t size) = &local_malloc;
|
|
|
|
void (*fort_free)(void *ptr) = &local_free;
|
|
|
|
void *(*fort_calloc)(size_t nmemb, size_t size) = &local_calloc;
|
|
|
|
void *(*fort_realloc)(void *ptr, size_t size) = &local_realloc;
|
|
|
|
#endif
|
2018-04-04 21:13:37 +02:00
|
|
|
|
|
|
|
static void *custom_fort_calloc(size_t nmemb, size_t size)
|
|
|
|
{
|
|
|
|
size_t total_size = nmemb * size;
|
|
|
|
void *result = F_MALLOC(total_size);
|
|
|
|
if (result != NULL)
|
|
|
|
memset(result, 0, total_size);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *custom_fort_realloc(void *ptr, size_t size)
|
|
|
|
{
|
|
|
|
if (ptr == NULL)
|
|
|
|
return F_MALLOC(size);
|
|
|
|
if (size == 0) {
|
|
|
|
F_FREE(ptr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *new_chunk = F_MALLOC(size);
|
|
|
|
if (new_chunk == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In theory we should copy MIN(size, size allocated for ptr) bytes,
|
|
|
|
* but this is rather dummy implementation so we don't care about it
|
|
|
|
*/
|
|
|
|
memcpy(new_chunk, ptr, size);
|
|
|
|
F_FREE(ptr);
|
|
|
|
return new_chunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr))
|
|
|
|
{
|
|
|
|
assert((f_malloc == NULL && f_free == NULL) /* Use std functions */
|
|
|
|
|| (f_malloc != NULL && f_free != NULL) /* Use custom functions */);
|
|
|
|
|
2018-04-16 21:46:53 +02:00
|
|
|
if (f_malloc == NULL && f_free == NULL) {
|
|
|
|
#ifndef FT_MICROSOFT_COMPILER
|
|
|
|
fort_malloc = &malloc;
|
|
|
|
fort_free = &free;
|
2018-04-04 21:13:37 +02:00
|
|
|
fort_calloc = &calloc;
|
|
|
|
fort_realloc = &realloc;
|
2018-04-16 21:46:53 +02:00
|
|
|
#else
|
|
|
|
fort_malloc = &local_malloc;
|
|
|
|
fort_free = &local_free;
|
|
|
|
fort_calloc = &local_calloc;
|
|
|
|
fort_realloc = &local_realloc;
|
|
|
|
#endif
|
2018-04-04 21:13:37 +02:00
|
|
|
} else {
|
2018-04-16 21:46:53 +02:00
|
|
|
fort_malloc = f_malloc;
|
|
|
|
fort_free = f_free;
|
2018-04-04 21:13:37 +02:00
|
|
|
fort_calloc = &custom_fort_calloc;
|
|
|
|
fort_realloc = &custom_fort_realloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-31 12:33:37 +02:00
|
|
|
char *fort_strdup(const char *str)
|
2018-01-17 19:22:57 +01:00
|
|
|
{
|
|
|
|
if (str == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
size_t sz = strlen(str);
|
2018-03-31 12:33:37 +02:00
|
|
|
char *str_copy = (char *)F_MALLOC((sz + 1) * sizeof(char));
|
2018-01-17 19:22:57 +01:00
|
|
|
if (str_copy == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
strcpy(str_copy, str);
|
|
|
|
return str_copy;
|
|
|
|
}
|
|
|
|
|
2018-03-31 12:33:37 +02:00
|
|
|
wchar_t *fort_wcsdup(const wchar_t *str)
|
2018-03-05 19:08:14 +01:00
|
|
|
{
|
|
|
|
if (str == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
size_t sz = wcslen(str);
|
2018-03-31 12:33:37 +02:00
|
|
|
wchar_t *str_copy = (wchar_t *)F_MALLOC((sz + 1) * sizeof(wchar_t));
|
2018-03-05 19:08:14 +01:00
|
|
|
if (str_copy == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
wcscpy(str_copy, str);
|
|
|
|
return str_copy;
|
|
|
|
}
|
|
|
|
|
2018-01-17 19:22:57 +01:00
|
|
|
size_t number_of_columns_in_format_string(const char *fmt)
|
|
|
|
{
|
|
|
|
int separator_counter = 0;
|
|
|
|
const char *pos = fmt;
|
|
|
|
while (1) {
|
|
|
|
pos = strchr(pos, FORT_COL_SEPARATOR);
|
|
|
|
if (pos == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
separator_counter++;
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
return separator_counter + 1;
|
|
|
|
}
|
|
|
|
|
2018-04-24 20:36:07 +02:00
|
|
|
size_t number_of_columns_in_format_wstring(const wchar_t *fmt)
|
|
|
|
{
|
|
|
|
int separator_counter = 0;
|
|
|
|
const wchar_t *pos = fmt;
|
|
|
|
while (1) {
|
|
|
|
pos = wcschr(pos, FORT_COL_SEPARATOR);
|
|
|
|
if (pos == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
separator_counter++;
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
return separator_counter + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-02 20:16:41 +02:00
|
|
|
//int snprint_n_chars(char *buf, size_t length, size_t n, char ch)
|
|
|
|
//{
|
|
|
|
// if (length <= n)
|
|
|
|
// return -1;
|
|
|
|
|
|
|
|
// if (n == 0)
|
|
|
|
// return 0;
|
|
|
|
|
|
|
|
// /* To ensure valid return value it is safely not print such big strings */
|
|
|
|
// if (n > INT_MAX)
|
|
|
|
// return -1;
|
|
|
|
|
|
|
|
// int status = snprintf(buf, length, "%0*d", (int)n, 0);
|
|
|
|
// if (status < 0)
|
|
|
|
// return status;
|
|
|
|
|
|
|
|
// size_t i = 0;
|
|
|
|
// for (i = 0; i < n; ++i) {
|
|
|
|
// *buf = ch;
|
|
|
|
// buf++;
|
|
|
|
// }
|
|
|
|
// return (int)n;
|
|
|
|
//}
|
|
|
|
|
|
|
|
int snprint_n_strings(char *buf, size_t length, size_t n, const char *str)
|
2018-01-17 19:22:57 +01:00
|
|
|
{
|
2018-05-02 20:16:41 +02:00
|
|
|
size_t str_len = strlen(str);
|
|
|
|
if (length <= n * str_len)
|
2018-01-17 19:22:57 +01:00
|
|
|
return -1;
|
|
|
|
|
2018-03-05 19:08:14 +01:00
|
|
|
if (n == 0)
|
|
|
|
return 0;
|
|
|
|
|
2018-04-17 19:14:50 +02:00
|
|
|
/* To ensure valid return value it is safely not print such big strings */
|
2018-05-02 20:16:41 +02:00
|
|
|
if (n * str_len > INT_MAX)
|
2018-04-17 19:14:50 +02:00
|
|
|
return -1;
|
|
|
|
|
2018-05-02 20:16:41 +02:00
|
|
|
int status = snprintf(buf, length, "%0*d", (int)(n * str_len), 0);
|
2018-01-17 19:22:57 +01:00
|
|
|
if (status < 0)
|
|
|
|
return status;
|
|
|
|
|
2018-03-09 10:44:16 +01:00
|
|
|
size_t i = 0;
|
|
|
|
for (i = 0; i < n; ++i) {
|
2018-05-02 20:16:41 +02:00
|
|
|
const char *str_p = str;
|
|
|
|
while (*str_p)
|
|
|
|
*(buf++) = *(str_p++);
|
2018-01-17 19:22:57 +01:00
|
|
|
}
|
2018-05-02 20:16:41 +02:00
|
|
|
return (int)(n * str_len);
|
2018-01-17 19:22:57 +01:00
|
|
|
}
|
2018-03-05 19:08:14 +01:00
|
|
|
|
|
|
|
|
2018-05-02 20:16:41 +02:00
|
|
|
//int wsnprint_n_chars(wchar_t *buf, size_t length, size_t n, wchar_t ch)
|
|
|
|
//{
|
|
|
|
// if (length <= n)
|
|
|
|
// return -1;
|
|
|
|
|
|
|
|
// if (n == 0)
|
|
|
|
// return 0;
|
|
|
|
|
|
|
|
// /* To ensure valid return value it is safely not print such big strings */
|
|
|
|
// if (n > INT_MAX)
|
|
|
|
// return -1;
|
|
|
|
|
|
|
|
// int status = swprintf(buf, length, L"%0*d", (int)n, 0);
|
|
|
|
// if (status < 0)
|
|
|
|
// return status;
|
|
|
|
|
|
|
|
// size_t i = 0;
|
|
|
|
// for (i = 0; i < n; ++i) {
|
|
|
|
// *buf = ch;
|
|
|
|
// buf++;
|
|
|
|
// }
|
|
|
|
// return (int)n;
|
|
|
|
//}
|
|
|
|
|
|
|
|
int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str)
|
2018-03-05 19:08:14 +01:00
|
|
|
{
|
2018-05-02 20:16:41 +02:00
|
|
|
size_t str_len = strlen(str);
|
|
|
|
|
|
|
|
/* This function doesn't work properly with multibyte characters
|
|
|
|
* so it is better return an error in this case
|
|
|
|
*/
|
|
|
|
if (str_len > 1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (length <= n * str_len)
|
2018-03-05 19:08:14 +01:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (n == 0)
|
|
|
|
return 0;
|
|
|
|
|
2018-05-02 20:16:41 +02:00
|
|
|
|
|
|
|
|
2018-04-17 19:14:50 +02:00
|
|
|
/* To ensure valid return value it is safely not print such big strings */
|
2018-05-02 20:16:41 +02:00
|
|
|
if (n * str_len > INT_MAX)
|
2018-04-17 19:14:50 +02:00
|
|
|
return -1;
|
|
|
|
|
2018-05-02 20:16:41 +02:00
|
|
|
int status = swprintf(buf, length, L"%0*d", (int)(n * str_len), 0);
|
2018-03-05 19:08:14 +01:00
|
|
|
if (status < 0)
|
|
|
|
return status;
|
|
|
|
|
2018-03-09 10:44:16 +01:00
|
|
|
size_t i = 0;
|
|
|
|
for (i = 0; i < n; ++i) {
|
2018-05-02 20:16:41 +02:00
|
|
|
const char *str_p = str;
|
|
|
|
while (*str_p)
|
|
|
|
*(buf++) = (wchar_t) * (str_p++);
|
2018-03-05 19:08:14 +01:00
|
|
|
}
|
2018-05-02 20:16:41 +02:00
|
|
|
return (int)(n * str_len);
|
2018-03-05 19:08:14 +01:00
|
|
|
}
|
2018-05-02 20:16:41 +02:00
|
|
|
|