Coverage Report

Created: 2025-11-09 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libconfig/lib/util.c
Line
Count
Source
1
/* ----------------------------------------------------------------------------
2
   libconfig - A library for processing structured configuration files
3
   Copyright (C) 2005-2025  Mark A Lindner
4
5
   This file is part of libconfig.
6
7
   This library is free software; you can redistribute it and/or
8
   modify it under the terms of the GNU Lesser General Public License
9
   as published by the Free Software Foundation; either version 2.1 of
10
   the License, or (at your option) any later version.
11
12
   This library is distributed in the hope that it will be useful, but
13
   WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
   Lesser General Public License for more details.
16
17
   You should have received a copy of the GNU Library General Public
18
   License along with this library; if not, see
19
   <http://www.gnu.org/licenses/>.
20
   ----------------------------------------------------------------------------
21
*/
22
23
#include "util.h"
24
#include "wincompat.h"
25
26
#include <errno.h>
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30
31
/* ------------------------------------------------------------------------- */
32
33
void libconfig_fatal_error_handler(const char *message)
34
0
{
35
0
  if(posix_write(STDERR_FILENO, (const void *)message, strlen(message))) {}
36
0
  abort();
37
0
}
38
39
/* ------------------------------------------------------------------------- */
40
41
static void (*__libconfig_fatal_error_func)(const char *) =
42
  libconfig_fatal_error_handler;
43
44
static const char *__libconfig_malloc_failure_message =
45
  "\alibconfig: memory allocation failure\n";
46
47
/* ------------------------------------------------------------------------- */
48
49
void libconfig_set_fatal_error_func(void (*func)(const char *))
50
0
{
51
0
  __libconfig_fatal_error_func = (func ? func
52
0
                                  : libconfig_fatal_error_handler);
53
0
}
54
55
/* ------------------------------------------------------------------------- */
56
57
void libconfig_fatal_error(const char *message)
58
0
{
59
0
  __libconfig_fatal_error_func(message);
60
0
}
61
62
/* ------------------------------------------------------------------------- */
63
64
void *libconfig_malloc(size_t size)
65
7.28k
{
66
7.28k
  void *ptr = malloc(size);
67
7.28k
  if(!ptr)
68
0
    libconfig_fatal_error(__libconfig_malloc_failure_message);
69
70
7.28k
  return(ptr);
71
7.28k
}
72
73
/* ------------------------------------------------------------------------- */
74
75
void *libconfig_calloc(size_t nmemb, size_t size)
76
82.6k
{
77
82.6k
  void *ptr = calloc(nmemb, size);
78
82.6k
  if(!ptr)
79
0
    libconfig_fatal_error(__libconfig_malloc_failure_message);
80
81
82.6k
  return(ptr);
82
82.6k
}
83
84
/* ------------------------------------------------------------------------- */
85
86
void *libconfig_realloc(void *ptr, size_t size)
87
27.5k
{
88
27.5k
  ptr = realloc(ptr, size);
89
27.5k
  if(!ptr)
90
0
    libconfig_fatal_error(__libconfig_malloc_failure_message);
91
92
27.5k
  return(ptr);
93
27.5k
}
94
95
/* ------------------------------------------------------------------------- */
96
97
/* Returns 1 on success, 0 on failure. Sets is_long to 1 if value is a
98
   64-bit int, otherwise to 0.
99
*/
100
101
int libconfig_parse_integer(const char *s, int base, long long *val,
102
                            int *is_long)
103
18.7k
{
104
18.7k
  char *endptr;
105
18.7k
  int errsave = errno;
106
107
18.7k
  errno = 0;
108
18.7k
  *val = strtoll(s, &endptr, base);
109
110
18.7k
  if((base != 10) && (*val > INT32_MAX) && (*val <= UINT32_MAX))
111
273
    *val = (long long)(int)*val;
112
113
18.7k
  *is_long = ((*val < INT32_MIN) || (*val > INT32_MAX));
114
115
  /* Check for trailing L's. */
116
23.2k
  while(!errno && *endptr == 'L')
117
4.45k
  {
118
4.45k
    *is_long = 1;
119
4.45k
    ++endptr;
120
4.45k
  }
121
122
18.7k
  if(*endptr || errno)
123
11
  {
124
11
    errno = errsave;
125
11
    return(0);  /* parse error */
126
11
  }
127
18.7k
  errno = errsave;
128
129
18.7k
  return(1);
130
18.7k
}
131
132
/* ------------------------------------------------------------------------- */
133
134
void libconfig_format_double(double val, int precision, int sci_ok, char *buf,
135
                             size_t buflen)
136
10.1k
{
137
10.1k
  const char *fmt = sci_ok ? "%.*g" : "%.*f";
138
10.1k
  char *p, *q;
139
140
10.1k
  snprintf(buf, buflen - 3, fmt, precision, val);
141
142
  /* Check for exponent. */
143
10.1k
  p = strchr(buf, 'e');
144
10.1k
  if(p) return;
145
146
  /* Check for decimal point. */
147
10.1k
  p = strchr(buf, '.');
148
10.1k
  if(!p)
149
286
  {
150
    /* No decimal point. Add trailing ".0". */
151
286
    strcat(buf, ".0");
152
286
  }
153
9.88k
  else
154
9.88k
  {
155
    /* Remove any excess trailing 0's after decimal point. */
156
55.4k
    for(q = buf + strlen(buf) - 1; q > p + 1; --q)
157
46.9k
    {
158
46.9k
      if(*q == '0')
159
45.5k
        *q = '\0';
160
1.35k
      else
161
1.35k
        break;
162
46.9k
    }
163
9.88k
  }
164
10.1k
}
165
166
/* ------------------------------------------------------------------------- */
167
168
/* buf must be at least 65 bytes. Return value is pointer to most significant
169
   nonzero bit, or pointer to the least significant zero bit if value is 0. */
170
171
char *libconfig_format_bin(int64_t val, char *buf)
172
1.67k
{
173
1.67k
  static const int num_bits = sizeof(val) * BITS_IN_BYTE;
174
1.67k
  char *p = buf + num_bits;
175
1.67k
  char *first_bit = NULL;
176
177
1.67k
  *p = '\0';
178
179
108k
  for(int i = 0; i < num_bits; ++i)
180
107k
  {
181
107k
    int x = val & 1;
182
107k
    val >>= 1;
183
107k
    *(--p) = '0' + x;
184
107k
    if(!first_bit || x) first_bit = p;
185
107k
  }
186
187
1.67k
  return(first_bit);
188
1.67k
}
189
190
/* ------------------------------------------------------------------------- */