• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aremmell / libsir / 1291

30 Nov 2023 06:26AM UTC coverage: 95.428% (-0.02%) from 95.452%
1291

Pull #346

gitlab-ci

johnsonjh
Regenerate docs

Signed-off-by: Jeffrey H. Johnson <trnsz@pobox.com>
Pull Request #346: Stricter SPDX compliance

3861 of 4046 relevant lines covered (95.43%)

473326.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.75
/src/sirhelpers.c
1
/*
2
 * sirhelpers.c
3
 *
4
 * Version: 2.2.4
5
 *
6
 * -----------------------------------------------------------------------------
7
 *
8
 * SPDX-License-Identifier: MIT
9
 *
10
 * Copyright (c) 2018-2023 Ryan M. Lederman <lederman@gmail.com>
11
 * Copyright (c) 2018-2023 Jeffrey H. Johnson <trnsz@pobox.com>
12
 *
13
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
14
 * this software and associated documentation files (the "Software"), to deal in
15
 * the Software without restriction, including without limitation the rights to
16
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
17
 * the Software, and to permit persons to whom the Software is furnished to do so,
18
 * subject to the following conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all
21
 * copies or substantial portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
26
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
27
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
 *
30
 * -----------------------------------------------------------------------------
31
 */
32

33
#include "sir/helpers.h"
34
#include "sir/errors.h"
35

36
void __sir_safefree(void** pp) {
404,098✔
37
    if (!pp || !*pp)
404,098✔
38
        return;
96,888✔
39

40
    free(*pp);
289,974✔
41
    *pp = NULL;
289,974✔
42
}
43

44
void _sir_safeclose(int* restrict fd) {
294✔
45
    if (!fd || 0 > *fd)
294✔
46
        return;
×
47

48
    if (-1 == close(*fd))
294✔
49
        (void)_sir_handleerr(errno);
×
50

51
    *fd = -1;
294✔
52
}
53

54
void _sir_safefclose(FILE* restrict* restrict f) {
31,740✔
55
    if (!f || !*f)
31,740✔
56
        return;
13,372✔
57

58
    if (0 != fclose(*f))
15,897✔
59
        (void)_sir_handleerr(errno);
×
60

61
    *f = NULL;
15,897✔
62
}
63

64
bool _sir_validfd(int fd) {
111✔
65
    /** stdin, stdout, stderr use up 0, 1, 2 */
66
    if (2 >= fd)
111✔
67
        return _sir_handleerr(EBADF);
69✔
68

69
#if !defined(__WIN__)
70
    int ret = fcntl(fd, F_GETFL);
42✔
71
#else /* __WIN__ */
72
# if !defined(SIR_MSVCRT_MINGW)
73
    invalparamfn old = _set_thread_local_invalid_parameter_handler(_sir_invalidparameter);
74
# endif
75
    struct _stat st;
76
    int ret = _fstat(fd, &st);
77
# if !defined(SIR_MSVCRT_MINGW)
78
    _set_thread_local_invalid_parameter_handler(old);
79
# endif
80
#endif
81
    return (-1 != ret || EBADF != errno) ? true : _sir_handleerr(errno);
42✔
82
}
83

84
/** Validates a sir_update_config_data structure. */
85
bool __sir_validupdatedata(const sir_update_config_data* data, const char* func,
63,561✔
86
    const char* file, uint32_t line) {
87
    if (!_sir_validptr(data))
63,561✔
88
        return false;
×
89

90
    bool valid = true;
53,462✔
91
    if ((data->fields & SIRU_ALL) == 0U || (data->fields & ~SIRU_ALL) != 0U)
63,553✔
92
        valid = false;
×
93

94
    if (valid && _sir_bittest(data->fields, SIRU_LEVELS))
63,554✔
95
        valid = _sir_validptrnofail(data->levels) &&
2,688✔
96
                _sir_validlevels(*data->levels);
1,344✔
97

98
    if (valid && _sir_bittest(data->fields, SIRU_OPTIONS))
63,546✔
99
        valid = _sir_validptrnofail(data->opts) &&
123,919✔
100
                _sir_validopts(*data->opts);
61,971✔
101

102
    if (valid && _sir_bittest(data->fields, SIRU_SYSLOG_ID))
63,439✔
103
        valid = _sir_validstrnofail(data->sl_identity);
94✔
104

105
    if (valid && _sir_bittest(data->fields, SIRU_SYSLOG_CAT))
63,428✔
106
        valid = _sir_validstrnofail(data->sl_category);
68✔
107

108
    if (!valid) {
63,426✔
109
        SIR_ASSERT(valid);
×
110
        (void)__sir_seterror(_SIR_E_INVALID, func, file, line);
×
111
    }
112

113
    return valid;
53,356✔
114
}
115

116
bool __sir_validlevels(sir_levels levels, const char* func,
36,369✔
117
    const char* file, uint32_t line) {
118
    if ((SIRL_ALL == levels || SIRL_NONE == levels) ||
38,253✔
119
        ((_sir_bittest(levels, SIRL_INFO)           ||
3,493✔
120
         _sir_bittest(levels, SIRL_DEBUG)           ||
2,444✔
121
         _sir_bittest(levels, SIRL_NOTICE)          ||
1,819✔
122
         _sir_bittest(levels, SIRL_WARN)            ||
1,478✔
123
         _sir_bittest(levels, SIRL_ERROR)           ||
998✔
124
         _sir_bittest(levels, SIRL_CRIT)            ||
498✔
125
         _sir_bittest(levels, SIRL_ALERT)           ||
323✔
126
         _sir_bittest(levels, SIRL_EMERG))          &&
2,281✔
127
         ((levels & ~SIRL_ALL) == 0U)))
128
         return true;
30,671✔
129

130
    _sir_selflog("invalid levels: %04"PRIx16, levels);
99✔
131
    return __sir_seterror(_SIR_E_LEVELS, func, file, line);
104✔
132
}
133

134
bool __sir_validlevel(sir_level level, const char* func, const char* file,
4,371,864✔
135
    uint32_t line) {
136
    if (SIRL_INFO   == level || SIRL_DEBUG == level ||
4,371,864✔
137
        SIRL_NOTICE == level || SIRL_WARN  == level ||
7,642✔
138
        SIRL_ERROR  == level || SIRL_CRIT  == level ||
4,567✔
139
        SIRL_ALERT  == level || SIRL_EMERG == level)
1,529✔
140
        return true;
4,317,845✔
141

142
    _sir_selflog("invalid level: %04"PRIx16, level);
22✔
143
    return __sir_seterror(_SIR_E_LEVELS, func, file, line);
23✔
144
}
145

146
bool __sir_validopts(sir_options opts, const char* func, const char* file,
97,200✔
147
    uint32_t line) {
148
    if ((SIRO_ALL == opts || SIRO_MSGONLY == opts) ||
151,942✔
149
        ((_sir_bittest(opts, SIRO_NOTIME)          ||
104,396✔
150
         _sir_bittest(opts, SIRO_NOHOST)           ||
47,183✔
151
         _sir_bittest(opts, SIRO_NOLEVEL)          ||
731✔
152
         _sir_bittest(opts, SIRO_NONAME)           ||
594✔
153
         _sir_bittest(opts, SIRO_NOMSEC)           ||
470✔
154
         _sir_bittest(opts, SIRO_NOPID)            ||
350✔
155
         _sir_bittest(opts, SIRO_NOTID)            ||
198✔
156
         _sir_bittest(opts, SIRO_NOHDR))           &&
92✔
157
         ((opts & ~(SIRO_MSGONLY | SIRO_NOHDR)) == 0U)))
64,899✔
158
         return true;
81,606✔
159

160
    _sir_selflog("invalid options: %08"PRIx32, opts);
308✔
161
    return __sir_seterror(_SIR_E_OPTIONS, func, file, line);
337✔
162
}
163

164
bool __sir_validtextattr(sir_textattr attr, const char* func, const char* file,
88,243✔
165
    uint32_t line) {
166
    switch(attr) {
88,243✔
167
        case SIRTA_NORMAL:
75,040✔
168
        case SIRTA_BOLD:
169
        case SIRTA_DIM:
170
        case SIRTA_EMPH:
171
        case SIRTA_ULINE:
172
            return true;
75,040✔
173
        default: {
23✔
174
            _sir_selflog("invalid text attr: %d", attr);
22✔
175
            return __sir_seterror(_SIR_E_TEXTATTR, func, file, line);
23✔
176
        }
177
    }
178
}
179

180
bool __sir_validtextcolor(sir_colormode mode, sir_textcolor color, const char* func,
176,417✔
181
    const char* file, uint32_t line) {
182
    bool valid = false;
150,060✔
183
    switch (mode) {
176,417✔
184
        case SIRCM_16:
152,129✔
185
            /* in 16-color mode:
186
             * compare to 30..37, 39, 40..47, 49, 90..97, 100..107. */
187
            valid = SIRTC_DEFAULT == color ||
152,129✔
188
                    (color >= 30U && color <= 37U) || color == 39U ||
152,129✔
189
                    (color >= 40U && color <= 47U) || color == 49U ||
69,490✔
190
                    (color >= 90U && color <= 97U) || (color >= 100U && color <= 107U);
257,880✔
191
            break;
128,940✔
192
        case SIRCM_256:
12,098✔
193
            /* in 256-color mode: compare to 0..255. sir_textcolor is unsigned,
194
             * so only need to ensure it's <= 255. */
195
            valid = SIRTC_DEFAULT == color || color <= 255U;
12,098✔
196
            break;
12,098✔
197
        case SIRCM_RGB: {
12,190✔
198
            /* in RGB-color mode: mask and compare to 0x00ffffff. */
199
            valid = SIRTC_DEFAULT == color || ((color & 0xff000000U) == 0U);
12,190✔
200
            break;
12,190✔
201
        }
202
        case SIRCM_INVALID: // GCOVR_EXCL_START
203
        default:
204
            valid = false;
205
            break;
206
    } // GCOVR_EXCL_STOP
207

208
    if (!valid) {
153,228✔
209
        _sir_selflog("invalid text color for mode %d %08"PRIx32" (%"PRIu32")",
22✔
210
            mode, color, color);
211
        (void)__sir_seterror(_SIR_E_TEXTCOLOR, func, file, line);
23✔
212
    }
213

214
    return valid;
176,417✔
215
}
216

217
bool __sir_validcolormode(sir_colormode mode, const char* func, const char* file,
89,239✔
218
    uint32_t line) {
219
    switch (mode) {
89,239✔
220
        case SIRCM_16:
75,906✔
221
        case SIRCM_256:
222
        case SIRCM_RGB:
223
            return true;
75,906✔
224
        case SIRCM_INVALID:
23✔
225
        default: {
226
            _sir_selflog("invalid color mode: %d", mode);
22✔
227
            return __sir_seterror(_SIR_E_COLORMODE, func, file, line);
23✔
228
        }
229
    }
230
}
231

232
int _sir_strncpy(char* restrict dest, size_t destsz, const char* restrict src,
4,180,295✔
233
    size_t count) {
234
    if (_sir_validptr(dest) && _sir_validstr(src)) {
4,180,295✔
235
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
236
        int ret = strncpy_s(dest, destsz, src, count);
237
        if (0 != ret) {
238
            (void)_sir_handleerr(ret);
239
            return -1;
240
        }
241
        return 0;
242
#else
243
        SIR_UNUSED(count);
244
        size_t cpy = strlcpy(dest, src, destsz);
4,155,240✔
245
        SIR_ASSERT_UNUSED(cpy < destsz, cpy);
4,171,947✔
246
        return 0;
4,180,282✔
247
#endif
248
    }
249

250
    return -1;
11✔
251
}
252

253
int _sir_strncat(char* restrict dest, size_t destsz, const char* restrict src,
28,181,796✔
254
    size_t count) {
255
    if (_sir_validptr(dest) && _sir_validstr(src)) {
28,181,796✔
256
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
257
        int ret = strncat_s(dest, destsz, src, count);
258
        if (0 != ret) {
259
            (void)_sir_handleerr(ret);
260
            return -1;
261
        }
262
        return 0;
263
#else
264
        SIR_UNUSED(count);
265
        size_t cat = strlcat(dest, src, destsz);
27,991,930✔
266
        SIR_ASSERT_UNUSED(cat < destsz, cat);
28,116,041✔
267
        return 0;
28,179,538✔
268
#endif
269
    }
270

271
    return -1;
2,542✔
272
}
273

274
int _sir_fopen(FILE* restrict* restrict streamptr, const char* restrict filename,
15,952✔
275
    const char* restrict mode) {
276
    if (_sir_validptrptr(streamptr) && _sir_validstr(filename) && _sir_validstr(mode)) {
15,952✔
277
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
278
        int ret = fopen_s(streamptr, filename, mode);
279
        if (0 != ret) {
280
            (void)_sir_handleerr(ret);
281
            return -1;
282
        }
283
        return 0;
284
#else
285
        *streamptr = fopen(filename, mode);
15,952✔
286
        if (!*streamptr) {
15,952✔
287
            (void)_sir_handleerr(errno);
95✔
288
            return -1;
95✔
289
        }
290
        return 0;
13,380✔
291
#endif
292
    }
293

294
    return -1;
×
295
}
296

297
bool _sir_getchar(char* input) {
1✔
298
#if defined(__WIN__)
299
# if defined(__EMBARCADEROC__) && (__clang_major__ < 15)
300
    if (input)
301
        *input = (char)getch();
302
# else
303
    if (input)
304
        *input = (char)_getch();
305
# endif
306
     return true;
307
#else /* !__WIN__ */
308
    struct termios cur = {0};
1✔
309
    if (0 != tcgetattr(STDIN_FILENO, &cur))
1✔
310
        return _sir_handleerr(errno);
×
311

312
    struct termios new = cur;
1✔
313
    new.c_lflag &= ~(ICANON | ECHO);
1✔
314

315
    if (0 != tcsetattr(STDIN_FILENO, TCSANOW, &new))
1✔
316
        return _sir_handleerr(errno);
×
317

318
    int ch = getchar();
1✔
319

320
    if (NULL != input)
1✔
321
        *input = (char)ch;
1✔
322

323
    return 0 == tcsetattr(STDIN_FILENO, TCSANOW, &cur) ? true
1✔
324
        : _sir_handleerr(errno);
1✔
325
#endif
326
}
327

328
char* _sir_strremove(char *str, const char *sub) {
69✔
329
    if (!str)
69✔
330
        return NULL;
20✔
331

332
    if (!sub)
46✔
333
        return str;
20✔
334

335
    const char* p;
336
    char* r;
337
    char* q;
338

339
    if (*sub && (q = r = strstr(str, sub)) != NULL) {
23✔
340
        size_t len = strnlen(sub, strlen(str));
23✔
341

342
        while ((r = strstr(p = r + len, sub)) != NULL)
23✔
343
            while (p < r)
×
344
                *q++ = *p++;
×
345

346
        while ((*q++ = *p++) != '\0');
46✔
347
    }
348

349
    return str;
20✔
350
}
351

352
char* _sir_strsqueeze(char *str) {
46✔
353
    if (!str)
46✔
354
        return NULL;
20✔
355

356
    unsigned long j;
357

358
    for (unsigned long i = j = 0; str[i]; ++i)
759✔
359
        if ((i > 0 && !isspace((unsigned char)(str[i - 1])))
736✔
360
                   || !isspace((unsigned char)(str[i])))
391✔
361
            str[j++] = str[i];
414✔
362

363
    str[j] = '\0';
23✔
364

365
    return str;
23✔
366
}
367

368
char* _sir_strredact(char *str, const char *sub, const char c) {
207✔
369
    if (!str)
207✔
370
        return NULL;
20✔
371

372
    if (!sub)
184✔
373
        return str;
20✔
374

375
    char *p = strstr(str, sub);
161✔
376

377
    if (!c || !p)
161✔
378
        return str;
60✔
379

380
    (void)memset(p, c, strnlen(sub, strlen(str)));
92✔
381

382
    return _sir_strredact(str, sub, c);
92✔
383
}
384

385
char* _sir_strreplace(char *str, const char c, const char n) {
92✔
386
    if (!str)
92✔
387
        return NULL;
20✔
388

389
    char *i = str;
60✔
390

391
    if (!c || !n)
69✔
392
        return str;
40✔
393

394
    while ((i = strchr(i, c)) != NULL)
46✔
395
        *i++ = n;
23✔
396

397
    return str;
20✔
398
}
399

400
size_t _sir_strcreplace(char *str, const char c, const char n, int32_t max) {
115✔
401
    char*  i   = str;
100✔
402
    size_t cnt = 0;
100✔
403

404
    if (!str || !c || !n || !max)
115✔
405
        return cnt;
80✔
406

407
    while (cnt < (size_t)max && (i = strchr(i, c)) != NULL) {
46✔
408
        *i++ = n;
23✔
409
        cnt++;
23✔
410
    }
411

412
    return cnt;
20✔
413
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc