422 lines
9.7 KiB
C
422 lines
9.7 KiB
C
/**
|
|
*
|
|
* Orcania library
|
|
*
|
|
* Different functions for different purposes but that can be shared between
|
|
* other projects
|
|
*
|
|
* orcania.c: main functions definitions
|
|
*
|
|
* Copyright 2015-2020 Nicolas Mora <mail@babelouest.org>
|
|
*
|
|
* This program 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;
|
|
* version 2.1 of the License.
|
|
*
|
|
* 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 GENERAL PUBLIC LICENSE for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
|
*
|
|
* This file is part of Open5GS.
|
|
*
|
|
* This program 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "core-config-private.h"
|
|
|
|
#if HAVE_FCNTL_H
|
|
#include <fcntl.h>
|
|
#endif
|
|
|
|
#if HAVE_STDARG_H
|
|
#include <stdarg.h>
|
|
#endif
|
|
|
|
#if HAVE_CTYPE_H
|
|
#include <ctype.h>
|
|
#endif
|
|
|
|
#include "ogs-core.h"
|
|
|
|
int ogs_vsnprintf(char *str, size_t size, const char *format, va_list ap)
|
|
{
|
|
int r = -1;
|
|
|
|
/* Microsoft has finally implemented snprintf in Visual Studio 2015.
|
|
* In previous versions, I will simulate it as below. */
|
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
|
ogs_assert(str);
|
|
|
|
if (size != 0)
|
|
r = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
|
|
|
|
if (r == -1)
|
|
r = _vscprintf(format, ap);
|
|
#else
|
|
r = vsnprintf(str, size, format, ap);
|
|
#endif
|
|
str[size-1] = '\0';
|
|
|
|
return r;
|
|
}
|
|
|
|
int ogs_snprintf(char *str, size_t size, const char *format, ...)
|
|
{
|
|
int r;
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
r = ogs_vsnprintf(str, size, format, ap);
|
|
va_end(ap);
|
|
|
|
return r;
|
|
}
|
|
|
|
char *ogs_vslprintf(char *str, char *last, const char *format, va_list ap)
|
|
{
|
|
int r = -1;
|
|
|
|
ogs_assert(last);
|
|
|
|
if (!str)
|
|
return NULL;
|
|
|
|
if (str < last)
|
|
r = ogs_vsnprintf(str, last - str, format, ap);
|
|
|
|
return (str + r);
|
|
}
|
|
|
|
char *ogs_slprintf(char *str, char *last, const char *format, ...)
|
|
{
|
|
char *r;
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
r = ogs_vslprintf(str, last, format, ap);
|
|
va_end(ap);
|
|
|
|
return r;
|
|
}
|
|
|
|
char *ogs_cpystrn(char *dst, const char *src, size_t dst_size)
|
|
{
|
|
char *d = dst, *end;
|
|
|
|
if (dst_size == 0) {
|
|
return (dst);
|
|
}
|
|
|
|
if (src) {
|
|
end = dst + dst_size - 1;
|
|
|
|
for (; d < end; ++d, ++src) {
|
|
if (!(*d = *src)) {
|
|
return (d);
|
|
}
|
|
}
|
|
}
|
|
|
|
*d = '\0'; /* always null terminate */
|
|
|
|
return (d);
|
|
}
|
|
|
|
/*****************************************
|
|
* Memory Pool - Use talloc library
|
|
*****************************************/
|
|
|
|
char *ogs_talloc_strdup(const void *t, const char *p)
|
|
{
|
|
char *ptr = NULL;
|
|
|
|
ogs_thread_mutex_lock(ogs_mem_get_mutex());
|
|
|
|
ptr = talloc_strdup(t, p);
|
|
ogs_expect(ptr);
|
|
|
|
ogs_thread_mutex_unlock(ogs_mem_get_mutex());
|
|
|
|
return ptr;
|
|
}
|
|
|
|
char *ogs_talloc_strndup(const void *t, const char *p, size_t n)
|
|
{
|
|
char *ptr = NULL;
|
|
|
|
ogs_thread_mutex_lock(ogs_mem_get_mutex());
|
|
|
|
ptr = talloc_strndup(t, p, n);
|
|
ogs_expect(ptr);
|
|
|
|
ogs_thread_mutex_unlock(ogs_mem_get_mutex());
|
|
|
|
return ptr;
|
|
}
|
|
|
|
void *ogs_talloc_memdup(const void *t, const void *p, size_t size)
|
|
{
|
|
void *ptr = NULL;
|
|
|
|
ogs_thread_mutex_lock(ogs_mem_get_mutex());
|
|
|
|
ptr = talloc_memdup(t, p, size);
|
|
ogs_expect(ptr);
|
|
|
|
ogs_thread_mutex_unlock(ogs_mem_get_mutex());
|
|
|
|
return ptr;
|
|
}
|
|
|
|
char *ogs_talloc_asprintf(const void *t, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
char *ret;
|
|
|
|
ogs_thread_mutex_lock(ogs_mem_get_mutex());
|
|
|
|
va_start(ap, fmt);
|
|
ret = talloc_vasprintf(t, fmt, ap);
|
|
ogs_expect(ret);
|
|
va_end(ap);
|
|
|
|
ogs_thread_mutex_unlock(ogs_mem_get_mutex());
|
|
|
|
return ret;
|
|
}
|
|
|
|
char *ogs_talloc_asprintf_append(char *s, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
ogs_thread_mutex_lock(ogs_mem_get_mutex());
|
|
|
|
va_start(ap, fmt);
|
|
s = talloc_vasprintf_append(s, fmt, ap);
|
|
ogs_expect(s);
|
|
va_end(ap);
|
|
|
|
ogs_thread_mutex_unlock(ogs_mem_get_mutex());
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
/*****************************************
|
|
* Memory Pool - Use pkbuf library
|
|
*****************************************/
|
|
|
|
char *ogs_strdup_debug(const char *s, const char *file_line)
|
|
{
|
|
char *res;
|
|
size_t len;
|
|
|
|
if (s == NULL)
|
|
return NULL;
|
|
|
|
len = strlen(s) + 1;
|
|
res = ogs_memdup_debug(s, len, file_line);
|
|
if (!res) {
|
|
ogs_error("ogs_memdup_debug[len:%d] failed", (int)len);
|
|
return res;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
char *ogs_strndup_debug(
|
|
const char *s, size_t n, const char *file_line)
|
|
{
|
|
char *res;
|
|
const char *end;
|
|
|
|
if (s == NULL)
|
|
return NULL;
|
|
|
|
end = memchr(s, '\0', n);
|
|
if (end != NULL)
|
|
n = end - s;
|
|
res = ogs_malloc_debug(n + 1, file_line);
|
|
if (!res) {
|
|
ogs_error("ogs_malloc_debug[n:%d] failed", (int)n);
|
|
return res;
|
|
}
|
|
memcpy(res, s, n);
|
|
res[n] = '\0';
|
|
return res;
|
|
}
|
|
|
|
void *ogs_memdup_debug(
|
|
const void *m, size_t n, const char *file_line)
|
|
{
|
|
void *res;
|
|
|
|
if (m == NULL)
|
|
return NULL;
|
|
|
|
res = ogs_malloc_debug(n, file_line);
|
|
if (!res) {
|
|
ogs_error("ogs_malloc_debug[n:%d] failed", (int)n);
|
|
return res;
|
|
}
|
|
memcpy(res, m, n);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
* char *ogs_msprintf(const char *message, ...)
|
|
* char *mstrcatf(char *source, const char *message, ...)
|
|
*
|
|
* Orcania library
|
|
* Copyright 2015-2018 Nicolas Mora <mail@babelouest.org>
|
|
* License: LGPL-2.1
|
|
*
|
|
* https://github.com/babelouest/orcania.git
|
|
*/
|
|
char *ogs_msprintf_debug(
|
|
const char *file_line, const char *message, ...)
|
|
{
|
|
va_list argp, argp_cpy;
|
|
size_t out_len = 0;
|
|
char *out = NULL;
|
|
if (message != NULL) {
|
|
va_start(argp, message);
|
|
va_copy(argp_cpy, argp); /* We make a copy because
|
|
in some architectures,
|
|
vsnprintf can modify argp */
|
|
out_len = vsnprintf(NULL, 0, message, argp);
|
|
out = ogs_malloc_debug(out_len + sizeof(char), file_line);
|
|
if (out == NULL) {
|
|
va_end(argp);
|
|
va_end(argp_cpy);
|
|
return NULL;
|
|
}
|
|
vsnprintf(out, (out_len + sizeof(char)), message, argp_cpy);
|
|
va_end(argp);
|
|
va_end(argp_cpy);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
char *ogs_mstrcatf_debug(
|
|
char *source, const char *file_line, const char *message, ...)
|
|
{
|
|
va_list argp, argp_cpy;
|
|
char *out = NULL, *message_formatted = NULL;
|
|
size_t message_formatted_len = 0, out_len = 0;
|
|
|
|
if (message != NULL) {
|
|
if (source != NULL) {
|
|
va_start(argp, message);
|
|
va_copy(argp_cpy, argp); /* We make a copy because
|
|
in some architectures,
|
|
vsnprintf can modify argp */
|
|
message_formatted_len = vsnprintf(NULL, 0, message, argp);
|
|
message_formatted = ogs_malloc(message_formatted_len+sizeof(char));
|
|
if (message_formatted != NULL) {
|
|
vsnprintf(message_formatted,
|
|
(message_formatted_len+sizeof(char)), message, argp_cpy);
|
|
out = ogs_msprintf_debug(
|
|
file_line, "%s%s", source, message_formatted);
|
|
ogs_free(message_formatted);
|
|
ogs_free(source);
|
|
}
|
|
va_end(argp);
|
|
va_end(argp_cpy);
|
|
} else {
|
|
va_start(argp, message);
|
|
va_copy(argp_cpy, argp); /* We make a copy because
|
|
in some architectures,
|
|
vsnprintf can modify argp */
|
|
out_len = vsnprintf(NULL, 0, message, argp);
|
|
out = ogs_malloc_debug(out_len+sizeof(char), file_line);
|
|
if (out != NULL) {
|
|
vsnprintf(out, (out_len+sizeof(char)), message, argp_cpy);
|
|
}
|
|
va_end(argp);
|
|
va_end(argp_cpy);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
char *ogs_trimwhitespace(char *str)
|
|
{
|
|
char *end;
|
|
|
|
if (str == NULL) {
|
|
return NULL;
|
|
} else if (*str == 0) {
|
|
return str;
|
|
}
|
|
|
|
while (isspace((unsigned char)*str)) str++;
|
|
|
|
end = str + strlen(str) - 1;
|
|
while(end > str && isspace((unsigned char)*end)) {
|
|
end--;
|
|
}
|
|
|
|
*(end+1) = 0;
|
|
|
|
return str;
|
|
}
|
|
|
|
char *ogs_left_trimcharacter(char *str, char to_remove)
|
|
{
|
|
if (str == NULL) {
|
|
return NULL;
|
|
} else if (*str == 0) {
|
|
return str;
|
|
}
|
|
|
|
while(*str == to_remove) str++;
|
|
|
|
return str;
|
|
}
|
|
|
|
char *ogs_right_trimcharacter(char *str, char to_remove)
|
|
{
|
|
char *end;
|
|
|
|
if (str == NULL) {
|
|
return NULL;
|
|
} else if (*str == 0) {
|
|
return str;
|
|
}
|
|
|
|
end = str + strlen(str) - 1;
|
|
while(end > str && (*end == to_remove)) {
|
|
end--;
|
|
}
|
|
|
|
*(end+1) = 0;
|
|
|
|
return str;
|
|
}
|
|
|
|
char *ogs_trimcharacter(char *str, char to_remove)
|
|
{
|
|
return ogs_right_trimcharacter(
|
|
ogs_left_trimcharacter(str, to_remove), to_remove);
|
|
}
|