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

aremmell / libsir / 1147

18 Oct 2023 06:52AM UTC coverage: 95.477% (+0.06%) from 95.414%
1147

Pull #340

gitlab-ci

johnsonjh
Appease Doxygen linter

Signed-off-by: Jeffrey H. Johnson <trnsz@pobox.com>
Pull Request #340: Add in-place string mangling utilities

99 of 99 new or added lines in 2 files covered. (100.0%)

3863 of 4046 relevant lines covered (95.48%)

503111.98 hits per line

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

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

30
void __sir_safefree(void** pp) {
892,993✔
31
    if (!pp || !*pp)
892,993✔
32
        return;
234,210✔
33

34
    free(*pp);
616,258✔
35
    *pp = NULL;
616,258✔
36
}
37

38
void _sir_safeclose(int* restrict fd) {
247✔
39
    if (!fd || 0 > *fd)
247✔
40
        return;
×
41

42
    if (-1 == close(*fd))
247✔
43
        (void)_sir_handleerr(errno);
×
44

45
    *fd = -1;
247✔
46
}
47

48
void _sir_safefclose(FILE* restrict* restrict f) {
77,512✔
49
    if (!f || !*f)
77,512✔
50
        return;
32,571✔
51

52
    if (0 != fclose(*f))
38,783✔
53
        (void)_sir_handleerr(errno);
×
54

55
    *f = NULL;
38,783✔
56
}
57

58
bool _sir_validfd(int fd) {
111✔
59
    /** stdin, stdout, stderr use up 0, 1, 2 */
60
    if (2 >= fd)
111✔
61
        return _sir_handleerr(EBADF);
69✔
62

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

78
/** Validates a sir_update_config_data structure. */
79
bool __sir_validupdatedata(const sir_update_config_data* data, const char* func,
154,232✔
80
    const char* file, uint32_t line) {
81
    if (!_sir_validptr(data))
154,232✔
82
        return false;
×
83

84
    bool valid = true;
130,009✔
85
    if ((data->fields & SIRU_ALL) == 0U || (data->fields & ~SIRU_ALL) != 0U)
154,272✔
86
        valid = false;
×
87

88
    if (valid && _sir_bittest(data->fields, SIRU_LEVELS))
154,267✔
89
        valid = _sir_validptrnofail(data->levels) &&
2,678✔
90
                _sir_validlevels(*data->levels);
1,339✔
91

92
    if (valid && _sir_bittest(data->fields, SIRU_OPTIONS))
154,258✔
93
        valid = _sir_validptrnofail(data->opts) &&
305,158✔
94
                _sir_validopts(*data->opts);
152,613✔
95

96
    if (valid && _sir_bittest(data->fields, SIRU_SYSLOG_ID))
154,053✔
97
        valid = _sir_validstrnofail(data->sl_identity);
116✔
98

99
    if (valid && _sir_bittest(data->fields, SIRU_SYSLOG_CAT))
154,047✔
100
        valid = _sir_validstrnofail(data->sl_category);
92✔
101

102
    if (!valid) {
154,029✔
103
        SIR_ASSERT(valid);
3✔
104
        (void)__sir_seterror(_SIR_E_INVALID, func, file, line);
2✔
105
    }
106

107
    return valid;
129,803✔
108
}
109

110
bool __sir_validlevels(sir_levels levels, const char* func,
82,136✔
111
    const char* file, uint32_t line) {
112
    if ((SIRL_ALL == levels || SIRL_NONE == levels) ||
84,034✔
113
        ((_sir_bittest(levels, SIRL_INFO)           ||
3,530✔
114
         _sir_bittest(levels, SIRL_DEBUG)           ||
2,486✔
115
         _sir_bittest(levels, SIRL_NOTICE)          ||
1,868✔
116
         _sir_bittest(levels, SIRL_WARN)            ||
1,531✔
117
         _sir_bittest(levels, SIRL_ERROR)           ||
1,042✔
118
         _sir_bittest(levels, SIRL_CRIT)            ||
503✔
119
         _sir_bittest(levels, SIRL_ALERT)           ||
310✔
120
         _sir_bittest(levels, SIRL_EMERG))          &&
2,296✔
121
         ((levels & ~SIRL_ALL) == 0U)))
122
         return true;
69,070✔
123

124
    _sir_selflog("invalid levels: %04"PRIx16, levels);
99✔
125
    return __sir_seterror(_SIR_E_LEVELS, func, file, line);
104✔
126
}
127

128
bool __sir_validlevel(sir_level level, const char* func, const char* file,
4,596,670✔
129
    uint32_t line) {
130
    if (SIRL_INFO   == level || SIRL_DEBUG == level ||
4,596,670✔
131
        SIRL_NOTICE == level || SIRL_WARN  == level ||
7,642✔
132
        SIRL_ERROR  == level || SIRL_CRIT  == level ||
4,567✔
133
        SIRL_ALERT  == level || SIRL_EMERG == level)
1,529✔
134
        return true;
4,506,893✔
135

136
    _sir_selflog("invalid level: %04"PRIx16, level);
22✔
137
    return __sir_seterror(_SIR_E_LEVELS, func, file, line);
23✔
138
}
139

140
bool __sir_validopts(sir_options opts, const char* func, const char* file,
233,557✔
141
    uint32_t line) {
142
    if ((SIRO_ALL == opts || SIRO_MSGONLY == opts) ||
364,750✔
143
        ((_sir_bittest(opts, SIRO_NOTIME)          ||
252,281✔
144
         _sir_bittest(opts, SIRO_NOHOST)           ||
115,092✔
145
         _sir_bittest(opts, SIRO_NOLEVEL)          ||
692✔
146
         _sir_bittest(opts, SIRO_NONAME)           ||
558✔
147
         _sir_bittest(opts, SIRO_NOMSEC)           ||
455✔
148
         _sir_bittest(opts, SIRO_NOPID)            ||
339✔
149
         _sir_bittest(opts, SIRO_NOTID)            ||
195✔
150
         _sir_bittest(opts, SIRO_NOHDR))           &&
92✔
151
         ((opts & ~(SIRO_MSGONLY | SIRO_NOHDR)) == 0U)))
155,502✔
152
         return true;
196,366✔
153

154
    _sir_selflog("invalid options: %08"PRIx32, opts);
307✔
155
    return __sir_seterror(_SIR_E_OPTIONS, func, file, line);
340✔
156
}
157

158
bool __sir_validtextattr(sir_textattr attr, const char* func, const char* file,
179,443✔
159
    uint32_t line) {
160
    switch(attr) {
179,443✔
161
        case SIRTA_NORMAL:
151,840✔
162
        case SIRTA_BOLD:
163
        case SIRTA_DIM:
164
        case SIRTA_EMPH:
165
        case SIRTA_ULINE:
166
            return true;
151,840✔
167
        default: {
23✔
168
            _sir_selflog("invalid text attr: %d", attr);
22✔
169
            return __sir_seterror(_SIR_E_TEXTATTR, func, file, line);
23✔
170
        }
171
    }
172
}
173

174
bool __sir_validtextcolor(sir_colormode mode, sir_textcolor color, const char* func,
358,817✔
175
    const char* file, uint32_t line) {
176
    bool valid = false;
303,660✔
177
    switch (mode) {
358,817✔
178
        case SIRCM_16:
334,529✔
179
            /* in 16-color mode:
180
             * compare to 30..37, 39, 40..47, 49, 90..97, 100..107. */
181
            valid = SIRTC_DEFAULT == color ||
334,529✔
182
                    (color >= 30U && color <= 37U) || color == 39U ||
334,529✔
183
                    (color >= 40U && color <= 47U) || color == 49U ||
146,290✔
184
                    (color >= 90U && color <= 97U) || (color >= 100U && color <= 107U);
565,080✔
185
            break;
282,540✔
186
        case SIRCM_256:
12,098✔
187
            /* in 256-color mode: compare to 0..255. sir_textcolor is unsigned,
188
             * so only need to ensure it's <= 255. */
189
            valid = SIRTC_DEFAULT == color || color <= 255U;
12,098✔
190
            break;
12,098✔
191
        case SIRCM_RGB: {
12,190✔
192
            /* in RGB-color mode: mask and compare to 0x00ffffff. */
193
            valid = SIRTC_DEFAULT == color || ((color & 0xff000000U) == 0U);
12,190✔
194
            break;
12,190✔
195
        }
196
        case SIRCM_INVALID: // GCOVR_EXCL_START
197
        default:
198
            valid = false;
199
            break;
200
    } // GCOVR_EXCL_STOP
201

202
    if (!valid) {
306,828✔
203
        _sir_selflog("invalid text color for mode %d %08"PRIx32" (%"PRIu32")",
22✔
204
            mode, color, color);
205
        (void)__sir_seterror(_SIR_E_TEXTCOLOR, func, file, line);
23✔
206
    }
207

208
    return valid;
358,817✔
209
}
210

211
bool __sir_validcolormode(sir_colormode mode, const char* func, const char* file,
180,439✔
212
    uint32_t line) {
213
    switch (mode) {
180,439✔
214
        case SIRCM_16:
152,706✔
215
        case SIRCM_256:
216
        case SIRCM_RGB:
217
            return true;
152,706✔
218
        case SIRCM_INVALID:
23✔
219
        default: {
220
            _sir_selflog("invalid color mode: %d", mode);
22✔
221
            return __sir_seterror(_SIR_E_COLORMODE, func, file, line);
23✔
222
        }
223
    }
224
}
225

226
int _sir_strncpy(char* restrict dest, size_t destsz, const char* restrict src,
4,278,263✔
227
    size_t count) {
228
    if (_sir_validptr(dest) && _sir_validstr(src)) {
4,278,263✔
229
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
230
        int ret = strncpy_s(dest, destsz, src, count);
231
        if (0 != ret) {
232
            (void)_sir_handleerr(ret);
233
            return -1;
234
        }
235
        return 0;
236
#else
237
        SIR_UNUSED(count);
238
        size_t cpy = strlcpy(dest, src, destsz);
4,238,838✔
239
        SIR_ASSERT_UNUSED(cpy < destsz, cpy);
4,265,127✔
240
        return 0;
4,278,249✔
241
#endif
242
    }
243

244
    return -1;
10✔
245
}
246

247
int _sir_strncat(char* restrict dest, size_t destsz, const char* restrict src,
29,481,562✔
248
    size_t count) {
249
    if (_sir_validptr(dest) && _sir_validstr(src)) {
29,481,562✔
250
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
251
        int ret = strncat_s(dest, destsz, src, count);
252
        if (0 != ret) {
253
            (void)_sir_handleerr(ret);
254
            return -1;
255
        }
256
        return 0;
257
#else
258
        SIR_UNUSED(count);
259
        size_t cat = strlcat(dest, src, destsz);
29,095,584✔
260
        SIR_ASSERT_UNUSED(cat < destsz, cat);
29,346,715✔
261
        return 0;
29,474,793✔
262
#endif
263
    }
264

265
    return -1;
6,920✔
266
}
267

268
int _sir_fopen(FILE* restrict* restrict streamptr, const char* restrict filename,
38,838✔
269
    const char* restrict mode) {
270
    if (_sir_validptrptr(streamptr) && _sir_validstr(filename) && _sir_validstr(mode)) {
38,838✔
271
#if defined(__HAVE_STDC_SECURE_OR_EXT1__)
272
        int ret = fopen_s(streamptr, filename, mode);
273
        if (0 != ret) {
274
            (void)_sir_handleerr(ret);
275
            return -1;
276
        }
277
        return 0;
278
#else
279
        *streamptr = fopen(filename, mode);
38,838✔
280
        if (!*streamptr) {
38,838✔
281
            (void)_sir_handleerr(errno);
95✔
282
            return -1;
95✔
283
        }
284
        return 0;
32,579✔
285
#endif
286
    }
287

288
    return -1;
×
289
}
290

291
bool _sir_getchar(char* input) {
1✔
292
#if defined(__WIN__)
293
# if defined(__EMBARCADEROC__)
294
    if (input)
295
        *input = (char)getch();
296
# else
297
    if (input)
298
        *input = (char)_getch();
299
# endif
300
     return true;
301
#else /* !__WIN__ */
302
    struct termios cur = {0};
1✔
303
    if (0 != tcgetattr(STDIN_FILENO, &cur))
1✔
304
        return _sir_handleerr(errno);
×
305

306
    struct termios new = cur;
1✔
307
    new.c_lflag &= ~(ICANON | ECHO);
1✔
308

309
    if (0 != tcsetattr(STDIN_FILENO, TCSANOW, &new))
1✔
310
        return _sir_handleerr(errno);
×
311

312
    int ch = getchar();
1✔
313

314
    if (NULL != input)
1✔
315
        *input = (char)ch;
1✔
316

317
    return 0 == tcsetattr(STDIN_FILENO, TCSANOW, &cur) ? true
1✔
318
        : _sir_handleerr(errno);
1✔
319
#endif
320
}
321

322
char* _sir_strremove(char *str, const char *sub) {
69✔
323
  if (!str)
69✔
324
      return NULL;
20✔
325

326
  if (!sub)
46✔
327
      return str;
20✔
328

329
  const char* p;
330
  char* r;
331
  char* q;
332

333
  if (*sub && (q = r = strstr(str, sub)) != NULL) {
23✔
334
      size_t len = strnlen(sub, strlen(str));
23✔
335

336
      while ((r = strstr(p = r + len, sub)) != NULL)
23✔
337
          while (p < r)
×
338
              *q++ = *p++;
×
339

340
      while ((*q++ = *p++) != '\0');
46✔
341
  }
342

343
  return str;
20✔
344
}
345

346
char* _sir_strsqueeze(char *str) {
46✔
347
  if (!str)
46✔
348
      return NULL;
20✔
349

350
  unsigned long j;
351

352
  for (unsigned long i = j = 0; str[i]; ++i)
759✔
353
      if ((i > 0 && !isspace((unsigned char)(str[i - 1])))
736✔
354
                 || !isspace((unsigned char)(str[i])))
391✔
355
          str[j++] = str[i];
414✔
356

357
  str[j] = '\0';
23✔
358

359
  return str;
23✔
360
}
361

362
char* _sir_strredact(char *str, const char *sub, const char c) {
207✔
363
  if (!str)
207✔
364
      return NULL;
20✔
365

366
  if (!sub)
184✔
367
      return str;
20✔
368

369
  char *p = strstr(str, sub);
161✔
370

371
  if (!c || !p)
161✔
372
      return str;
60✔
373

374
  (void)memset(p, c, strnlen(sub, strlen(str)));
92✔
375

376
  return _sir_strredact(str, sub, c);
92✔
377
}
378

379
char* _sir_strreplace(char *str, const char c, const char n) {
92✔
380
  if (!str)
92✔
381
      return NULL;
20✔
382

383
  char *i = str;
60✔
384

385
  if (!c || !n)
69✔
386
      return str;
40✔
387

388
  while ((i = strchr(i, c)) != NULL)
46✔
389
      *i++ = n;
23✔
390

391
  return str;
20✔
392
}
393

394
size_t _sir_strcreplace(char *str, const char c, const char n, int32_t max) {
115✔
395
  char*  i   = str;
100✔
396
  size_t cnt = 0;
100✔
397

398
  if (!str || !c || !n || !max)
115✔
399
      return cnt;
80✔
400

401
  while (cnt < (size_t)max && (i = strchr(i, c)) != NULL) {
46✔
402
      *i++ = n;
23✔
403
      cnt++;
23✔
404
  }
405

406
  return cnt;
20✔
407
}
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