Branch data Line data Source code
1 : : /*
2 : : * SPDX-License-Identifier: MIT
3 : : * Copyright (c) 2024 IUPAC and InChI Trust
4 : : */
5 : :
6 : : #include <stdlib.h>
7 : : #include <ctype.h>
8 : : #include <string.h>
9 : : #include <math.h>
10 : : #include <float.h>
11 : : #include <limits.h>
12 : :
13 : : #include "mode.h"
14 : : #include "mol_fmt.h"
15 : :
16 : : #include "ichierr.h"
17 : : #include "util.h"
18 : : #include "ichi_io.h"
19 : :
20 : : #include "bcf_s.h"
21 : :
22 : : /*
23 : : MolFile related procedures - 2
24 : :
25 : : */
26 : :
27 : : /****************************************************************************
28 : : Read n chars and find where they are terminated with space or trailing 0
29 : : ****************************************************************************/
30 : 4559 : int MolfileStrnread(char *dest,
31 : : char *source,
32 : : int len,
33 : : char **first_space)
34 : : {
35 : : /* required len >= 0; dest must have at least len+1 bytes */
36 : :
37 : : int i, c;
38 : :
39 [ + + ]: 4559 : if (len > 0)
40 : : {
41 : 4306 : strncpy(dest, source, len);
42 : : }
43 : 4559 : dest[len] = '\0';
44 : :
45 [ + + ]: 4559 : len = (len > 0) ? (int)strlen(dest) : 0;
46 : :
47 [ + + + - : 6168 : for (i = ( len - 1 ); i >= 0 && 0 != ( c = source[i] ) && isspace( UCINT c ); i--);
+ + ]
48 : :
49 : 4559 : *first_space = dest + ((long long)i + 1); /* first blank or zero terminating byte in dest */ /* djb-rwth: cast operator added */
50 : :
51 : 4559 : return len; /* number of actually processed bytes excluding zero terminator */
52 : : }
53 : :
54 : : /****************************************************************************
55 : : * Extract the 'data' in the mol file field at given text position 'line_ptr'
56 : : *
57 : : *
58 : : * 1. 'field_len' for MOL_FMT_STRING_DATA does not include trailing zero,
59 : : * that is actual length of the string pointed by 'data'
60 : : * should be at least field_len+1 bytes.
61 : : * For numerical data 'field_len' is length of input data field
62 : : * For numerical integral data field_len <= 0 means read up to first
63 : : * non-numeric character as strtod() does ("free format")
64 : : * 2. return value: for MOL_FMT_STRING_DATA: number of bytes excluding trailing zero
65 : : * for all others: 1=success; 0 = empty; -1= error
66 : : * 3. on exit *line_ptr points to the next byte after the last entered
67 : : *
68 : : *
69 : : ****************************************************************************/
70 : 6884 : int MolfileReadField(void *data,
71 : : int field_len,
72 : : int data_type,
73 : : char **line_ptr)
74 : : {
75 : 6884 : char *p = *line_ptr, *q, *p_end;
76 : 6884 : int i, c, len, ret = 1;
77 : : long ldata;
78 : : double ddata;
79 : :
80 : 6884 : int DEFINITE_LENGTH_FIELD = 0;
81 : 6884 : int FIELD_ENDS_AT_FIRST_NON_DIGIT = 0;
82 : 6884 : int TOO_LONG_FIELD = 0;
83 : :
84 [ + + ]: 6884 : if (field_len > MOL_FMT_MAX_VALUE_LEN)
85 : : {
86 : 364 : TOO_LONG_FIELD = 1;
87 : : }
88 [ + + ]: 6520 : else if (field_len <= 0)
89 : : {
90 : 25 : FIELD_ENDS_AT_FIRST_NON_DIGIT = 1;
91 : : }
92 : : else
93 : : {
94 : 6495 : DEFINITE_LENGTH_FIELD = 1;
95 : : }
96 : :
97 [ + + + + : 6884 : switch (data_type)
- ]
98 : : {
99 : 1397 : case MOL_FMT_STRING_DATA:
100 : : /* pass by all leading spaces */
101 : 1397 : for (i = 0;
102 [ + + + + : 2909 : i < field_len && 0 != (c = p[i]) && isspace(UCINT c);
+ + ]
103 : 1512 : i++)
104 : : {
105 : : ;
106 : : }
107 : :
108 : 1397 : len = MolfileStrnread((char *)data, &p[i], field_len - i, &q);
109 : :
110 : 1397 : ret = ( q - (char*) data );/* actual data length */
111 : 1397 : *q = '\0'; /* add zero termination to data if it is not there yet*/
112 : 1397 : *line_ptr += ( (long long)len + (long long)i ); /* ptr to the 1st byte of the next input field or to zero termination */ /* djb-rwth: cast operators added */
113 : 1397 : break;
114 : :
115 : 2475 : case MOL_FMT_CHAR_INT_DATA:
116 : : case MOL_FMT_SHORT_INT_DATA:
117 : : case MOL_FMT_LONG_INT_DATA:
118 : : {
119 : : char str[MOL_FMT_MAX_VALUE_LEN + 1];
120 : 2475 : ldata = 0L;
121 [ - + ]: 2475 : if (TOO_LONG_FIELD)
122 : : {
123 : 0 : ret = -1;
124 : : }
125 [ + + ]: 2475 : else if (DEFINITE_LENGTH_FIELD)
126 : : {
127 : : /* fixed length */
128 : 2458 : *line_ptr += (len = MolfileStrnread(str, p, field_len, &q));
129 : :
130 : 2458 : *q = '\0';
131 [ + + + + ]: 2458 : if (!len || !(q - str))
132 : : {
133 : 490 : ret = 0; /* empty string */
134 : : }
135 : : else
136 : : {
137 [ + + ]: 1968 : if ((ldata = strtol(str, &p_end, 10), p_end != q))
138 : : {
139 : 5 : ret = -1; /* wrong data: incompletely interpreted */
140 : : }
141 : : }
142 : : }
143 [ + - ]: 17 : else if (FIELD_ENDS_AT_FIRST_NON_DIGIT)
144 : : {
145 : : /* free format: field_len <= 0 */
146 : 17 : ldata = strtol(p, &p_end, 10);
147 : 17 : *line_ptr += (len = p_end - p);
148 [ - + ]: 17 : if (len == 0)
149 : : {
150 : 0 : ret = 0;
151 : : }
152 : : }
153 : : else
154 : : {
155 : : /* should not come here */
156 : 0 : ret = -1;
157 : : }
158 : :
159 [ + + + - ]: 2475 : switch (data_type)
160 : : {
161 : 1530 : case MOL_FMT_CHAR_INT_DATA:
162 [ + - + - ]: 1530 : if (SCHAR_MIN <= ldata && ldata <= SCHAR_MAX)
163 : : {
164 : : /* from || to &&: 11-19-96 */
165 : 1530 : *(S_CHAR *)data = (S_CHAR)ldata;
166 : : }
167 : : else
168 : : {
169 : 0 : *(S_CHAR *)data = (S_CHAR)0;
170 : 0 : ret = -1;
171 : : }
172 : 1530 : break;
173 : 824 : case MOL_FMT_SHORT_INT_DATA:
174 [ + - + - ]: 824 : if (SHRT_MIN <= ldata && ldata <= SHRT_MAX)
175 : : {
176 : 824 : *(S_SHORT *)data = (S_SHORT)ldata;
177 : : }
178 : : else
179 : : {
180 : 0 : *(S_SHORT *)data = (S_SHORT)0;
181 : 0 : ret = -1;
182 : : }
183 : 824 : break;
184 : 121 : case MOL_FMT_LONG_INT_DATA:
185 [ + - + - ]: 121 : if (LONG_MIN < ldata && ldata < LONG_MAX)
186 : : {
187 : 121 : *(long *)data = (long)ldata;
188 : : }
189 : : else
190 : : {
191 : 0 : *(long *)data = 0L;
192 : 0 : ret = -1;
193 : : }
194 : 121 : break;
195 : 0 : default:
196 : 0 : ret = -1;
197 : : }
198 : : } /* MOL_FMT_CHAR_INT_DATA... */
199 : 2475 : break;
200 : :
201 : 712 : case MOL_FMT_DOUBLE_DATA:
202 : : case MOL_FMT_FLOAT_DATA:
203 : : {
204 : : char str[MOL_FMT_MAX_VALUE_LEN + 1];
205 : :
206 [ - + ]: 712 : if (TOO_LONG_FIELD)
207 : : {
208 : 0 : ret = -1;
209 : 0 : ddata = 0.0;
210 : : }
211 [ + + ]: 712 : else if (DEFINITE_LENGTH_FIELD)
212 : : {
213 : 704 : *line_ptr += (len = MolfileStrnread(str, p, field_len, &q));
214 : 704 : *q = '\0';
215 [ + + + + ]: 704 : if (!len || !(q - str))
216 : : {
217 : : /* empty string */
218 : 240 : ddata = 0.0;
219 : 240 : ret = 0;
220 : : }
221 [ - + ]: 464 : else if ((ddata = strtod(str, &p_end), p_end != q))
222 : : {
223 : : /* wrong data */
224 : 0 : ret = -1;
225 : : }
226 : : }
227 [ + - ]: 8 : else if (FIELD_ENDS_AT_FIRST_NON_DIGIT)
228 : : {
229 : : /* free format */
230 : 8 : ddata = strtod(p, &p_end);
231 : 8 : *line_ptr += (len = p_end - p);
232 [ - + ]: 8 : if (len == 0)
233 : : {
234 : 0 : ret = 0;
235 : : }
236 : : }
237 : : else
238 : : {
239 : : /* should not come here */
240 : 0 : ret = -1; /* djb-rwth: addressing coverity ID #499478 -- see the original comment above */
241 : : }
242 : :
243 [ + - - ]: 712 : switch (data_type)
244 : : {
245 : :
246 : 712 : case MOL_FMT_DOUBLE_DATA:
247 [ + - + - ]: 712 : if (ddata != HUGE_VAL && /*ldata*/ ddata != -HUGE_VAL)
248 : : { /* replaced ldata with ddata 6-30-98 DCh */
249 : 712 : *(double *)data = ddata;
250 : : }
251 : : else
252 : : {
253 : 0 : *(double *)data = 0.0;
254 : 0 : ret = -1;
255 : : }
256 : 712 : break;
257 : :
258 : 0 : case MOL_FMT_FLOAT_DATA:
259 [ # # ]: 0 : if (fabs(ddata) <= (double)FLT_MIN)
260 : : {
261 : 0 : *(float *)data = 0.0;
262 : : }
263 [ # # ]: 0 : else if (fabs(ddata) >= (double)FLT_MAX)
264 : : {
265 : 0 : *(float *)data = 0.0;
266 : 0 : ret = -1;
267 : : }
268 : : else
269 : : {
270 : 0 : *(float *)data = (float)ddata;
271 : : }
272 : 0 : break;
273 : : }
274 : : } /* MOL_FMT_DOUBLE_DATA... */
275 : 712 : break;
276 : :
277 : 2300 : case MOL_FMT_JUMP_TO_RIGHT:
278 : : {
279 : :
280 [ + + + + ]: 8832 : for (i = 0; i < field_len && p[i]; i++)
281 : : ;
282 : :
283 : 2300 : *line_ptr += i;
284 : 2300 : ret = i;
285 : : }
286 : 2300 : break;
287 : :
288 : 0 : default:
289 : 0 : ret = -1;
290 : : }
291 : :
292 : 6884 : return ret;
293 : : }
294 : :
295 : : /****************************************************************************
296 : : Read molfile number from the name line like "Structure #22"
297 : : ****************************************************************************/
298 : 121 : long MolfileExtractStrucNum(MOL_FMT_HEADER_BLOCK *pHdr)
299 : : {
300 : : static char sStruct[] = "Structure #";
301 : : static char sINCHI[] = INCHI_NAME;
302 : 121 : long lMolfileNumber = 0;
303 : 121 : char *p, *q = NULL;
304 : :
305 [ + - ]: 121 : if (pHdr)
306 : : {
307 [ - + ]: 121 : if (!inchi_memicmp(pHdr->molname, sStruct, sizeof(sStruct) - 1))
308 : : {
309 : 0 : p = pHdr->molname + sizeof(sStruct) - 1;
310 : 0 : lMolfileNumber = strtol(p, &q, 10);
311 : 0 : p = pHdr->line2;
312 [ # # # # : 0 : if (!q || *q ||
# # ]
313 : 0 : inchi_memicmp(p, sINCHI, sizeof(sINCHI) - 1) ||
314 [ # # ]: 0 : !strstr(p + sizeof(sINCHI) - 1, "SDfile Output"))
315 : : {
316 : 0 : lMolfileNumber = 0;
317 : : }
318 : : }
319 : : }
320 : :
321 : 121 : return lMolfileNumber;
322 : : }
323 : :
324 : : /****************************************************************************
325 : : Check if MOL file contains no structure
326 : : ****************************************************************************/
327 : 242 : int MolfileHasNoChemStruc(MOL_FMT_DATA *mfdata)
328 : : {
329 [ + - - + ]: 242 : if (!mfdata || !mfdata->ctab.atoms)
330 : : {
331 : 0 : return 1;
332 : : }
333 : :
334 [ - + ]: 242 : if (mfdata->ctab.n_atoms <= 0)
335 : : {
336 : 0 : return 1;
337 : : }
338 : :
339 [ + + - + ]: 242 : if (0 < mfdata->ctab.n_bonds && !mfdata->ctab.bonds)
340 : : {
341 : 0 : return 1;
342 : : }
343 : :
344 : 242 : return 0;
345 : : }
346 : :
347 : : /****************************************************************************
348 : : Copy MOL-formatted data of SDF record or Molfile to another file
349 : : ****************************************************************************/
350 : 0 : int MolfileSaveCopy(INCHI_IOSTREAM *inp_file,
351 : : long fPtrStart,
352 : : long fPtrEnd,
353 : : FILE *outfile,
354 : : long num)
355 : : {
356 : : char line[MOL_FMT_INPLINELEN], *p;
357 : : long fPtr;
358 : 0 : int ret = 1;
359 : : char szNumber[32];
360 : :
361 [ # # ]: 0 : if (inp_file->type == INCHI_IOS_TYPE_FILE)
362 : : {
363 : :
364 : 0 : FILE *infile = inp_file->f;
365 : :
366 [ # # ]: 0 : if (!infile)
367 : : {
368 : 0 : return 1;
369 : : }
370 : :
371 [ # # ]: 0 : if (!outfile)
372 : : {
373 : 0 : return 1;
374 : : }
375 : :
376 [ # # # # ]: 0 : if (fPtrStart < 0L && fPtrEnd <= fPtrStart)
377 : : {
378 : 0 : return 1;
379 : : }
380 : :
381 [ # # ]: 0 : if (0 != fseek(infile, fPtrStart, SEEK_SET))
382 : : {
383 : 0 : return 1;
384 : : }
385 : :
386 [ # # ]: 0 : while (fPtrEnd > (fPtr = ftell(infile)) && fPtr >= 0L
387 [ # # # # ]: 0 : && inchi_fgetsLf(line, sizeof(line) - 1, inp_file))
388 : : {
389 : :
390 : 0 : line[sizeof(line) - 1] = '\0'; /* unnecessary extra precaution */
391 : :
392 [ # # # # ]: 0 : if (fPtr == fPtrStart && num)
393 : : {
394 : : int len;
395 : 0 : lrtrim(line, &len);
396 [ # # ]: 0 : len = sprintf(szNumber, "#%ld%s", num, len ? "/" : "");
397 : 0 : mystrncpy(line + len, line, sizeof(line) - len - 1);
398 : 0 : memcpy(line, szNumber, len);
399 : : }
400 : :
401 [ # # ]: 0 : if (!strchr(line, '\n'))
402 : : {
403 : 0 : p = line + strlen(line);
404 : 0 : p[0] = '\n';
405 : 0 : p[1] = '\0';
406 : : }
407 : :
408 : 0 : fputs(line, outfile);
409 : : }
410 : :
411 : 0 : ret = fseek(infile, fPtrEnd, SEEK_SET);
412 : : }
413 : 0 : else if (inp_file->type == INCHI_IOS_TYPE_STRING)
414 : : {
415 : : ;
416 : : }
417 : : else
418 : : {
419 : : ;
420 : : }
421 : :
422 : 0 : return ret;
423 : : }
424 : :
425 : :
426 : : #define MIN_STDATA_X_COORD 0.0
427 : : #define MAX_STDATA_X_COORD 256.0
428 : : #define MIN_STDATA_Y_COORD 0.0
429 : : #define MAX_STDATA_Y_COORD 256.0
430 : : #define MIN_STDATA_Z_COORD 0.0
431 : : #define MAX_STDATA_Z_COORD 256.0
432 : : #define MAX_STDATA_AVE_BOND_LENGTH 20.0
433 : : #define MIN_STDATA_AVE_BOND_LENGTH 10.0
434 : :
435 : :
436 : : /****************************************************************************
437 : : Get xyz dimensionality and normalization factors
438 : : ****************************************************************************/
439 : 121 : int MolfileGetXYZDimAndNormFactors(MOL_FMT_DATA *mfdata,
440 : : int find_norm_factors,
441 : : double *x0,
442 : : double *y0,
443 : : double *z0,
444 : : double *xmin,
445 : : double *ymin,
446 : : double *zmin,
447 : : double *scaler,
448 : : int *err,
449 : : char *pStrErr)
450 : :
451 : : {
452 : : int i;
453 : 121 : int num_dimensions = 0, num_atoms, num_bonds;
454 : 121 : double max_x = -1.0e32, max_y = -1.0e32, max_z = -1.0e32;
455 : 121 : double min_x = 1.0e32, min_y = 1.0e32, min_z = 1.0e32;
456 : 121 : double macheps = 1.0e-10, small_coeff = 0.00001;
457 : 121 : double x_coeff, y_coeff, z_coeff, coeff = 1.0, average_bond_length;
458 : :
459 : 121 : *x0 = MIN_STDATA_X_COORD;
460 : 121 : *y0 = MIN_STDATA_Y_COORD;
461 : 121 : *z0 = MIN_STDATA_Z_COORD;
462 : 121 : *xmin = *ymin = *zmin = 0.0;
463 : 121 : *scaler = coeff;
464 : :
465 [ - + ]: 121 : if (MolfileHasNoChemStruc(mfdata))
466 : : {
467 : 0 : goto exit_function;
468 : : }
469 : :
470 : 121 : num_atoms = mfdata->ctab.n_atoms;
471 [ + + ]: 923 : for (i = 0; i < num_atoms; i++)
472 : : {
473 [ + + ]: 802 : max_x = inchi_max(mfdata->ctab.atoms[i].fx, max_x);
474 [ + + ]: 802 : min_x = inchi_min(mfdata->ctab.atoms[i].fx, min_x);
475 [ + + ]: 802 : max_y = inchi_max(mfdata->ctab.atoms[i].fy, max_y);
476 [ + + ]: 802 : min_y = inchi_min(mfdata->ctab.atoms[i].fy, min_y);
477 [ + + ]: 802 : max_z = inchi_max(mfdata->ctab.atoms[i].fz, max_z);
478 [ + + ]: 802 : min_z = inchi_min(mfdata->ctab.atoms[i].fz, min_z);
479 : : }
480 : :
481 : 121 : num_bonds = 0;
482 : 121 : average_bond_length = 0.0;
483 [ + + ]: 817 : for (i = 0; i < mfdata->ctab.n_bonds; i++)
484 : : {
485 : : double dx, dy, dz;
486 : 696 : int a1 = mfdata->ctab.bonds[i].atnum1 - 1;
487 : 696 : int a2 = mfdata->ctab.bonds[i].atnum2 - 1;
488 : :
489 [ + - + - : 696 : if (a1 < 0 || a1 >= num_atoms ||
+ - ]
490 [ + - - + ]: 696 : a2 < 0 || a2 >= num_atoms ||
491 : : a1 == a2)
492 : : {
493 : 0 : *err |= 1; /* bond for invalid atom number(s); ignored */
494 : 0 : TREAT_ERR(*err, 0, "Bond to nonexistent atom");
495 : 0 : continue;
496 : : }
497 : :
498 : 696 : dx = mfdata->ctab.atoms[a1].fx - mfdata->ctab.atoms[a2].fx;
499 : 696 : dy = mfdata->ctab.atoms[a1].fy - mfdata->ctab.atoms[a2].fy;
500 : 696 : dz = mfdata->ctab.atoms[a1].fz - mfdata->ctab.atoms[a2].fz;
501 : :
502 : 696 : average_bond_length += sqrt(dx*dx + dy*dy + dz*dz);
503 : 696 : num_bonds++;
504 : : }
505 : :
506 [ + + ]: 121 : if (max_x - min_x <= small_coeff * (fabs(max_x) + fabs(min_x)))
507 : : {
508 : 48 : x_coeff = 0.0;
509 : : }
510 : : else
511 : : {
512 : 73 : x_coeff = (MAX_STDATA_X_COORD - MIN_STDATA_X_COORD) / (max_x - min_x);
513 : : }
514 : :
515 [ + + ]: 121 : if (max_y - min_y <= small_coeff * (fabs(max_y) + fabs(min_y)))
516 : : {
517 : 48 : y_coeff = 0.0;
518 : : }
519 : : else
520 : : {
521 : 73 : y_coeff = (MAX_STDATA_Y_COORD - MIN_STDATA_Y_COORD) / (max_y - min_y);
522 : : }
523 : :
524 [ + + ]: 121 : if (max_z - min_z <= small_coeff * (fabs(max_z) + fabs(min_z)))
525 : : {
526 : 120 : z_coeff = 0.0;
527 : : }
528 : : else
529 : : {
530 : 1 : z_coeff = (MAX_STDATA_Z_COORD - MIN_STDATA_Z_COORD) / (max_z - min_z);
531 : : }
532 : :
533 [ - + + + ]: 121 : num_dimensions = ((x_coeff > macheps || y_coeff > macheps) && fabs(z_coeff) < macheps)
534 : : ? 2
535 [ + + + + ]: 242 : : ( fabs( z_coeff ) > macheps ) ? 3 : 0;
536 : :
537 : :
538 [ + - ]: 121 : if (!find_norm_factors)
539 : : {
540 : 121 : goto exit_function;
541 : : }
542 : :
543 : : /* Find normalization parameters */
544 [ # # # # ]: 0 : switch (num_dimensions)
545 : : {
546 : 0 : case 0:
547 : 0 : coeff = 0.0;
548 : 0 : break;
549 : :
550 : 0 : case 2:
551 : : /* choose the smallest stretching coefficient */
552 [ # # # # ]: 0 : if (x_coeff > macheps && y_coeff > macheps)
553 : : {
554 [ # # ]: 0 : coeff = inchi_min(x_coeff, y_coeff);
555 : : }
556 [ # # ]: 0 : else if (x_coeff > macheps)
557 : : {
558 : 0 : coeff = x_coeff;
559 : : }
560 [ # # ]: 0 : else if (y_coeff > macheps)
561 : : {
562 : 0 : coeff = y_coeff;
563 : : }
564 : : else
565 : : {
566 : 0 : coeff = 1.0;
567 : : }
568 : 0 : break;
569 : :
570 : 0 : case 3:
571 : : /* choose the smallest stretching coefficient */
572 [ # # # # ]: 0 : if (x_coeff > macheps && y_coeff > macheps)
573 : : {
574 [ # # ]: 0 : coeff = inchi_min(x_coeff, y_coeff);
575 [ # # ]: 0 : coeff = inchi_min(coeff, z_coeff);
576 : : }
577 [ # # ]: 0 : else if (x_coeff > macheps)
578 : : {
579 [ # # ]: 0 : coeff = inchi_min(x_coeff, z_coeff);
580 : : }
581 [ # # ]: 0 : else if (y_coeff > macheps)
582 : : {
583 [ # # ]: 0 : coeff = inchi_min(y_coeff, z_coeff);
584 : : }
585 : : else
586 : : {
587 : 0 : coeff = z_coeff;
588 : : }
589 : 0 : break;
590 : :
591 : 0 : default:
592 : 0 : coeff = 0.0;
593 : : }
594 : :
595 [ # # ]: 0 : if (num_bonds > 0)
596 : : {
597 : :
598 : 0 : average_bond_length /= (double)num_bonds;
599 [ # # ]: 0 : if (average_bond_length * coeff > MAX_STDATA_AVE_BOND_LENGTH)
600 : : {
601 : 0 : coeff = MAX_STDATA_AVE_BOND_LENGTH / average_bond_length; /* avoid too long bonds */
602 : : }
603 [ # # ]: 0 : else if (average_bond_length * coeff < macheps)
604 : : {
605 : 0 : coeff = 1.0; /* all lengths are of zero length */
606 : : }
607 [ # # ]: 0 : else if (average_bond_length * coeff < MIN_STDATA_AVE_BOND_LENGTH)
608 : : {
609 : 0 : coeff = MIN_STDATA_AVE_BOND_LENGTH / average_bond_length; /* avoid too short bonds */
610 : : }
611 : : }
612 : :
613 : 0 : exit_function:;
614 : :
615 : 121 : *x0 = min_x;
616 : 121 : *y0 = min_y;
617 : 121 : *z0 = min_z;
618 : 121 : *xmin = MIN_STDATA_X_COORD;
619 : 121 : *ymin = MIN_STDATA_Y_COORD;
620 : 121 : *zmin = MIN_STDATA_Z_COORD;
621 : 121 : *scaler = coeff;
622 : :
623 : 121 : return num_dimensions;
624 : : }
625 : :
626 : : /****************************************************************************
627 : : Clean up MOL-format parser data
628 : : ****************************************************************************/
629 : 121 : MOL_FMT_DATA *FreeMolfileData(MOL_FMT_DATA *mfdata)
630 : : {
631 [ + - ]: 121 : if (mfdata)
632 : : {
633 : :
634 [ + - ]: 121 : if (mfdata->ctab.atoms)
635 : : {
636 [ + - ]: 121 : inchi_free(mfdata->ctab.atoms);
637 : : }
638 : :
639 [ + - ]: 121 : if (mfdata->ctab.bonds)
640 : : {
641 [ + - ]: 121 : inchi_free(mfdata->ctab.bonds);
642 : : }
643 : :
644 [ - + ]: 121 : if (mfdata->ctab.coords)
645 : : {
646 [ # # ]: 0 : inchi_free(mfdata->ctab.coords);
647 : : }
648 : :
649 : : /*if ( 0!=mfdata->ctab.sgroups.used )*/
650 : 121 : MolFmtSgroups_Free(&(mfdata->ctab.sgroups));
651 : :
652 [ + + ]: 121 : if (mfdata->ctab.v3000)
653 : : {
654 : 57 : DeleteMolfileV3000Info(mfdata->ctab.v3000);
655 : : }
656 : :
657 [ + - ]: 121 : inchi_free(mfdata);
658 : 121 : mfdata = NULL;
659 : : }
660 : :
661 : 121 : return mfdata;
662 : : }
|