Branch data Line data Source code
1 : : /*
2 : : * International Chemical Identifier (InChI)
3 : : * Version 1
4 : : * Software version 1.07
5 : : * April 30, 2024
6 : : *
7 : : * MIT License
8 : : *
9 : : * Copyright (c) 2024 IUPAC and InChI Trust
10 : : *
11 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
12 : : * of this software and associated documentation files (the "Software"), to deal
13 : : * in the Software without restriction, including without limitation the rights
14 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 : : * copies of the Software, and to permit persons to whom the Software is
16 : : * furnished to do so, subject to the following conditions:
17 : : *
18 : : * The above copyright notice and this permission notice shall be included in all
19 : : * copies or substantial portions of the Software.
20 : : *
21 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 : : * SOFTWARE.
28 : : *
29 : : * The InChI library and programs are free software developed under the
30 : : * auspices of the International Union of Pure and Applied Chemistry (IUPAC).
31 : : * Originally developed at NIST.
32 : : * Modifications and additions by IUPAC and the InChI Trust.
33 : : * Some portions of code were developed/changed by external contributors
34 : : * (either contractor or volunteer) which are listed in the file
35 : : * 'External-contributors' included in this distribution.
36 : : *
37 : : * info@inchi-trust.org
38 : : *
39 : : */
40 : :
41 : : /* djb-rwth: implementation of missing bounds - checking functions */
42 : :
43 : : #include <stdio.h>
44 : : #include <stdlib.h>
45 : : #include <string.h>
46 : : #include <errno.h>
47 : : #include "ichirvrs.h"
48 : : #include <math.h>
49 : : #include "bcf_s.h"
50 : :
51 : : #define STB_SPRINTF_IMPLEMENTATION
52 : : #include "stb_sprintf.h"
53 : :
54 : : static int dbl2int_f(double dblinp, int fwidth, int ndecpl, char* str);
55 : : static int dbl2int_e(double dblinp, int fwidth, int ndecpl, char* str);
56 : : static int dbl2int_g(double dblinp, int fwidth, int ndecpl, char* str);
57 : :
58 : 0 : int max_3(int a, int b, int c)
59 : : {
60 [ # # # # ]: 0 : if ((a > b) && (a > c))
61 : 0 : return a;
62 [ # # # # ]: 0 : else if ((b > a) && (b > c))
63 : 0 : return b;
64 : : else
65 : 0 : return c;
66 : : }
67 : :
68 : 0 : int memcpy_custom(char** dst, char* src, unsigned long long len)
69 : : {
70 : 0 : char* dst_local = (char*)calloc(len, sizeof(char));
71 : 0 : char* src_local = src;
72 : : int k;
73 : :
74 [ # # ]: 0 : if (dst_local)
75 : : {
76 : 0 : *dst = dst_local;
77 [ # # ]: 0 : for (k = 0; k < len; k++)
78 : : {
79 : 0 : dst_local[k] = src_local[k];
80 : : }
81 : : }
82 : : else
83 : : {
84 : 0 : free(dst_local);
85 : 0 : free(src_local);
86 : 0 : return RI_ERR_ALLOC;
87 : : }
88 : 0 : return 0;
89 : : }
90 : :
91 : : /* djb-rwth: main sprintf emulation for avoiding locales */
92 : 0 : int dbl2int(char* str, int fwidth, int ndecpl, char dbl_flag, double dblinp)
93 : : {
94 [ # # # # ]: 0 : switch (dbl_flag)
95 : : {
96 : 0 : case 'f':
97 : : case 'F':
98 : 0 : return dbl2int_f(dblinp, fwidth, ndecpl, str);
99 : : break;
100 : 0 : case 'e':
101 : : case 'E':
102 : 0 : return dbl2int_e(dblinp, fwidth, ndecpl, str);
103 : : break;
104 : 0 : case 'g':
105 : : case 'G':
106 : 0 : return dbl2int_g(dblinp, fwidth, ndecpl, str);
107 : : break;
108 : 0 : default:
109 : 0 : printf("dbl2int format flag not valid.\n");
110 : 0 : break;
111 : : }
112 : :
113 : 0 : return -1;
114 : : }
115 : :
116 : : /* djb-rwth: sprintf("%X.Yf", arg) emulation */
117 : 0 : static int dbl2int_f(double dblinp, int fwidth, int ndecpl, char* str)
118 : : {
119 : : double dec_part, dblinpabs;
120 : : char* intpl_str;
121 : : const char* dblinp_sign;
122 : 0 : int fw_int, fw_dec, i, fw_real, ret = 0;
123 : 0 : long long int intpl, decpl = 0, intpl_size;
124 : :
125 [ # # ]: 0 : dblinp_sign = (dblinp >= 0.0) ? "" : "-";
126 : 0 : dblinpabs = fabsl(dblinp);
127 : 0 : intpl = (long long int)trunc(dblinpabs);
128 : 0 : dec_part = dblinpabs - intpl;
129 [ # # ]: 0 : fw_int = (int)log10((double)intpl > 0 ? (double)intpl : 1.0) + 1 + !strcmp(dblinp_sign, "-");
130 : 0 : intpl_size = ((long long int)fw_int + 3) * sizeof(unsigned long long int);
131 : 0 : intpl_str = (char*)inchi_malloc(intpl_size);
132 : :
133 [ # # ]: 0 : if (ndecpl > 0)
134 : : {
135 : 0 : fw_dec = (ndecpl > 9) ? 9 : ndecpl;
136 : : }
137 [ # # ]: 0 : else if (ndecpl == 0)
138 : : {
139 : 0 : fw_dec = 0;
140 : : }
141 : : else
142 : : {
143 : 0 : fw_dec = 6;
144 : : }
145 : 0 : fw_real = fw_int + (ndecpl != 0) + fw_dec;
146 : :
147 [ # # ]: 0 : if (ndecpl)
148 : : {
149 : 0 : fw_int += (fwidth - fw_real > 0) ? fwidth - fw_real : 0;
150 : :
151 [ # # ]: 0 : for (i = 0; i < fw_dec; i++)
152 : : {
153 : 0 : dec_part *= 10;
154 : 0 : decpl = 10 * decpl + (long long int)dec_part;
155 : 0 : dec_part = dec_part - trunc(dec_part);
156 : : }
157 : :
158 : 0 : decpl += (long long int)round(dec_part);
159 [ # # # # ]: 0 : if (((int)log10((double)decpl > 0 ? (double)decpl : 1.0) + 1) > fw_dec)
160 : : {
161 : 0 : intpl++;
162 : 0 : decpl -= (int)pow(10, fw_dec);
163 : : }
164 : :
165 [ # # ]: 0 : if (intpl_str)
166 : : {
167 : 0 : sprintf(intpl_str, "%s%lld", dblinp_sign, intpl); /* djb-rwth: ignoring LLVM warning */
168 : : }
169 : : else
170 : : {
171 : 0 : return -1;
172 : : }
173 : :
174 : 0 : ret = sprintf(str, "%*s.%0*lld", fw_int, intpl_str, fw_dec, decpl); /* djb-rwth: ignoring LLVM warning */
175 [ # # ]: 0 : inchi_free(intpl_str);
176 : 0 : return ret;
177 : : }
178 : : else
179 : : {
180 : 0 : intpl = (long long int)round(dblinp);
181 : :
182 [ # # ]: 0 : inchi_free(intpl_str);
183 : 0 : return sprintf(str, "%*lld", fw_real, intpl); /* djb-rwth: ignoring LLVM warning */
184 : : }
185 : : }
186 : :
187 : : /* djb-rwth: sprintf("%X.Ye", arg) emulation */
188 : 0 : static int dbl2int_e(double dblinp, int fwidth, int ndecpl, char* str)
189 : : {
190 : : double dec_part, dblinpabs;
191 : 0 : int expnr = 0, fw_int, fw_dec, fw_real, dblinp_sign, nintpl, i, j;
192 : 0 : long long int intpl = 0, decpl = 0;
193 : :
194 [ # # ]: 0 : dblinp_sign = (dblinp >= 0.0) ? 1 : -1;
195 : 0 : dblinpabs = fabsl(dblinp);
196 : 0 : intpl = (long long int)trunc(dblinpabs);
197 [ # # ]: 0 : nintpl = (int)log10((double)intpl > 0 ? (double)intpl : 1) + 1;
198 : :
199 [ # # ]: 0 : if (nintpl > 1)
200 : : {
201 [ # # ]: 0 : for (j = 0; j < nintpl - 1; j++)
202 : : {
203 : 0 : dblinp /= 10.0;
204 : 0 : expnr++;
205 : : }
206 : : }
207 : : else
208 : : {
209 [ # # ]: 0 : if (dblinp)
210 : : {
211 [ # # ]: 0 : while (!trunc(dblinp))
212 : : {
213 : 0 : dblinp *= 10.0;
214 : 0 : expnr--;
215 : : }
216 : : }
217 : : }
218 : :
219 : 0 : dblinpabs = fabsl(dblinp);
220 : 0 : intpl = (long long int)trunc(dblinpabs);
221 : 0 : dec_part = dblinpabs - intpl;
222 [ # # ]: 0 : fw_int = (dblinp_sign < 0) + 1;
223 : :
224 [ # # ]: 0 : if (ndecpl > 0)
225 : : {
226 : 0 : fw_dec = (ndecpl > 9) ? 9 : ndecpl;
227 : : }
228 [ # # ]: 0 : else if (ndecpl == 0)
229 : : {
230 : 0 : fw_dec = 0;
231 : : }
232 : : else
233 : : {
234 : 0 : fw_dec = 6;
235 : : }
236 : 0 : fw_real = fw_int + (ndecpl != 0) + fw_dec + 4;
237 : :
238 [ # # ]: 0 : if (ndecpl)
239 : : {
240 : 0 : fw_int += (fwidth - fw_real > 0) ? fwidth - fw_real : 0;
241 : :
242 [ # # ]: 0 : for (i = 0; i < fw_dec; i++)
243 : : {
244 : 0 : dec_part *= 10;
245 : 0 : decpl = 10 * decpl + (int)dec_part;
246 : 0 : dec_part = dec_part - trunc(dec_part);
247 : : }
248 : :
249 : 0 : decpl += (long long int)round(dec_part);
250 [ # # # # ]: 0 : if (((int)log10((double)decpl > 0 ? (double)decpl : 1.0) + 1) > fw_dec)
251 : : {
252 : 0 : intpl++;
253 : 0 : decpl -= (int)pow(10, fw_dec);
254 : : }
255 : :
256 [ # # ]: 0 : nintpl = (int)log10((double)intpl > 0 ? (double)intpl : 1.0) + 1;
257 [ # # ]: 0 : if (nintpl > 1)
258 : : {
259 : 0 : intpl /= 10;
260 : 0 : expnr++;
261 : : }
262 : :
263 : 0 : intpl *= dblinp_sign;
264 : :
265 : 0 : return sprintf(str, "%*lld.%0*llde%+0*d", fw_int, intpl, fw_dec, decpl, 3, expnr); /* djb-rwth: ignoring LLVM warning */
266 : : }
267 : : else
268 : : {
269 : 0 : intpl = (int)round(dblinp);
270 : :
271 : 0 : return sprintf(str, "%*llde%+0*d", fw_real, intpl, 3, expnr); /* djb-rwth: ignoring LLVM warning */
272 : : }
273 : : }
274 : :
275 : : /* djb-rwth: sprintf("%X.Yg", arg) emulation */
276 : 0 : static int dbl2int_g(double dblinp, int fwidth, int ndecpl, char* str)
277 : : {
278 : 0 : double dec_part, dblinpabs, dblinpc = dblinp;
279 : : char* intpl_str;
280 : : const char* dblinp_signf;
281 : 0 : int expnr = 0, fw_int, fw_dec, fw_real, dblinp_signe, nintpl, i, j, ret = 0;
282 : 0 : long long int intpl = 0, decpl = 0, intpl_size;
283 : :
284 : 0 : dblinpabs = fabsl(dblinpc);
285 : 0 : intpl = (long long int)trunc(dblinpabs);
286 [ # # ]: 0 : nintpl = (int)log10((double)intpl > 0 ? (double)intpl : 1) + 1;
287 : :
288 [ # # ]: 0 : if (nintpl > 1)
289 : : {
290 [ # # ]: 0 : for (j = 0; j < nintpl - 1; j++)
291 : : {
292 : 0 : dblinpc /= 10.0;
293 : 0 : expnr++;
294 : : }
295 : : }
296 : : else
297 : : {
298 [ # # ]: 0 : if (dblinp)
299 : : {
300 [ # # ]: 0 : while (!trunc(dblinpc))
301 : : {
302 : 0 : dblinpc *= 10.0;
303 : 0 : expnr--;
304 : : }
305 : : }
306 : : }
307 : :
308 [ # # ]: 0 : if (ndecpl > 0)
309 : : {
310 : 0 : fw_dec = (ndecpl > 9) ? 9 : ndecpl;
311 : : }
312 [ # # ]: 0 : else if (ndecpl == 0)
313 : : {
314 : 0 : fw_dec = 1;
315 : : }
316 : : else
317 : : {
318 : 0 : fw_dec = 6;
319 : : }
320 : :
321 [ # # ]: 0 : if (!dblinpc)
322 : : {
323 : 0 : ret = sprintf(str, "%lld", intpl); /* djb-rwth: ignoring LLVM warning */
324 : 0 : return ret;
325 : : }
326 : :
327 [ # # # # ]: 0 : if ((fw_dec > expnr) && (expnr >= -4))
328 : : {
329 [ # # ]: 0 : dblinp_signf = (dblinp >= 0.0) ? "" : "-";
330 : 0 : dblinpabs = fabsl(dblinp);
331 : 0 : intpl = (long long int)trunc(dblinpabs);
332 : 0 : dec_part = dblinpabs - intpl;
333 [ # # ]: 0 : fw_int = (int)log10((double)intpl > 0 ? (double)intpl : 1.0) + 1 + !strcmp(dblinp_signf, "-");
334 : 0 : intpl_size = ((long long int)fw_int + 3) * sizeof(unsigned long long int);
335 : 0 : intpl_str = (char*)inchi_malloc(intpl_size);
336 : :
337 : 0 : fw_real = fw_int + (ndecpl != 0) + fw_dec;
338 : :
339 [ # # ]: 0 : if (fw_dec)
340 : : {
341 : 0 : fw_int += (fwidth - fw_real > 0) ? fwidth - fw_real : 0;
342 : :
343 [ # # ]: 0 : for (i = 0; i < fw_dec; i++)
344 : : {
345 : 0 : dec_part *= 10;
346 : 0 : decpl = 10 * decpl + (long long int)dec_part;
347 : 0 : dec_part -= trunc(dec_part);
348 : : }
349 : :
350 : 0 : decpl += (long long int)round(dec_part);
351 : :
352 [ # # # # ]: 0 : if (((int)log10((double)decpl > 0 ? (double)decpl : 1.0) + 1) > fw_dec)
353 : : {
354 : 0 : intpl++;
355 : 0 : decpl -= (int)pow(10, fw_dec);
356 : : }
357 : :
358 [ # # ]: 0 : if (decpl)
359 : : {
360 [ # # ]: 0 : while (!(decpl % 10))
361 : : {
362 : 0 : decpl /= 10;
363 : 0 : fw_dec--;
364 : : }
365 : : }
366 : :
367 [ # # ]: 0 : if (intpl_str)
368 : : {
369 [ # # ]: 0 : sprintf(intpl_str, "%s%lld", intpl ? dblinp_signf : "", intpl); /* djb-rwth: ignoring LLVM warning */
370 : : }
371 : : else
372 : : {
373 : 0 : return -1;
374 : : }
375 : :
376 [ # # ]: 0 : if (decpl)
377 : : {
378 : 0 : ret = sprintf(str, "%*s.%0*lld", fw_int, intpl_str, fw_dec, decpl); /* djb-rwth: ignoring LLVM warning */
379 [ # # ]: 0 : inchi_free(intpl_str);
380 : 0 : return ret;
381 : : }
382 : : else
383 : : {
384 : 0 : ret = sprintf(str, "%*s", fw_int, intpl_str); /* djb-rwth: ignoring LLVM warning */
385 [ # # ]: 0 : inchi_free(intpl_str);
386 : 0 : return ret;
387 : : }
388 : : }
389 : : else
390 : : { /* djb-rwth: addressing coverity ID #499558 -- currently leaving this as it is still a part of GHI #100 */
391 : 0 : intpl = (long long int)round(dblinp);
392 : 0 : ret = sprintf(str, "%*lld", fw_real, intpl); /* djb-rwth: ignoring LLVM warning */
393 : 0 : return ret;
394 : : }
395 : : }
396 : : else
397 : : {
398 [ # # ]: 0 : dblinp_signe = (dblinpc >= 0.0) ? 1 : -1;
399 : 0 : dblinpabs = fabsl(dblinpc);
400 : 0 : intpl = (long long int)trunc(dblinpabs);
401 : 0 : dec_part = dblinpabs - intpl;
402 [ # # ]: 0 : fw_int = (dblinp_signe < 0) + 1;
403 : :
404 : 0 : fw_real = fw_int + (ndecpl != 0) + fw_dec + 4;
405 : :
406 [ # # ]: 0 : if (ndecpl)
407 : : {
408 : 0 : fw_int += (fwidth - fw_real > 0) ? fwidth - fw_real : 0;
409 : :
410 [ # # ]: 0 : for (i = 0; i < fw_dec; i++)
411 : : {
412 : 0 : dec_part *= 10;
413 : 0 : decpl = 10 * decpl + (int)dec_part;
414 : 0 : dec_part = dec_part - trunc(dec_part);
415 : : }
416 : :
417 : 0 : decpl += (long long int)round(dec_part);
418 [ # # # # ]: 0 : if (((int)log10((double)decpl > 0 ? (double)decpl : 1.0) + 1) > fw_dec)
419 : : {
420 : 0 : intpl++;
421 : 0 : decpl -= (int)pow(10, fw_dec);
422 : : }
423 : :
424 [ # # ]: 0 : nintpl = (int)log10((double)intpl > 0 ? (double)intpl : 1.0) + 1;
425 [ # # ]: 0 : if (nintpl > 1)
426 : : {
427 : 0 : intpl /= 10;
428 : 0 : expnr++;
429 : : }
430 : :
431 : 0 : intpl *= dblinp_signe;
432 : 0 : ret = sprintf(str, "%*lld.%0*llde%+0*d", fw_int, intpl, fw_dec, decpl, 3, expnr); /* djb-rwth: ignoring LLVM warning */
433 : 0 : return ret;
434 : : }
435 : : else
436 : : {
437 : 0 : intpl = (int)round(dblinpc);
438 : 0 : ret = sprintf(str, "%*llde%+0*d", fw_real, intpl, 3, expnr); /* djb-rwth: ignoring LLVM warning */
439 : 0 : return ret;
440 : : }
441 : : }
442 : : }
|