RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
MolSupplier.h
Go to the documentation of this file.
1//
2// Copyright (C) 2002-2024 greg landrum and other RDKit contributors
3//
4// @@ All Rights Reserved @@
5// This file is part of the RDKit.
6// The contents are covered by the terms of the BSD license
7// which is included in the file license.txt, found at the root
8// of the RDKit source tree.
9//
10#include <RDGeneral/export.h>
11#ifndef RD_MOLSUPPLIER_H
12#define RD_MOLSUPPLIER_H
13
14#include <RDGeneral/types.h>
15
16#include <string>
17#include <string_view>
18#include <list>
19#include <memory>
20#include <vector>
21#include <fstream>
22#include <iterator>
23#include <GraphMol/ROMol.h>
25#include "FileParsers.h"
27#ifdef RDK_BUILD_THREADSAFE_SSS
28#include <mutex>
29#endif
30
31#ifdef RDK_BUILD_MAEPARSER_SUPPORT
32namespace schrodinger {
33namespace mae {
34class Reader;
35class Block;
36} // namespace mae
37} // namespace schrodinger
38#endif // RDK_BUILD_MAEPARSER_SUPPORT
39
40namespace RDKit {
41RDKIT_FILEPARSERS_EXPORT std::string strip(const std::string &orig);
42
43namespace v2 {
44namespace FileParsers {
45// clang-format off
46/*!
47
48 Here are some of the ways one can interact with MolSuppliers:
49
50 1) Lazy (works with forward and random access suppliers):
51 while(!supplier.atEnd()){
52 auto mol = supplier.next(); // mol is a std::unique_ptr<RWMol>
53 if(mol){
54 do something;
55 }
56 }
57
58 2) Range based for loops (works with forward and random access suppliers):
59 for(auto mol : supplier){
60 if(mol) {
61 do something; // mol is a shared_ptr<RWMol>
62 }
63 }
64
65 3) Random Access:
66 for(int i=0;i<supplier.length();i++){
67 auto mol = supplier[i]; // mol is a std::unique_ptr<RWMol>
68 if(mol){
69 do something;
70 }
71 }
72
73 4) Random access supplier also support caching:
74 supplier.setCaching(true);
75 for(auto mol : supplier){
76 if(mol) {
77 do something; // mol is a shared_ptr<RWMol>
78 }
79 }
80 Subsequent iterations will be much faster as the molecules are cached
81 after the first read.
82
83 It's also possible to access the cached molecules directly using the getShared method:
84 supplier.setCaching(true);
85 for(int i=0;i<supplier.length();i++){
86 auto mol = supplier.getShared(i); // mol is a std::shared_ptr<RWMol>;
87 if(mol){
88 do something;
89 }
90 }
91
92 5) Random access suppliers can also be used with parallel algorithms:
93 supplier.setCaching(true);
94 std::for_each(std::execution::par, supplier.begin(), supplier.end(),
95 [](auto mol) {
96 if (mol) {
97 do something;
98 }
99 });
100
101 Caching is not required here, but if you are planning on working with the
102 molecules multiple times, it can speed things up significantly.
103
104*/
105// clang-format on
107 // this is an abstract base class to supply molecules one at a time
108 public:
110 virtual ~MolSupplier() {}
111 virtual void init() = 0;
112 virtual void reset() = 0;
113 virtual bool atEnd() = 0;
114 virtual std::unique_ptr<RWMol> next() = 0;
115
116 virtual void close() {
117 if (df_owner) {
118 delete dp_inStream;
119 df_owner = false;
120 }
121 dp_inStream = nullptr;
122 }
123
124 private:
125 // disable automatic copy constructors and assignment operators
126 // for this class and its subclasses. They will likely be
127 // carrying around stream pointers and copying those is a recipe
128 // for disaster.
129 MolSupplier(const MolSupplier &);
130 MolSupplier &operator=(const MolSupplier &);
131
132 protected:
133 // stream to read the molecules from:
134 std::istream *dp_inStream = nullptr;
135 // do we own dp_inStream?
136 bool df_owner = false;
137 // opens a stream for reading and verifies that it can be read from.
138 // if not it throws an exception
139 // the caller owns the resulting stream
140 std::istream *openAndCheckStream(const std::string &filename) {
141 // FIX: this binary mode of opening file is here because of a bug in
142 // VC++ 6.0
143 // the function "tellg" does not work correctly if we do not open it this
144 // way
145 // Jan 2009: Confirmed that this is still the case in visual studio 2008
146 std::ifstream *strm =
147 new std::ifstream(filename.c_str(), std::ios_base::binary);
148 if ((!(*strm)) || strm->bad()) {
149 std::ostringstream errout;
150 errout << "Bad input file " << filename;
151 delete strm;
152 throw BadFileException(errout.str());
153 }
154 strm->peek();
155 if (strm->bad() || strm->eof()) {
156 std::ostringstream errout;
157 errout << "Invalid input file " << filename;
158 delete strm;
159 throw BadFileException(errout.str());
160 }
161 return static_cast<std::istream *>(strm);
162 }
163};
164
165// g++ 13 generates some spurious warnings from here (they are gone in g++ 14).
166// disable them
167#if !defined(__clang__) && defined(__GNUC__)
168#pragma GCC diagnostic push
169#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
170#endif
171
172// \brief an input iterator for suppliers that only support forward reading
173template <typename Supplier>
175 using iterator_category = std::input_iterator_tag;
176 using difference_type = std::ptrdiff_t;
177 using value_type = std::shared_ptr<RWMol>;
178 using const_value_type = const std::shared_ptr<RWMol>;
179
180 Supplier *supplier = nullptr;
181 std::optional<value_type> current;
187
188 explicit ForwardSupplierIter(Supplier *supplier)
189 : supplier(supplier), current(supplier->nextShared()) {}
190 const_value_type operator*() const { return current.value(); }
192 if (supplier->atEnd()) {
193 current.reset();
194 return *this;
195 }
196 current = supplier->nextShared();
197 // This is the special case where there's a trailing blank line in the SDF.
198 // we were actually at the logical end of the file coming in, but atEnd()
199 // hadn't yet been set.
200 // In this case we want to make sure to reset the iterator to the end state
201 // instead of returning a null molecule.
202 if (!current.value() && supplier->getEOFHitOnRead()) {
203 current.reset();
204 }
205 return *this;
206 }
208 if (supplier->atEnd()) {
209 current.reset();
210 return *this;
211 }
212 ForwardSupplierIter tmp = *this;
213 ++(*this);
214 return tmp;
215 }
216 bool operator==(const ForwardSupplierIter &other) const {
217 return !current.has_value() && !other.current.has_value();
218 }
219};
220#if !defined(__clang__) && defined(__GNUC__)
221#pragma GCC diagnostic pop
222#endif
223
224// \brief a supplier from an SD file that only reads forward:
226 /*************************************************************************
227 * A lazy mol supplier from a SD file.
228 * - When new molecules are read using "next" their positions in the file are
229 *noted.
230 ***********************************************************************************/
231 public:
234
236 std::istream *inStream, bool takeOwnership = true,
237 const MolFileParserParams &params = MolFileParserParams());
238
239 ~ForwardSDMolSupplier() override { close(); }
240
241 void init() override;
242 void reset() override;
243 std::unique_ptr<RWMol> next() override;
244 std::shared_ptr<RWMol> nextShared() {
245 return std::shared_ptr<RWMol>(this->next());
246 };
247 bool atEnd() override;
248
251
252 bool getEOFHitOnRead() const { return df_eofHitOnRead; }
253
255 if (d_line) {
257 "Cannot create an iterator for a ForwardSDMolSupplier that has already "
258 "been read from.");
259 }
260 return iterator(this);
261 }
262 iterator end() { return iterator(); }
263
264 protected:
265 virtual void checkForEnd();
266 std::unique_ptr<RWMol> _next();
267 virtual void readMolProps(ROMol &);
268 bool df_end = false;
269 int d_line = 0; // line number we are currently on
272 bool df_eofHitOnRead = false;
273};
274// clang-format off
275static_assert(
276 std::ranges::input_range<ForwardSDMolSupplier>
277 );
278// clang-format on
279
280// \brief a random access iterator for suppliers that support random access
281template <typename Supplier>
283 using iterator_category = std::random_access_iterator_tag;
284 using difference_type = std::ptrdiff_t;
285 using value_type = std::shared_ptr<RWMol>;
286 using const_value_type = const std::shared_ptr<RWMol>;
287
288 Supplier *supplier = nullptr;
289 size_t current_idx = 0;
293 default;
298 RandomAccessSupplierIter(Supplier *supplier, size_t idx)
299 : supplier(supplier), current_idx(idx) {}
301 return supplier->getShared(current_idx);
302 }
303 const_value_type operator[](size_t idx) const {
304 return supplier->getShared(idx);
305 }
307 ++current_idx;
308 return *this;
309 }
311 RandomAccessSupplierIter tmp(this->supplier, current_idx);
312 ++(*this);
313 return tmp;
314 }
316 --current_idx;
317 return *this;
318 }
320 RandomAccessSupplierIter tmp(this->supplier, current_idx);
321 --(*this);
322 return tmp;
323 }
325 current_idx += n;
326 return *this;
327 }
329 current_idx -= n;
330 return *this;
331 }
339 return static_cast<difference_type>(current_idx) -
340 static_cast<difference_type>(other.current_idx);
341 }
346 auto operator<=>(const RandomAccessSupplierIter &other) const {
347 return current_idx <=> other.current_idx;
348 }
349 bool operator==(const RandomAccessSupplierIter &other) const {
350 return this->supplier == other.supplier &&
351 this->current_idx == other.current_idx;
352 }
353};
354
355// \brief a lazy supplier from an SD file
357 /*************************************************************************
358 * A lazy mol supplier from a SD file.
359 * - When new molecules are read using "next()" their positions in the file
360 * are stored.
361 * - A call to the "length()" will automatically parse the entire file and
362 * store all the mol block positions
363 * - [] operator is used to access a molecule at "idx", calling next()
364 * after this will result in the next molecule after "idx"
365 ***********************************************************************************/
366 public:
368 using reverse_iterator = std::reverse_iterator<iterator>;
369
371
372 /*!
373 * \param fileName - the name of the SD file
374 * \param sanitize - if true sanitize the molecule before returning it
375 * \param removeHs - if true remove Hs from the molecule before returning it
376 * (triggers sanitization)
377 * \param strictParsing - if set to false, the parser is more lax about
378 * correctness
379 * of the contents.
380 */
382 const std::string &fileName,
383 const MolFileParserParams &params = MolFileParserParams());
384
386 std::istream *inStream, bool takeOwnership = true,
387 const MolFileParserParams &params = MolFileParserParams());
388
389 ~SDMolSupplier() override { close(); }
390 void init() override;
391 void reset() override;
392 std::unique_ptr<RWMol> next() override;
393 bool atEnd() override;
394 void moveTo(unsigned int idx);
395 std::unique_ptr<RWMol> operator[](unsigned int idx);
396 ///! \brief returns a shared pointer to the molecule at the given index.
397 std::shared_ptr<RWMol> getShared(unsigned int idx);
398 /*! \brief returns the text block for a particular item
399 *
400 * \param idx - which item to return
401 */
402 std::string getItemText(unsigned int idx);
403 unsigned int length();
404 void setData(const std::string &text);
405 void setData(const std::string &text, const MolFileParserParams &params);
406
407 /*! Resets our internal state and sets the indices of molecules in the stream.
408 * The client should be *very* careful about calling this method, as it's
409 *trivial
410 * to end up with a completely useless supplier.
411 *
412 * \param locs - the vector of stream positions.
413 *
414 * Note that this can be used not only to make reading selected molecules
415 *from a
416 * large SD file much faster, but it can also allow subsetting an SD file or
417 * rearranging the order of the molecules.
418 */
419 void setStreamIndices(const std::vector<std::streampos> &locs);
420
425
426 void setCaching(bool val) { d_cacheMolecules = val; }
427 bool getCaching() const { return d_cacheMolecules; }
428
429 private:
430 void checkForEnd() override;
431 void peekCheckForEnd(char *bufPtr, char *bufEnd, std::streampos molStartPos);
432 void buildIndexTo(unsigned int targetIdx);
433 int d_len = 0; // total number of mol blocks in the file (initialized to -1)
434 int d_last = 0; // the molecule we are ready to read
435 std::vector<std::streampos> d_molpos;
436 bool d_cacheMolecules = false;
437 std::vector<std::optional<std::shared_ptr<RWMol>>> d_molCache;
438#ifdef RDK_BUILD_THREADSAFE_SSS
439 std::mutex d_readMutex;
440 std::mutex d_cacheMutex;
441#endif
442};
443// clang-format off
444static_assert(
445 std::ranges::random_access_range<SDMolSupplier>
446 );
447// clang-format on
448
450 std::string delimiter = " \t";
452 int nameColumn = 1;
453 bool titleLine = true;
455 true, // sanitize
456 false, // allowCXSMILES
457 true, // strictCXSMILES
458 false, // parseName
459 true, // removeHs
460 false, // skipCleanup
461 false, // debugParse
462 {} // replacements
463 };
464};
465
466//! lazy file parser for Smiles tables
468 /**************************************************************************
469 * Lazy file parser for Smiles table file, similar to the lazy SD
470 * file parser above
471 * - When new molecules are read using "next()" their
472 * positions in the file are stored.
473 * - A call to "length()" will automatically parse the entire
474 * file and store all the mol block positions
475 * - [] operator is used to access a molecule at "idx", calling
476 * next() following this will result in the next molecule after
477 * "idx"
478 ***************************************************************************/
479 public:
481 using reverse_iterator = std::reverse_iterator<iterator>;
482 /*!
483 * \param fileName - the name of smiles table file
484 * \param params - SmilesMolSupplierParams object controlling how
485 * the file itself and the individual SMILES are parsed.
486 */
488 const std::string &fileName,
492 std::istream *inStream, bool takeOwnership = true,
494
495 ~SmilesMolSupplier() override { close(); }
496 void setData(const std::string &text, const SmilesMolSupplierParams &params =
498 void init() override;
499 void reset() override;
500 std::unique_ptr<RWMol> next() override;
501 bool atEnd() override;
502 void moveTo(unsigned int idx);
503 std::unique_ptr<RWMol> operator[](unsigned int idx);
504 std::shared_ptr<RWMol> getShared(unsigned int idx);
505 /*! \brief returns the text block for a particular item
506 *
507 * \param idx - which item to return
508 */
509 std::string getItemText(unsigned int idx);
510 unsigned int length();
511
512 iterator begin() { return iterator(this); }
513 iterator end() { return iterator(this, length()); }
516
517 void setCaching(bool val) { d_cacheMolecules = val; }
518 bool getCaching() const { return d_cacheMolecules; }
519
520 private:
521 std::unique_ptr<RWMol> processLine(std::string inLine);
522 void processTitleLine();
523 std::string nextLine();
524 long int skipComments();
525 void checkForEnd();
526
527 bool df_end = false; // have we reached the end of the file?
528 long d_len = 0; // total number of smiles in the file
529 long d_next = 0; // the molecule we are ready to read
530 size_t d_line = 0; // line number we are currently on
532 std::vector<std::streampos>
533 d_molpos; // vector of positions in the file for molecules
534 std::vector<int> d_lineNums;
535 STR_VECT d_props; // vector of property names
536 bool d_cacheMolecules = false;
537 std::vector<std::optional<std::shared_ptr<RWMol>>> d_molCache;
538#ifdef RDK_BUILD_THREADSAFE_SSS
539 std::mutex d_readMutex;
540 std::mutex d_cacheMutex;
541#endif
542};
543
545 std::string nameRecord = "";
546 int confId2D = -1;
547 int confId3D = -1;
549 true, // sanitize
550 false, // allowCXSMILES
551 true, // strictCXSMILES
552 false, // parseName
553 true, // removeHs
554 false, // skipCleanup
555 false, // debugParse
556 {} // replacements
557 };
558};
559
560//! lazy file parser for TDT files
562 /**************************************************************************
563 * Lazy file parser for TDT files, similar to the lazy SD
564 * file parser above
565 * - When new molecules are read using "next()" their
566 * positions in the file are noted.
567 * - A call to "length()" will automatically parse the entire
568 * file and store all the mol block positions
569 * - [] operator is used to access a molecule at "idx", calling
570 * next() following this will result in the next molecule after
571 * "idx"
572 ***************************************************************************/
573 public:
575 using reverse_iterator = std::reverse_iterator<iterator>;
576
577 /*!
578 * \param fileName - the name of the TDT file
579 * \param params - TDTMolSupplierParams object controlling how the file
580 * itself and the individual records are parsed.
581 */
583 const std::string &fileName,
586 std::istream *inStream, bool takeOwnership = true,
589 ~TDTMolSupplier() override { close(); }
590 void setData(const std::string &text,
592 void init() override;
593 void reset() override;
594 std::unique_ptr<RWMol> next() override;
595 bool atEnd() override;
596 void moveTo(unsigned int idx);
597 std::unique_ptr<RWMol> operator[](unsigned int idx);
598 std::shared_ptr<RWMol> getShared(unsigned int idx);
599
600 /*! \brief returns the text block for a particular item
601 *
602 * \param idx - which item to return
603 */
604 std::string getItemText(unsigned int idx);
605 unsigned int length();
606
607 iterator begin() { return iterator(this); }
608 iterator end() { return iterator(this, length()); }
611
612 void setCaching(bool val) { d_cacheMolecules = val; }
613 bool getCaching() const { return d_cacheMolecules; }
614
615 private:
616 bool advanceToNextRecord();
617 void checkForEnd();
618 std::unique_ptr<RWMol> parseMol(std::string inLine);
619
620 bool df_end = false; // have we reached the end of the file?
621 int d_len = 0; // total number of mols in the file
622 int d_last = 0; // the molecule we are ready to read
623 int d_line = 0; // line number we are currently on
624 std::vector<std::streampos>
625 d_molpos; // vector of positions in the file for molecules
626 TDTMolSupplierParams d_params;
627 bool d_cacheMolecules = false;
628 std::vector<std::optional<std::shared_ptr<RWMol>>> d_molCache;
629#ifdef RDK_BUILD_THREADSAFE_SSS
630 std::mutex d_readMutex;
631 std::mutex d_cacheMutex;
632#endif
633};
634
635#ifdef RDK_BUILD_MAEPARSER_SUPPORT
636struct MaeMolSupplierParams {
637 bool sanitize = true;
638 bool removeHs = true;
639};
640//! lazy file parser for MAE files
641class RDKIT_FILEPARSERS_EXPORT MaeMolSupplier : public MolSupplier {
642 /**
643 * Due to maeparser's shared_ptr<istream> Reader interface, MaeMolSupplier
644 * always requires taking ownership of the istream ptr, as the shared ptr will
645 * always clear it upon destruction.
646 */
647
648 public:
649 MaeMolSupplier() {}
650
651 explicit MaeMolSupplier(
652 std::shared_ptr<std::istream> inStream,
653 const MaeMolSupplierParams &params = MaeMolSupplierParams());
654
655 explicit MaeMolSupplier(
656 std::istream *inStream, bool takeOwnership = true,
657 const MaeMolSupplierParams &params = MaeMolSupplierParams());
658
659 explicit MaeMolSupplier(
660 const std::string &fname,
661 const MaeMolSupplierParams &params = MaeMolSupplierParams());
662
663 ~MaeMolSupplier() override {}
664
665 void init() override;
666 void reset() override;
667 std::unique_ptr<RWMol> next() override;
668 bool atEnd() override;
669 void moveTo(unsigned int idx);
670 std::unique_ptr<RWMol> operator[](unsigned int idx);
671
672 unsigned int length();
673
674 void close() override { dp_sInStream.reset(); }
675
676 void setData(const std::string &text,
677 const MaeMolSupplierParams &params = MaeMolSupplierParams());
678
679 private:
680 void moveToNextBlock();
681
682 protected:
683 MaeMolSupplierParams d_params;
684 std::shared_ptr<schrodinger::mae::Reader> d_reader;
685 std::shared_ptr<schrodinger::mae::Block> d_next_struct;
686 std::shared_ptr<std::istream> dp_sInStream;
687 std::string d_stored_exc;
688 unsigned d_position;
689 unsigned d_length;
690};
691#endif // RDK_BUILD_MAEPARSER_SUPPORT
692
693} // namespace FileParsers
694} // namespace v2
695} // namespace RDKit
696
697#include "MolSupplier.v1API.h"
698
699#endif
Defines the primary molecule class ROMol as well as associated typedefs.
used by various file parsing classes to indicate a bad file
ForwardSDMolSupplier(std::istream *inStream, bool takeOwnership=true, const MolFileParserParams &params=MolFileParserParams())
ForwardSupplierIter< ForwardSDMolSupplier > iterator
std::unique_ptr< RWMol > next() override
std::istream * openAndCheckStream(const std::string &filename)
virtual std::unique_ptr< RWMol > next()=0
void setStreamIndices(const std::vector< std::streampos > &locs)
void setData(const std::string &text)
std::reverse_iterator< iterator > reverse_iterator
std::unique_ptr< RWMol > next() override
SDMolSupplier(std::istream *inStream, bool takeOwnership=true, const MolFileParserParams &params=MolFileParserParams())
RandomAccessSupplierIter< SDMolSupplier > iterator
std::string getItemText(unsigned int idx)
returns the text block for a particular item
std::shared_ptr< RWMol > getShared(unsigned int idx)
!
void setData(const std::string &text, const MolFileParserParams &params)
SDMolSupplier(const std::string &fileName, const MolFileParserParams &params=MolFileParserParams())
std::unique_ptr< RWMol > operator[](unsigned int idx)
std::string getItemText(unsigned int idx)
returns the text block for a particular item
std::shared_ptr< RWMol > getShared(unsigned int idx)
std::unique_ptr< RWMol > next() override
SmilesMolSupplier(std::istream *inStream, bool takeOwnership=true, const SmilesMolSupplierParams &params=SmilesMolSupplierParams())
std::unique_ptr< RWMol > operator[](unsigned int idx)
SmilesMolSupplier(const std::string &fileName, const SmilesMolSupplierParams &params=SmilesMolSupplierParams())
RandomAccessSupplierIter< SmilesMolSupplier > iterator
std::reverse_iterator< iterator > reverse_iterator
void setData(const std::string &text, const SmilesMolSupplierParams &params=SmilesMolSupplierParams())
std::unique_ptr< RWMol > operator[](unsigned int idx)
void setData(const std::string &text, const TDTMolSupplierParams &params=TDTMolSupplierParams())
TDTMolSupplier(const std::string &fileName, const TDTMolSupplierParams &params=TDTMolSupplierParams())
std::reverse_iterator< iterator > reverse_iterator
RandomAccessSupplierIter< TDTMolSupplier > iterator
std::string getItemText(unsigned int idx)
returns the text block for a particular item
TDTMolSupplier(std::istream *inStream, bool takeOwnership=true, const TDTMolSupplierParams &params=TDTMolSupplierParams())
std::shared_ptr< RWMol > getShared(unsigned int idx)
std::unique_ptr< RWMol > next() override
Class to allow us to throw a ValueError from C++ and have it make it back to Python.
Definition Exceptions.h:41
#define RDKIT_FILEPARSERS_EXPORT
Definition export.h:177
Std stuff.
RDKIT_FILEPARSERS_EXPORT std::string strip(const std::string &orig)
std::vector< std::string > STR_VECT
Definition Dict.h:29
const std::shared_ptr< RWMol > const_value_type
ForwardSupplierIter(const ForwardSupplierIter &)=default
bool operator==(const ForwardSupplierIter &other) const
ForwardSupplierIter(ForwardSupplierIter &&)=default
ForwardSupplierIter & operator=(const ForwardSupplierIter &)=default
ForwardSupplierIter & operator=(ForwardSupplierIter &&)=default
RandomAccessSupplierIter(const RandomAccessSupplierIter &)=default
std::random_access_iterator_tag iterator_category
RandomAccessSupplierIter operator-(difference_type n) const
const std::shared_ptr< RWMol > const_value_type
const_value_type operator[](size_t idx) const
RandomAccessSupplierIter operator+(difference_type n) const
RandomAccessSupplierIter & operator=(RandomAccessSupplierIter &&)=default
bool operator==(const RandomAccessSupplierIter &other) const
RandomAccessSupplierIter(Supplier *supplier, size_t idx)
RandomAccessSupplierIter(RandomAccessSupplierIter &&)=default
friend RandomAccessSupplierIter operator+(difference_type n, const RandomAccessSupplierIter &it)
auto operator<=>(const RandomAccessSupplierIter &other) const
RandomAccessSupplierIter & operator=(const RandomAccessSupplierIter &)=default
RandomAccessSupplierIter & operator+=(difference_type n)
difference_type operator-(const RandomAccessSupplierIter &other) const
RandomAccessSupplierIter & operator-=(difference_type n)
v2::SmilesParse::SmilesParserParams parseParameters
v2::SmilesParse::SmilesParserParams parseParameters