/src/openbabel/src/ops/deferred.h
Line | Count | Source (jump to first uncovered line) |
1 | | #include <openbabel/babelconfig.h> |
2 | | #include <openbabel/op.h> |
3 | | #include <openbabel/obconversion.h> |
4 | | #include <vector> |
5 | | #include <algorithm> |
6 | | |
7 | | namespace OpenBabel |
8 | | { |
9 | | /** |
10 | | DeferredFormat class is intended to assist writing ops that influence the |
11 | | conversion of multiple molecules with the OBConversion Convert interface. |
12 | | See, for instance, OpSort. Although it is a format, it does not registered |
13 | | itself, an object is not constructed in ReadChemObject() or deleted in |
14 | | WriteChemObject(). It is used in a different way from normal formats. An |
15 | | op makes an instance of DeferredFormat, probably when it is first called |
16 | | in its Do() function. |
17 | | \code |
18 | | if(pConv && pConv->IsFirstInput()) |
19 | | new DeferredFormat(pConv, this); //it will delete itself |
20 | | \endcode |
21 | | Output objects (probably molecules) will then all be diverted to the |
22 | | DeferredFormat instance and pointers to them stored there. After the last |
23 | | object, it calls the op's ProcessVec(std::vector<OBBase*>& vec) function. |
24 | | The objects can be manipulated or deleted (call delete with their pointer). |
25 | | When the function returns, the remaining molecules in the vector will be |
26 | | output to the normal output format. No conversion options are applied at |
27 | | this stage, since they already have been earlier. |
28 | | |
29 | | Constructing with a third boolean parameter set true allows an alternative mode |
30 | | of operation. Before storing the pointer to an object, DeferredFormat calls |
31 | | the op's Do() function and stores the object pointer only if this returns true. |
32 | | This has the effect of allowing the op to act after all the other options, |
33 | | rather than before most of them. See OpLargest for an example. |
34 | | **/ |
35 | | class DeferredFormat : public OBFormat |
36 | | { |
37 | | public: |
38 | | DeferredFormat(OBConversion* pConv, OBOp* pOp=nullptr, bool CallDo=false) |
39 | 0 | { |
40 | 0 | _pRealOutFormat = pConv->GetOutFormat(); |
41 | 0 | pConv->SetOutFormat(this); |
42 | 0 | _pOp = pOp; |
43 | 0 | _callDo = CallDo; |
44 | 0 | } |
45 | 0 | const char* Description() override { return "Read and write an OBBase* array"; } |
46 | | |
47 | | bool ReadChemObject(OBConversion* pConv) override |
48 | 0 | { |
49 | 0 | if(_obvec.empty()) |
50 | 0 | { |
51 | 0 | delete this;//self destruction; was made in new in an OBOp |
52 | 0 | return false; |
53 | 0 | } |
54 | | //returned in reverse order, because its easier with a vector |
55 | 0 | pConv->AddChemObject(_obvec.back()); |
56 | 0 | _obvec.pop_back(); |
57 | 0 | return true; |
58 | 0 | } |
59 | | |
60 | | bool WriteChemObject(OBConversion* pConv) override |
61 | 0 | { |
62 | 0 | OBBase* pOb = pConv->GetChemObject(); |
63 | 0 | if(!_callDo || _pOp->Do(pOb, "", pConv->GetOptions(OBConversion::GENOPTIONS), pConv)) |
64 | 0 | _obvec.push_back(pOb); // Store the object pointer. |
65 | |
|
66 | 0 | if(pConv->IsLast()) |
67 | 0 | { |
68 | | //At the end, sort, or whatever, the vector |
69 | 0 | if(_pOp) |
70 | 0 | { |
71 | | //clear the options if return is true - they have already been applied |
72 | 0 | if(_pOp->ProcessVec(_obvec)) |
73 | 0 | pConv->SetOptions("",OBConversion::GENOPTIONS); |
74 | | |
75 | | //Now output the processed vector, unless it is empty |
76 | 0 | if(!_obvec.empty()) |
77 | 0 | { |
78 | 0 | std::reverse(_obvec.begin(),_obvec.end()); //because DeferredFormat outputs in reverse order |
79 | 0 | pConv->SetInAndOutFormats(this, _pRealOutFormat); |
80 | |
|
81 | 0 | std::ifstream ifs; // get rid of gcc warning |
82 | 0 | pConv->SetInStream(&ifs);//Not used, but Convert checks it is ok |
83 | 0 | pConv->GetInStream()->clear(); |
84 | |
|
85 | 0 | pConv->SetOutputIndex(0); |
86 | 0 | pConv->Convert(); |
87 | 0 | } |
88 | 0 | } |
89 | 0 | } |
90 | 0 | return true; |
91 | 0 | } |
92 | | private: |
93 | | OBFormat* _pRealOutFormat; |
94 | | std::vector<OBBase*> _obvec; |
95 | | public: |
96 | | OBOp* _pOp; |
97 | | bool _callDo; |
98 | | }; |
99 | | |
100 | | } //namespace |
101 | | |