  380 |                 !strcmp(model, "X-E4")        ||
  381 |                 !strcmp(model, "X-T30 II")    ||
  382 |                 !strcmp(model, "X-S10"))
  383 |             is34 = 1;
  384 |
  385 |           if (imFuji.RAFDataVersion == 0x4500) // X-E1, RAFData gen. 3
  386 |           {
  387 |             wb_section_offset = 0x13ac;
  388 |           }
  389 |           else if (imFuji.RAFDataVersion == 0x0146 || // X20
  390 |                    imFuji.RAFDataVersion == 0x0149 || // X100S
  391 |                    imFuji.RAFDataVersion == 0x0249)   // X100S
  392 |           {
  393 |             wb_section_offset = 0x1410;
  394 |           }
  395 |           else if (imFuji.RAFDataVersion == 0x014d || // X-M1
  396 |                    imFuji.RAFDataVersion == 0x014e)   // X-A1, X-A2
  397 |           {
  398 |             wb_section_offset = 0x1474;
  399 |           }
  400 |           else if (imFuji.RAFDataVersion == 0x014f || // X-E2
  401 |                    imFuji.RAFDataVersion == 0x024f || // X-E2
  402 |                    imFuji.RAFDataVersion == 0x025d || // X-H1
  403 |                    imFuji.RAFDataVersion == 0x035d)   // X-H1
  404 |           {
  405 |             wb_section_offset = 0x1480;
  406 |           }
  407 |           else if (imFuji.RAFDataVersion == 0x0150) // XQ1, XQ2
  408 |           {
  409 |             wb_section_offset = 0x1414;
  410 |           }
  411 |           else if (imFuji.RAFDataVersion == 0x0151 || // X-T1 w/diff. fws
  412 |                    imFuji.RAFDataVersion == 0x0251 || imFuji.RAFDataVersion == 0x0351 ||
  413 |                    imFuji.RAFDataVersion == 0x0451 || imFuji.RAFDataVersion == 0x0551)
  414 |           {
  415 |             wb_section_offset = 0x14b0;
  416 |           }
  417 |           else if (imFuji.RAFDataVersion == 0x0152 || // X30
  418 |                    imFuji.RAFDataVersion == 0x0153)   // X100T
  419 |           {
  420 |             wb_section_offset = 0x1444;
  421 |           }
  422 |           else if (imFuji.RAFDataVersion == 0x0154) // X-T10
  423 |           {
  424 |             wb_section_offset = 0x1824;
  425 |           }
  426 |           else if (imFuji.RAFDataVersion == 0x0155) // X70
  427 |           {
  428 |             wb_section_offset = 0x17b4;
  429 |           }
  430 |           else if (imFuji.RAFDataVersion == 0x0255 || // X-Pro2
  431 |                    imFuji.RAFDataVersion == 0x0455)
  432 |           {
  433 |             wb_section_offset = 0x135c;
  434 |           }
  435 |           else if (imFuji.RAFDataVersion == 0x0258 || // X-T2
  436 |                    imFuji.RAFDataVersion == 0x025b)   // X-T20
  437 |           {
  438 |             wb_section_offset = 0x13dc;
  439 |           }
  440 |           else if (imFuji.RAFDataVersion == 0x0259) // X100F
  441 |           {
  442 |             wb_section_offset = 0x1370;
  443 |           }
  444 |           else if (imFuji.RAFDataVersion == 0x025a || // GFX 50S
  445 |                    imFuji.RAFDataVersion == 0x045a)
  446 |           {
  447 |             wb_section_offset = 0x1424;
  448 |          }
  449 |           else if (imFuji.RAFDataVersion == 0x025c) // X-E3
  450 |           {
  451 |             wb_section_offset = 0x141c;
  452 |           }
  453 |           else if (imFuji.RAFDataVersion == 0x025e) // X-T3
  454 |           {
  455 |             wb_section_offset = 0x2014;
  456 |           }
  457 |           else if (imFuji.RAFDataVersion == 0x025f) // X-T30, GFX 50R, GFX 100 (? RAFDataVersion 0x045f)
  458 |           {
  459 |             if (!strcmp(model, "X-T30")) {
  460 |               if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x20b8))
  461 |                 wb_section_offset = 0x20b8;
  462 |               else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x20c8))
  463 | 					  wb_section_offset = 0x20c8;
  464 |             }
  465 |             else if (!strcmp(model, "GFX 50R"))
  466 |               wb_section_offset = 0x1424;
  467 |             else if (!strcmp(model, "GFX 100"))
  468 |               wb_section_offset = 0x20e4;
  469 |           }
  470 |           else if (imFuji.RAFDataVersion == 0x0260) // X-Pro3, GFX 100S
  471 |           {
  472 |            if (!strcmp(model, "X-Pro3"))
  473 |               wb_section_offset = 0x20e8;
  474 |             else if (!strcmp(model, "GFX 100S") || !strcmp(model, "GFX100S"))
  475 |               wb_section_offset = 0x2108;
  476 |           }
  477 |           else if (imFuji.RAFDataVersion == 0x0261) // X100V, GFX 50S II
  478 |           {
  479 |             if (!strcmp(model, "X100V"))
> 480 |               wb_section_offset = 0x2078;
  481 |             else if (!strcmp(model, "GFX 50S II") || !strcmp(model, "GFX50S II"))
  482 |               wb_section_offset = 0x214c;
  483 |           }
  484 |           else if (imFuji.RAFDataVersion == 0x0262) // X-T4
  485 |           {
  486 |             if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x21c8))
  487 |               wb_section_offset = 0x21c8;
  488 |             else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x21cc))
  489 |               wb_section_offset = 0x21cc;
  490 |           }
  491 |           else if (imFuji.RAFDataVersion == 0x0263) // X-H2S
  492 |           {
  493 |             wb_section_offset = 0x0b40;
  494 |           }
  495 |           else if (imFuji.RAFDataVersion == 0x0264) // X-S10, X-H2
  496 |           {
  497 |             if (!strcmp(model, "X-S10"))
  498 |               wb_section_offset = 0x21de;
  499 |             else if (!strcmp(model, "X-H2"))
  500 |               wb_section_offset = 0x0b3e;
  501 |           }
  502 |           else if ((imFuji.RAFDataVersion == 0x0265)  || // X-E4, X-T5
  503 |                    (imFuji.RAFDataVersion == 0x0266))    // X-T30 II, X-S20
  504 |           {
  505 |             if (!strcmp(model, "X-T5") ||
  506 |                 !strcmp(model, "X-S20"))
  507 |               wb_section_offset = 0x0c72;
  508 |             else
  509 |               wb_section_offset = 0x21cc;
  510 |           }
  511 |           else if (imFuji.RAFDataVersion == 0x0267) // GFX 100 II
  512 |           {
  513 |             wb_section_offset = 0x0cae;
  514 |           }
  515 |           else if (imFuji.RAFDataVersion == 0x0355) // X-E2S
  516 |           {
  517 |             wb_section_offset = 0x1840;
  518 |           }
  519 |           else if (imFuji.RAFDataVersion == 0x0368) // GFX 100S II
  520 |           {
  521 |             wb_section_offset = 0x0cba;
  522 |           }
  523 |           else if (imFuji.RAFDataVersion == 0x0369) // X100VI
  524 |           {
  525 |             wb_section_offset = 0x0c5a;
  526 |           }
  527 |           else if (imFuji.RAFDataVersion == 0x036a) // X-T50
  528 |           {
  529 |             wb_section_offset = 0x0cca;
  530 |           }
  531 |           else if (imFuji.RAFDataVersion == 0x036b) // X-M5
  532 |           {
  533 |             wb_section_offset = 0x0cea;
  534 |           }
  535 |
  536 | /* try for unknown RAF Data versions */
  537 |           else if (!strcmp(model, "X-Pro2"))
  538 |           {
  539 |             if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x135c))
  540 |               wb_section_offset = 0x135c;
  541 |           }
  542 |           else if (!strcmp(model, "X100F"))
  543 |           {
  544 |             if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1370))
  545 |               wb_section_offset = 0x1370;
  546 |           }
  547 |           else if (!strcmp(model, "X-E1"))
  548 |           {
  549 |             if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x13ac))
  550 |               wb_section_offset = 0x13ac;
  551 |           }
  552 |           else if (!strcmp(model, "X-T2") ||
  553 |                    !strcmp(model, "X-T20"))
  554 |           {
  555 |             if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x13dc))
  556 |               wb_section_offset = 0x13dc;
  557 |           }
  558 |           else if (!strcmp(model, "X20") ||
  559 |                    !strcmp(model, "X100S"))
  560 |           {
  561 |             if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1410))
  562 |               wb_section_offset = 0x1410;
  563 |           }
  564 |           else if (!strcmp(model, "XQ1") ||
  565 |                    !strcmp(model, "XQ2"))
  566 |           {
  567 |             if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1414))
  568 |               wb_section_offset = 0x1414;
  569 |           }
  570 |           else if (!strcmp(model, "X-E3"))
  571 |           {
  572 |             if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x141c))
  573 |               wb_section_offset = 0x141c;
  574 |           }
  575 |           else if (!strcmp(model, "GFX 50S") ||
  576 |                    !strcmp(model, "GFX 50R"))
  577 |           {
  578 |             if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1424))
  579 |               wb_section_offset = 0x1424;
  580 |           }

Reach line at /src/libraw/src/metadata/fuji.cpp:480 (observed count 0).


   72 |     /* pre subtract black callback: check for it above to disable subtract
   73 |      * inline */
   74 |
   75 |     if (callbacks.pre_subtractblack_cb)
   76 |       (callbacks.pre_subtractblack_cb)(this);
   77 |
   78 |     quality = 2 + !IO.fuji_width;
   79 |
   80 |     if (O.user_qual >= 0)
   81 |       quality = O.user_qual;
   82 |
   83 |     if (!subtract_inline || !C.data_maximum)
   84 |     {
   85 |       adjust_bl();
   86 |       subtract_black_internal();
   87 |     }
   88 |
   89 |     if (!(di.decoder_flags & LIBRAW_DECODER_FIXEDMAXC))
   90 |       adjust_maximum();
   91 |
   92 |     if (O.user_sat > 0)
   93 |       C.maximum = O.user_sat;
   94 |
   95 |     if (P1.is_foveon)
   96 |     {
   97 |       if (load_raw == &LibRaw::x3f_load_raw)
   98 |       {
   99 |         // Filter out zeroes
  100 |         for (int q = 0; q < S.height * S.width; q++)
  101 |         {
  102 |           for (int c = 0; c < 4; c++)
  103 |             if ((short)imgdata.image[q][c] < 0)
  104 |               imgdata.image[q][c] = 0;
  105 |         }
  106 |       }
  107 |       SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE);
  108 |     }
  109 |
  110 |     if (O.green_matching && !O.half_size)
  111 |     {
  112 |       green_matching();
  113 |     }
  114 |
  115 |     if (callbacks.pre_scalecolors_cb)
  116 |       (callbacks.pre_scalecolors_cb)(this);
  117 |
  118 |     if (!O.no_auto_scale)
  119 |     {
  120 |       scale_colors();
  121 |       SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS);
  122 |     }
  123 |
  124 |     if (callbacks.pre_preinterpolate_cb)
  125 |       (callbacks.pre_preinterpolate_cb)(this);
  126 |
  127 |     pre_interpolate();
  128 |
  129 |     SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
  130 |
  131 |     if (O.dcb_iterations >= 0)
  132 |       iterations = O.dcb_iterations;
  133 |     if (O.dcb_enhance_fl >= 0)
  134 |       dcb_enhance = O.dcb_enhance_fl;
  135 |     if (O.fbdd_noiserd >= 0)
  136 |       noiserd = O.fbdd_noiserd;
  137 |
  138 |     /* pre-exposure correction callback */
  139 |
  140 |     if (O.exp_correc > 0)
  141 |     {
  142 |       expos = O.exp_shift;
  143 |       preser = O.exp_preser;
  144 |       exp_bef(expos, preser);
  145 |     }
  146 |
  147 |     if (callbacks.pre_interpolate_cb)
  148 |       (callbacks.pre_interpolate_cb)(this);
  149 |
  150 |     /* post-exposure correction fallback */
  151 |     if (P1.filters && !O.no_interpolation)
  152 |     {
  153 | 	  int real_colors = P1.colors;
  154 | 	  int bad_bayer = 0;
  155 | 	  if (P1.filters > 1000)
  156 | 		  for (int r = 0; r < 4; r++)
  157 | 			  for (int c = 0; c < 8; c++)
  158 | 			  {
  159 | 				  real_colors = MAX(COLOR(r, c) + 1, real_colors);
  160 | 				  if (P1.filters > 1000)
  161 | 				  {
  162 | 					  // Normal bayer: adjacent pixels horizontally/vertically have different colors
  163 | 					  bad_bayer += (FC(r, c) == FC(r + 1, c));
  164 | 					  bad_bayer += (FC(r, c) == FC(r, c + 1));
  165 | 				  }
  166 | 			  }
  167 |
  168 |       if (noiserd > 0 && P1.colors == 3 && real_colors == 3 && P1.filters > 1000)
  169 |         fbdd(noiserd);
  170 |
  171 |       if (P1.filters > 1000 && callbacks.interpolate_bayer_cb)
> 172 |         (callbacks.interpolate_bayer_cb)(this);
  173 |       else if (P1.filters == 9 && callbacks.interpolate_xtrans_cb)
  174 |         (callbacks.interpolate_xtrans_cb)(this);
  175 |       else if (quality == 0)
  176 |         lin_interpolate();
  177 |       else if (quality == 1 || P1.colors > 3 || real_colors > 3 || bad_bayer || (P1.filters != LIBRAW_XTRANS && P1.filters <= 1000))
  178 |         vng_interpolate();
  179 |       else if (quality == 2 && P1.filters > 1000)
  180 |         ppg_interpolate();
  181 |       else if (P1.filters == LIBRAW_XTRANS)
  182 |       {
  183 |         // Fuji X-Trans
  184 |         xtrans_interpolate(quality > 2 ? 3 : 1);
  185 |       }
  186 |       else if (quality == 3)
  187 |         ahd_interpolate(); // really don't need it here due to fallback op
  188 |       else if (quality == 4)
  189 |         dcb(iterations, dcb_enhance);
  190 |
  191 |       else if (quality == 11)
  192 |         dht_interpolate();
  193 |       else if (quality == 12)
  194 |         aahd_interpolate();
  195 |       // fallback to AHD
  196 |       else
  197 |       {
  198 |         ahd_interpolate();
  199 |         imgdata.process_warnings |= LIBRAW_WARN_FALLBACK_TO_AHD;
  200 |       }
  201 |
  202 |       SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE);
  203 |     }
  204 |     if (IO.mix_green)
  205 |     {
  206 |       for (P1.colors = 3, i = 0; i < S.height * S.width; i++)
  207 |         imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
  208 |       SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
  209 |     }
  210 |
  211 |     if (callbacks.post_interpolate_cb)
  212 |       (callbacks.post_interpolate_cb)(this);
  213 |     else if (!P1.is_foveon && P1.colors == 3 && O.med_passes > 0)
  214 |     {
  215 |       median_filter();
  216 |       SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
  217 |     }
  218 |
  219 |     if (O.highlight == 2)
  220 |     {
  221 |       blend_highlights();
  222 |       SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
  223 |     }
  224 |
  225 |     if (O.highlight > 2)
  226 |     {
  227 |       recover_highlights();
  228 |       SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
  229 |     }
  230 |
  231 |     if (O.use_fuji_rotate)
  232 |     {
  233 |       fuji_rotate();
  234 |       SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
  235 |     }
  236 |
  237 |     if (!libraw_internal_data.output_data.histogram)
  238 |     {
  239 |       libraw_internal_data.output_data.histogram =
  240 |           (int(*)[LIBRAW_HISTOGRAM_SIZE])calloc(1,
  241 |               sizeof(*libraw_internal_data.output_data.histogram) * 4);
  242 |     }
  243 | #ifndef NO_LCMS
  244 |     if (O.camera_profile)
  245 |     {
  246 |       apply_profile(O.camera_profile, O.output_profile);
  247 |       SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
  248 |     }
  249 | #endif
  250 |
  251 |     if (callbacks.pre_converttorgb_cb)
  252 |       (callbacks.pre_converttorgb_cb)(this);
  253 |
  254 |     convert_to_rgb();
  255 |     SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
  256 |
  257 |     if (callbacks.post_converttorgb_cb)
  258 |       (callbacks.post_converttorgb_cb)(this);
  259 |
  260 |     if (O.use_fuji_rotate)
  261 |     {
  262 |       stretch();
  263 |       SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
  264 |     }
  265 |     O.four_color_rgb = save_4color; // also, restore
  266 |
  267 |     return 0;
  268 |   }
  269 |   catch (const std::bad_alloc&)
  270 |   {
  271 |       recycle();
  272 |       return LIBRAW_UNSUFFICIENT_MEMORY;

Reach line at /src/libraw/src/postprocessing/dcraw_process.cpp:172 (observed count 0).


  623 |   else if (!memcmp(head, "RIFF", 4))
  624 |   {
  625 |     fseek(ifp, 0, SEEK_SET);
  626 |     parse_riff(100);
  627 |   }
  628 |   else if (!memcmp(head + 4, "ftypqt   ", 9))
  629 |   {
  630 |     fseek(ifp, 0, SEEK_SET);
  631 | 	// Use existing variable that definitely not used in parse_qt/parse_jpeg to avoid ABI change
  632 | 	short cr3save = libraw_internal_data.unpacker_data.CR3_Version;
  633 | 	libraw_internal_data.unpacker_data.CR3_Version = 32;
  634 |     parse_qt(fsize);
  635 | 	libraw_internal_data.unpacker_data.CR3_Version = cr3save;
  636 |     is_raw = 0;
  637 |   }
  638 |   else if (!memcmp(head, "\0\001\0\001\0@", 6))
  639 |   {
  640 |     fseek(ifp, 6, SEEK_SET);
  641 |     fread(make, 1, 8, ifp);
  642 |     fread(model, 1, 8, ifp);
  643 |     fread(model2, 1, 16, ifp);
  644 |     data_offset = get2();
  645 |     get2();
  646 |     raw_width = get2();
  647 |     raw_height = get2();
  648 |     load_raw = &LibRaw::nokia_load_raw;
  649 |     filters = 0x61616161;
  650 |   }
  651 |   else if (!memcmp(head, "NOKIARAW", 8))
  652 |   {
  653 |     strcpy(make, "NOKIA");
  654 |     order = 0x4949;
  655 |     fseek(ifp, 300, SEEK_SET);
  656 |     data_offset = get4();
  657 |     i = get4(); // bytes count
  658 |     width = get2();
  659 |     height = get2();
  660 |
  661 |     // Data integrity check
  662 |     if (width < 1 || width > 16000 || height < 1 || height > 16000 ||
  663 |         i < (width * height) || i > (2 * width * height))
  664 |       throw LIBRAW_EXCEPTION_IO_CORRUPT;
  665 |
  666 |     switch (tiff_bps = i * 8 / (width * height))
  667 |     {
  668 |     case 8:
  669 |       load_raw = &LibRaw::eight_bit_load_raw;
  670 |       break;
  671 |     case 10:
  672 |       load_raw = &LibRaw::nokia_load_raw;
  673 |       break;
  674 |     case 0:
  675 |       throw LIBRAW_EXCEPTION_IO_CORRUPT;
  676 |       break;
  677 |     }
  678 |     raw_height = height + (top_margin = i / (width * tiff_bps / 8) - height);
  679 |     mask[0][3] = 1;
  680 |     filters = 0x61616161;
  681 |   }
  682 |   else if (!memcmp(head, "DSC-Image", 9))
  683 |     parse_rollei();
  684 |   else if (!memcmp(head, "PWAD", 4))
  685 |     parse_sinar_ia();
  686 |   else if (!memcmp(head, "\0MRM", 4))
  687 |     parse_minolta(0);
  688 |   else if (!memcmp(head, "FOVb", 4))
  689 |   {
  690 |     parse_x3f(); /* Does nothing if USE_X3FTOOLS is not defined */
  691 |   }
  692 |   else if (!memcmp(head, "CI", 2))
  693 |     parse_cine();
  694 | #ifdef USE_6BY9RPI
  695 |   else if (!memcmp(head, "BRCM", 4)) {
  696 | 	fseek(ifp, 0, SEEK_SET);
  697 | 	strcpy(make, "RaspberryPi");
  698 | 	strcpy(model, "Pi");
  699 | 	parse_raspberrypi();
  700 | 	}
  701 | #endif
  702 |   else if (!memcmp(head + 4, "ftypcrx ", 8))
  703 |   {
  704 |     int err;
  705 |     UINT64 szAtomList;
  706 |     short nesting = -1;
  707 |     short nTrack = -1;
  708 |     short TrackType;
  709 |     char AtomNameStack[129];
  710 |     strcpy(make, "Canon");
  711 |
  712 |     szAtomList = ifp->size();
  713 |     err = parseCR3(0ULL, szAtomList, nesting, AtomNameStack, nTrack, TrackType,szAtomList);
  714 |     libraw_internal_data.unpacker_data.crx_track_count = nTrack;
  715 |     if ((err == 0 || err == -14) &&
  716 |         nTrack >= 0) // no error, or too deep nesting
  717 |       selectCRXTrack();
  718 |   }
  719 |
  720 |   if (dng_version)
  721 |   {
  722 |       if (fsize > LIBRAW_MAX_DNG_RAW_FILE_SIZE)
> 723 |           throw LIBRAW_EXCEPTION_TOOBIG;
  724 |   }
  725 |   else if (load_raw == &LibRaw::crxLoadRaw)
  726 |   {
  727 |     if (fsize > LIBRAW_MAX_CR3_RAW_FILE_SIZE)
  728 |       throw LIBRAW_EXCEPTION_TOOBIG;
  729 |   }
  730 |   else
  731 |   {
  732 |     if (fsize > LIBRAW_MAX_NONDNG_RAW_FILE_SIZE)
  733 |       throw LIBRAW_EXCEPTION_TOOBIG;
  734 |   }
  735 |
  736 |   if (make[0] == 0)
  737 |     for (zero_fsize = i = 0; i < (int)camera_count; i++)
  738 |       if (fsize == (INT64)table[i].fsize)
  739 |       {
  740 |         strcpy(make, table[i].t_make);
  741 |         strcpy(model, table[i].t_model);
  742 |         flip = table[i].flags >> 2;
  743 |         zero_is_bad = table[i].flags & 2;
  744 |         data_offset = table[i].offset == 0xffff ? 0 : table[i].offset;
  745 |         raw_width = table[i].rw;
  746 |         raw_height = table[i].rh;
  747 |         left_margin = table[i].lm;
  748 |         top_margin = table[i].tm;
  749 |         width = raw_width - left_margin - table[i].rm;
  750 |         height = raw_height - top_margin - table[i].bm;
  751 |         filters = 0x1010101U * table[i].cf;
  752 |         colors = 4 - !((filters & filters >> 1) & 0x5555);
  753 |         load_flags = table[i].lf & 0xff;
  754 |         if (table[i].lf & 0x100) /* Monochrome sensor dump */
  755 |         {
  756 |           colors = 1;
  757 |           filters = 0;
  758 |         }
  759 |         switch (tiff_bps = unsigned((fsize - data_offset) * 8LL / (INT64(raw_width) * INT64(raw_height))))
  760 |         {
  761 |         case 6:
  762 |           load_raw = &LibRaw::minolta_rd175_load_raw;
  763 |           ilm.CameraMount = LIBRAW_MOUNT_Minolta_A;
  764 |           break;
  765 |         case 8:
  766 |           load_raw = &LibRaw::eight_bit_load_raw;
  767 |           break;
  768 |         case 10:
  769 |           if ((fsize - data_offset) / INT64(raw_height) * 3LL >= INT64(raw_width) * 4LL)
  770 |           {
  771 |             load_raw = &LibRaw::android_loose_load_raw;
  772 |             break;
  773 |           }
  774 |           else if (load_flags & 1)
  775 |           {
  776 |             load_raw = &LibRaw::android_tight_load_raw;
  777 |             break;
  778 |           }
  779 |         case 12:
  780 |           load_flags |= 128;
  781 |           load_raw = &LibRaw::packed_load_raw;
  782 |           break;
  783 |         case 16:
  784 |           order = 0x4949 | 0x404 * (load_flags & 1);
  785 |           tiff_bps -= load_flags >> 4;
  786 |           tiff_bps -= load_flags = load_flags >> 1 & 7;
  787 |           load_raw = table[i].offset == 0xffff
  788 |                          ? &LibRaw::unpacked_load_raw_reversed
  789 |                          : &LibRaw::unpacked_load_raw;
  790 |         }
  791 |         maximum = (1 << tiff_bps) - (1 << table[i].max);
  792 |         break;
  793 |       }
  794 |   if (zero_fsize)
  795 |     fsize = 0;
  796 |   if (make[0] == 0 && fsize < 25000000LL)
  797 |     parse_smal(0, flen);
  798 |   if (make[0] == 0)
  799 |   {
  800 |     parse_jpeg(0);
  801 | #ifdef USE_6BY9RPI
  802 | 	if (!(strncmp(model, "ov", 2) && strncmp(model, "RP_", 3) && strncmp(model, "imx477", 6))) {
  803 | 		//Assume that this isn't a raw unless the header can be found
  804 | 		is_raw = 0;
  805 |
  806 | 		if (!strncasecmp(model, "RP_testc",8)
  807 |             || !strncasecmp(model, "imx477", 6) //  from PyDNG
  808 | 		    || !strncasecmp(model, "RP_imx477",9)) {
  809 | 			const long offsets[] = {
  810 | 				//IMX477 offsets
  811 | 				3375104,  //2028x1080 12bit
  812 | 				4751360,  //2028x1520 12bit
  813 | 				18711040, //4056x3040 12bit
  814 | 				1015808,  //1012x760 10bit
  815 | 				-1        //Marker for end of table
  816 | 			};
  817 | 			int offset_idx;
  818 | 			for (offset_idx=0; offsets[offset_idx]!=-1; offset_idx++) {
  819 | 				if(!fseek (ifp, -offsets[offset_idx], SEEK_END) &&
  820 | 				   fread (head, 1, 32, ifp) && !strncmp(head,"BRCM", 4)) {
  821 | 					fseek(ifp, -32, SEEK_CUR);
  822 | 					strcpy (make, "RaspberryPi");
  823 |                     strcpy(model, "RP_imx477"); // Force single model

Reach line at /src/libraw/src/metadata/identify.cpp:723 (observed count 0).


  234 | 		  load_raw == &LibRaw::sony_ycbcr_load_raw;
  235 | }
  236 | int LibRaw::is_coolscan_nef()
  237 | {
  238 |   return load_raw == &LibRaw::nikon_coolscan_load_raw;
  239 | }
  240 | int LibRaw::is_jpeg_thumb()
  241 | {
  242 |   return libraw_internal_data.unpacker_data.thumb_format == LIBRAW_INTERNAL_THUMBNAIL_JPEG;
  243 | }
  244 |
  245 | int LibRaw::is_nikon_sraw() { return load_raw == &LibRaw::nikon_load_sraw; }
  246 | int LibRaw::sraw_midpoint()
  247 | {
  248 |   if (load_raw == &LibRaw::canon_sraw_load_raw)
  249 |     return 8192;
  250 |   else if (load_raw == &LibRaw::sony_ycbcr_load_raw)
  251 |     return 8192; // adjusted as in canon sRAW
  252 |   else if (load_raw == &LibRaw::nikon_load_sraw)
  253 |     return 2048;
  254 |   else
  255 |     return 0;
  256 | }
  257 |
  258 | void *LibRaw::malloc(size_t t)
  259 | {
  260 |   void *p = memmgr.malloc(t);
  261 |   if (!p)
  262 |     throw LIBRAW_EXCEPTION_ALLOC;
  263 |   return p;
  264 | }
  265 | void *LibRaw::realloc(void *q, size_t t)
  266 | {
  267 |   void *p = memmgr.realloc(q, t);
  268 |   if (!p)
  269 |     throw LIBRAW_EXCEPTION_ALLOC;
  270 |   return p;
  271 | }
  272 |
  273 | void *LibRaw::calloc(size_t n, size_t t)
  274 | {
  275 |   void *p = memmgr.calloc(n, t);
  276 |   if (!p)
  277 |     throw LIBRAW_EXCEPTION_ALLOC;
  278 |   return p;
  279 | }
  280 | void LibRaw::free(void *p) { memmgr.free(p); }
  281 |
  282 | void LibRaw::recycle_datastream()
  283 | {
  284 |   if (libraw_internal_data.internal_data.input &&
  285 |       libraw_internal_data.internal_data.input_internal)
  286 |   {
  287 |     delete libraw_internal_data.internal_data.input;
  288 |     libraw_internal_data.internal_data.input = NULL;
  289 |   }
  290 |   libraw_internal_data.internal_data.input_internal = 0;
  291 | }
  292 |
  293 | void LibRaw::clearCancelFlag()
  294 | {
  295 | #ifdef _MSC_VER
  296 |   InterlockedExchange(&_exitflag, 0);
  297 | #else
  298 |   __sync_fetch_and_and(&_exitflag, 0);
  299 | #endif
  300 | #ifdef RAWSPEED_FASTEXIT
  301 |   if (_rawspeed_decoder)
  302 |   {
  303 |     RawSpeed::RawDecoder *d =
  304 |         static_cast<RawSpeed::RawDecoder *>(_rawspeed_decoder);
  305 |     d->resumeProcessing();
  306 |   }
  307 | #endif
  308 | }
  309 |
  310 | void LibRaw::setCancelFlag()
  311 | {
  312 | #ifdef _MSC_VER
  313 |   InterlockedExchange(&_exitflag, 1);
  314 | #else
  315 |   __sync_fetch_and_add(&_exitflag, 1);
  316 | #endif
  317 | #ifdef RAWSPEED_FASTEXIT
  318 |   if (_rawspeed_decoder)
  319 |   {
  320 |     RawSpeed::RawDecoder *d =
  321 |         static_cast<RawSpeed::RawDecoder *>(_rawspeed_decoder);
  322 |     d->cancelProcessing();
  323 |   }
  324 | #endif
  325 | }
  326 |
  327 | void LibRaw::checkCancel()
  328 | {
  329 | #ifdef _MSC_VER
  330 |   if (InterlockedExchange(&_exitflag, 0))
  331 |     throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK;
  332 | #else
  333 |   if (__sync_fetch_and_and(&_exitflag, 0))
> 334 |     throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK;
  335 | #endif
  336 | }
  337 |
  338 | int LibRaw::is_curve_linear()
  339 | {
  340 |   for (int i = 0; i < 0x10000; i++)
  341 |     if (imgdata.color.curve[i] != i)
  342 |       return 0;
  343 |   return 1;
  344 | }
  345 |
  346 | void LibRaw::free_image(void)
  347 | {
  348 |   if (imgdata.image)
  349 |   {
  350 |     free(imgdata.image);
  351 |     imgdata.image = 0;
  352 |     imgdata.progress_flags = LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN |
  353 |                              LIBRAW_PROGRESS_IDENTIFY |
  354 |                              LIBRAW_PROGRESS_SIZE_ADJUST |
  355 |                              LIBRAW_PROGRESS_LOAD_RAW;
  356 |   }
  357 | }
  358 |
  359 | int LibRaw::is_phaseone_compressed()
  360 | {
  361 |   return (load_raw == &LibRaw::phase_one_load_raw_c ||
  362 | 		  load_raw == &LibRaw::phase_one_load_raw_s ||
  363 |           load_raw == &LibRaw::phase_one_load_raw);
  364 | }
  365 |
  366 | int LibRaw::is_canon_600() { return load_raw == &LibRaw::canon_600_load_raw; }
  367 | const char *LibRaw::strprogress(enum LibRaw_progress p)
  368 | {
  369 |   switch (p)
  370 |   {
  371 |   case LIBRAW_PROGRESS_START:
  372 |     return "Starting";
  373 |   case LIBRAW_PROGRESS_OPEN:
  374 |     return "Opening file";
  375 |   case LIBRAW_PROGRESS_IDENTIFY:
  376 |     return "Reading metadata";
  377 |   case LIBRAW_PROGRESS_SIZE_ADJUST:
  378 |     return "Adjusting size";
  379 |   case LIBRAW_PROGRESS_LOAD_RAW:
  380 |     return "Reading RAW data";
  381 |   case LIBRAW_PROGRESS_REMOVE_ZEROES:
  382 |     return "Clearing zero values";
  383 |   case LIBRAW_PROGRESS_BAD_PIXELS:
  384 |     return "Removing dead pixels";
  385 |   case LIBRAW_PROGRESS_DARK_FRAME:
  386 |     return "Subtracting dark frame data";
  387 |   case LIBRAW_PROGRESS_FOVEON_INTERPOLATE:
  388 |     return "Interpolating Foveon sensor data";
  389 |   case LIBRAW_PROGRESS_SCALE_COLORS:
  390 |     return "Scaling colors";
  391 |   case LIBRAW_PROGRESS_PRE_INTERPOLATE:
  392 |     return "Pre-interpolating";
  393 |   case LIBRAW_PROGRESS_INTERPOLATE:
  394 |     return "Interpolating";
  395 |   case LIBRAW_PROGRESS_MIX_GREEN:
  396 |     return "Mixing green channels";
  397 |   case LIBRAW_PROGRESS_MEDIAN_FILTER:
  398 |     return "Median filter";
  399 |   case LIBRAW_PROGRESS_HIGHLIGHTS:
  400 |     return "Highlight recovery";
  401 |   case LIBRAW_PROGRESS_FUJI_ROTATE:
  402 |     return "Rotating Fuji diagonal data";
  403 |   case LIBRAW_PROGRESS_FLIP:
  404 |     return "Flipping image";
  405 |   case LIBRAW_PROGRESS_APPLY_PROFILE:
  406 |     return "ICC conversion";
  407 |   case LIBRAW_PROGRESS_CONVERT_RGB:
  408 |     return "Converting to RGB";
  409 |   case LIBRAW_PROGRESS_STRETCH:
  410 |     return "Stretching image";
  411 |   case LIBRAW_PROGRESS_THUMB_LOAD:
  412 |     return "Loading thumbnail";
  413 |   default:
  414 |     return "Some strange things";
  415 |   }
  416 | }
  417 | int LibRaw::adjust_sizes_info_only(void)
  418 | {
  419 |   CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
  420 |
  421 |   raw2image_start();
  422 |   if (O.use_fuji_rotate)
  423 |   {
  424 |     if (IO.fuji_width)
  425 |     {
  426 |       IO.fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink;
  427 |       S.iwidth = (ushort)(IO.fuji_width / sqrt(0.5));
  428 |       S.iheight = (ushort)((S.iheight - IO.fuji_width) / sqrt(0.5));
  429 |     }
  430 |     else
  431 |     {
  432 |       if (S.pixel_aspect < 0.995)
  433 |         S.iheight = (ushort)(S.iheight / S.pixel_aspect + 0.5);
  434 |       if (S.pixel_aspect > 1.005)

Reach line at /src/libraw/src/utils/utils_libraw.cpp:334 (observed count 0).


  462 |       !strcmp(buf, "PENTAX "))
  463 |   {
  464 |     base = ftell(ifp) - 10;
  465 |     fseek(ifp, -2, SEEK_CUR);
  466 | 	if (buf[1] == 'M')
  467 | 		get4();
  468 |     order = get2();
  469 |     if (buf[0] == 'O')
  470 |       get2();
  471 |   }
  472 |   else if (!strncmp(buf, "SONY", 4) || // DSLR-A100
  473 |            !strcmp(buf, "Panasonic")) {
  474 |     if (buf[0] == 'S')
  475 |       is_Sony = 1;
  476 |     goto nf;
  477 |   }
  478 |   else if (!strncmp(buf, "FUJIFILM", 8))
  479 |   {
  480 |     base = ftell(ifp) - 10;
  481 |   nf:
  482 |     order = 0x4949;
  483 |     fseek(ifp, 2, SEEK_CUR);
  484 |   }
  485 |   else if (!strcmp (buf, "OLYMP")    ||
  486 |            !strncmp(buf, "LEICA", 5) ||
  487 |            !strcmp (buf, "Ricoh"))
  488 |   {
  489 |     fseek(ifp, -2, SEEK_CUR);
  490 |   }
  491 |   else if (!strcmp(buf, "AOC") || // Pentax, tribute to Asahi Optical Co.
  492 |            !strcmp(buf, "QVC"))   // Casio, from "QV-Camera"
  493 |   {
  494 |     fseek(ifp, -4, SEEK_CUR);
  495 |   }
  496 |   else if (!strncmp(buf, "CMT3", 4))
  497 |   {
  498 |     order = sget2((uchar *)(buf + 4));
  499 |     fseek(ifp, 2L, SEEK_CUR);
  500 |   }
  501 |   else if (libraw_internal_data.unpacker_data.CR3_CTMDtag)
  502 |   {
  503 |     order = sget2((uchar *)buf);
  504 |     fseek(ifp, -2L, SEEK_CUR);
  505 |   }
  506 |   else
  507 |   {
  508 |     fseek(ifp, -10, SEEK_CUR);
  509 |     if (!strncmp(make, "SAMSUNG", 7))
  510 |       base = ftell(ifp);
  511 |   }
  512 |
  513 |   if (!is_Olympus &&
  514 |       (!strncasecmp(make, "Olympus", 7) || !strncmp(make, "OM Digi", 7) ||
  515 |       (!strncasecmp(make, "CLAUSS", 6) && !strncasecmp(model, "piX 5oo", 7)))) {
  516 |     is_Olympus = 1;
  517 |   }
  518 |
  519 |   if (!is_Sony &&
  520 |       (!strncasecmp(make, "SONY", 4) ||
  521 |        !strncasecmp(make, "Konica", 6) ||
  522 |        !strncasecmp(make, "Minolta", 7) ||
  523 |        (!strncasecmp(make, "Hasselblad", 10) &&
  524 |         (!strncasecmp(model, "Stellar", 7) ||
  525 |          !strncasecmp(model, "Lunar", 5) ||
  526 |          !strncasecmp(model, "Lusso", 5) ||
  527 |          !strncasecmp(model, "HV", 2))))) {
  528 |     is_Sony = 1;
  529 |   }
  530 |
  531 |   if (strcasestr(make, "Kodak") &&
  532 |       (sget2((uchar *)buf) > 1) && // check number of entries
  533 |       (sget2((uchar *)buf) < 128) &&
  534 |       (sget2((uchar *)(buf + 4)) > 0) && // check type
  535 |       (sget2((uchar *)(buf + 4)) < 13) &&
  536 |       (sget4((uchar *)(buf + 6)) < 256) // check count
  537 |   )
  538 |     imKodak.MakerNoteKodak8a = 1; // Kodak P712 / P850 / P880
  539 |
  540 |   entries = get2();
  541 |   if (entries > 1000)
  542 |     return;
  543 |
  544 |   morder = order;
  545 |   while (entries--)
  546 |   {
  547 |     order = morder;
  548 |     tiff_get(base, &tag, &type, &len, &save);
  549 |     tag |= uptag << 16;
  550 |
  551 |     INT64 _pos = ftell(ifp);
  552 |     if (len > 100 * 1024 * 1024)
  553 | 	goto next; // 100Mb tag? No!
  554 |     if (len > 8 && _pos + len > 2 * fsize)
  555 |     {
  556 |       fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
  557 |       continue;
  558 |     }
  559 |
  560 | 	if (callbacks.makernotes_cb)
  561 |     {
> 562 |       INT64 _savepos = ifp->tell();
  563 |       callbacks.makernotes_cb(callbacks.makernotesparser_data, tag, type, len, order, ifp, base);
  564 |       fseek(ifp, _savepos, SEEK_SET);
  565 |     }
  566 |
  567 |     if (imKodak.MakerNoteKodak8a)
  568 |     {
  569 |       if ((tag == 0xff00) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG) && (len == 1))
  570 |       {
  571 |         INT64 _pos1 = get4();
  572 |         if ((_pos1 < fsize) && (_pos1 > 0))
  573 |         {
  574 |           fseek(ifp, _pos1, SEEK_SET);
  575 |           parse_makernote(base, tag);
  576 |         }
  577 |       }
  578 |       else if (tag == 0xff00f90b)
  579 |       {
  580 |         imKodak.clipBlack = get2();
  581 |       }
  582 |       else if (tag == 0xff00f90c)
  583 |       {
  584 |         imKodak.clipWhite = imgdata.color.linear_max[0] =
  585 |             imgdata.color.linear_max[1] = imgdata.color.linear_max[2] =
  586 |                 imgdata.color.linear_max[3] = get2();
  587 |       }
  588 |     }
  589 |     else if (!strncmp(make, "Canon", 5))
  590 |     {
  591 |       if (tag == 0x000d && len < 256000) // camera info
  592 |       {
  593 |         if (!tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
  594 |         {
  595 |           CanonCameraInfo = (uchar *)calloc(MAX(16, len)+1,1);
  596 |           fread(CanonCameraInfo, len, 1, ifp);
  597 |         }
  598 |         else
  599 |         {
  600 |           CanonCameraInfo = (uchar *)calloc(MAX(16, len * 4)+1,1);
  601 |           fread(CanonCameraInfo, len, 4, ifp);
  602 |         }
  603 |         lenCanonCameraInfo = len;
  604 |         typeCanonCameraInfo = type;
  605 |       }
  606 |
  607 |       else if (tag == 0x0010) // Canon ModelID
  608 |       {
  609 |         unique_id = get4();
  610 |         setCanonBodyFeatures(unique_id);
  611 |         if (lenCanonCameraInfo)
  612 |         {
  613 |           processCanonCameraInfo(unique_id, CanonCameraInfo, lenCanonCameraInfo,
  614 |                                  typeCanonCameraInfo, nonDNG);
  615 | 	  if(CanonCameraInfo)
  616 |             free(CanonCameraInfo);
  617 |           CanonCameraInfo = 0;
  618 |           lenCanonCameraInfo = 0;
  619 |         }
  620 |       }
  621 |
  622 |       else
  623 |         parseCanonMakernotes(tag, type, len, nonDNG);
  624 |     }
  625 |
  626 |     else if (!strncmp(make, "FUJI", 4))
  627 |       parseFujiMakernotes(tag, type, len, nonDNG);
  628 |
  629 |     else if (!strncasecmp(model, "Hasselblad X1D", 14) ||
  630 |              !strncasecmp(model, "Hasselblad H6D", 14) ||
  631 |              !strncasecmp(model, "Hasselblad A6D", 14))
  632 |     {
  633 |       if (tag == 0x0045)
  634 |       {
  635 |         imHassy.BaseISO = get4();
  636 |       }
  637 |       else if (tag == 0x0046)
  638 |       {
  639 |         imHassy.Gain = getreal(type);
  640 |       }
  641 |     }
  642 |
  643 |     else if (!strncmp(make, "PENTAX", 6) ||
  644 |              !strncmp(make, "RICOH", 5) ||
  645 |              !strncmp(model, "PENTAX", 6))
  646 |     {
  647 |       if (!strncmp(model, "GR", 2) ||
  648 |           !strncmp(model, "GXR", 3))
  649 |       {
  650 |         parseRicohMakernotes(base, tag, type, len, CameraDNG);
  651 |       }
  652 |       else
  653 |       {
  654 |         parsePentaxMakernotes(base, tag, type, len, nonDNG);
  655 |       }
  656 |     }
  657 |
  658 |     else if (!strncmp(make, "SAMSUNG", 7))
  659 |     {
  660 |       if (!dng_version)
  661 |         parseSamsungMakernotes(base, tag, type, len, nonDNG);
  662 |       else

Reach line at /src/libraw/src/metadata/makernotes.cpp:562 (observed count 0).


  537 |
  538 | bool ROMol::hasQuery() const {
  539 |   for (auto atom : atoms()) {
  540 |     if (atom->hasQuery()) {
  541 |       return true;
  542 |     }
  543 |   }
  544 |   for (auto bond : bonds()) {
  545 |     if (bond->hasQuery()) {
  546 |       return true;
  547 |     }
  548 |   }
  549 |   return false;
  550 | }
  551 |
  552 | ROMol::QueryAtomIterator ROMol::beginQueryAtoms(QueryAtom const *what) {
  553 |   return QueryAtomIterator(this, what);
  554 | }
  555 | ROMol::ConstQueryAtomIterator ROMol::beginQueryAtoms(
  556 |     QueryAtom const *what) const {
  557 |   return ConstQueryAtomIterator(this, what);
  558 | }
  559 | ROMol::QueryAtomIterator ROMol::endQueryAtoms() {
  560 |   return QueryAtomIterator(this, getNumAtoms());
  561 | }
  562 | ROMol::ConstQueryAtomIterator ROMol::endQueryAtoms() const {
  563 |   return ConstQueryAtomIterator(this, getNumAtoms());
  564 | }
  565 | ROMol::MatchingAtomIterator ROMol::beginMatchingAtoms(bool (*what)(Atom *)) {
  566 |   return MatchingAtomIterator(this, what);
  567 | }
  568 | ROMol::ConstMatchingAtomIterator ROMol::beginMatchingAtoms(
  569 |     bool (*what)(const Atom *)) const {
  570 |   return ConstMatchingAtomIterator(this, what);
  571 | }
  572 | ROMol::MatchingAtomIterator ROMol::endMatchingAtoms() {
  573 |   return MatchingAtomIterator(this, getNumAtoms());
  574 | }
  575 | ROMol::ConstMatchingAtomIterator ROMol::endMatchingAtoms() const {
  576 |   return ConstMatchingAtomIterator(this, getNumAtoms());
  577 | }
  578 |
  579 | ROMol::BondIterator ROMol::beginBonds() { return BondIterator(this); }
  580 | ROMol::ConstBondIterator ROMol::beginBonds() const {
  581 |   return ConstBondIterator(this);
  582 | }
  583 | ROMol::BondIterator ROMol::endBonds() {
  584 |   auto [beg, end] = getEdges();
  585 |   return BondIterator(this, end);
  586 | }
  587 | ROMol::ConstBondIterator ROMol::endBonds() const {
  588 |   auto [beg, end] = getEdges();
  589 |   return ConstBondIterator(this, end);
  590 | }
  591 |
  592 | void ROMol::clearComputedProps(bool includeRings) const {
  593 |   // the SSSR information:
  594 |   if (includeRings) {
  595 |     this->dp_ringInfo->reset();
  596 |   }
  597 |
  598 |   RDProps::clearComputedProps();
  599 |
  600 |   for (auto atom : atoms()) {
  601 |     atom->clearComputedProps();
  602 |   }
  603 |
  604 |   for (auto bond : bonds()) {
  605 |     bond->clearComputedProps();
  606 |   }
  607 | }
  608 |
  609 | void ROMol::updatePropertyCache(bool strict) {
  610 |   for (auto atom : atoms()) {
  611 |     atom->updatePropertyCache(strict);
  612 |   }
  613 |   for (auto bond : bonds()) {
  614 |     bond->updatePropertyCache(strict);
  615 |   }
  616 | }
  617 |
  618 | bool ROMol::needsUpdatePropertyCache() const {
  619 |   for (const auto atom : atoms()) {
  620 |     if (atom->needsUpdatePropertyCache()) {
  621 |       return true;
  622 |     }
  623 |   }
  624 |   // there is no test for bonds yet since they do not obtain a valence property
  625 |   return false;
  626 | }
  627 |
  628 | void ROMol::clearPropertyCache() {
  629 |   for (auto atom : atoms()) {
  630 |     atom->clearPropertyCache();
  631 |   }
  632 | }
  633 |
  634 | const Conformer &ROMol::getConformer(int id) const {
  635 |   // make sure we have more than one conformation
  636 |   if (d_confs.size() == 0) {
> 637 |     throw ConformerException("No conformations available on the molecule");
  638 |   }
  639 |
  640 |   if (id < 0) {
  641 |     return *(d_confs.front());
  642 |   }
  643 |   auto cid = (unsigned int)id;
  644 |   for (auto conf : d_confs) {
  645 |     if (conf->getId() == cid) {
  646 |       return *conf;
  647 |     }
  648 |   }
  649 |   // we did not find a conformation with the specified ID
  650 |   std::string mesg = "Can't find conformation with ID: ";
  651 |   mesg += id;
  652 |   throw ConformerException(mesg);
  653 | }
  654 |
  655 | Conformer &ROMol::getConformer(int id) {
  656 |   return const_cast<Conformer &>(
  657 |       static_cast<const ROMol *>(this)->getConformer(id));
  658 | }
  659 |
  660 | void ROMol::removeConformer(unsigned int id) {
  661 |   for (auto ci = d_confs.begin(); ci != d_confs.end(); ++ci) {
  662 |     if ((*ci)->getId() == id) {
  663 |       d_confs.erase(ci);
  664 |       return;
  665 |     }
  666 |   }
  667 | }
  668 |
  669 | unsigned int ROMol::addConformer(Conformer *conf, bool assignId) {
  670 |   PRECONDITION(conf, "bad conformer");
  671 |   PRECONDITION(conf->getNumAtoms() == this->getNumAtoms(),
  672 |                "Number of atom mismatch");
  673 |   if (assignId) {
  674 |     int maxId = -1;
  675 |     for (auto cptr : d_confs) {
  676 |       maxId = std::max((int)(cptr->getId()), maxId);
  677 |     }
  678 |     maxId++;
  679 |     conf->setId((unsigned int)maxId);
  680 |   }
  681 |   conf->setOwningMol(this);
  682 |   CONFORMER_SPTR nConf(conf);
  683 |   d_confs.push_back(nConf);
  684 |   return conf->getId();
  685 | }
  686 |
  687 | #ifdef RDK_USE_BOOST_SERIALIZATION
  688 | template <class Archive>
  689 | void ROMol::save(Archive &ar, const unsigned int) const {
  690 |   std::string pkl;
  691 |   MolPickler::pickleMol(*this, pkl, PicklerOps::AllProps);
  692 |   ar << pkl;
  693 | }
  694 |
  695 | template <class Archive>
  696 | void ROMol::load(Archive &ar, const unsigned int) {
  697 |   std::string pkl;
  698 |   ar >> pkl;
  699 |
  700 |   delete dp_ringInfo;
  701 |   initMol();
  702 |
  703 |   numBonds = 0;
  704 |   MolPickler::molFromPickle(pkl, *this, PicklerOps::AllProps);
  705 |   numBonds = rdcast<unsigned int>(boost::num_edges(d_graph));
  706 | }
  707 |
  708 | template RDKIT_GRAPHMOL_EXPORT void ROMol::save<boost::archive::text_oarchive>(
  709 |     boost::archive::text_oarchive &, const unsigned int) const;
  710 | template RDKIT_GRAPHMOL_EXPORT void ROMol::load<boost::archive::text_iarchive>(
  711 |     boost::archive::text_iarchive &, const unsigned int);
  712 | #endif
  713 |
  714 | }  // namespace RDKit

Reach line at /src/rdkit/Code/GraphMol/ROMol.cpp:637 (observed count 0).


  255 |   template <typename T>
  256 |   bool getValIfPresent(const std::string_view what, T &res) const {
  257 |     for (const auto &data : _data) {
  258 |       if (data.key == what) {
  259 |         res = from_rdvalue<T>(data.val);
  260 |         return true;
  261 |       }
  262 |     }
  263 |     return false;
  264 |   }
  265 |
  266 |   //! \overload
  267 |   bool getValIfPresent(const std::string_view what, std::string &res) const {
  268 |     for (const auto &i : _data) {
  269 |       if (i.key == what) {
  270 |         rdvalue_tostring(i.val, res);
  271 |         return true;
  272 |       }
  273 |     }
  274 |     return false;
  275 |   }
  276 |
  277 |   //----------------------------------------------------------
  278 |   //! \brief Sets the value associated with a key
  279 |   /*!
  280 |
  281 |      \param what the key to set
  282 |      \param val  the value to store
  283 |
  284 |      <b>Notes:</b>
  285 |         - If \c val is a <tt>const char *</tt>, it will be converted
  286 |            to a \c std::string for storage.
  287 |         - If the dictionary already contains the key \c what,
  288 |           the value will be replaced.
  289 |   */
  290 |   template <typename T>
  291 |   void setVal(const std::string_view what, T &val) {
  292 |     static_assert(!std::is_same_v<T, std::string_view>,
  293 |                   "T cannot be string_view");
  294 |     if (what.empty()) {
  295 |       throw ValueErrorException("Cannot set value with empty key");
  296 |     }
  297 |     _hasNonPodData = true;
  298 |     for (auto &&data : _data) {
  299 |       if (data.key == what) {
  300 |         RDValue::cleanup_rdvalue(data.val);
  301 |         data.val = val;
  302 |         return;
  303 |       }
  304 |     }
  305 |     _data.push_back(Pair(what, val));
  306 |   }
  307 |
  308 |   template <typename T>
  309 |   void setPODVal(const std::string_view what, T val) {
  310 |     static_assert(!std::is_same_v<T, std::string_view>,
  311 |                   "T cannot be string_view");
  312 |     if (what.empty()) {
  313 |       throw ValueErrorException("Cannot set value with empty key");
  314 |     }
  315 |     // don't change the hasNonPodData status
  316 |     for (auto &&data : _data) {
  317 |       if (data.key == what) {
  318 |         RDValue::cleanup_rdvalue(data.val);
  319 |         data.val = val;
  320 |         return;
  321 |       }
  322 |     }
  323 |     _data.push_back(Pair(what, val));
  324 |   }
  325 |
  326 |   void setVal(const std::string_view what, bool val) {
  327 |     if (what.empty()) {
  328 |       throw ValueErrorException("Cannot set value with empty key");
  329 |     }
  330 |     setPODVal(what, val);
  331 |   }
  332 |
  333 |   void setVal(const std::string_view what, double val) {
  334 |     if (what.empty()) {
  335 |       throw ValueErrorException("Cannot set value with empty key");
  336 |     }
  337 |     setPODVal(what, val);
  338 |   }
  339 |
  340 |   void setVal(const std::string_view what, float val) {
  341 |     if (what.empty()) {
  342 |       throw ValueErrorException("Cannot set value with empty key");
  343 |     }
  344 |     setPODVal(what, val);
  345 |   }
  346 |   void setVal(const std::string_view what, int val) {
  347 |     if (what.empty()) {
  348 |       throw ValueErrorException("Cannot set value with empty key");
  349 |     }
  350 |     setPODVal(what, val);
  351 |   }
  352 |
  353 |   void setVal(const std::string_view what, unsigned int val) {
  354 |     if (what.empty()) {
> 355 |       throw ValueErrorException("Cannot set value with empty key");
  356 |     }
  357 |     setPODVal(what, val);
  358 |   }
  359 |
  360 |   //! \overload
  361 |   void setVal(const std::string_view what, const char *val) {
  362 |     if (what.empty()) {
  363 |       throw ValueErrorException("Cannot set value with empty key");
  364 |     }
  365 |     std::string h(val);
  366 |     setVal(what, h);
  367 |   }
  368 |
  369 |   //----------------------------------------------------------
  370 |   //! \brief Clears the value associated with a particular key,
  371 |   //!     removing the key from the dictionary.
  372 |   /*!
  373 |
  374 |      \param what the key to clear
  375 |
  376 |   */
  377 |   void clearVal(const std::string_view what) {
  378 |     for (auto it = _data.begin(); it < _data.end(); ++it) {
  379 |       if (it->key == what) {
  380 |         if (_hasNonPodData) {
  381 |           RDValue::cleanup_rdvalue(it->val);
  382 |         }
  383 |         _data.erase(it);
  384 |         return;
  385 |       }
  386 |     }
  387 |   }
  388 |
  389 |   //----------------------------------------------------------
  390 |   //! \brief Clears all keys (and values) from the dictionary.
  391 |   //!
  392 |   void reset() {
  393 |     if (_hasNonPodData) {
  394 |       for (auto &&data : _data) {
  395 |         RDValue::cleanup_rdvalue(data.val);
  396 |       }
  397 |     }
  398 |     DataType data;
  399 |     _data.swap(data);
  400 |   }
  401 |
  402 |  private:
  403 |   DataType _data{};            //!< the actual dictionary
  404 |   bool _hasNonPodData{false};  // if true, need a deep copy
  405 |                                //  (copy_rdvalue)
  406 | };
  407 |
  408 | template <>
  409 | inline std::string Dict::getVal<std::string>(
  410 |     const std::string_view what) const {
  411 |   std::string res;
  412 |   getVal(what, res);
  413 |   return res;
  414 | }
  415 |
  416 | // Utility class for holding a Dict::Pair
  417 | //  Dict::Pairs require containers for memory management
  418 | //  This utility class covers cleanup and copying
  419 | class PairHolder : public Dict::Pair {
  420 |  public:
  421 |   PairHolder() : Pair() {}
  422 |
  423 |   explicit PairHolder(const PairHolder &p) : Pair(p.key) {
  424 |     copy_rdvalue(this->val, p.val);
  425 |   }
  426 |
  427 |   explicit PairHolder(PairHolder &&p) : Pair(p.key) {
  428 |     this->val = p.val;
  429 |     p.val.type = RDTypeTag::EmptyTag;
  430 |   }
  431 |
  432 |   explicit PairHolder(Dict::Pair &&p) : Pair(p.key) {
  433 |     this->val = p.val;
  434 |     p.val.type = RDTypeTag::EmptyTag;
  435 |   }
  436 |
  437 |   ~PairHolder() { RDValue::cleanup_rdvalue(this->val); }
  438 | };
  439 | }  // namespace RDKit
  440 | #endif

Reach line at /src/rdkit/Code/RDGeneral/Dict.h:355 (observed count 0).


228 |   }
  229 |
  230 |   //! \overload
  231 |   void getVal(const std::string_view what, std::string &res) const {
  232 |     for (const auto &i : _data) {
  233 |       if (i.key == what) {
  234 |         rdvalue_tostring(i.val, res);
  235 |         return;
  236 |       }
  237 |     }
  238 |     throw KeyErrorException(what);
  239 |   }
  240 |
  241 |   //----------------------------------------------------------
  242 |   //! \brief Potentially gets the value associated with a particular key
  243 |   //!        returns true on success/false on failure.
  244 |   /*!
  245 |      \param what  the key to lookup
  246 |      \param res   a reference used to return the result
  247 |
  248 |      Notes:
  249 |       - If \c res is a \c std::string, every effort will be made
  250 |         to convert the specified element to a string using the
  251 |         \c boost::lexical_cast machinery.
  252 |       - If the dictionary does not contain the key \c what,
  253 |         a KeyErrorException will be thrown.
  254 |   */
  255 |   template <typename T>
  256 |   bool getValIfPresent(const std::string_view what, T &res) const {
  257 |     for (const auto &data : _data) {
  258 |       if (data.key == what) {
  259 |         res = from_rdvalue<T>(data.val);
  260 |         return true;
  261 |       }
  262 |     }
  263 |     return false;
  264 |   }
  265 |
  266 |   //! \overload
  267 |   bool getValIfPresent(const std::string_view what, std::string &res) const {
  268 |     for (const auto &i : _data) {
  269 |       if (i.key == what) {
  270 |         rdvalue_tostring(i.val, res);
  271 |         return true;
  272 |       }
  273 |     }
  274 |     return false;
  275 |   }
  276 |
  277 |   //----------------------------------------------------------
  278 |   //! \brief Sets the value associated with a key
  279 |   /*!
  280 |
  281 |      \param what the key to set
  282 |      \param val  the value to store
  283 |
  284 |      Notes:
  285 |         - If \c val is a <tt>const char *</tt>, it will be converted
  286 |            to a \c std::string for storage.
  287 |         - If the dictionary already contains the key \c what,
  288 |           the value will be replaced.
  289 |   */
  290 |   template <typename T>
  291 |   void setVal(const std::string_view what, T &val) {
  292 |     static_assert(!std::is_same_v<T, std::string_view>,
  293 |                   "T cannot be string_view");
  294 |     if (what.empty()) {
  295 |       throw ValueErrorException("Cannot set value with empty key");
  296 |     }
  297 |     _hasNonPodData = true;
  298 |     for (auto &&data : _data) {
  299 |       if (data.key == what) {
  300 |         RDValue::cleanup_rdvalue(data.val);
  301 |         data.val = val;
  302 |         return;
  303 |       }
  304 |     }
  305 |     _data.push_back(Pair(what, val));
  306 |   }
  307 |
  308 |   template <typename T>
  309 |   void setPODVal(const std::string_view what, T val) {
  310 |     static_assert(!std::is_same_v<T, std::string_view>,
  311 |                   "T cannot be string_view");
  312 |     if (what.empty()) {
  313 |       throw ValueErrorException("Cannot set value with empty key");
  314 |     }
  315 |     // don't change the hasNonPodData status
  316 |     for (auto &&data : _data) {
  317 |       if (data.key == what) {
  318 |         RDValue::cleanup_rdvalue(data.val);
  319 |         data.val = val;
  320 |         return;
  321 |       }
  322 |     }
  323 |     _data.push_back(Pair(what, val));
  324 |   }
  325 |
  326 |   void setVal(const std::string_view what, bool val) {
  327 |     if (what.empty()) {
> 328 |       throw ValueErrorException("Cannot set value with empty key");
  329 |     }
  330 |     setPODVal(what, val);
  331 |   }
  332 |
  333 |   void setVal(const std::string_view what, double val) {
  334 |     if (what.empty()) {
  335 |       throw ValueErrorException("Cannot set value with empty key");
  336 |     }
  337 |     setPODVal(what, val);
  338 |   }
  339 |
  340 |   void setVal(const std::string_view what, float val) {
  341 |     if (what.empty()) {
  342 |       throw ValueErrorException("Cannot set value with empty key");
  343 |     }
  344 |     setPODVal(what, val);
  345 |   }
  346 |   void setVal(const std::string_view what, int val) {
  347 |     if (what.empty()) {
  348 |       throw ValueErrorException("Cannot set value with empty key");
  349 |     }
  350 |     setPODVal(what, val);
  351 |   }
  352 |
  353 |   void setVal(const std::string_view what, unsigned int val) {
  354 |     if (what.empty()) {
  355 |       throw ValueErrorException("Cannot set value with empty key");
  356 |     }
  357 |     setPODVal(what, val);
  358 |   }
  359 |
  360 |   //! \overload
  361 |   void setVal(const std::string_view what, const char *val) {
  362 |     if (what.empty()) {
  363 |       throw ValueErrorException("Cannot set value with empty key");
  364 |     }
  365 |     std::string h(val);
  366 |     setVal(what, h);
  367 |   }
  368 |
  369 |   //----------------------------------------------------------
  370 |   //! \brief Clears the value associated with a particular key,
  371 |   //!     removing the key from the dictionary.
  372 |   /*!
  373 |
  374 |      \param what the key to clear
  375 |
  376 |   */
  377 |   void clearVal(const std::string_view what) {
  378 |     for (auto it = _data.begin(); it < _data.end(); ++it) {
  379 |       if (it->key == what) {
  380 |         if (_hasNonPodData) {
  381 |           RDValue::cleanup_rdvalue(it->val);
  382 |         }
  383 |         _data.erase(it);
  384 |         return;
  385 |       }
  386 |     }
  387 |   }
  388 |
  389 |   //----------------------------------------------------------
  390 |   //! \brief Clears all keys (and values) from the dictionary.
  391 |   //!
  392 |   void reset() {
  393 |     if (_hasNonPodData) {
  394 |       for (auto &&data : _data) {
  395 |         RDValue::cleanup_rdvalue(data.val);
  396 |       }
  397 |     }
  398 |     DataType data;
  399 |     _data.swap(data);
  400 |   }
  401 |
  402 |  private:
  403 |   DataType _data{};            //!< the actual dictionary
  404 |   bool _hasNonPodData{false};  // if true, need a deep copy
  405 |                                //  (copy_rdvalue)
  406 | };
  407 |
  408 | template <>
  409 | inline std::string Dict::getVal<std::string>(
  410 |     const std::string_view what) const {
  411 |   std::string res;
  412 |   getVal(what, res);
  413 |   return res;
  414 | }
  415 |
  416 | // Utility class for holding a Dict::Pair
  417 | //  Dict::Pairs require containers for memory management
  418 | //  This utility class covers cleanup and copying
  419 | class PairHolder : public Dict::Pair {
  420 |  public:
  421 |   PairHolder() : Pair() {}
  422 |
  423 |   explicit PairHolder(const PairHolder &p) : Pair(p.key) {
  424 |     copy_rdvalue(this->val, p.val);
  425 |   }
  426 |
  427 |   explicit PairHolder(PairHolder &&p) : Pair(p.key) {
  428 |     this->val = p.val;

Reach line at /src/rdkit/Code/RDGeneral/Dict.h:328 (observed count 0).


  148 |         dp_atomsInPlay(atomsInPlay),
  149 |         dp_bondsInPlay(bondsInPlay) {}
  150 |   int operator()(int i, int j) const {
  151 |     PRECONDITION(dp_atoms, "no atoms");
  152 |     PRECONDITION(dp_mol, "no molecule");
  153 |     PRECONDITION(i != j, "bad call");
  154 |     if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
  155 |       return 0;
  156 |     }
  157 |
  158 |     if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
  159 |       updateAtomNeighborIndex(dp_atoms, dp_atoms[i].bonds);
  160 |     }
  161 |     if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
  162 |       updateAtomNeighborIndex(dp_atoms, dp_atoms[j].bonds);
  163 |     }
  164 |     for (unsigned int ii = 0;
  165 |          ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
  166 |       int cmp =
  167 |           bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]);
  168 |       if (cmp) {
  169 |         return cmp;
  170 |       }
  171 |     }
  172 |
  173 |     std::vector<std::pair<unsigned int, unsigned int>> swapsi;
  174 |     std::vector<std::pair<unsigned int, unsigned int>> swapsj;
  175 |     if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
  176 |       updateAtomNeighborNumSwaps(dp_atoms, dp_atoms[i].bonds, i, swapsi);
  177 |     }
  178 |     if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
  179 |       updateAtomNeighborNumSwaps(dp_atoms, dp_atoms[j].bonds, j, swapsj);
  180 |     }
  181 |
  182 |     for (unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
  183 |       int cmp = swapsi[ii].second - swapsj[ii].second;
  184 |
  185 |       if (cmp) {
  186 |         return cmp;
  187 |       }
  188 |     }
  189 |
  190 |     return 0;
  191 |   }
  192 | };
  193 |
  194 | class RDKIT_GRAPHMOL_EXPORT SpecialSymmetryAtomCompareFunctor {
  195 |  public:
  196 |   Canon::canon_atom *dp_atoms{nullptr};
  197 |   const ROMol *dp_mol{nullptr};
  198 |   const boost::dynamic_bitset<> *dp_atomsInPlay{nullptr},
  199 |       *dp_bondsInPlay{nullptr};
  200 |
  201 |   SpecialSymmetryAtomCompareFunctor() {}
  202 |   SpecialSymmetryAtomCompareFunctor(
  203 |       Canon::canon_atom *atoms, const ROMol &m,
  204 |       const boost::dynamic_bitset<> *atomsInPlay = nullptr,
  205 |       const boost::dynamic_bitset<> *bondsInPlay = nullptr)
  206 |       : dp_atoms(atoms),
  207 |         dp_mol(&m),
  208 |         dp_atomsInPlay(atomsInPlay),
  209 |         dp_bondsInPlay(bondsInPlay) {}
  210 |   int operator()(int i, int j) const {
  211 |     PRECONDITION(dp_atoms, "no atoms");
  212 |     PRECONDITION(dp_mol, "no molecule");
  213 |     PRECONDITION(i != j, "bad call");
  214 |     if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
  215 |       return 0;
  216 |     }
  217 |
  218 |     if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) {
  219 |       return -1;
  220 |     } else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) {
  221 |       return 1;
  222 |     }
  223 |
  224 |     if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) {
  225 |       return -1;
  226 |     } else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) {
  227 |       return 1;
  228 |     }
  229 |
  230 |     if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
  231 |       updateAtomNeighborIndex(dp_atoms, dp_atoms[i].bonds);
  232 |     }
  233 |     if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
  234 |       updateAtomNeighborIndex(dp_atoms, dp_atoms[j].bonds);
  235 |     }
  236 |     for (unsigned int ii = 0;
  237 |          ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
  238 |       int cmp =
  239 |           bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]);
  240 |       if (cmp) {
  241 |         return cmp;
  242 |       }
  243 |     }
  244 |
  245 |     if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
  246 |       return -1;
  247 |     } else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
> 248 |       return 1;
  249 |     }
  250 |     return 0;
  251 |   }
  252 | };
  253 |
  254 | namespace {
  255 | unsigned int getChiralRank(const ROMol *dp_mol, canon_atom *dp_atoms,
  256 |                            unsigned int i) {
  257 |   unsigned int res = 0;
  258 |   std::vector<unsigned int> perm;
  259 |   perm.reserve(dp_atoms[i].atom->getDegree());
  260 |   for (const auto nbr : dp_mol->atomNeighbors(dp_atoms[i].atom)) {
  261 |     auto rnk = dp_atoms[nbr->getIdx()].index;
  262 |     // make sure we don't have duplicate ranks
  263 |     if (std::find(perm.begin(), perm.end(), rnk) != perm.end()) {
  264 |       break;
  265 |     } else {
  266 |       perm.push_back(rnk);
  267 |     }
  268 |   }
  269 |   if (perm.size() == dp_atoms[i].atom->getDegree()) {
  270 |     auto ctag = dp_atoms[i].atom->getChiralTag();
  271 |     if (ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CW ||
  272 |         ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CCW) {
  273 |       auto sortedPerm = perm;
  274 |       std::sort(sortedPerm.begin(), sortedPerm.end());
  275 |       auto nswaps = countSwapsToInterconvert(perm, sortedPerm);
  276 |       res = ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CW ? 2 : 1;
  277 |       if (nswaps % 2) {
  278 |         res = res == 2 ? 1 : 2;
  279 |       }
  280 |     }
  281 |   }
  282 |   return res;
  283 | }
  284 | }  // namespace
  285 | class RDKIT_GRAPHMOL_EXPORT AtomCompareFunctor {
  286 |   unsigned int getAtomRingNbrCode(unsigned int i) const {
  287 |     if (!dp_atoms[i].hasRingNbr) {
  288 |       return 0;
  289 |     }
  290 |
  291 |     auto nbrs = dp_atoms[i].nbrIds.get();
  292 |     unsigned int code = 0;
  293 |     for (unsigned j = 0; j < dp_atoms[i].degree; ++j) {
  294 |       if (dp_atoms[nbrs[j]].isRingStereoAtom) {
  295 |         code += dp_atoms[nbrs[j]].index * 10000 + 1;  // j;
  296 |       }
  297 |     }
  298 |     return code;
  299 |   }
  300 |
  301 |   int basecomp(int i, int j) const {
  302 |     unsigned int ivi, ivj;
  303 |
  304 |     // always start with the current class:
  305 |     ivi = dp_atoms[i].index;
  306 |     ivj = dp_atoms[j].index;
  307 |     if (ivi < ivj) {
  308 |       return -1;
  309 |     } else if (ivi > ivj) {
  310 |       return 1;
  311 |     }
  312 |
  313 |     if (df_useNonStereoRanks) {
  314 |       // use the non-stereo ranks if they were assigned
  315 |       int rankingNumber_i = 0;
  316 |       int rankingNumber_j = 0;
  317 |       dp_atoms[i].atom->getPropIfPresent(
  318 |           common_properties::_CanonicalRankingNumber, rankingNumber_i);
  319 |       dp_atoms[j].atom->getPropIfPresent(
  320 |           common_properties::_CanonicalRankingNumber, rankingNumber_j);
  321 |       if (rankingNumber_i < rankingNumber_j) {
  322 |         return -1;
  323 |       } else if (rankingNumber_i > rankingNumber_j) {
  324 |         return 1;
  325 |       }
  326 |     }
  327 |
  328 |     if (df_useAtomMaps || df_useAtomMapsOnDummies) {
  329 |       // use the atom-mapping numbers if they were assigned
  330 |       int molAtomMapNumber_i = 0;
  331 |       int molAtomMapNumber_j = 0;
  332 |       if (df_useAtomMaps ||
  333 |           (df_useAtomMapsOnDummies && dp_atoms[i].atom->getAtomicNum() == 0)) {
  334 |         dp_atoms[i].atom->getPropIfPresent(common_properties::molAtomMapNumber,
  335 |                                            molAtomMapNumber_i);
  336 |       }
  337 |       if (df_useAtomMaps ||
  338 |           (df_useAtomMapsOnDummies && dp_atoms[j].atom->getAtomicNum() == 0)) {
  339 |         dp_atoms[j].atom->getPropIfPresent(common_properties::molAtomMapNumber,
  340 |                                            molAtomMapNumber_j);
  341 |       }
  342 |       if (molAtomMapNumber_i < molAtomMapNumber_j) {
  343 |         return -1;
  344 |       } else if (molAtomMapNumber_i > molAtomMapNumber_j) {
  345 |         return 1;
  346 |       }
  347 |     }
  348 |     // start by comparing degree

Reach line at /src/rdkit/Code/GraphMol/new_canon.h:248 (observed count 0).


  319 |   curRs.push_back(fused.front());
  320 |   int pos = -1;
  321 |   unsigned int i;
  322 |   unsigned int curSize = 0;
  323 |   INT_VECT comb;
  324 |
  325 |   size_t nRingBonds;
  326 |   {
  327 |     boost::dynamic_bitset<> fusedBonds(mol.getNumBonds());
  328 |     for (auto ridx : fused) {
  329 |       for (auto bidx : brings[ridx]) {
  330 |         fusedBonds[bidx] = true;
  331 |       }
  332 |     }
  333 |     nRingBonds = rdcast<unsigned int>(fusedBonds.count());
  334 |   }
  335 |   std::set<unsigned int> doneBonds;
  336 |   while (1) {
  337 |     if (pos == -1) {
  338 |       // If a ring system has more than 300 rings and a ring combination search
  339 |       // larger than 2 is reached, the calculation becomes exponentially longer,
  340 |       // in some case it never completes.
  341 |       if ((curSize == 2) && (nrings > 300)) {
  342 |         BOOST_LOG(rdWarningLog)
  343 |             << "Aromaticity detection halted on some rings due to ring system size."
  344 |             << std::endl;
  345 |         break;
  346 |       }
  347 |
  348 |       ++curSize;
  349 |       // check if we are done with all the atoms in the fused
  350 |       // system, if so quit. This is a fix for Issue252 REVIEW: is
  351 |       // this check sufficient or should we add an additional
  352 |       // constraint on the number of combinations of rings in a
  353 |       // fused system that we will try. The number of combinations
  354 |       // can obviously be quite large when the number of rings in
  355 |       // the fused system is large
  356 |       if (curSize > std::min(nrings, maxNumFusedRings) ||
  357 |           doneBonds.size() >= nRingBonds) {
  358 |         break;
  359 |       }
  360 |       comb.resize(curSize);
  361 |       std::iota(comb.begin(), comb.end(), 0);
  362 |       pos = 0;
  363 |     } else {
  364 |       pos = nextCombination(comb, nrings);
  365 |     }
  366 |
  367 |     if (pos == -1) {
  368 |       continue;
  369 |     }
  370 |
  371 |     curRs.clear();
  372 |     std::transform(comb.begin(), comb.end(), std::back_inserter(curRs),
  373 |                    [&fused](const int i) { return fused[i]; });
  374 |
  375 |     // check if the picked subsystem is fused
  376 |     if (ringNeighs.size() && !RingUtils::checkFused(curRs, ringNeighs)) {
  377 |       continue;
  378 |     }
  379 |
  380 |     // check aromaticity on the current fused system
  381 |     INT_VECT atsInRingSystem(mol.getNumAtoms(), 0);
  382 |     for (auto ridx : curRs) {
  383 |       for (auto rid : srings[ridx]) {
  384 |         ++atsInRingSystem[rid];
  385 |       }
  386 |     }
  387 |     INT_VECT unon;
  388 |     for (i = 0; i < atsInRingSystem.size(); ++i) {
  389 |       // condition for inclusion of an atom in the aromaticity of a fused ring
  390 |       // system is that it's present in one or two of the rings. this was #2895:
  391 |       // the central atom in acepentalene was being included in the count of
  392 |       // aromatic atoms
  393 |       if (atsInRingSystem[i] == 1 || atsInRingSystem[i] == 2) {
  394 |         unon.push_back(i);
  395 |       }
  396 |     }
  397 |     if (applyHuckel(mol, unon, edon, minRingSize)) {
  398 |       // mark the atoms and bonds in these rings to be aromatic
  399 |       markAtomsBondsArom(brings, curRs, doneBonds, bondsByIdx);
  400 |
  401 |       // add the ring IDs to the aromatic rings found so far
  402 |       // avoid duplicates
  403 |       std::copy(curRs.begin(), curRs.end(),
  404 |                 std::inserter(aromRings, aromRings.begin()));
  405 |     }  // end check huckel rule
  406 |   }  // end while(1)
  407 |   narom += rdcast<int>(aromRings.size());
  408 | }
  409 |
  410 | bool isAtomCandForArom(const Atom *at, const ElectronDonorType edon,
  411 |                        bool allowThirdRow = true, bool allowTripleBonds = true,
  412 |                        bool allowHigherExceptions = true, bool onlyCorN = false,
  413 |                        bool allowExocyclicMultipleBonds = true) {
  414 |   PRECONDITION(at, "bad atom");
  415 |   if (onlyCorN && at->getAtomicNum() != 6 && at->getAtomicNum() != 7) {
  416 |     return false;
  417 |   }
  418 |   if (!allowThirdRow && at->getAtomicNum() > 10) {
> 419 |     return false;
  420 |   }
  421 |
  422 |   // limit aromaticity to:
  423 |   //   - the first two rows of the periodic table
  424 |   //   - Se and Te
  425 |   if (at->getAtomicNum() > 18 &&
  426 |       (!allowHigherExceptions ||
  427 |        (at->getAtomicNum() != 34 && at->getAtomicNum() != 52))) {
  428 |     return false;
  429 |   }
  430 |   switch (edon) {
  431 |     case VacantElectronDonorType:
  432 |     case OneElectronDonorType:
  433 |     case TwoElectronDonorType:
  434 |     case OneOrTwoElectronDonorType:
  435 |     case AnyElectronDonorType:
  436 |       break;
  437 |     default:
  438 |       return (false);
  439 |   }
  440 |
  441 |   // atoms that aren't in their default valence state also get shut out
  442 |   auto defVal =
  443 |       PeriodicTable::getTable()->getDefaultValence(at->getAtomicNum());
  444 |   if (defVal > 0 && rdcast<int>(at->getTotalValence()) >
  445 |                         (PeriodicTable::getTable()->getDefaultValence(
  446 |                             at->getAtomicNum() - at->getFormalCharge()))) {
  447 |     return false;
  448 |   }
  449 |
  450 |   // heteroatoms or charged carbons with radicals also disqualify us from being
  451 |   // considered. This was github issue 432 (heteroatoms) and 1936 (charged
  452 |   // carbons)
  453 |   if (at->getNumRadicalElectrons() &&
  454 |       (at->getAtomicNum() != 6 || at->getFormalCharge())) {
  455 |     return false;
  456 |   }
  457 |
  458 |   // We are going to explicitly disallow atoms that have more
  459 |   // than one double or triple bond. This is to handle
  460 |   // the situation:
  461 |   //   C1=C=NC=N1 (sf.net bug 1934360)
  462 |   int nUnsaturations =
  463 |       at->getValence(Atom::ValenceType::EXPLICIT) - at->getDegree();
  464 |   if (nUnsaturations > 1) {
  465 |     unsigned int nMult = 0;
  466 |     const auto &mol = at->getOwningMol();
  467 |     for (const auto bond : mol.atomBonds(at)) {
  468 |       switch (bond->getBondType()) {
  469 |         case Bond::SINGLE:
  470 |         case Bond::AROMATIC:
  471 |           break;
  472 |         case Bond::DOUBLE:
  473 |           ++nMult;
  474 |           break;
  475 |         case Bond::TRIPLE:
  476 |           if (!allowTripleBonds) {
  477 |             return false;
  478 |           }
  479 |           ++nMult;
  480 |           break;
  481 |         default:
  482 |           // hopefully we had enough sense that we don't even
  483 |           // get here with these bonds... If we do land here,
  484 |           // just bail... I have no good answer for them.
  485 |           break;
  486 |       }
  487 |       if (nMult > 1) {
  488 |         break;
  489 |       }
  490 |     }
  491 |     if (nMult > 1) {
  492 |       return (false);
  493 |     }
  494 |   }
  495 |
  496 |   if (!allowExocyclicMultipleBonds) {
  497 |     const auto &mol = at->getOwningMol();
  498 |     for (const auto bond : mol.atomBonds(at)) {
  499 |       if ((bond->getBondType() == Bond::DOUBLE ||
  500 |            bond->getBondType() == Bond::TRIPLE) &&
  501 |           !queryIsBondInRing(bond)) {
  502 |         return false;
  503 |       }
  504 |     }
  505 |   }
  506 |
  507 |   return (true);
  508 | }
  509 |
  510 | ElectronDonorType getAtomDonorTypeArom(
  511 |     const Atom *at, bool exocyclicBondsStealElectrons = true) {
  512 |   PRECONDITION(at, "bad atom");
  513 |   const auto &mol = at->getOwningMol();
  514 |   if (at->getAtomicNum() == 0) {
  515 |     return incidentCyclicMultipleBond(at) ? OneElectronDonorType
  516 |                                           : AnyElectronDonorType;
  517 |   }
  518 |
  519 |   ElectronDonorType res = NoElectronDonorType;

Reach line at /src/rdkit/Code/GraphMol/Aromaticity.cpp:419 (observed count 0).