Coverage Report

Created: 2025-07-23 07:05

/src/open5gs/lib/core/ogs-strings.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 *
3
 * Orcania library
4
 *
5
 * Different functions for different purposes but that can be shared between
6
 * other projects
7
 *
8
 * orcania.c: main functions definitions
9
 *
10
 * Copyright 2015-2020 Nicolas Mora <mail@babelouest.org>
11
 *
12
 * This program is free software; you can redistribute it and/or
13
 * modify it under the terms of the GNU Lesser General Public License
14
 * as published by the Free Software Foundation;
15
 * version 2.1 of the License.
16
 *
17
 * This library is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU GENERAL PUBLIC LICENSE for more details.
21
 *
22
 * You should have received a copy of the GNU General Public
23
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
/*
28
 * Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
29
 *
30
 * This file is part of Open5GS.
31
 *
32
 * This program is free software: you can redistribute it and/or modify
33
 * it under the terms of the GNU Lesser General Public License as published by
34
 * the Free Software Foundation, either version 3 of the License, or
35
 * (at your option) any later version.
36
 *
37
 * This program is distributed in the hope that it will be useful,
38
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40
 * GNU General Public License for more details.
41
 *
42
 * You should have received a copy of the GNU General Public License
43
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
44
 */
45
46
#include "core-config-private.h"
47
48
#if HAVE_FCNTL_H
49
#include <fcntl.h>
50
#endif
51
52
#if HAVE_STDARG_H
53
#include <stdarg.h>
54
#endif
55
56
#if HAVE_CTYPE_H
57
#include <ctype.h>
58
#endif
59
60
#include "ogs-core.h"
61
62
int ogs_vsnprintf(char *str, size_t size, const char *format, va_list ap)
63
2.14M
{
64
2.14M
    int r = -1;
65
66
    /* Microsoft has finally implemented snprintf in Visual Studio 2015.
67
     * In previous versions, I will simulate it as below. */
68
#if defined(_MSC_VER) && _MSC_VER < 1900
69
    ogs_assert(str);
70
71
    if (size != 0)
72
        r = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
73
74
    if (r == -1)
75
        r = _vscprintf(format, ap);
76
#else
77
2.14M
    r = vsnprintf(str, size, format, ap);
78
2.14M
#endif
79
2.14M
    str[size-1] = '\0';
80
81
2.14M
    return r;
82
2.14M
}
83
84
int ogs_snprintf(char *str, size_t size, const char *format, ...)
85
0
{
86
0
    int r;
87
0
    va_list ap;
88
89
0
    va_start(ap, format);
90
0
    r = ogs_vsnprintf(str, size, format, ap);
91
0
    va_end(ap);
92
93
0
    return r;
94
0
}
95
96
char *ogs_vslprintf(char *str, char *last, const char *format, va_list ap)
97
2.14M
{
98
2.14M
    int r = -1;
99
100
2.14M
    ogs_assert(last);
101
102
2.14M
    if (!str)
103
0
        return NULL;
104
105
2.14M
    if (str < last)
106
2.14M
        r = ogs_vsnprintf(str, last - str, format, ap);
107
108
2.14M
    return (str + r);
109
2.14M
}
110
111
char *ogs_slprintf(char *str, char *last, const char *format, ...)
112
2.13M
{
113
2.13M
    char *r;
114
2.13M
    va_list ap;
115
116
2.13M
    va_start(ap, format);
117
2.13M
    r = ogs_vslprintf(str, last, format, ap);
118
2.13M
    va_end(ap);
119
120
2.13M
    return r;
121
2.13M
}
122
123
char *ogs_cpystrn(char *dst, const char *src, size_t dst_size)
124
0
{
125
0
    char *d = dst, *end;
126
127
0
    if (dst_size == 0) {
128
0
        return (dst);
129
0
    }
130
131
0
    if (src) {
132
0
        end = dst + dst_size - 1;
133
134
0
        for (; d < end; ++d, ++src) {
135
0
            if (!(*d = *src)) {
136
0
                return (d);
137
0
            }
138
0
        }
139
0
    }
140
141
0
    *d = '\0';    /* always null terminate */
142
143
0
    return (d);
144
0
}
145
146
/*****************************************
147
 * Memory Pool - Use talloc library
148
 *****************************************/
149
150
char *ogs_talloc_strdup(const void *t, const char *p)
151
0
{
152
0
    char *ptr = NULL;
153
154
0
    ogs_thread_mutex_lock(ogs_mem_get_mutex());
155
156
0
    ptr = talloc_strdup(t, p);
157
0
    ogs_expect(ptr);
158
159
0
    ogs_thread_mutex_unlock(ogs_mem_get_mutex());
160
161
0
    return ptr;
162
0
}
163
164
char *ogs_talloc_strndup(const void *t, const char *p, size_t n)
165
0
{
166
0
    char *ptr = NULL;
167
168
0
    ogs_thread_mutex_lock(ogs_mem_get_mutex());
169
170
0
    ptr = talloc_strndup(t, p, n);
171
0
    ogs_expect(ptr);
172
173
0
    ogs_thread_mutex_unlock(ogs_mem_get_mutex());
174
175
0
    return ptr;
176
0
}
177
178
void *ogs_talloc_memdup(const void *t, const void *p, size_t size)
179
0
{
180
0
    void *ptr = NULL;
181
182
0
    ogs_thread_mutex_lock(ogs_mem_get_mutex());
183
184
0
    ptr = talloc_memdup(t, p, size);
185
0
    ogs_expect(ptr);
186
187
0
    ogs_thread_mutex_unlock(ogs_mem_get_mutex());
188
189
0
    return ptr;
190
0
}
191
192
char *ogs_talloc_asprintf(const void *t, const char *fmt, ...)
193
0
{
194
0
    va_list ap;
195
0
    char *ret;
196
197
0
    ogs_thread_mutex_lock(ogs_mem_get_mutex());
198
199
0
    va_start(ap, fmt);
200
0
    ret = talloc_vasprintf(t, fmt, ap);
201
0
    ogs_expect(ret);
202
0
    va_end(ap);
203
204
0
    ogs_thread_mutex_unlock(ogs_mem_get_mutex());
205
206
0
    return ret;
207
0
}
208
209
char *ogs_talloc_asprintf_append(char *s, const char *fmt, ...)
210
0
{
211
0
    va_list ap;
212
213
0
    ogs_thread_mutex_lock(ogs_mem_get_mutex());
214
215
0
    va_start(ap, fmt);
216
0
    s = talloc_vasprintf_append(s, fmt, ap);
217
0
    ogs_expect(s);
218
0
    va_end(ap);
219
220
0
    ogs_thread_mutex_unlock(ogs_mem_get_mutex());
221
222
0
    return s;
223
0
}
224
225
226
/*****************************************
227
 * Memory Pool - Use pkbuf library
228
 *****************************************/
229
230
char *ogs_strdup_debug(const char *s, const char *file_line)
231
0
{
232
0
    char *res;
233
0
    size_t len;
234
235
0
    if (s == NULL)
236
0
        return NULL;
237
238
0
    len = strlen(s) + 1;
239
0
    res = ogs_memdup_debug(s, len, file_line);
240
0
    if (!res) {
241
0
        ogs_error("ogs_memdup_debug[len:%d] failed", (int)len);
242
0
        return res;
243
0
    }
244
0
    return res;
245
0
}
246
247
char *ogs_strndup_debug(
248
        const char *s, size_t n, const char *file_line)
249
0
{
250
0
    char *res;
251
0
    const char *end;
252
253
0
    if (s == NULL)
254
0
        return NULL;
255
256
0
    end = memchr(s, '\0', n);
257
0
    if (end != NULL)
258
0
        n = end - s;
259
0
    res = ogs_malloc_debug(n + 1, file_line);
260
0
    if (!res) {
261
0
        ogs_error("ogs_malloc_debug[n:%d] failed", (int)n);
262
0
        return res;
263
0
    }
264
0
    memcpy(res, s, n);
265
0
    res[n] = '\0';
266
0
    return res;
267
0
}
268
269
void *ogs_memdup_debug(
270
        const void *m, size_t n, const char *file_line)
271
0
{
272
0
    void *res;
273
274
0
    if (m == NULL)
275
0
        return NULL;
276
277
0
    res = ogs_malloc_debug(n, file_line);
278
0
    if (!res) {
279
0
        ogs_error("ogs_malloc_debug[n:%d] failed", (int)n);
280
0
        return res;
281
0
    }
282
0
    memcpy(res, m, n);
283
0
    return res;
284
0
}
285
286
/*
287
 * char *ogs_msprintf(const char *message, ...)
288
 * char *mstrcatf(char *source, const char *message, ...)
289
 *
290
 * Orcania library
291
 * Copyright 2015-2018 Nicolas Mora <mail@babelouest.org>
292
 * License: LGPL-2.1
293
 *
294
 * https://github.com/babelouest/orcania.git
295
 */
296
char *ogs_msprintf_debug(
297
        const char *file_line, const char *message, ...)
298
0
{
299
0
    va_list argp, argp_cpy;
300
0
    size_t out_len = 0;
301
0
    char *out = NULL;
302
0
    if (message != NULL) {
303
0
        va_start(argp, message);
304
0
        va_copy(argp_cpy, argp); /* We make a copy because
305
                                    in some architectures,
306
                                    vsnprintf can modify argp */
307
0
        out_len = vsnprintf(NULL, 0, message, argp);
308
0
        out = ogs_malloc_debug(out_len + sizeof(char), file_line);
309
0
        if (out == NULL) {
310
0
            va_end(argp);
311
0
            va_end(argp_cpy);
312
0
            return NULL;
313
0
        }
314
0
        vsnprintf(out, (out_len + sizeof(char)), message, argp_cpy);
315
0
        va_end(argp);
316
0
        va_end(argp_cpy);
317
0
    }
318
0
    return out;
319
0
}
320
321
char *ogs_mstrcatf_debug(
322
        char *source, const char *file_line, const char *message, ...)
323
0
{
324
0
    va_list argp, argp_cpy;
325
0
    char *out = NULL, *message_formatted = NULL;
326
0
    size_t message_formatted_len = 0, out_len = 0;
327
328
0
    if (message != NULL) {
329
0
        if (source != NULL) {
330
0
            va_start(argp, message);
331
0
            va_copy(argp_cpy, argp); /* We make a copy because
332
                                        in some architectures,
333
                                        vsnprintf can modify argp */
334
0
            message_formatted_len = vsnprintf(NULL, 0, message, argp);
335
0
            message_formatted = ogs_malloc(message_formatted_len+sizeof(char));
336
0
            if (message_formatted != NULL) {
337
0
                vsnprintf(message_formatted,
338
0
                    (message_formatted_len+sizeof(char)), message, argp_cpy);
339
0
                out = ogs_msprintf_debug(
340
0
                        file_line, "%s%s", source, message_formatted);
341
0
                ogs_free(message_formatted);
342
0
                ogs_free(source);
343
0
            }
344
0
            va_end(argp);
345
0
            va_end(argp_cpy);
346
0
        } else {
347
0
            va_start(argp, message);
348
0
            va_copy(argp_cpy, argp); /* We make a copy because
349
                                        in some architectures,
350
                                        vsnprintf can modify argp */
351
0
            out_len = vsnprintf(NULL, 0, message, argp);
352
0
            out = ogs_malloc_debug(out_len+sizeof(char), file_line);
353
0
            if (out != NULL) {
354
0
                vsnprintf(out, (out_len+sizeof(char)), message, argp_cpy);
355
0
            }
356
0
            va_end(argp);
357
0
            va_end(argp_cpy);
358
0
        }
359
0
    }
360
0
    return out;
361
0
}
362
363
char *ogs_trimwhitespace(char *str)
364
0
{
365
0
    char *end;
366
367
0
    if (str == NULL) {
368
0
        return NULL;
369
0
    } else if (*str == 0) {
370
0
        return str;
371
0
    }
372
373
0
    while (isspace((unsigned char)*str)) str++;
374
375
0
    end = str + strlen(str) - 1;
376
0
    while(end > str && isspace((unsigned char)*end)) {
377
0
        end--;
378
0
    }
379
380
0
    *(end+1) = 0;
381
382
0
    return str;
383
0
}
384
385
char *ogs_left_trimcharacter(char *str, char to_remove)
386
0
{
387
0
    if (str == NULL) {
388
0
        return NULL;
389
0
    } else if (*str == 0) {
390
0
        return str;
391
0
    }
392
393
0
    while(*str == to_remove) str++;
394
395
0
    return str;
396
0
}
397
398
char *ogs_right_trimcharacter(char *str, char to_remove)
399
0
{
400
0
    char *end;
401
402
0
    if (str == NULL) {
403
0
        return NULL;
404
0
    } else if (*str == 0) {
405
0
        return str;
406
0
    }
407
408
0
    end = str + strlen(str) - 1;
409
0
    while(end > str && (*end == to_remove)) {
410
0
        end--;
411
0
    }
412
413
0
    *(end+1) = 0;
414
415
0
    return str;
416
0
}
417
418
char *ogs_trimcharacter(char *str, char to_remove)
419
0
{
420
0
    return ogs_right_trimcharacter(
421
0
            ogs_left_trimcharacter(str, to_remove), to_remove);
422
0
}