/src/libconfig/lib/util.c
Line | Count | Source (jump to first uncovered line) |
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 | 9.58k | { |
66 | 9.58k | void *ptr = malloc(size); |
67 | 9.58k | if(!ptr) |
68 | 0 | libconfig_fatal_error(__libconfig_malloc_failure_message); |
69 | | |
70 | 9.58k | return(ptr); |
71 | 9.58k | } |
72 | | |
73 | | /* ------------------------------------------------------------------------- */ |
74 | | |
75 | | void *libconfig_calloc(size_t nmemb, size_t size) |
76 | 149k | { |
77 | 149k | void *ptr = calloc(nmemb, size); |
78 | 149k | if(!ptr) |
79 | 0 | libconfig_fatal_error(__libconfig_malloc_failure_message); |
80 | | |
81 | 149k | return(ptr); |
82 | 149k | } |
83 | | |
84 | | /* ------------------------------------------------------------------------- */ |
85 | | |
86 | | void *libconfig_realloc(void *ptr, size_t size) |
87 | 59.0k | { |
88 | 59.0k | ptr = realloc(ptr, size); |
89 | 59.0k | if(!ptr) |
90 | 0 | libconfig_fatal_error(__libconfig_malloc_failure_message); |
91 | | |
92 | 59.0k | return(ptr); |
93 | 59.0k | } |
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 | 17.3k | { |
104 | 17.3k | char *endptr; |
105 | 17.3k | int errsave = errno; |
106 | | |
107 | 17.3k | errno = 0; |
108 | 17.3k | *val = strtoll(s, &endptr, base); |
109 | | |
110 | 17.3k | if((base != 10) && (*val > INT32_MAX) && (*val <= UINT32_MAX)) |
111 | 272 | *val = (long long)(int)*val; |
112 | | |
113 | 17.3k | *is_long = ((*val < INT32_MIN) || (*val > INT32_MAX)); |
114 | | |
115 | | /* Check for trailing L's. */ |
116 | 21.4k | while(!errno && *endptr == 'L') |
117 | 4.15k | { |
118 | 4.15k | *is_long = 1; |
119 | 4.15k | ++endptr; |
120 | 4.15k | } |
121 | | |
122 | 17.3k | if(*endptr || errno) |
123 | 12 | { |
124 | 12 | errno = errsave; |
125 | 12 | return(0); /* parse error */ |
126 | 12 | } |
127 | 17.2k | errno = errsave; |
128 | | |
129 | 17.2k | return(1); |
130 | 17.3k | } |
131 | | |
132 | | /* ------------------------------------------------------------------------- */ |
133 | | |
134 | | void libconfig_format_double(double val, int precision, int sci_ok, char *buf, |
135 | | size_t buflen) |
136 | 13.1k | { |
137 | 13.1k | const char *fmt = sci_ok ? "%.*g" : "%.*f"; |
138 | 13.1k | char *p, *q; |
139 | | |
140 | 13.1k | snprintf(buf, buflen - 3, fmt, precision, val); |
141 | | |
142 | | /* Check for exponent. */ |
143 | 13.1k | p = strchr(buf, 'e'); |
144 | 13.1k | if(p) return; |
145 | | |
146 | | /* Check for decimal point. */ |
147 | 13.1k | p = strchr(buf, '.'); |
148 | 13.1k | if(!p) |
149 | 225 | { |
150 | | /* No decimal point. Add trailing ".0". */ |
151 | 225 | strcat(buf, ".0"); |
152 | 225 | } |
153 | 12.9k | else |
154 | 12.9k | { |
155 | | /* Remove any excess trailing 0's after decimal point. */ |
156 | 74.2k | for(q = buf + strlen(buf) - 1; q > p + 1; --q) |
157 | 62.5k | { |
158 | 62.5k | if(*q == '0') |
159 | 61.3k | *q = '\0'; |
160 | 1.18k | else |
161 | 1.18k | break; |
162 | 62.5k | } |
163 | 12.9k | } |
164 | 13.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.16k | { |
173 | 1.16k | static const int num_bits = sizeof(val) * BITS_IN_BYTE; |
174 | 1.16k | char *p = buf + num_bits; |
175 | 1.16k | char *first_bit = NULL; |
176 | | |
177 | 1.16k | *p = '\0'; |
178 | | |
179 | 75.8k | for(int i = 0; i < num_bits; ++i) |
180 | 74.6k | { |
181 | 74.6k | int x = val & 1; |
182 | 74.6k | val >>= 1; |
183 | 74.6k | *(--p) = '0' + x; |
184 | 74.6k | if(!first_bit || x) first_bit = p; |
185 | 74.6k | } |
186 | | |
187 | 1.16k | return(first_bit); |
188 | 1.16k | } |
189 | | |
190 | | /* ------------------------------------------------------------------------- */ |