Coverage Report

Created: 2026-09-28 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rdkit/Code/GraphMol/MolPickler.cpp
Line
Count
Source
1
//
2
//  Copyright (C) 2001-2021 Greg Landrum and Rational Discovery LLC
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 <GraphMol/RDKitBase.h>
11
#include <GraphMol/RDKitQueries.h>
12
#include <GraphMol/MolPickler.h>
13
#include <GraphMol/QueryOps.h>
14
#include <GraphMol/MonomerInfo.h>
15
#include <GraphMol/StereoGroup.h>
16
#include <GraphMol/SubstanceGroup.h>
17
#include <RDGeneral/utils.h>
18
#include <RDGeneral/RDLog.h>
19
#include <RDGeneral/StreamOps.h>
20
#include <RDGeneral/types.h>
21
#include <DataStructs/DatastructsStreamOps.h>
22
#include <Query/QueryObjects.h>
23
#include <map>
24
#include <cstdint>
25
#include <string_view>
26
#include <boost/algorithm/string.hpp>
27
28
#ifdef RDK_BUILD_THREADSAFE_SSS
29
#include <mutex>
30
#endif
31
32
using std::int32_t;
33
using std::uint32_t;
34
35
namespace RDKit {
36
37
constexpr int32_t MolPickler::versionMajor = 16;
38
constexpr int32_t MolPickler::versionMinor = 4;
39
constexpr int32_t MolPickler::versionPatch = 0;
40
constexpr int32_t MolPickler::endianId = 0xDEADBEEF;
41
42
0
void streamWrite(std::ostream &ss, MolPickler::Tags tag) {
43
0
  auto tmp = static_cast<unsigned char>(tag);
44
0
  streamWrite(ss, tmp);
45
0
}
46
template <typename T>
47
0
void streamWrite(std::ostream &ss, MolPickler::Tags tag, const T &what) {
48
0
  streamWrite(ss, tag);
49
0
  streamWrite(ss, what);
50
0
};
Unexecuted instantiation: void RDKit::streamWrite<int>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::MolPickler::Tags, int const&)
Unexecuted instantiation: void RDKit::streamWrite<char>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::MolPickler::Tags, char const&)
Unexecuted instantiation: void RDKit::streamWrite<unsigned int>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::MolPickler::Tags, unsigned int const&)
Unexecuted instantiation: void RDKit::streamWrite<double>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::MolPickler::Tags, double const&)
Unexecuted instantiation: void RDKit::streamWrite<unsigned char>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::MolPickler::Tags, unsigned char const&)
Unexecuted instantiation: void RDKit::streamWrite<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::MolPickler::Tags, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: void RDKit::streamWrite<RDKit::Atom::ChiralType>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::MolPickler::Tags, RDKit::Atom::ChiralType const&)
Unexecuted instantiation: void RDKit::streamWrite<RDKit::Bond::BondType>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::MolPickler::Tags, RDKit::Bond::BondType const&)
Unexecuted instantiation: void RDKit::streamWrite<RDKit::Bond::BondDir>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::MolPickler::Tags, RDKit::Bond::BondDir const&)
51
52
2.15M
void streamRead(std::istream &ss, MolPickler::Tags &tag, int version) {
53
2.15M
  if (version < 7000) {
54
2.08M
    int32_t tmp;
55
2.08M
    streamRead(ss, tmp, version);
56
2.08M
    if (tmp < 0 || tmp >= MolPickler::Tags::INVALID_TAG) {
57
12
      throw MolPicklerException("Invalid tag found.");
58
12
    }
59
2.08M
    tag = static_cast<MolPickler::Tags>(tmp);
60
2.08M
  } else {
61
70.8k
    unsigned char tmp;
62
70.8k
    streamRead(ss, tmp, version);
63
70.8k
    if (tmp >= MolPickler::Tags::INVALID_TAG) {
64
2
      throw MolPicklerException("Invalid tag found.");
65
2
    }
66
70.8k
    tag = static_cast<MolPickler::Tags>(tmp);
67
70.8k
  }
68
2.15M
}
69
70
662
void streamReadPositiveChar(std::istream &ss, char &res, int version) {
71
662
  streamRead(ss, res, version);
72
662
  if (res < 0) {
73
2
    throw MolPicklerException("invalid value in pickle");
74
2
  }
75
662
}
76
77
namespace {
78
static unsigned int defaultProperties = PicklerOps::NoProps;
79
static CustomPropHandlerVec defaultPropHandlers = {};
80
81
#ifdef RDK_BUILD_THREADSAFE_SSS
82
48.1k
std::mutex &propmutex_get() {
83
  // create on demand
84
48.1k
  static std::mutex _mutex;
85
48.1k
  return _mutex;
86
48.1k
}
87
88
1
void propmutex_create() {
89
1
  std::mutex &mutex = propmutex_get();
90
1
  std::lock_guard<std::mutex> test_lock(mutex);
91
1
}
92
93
48.1k
std::mutex &GetPropMutex() {
94
48.1k
  static std::once_flag flag;
95
48.1k
  std::call_once(flag, propmutex_create);
96
48.1k
  return propmutex_get();
97
48.1k
}
98
#endif
99
100
void write_sstream_to_stream(std::ostream &outStream,
101
0
                             const std::stringstream &toWrite) {
102
0
  auto ts = toWrite.str();
103
0
  int32_t tmpInt = static_cast<int32_t>(ts.size());
104
0
  streamWrite(outStream, tmpInt);
105
0
  outStream.write(ts.c_str(), sizeof(char) * tmpInt);
106
0
}
107
108
}  // namespace
109
110
void MolPickler::_pickleProperties(std::ostream &ss, const RDProps &props,
111
0
                                   unsigned int pickleFlags) {
112
0
  if (!pickleFlags) {
113
0
    return;
114
0
  }
115
116
0
  streamWriteProps<std::uint16_t>(ss, props,
117
0
                                  pickleFlags & PicklerOps::PrivateProps,
118
0
                                  pickleFlags & PicklerOps::ComputedProps,
119
0
                                  MolPickler::getCustomPropHandlers());
120
0
}
121
122
namespace {
123
124
template <typename SAVEAS, typename STOREAS, typename EXPLICIT>
125
inline void unpickleExplicitProperties(std::istream &ss, RDProps &props,
126
                                       int version,
127
428
                                       const EXPLICIT &explicitProps) {
128
428
  if (version >= 14000) {
129
0
    std::uint8_t bprops;
130
0
    streamRead(ss, bprops, version);
131
0
    for (const auto &pr : explicitProps) {
132
0
      if (bprops & pr.second) {
133
0
        SAVEAS bv;
134
0
        streamRead(ss, bv, version);
135
0
        props.setProp(pr.first, static_cast<STOREAS>(bv));
136
0
      }
137
0
    }
138
0
  }
139
428
}
MolPickler.cpp:void RDKit::(anonymous namespace)::unpickleExplicitProperties<short, int, std::__1::array<std::__1::pair<std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned short>, 4ul> >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::RDProps&, int, std::__1::array<std::__1::pair<std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned short>, 4ul> const&)
Line
Count
Source
127
428
                                       const EXPLICIT &explicitProps) {
128
428
  if (version >= 14000) {
129
0
    std::uint8_t bprops;
130
0
    streamRead(ss, bprops, version);
131
0
    for (const auto &pr : explicitProps) {
132
0
      if (bprops & pr.second) {
133
0
        SAVEAS bv;
134
0
        streamRead(ss, bv, version);
135
0
        props.setProp(pr.first, static_cast<STOREAS>(bv));
136
0
      }
137
0
    }
138
0
  }
139
428
}
Unexecuted instantiation: MolPickler.cpp:void RDKit::(anonymous namespace)::unpickleExplicitProperties<signed char, int, std::__1::array<std::__1::pair<std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned short>, 5ul> >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::RDProps&, int, std::__1::array<std::__1::pair<std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned short>, 5ul> const&)
140
141
template <typename SAVEAS, typename EXPLICIT>
142
inline bool pickleExplicitProperties(std::ostream &ss, const RDProps &props,
143
0
                                     const EXPLICIT &explicitProps) {
144
0
  std::uint8_t bprops = 0;
145
0
  std::vector<SAVEAS> ps;
146
0
  SAVEAS bv;
147
0
  for (const auto &pr : explicitProps) {
148
0
    if (props.getPropIfPresent(pr.first, bv)) {
149
0
      bprops |= pr.second;
150
0
      ps.push_back(bv);
151
0
    }
152
0
  }
153
154
0
  streamWrite(ss, bprops);
155
0
  for (auto v : ps) {
156
0
    streamWrite(ss, v);
157
0
  }
158
0
  return !ps.empty();
159
0
}
Unexecuted instantiation: MolPickler.cpp:bool RDKit::(anonymous namespace)::pickleExplicitProperties<short, std::__1::array<std::__1::pair<std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned short>, 4ul> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::RDProps const&, std::__1::array<std::__1::pair<std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned short>, 4ul> const&)
Unexecuted instantiation: MolPickler.cpp:bool RDKit::(anonymous namespace)::pickleExplicitProperties<signed char, std::__1::array<std::__1::pair<std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned short>, 5ul> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::RDProps const&, std::__1::array<std::__1::pair<std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned short>, 5ul> const&)
160
161
// you're going to scratch your head and wonder why on earth this is using a
162
// class instead of a set of globals. This is a workaround for some very strange
163
// problem with globals and the cartridge
164
class PropTracker {
165
 public:
166
  // this is stored as bitflags in a byte, so don't exceed 8 entries or we need
167
  // to update the pickle format.
168
  // the properties themselves are stored as std::int8_t
169
  static constexpr std::array<std::pair<std::string_view, std::uint16_t>, 5>
170
      explicitBondProps{{
171
          {RDKit::common_properties::_MolFileBondType, 0x1},
172
          {RDKit::common_properties::_MolFileBondStereo, 0x2},
173
          {RDKit::common_properties::_MolFileBondCfg, 0x4},
174
          {RDKit::common_properties::_MolFileBondQuery, 0x8},
175
          {RDKit::common_properties::molStereoCare, 0x10},
176
      }};
177
  // this is stored as bitflags in a byte, so don't exceed 8 entries or we need
178
  // to update the pickle format.
179
  // the properties themselves are stored as std::int16_t
180
  static constexpr std::array<std::pair<std::string_view, std::uint16_t>, 4>
181
      explicitAtomProps{{
182
          {common_properties::molStereoCare, 0x1},
183
          {common_properties::molParity, 0x2},
184
          {common_properties::molInversionFlag, 0x4},
185
          {common_properties::_ChiralityPossible, 0x8},
186
187
      }};
188
  static constexpr std::array<std::string_view, 2> ignoreAtomProps{
189
      common_properties::molAtomMapNumber,
190
      common_properties::dummyLabel,
191
  };
192
  std::unordered_set<std::string_view> ignoreBondProps;
193
1
  PropTracker() {
194
5
    for (const auto &pr : explicitBondProps) {
195
5
      ignoreBondProps.insert(pr.first);
196
5
    }
197
1
  };
198
};
199
200
bool pickleAtomProperties(std::ostream &ss, const RDProps &props,
201
0
                          unsigned int pickleFlags) {
202
0
  const static PropTracker aprops;
203
0
  static std::unordered_set<std::string_view> ignoreProps;
204
0
  if (ignoreProps.empty()) {
205
0
    for (const auto &pr : aprops.explicitAtomProps) {
206
0
      ignoreProps.insert(pr.first);
207
0
    }
208
0
    for (const auto &pn : aprops.ignoreAtomProps) {
209
0
      ignoreProps.insert(pn);
210
0
    }
211
0
  }
212
213
0
  if (!pickleFlags) {
214
0
    return false;
215
0
  }
216
217
0
  bool res = streamWriteProps<std::uint16_t>(
218
0
      ss, props, pickleFlags & PicklerOps::PrivateProps,
219
0
      pickleFlags & PicklerOps::ComputedProps,
220
0
      MolPickler::getCustomPropHandlers(), ignoreProps);
221
222
0
  res |= pickleExplicitProperties<std::int16_t>(ss, props,
223
0
                                                PropTracker::explicitAtomProps);
224
0
  return res;
225
0
}
226
227
429
void unpickleAtomProperties(std::istream &ss, RDProps &props, int version) {
228
429
  const static PropTracker aprops;
229
429
  if (version >= 14000) {
230
0
    streamReadProps<std::uint16_t>(ss, props,
231
0
                                   MolPickler::getCustomPropHandlers(), false);
232
429
  } else {
233
429
    streamReadProps<unsigned int>(ss, props,
234
429
                                  MolPickler::getCustomPropHandlers(), false);
235
429
  }
236
429
  unpickleExplicitProperties<std::int16_t, int>(ss, props, version,
237
429
                                                PropTracker::explicitAtomProps);
238
429
}
239
240
bool pickleBondProperties(std::ostream &ss, const RDProps &props,
241
0
                          unsigned int pickleFlags) {
242
0
  const static PropTracker bprops;
243
0
  if (!pickleFlags) {
244
0
    return false;
245
0
  }
246
0
  bool res = streamWriteProps<std::uint16_t>(
247
0
      ss, props, pickleFlags & PicklerOps::PrivateProps,
248
0
      pickleFlags & PicklerOps::ComputedProps,
249
0
      MolPickler::getCustomPropHandlers(), bprops.ignoreBondProps);
250
0
  res |= pickleExplicitProperties<std::int8_t>(ss, props,
251
0
                                               PropTracker::explicitBondProps);
252
0
  return res;
253
0
}
254
255
0
void unpickleBondProperties(std::istream &ss, RDProps &props, int version) {
256
0
  const static PropTracker bprops;
257
0
  if (version >= 14000) {
258
0
    streamReadProps<std::uint16_t>(ss, props,
259
0
                                   MolPickler::getCustomPropHandlers(), false);
260
0
  } else {
261
0
    streamReadProps<unsigned int>(ss, props,
262
0
                                  MolPickler::getCustomPropHandlers(), false);
263
0
  }
264
0
  unpickleExplicitProperties<std::int8_t, int>(ss, props, version,
265
0
                                               PropTracker::explicitBondProps);
266
0
}
267
268
}  // namespace
269
270
0
unsigned int MolPickler::getDefaultPickleProperties() {
271
0
#ifdef RDK_BUILD_THREADSAFE_SSS
272
0
  std::lock_guard<std::mutex> lock(GetPropMutex());
273
0
#endif
274
0
  unsigned int props = defaultProperties;
275
0
  return props;
276
0
}
277
278
0
void MolPickler::setDefaultPickleProperties(unsigned int props) {
279
0
#ifdef RDK_BUILD_THREADSAFE_SSS
280
0
  std::lock_guard<std::mutex> lock(GetPropMutex());
281
0
#endif
282
0
  defaultProperties = props;
283
0
}
284
285
48.1k
const CustomPropHandlerVec &MolPickler::getCustomPropHandlers() {
286
48.1k
#ifdef RDK_BUILD_THREADSAFE_SSS
287
48.1k
  std::lock_guard<std::mutex> lock(GetPropMutex());
288
48.1k
#endif
289
48.1k
  if (defaultPropHandlers.size() == 0) {
290
    // initialize handlers
291
1
    defaultPropHandlers.push_back(
292
1
        std::make_shared<DataStructsExplicitBitVecPropHandler>());
293
1
  }
294
48.1k
  return defaultPropHandlers;
295
48.1k
}
296
297
0
void MolPickler::addCustomPropHandler(const CustomPropHandler &handler) {
298
0
#ifdef RDK_BUILD_THREADSAFE_SSS
299
0
  std::lock_guard<std::mutex> lock(GetPropMutex());
300
0
#endif
301
0
  if (defaultPropHandlers.size() == 0) {
302
    // initialize handlers
303
0
    defaultPropHandlers.push_back(
304
0
        std::make_shared<DataStructsExplicitBitVecPropHandler>());
305
0
  }
306
0
  defaultPropHandlers.push_back(
307
0
      std::shared_ptr<CustomPropHandler>(handler.clone()));
308
0
}
309
310
using namespace Queries;
311
namespace PicklerOps {
312
313
template <class T>
314
0
QueryDetails getQueryDetails(const Query<int, T const *, true> *query) {
315
0
  PRECONDITION(query, "no query");
316
0
  if (typeid(*query) == typeid(AndQuery<int, T const *, true>)) {
317
0
    return QueryDetails(MolPickler::QUERY_AND);
318
0
  } else if (typeid(*query) == typeid(OrQuery<int, T const *, true>)) {
319
0
    return QueryDetails(MolPickler::QUERY_OR);
320
0
  } else if (typeid(*query) == typeid(XOrQuery<int, T const *, true>)) {
321
0
    return QueryDetails(MolPickler::QUERY_XOR);
322
0
  } else if (typeid(*query) == typeid(EqualityQuery<int, T const *, true>)) {
323
0
    return QueryDetails(std::make_tuple(
324
0
        MolPickler::QUERY_EQUALS,
325
0
        static_cast<const EqualityQuery<int, T const *, true> *>(query)
326
0
            ->getVal(),
327
0
        static_cast<const EqualityQuery<int, T const *, true> *>(query)
328
0
            ->getTol()));
329
0
  } else if (typeid(*query) == typeid(GreaterQuery<int, T const *, true>)) {
330
0
    return QueryDetails(std::make_tuple(
331
0
        MolPickler::QUERY_GREATER,
332
0
        static_cast<const GreaterQuery<int, T const *, true> *>(query)
333
0
            ->getVal(),
334
0
        static_cast<const GreaterQuery<int, T const *, true> *>(query)
335
0
            ->getTol()));
336
0
  } else if (typeid(*query) ==
337
0
             typeid(GreaterEqualQuery<int, T const *, true>)) {
338
0
    return QueryDetails(std::make_tuple(
339
0
        MolPickler::QUERY_GREATEREQUAL,
340
0
        static_cast<const GreaterEqualQuery<int, T const *, true> *>(query)
341
0
            ->getVal(),
342
0
        static_cast<const GreaterEqualQuery<int, T const *, true> *>(query)
343
0
            ->getTol()));
344
0
  } else if (typeid(*query) == typeid(LessQuery<int, T const *, true>)) {
345
0
    return QueryDetails(std::make_tuple(
346
0
        MolPickler::QUERY_LESS,
347
0
        static_cast<const LessQuery<int, T const *, true> *>(query)->getVal(),
348
0
        static_cast<const LessQuery<int, T const *, true> *>(query)->getTol()));
349
0
  } else if (typeid(*query) == typeid(LessEqualQuery<int, T const *, true>)) {
350
0
    return QueryDetails(std::make_tuple(
351
0
        MolPickler::QUERY_LESSEQUAL,
352
0
        static_cast<const LessEqualQuery<int, T const *, true> *>(query)
353
0
            ->getVal(),
354
0
        static_cast<const LessEqualQuery<int, T const *, true> *>(query)
355
0
            ->getTol()));
356
0
  } else if (typeid(*query) == typeid(AtomRingQuery)) {
357
0
    return QueryDetails(std::make_tuple(
358
0
        MolPickler::QUERY_ATOMRING,
359
0
        static_cast<const EqualityQuery<int, T const *, true> *>(query)
360
0
            ->getVal(),
361
0
        static_cast<const EqualityQuery<int, T const *, true> *>(query)
362
0
            ->getTol()));
363
0
  } else if (typeid(*query) == typeid(HasPropQuery<T const *>)) {
364
0
    return QueryDetails(std::make_tuple(
365
0
        MolPickler::QUERY_PROPERTY,
366
0
        static_cast<const HasPropQuery<T const *> *>(query)->getPropName()));
367
0
  } else if (typeid(*query) == typeid(Query<int, T const *, true>)) {
368
0
    return QueryDetails(MolPickler::QUERY_NULL);
369
0
  } else if (typeid(*query) == typeid(RangeQuery<int, T const *, true>)) {
370
0
    char ends;
371
0
    bool lowerOpen, upperOpen;
372
0
    boost::tie(lowerOpen, upperOpen) =
373
0
        static_cast<const RangeQuery<int, T const *, true> *>(query)
374
0
            ->getEndsOpen();
375
0
    ends = 0 | (rdcast<int>(lowerOpen) << 1) | rdcast<int>(upperOpen);
376
0
    return QueryDetails(std::make_tuple(
377
0
        MolPickler::QUERY_RANGE,
378
0
        static_cast<const RangeQuery<int, T const *, true> *>(query)
379
0
            ->getLower(),
380
0
        static_cast<const RangeQuery<int, T const *, true> *>(query)
381
0
            ->getUpper(),
382
0
        static_cast<const RangeQuery<int, T const *, true> *>(query)->getTol(),
383
0
        ends));
384
0
  } else if (typeid(*query) == typeid(SetQuery<int, T const *, true>)) {
385
0
    std::set<int32_t> tset(
386
0
        static_cast<const SetQuery<int, T const *, true> *>(query)->beginSet(),
387
0
        static_cast<const SetQuery<int, T const *, true> *>(query)->endSet());
388
0
    return QueryDetails(
389
0
        std::make_tuple(MolPickler::QUERY_SET, std::move(tset)));
390
0
  } else if (auto q = dynamic_cast<const HasPropWithValueQueryBase *>(query)) {
391
0
    return QueryDetails(std::make_tuple(MolPickler::QUERY_PROPERTY_WITH_VALUE,
392
0
                                        q->getPair(), q->getTolerance()));
393
0
  } else {
394
0
    throw MolPicklerException("do not know how to pickle part of the query.");
395
0
  }
396
0
}
Unexecuted instantiation: std::__1::variant<RDKit::MolPickler::Tags, std::__1::tuple<RDKit::MolPickler::Tags, int>, std::__1::tuple<RDKit::MolPickler::Tags, int, int>, std::__1::tuple<RDKit::MolPickler::Tags, int, int, int, char>, std::__1::tuple<RDKit::MolPickler::Tags, std::__1::set<int, std::__1::less<int>, std::__1::allocator<int> > >, std::__1::tuple<RDKit::MolPickler::Tags, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::tuple<RDKit::MolPickler::Tags, RDKit::PairHolder, double> > RDKit::PicklerOps::getQueryDetails<RDKit::Atom>(Queries::Query<int, RDKit::Atom const*, true> const*)
Unexecuted instantiation: std::__1::variant<RDKit::MolPickler::Tags, std::__1::tuple<RDKit::MolPickler::Tags, int>, std::__1::tuple<RDKit::MolPickler::Tags, int, int>, std::__1::tuple<RDKit::MolPickler::Tags, int, int, int, char>, std::__1::tuple<RDKit::MolPickler::Tags, std::__1::set<int, std::__1::less<int>, std::__1::allocator<int> > >, std::__1::tuple<RDKit::MolPickler::Tags, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::tuple<RDKit::MolPickler::Tags, RDKit::PairHolder, double> > RDKit::PicklerOps::getQueryDetails<RDKit::Bond>(Queries::Query<int, RDKit::Bond const*, true> const*)
397
template RDKIT_GRAPHMOL_EXPORT QueryDetails getQueryDetails<RDKit::Atom>(
398
    const Queries::Query<int, RDKit::Atom const *, true> *query);
399
template RDKIT_GRAPHMOL_EXPORT QueryDetails getQueryDetails<RDKit::Bond>(
400
    const Queries::Query<int, RDKit::Bond const *, true> *query);
401
402
}  // namespace PicklerOps
403
404
namespace {
405
template <class T>
406
0
void pickleQuery(std::ostream &ss, const Query<int, T const *, true> *query) {
407
0
  PRECONDITION(query, "no query");
408
0
  streamWrite(ss, query->getDescription());
409
0
  if (!query->getTypeLabel().empty()) {
410
0
    streamWrite(ss, MolPickler::QUERY_TYPELABEL);
411
0
    streamWrite(ss, query->getTypeLabel());
412
0
  }
413
0
  if (query->getNegation()) {
414
0
    streamWrite(ss, MolPickler::QUERY_ISNEGATED);
415
0
  }
416
0
  if (typeid(*query) == typeid(RecursiveStructureQuery)) {
417
0
    streamWrite(ss, MolPickler::QUERY_RECURSIVE);
418
0
    streamWrite(ss, MolPickler::QUERY_VALUE);
419
0
    MolPickler::pickleMol(
420
0
        ((const RecursiveStructureQuery *)query)->getQueryMol(), ss);
421
0
  } else {
422
0
    auto qdetails = PicklerOps::getQueryDetails(query);
423
0
    switch (qdetails.index()) {
424
0
      case 0:
425
0
        streamWrite(ss, std::get<MolPickler::Tags>(qdetails));
426
0
        break;
427
0
      case 1: {
428
0
        auto v = std::get<std::tuple<MolPickler::Tags, int32_t>>(qdetails);
429
0
        streamWrite(ss, std::get<0>(v));
430
0
        streamWrite(ss, MolPickler::QUERY_VALUE, std::get<1>(v));
431
0
      } break;
432
0
      case 2: {
433
0
        auto v =
434
0
            std::get<std::tuple<MolPickler::Tags, int32_t, int32_t>>(qdetails);
435
0
        streamWrite(ss, std::get<0>(v));
436
0
        streamWrite(ss, MolPickler::QUERY_VALUE, std::get<1>(v));
437
0
        streamWrite(ss, std::get<2>(v));
438
0
      } break;
439
0
      case 3: {
440
0
        auto v = std::get<
441
0
            std::tuple<MolPickler::Tags, int32_t, int32_t, int32_t, char>>(
442
0
            qdetails);
443
0
        streamWrite(ss, std::get<0>(v));
444
0
        streamWrite(ss, MolPickler::QUERY_VALUE, std::get<1>(v));
445
0
        streamWrite(ss, std::get<2>(v));
446
0
        streamWrite(ss, std::get<3>(v));
447
0
        streamWrite(ss, std::get<4>(v));
448
0
      } break;
449
0
      case 4: {
450
0
        auto v =
451
0
            std::get<std::tuple<MolPickler::Tags, std::set<int32_t>>>(qdetails);
452
0
        streamWrite(ss, std::get<0>(v));
453
0
        const auto &tset = std::get<1>(v);
454
0
        int32_t sz = tset.size();
455
0
        streamWrite(ss, MolPickler::QUERY_VALUE, sz);
456
0
        for (auto val : tset) {
457
0
          streamWrite(ss, val);
458
0
        }
459
460
0
      } break;
461
0
      case 5: {
462
0
        auto v = std::get<std::tuple<MolPickler::Tags, std::string>>(qdetails);
463
0
        streamWrite(ss, std::get<0>(v));
464
0
        const auto &pval = std::get<1>(v);
465
0
        streamWrite(ss, MolPickler::QUERY_VALUE, pval);
466
0
      } break;
467
0
      case 6: {
468
0
        auto &v = std::get<std::tuple<MolPickler::Tags, PairHolder, double>>(
469
0
            qdetails);
470
0
        streamWrite(ss, std::get<0>(v));
471
        // The tolerance is pickled first as we can't pickle a PairHolder with
472
        // the QUERY_VALUE tag
473
0
        streamWrite(ss, MolPickler::QUERY_VALUE, std::get<2>(v));
474
0
        streamWriteProp(ss, std::get<1>(v),
475
0
                        MolPickler::getCustomPropHandlers());
476
0
      } break;
477
0
      default:
478
0
        throw MolPicklerException(
479
0
            "do not know how to pickle part of the query.");
480
0
    }
481
0
  }
482
483
  // now the children:
484
0
  streamWrite(ss, MolPickler::QUERY_NUMCHILDREN,
485
0
              static_cast<unsigned char>(query->endChildren() -
486
0
                                         query->beginChildren()));
487
0
  typename Query<int, T const *, true>::CHILD_VECT_CI cit;
488
0
  for (cit = query->beginChildren(); cit != query->endChildren(); ++cit) {
489
0
    pickleQuery(ss, cit->get());
490
0
  }
491
0
}
Unexecuted instantiation: MolPickler.cpp:void RDKit::(anonymous namespace)::pickleQuery<RDKit::Atom>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Queries::Query<int, RDKit::Atom const*, true> const*)
Unexecuted instantiation: MolPickler.cpp:void RDKit::(anonymous namespace)::pickleQuery<RDKit::Bond>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Queries::Query<int, RDKit::Bond const*, true> const*)
492
493
template <class T>
494
Query<int, T const *, true> *buildBaseQuery(std::istream &ss, T const *owner,
495
1.85k
                                            MolPickler::Tags tag, int version) {
496
1.85k
  PRECONDITION(owner, "no query");
497
1.85k
  std::string descr;
498
1.85k
  Query<int, T const *, true> *res = nullptr;
499
1.85k
  int32_t val;
500
1.85k
  int32_t nMembers;
501
1.85k
  char cval;
502
1.85k
  const unsigned int lowerOpen = 1 << 1;
503
1.85k
  const unsigned int upperOpen = 1;
504
1.85k
  switch (tag) {
505
0
    case MolPickler::QUERY_AND:
506
0
      res = new AndQuery<int, T const *, true>();
507
0
      break;
508
164
    case MolPickler::QUERY_OR:
509
164
      res = new OrQuery<int, T const *, true>();
510
164
      break;
511
1
    case MolPickler::QUERY_XOR:
512
1
      res = new XOrQuery<int, T const *, true>();
513
1
      break;
514
571
    case MolPickler::QUERY_EQUALS:
515
571
      res = new EqualityQuery<int, T const *, true>();
516
571
      streamRead(ss, tag, version);
517
571
      if (tag != MolPickler::QUERY_VALUE) {
518
0
        delete res;
519
0
        throw MolPicklerException(
520
0
            "Bad pickle format: QUERY_VALUE tag not found.");
521
0
      }
522
571
      streamRead(ss, val, version);
523
571
      static_cast<EqualityQuery<int, T const *, true> *>(res)->setVal(val);
524
571
      streamRead(ss, val, version);
525
571
      static_cast<EqualityQuery<int, T const *, true> *>(res)->setTol(val);
526
571
      break;
527
869
    case MolPickler::QUERY_GREATER:
528
869
      res = new GreaterQuery<int, T const *, true>();
529
869
      streamRead(ss, tag, version);
530
869
      if (tag != MolPickler::QUERY_VALUE) {
531
0
        delete res;
532
0
        throw MolPicklerException(
533
0
            "Bad pickle format: QUERY_VALUE tag not found.");
534
0
      }
535
869
      streamRead(ss, val, version);
536
869
      static_cast<GreaterQuery<int, T const *, true> *>(res)->setVal(val);
537
869
      streamRead(ss, val, version);
538
869
      static_cast<GreaterQuery<int, T const *, true> *>(res)->setTol(val);
539
869
      break;
540
2
    case MolPickler::QUERY_GREATEREQUAL:
541
2
      res = new GreaterEqualQuery<int, T const *, true>();
542
2
      streamRead(ss, tag, version);
543
2
      if (tag != MolPickler::QUERY_VALUE) {
544
0
        delete res;
545
0
        throw MolPicklerException(
546
0
            "Bad pickle format: QUERY_VALUE tag not found.");
547
0
      }
548
2
      streamRead(ss, val, version);
549
2
      static_cast<GreaterEqualQuery<int, T const *, true> *>(res)->setVal(val);
550
2
      streamRead(ss, val, version);
551
2
      static_cast<GreaterEqualQuery<int, T const *, true> *>(res)->setTol(val);
552
2
      break;
553
0
    case MolPickler::QUERY_LESS:
554
0
      res = new LessQuery<int, T const *, true>();
555
0
      streamRead(ss, tag, version);
556
0
      if (tag != MolPickler::QUERY_VALUE) {
557
0
        delete res;
558
0
        throw MolPicklerException(
559
0
            "Bad pickle format: QUERY_VALUE tag not found.");
560
0
      }
561
0
      streamRead(ss, val, version);
562
0
      static_cast<LessQuery<int, T const *, true> *>(res)->setVal(val);
563
0
      streamRead(ss, val, version);
564
0
      static_cast<LessQuery<int, T const *, true> *>(res)->setTol(val);
565
0
      break;
566
0
    case MolPickler::QUERY_LESSEQUAL:
567
0
      res = new LessEqualQuery<int, T const *, true>();
568
0
      streamRead(ss, tag, version);
569
0
      if (tag != MolPickler::QUERY_VALUE) {
570
0
        delete res;
571
0
        throw MolPicklerException(
572
0
            "Bad pickle format: QUERY_VALUE tag not found.");
573
0
      }
574
0
      streamRead(ss, val, version);
575
0
      static_cast<LessEqualQuery<int, T const *, true> *>(res)->setVal(val);
576
0
      streamRead(ss, val, version);
577
0
      static_cast<LessEqualQuery<int, T const *, true> *>(res)->setTol(val);
578
0
      break;
579
0
    case MolPickler::QUERY_RANGE:
580
0
      res = new RangeQuery<int, T const *, true>();
581
0
      streamRead(ss, tag, version);
582
0
      if (tag != MolPickler::QUERY_VALUE) {
583
0
        delete res;
584
0
        throw MolPicklerException(
585
0
            "Bad pickle format: QUERY_VALUE tag not found.");
586
0
      }
587
0
      streamRead(ss, val, version);
588
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setLower(val);
589
0
      streamRead(ss, val, version);
590
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setUpper(val);
591
0
      streamRead(ss, val, version);
592
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setTol(val);
593
0
      streamRead(ss, cval, version);
594
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setEndsOpen(
595
0
          cval & lowerOpen, cval & upperOpen);
596
0
      break;
597
247
    case MolPickler::QUERY_SET:
598
247
      res = new SetQuery<int, T const *, true>();
599
247
      streamRead(ss, tag, version);
600
247
      if (tag != MolPickler::QUERY_VALUE) {
601
0
        delete res;
602
0
        throw MolPicklerException(
603
0
            "Bad pickle format: QUERY_VALUE tag not found.");
604
0
      }
605
247
      streamRead(ss, nMembers);
606
21.8k
      while (nMembers > 0) {
607
21.6k
        streamRead(ss, val, version);
608
21.6k
        static_cast<SetQuery<int, T const *, true> *>(res)->insert(val);
609
21.6k
        --nMembers;
610
21.6k
      }
611
247
      break;
612
0
    case MolPickler::QUERY_NULL:
613
0
      res = new Query<int, T const *, true>();
614
0
      break;
615
0
    case MolPickler::QUERY_PROPERTY: {
616
0
      streamRead(ss, tag, version);
617
0
      if (tag != MolPickler::QUERY_VALUE) {
618
0
        throw MolPicklerException(
619
0
            "Bad pickle format: QUERY_VALUE tag not found.");
620
0
      }
621
0
      std::string propName = "";
622
0
      streamRead(ss, propName, version);
623
0
      res = makeHasPropQuery<T>(propName);
624
0
    } break;
625
0
    case MolPickler::QUERY_PROPERTY_WITH_VALUE: {
626
0
      streamRead(ss, tag, version);
627
0
      if (tag != MolPickler::QUERY_VALUE) {
628
0
        throw MolPicklerException(
629
0
            "Bad pickle format: QUERY_VALUE tag not found.");
630
0
      }
631
0
      double tolerance{0.0};
632
0
      streamRead(ss, tolerance, version);
633
0
      PairHolder pair;
634
0
      streamReadProp(ss, pair, MolPickler::getCustomPropHandlers());
635
0
      switch (pair.val.getTag()) {
636
0
        case RDTypeTag::IntTag:
637
0
          res = makePropQuery<T, int>(pair.key, rdvalue_cast<int>(pair.val),
638
0
                                      tolerance);
639
0
          break;
640
0
        case RDTypeTag::UnsignedIntTag:
641
0
          res = makePropQuery<T, unsigned int>(
642
0
              pair.key, rdvalue_cast<unsigned int>(pair.val), tolerance);
643
0
          break;
644
0
        case RDTypeTag::BoolTag:
645
0
          res = makePropQuery<T, bool>(pair.key, rdvalue_cast<bool>(pair.val),
646
0
                                       tolerance);
647
0
          break;
648
0
        case RDTypeTag::FloatTag:
649
0
          res = makePropQuery<T, float>(pair.key, rdvalue_cast<float>(pair.val),
650
0
                                        tolerance);
651
0
          break;
652
0
        case RDTypeTag::DoubleTag:
653
0
          res = makePropQuery<T, double>(
654
0
              pair.key, rdvalue_cast<double>(pair.val), tolerance);
655
0
          break;
656
0
        case RDTypeTag::StringTag:
657
0
          res = makePropQuery<T, std::string>(
658
0
              pair.key, rdvalue_cast<std::string>(pair.val), tolerance);
659
0
          break;
660
0
        case RDTypeTag::AnyTag: {
661
0
          if (rdvalue_is<ExplicitBitVect>(pair.val)) {
662
0
            res = makePropQuery<T, ExplicitBitVect>(
663
0
                pair.key, rdvalue_cast<ExplicitBitVect>(pair.val), tolerance);
664
0
          } else {
665
0
            throw MolPicklerException("unknown query-type tag encountered");
666
0
          }
667
0
        } break;
668
0
      }
669
0
    } break;
670
2
    default:
671
2
      throw MolPicklerException("unknown query-type tag encountered");
672
1.85k
  }
673
674
1.84k
  POSTCONDITION(res, "no match found");
675
1.84k
  return res;
676
1.84k
}
MolPickler.cpp:Queries::Query<int, RDKit::Atom const*, true>* RDKit::(anonymous namespace)::buildBaseQuery<RDKit::Atom>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::Atom const*, RDKit::MolPickler::Tags, int)
Line
Count
Source
495
1.85k
                                            MolPickler::Tags tag, int version) {
496
1.85k
  PRECONDITION(owner, "no query");
497
1.85k
  std::string descr;
498
1.85k
  Query<int, T const *, true> *res = nullptr;
499
1.85k
  int32_t val;
500
1.85k
  int32_t nMembers;
501
1.85k
  char cval;
502
1.85k
  const unsigned int lowerOpen = 1 << 1;
503
1.85k
  const unsigned int upperOpen = 1;
504
1.85k
  switch (tag) {
505
0
    case MolPickler::QUERY_AND:
506
0
      res = new AndQuery<int, T const *, true>();
507
0
      break;
508
164
    case MolPickler::QUERY_OR:
509
164
      res = new OrQuery<int, T const *, true>();
510
164
      break;
511
1
    case MolPickler::QUERY_XOR:
512
1
      res = new XOrQuery<int, T const *, true>();
513
1
      break;
514
571
    case MolPickler::QUERY_EQUALS:
515
571
      res = new EqualityQuery<int, T const *, true>();
516
571
      streamRead(ss, tag, version);
517
571
      if (tag != MolPickler::QUERY_VALUE) {
518
0
        delete res;
519
0
        throw MolPicklerException(
520
0
            "Bad pickle format: QUERY_VALUE tag not found.");
521
0
      }
522
571
      streamRead(ss, val, version);
523
571
      static_cast<EqualityQuery<int, T const *, true> *>(res)->setVal(val);
524
571
      streamRead(ss, val, version);
525
571
      static_cast<EqualityQuery<int, T const *, true> *>(res)->setTol(val);
526
571
      break;
527
868
    case MolPickler::QUERY_GREATER:
528
868
      res = new GreaterQuery<int, T const *, true>();
529
868
      streamRead(ss, tag, version);
530
868
      if (tag != MolPickler::QUERY_VALUE) {
531
0
        delete res;
532
0
        throw MolPicklerException(
533
0
            "Bad pickle format: QUERY_VALUE tag not found.");
534
0
      }
535
868
      streamRead(ss, val, version);
536
868
      static_cast<GreaterQuery<int, T const *, true> *>(res)->setVal(val);
537
868
      streamRead(ss, val, version);
538
868
      static_cast<GreaterQuery<int, T const *, true> *>(res)->setTol(val);
539
868
      break;
540
2
    case MolPickler::QUERY_GREATEREQUAL:
541
2
      res = new GreaterEqualQuery<int, T const *, true>();
542
2
      streamRead(ss, tag, version);
543
2
      if (tag != MolPickler::QUERY_VALUE) {
544
0
        delete res;
545
0
        throw MolPicklerException(
546
0
            "Bad pickle format: QUERY_VALUE tag not found.");
547
0
      }
548
2
      streamRead(ss, val, version);
549
2
      static_cast<GreaterEqualQuery<int, T const *, true> *>(res)->setVal(val);
550
2
      streamRead(ss, val, version);
551
2
      static_cast<GreaterEqualQuery<int, T const *, true> *>(res)->setTol(val);
552
2
      break;
553
0
    case MolPickler::QUERY_LESS:
554
0
      res = new LessQuery<int, T const *, true>();
555
0
      streamRead(ss, tag, version);
556
0
      if (tag != MolPickler::QUERY_VALUE) {
557
0
        delete res;
558
0
        throw MolPicklerException(
559
0
            "Bad pickle format: QUERY_VALUE tag not found.");
560
0
      }
561
0
      streamRead(ss, val, version);
562
0
      static_cast<LessQuery<int, T const *, true> *>(res)->setVal(val);
563
0
      streamRead(ss, val, version);
564
0
      static_cast<LessQuery<int, T const *, true> *>(res)->setTol(val);
565
0
      break;
566
0
    case MolPickler::QUERY_LESSEQUAL:
567
0
      res = new LessEqualQuery<int, T const *, true>();
568
0
      streamRead(ss, tag, version);
569
0
      if (tag != MolPickler::QUERY_VALUE) {
570
0
        delete res;
571
0
        throw MolPicklerException(
572
0
            "Bad pickle format: QUERY_VALUE tag not found.");
573
0
      }
574
0
      streamRead(ss, val, version);
575
0
      static_cast<LessEqualQuery<int, T const *, true> *>(res)->setVal(val);
576
0
      streamRead(ss, val, version);
577
0
      static_cast<LessEqualQuery<int, T const *, true> *>(res)->setTol(val);
578
0
      break;
579
0
    case MolPickler::QUERY_RANGE:
580
0
      res = new RangeQuery<int, T const *, true>();
581
0
      streamRead(ss, tag, version);
582
0
      if (tag != MolPickler::QUERY_VALUE) {
583
0
        delete res;
584
0
        throw MolPicklerException(
585
0
            "Bad pickle format: QUERY_VALUE tag not found.");
586
0
      }
587
0
      streamRead(ss, val, version);
588
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setLower(val);
589
0
      streamRead(ss, val, version);
590
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setUpper(val);
591
0
      streamRead(ss, val, version);
592
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setTol(val);
593
0
      streamRead(ss, cval, version);
594
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setEndsOpen(
595
0
          cval & lowerOpen, cval & upperOpen);
596
0
      break;
597
243
    case MolPickler::QUERY_SET:
598
243
      res = new SetQuery<int, T const *, true>();
599
243
      streamRead(ss, tag, version);
600
243
      if (tag != MolPickler::QUERY_VALUE) {
601
0
        delete res;
602
0
        throw MolPicklerException(
603
0
            "Bad pickle format: QUERY_VALUE tag not found.");
604
0
      }
605
243
      streamRead(ss, nMembers);
606
16.7k
      while (nMembers > 0) {
607
16.4k
        streamRead(ss, val, version);
608
16.4k
        static_cast<SetQuery<int, T const *, true> *>(res)->insert(val);
609
16.4k
        --nMembers;
610
16.4k
      }
611
243
      break;
612
0
    case MolPickler::QUERY_NULL:
613
0
      res = new Query<int, T const *, true>();
614
0
      break;
615
0
    case MolPickler::QUERY_PROPERTY: {
616
0
      streamRead(ss, tag, version);
617
0
      if (tag != MolPickler::QUERY_VALUE) {
618
0
        throw MolPicklerException(
619
0
            "Bad pickle format: QUERY_VALUE tag not found.");
620
0
      }
621
0
      std::string propName = "";
622
0
      streamRead(ss, propName, version);
623
0
      res = makeHasPropQuery<T>(propName);
624
0
    } break;
625
0
    case MolPickler::QUERY_PROPERTY_WITH_VALUE: {
626
0
      streamRead(ss, tag, version);
627
0
      if (tag != MolPickler::QUERY_VALUE) {
628
0
        throw MolPicklerException(
629
0
            "Bad pickle format: QUERY_VALUE tag not found.");
630
0
      }
631
0
      double tolerance{0.0};
632
0
      streamRead(ss, tolerance, version);
633
0
      PairHolder pair;
634
0
      streamReadProp(ss, pair, MolPickler::getCustomPropHandlers());
635
0
      switch (pair.val.getTag()) {
636
0
        case RDTypeTag::IntTag:
637
0
          res = makePropQuery<T, int>(pair.key, rdvalue_cast<int>(pair.val),
638
0
                                      tolerance);
639
0
          break;
640
0
        case RDTypeTag::UnsignedIntTag:
641
0
          res = makePropQuery<T, unsigned int>(
642
0
              pair.key, rdvalue_cast<unsigned int>(pair.val), tolerance);
643
0
          break;
644
0
        case RDTypeTag::BoolTag:
645
0
          res = makePropQuery<T, bool>(pair.key, rdvalue_cast<bool>(pair.val),
646
0
                                       tolerance);
647
0
          break;
648
0
        case RDTypeTag::FloatTag:
649
0
          res = makePropQuery<T, float>(pair.key, rdvalue_cast<float>(pair.val),
650
0
                                        tolerance);
651
0
          break;
652
0
        case RDTypeTag::DoubleTag:
653
0
          res = makePropQuery<T, double>(
654
0
              pair.key, rdvalue_cast<double>(pair.val), tolerance);
655
0
          break;
656
0
        case RDTypeTag::StringTag:
657
0
          res = makePropQuery<T, std::string>(
658
0
              pair.key, rdvalue_cast<std::string>(pair.val), tolerance);
659
0
          break;
660
0
        case RDTypeTag::AnyTag: {
661
0
          if (rdvalue_is<ExplicitBitVect>(pair.val)) {
662
0
            res = makePropQuery<T, ExplicitBitVect>(
663
0
                pair.key, rdvalue_cast<ExplicitBitVect>(pair.val), tolerance);
664
0
          } else {
665
0
            throw MolPicklerException("unknown query-type tag encountered");
666
0
          }
667
0
        } break;
668
0
      }
669
0
    } break;
670
2
    default:
671
2
      throw MolPicklerException("unknown query-type tag encountered");
672
1.85k
  }
673
674
1.84k
  POSTCONDITION(res, "no match found");
675
1.84k
  return res;
676
1.84k
}
MolPickler.cpp:Queries::Query<int, RDKit::Bond const*, true>* RDKit::(anonymous namespace)::buildBaseQuery<RDKit::Bond>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::Bond const*, RDKit::MolPickler::Tags, int)
Line
Count
Source
495
5
                                            MolPickler::Tags tag, int version) {
496
5
  PRECONDITION(owner, "no query");
497
5
  std::string descr;
498
5
  Query<int, T const *, true> *res = nullptr;
499
5
  int32_t val;
500
5
  int32_t nMembers;
501
5
  char cval;
502
5
  const unsigned int lowerOpen = 1 << 1;
503
5
  const unsigned int upperOpen = 1;
504
5
  switch (tag) {
505
0
    case MolPickler::QUERY_AND:
506
0
      res = new AndQuery<int, T const *, true>();
507
0
      break;
508
0
    case MolPickler::QUERY_OR:
509
0
      res = new OrQuery<int, T const *, true>();
510
0
      break;
511
0
    case MolPickler::QUERY_XOR:
512
0
      res = new XOrQuery<int, T const *, true>();
513
0
      break;
514
0
    case MolPickler::QUERY_EQUALS:
515
0
      res = new EqualityQuery<int, T const *, true>();
516
0
      streamRead(ss, tag, version);
517
0
      if (tag != MolPickler::QUERY_VALUE) {
518
0
        delete res;
519
0
        throw MolPicklerException(
520
0
            "Bad pickle format: QUERY_VALUE tag not found.");
521
0
      }
522
0
      streamRead(ss, val, version);
523
0
      static_cast<EqualityQuery<int, T const *, true> *>(res)->setVal(val);
524
0
      streamRead(ss, val, version);
525
0
      static_cast<EqualityQuery<int, T const *, true> *>(res)->setTol(val);
526
0
      break;
527
1
    case MolPickler::QUERY_GREATER:
528
1
      res = new GreaterQuery<int, T const *, true>();
529
1
      streamRead(ss, tag, version);
530
1
      if (tag != MolPickler::QUERY_VALUE) {
531
0
        delete res;
532
0
        throw MolPicklerException(
533
0
            "Bad pickle format: QUERY_VALUE tag not found.");
534
0
      }
535
1
      streamRead(ss, val, version);
536
1
      static_cast<GreaterQuery<int, T const *, true> *>(res)->setVal(val);
537
1
      streamRead(ss, val, version);
538
1
      static_cast<GreaterQuery<int, T const *, true> *>(res)->setTol(val);
539
1
      break;
540
0
    case MolPickler::QUERY_GREATEREQUAL:
541
0
      res = new GreaterEqualQuery<int, T const *, true>();
542
0
      streamRead(ss, tag, version);
543
0
      if (tag != MolPickler::QUERY_VALUE) {
544
0
        delete res;
545
0
        throw MolPicklerException(
546
0
            "Bad pickle format: QUERY_VALUE tag not found.");
547
0
      }
548
0
      streamRead(ss, val, version);
549
0
      static_cast<GreaterEqualQuery<int, T const *, true> *>(res)->setVal(val);
550
0
      streamRead(ss, val, version);
551
0
      static_cast<GreaterEqualQuery<int, T const *, true> *>(res)->setTol(val);
552
0
      break;
553
0
    case MolPickler::QUERY_LESS:
554
0
      res = new LessQuery<int, T const *, true>();
555
0
      streamRead(ss, tag, version);
556
0
      if (tag != MolPickler::QUERY_VALUE) {
557
0
        delete res;
558
0
        throw MolPicklerException(
559
0
            "Bad pickle format: QUERY_VALUE tag not found.");
560
0
      }
561
0
      streamRead(ss, val, version);
562
0
      static_cast<LessQuery<int, T const *, true> *>(res)->setVal(val);
563
0
      streamRead(ss, val, version);
564
0
      static_cast<LessQuery<int, T const *, true> *>(res)->setTol(val);
565
0
      break;
566
0
    case MolPickler::QUERY_LESSEQUAL:
567
0
      res = new LessEqualQuery<int, T const *, true>();
568
0
      streamRead(ss, tag, version);
569
0
      if (tag != MolPickler::QUERY_VALUE) {
570
0
        delete res;
571
0
        throw MolPicklerException(
572
0
            "Bad pickle format: QUERY_VALUE tag not found.");
573
0
      }
574
0
      streamRead(ss, val, version);
575
0
      static_cast<LessEqualQuery<int, T const *, true> *>(res)->setVal(val);
576
0
      streamRead(ss, val, version);
577
0
      static_cast<LessEqualQuery<int, T const *, true> *>(res)->setTol(val);
578
0
      break;
579
0
    case MolPickler::QUERY_RANGE:
580
0
      res = new RangeQuery<int, T const *, true>();
581
0
      streamRead(ss, tag, version);
582
0
      if (tag != MolPickler::QUERY_VALUE) {
583
0
        delete res;
584
0
        throw MolPicklerException(
585
0
            "Bad pickle format: QUERY_VALUE tag not found.");
586
0
      }
587
0
      streamRead(ss, val, version);
588
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setLower(val);
589
0
      streamRead(ss, val, version);
590
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setUpper(val);
591
0
      streamRead(ss, val, version);
592
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setTol(val);
593
0
      streamRead(ss, cval, version);
594
0
      static_cast<RangeQuery<int, T const *, true> *>(res)->setEndsOpen(
595
0
          cval & lowerOpen, cval & upperOpen);
596
0
      break;
597
4
    case MolPickler::QUERY_SET:
598
4
      res = new SetQuery<int, T const *, true>();
599
4
      streamRead(ss, tag, version);
600
4
      if (tag != MolPickler::QUERY_VALUE) {
601
0
        delete res;
602
0
        throw MolPicklerException(
603
0
            "Bad pickle format: QUERY_VALUE tag not found.");
604
0
      }
605
4
      streamRead(ss, nMembers);
606
5.10k
      while (nMembers > 0) {
607
5.10k
        streamRead(ss, val, version);
608
5.10k
        static_cast<SetQuery<int, T const *, true> *>(res)->insert(val);
609
5.10k
        --nMembers;
610
5.10k
      }
611
4
      break;
612
0
    case MolPickler::QUERY_NULL:
613
0
      res = new Query<int, T const *, true>();
614
0
      break;
615
0
    case MolPickler::QUERY_PROPERTY: {
616
0
      streamRead(ss, tag, version);
617
0
      if (tag != MolPickler::QUERY_VALUE) {
618
0
        throw MolPicklerException(
619
0
            "Bad pickle format: QUERY_VALUE tag not found.");
620
0
      }
621
0
      std::string propName = "";
622
0
      streamRead(ss, propName, version);
623
0
      res = makeHasPropQuery<T>(propName);
624
0
    } break;
625
0
    case MolPickler::QUERY_PROPERTY_WITH_VALUE: {
626
0
      streamRead(ss, tag, version);
627
0
      if (tag != MolPickler::QUERY_VALUE) {
628
0
        throw MolPicklerException(
629
0
            "Bad pickle format: QUERY_VALUE tag not found.");
630
0
      }
631
0
      double tolerance{0.0};
632
0
      streamRead(ss, tolerance, version);
633
0
      PairHolder pair;
634
0
      streamReadProp(ss, pair, MolPickler::getCustomPropHandlers());
635
0
      switch (pair.val.getTag()) {
636
0
        case RDTypeTag::IntTag:
637
0
          res = makePropQuery<T, int>(pair.key, rdvalue_cast<int>(pair.val),
638
0
                                      tolerance);
639
0
          break;
640
0
        case RDTypeTag::UnsignedIntTag:
641
0
          res = makePropQuery<T, unsigned int>(
642
0
              pair.key, rdvalue_cast<unsigned int>(pair.val), tolerance);
643
0
          break;
644
0
        case RDTypeTag::BoolTag:
645
0
          res = makePropQuery<T, bool>(pair.key, rdvalue_cast<bool>(pair.val),
646
0
                                       tolerance);
647
0
          break;
648
0
        case RDTypeTag::FloatTag:
649
0
          res = makePropQuery<T, float>(pair.key, rdvalue_cast<float>(pair.val),
650
0
                                        tolerance);
651
0
          break;
652
0
        case RDTypeTag::DoubleTag:
653
0
          res = makePropQuery<T, double>(
654
0
              pair.key, rdvalue_cast<double>(pair.val), tolerance);
655
0
          break;
656
0
        case RDTypeTag::StringTag:
657
0
          res = makePropQuery<T, std::string>(
658
0
              pair.key, rdvalue_cast<std::string>(pair.val), tolerance);
659
0
          break;
660
0
        case RDTypeTag::AnyTag: {
661
0
          if (rdvalue_is<ExplicitBitVect>(pair.val)) {
662
0
            res = makePropQuery<T, ExplicitBitVect>(
663
0
                pair.key, rdvalue_cast<ExplicitBitVect>(pair.val), tolerance);
664
0
          } else {
665
0
            throw MolPicklerException("unknown query-type tag encountered");
666
0
          }
667
0
        } break;
668
0
      }
669
0
    } break;
670
0
    default:
671
0
      throw MolPicklerException("unknown query-type tag encountered");
672
5
  }
673
674
1
  POSTCONDITION(res, "no match found");
675
1
  return res;
676
1
}
677
678
Query<int, Atom const *, true> *unpickleQuery(std::istream &ss,
679
16.0k
                                              Atom const *owner, int version) {
680
16.0k
  PRECONDITION(owner, "no query");
681
16.0k
  std::string descr;
682
16.0k
  std::string typeLabel = "";
683
16.0k
  bool isNegated = false;
684
16.0k
  Query<int, Atom const *, true> *res;
685
16.0k
  streamRead(ss, descr, version);
686
16.0k
  MolPickler::Tags tag;
687
16.0k
  streamRead(ss, tag, version);
688
16.0k
  if (tag == MolPickler::QUERY_TYPELABEL) {
689
0
    streamRead(ss, typeLabel, version);
690
0
    streamRead(ss, tag, version);
691
0
  }
692
16.0k
  if (tag == MolPickler::QUERY_ISNEGATED) {
693
0
    isNegated = true;
694
0
    streamRead(ss, tag, version);
695
0
  }
696
16.0k
  int32_t val;
697
16.0k
  ROMol *tmpMol;
698
16.0k
  switch (tag) {
699
156
    case MolPickler::QUERY_ATOMRING:
700
156
      streamRead(ss, tag, version);
701
156
      if (tag != MolPickler::QUERY_VALUE) {
702
0
        throw MolPicklerException(
703
0
            "Bad pickle format: QUERY_VALUE tag not found.");
704
0
      }
705
156
      res = new AtomRingQuery();
706
156
      streamRead(ss, val, version);
707
156
      static_cast<EqualityQuery<int, Atom const *, true> *>(res)->setVal(val);
708
156
      streamRead(ss, val, version);
709
156
      static_cast<EqualityQuery<int, Atom const *, true> *>(res)->setTol(val);
710
156
      break;
711
14.0k
    case MolPickler::QUERY_RECURSIVE:
712
14.0k
      streamRead(ss, tag, version);
713
14.0k
      if (tag != MolPickler::QUERY_VALUE) {
714
1
        throw MolPicklerException(
715
1
            "Bad pickle format: QUERY_VALUE tag not found.");
716
1
      }
717
14.0k
      tmpMol = new ROMol();
718
14.0k
      MolPickler::molFromPickle(ss, tmpMol);
719
14.0k
      res = new RecursiveStructureQuery(tmpMol);
720
14.0k
      break;
721
1.85k
    default:
722
1.85k
      res = buildBaseQuery(ss, owner, tag, version);
723
1.85k
      break;
724
16.0k
  }
725
1.99k
  CHECK_INVARIANT(res, "no query!");
726
727
1.99k
  res->setNegation(isNegated);
728
1.99k
  res->setDescription(descr);
729
1.99k
  if (!typeLabel.empty()) {
730
0
    res->setTypeLabel(typeLabel);
731
0
  }
732
733
1.99k
  QueryOps::finalizeQueryFromDescription(res, owner);
734
735
  // read in the children:
736
1.99k
  streamRead(ss, tag, version);
737
1.99k
  if (tag != MolPickler::QUERY_NUMCHILDREN) {
738
5
    throw MolPicklerException(
739
5
        "Bad pickle format: QUERY_NUMCHILDREN tag not found.");
740
5
  }
741
1.99k
  unsigned char numChildren;
742
1.99k
  streamRead(ss, numChildren, version);
743
3.60k
  while (numChildren > 0) {
744
1.60k
    Query<int, Atom const *, true> *child = unpickleQuery(ss, owner, version);
745
1.60k
    res->addChild(Query<int, Atom const *, true>::CHILD_TYPE(child));
746
1.60k
    --numChildren;
747
1.60k
  }
748
1.99k
  return res;
749
1.99k
}
750
Query<int, Bond const *, true> *unpickleQuery(std::istream &ss,
751
5
                                              Bond const *owner, int version) {
752
5
  PRECONDITION(owner, "no query");
753
5
  std::string descr;
754
5
  std::string typeLabel = "";
755
5
  bool isNegated = false;
756
5
  Query<int, Bond const *, true> *res;
757
5
  streamRead(ss, descr, version);
758
5
  MolPickler::Tags tag;
759
5
  streamRead(ss, tag, version);
760
5
  if (tag == MolPickler::QUERY_TYPELABEL) {
761
0
    streamRead(ss, typeLabel, version);
762
0
    streamRead(ss, tag, version);
763
0
  }
764
5
  if (tag == MolPickler::QUERY_ISNEGATED) {
765
0
    isNegated = true;
766
0
    streamRead(ss, tag, version);
767
0
  }
768
5
  res = buildBaseQuery(ss, owner, tag, version);
769
5
  CHECK_INVARIANT(res, "no query!");
770
771
5
  res->setNegation(isNegated);
772
5
  res->setDescription(descr);
773
774
5
  QueryOps::finalizeQueryFromDescription(res, owner);
775
776
  // read in the children:
777
5
  streamRead(ss, tag, version);
778
5
  if (tag != MolPickler::QUERY_NUMCHILDREN) {
779
0
    throw MolPicklerException(
780
0
        "Bad pickle format: QUERY_NUMCHILDREN tag not found.");
781
0
  }
782
5
  unsigned char numChildren;
783
5
  streamRead(ss, numChildren, version);
784
5
  while (numChildren > 0) {
785
0
    Query<int, Bond const *, true> *child = unpickleQuery(ss, owner, version);
786
0
    res->addChild(Query<int, Bond const *, true>::CHILD_TYPE(child));
787
0
    --numChildren;
788
0
  }
789
5
  return res;
790
5
}
791
792
void pickleAtomPDBResidueInfo(std::ostream &ss,
793
0
                              const AtomPDBResidueInfo *info) {
794
0
  PRECONDITION(info, "no info");
795
0
  streamWrite(ss, info->getName());
796
0
  streamWrite(ss, static_cast<unsigned int>(info->getMonomerType()));
797
0
  if (info->getSerialNumber()) {
798
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_SERIALNUMBER,
799
0
                info->getSerialNumber());
800
0
  }
801
0
  if (info->getAltLoc() != "") {
802
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_ALTLOC, info->getAltLoc());
803
0
  }
804
0
  if (info->getResidueName() != "") {
805
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_RESIDUENAME,
806
0
                info->getResidueName());
807
0
  }
808
0
  if (info->getResidueNumber()) {
809
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_RESIDUENUMBER,
810
0
                info->getResidueNumber());
811
0
  }
812
0
  if (info->getChainId() != "") {
813
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_CHAINID, info->getChainId());
814
0
  }
815
0
  if (info->getInsertionCode() != "") {
816
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_INSERTIONCODE,
817
0
                info->getInsertionCode());
818
0
  }
819
0
  if (info->getOccupancy()) {
820
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_OCCUPANCY,
821
0
                info->getOccupancy());
822
0
  }
823
0
  if (info->getTempFactor()) {
824
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_TEMPFACTOR,
825
0
                info->getTempFactor());
826
0
  }
827
0
  if (info->getIsHeteroAtom()) {
828
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_ISHETEROATOM,
829
0
                static_cast<char>(info->getIsHeteroAtom()));
830
0
  }
831
0
  if (info->getSecondaryStructure()) {
832
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_SECONDARYSTRUCTURE,
833
0
                info->getSecondaryStructure());
834
0
  }
835
0
  if (info->getSegmentNumber()) {
836
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_SEGMENTNUMBER,
837
0
                info->getSegmentNumber());
838
0
  }
839
0
  if (info->getMonomerClass() != "") {
840
0
    streamWrite(ss, MolPickler::ATOM_PDB_RESIDUE_MONOMERCLASS,
841
0
                info->getMonomerClass());
842
0
  }
843
0
}
844
845
1.59k
AtomMonomerInfo *unpickleAtomPDBResidueInfo(std::istream &ss, int version) {
846
1.59k
  std::string nm;
847
1.59k
  streamRead(ss, nm, version);
848
1.59k
  unsigned int typ;
849
1.59k
  streamRead(ss, typ, version);
850
851
  // As of version 16.3, some member fields from AtomPDBResidueInfo were moved
852
  // to the AtomMonomerInfo base class. Pickles made from 16.3+ will use the new
853
  // tags and unpickleAtomMonomerInfo to unpickle, but we need to continue to
854
  // support old pickles that don't use the new tags.
855
1.59k
  auto type = static_cast<AtomMonomerInfo::AtomMonomerType>(typ);
856
1.59k
  if (type != AtomMonomerInfo::AtomMonomerType::PDBRESIDUE) {
857
0
    auto info = new AtomMonomerInfo(type, nm);
858
0
    return info;
859
0
  }
860
861
1.59k
  auto info = new AtomPDBResidueInfo(nm);
862
1.59k
  std::string sval;
863
1.59k
  double dval;
864
1.59k
  char cval;
865
1.59k
  unsigned int uival;
866
1.59k
  int ival;
867
1.59k
  MolPickler::Tags tag = MolPickler::BEGIN_PDB_RESIDUE;
868
7.84k
  while (tag != MolPickler::END_PDB_RESIDUE) {
869
6.25k
    streamRead(ss, tag, version);
870
6.25k
    switch (tag) {
871
0
      case MolPickler::ATOM_PDB_RESIDUE_SERIALNUMBER:
872
0
        streamRead(ss, ival, version);
873
0
        info->setSerialNumber(ival);
874
0
        break;
875
0
      case MolPickler::ATOM_PDB_RESIDUE_ALTLOC:
876
0
        streamRead(ss, sval, version);
877
0
        info->setAltLoc(sval);
878
0
        break;
879
173
      case MolPickler::ATOM_PDB_RESIDUE_RESIDUENAME:
880
173
        streamRead(ss, sval, version);
881
173
        info->setResidueName(sval);
882
173
        break;
883
0
      case MolPickler::ATOM_PDB_RESIDUE_RESIDUENUMBER:
884
0
        streamRead(ss, ival, version);
885
0
        info->setResidueNumber(ival);
886
0
        break;
887
1.02k
      case MolPickler::ATOM_PDB_RESIDUE_CHAINID:
888
1.02k
        streamRead(ss, sval, version);
889
1.02k
        info->setChainId(sval);
890
1.02k
        break;
891
282
      case MolPickler::ATOM_PDB_RESIDUE_INSERTIONCODE:
892
282
        streamRead(ss, sval, version);
893
282
        info->setInsertionCode(sval);
894
282
        break;
895
1.06k
      case MolPickler::ATOM_PDB_RESIDUE_OCCUPANCY:
896
1.06k
        streamRead(ss, dval, version);
897
1.06k
        info->setOccupancy(dval);
898
1.06k
        break;
899
2.12k
      case MolPickler::ATOM_PDB_RESIDUE_TEMPFACTOR:
900
2.12k
        streamRead(ss, dval, version);
901
2.12k
        info->setTempFactor(dval);
902
2.12k
        break;
903
0
      case MolPickler::ATOM_PDB_RESIDUE_ISHETEROATOM:
904
0
        streamRead(ss, cval, version);
905
0
        info->setIsHeteroAtom(cval);
906
0
        break;
907
1
      case MolPickler::ATOM_PDB_RESIDUE_SECONDARYSTRUCTURE:
908
1
        streamRead(ss, uival, version);
909
1
        info->setSecondaryStructure(uival);
910
1
        break;
911
0
      case MolPickler::ATOM_PDB_RESIDUE_SEGMENTNUMBER:
912
0
        streamRead(ss, uival, version);
913
0
        info->setSegmentNumber(uival);
914
0
        break;
915
0
      case MolPickler::ATOM_PDB_RESIDUE_MONOMERCLASS:
916
0
        streamRead(ss, sval, version);
917
0
        info->setMonomerClass(sval);
918
0
        break;
919
1.58k
      case MolPickler::END_PDB_RESIDUE:
920
1.58k
        break;
921
3
      default:
922
3
        throw MolPicklerException(
923
3
            "unrecognized tag while parsing atom peptide residue info");
924
6.25k
    }
925
6.25k
  }
926
1.58k
  return info;
927
1.59k
}
928
929
0
void pickleAtomMonomerInfo(std::ostream &ss, const AtomMonomerInfo *info) {
930
0
  PRECONDITION(info, "no info");
931
0
  streamWrite(ss, info->getName());
932
933
0
  auto monomer_type = info->getMonomerType();
934
0
  streamWrite(ss, static_cast<std::uint8_t>(monomer_type));
935
936
  // Additional AtomMonomerInfo base class fields added in version 16.3,
937
  // these fields are pickled for all MonomerTypes
938
0
  if (!info->getResidueName().empty()) {
939
0
    streamWrite(ss, MolPickler::ATOM_MONOMER_INFO_RESIDUENAME,
940
0
                info->getResidueName());
941
0
  }
942
0
  if (info->getResidueNumber()) {
943
0
    streamWrite(ss, MolPickler::ATOM_MONOMER_INFO_RESIDUENUMBER,
944
0
                info->getResidueNumber());
945
0
  }
946
0
  if (!info->getChainId().empty()) {
947
0
    streamWrite(ss, MolPickler::ATOM_MONOMER_INFO_CHAINID, info->getChainId());
948
0
  }
949
0
  if (!info->getMonomerClass().empty()) {
950
0
    streamWrite(ss, MolPickler::ATOM_MONOMER_INFO_MONOMERCLASS,
951
0
                info->getMonomerClass());
952
0
  }
953
0
}
954
955
0
AtomMonomerInfo *unpickleAtomMonomerInfo(std::istream &ss, int version) {
956
0
  std::string nm;
957
0
  std::uint8_t typ;
958
0
  streamRead(ss, nm, version);
959
0
  streamRead(ss, typ, version);
960
0
  auto info = new AtomMonomerInfo(
961
0
      static_cast<RDKit::AtomMonomerInfo::AtomMonomerType>(typ), nm);
962
963
0
  std::string residueName = "";
964
0
  int residueNumber = 0;
965
0
  std::string chainId = "";
966
0
  std::string monomerClass = "";
967
0
  MolPickler::Tags tag = MolPickler::BEGIN_ATOM_MONOMER_INFO;
968
0
  while (tag != MolPickler::END_ATOM_MONOMER_INFO) {
969
0
    streamRead(ss, tag, version);
970
0
    switch (tag) {
971
0
      case MolPickler::ATOM_MONOMER_INFO_RESIDUENAME:
972
0
        streamRead(ss, residueName, version);
973
0
        info->setResidueName(residueName);
974
0
        break;
975
0
      case MolPickler::ATOM_MONOMER_INFO_RESIDUENUMBER:
976
0
        streamRead(ss, residueNumber, version);
977
0
        info->setResidueNumber(residueNumber);
978
0
        break;
979
0
      case MolPickler::ATOM_MONOMER_INFO_CHAINID:
980
0
        streamRead(ss, chainId, version);
981
0
        info->setChainId(chainId);
982
0
        break;
983
0
      case MolPickler::ATOM_MONOMER_INFO_MONOMERCLASS:
984
0
        streamRead(ss, monomerClass, version);
985
0
        info->setMonomerClass(monomerClass);
986
0
        break;
987
0
      case MolPickler::END_ATOM_MONOMER_INFO:
988
0
        break;
989
0
      default:
990
        // None of the ATOM_PDB_RESIDUE_XXX tags should appear here
991
0
        throw MolPicklerException(
992
0
            "unrecognized tag while parsing atom monomer info " +
993
0
            std::to_string(static_cast<int>(tag)));
994
0
    }
995
0
  }
996
0
  return info;
997
0
}
998
999
}  // namespace
1000
1001
// Resets the `exceptionState` of the passed stream `ss` in the destructor to
1002
// the `exceptionState` the stream ss was in, before setting
1003
// `newExceptionState`.
1004
struct IOStreamExceptionStateResetter {
1005
  std::ios &originalStream;
1006
  std::ios_base::iostate originalExceptionState;
1007
  IOStreamExceptionStateResetter(std::ios &ss,
1008
                                 std::ios_base::iostate newExceptionState)
1009
14.4k
      : originalStream(ss), originalExceptionState(ss.exceptions()) {
1010
14.4k
    ss.exceptions(newExceptionState);
1011
14.4k
  }
1012
1013
14.4k
  ~IOStreamExceptionStateResetter() {
1014
14.4k
    if (originalStream) {
1015
10.3k
      originalStream.exceptions(originalExceptionState);
1016
10.3k
    }
1017
14.4k
  }
1018
};
1019
1020
0
void MolPickler::pickleMol(const ROMol *mol, std::ostream &ss) {
1021
0
  pickleMol(mol, ss, MolPickler::getDefaultPickleProperties());
1022
0
}
1023
1024
void MolPickler::pickleMol(const ROMol *mol, std::ostream &ss,
1025
0
                           unsigned int propertyFlags) {
1026
0
  PRECONDITION(mol, "empty molecule");
1027
1028
  // Ensure that the exception state of the `ostream` is reset to the previous
1029
  // state after we're done.
1030
  // Also enable exceptions here, so we're notified when we've reached EOF or
1031
  // any other problem.
1032
0
  IOStreamExceptionStateResetter resetter(ss, std::ios_base::eofbit |
1033
0
                                                  std::ios_base::failbit |
1034
0
                                                  std::ios_base::badbit);
1035
1036
0
  try {
1037
0
    streamWrite(ss, endianId);
1038
0
    streamWrite(ss, static_cast<int>(VERSION));
1039
0
    streamWrite(ss, versionMajor);
1040
0
    streamWrite(ss, versionMinor);
1041
0
    streamWrite(ss, versionPatch);
1042
0
#ifndef OLD_PICKLE
1043
0
    if (mol->getNumAtoms() > 255 || mol->getNumBonds() > 255) {
1044
0
      _pickle<int32_t>(mol, ss, propertyFlags);
1045
0
    } else {
1046
0
      _pickle<unsigned char>(mol, ss, propertyFlags);
1047
0
    }
1048
#else
1049
    _pickleV1(mol, ss);
1050
#endif
1051
0
  } catch (const std::ios_base::failure &) {
1052
0
    if (ss.eof()) {
1053
0
      throw MolPicklerException(
1054
0
          "Bad pickle format: unexpected End-of-File while writing");
1055
0
    } else if (ss.bad()) {
1056
0
      throw MolPicklerException("Bad pickle format: write error while writing");
1057
0
    } else if (ss.fail()) {
1058
0
      throw MolPicklerException(
1059
0
          "Bad pickle format: logical error while writing");
1060
0
    } else {
1061
0
      throw MolPicklerException(
1062
0
          "Bad pickle format: unexpected error while writing");
1063
0
    }
1064
0
  }
1065
0
}
1066
1067
0
void MolPickler::pickleMol(const ROMol &mol, std::ostream &ss) {
1068
0
  pickleMol(&mol, ss, MolPickler::getDefaultPickleProperties());
1069
0
}
1070
1071
0
void MolPickler::pickleMol(const ROMol *mol, std::string &res) {
1072
0
  pickleMol(mol, res, MolPickler::getDefaultPickleProperties());
1073
0
}
1074
1075
void MolPickler::pickleMol(const ROMol *mol, std::string &res,
1076
0
                           unsigned int pickleFlags) {
1077
0
  PRECONDITION(mol, "empty molecule");
1078
0
  std::stringstream ss(std::ios_base::binary | std::ios_base::out |
1079
0
                       std::ios_base::in);
1080
0
  MolPickler::pickleMol(mol, ss, pickleFlags);
1081
0
  res = ss.str();
1082
0
}
1083
1084
0
void MolPickler::pickleMol(const ROMol &mol, std::string &ss) {
1085
0
  pickleMol(&mol, ss, MolPickler::getDefaultPickleProperties());
1086
0
}
1087
1088
// NOTE: if the mol passed in here already has atoms and bonds, they will
1089
// be left intact.  The side effect is that ALL atom and bond bookmarks
1090
// will be blown out by the end of this process.
1091
void MolPickler::molFromPickle(std::istream &ss, ROMol *mol,
1092
14.4k
                               unsigned int propertyFlags) {
1093
14.4k
  PRECONDITION(mol, "empty molecule");
1094
1095
  // Ensure that the exception state of the `istream` is reset to the previous
1096
  // state after we're done.
1097
  // Also enable exceptions here, so we're notified when we've reached EOF or
1098
  // any other problem.
1099
14.4k
  IOStreamExceptionStateResetter resetter(ss, std::ios_base::eofbit |
1100
14.4k
                                                  std::ios_base::failbit |
1101
14.4k
                                                  std::ios_base::badbit);
1102
1103
14.4k
  try {
1104
14.4k
    int32_t tmpInt;
1105
1106
14.4k
    mol->clearAllAtomBookmarks();
1107
14.4k
    mol->clearAllBondBookmarks();
1108
1109
14.4k
    streamRead(ss, tmpInt);
1110
14.4k
    if (tmpInt != endianId) {
1111
6
      throw MolPicklerException(
1112
6
          "Bad pickle format: bad endian ID or invalid file format");
1113
6
    }
1114
1115
14.4k
    streamRead(ss, tmpInt);
1116
14.4k
    if (static_cast<Tags>(tmpInt) != VERSION) {
1117
2
      throw MolPicklerException("Bad pickle format: no version tag");
1118
2
    }
1119
14.4k
    int32_t majorVersion, minorVersion, patchVersion;
1120
14.4k
    streamRead(ss, majorVersion);
1121
14.4k
    streamRead(ss, minorVersion);
1122
14.4k
    streamRead(ss, patchVersion);
1123
14.4k
    if (majorVersion > versionMajor ||
1124
13.4k
        (majorVersion == versionMajor && minorVersion > versionMinor)) {
1125
1.04k
      BOOST_LOG(rdWarningLog)
1126
0
          << "Depickling from a version number (" << majorVersion << "."
1127
0
          << minorVersion << ")"
1128
0
          << "that is higher than our version (" << versionMajor << "."
1129
0
          << versionMinor << ").\nThis probably won't work." << std::endl;
1130
1.04k
    }
1131
    // version sanity checking
1132
14.4k
    if (majorVersion > 1000 || minorVersion > 100 || patchVersion > 100) {
1133
5
      throw MolPicklerException("unreasonable version numbers");
1134
5
    }
1135
14.4k
    majorVersion = 1000 * majorVersion + minorVersion * 10 + patchVersion;
1136
14.4k
    if (majorVersion == 1) {
1137
102
      _depickleV1(ss, mol);
1138
14.3k
    } else {
1139
14.3k
      int32_t numAtoms;
1140
14.3k
      int32_t numBonds;
1141
14.3k
      streamRead(ss, numAtoms, majorVersion);
1142
14.3k
      streamRead(ss, numBonds, majorVersion);
1143
14.3k
      if (numAtoms > 255 || (majorVersion >= 16040 && numBonds > 255)) {
1144
14.2k
        _depickle<int32_t>(ss, mol, majorVersion, numAtoms, numBonds,
1145
14.2k
                           propertyFlags);
1146
14.2k
      } else {
1147
55
        _depickle<unsigned char>(ss, mol, majorVersion, numAtoms, numBonds,
1148
55
                                 propertyFlags);
1149
55
      }
1150
14.3k
    }
1151
14.4k
    mol->clearAllAtomBookmarks();
1152
14.4k
    mol->clearAllBondBookmarks();
1153
14.4k
    if (majorVersion < 4000) {
1154
      // FIX for issue 220 - probably better to change the pickle format later
1155
128
      MolOps::assignStereochemistry(*mol, true);
1156
128
    }
1157
14.4k
  } catch (const std::ios_base::failure &) {
1158
138
    if (ss.eof()) {
1159
138
      throw MolPicklerException(
1160
138
          "Bad pickle format: unexpected End-of-File while reading");
1161
138
    } else if (ss.bad()) {
1162
0
      throw MolPicklerException("Bad pickle format: read error while reading");
1163
0
    } else if (ss.fail()) {
1164
0
      throw MolPicklerException(
1165
0
          "Bad pickle format: logical error while reading");
1166
0
    } else {
1167
0
      throw MolPicklerException(
1168
0
          "Bad pickle format: unexpected error while reading");
1169
0
    }
1170
138
  }
1171
14.4k
}
1172
void MolPickler::molFromPickle(const std::string &pickle, ROMol *mol,
1173
423
                               unsigned int propertyFlags) {
1174
423
  PRECONDITION(mol, "empty molecule");
1175
423
  std::stringstream ss(std::ios_base::binary | std::ios_base::out |
1176
423
                       std::ios_base::in);
1177
423
  ss.write(pickle.c_str(), pickle.length());
1178
423
  MolPickler::molFromPickle(ss, mol, propertyFlags);
1179
423
}
1180
1181
//--------------------------------------
1182
//
1183
//            Molecules
1184
//
1185
//--------------------------------------
1186
template <typename T>
1187
void MolPickler::_pickle(const ROMol *mol, std::ostream &ss,
1188
0
                         unsigned int propertyFlags) {
1189
0
  PRECONDITION(mol, "empty molecule");
1190
0
  int32_t tmpInt;
1191
0
  std::map<int, int> atomIdxMap;
1192
0
  std::map<int, int> bondIdxMap;
1193
1194
0
  tmpInt = static_cast<int32_t>(mol->getNumAtoms());
1195
0
  streamWrite(ss, tmpInt);
1196
0
  tmpInt = static_cast<int32_t>(mol->getNumBonds());
1197
0
  streamWrite(ss, tmpInt);
1198
1199
0
  unsigned char flag = 0x1 << 7;
1200
0
  streamWrite(ss, flag);
1201
1202
  // -------------------
1203
  //
1204
  // Write Atoms
1205
  //
1206
  // -------------------
1207
0
  streamWrite(ss, BEGINATOM);
1208
0
  ROMol::ConstAtomIterator atIt;
1209
0
  int nWritten = 0;
1210
0
  for (auto atom : mol->atoms()) {
1211
0
    _pickleAtom<T>(ss, atom);
1212
0
    atomIdxMap[atom->getIdx()] = nWritten;
1213
0
    nWritten++;
1214
0
  }
1215
1216
  // -------------------
1217
  //
1218
  // Write Bonds
1219
  //
1220
  // -------------------
1221
0
  streamWrite(ss, BEGINBOND);
1222
0
  for (auto bond : mol->bonds()) {
1223
0
    _pickleBond<T>(ss, bond, atomIdxMap);
1224
0
    bondIdxMap[bond->getIdx()] = bond->getIdx();
1225
0
  }
1226
1227
  // -------------------
1228
  //
1229
  // Write Rings (if present)
1230
  //
1231
  // -------------------
1232
0
  const RingInfo *ringInfo = mol->getRingInfo();
1233
0
  if (ringInfo && ringInfo->isInitialized()) {
1234
0
    switch (ringInfo->getRingType()) {
1235
0
      case RDKit::FIND_RING_TYPE::FIND_RING_TYPE_FAST:
1236
0
        streamWrite(ss, BEGINFASTFIND);
1237
0
        break;
1238
0
      case RDKit::FIND_RING_TYPE::FIND_RING_TYPE_SSSR:
1239
0
        streamWrite(ss, BEGINSSSR);
1240
0
        break;
1241
0
      case RDKit::FIND_RING_TYPE::FIND_RING_TYPE_SYMM_SSSR:
1242
0
        streamWrite(ss, BEGINSYMMSSSR);
1243
0
        break;
1244
0
      default:
1245
0
        streamWrite(ss, BEGINFINDOTHERORUNKNOWN);
1246
0
        break;
1247
0
    }
1248
0
    _pickleSSSR<T>(ss, ringInfo, atomIdxMap);
1249
0
  }
1250
1251
  // -------------------
1252
  //
1253
  // Write SubstanceGroups (if present)
1254
  //
1255
  // -------------------
1256
0
  const auto &sgroups = getSubstanceGroups(*mol);
1257
0
  if (!sgroups.empty()) {
1258
0
    streamWrite(ss, BEGINSGROUP);
1259
1260
0
    tmpInt = static_cast<int32_t>(sgroups.size());
1261
0
    streamWrite(ss, tmpInt);
1262
1263
0
    for (const auto &sgroup : sgroups) {
1264
0
      _pickleSubstanceGroup<T>(ss, sgroup, atomIdxMap, bondIdxMap);
1265
0
    }
1266
0
  }
1267
  // Write Stereo Groups
1268
0
  {
1269
0
    auto &stereo_groups = mol->getStereoGroups();
1270
0
    if (stereo_groups.size() > 0u) {
1271
0
      streamWrite(ss, BEGINSTEREOGROUP);
1272
0
      _pickleStereo<T>(ss, stereo_groups, atomIdxMap, bondIdxMap);
1273
0
    }
1274
0
  }
1275
1276
0
  if (!(propertyFlags & PicklerOps::NoConformers)) {
1277
0
    std::stringstream tss;
1278
0
    if (propertyFlags & PicklerOps::CoordsAsDouble) {
1279
      // pickle the conformations
1280
0
      streamWrite(ss, BEGINCONFS_DOUBLE);
1281
0
      tmpInt = static_cast<int32_t>(mol->getNumConformers());
1282
0
      streamWrite(tss, tmpInt);
1283
0
      for (auto ci = mol->beginConformers(); ci != mol->endConformers(); ++ci) {
1284
0
        const Conformer *conf = ci->get();
1285
0
        _pickleConformer<T, double>(tss, conf);
1286
0
      }
1287
0
    } else {
1288
      // pickle the conformations
1289
0
      streamWrite(ss, BEGINCONFS);
1290
0
      tmpInt = static_cast<int32_t>(mol->getNumConformers());
1291
0
      streamWrite(tss, tmpInt);
1292
0
      for (auto ci = mol->beginConformers(); ci != mol->endConformers(); ++ci) {
1293
0
        const Conformer *conf = ci->get();
1294
0
        _pickleConformer<T, float>(tss, conf);
1295
0
      }
1296
0
    }
1297
1298
0
    if (propertyFlags & PicklerOps::MolProps) {
1299
0
      streamWrite(tss, BEGINCONFPROPS);
1300
0
      std::stringstream tss2;
1301
0
      for (auto ci = mol->beginConformers(); ci != mol->endConformers(); ++ci) {
1302
0
        const Conformer *conf = ci->get();
1303
0
        _pickleProperties(tss2, *conf, propertyFlags);
1304
0
      }
1305
0
      write_sstream_to_stream(tss, tss2);
1306
0
    }
1307
0
    write_sstream_to_stream(ss, tss);
1308
0
  }
1309
1310
0
  if (propertyFlags & PicklerOps::MolProps) {
1311
0
    std::stringstream tss;
1312
0
    _pickleProperties(tss, *mol, propertyFlags);
1313
0
    if (!tss.str().empty()) {
1314
0
      streamWrite(ss, BEGINPROPS);
1315
0
      write_sstream_to_stream(ss, tss);
1316
0
      streamWrite(ss, ENDPROPS);
1317
0
    }
1318
0
  }
1319
1320
0
  if (propertyFlags & PicklerOps::AtomProps) {
1321
0
    std::stringstream tss;
1322
0
    bool anyWritten = false;
1323
0
    for (const auto atom : mol->atoms()) {
1324
0
      anyWritten |= pickleAtomProperties(tss, *atom, propertyFlags);
1325
0
    }
1326
0
    if (anyWritten) {
1327
0
      streamWrite(ss, BEGINATOMPROPS);
1328
0
      write_sstream_to_stream(ss, tss);
1329
0
      streamWrite(ss, ENDPROPS);
1330
0
    }
1331
0
  }
1332
1333
0
  if (propertyFlags & PicklerOps::BondProps) {
1334
0
    std::stringstream tss;
1335
0
    bool anyWritten = false;
1336
0
    for (const auto bond : mol->bonds()) {
1337
0
      anyWritten |= pickleBondProperties(tss, *bond, propertyFlags);
1338
0
    }
1339
0
    if (anyWritten) {
1340
0
      streamWrite(ss, BEGINBONDPROPS);
1341
0
      write_sstream_to_stream(ss, tss);
1342
0
      streamWrite(ss, ENDPROPS);
1343
0
    }
1344
0
  }
1345
0
  streamWrite(ss, ENDMOL);
1346
0
}
Unexecuted instantiation: void RDKit::MolPickler::_pickle<int>(RDKit::ROMol const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&, unsigned int)
Unexecuted instantiation: void RDKit::MolPickler::_pickle<unsigned char>(RDKit::ROMol const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&, unsigned int)
1347
1348
template <typename T>
1349
void MolPickler::_depickle(std::istream &ss, ROMol *mol, int version,
1350
                           int numAtoms, int numBonds,
1351
14.3k
                           unsigned int propertyFlags) {
1352
14.3k
  PRECONDITION(mol, "empty molecule");
1353
14.3k
  bool directMap = mol->getNumAtoms() == 0;
1354
14.3k
  Tags tag;
1355
14.3k
  int32_t tmpInt;
1356
14.3k
  bool haveQuery = false;
1357
1358
  // did we include coordinates
1359
14.3k
  bool includeCoords = false;
1360
14.3k
  if (version >= 3000) {
1361
14.1k
    unsigned char flag;
1362
14.1k
    streamRead(ss, flag, version);
1363
14.1k
    if (flag & 0x1 << 7) {
1364
38
      includeCoords = true;
1365
38
    }
1366
14.1k
  }
1367
  // -------------------
1368
  //
1369
  // Read Atoms
1370
  //
1371
  // -------------------
1372
14.3k
  streamRead(ss, tag, version);
1373
14.3k
  if (tag != BEGINATOM) {
1374
5
    throw MolPicklerException("Bad pickle format: BEGINATOM tag not found.");
1375
5
  }
1376
14.3k
  Conformer *conf = nullptr;
1377
14.3k
  if ((version >= 2000 && version < 3000) && includeCoords) {
1378
    // there can only one conformation - since the positions were stored on
1379
    // the atoms themselves in this version
1380
0
    conf = new Conformer(numAtoms);
1381
0
    mol->addConformer(conf, true);
1382
0
  }
1383
445k
  for (int i = 0; i < numAtoms; i++) {
1384
431k
    RDGeom::Point3D pos;
1385
431k
    Atom *atom = _addAtomFromPickle<T>(ss, mol, pos, version, directMap);
1386
431k
    if ((version >= 2000 && version < 3000) && includeCoords) {
1387
      // this is a older pickle so we go the pos
1388
0
      conf->setAtomPos(i, pos);
1389
0
    }
1390
431k
    if (!directMap) {
1391
0
      mol->setAtomBookmark(atom, i);
1392
0
    }
1393
431k
    if (atom->hasQuery()) {
1394
383
      haveQuery = true;
1395
383
    }
1396
431k
  }
1397
1398
  // -------------------
1399
  //
1400
  // Read Bonds
1401
  //
1402
  // -------------------
1403
14.3k
  streamRead(ss, tag, version);
1404
14.3k
  if (tag != BEGINBOND) {
1405
0
    throw MolPicklerException("Bad pickle format: BEGINBOND tag not found.");
1406
0
  }
1407
14.3k
  for (int i = 0; i < numBonds; i++) {
1408
22
    Bond *bond = _addBondFromPickle<T>(ss, mol, version, directMap);
1409
22
    if (!directMap) {
1410
0
      mol->setBondBookmark(bond, i);
1411
0
    }
1412
22
  }
1413
1414
  // -------------------
1415
  //
1416
  // Read Rings (if needed)
1417
  //
1418
  // -------------------
1419
14.3k
  streamRead(ss, tag, version);
1420
14.3k
  bool ringFound = false;
1421
14.3k
  bool ringFamiliesFound = false;
1422
14.3k
  FIND_RING_TYPE ringType =
1423
14.3k
      RDKit::FIND_RING_TYPE::FIND_RING_TYPE_OTHER_OR_UNKNOWN;
1424
14.3k
  if (tag == BEGINSSSR) {
1425
25
    ringFound = true;
1426
25
    ringFamiliesFound = true;
1427
25
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_SSSR;
1428
14.3k
  } else if (tag == BEGINSYMMSSSR) {
1429
0
    ringFound = true;
1430
0
    ringFamiliesFound = true;
1431
0
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_SYMM_SSSR;
1432
14.3k
  } else if (tag == BEGINFASTFIND) {
1433
0
    ringFound = true;
1434
0
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_FAST;
1435
14.3k
  } else if (tag == BEGINFINDOTHERORUNKNOWN) {
1436
1
    ringFound = true;
1437
1
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_OTHER_OR_UNKNOWN;
1438
1
  }
1439
14.3k
  if (ringFound) {
1440
26
    _addRingInfoFromPickle<T>(ss, mol, version, directMap, ringType);
1441
26
    streamRead(ss, tag, version);
1442
26
  }
1443
14.3k
  if (ringFamiliesFound) {
1444
    // findSSSR now initializes ring families, so make sure
1445
    // unpickled mols have done this to prevent issues with
1446
    // code that expects ring families to be initialized.
1447
1
    MolOps::findRingFamilies(*mol);
1448
1
  }
1449
1450
  // -------------------
1451
  //
1452
  // Read SubstanceGroups (if needed)
1453
  //
1454
  // -------------------
1455
1456
14.3k
  if (tag == BEGINSGROUP) {
1457
84
    streamRead(ss, tmpInt, version);
1458
1459
    // Create SubstanceGroups
1460
47.7k
    for (int i = 0; i < tmpInt; ++i) {
1461
47.6k
      auto sgroup = _getSubstanceGroupFromPickle<T>(ss, mol, version);
1462
47.6k
      addSubstanceGroup(*mol, sgroup);
1463
47.6k
    }
1464
1465
84
    streamRead(ss, tag, version);
1466
84
  }
1467
1468
14.3k
  if (tag == BEGINSTEREOGROUP) {
1469
24
    _depickleStereo<T>(ss, mol, version);
1470
24
    streamRead(ss, tag, version);
1471
24
  }
1472
1473
14.3k
  if (tag == BEGINCONFS || tag == BEGINCONFS_DOUBLE) {
1474
46
    int32_t blkSize = 0;
1475
46
    if (version >= 13000) {
1476
0
      streamRead(ss, blkSize, version);
1477
0
    }
1478
46
    if (version >= 13000 && (propertyFlags & PicklerOps::NoConformers)) {
1479
      // not reading coordinates, so just skip over those bytes
1480
0
      ss.seekg(blkSize, std::ios_base::cur);
1481
0
      streamRead(ss, tag, version);
1482
46
    } else {
1483
      // read in the conformation
1484
46
      streamRead(ss, tmpInt, version);
1485
46
      std::vector<unsigned int> cids(tmpInt);
1486
169
      for (auto i = 0; i < tmpInt; i++) {
1487
123
        Conformer *conf;
1488
123
        if (tag == BEGINCONFS) {
1489
63
          conf = _conformerFromPickle<T, float>(ss, version);
1490
63
        } else {
1491
60
          conf = _conformerFromPickle<T, double>(ss, version);
1492
60
        }
1493
123
        mol->addConformer(conf);
1494
123
        cids[i] = conf->getId();
1495
123
      }
1496
46
      streamRead(ss, tag, version);
1497
46
      if (tag == BEGINCONFPROPS) {
1498
2
        int32_t blkSize = 0;
1499
2
        if (version >= 13000) {
1500
0
          streamRead(ss, blkSize, version);
1501
0
        }
1502
2
        if (version >= 13000 && !(propertyFlags & PicklerOps::MolProps)) {
1503
0
          ss.seekg(blkSize, std::ios_base::cur);
1504
2
        } else {
1505
2
          for (auto cid : cids) {
1506
2
            _unpickleProperties(ss, mol->getConformer(cid), version);
1507
2
          }
1508
2
        }
1509
2
        streamRead(ss, tag, version);
1510
2
      }
1511
46
    }
1512
46
  }
1513
1514
14.3k
  while (tag != ENDMOL) {
1515
8
    if (tag == BEGINPROPS) {
1516
0
      int32_t blkSize = 0;
1517
0
      if (version >= 13000) {
1518
0
        streamRead(ss, blkSize, version);
1519
0
      }
1520
0
      if (version >= 13000 && !(propertyFlags & PicklerOps::MolProps)) {
1521
0
        ss.seekg(blkSize, std::ios_base::cur);
1522
0
      } else {
1523
0
        _unpickleProperties(ss, *mol, version);
1524
0
      }
1525
0
      streamRead(ss, tag, version);
1526
8
    } else if (tag == BEGINATOMPROPS) {
1527
2
      int32_t blkSize = 0;
1528
2
      if (version >= 13000) {
1529
0
        streamRead(ss, blkSize, version);
1530
0
      }
1531
2
      if (version >= 13000 && !(propertyFlags & PicklerOps::AtomProps)) {
1532
0
        ss.seekg(blkSize, std::ios_base::cur);
1533
2
      } else {
1534
429
        for (const auto atom : mol->atoms()) {
1535
429
          unpickleAtomProperties(ss, *atom, version);
1536
429
        }
1537
2
      }
1538
2
      streamRead(ss, tag, version);
1539
6
    } else if (tag == BEGINBONDPROPS) {
1540
0
      int32_t blkSize = 0;
1541
0
      if (version >= 13000) {
1542
0
        streamRead(ss, blkSize, version);
1543
0
      }
1544
0
      if (version >= 13000 && !(propertyFlags & PicklerOps::BondProps)) {
1545
0
        ss.seekg(blkSize, std::ios_base::cur);
1546
0
      } else {
1547
0
        for (const auto bond : mol->bonds()) {
1548
0
          unpickleBondProperties(ss, *bond, version);
1549
0
        }
1550
0
      }
1551
0
      streamRead(ss, tag, version);
1552
6
    } else if (tag == BEGINQUERYATOMDATA) {
1553
0
      for (const auto atom : mol->atoms()) {
1554
0
        _unpickleAtomData(ss, atom, version);
1555
0
      }
1556
0
      streamRead(ss, tag, version);
1557
6
    } else {
1558
6
      break;  // break to tag != ENDMOL
1559
6
    }
1560
2
    if (tag != ENDPROPS) {
1561
1
      throw MolPicklerException("Bad pickle format: ENDPROPS tag not found.");
1562
1
    }
1563
1
    streamRead(ss, tag, version);
1564
1
  }
1565
14.3k
  if (tag != ENDMOL) {
1566
6
    throw MolPicklerException("Bad pickle format: ENDMOL tag not found.");
1567
6
  }
1568
1569
14.3k
  if (haveQuery) {
1570
    // we didn't read any property info for atoms with associated
1571
    // queries. update their property caches
1572
    // (was sf.net Issue 3316407)
1573
0
    for (const auto atom : mol->atoms()) {
1574
0
      if (atom->hasQuery()) {
1575
0
        atom->updatePropertyCache(false);
1576
0
      }
1577
0
    }
1578
0
  }
1579
14.3k
}
void RDKit::MolPickler::_depickle<int>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, int, int, int, unsigned int)
Line
Count
Source
1351
14.2k
                           unsigned int propertyFlags) {
1352
14.2k
  PRECONDITION(mol, "empty molecule");
1353
14.2k
  bool directMap = mol->getNumAtoms() == 0;
1354
14.2k
  Tags tag;
1355
14.2k
  int32_t tmpInt;
1356
14.2k
  bool haveQuery = false;
1357
1358
  // did we include coordinates
1359
14.2k
  bool includeCoords = false;
1360
14.2k
  if (version >= 3000) {
1361
14.1k
    unsigned char flag;
1362
14.1k
    streamRead(ss, flag, version);
1363
14.1k
    if (flag & 0x1 << 7) {
1364
33
      includeCoords = true;
1365
33
    }
1366
14.1k
  }
1367
  // -------------------
1368
  //
1369
  // Read Atoms
1370
  //
1371
  // -------------------
1372
14.2k
  streamRead(ss, tag, version);
1373
14.2k
  if (tag != BEGINATOM) {
1374
4
    throw MolPicklerException("Bad pickle format: BEGINATOM tag not found.");
1375
4
  }
1376
14.2k
  Conformer *conf = nullptr;
1377
14.2k
  if ((version >= 2000 && version < 3000) && includeCoords) {
1378
    // there can only one conformation - since the positions were stored on
1379
    // the atoms themselves in this version
1380
0
    conf = new Conformer(numAtoms);
1381
0
    mol->addConformer(conf, true);
1382
0
  }
1383
445k
  for (int i = 0; i < numAtoms; i++) {
1384
431k
    RDGeom::Point3D pos;
1385
431k
    Atom *atom = _addAtomFromPickle<T>(ss, mol, pos, version, directMap);
1386
431k
    if ((version >= 2000 && version < 3000) && includeCoords) {
1387
      // this is a older pickle so we go the pos
1388
0
      conf->setAtomPos(i, pos);
1389
0
    }
1390
431k
    if (!directMap) {
1391
0
      mol->setAtomBookmark(atom, i);
1392
0
    }
1393
431k
    if (atom->hasQuery()) {
1394
381
      haveQuery = true;
1395
381
    }
1396
431k
  }
1397
1398
  // -------------------
1399
  //
1400
  // Read Bonds
1401
  //
1402
  // -------------------
1403
14.2k
  streamRead(ss, tag, version);
1404
14.2k
  if (tag != BEGINBOND) {
1405
0
    throw MolPicklerException("Bad pickle format: BEGINBOND tag not found.");
1406
0
  }
1407
14.3k
  for (int i = 0; i < numBonds; i++) {
1408
17
    Bond *bond = _addBondFromPickle<T>(ss, mol, version, directMap);
1409
17
    if (!directMap) {
1410
0
      mol->setBondBookmark(bond, i);
1411
0
    }
1412
17
  }
1413
1414
  // -------------------
1415
  //
1416
  // Read Rings (if needed)
1417
  //
1418
  // -------------------
1419
14.2k
  streamRead(ss, tag, version);
1420
14.2k
  bool ringFound = false;
1421
14.2k
  bool ringFamiliesFound = false;
1422
14.2k
  FIND_RING_TYPE ringType =
1423
14.2k
      RDKit::FIND_RING_TYPE::FIND_RING_TYPE_OTHER_OR_UNKNOWN;
1424
14.2k
  if (tag == BEGINSSSR) {
1425
25
    ringFound = true;
1426
25
    ringFamiliesFound = true;
1427
25
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_SSSR;
1428
14.2k
  } else if (tag == BEGINSYMMSSSR) {
1429
0
    ringFound = true;
1430
0
    ringFamiliesFound = true;
1431
0
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_SYMM_SSSR;
1432
14.2k
  } else if (tag == BEGINFASTFIND) {
1433
0
    ringFound = true;
1434
0
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_FAST;
1435
14.2k
  } else if (tag == BEGINFINDOTHERORUNKNOWN) {
1436
1
    ringFound = true;
1437
1
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_OTHER_OR_UNKNOWN;
1438
1
  }
1439
14.2k
  if (ringFound) {
1440
26
    _addRingInfoFromPickle<T>(ss, mol, version, directMap, ringType);
1441
26
    streamRead(ss, tag, version);
1442
26
  }
1443
14.2k
  if (ringFamiliesFound) {
1444
    // findSSSR now initializes ring families, so make sure
1445
    // unpickled mols have done this to prevent issues with
1446
    // code that expects ring families to be initialized.
1447
1
    MolOps::findRingFamilies(*mol);
1448
1
  }
1449
1450
  // -------------------
1451
  //
1452
  // Read SubstanceGroups (if needed)
1453
  //
1454
  // -------------------
1455
1456
14.2k
  if (tag == BEGINSGROUP) {
1457
51
    streamRead(ss, tmpInt, version);
1458
1459
    // Create SubstanceGroups
1460
6.54k
    for (int i = 0; i < tmpInt; ++i) {
1461
6.49k
      auto sgroup = _getSubstanceGroupFromPickle<T>(ss, mol, version);
1462
6.49k
      addSubstanceGroup(*mol, sgroup);
1463
6.49k
    }
1464
1465
51
    streamRead(ss, tag, version);
1466
51
  }
1467
1468
14.2k
  if (tag == BEGINSTEREOGROUP) {
1469
24
    _depickleStereo<T>(ss, mol, version);
1470
24
    streamRead(ss, tag, version);
1471
24
  }
1472
1473
14.2k
  if (tag == BEGINCONFS || tag == BEGINCONFS_DOUBLE) {
1474
44
    int32_t blkSize = 0;
1475
44
    if (version >= 13000) {
1476
0
      streamRead(ss, blkSize, version);
1477
0
    }
1478
44
    if (version >= 13000 && (propertyFlags & PicklerOps::NoConformers)) {
1479
      // not reading coordinates, so just skip over those bytes
1480
0
      ss.seekg(blkSize, std::ios_base::cur);
1481
0
      streamRead(ss, tag, version);
1482
44
    } else {
1483
      // read in the conformation
1484
44
      streamRead(ss, tmpInt, version);
1485
44
      std::vector<unsigned int> cids(tmpInt);
1486
165
      for (auto i = 0; i < tmpInt; i++) {
1487
121
        Conformer *conf;
1488
121
        if (tag == BEGINCONFS) {
1489
61
          conf = _conformerFromPickle<T, float>(ss, version);
1490
61
        } else {
1491
60
          conf = _conformerFromPickle<T, double>(ss, version);
1492
60
        }
1493
121
        mol->addConformer(conf);
1494
121
        cids[i] = conf->getId();
1495
121
      }
1496
44
      streamRead(ss, tag, version);
1497
44
      if (tag == BEGINCONFPROPS) {
1498
2
        int32_t blkSize = 0;
1499
2
        if (version >= 13000) {
1500
0
          streamRead(ss, blkSize, version);
1501
0
        }
1502
2
        if (version >= 13000 && !(propertyFlags & PicklerOps::MolProps)) {
1503
0
          ss.seekg(blkSize, std::ios_base::cur);
1504
2
        } else {
1505
2
          for (auto cid : cids) {
1506
2
            _unpickleProperties(ss, mol->getConformer(cid), version);
1507
2
          }
1508
2
        }
1509
2
        streamRead(ss, tag, version);
1510
2
      }
1511
44
    }
1512
44
  }
1513
1514
14.2k
  while (tag != ENDMOL) {
1515
8
    if (tag == BEGINPROPS) {
1516
0
      int32_t blkSize = 0;
1517
0
      if (version >= 13000) {
1518
0
        streamRead(ss, blkSize, version);
1519
0
      }
1520
0
      if (version >= 13000 && !(propertyFlags & PicklerOps::MolProps)) {
1521
0
        ss.seekg(blkSize, std::ios_base::cur);
1522
0
      } else {
1523
0
        _unpickleProperties(ss, *mol, version);
1524
0
      }
1525
0
      streamRead(ss, tag, version);
1526
8
    } else if (tag == BEGINATOMPROPS) {
1527
2
      int32_t blkSize = 0;
1528
2
      if (version >= 13000) {
1529
0
        streamRead(ss, blkSize, version);
1530
0
      }
1531
2
      if (version >= 13000 && !(propertyFlags & PicklerOps::AtomProps)) {
1532
0
        ss.seekg(blkSize, std::ios_base::cur);
1533
2
      } else {
1534
429
        for (const auto atom : mol->atoms()) {
1535
429
          unpickleAtomProperties(ss, *atom, version);
1536
429
        }
1537
2
      }
1538
2
      streamRead(ss, tag, version);
1539
6
    } else if (tag == BEGINBONDPROPS) {
1540
0
      int32_t blkSize = 0;
1541
0
      if (version >= 13000) {
1542
0
        streamRead(ss, blkSize, version);
1543
0
      }
1544
0
      if (version >= 13000 && !(propertyFlags & PicklerOps::BondProps)) {
1545
0
        ss.seekg(blkSize, std::ios_base::cur);
1546
0
      } else {
1547
0
        for (const auto bond : mol->bonds()) {
1548
0
          unpickleBondProperties(ss, *bond, version);
1549
0
        }
1550
0
      }
1551
0
      streamRead(ss, tag, version);
1552
6
    } else if (tag == BEGINQUERYATOMDATA) {
1553
0
      for (const auto atom : mol->atoms()) {
1554
0
        _unpickleAtomData(ss, atom, version);
1555
0
      }
1556
0
      streamRead(ss, tag, version);
1557
6
    } else {
1558
6
      break;  // break to tag != ENDMOL
1559
6
    }
1560
2
    if (tag != ENDPROPS) {
1561
1
      throw MolPicklerException("Bad pickle format: ENDPROPS tag not found.");
1562
1
    }
1563
1
    streamRead(ss, tag, version);
1564
1
  }
1565
14.2k
  if (tag != ENDMOL) {
1566
6
    throw MolPicklerException("Bad pickle format: ENDMOL tag not found.");
1567
6
  }
1568
1569
14.2k
  if (haveQuery) {
1570
    // we didn't read any property info for atoms with associated
1571
    // queries. update their property caches
1572
    // (was sf.net Issue 3316407)
1573
0
    for (const auto atom : mol->atoms()) {
1574
0
      if (atom->hasQuery()) {
1575
0
        atom->updatePropertyCache(false);
1576
0
      }
1577
0
    }
1578
0
  }
1579
14.2k
}
void RDKit::MolPickler::_depickle<unsigned char>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, int, int, int, unsigned int)
Line
Count
Source
1351
44
                           unsigned int propertyFlags) {
1352
44
  PRECONDITION(mol, "empty molecule");
1353
44
  bool directMap = mol->getNumAtoms() == 0;
1354
44
  Tags tag;
1355
44
  int32_t tmpInt;
1356
44
  bool haveQuery = false;
1357
1358
  // did we include coordinates
1359
44
  bool includeCoords = false;
1360
44
  if (version >= 3000) {
1361
43
    unsigned char flag;
1362
43
    streamRead(ss, flag, version);
1363
43
    if (flag & 0x1 << 7) {
1364
5
      includeCoords = true;
1365
5
    }
1366
43
  }
1367
  // -------------------
1368
  //
1369
  // Read Atoms
1370
  //
1371
  // -------------------
1372
44
  streamRead(ss, tag, version);
1373
44
  if (tag != BEGINATOM) {
1374
1
    throw MolPicklerException("Bad pickle format: BEGINATOM tag not found.");
1375
1
  }
1376
43
  Conformer *conf = nullptr;
1377
43
  if ((version >= 2000 && version < 3000) && includeCoords) {
1378
    // there can only one conformation - since the positions were stored on
1379
    // the atoms themselves in this version
1380
0
    conf = new Conformer(numAtoms);
1381
0
    mol->addConformer(conf, true);
1382
0
  }
1383
49
  for (int i = 0; i < numAtoms; i++) {
1384
6
    RDGeom::Point3D pos;
1385
6
    Atom *atom = _addAtomFromPickle<T>(ss, mol, pos, version, directMap);
1386
6
    if ((version >= 2000 && version < 3000) && includeCoords) {
1387
      // this is a older pickle so we go the pos
1388
0
      conf->setAtomPos(i, pos);
1389
0
    }
1390
6
    if (!directMap) {
1391
0
      mol->setAtomBookmark(atom, i);
1392
0
    }
1393
6
    if (atom->hasQuery()) {
1394
2
      haveQuery = true;
1395
2
    }
1396
6
  }
1397
1398
  // -------------------
1399
  //
1400
  // Read Bonds
1401
  //
1402
  // -------------------
1403
43
  streamRead(ss, tag, version);
1404
43
  if (tag != BEGINBOND) {
1405
0
    throw MolPicklerException("Bad pickle format: BEGINBOND tag not found.");
1406
0
  }
1407
48
  for (int i = 0; i < numBonds; i++) {
1408
5
    Bond *bond = _addBondFromPickle<T>(ss, mol, version, directMap);
1409
5
    if (!directMap) {
1410
0
      mol->setBondBookmark(bond, i);
1411
0
    }
1412
5
  }
1413
1414
  // -------------------
1415
  //
1416
  // Read Rings (if needed)
1417
  //
1418
  // -------------------
1419
43
  streamRead(ss, tag, version);
1420
43
  bool ringFound = false;
1421
43
  bool ringFamiliesFound = false;
1422
43
  FIND_RING_TYPE ringType =
1423
43
      RDKit::FIND_RING_TYPE::FIND_RING_TYPE_OTHER_OR_UNKNOWN;
1424
43
  if (tag == BEGINSSSR) {
1425
0
    ringFound = true;
1426
0
    ringFamiliesFound = true;
1427
0
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_SSSR;
1428
43
  } else if (tag == BEGINSYMMSSSR) {
1429
0
    ringFound = true;
1430
0
    ringFamiliesFound = true;
1431
0
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_SYMM_SSSR;
1432
43
  } else if (tag == BEGINFASTFIND) {
1433
0
    ringFound = true;
1434
0
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_FAST;
1435
43
  } else if (tag == BEGINFINDOTHERORUNKNOWN) {
1436
0
    ringFound = true;
1437
0
    ringType = FIND_RING_TYPE::FIND_RING_TYPE_OTHER_OR_UNKNOWN;
1438
0
  }
1439
43
  if (ringFound) {
1440
0
    _addRingInfoFromPickle<T>(ss, mol, version, directMap, ringType);
1441
0
    streamRead(ss, tag, version);
1442
0
  }
1443
43
  if (ringFamiliesFound) {
1444
    // findSSSR now initializes ring families, so make sure
1445
    // unpickled mols have done this to prevent issues with
1446
    // code that expects ring families to be initialized.
1447
0
    MolOps::findRingFamilies(*mol);
1448
0
  }
1449
1450
  // -------------------
1451
  //
1452
  // Read SubstanceGroups (if needed)
1453
  //
1454
  // -------------------
1455
1456
43
  if (tag == BEGINSGROUP) {
1457
33
    streamRead(ss, tmpInt, version);
1458
1459
    // Create SubstanceGroups
1460
41.2k
    for (int i = 0; i < tmpInt; ++i) {
1461
41.1k
      auto sgroup = _getSubstanceGroupFromPickle<T>(ss, mol, version);
1462
41.1k
      addSubstanceGroup(*mol, sgroup);
1463
41.1k
    }
1464
1465
33
    streamRead(ss, tag, version);
1466
33
  }
1467
1468
43
  if (tag == BEGINSTEREOGROUP) {
1469
0
    _depickleStereo<T>(ss, mol, version);
1470
0
    streamRead(ss, tag, version);
1471
0
  }
1472
1473
43
  if (tag == BEGINCONFS || tag == BEGINCONFS_DOUBLE) {
1474
2
    int32_t blkSize = 0;
1475
2
    if (version >= 13000) {
1476
0
      streamRead(ss, blkSize, version);
1477
0
    }
1478
2
    if (version >= 13000 && (propertyFlags & PicklerOps::NoConformers)) {
1479
      // not reading coordinates, so just skip over those bytes
1480
0
      ss.seekg(blkSize, std::ios_base::cur);
1481
0
      streamRead(ss, tag, version);
1482
2
    } else {
1483
      // read in the conformation
1484
2
      streamRead(ss, tmpInt, version);
1485
2
      std::vector<unsigned int> cids(tmpInt);
1486
4
      for (auto i = 0; i < tmpInt; i++) {
1487
2
        Conformer *conf;
1488
2
        if (tag == BEGINCONFS) {
1489
2
          conf = _conformerFromPickle<T, float>(ss, version);
1490
2
        } else {
1491
0
          conf = _conformerFromPickle<T, double>(ss, version);
1492
0
        }
1493
2
        mol->addConformer(conf);
1494
2
        cids[i] = conf->getId();
1495
2
      }
1496
2
      streamRead(ss, tag, version);
1497
2
      if (tag == BEGINCONFPROPS) {
1498
0
        int32_t blkSize = 0;
1499
0
        if (version >= 13000) {
1500
0
          streamRead(ss, blkSize, version);
1501
0
        }
1502
0
        if (version >= 13000 && !(propertyFlags & PicklerOps::MolProps)) {
1503
0
          ss.seekg(blkSize, std::ios_base::cur);
1504
0
        } else {
1505
0
          for (auto cid : cids) {
1506
0
            _unpickleProperties(ss, mol->getConformer(cid), version);
1507
0
          }
1508
0
        }
1509
0
        streamRead(ss, tag, version);
1510
0
      }
1511
2
    }
1512
2
  }
1513
1514
43
  while (tag != ENDMOL) {
1515
0
    if (tag == BEGINPROPS) {
1516
0
      int32_t blkSize = 0;
1517
0
      if (version >= 13000) {
1518
0
        streamRead(ss, blkSize, version);
1519
0
      }
1520
0
      if (version >= 13000 && !(propertyFlags & PicklerOps::MolProps)) {
1521
0
        ss.seekg(blkSize, std::ios_base::cur);
1522
0
      } else {
1523
0
        _unpickleProperties(ss, *mol, version);
1524
0
      }
1525
0
      streamRead(ss, tag, version);
1526
0
    } else if (tag == BEGINATOMPROPS) {
1527
0
      int32_t blkSize = 0;
1528
0
      if (version >= 13000) {
1529
0
        streamRead(ss, blkSize, version);
1530
0
      }
1531
0
      if (version >= 13000 && !(propertyFlags & PicklerOps::AtomProps)) {
1532
0
        ss.seekg(blkSize, std::ios_base::cur);
1533
0
      } else {
1534
0
        for (const auto atom : mol->atoms()) {
1535
0
          unpickleAtomProperties(ss, *atom, version);
1536
0
        }
1537
0
      }
1538
0
      streamRead(ss, tag, version);
1539
0
    } else if (tag == BEGINBONDPROPS) {
1540
0
      int32_t blkSize = 0;
1541
0
      if (version >= 13000) {
1542
0
        streamRead(ss, blkSize, version);
1543
0
      }
1544
0
      if (version >= 13000 && !(propertyFlags & PicklerOps::BondProps)) {
1545
0
        ss.seekg(blkSize, std::ios_base::cur);
1546
0
      } else {
1547
0
        for (const auto bond : mol->bonds()) {
1548
0
          unpickleBondProperties(ss, *bond, version);
1549
0
        }
1550
0
      }
1551
0
      streamRead(ss, tag, version);
1552
0
    } else if (tag == BEGINQUERYATOMDATA) {
1553
0
      for (const auto atom : mol->atoms()) {
1554
0
        _unpickleAtomData(ss, atom, version);
1555
0
      }
1556
0
      streamRead(ss, tag, version);
1557
0
    } else {
1558
0
      break;  // break to tag != ENDMOL
1559
0
    }
1560
0
    if (tag != ENDPROPS) {
1561
0
      throw MolPicklerException("Bad pickle format: ENDPROPS tag not found.");
1562
0
    }
1563
0
    streamRead(ss, tag, version);
1564
0
  }
1565
43
  if (tag != ENDMOL) {
1566
0
    throw MolPicklerException("Bad pickle format: ENDMOL tag not found.");
1567
0
  }
1568
1569
43
  if (haveQuery) {
1570
    // we didn't read any property info for atoms with associated
1571
    // queries. update their property caches
1572
    // (was sf.net Issue 3316407)
1573
0
    for (const auto atom : mol->atoms()) {
1574
0
      if (atom->hasQuery()) {
1575
0
        atom->updatePropertyCache(false);
1576
0
      }
1577
0
    }
1578
0
  }
1579
43
}
1580
1581
//--------------------------------------
1582
//
1583
//            Atoms
1584
//
1585
//--------------------------------------
1586
1587
namespace {
1588
0
bool getAtomMapNumber(const Atom *atom, int &mapNum) {
1589
0
  PRECONDITION(atom, "bad atom");
1590
0
  if (!atom->hasProp(common_properties::molAtomMapNumber)) {
1591
0
    return false;
1592
0
  }
1593
0
  bool res = true;
1594
0
  int tmpInt;
1595
0
  try {
1596
0
    atom->getProp(common_properties::molAtomMapNumber, tmpInt);
1597
0
  } catch (std::bad_any_cast &) {
1598
0
    const std::string &tmpSVal =
1599
0
        atom->getProp<std::string>(common_properties::molAtomMapNumber);
1600
0
    try {
1601
0
      tmpInt = boost::lexical_cast<int>(tmpSVal);
1602
0
    } catch (boost::bad_lexical_cast &) {
1603
0
      res = false;
1604
0
    }
1605
0
  }
1606
0
  if (res) {
1607
0
    mapNum = tmpInt;
1608
0
  }
1609
0
  return res;
1610
0
}
1611
}  // namespace
1612
1613
0
int32_t MolPickler::_pickleAtomData(std::ostream &tss, const Atom *atom) {
1614
0
  int32_t propFlags = 0;
1615
0
  char tmpChar;
1616
0
  signed char tmpSchar;
1617
  // tmpFloat=atom->getMass()-PeriodicTable::getTable()->getAtomicWeight(atom->getAtomicNum());
1618
  // if(fabs(tmpFloat)>.0001){
1619
  //   propFlags |= 1;
1620
  //   streamWrite(tss,tmpFloat);
1621
  // }
1622
0
  tmpSchar = static_cast<signed char>(atom->getFormalCharge());
1623
0
  if (tmpSchar != 0) {
1624
0
    propFlags |= 1 << 1;
1625
0
    streamWrite(tss, tmpSchar);
1626
0
  }
1627
0
  tmpChar = static_cast<char>(atom->getChiralTag());
1628
0
  if (tmpChar != 0) {
1629
0
    propFlags |= 1 << 2;
1630
0
    streamWrite(tss, tmpChar);
1631
0
  }
1632
0
  tmpChar = static_cast<char>(atom->getHybridization());
1633
0
  if (tmpChar != static_cast<char>(Atom::SP3)) {
1634
0
    propFlags |= 1 << 3;
1635
0
    streamWrite(tss, tmpChar);
1636
0
  }
1637
1638
0
  tmpChar = static_cast<char>(atom->getNumExplicitHs());
1639
0
  if (tmpChar != 0) {
1640
0
    propFlags |= 1 << 4;
1641
0
    streamWrite(tss, tmpChar);
1642
0
  }
1643
0
  if (atom->d_explicitValence > 0) {
1644
0
    tmpChar = static_cast<char>(atom->d_explicitValence);
1645
0
    propFlags |= 1 << 5;
1646
0
    streamWrite(tss, tmpChar);
1647
0
  }
1648
0
  if (atom->d_implicitValence > 0) {
1649
0
    tmpChar = static_cast<char>(atom->d_implicitValence);
1650
0
    propFlags |= 1 << 6;
1651
0
    streamWrite(tss, tmpChar);
1652
0
  }
1653
0
  tmpChar = static_cast<char>(atom->getNumRadicalElectrons());
1654
0
  if (tmpChar != 0) {
1655
0
    propFlags |= 1 << 7;
1656
0
    streamWrite(tss, tmpChar);
1657
0
  }
1658
1659
0
  unsigned int tmpuint = atom->getIsotope();
1660
0
  if (tmpuint > 0) {
1661
0
    propFlags |= 1 << 8;
1662
0
    streamWrite(tss, tmpuint);
1663
0
  }
1664
0
  return propFlags;
1665
0
}
1666
1667
26.9k
void MolPickler::_unpickleAtomData(std::istream &ss, Atom *atom, int version) {
1668
26.9k
  int propFlags;
1669
26.9k
  char tmpChar;
1670
26.9k
  signed char tmpSchar;
1671
1672
26.9k
  streamRead(ss, propFlags, version);
1673
26.9k
  if (propFlags & 1) {
1674
1.68k
    float tmpFloat;
1675
1.68k
    streamRead(ss, tmpFloat, version);
1676
1.68k
    int iso = static_cast<int>(floor(tmpFloat + atom->getMass() + .0001));
1677
1.68k
    atom->setIsotope(iso);
1678
1.68k
  }
1679
1680
26.9k
  if (propFlags & (1 << 1)) {
1681
574
    streamRead(ss, tmpSchar, version);
1682
26.4k
  } else {
1683
26.4k
    tmpSchar = 0;
1684
26.4k
  }
1685
26.9k
  atom->setFormalCharge(static_cast<int>(tmpSchar));
1686
1687
26.9k
  if (propFlags & (1 << 2)) {
1688
36
    streamReadPositiveChar(ss, tmpChar, version);
1689
26.9k
  } else {
1690
26.9k
    tmpChar = 0;
1691
26.9k
  }
1692
26.9k
  atom->setChiralTag(static_cast<Atom::ChiralType>(tmpChar));
1693
1694
26.9k
  if (propFlags & (1 << 3)) {
1695
559
    streamReadPositiveChar(ss, tmpChar, version);
1696
26.4k
  } else {
1697
26.4k
    tmpChar = Atom::SP3;
1698
26.4k
  }
1699
26.9k
  atom->setHybridization(static_cast<Atom::HybridizationType>(tmpChar));
1700
1701
26.9k
  if (propFlags & (1 << 4)) {
1702
32
    streamRead(ss, tmpChar, version);
1703
26.9k
  } else {
1704
26.9k
    tmpChar = 0;
1705
26.9k
  }
1706
26.9k
  atom->setNumExplicitHs(tmpChar);
1707
1708
26.9k
  if (propFlags & (1 << 5)) {
1709
49
    streamRead(ss, tmpChar, version);
1710
26.9k
  } else {
1711
26.9k
    tmpChar = 0;
1712
26.9k
  }
1713
26.9k
  atom->d_explicitValence = tmpChar;
1714
1715
26.9k
  if (propFlags & (1 << 6)) {
1716
68
    streamRead(ss, tmpChar, version);
1717
26.9k
  } else {
1718
26.9k
    tmpChar = 0;
1719
26.9k
  }
1720
26.9k
  atom->d_implicitValence = tmpChar;
1721
26.9k
  if (propFlags & (1 << 7)) {
1722
55
    streamReadPositiveChar(ss, tmpChar, version);
1723
26.9k
  } else {
1724
26.9k
    tmpChar = 0;
1725
26.9k
  }
1726
26.9k
  atom->d_numRadicalElectrons = static_cast<unsigned int>(tmpChar);
1727
1728
26.9k
  atom->d_isotope = 0;
1729
26.9k
  if (propFlags & (1 << 8)) {
1730
2.67k
    unsigned int tmpuint;
1731
2.67k
    streamRead(ss, tmpuint, version);
1732
2.67k
    atom->setIsotope(tmpuint);
1733
2.67k
  }
1734
26.9k
}
1735
1736
// T refers to the type of the atom indices written
1737
template <typename T>
1738
0
void MolPickler::_pickleAtom(std::ostream &ss, const Atom *atom) {
1739
0
  PRECONDITION(atom, "empty atom");
1740
0
  char tmpChar;
1741
0
  unsigned char tmpUchar;
1742
0
  int tmpInt;
1743
0
  char flags;
1744
1745
0
  tmpUchar = atom->getAtomicNum() % 256;
1746
0
  streamWrite(ss, tmpUchar);
1747
1748
0
  flags = 0;
1749
0
  if (atom->getIsAromatic()) {
1750
0
    flags |= 0x1 << 6;
1751
0
  }
1752
0
  if (atom->getNoImplicit()) {
1753
0
    flags |= 0x1 << 5;
1754
0
  }
1755
0
  if (atom->hasQuery()) {
1756
0
    flags |= 0x1 << 4;
1757
0
  }
1758
0
  if (getAtomMapNumber(atom, tmpInt)) {
1759
0
    flags |= 0x1 << 3;
1760
0
  }
1761
0
  if (atom->hasProp(common_properties::dummyLabel)) {
1762
0
    flags |= 0x1 << 2;
1763
0
  }
1764
0
  if (atom->getMonomerInfo()) {
1765
0
    flags |= 0x1 << 1;
1766
0
  }
1767
1768
0
  streamWrite(ss, flags);
1769
1770
0
  std::stringstream tss(std::ios_base::binary | std::ios_base::out |
1771
0
                        std::ios_base::in);
1772
0
  int32_t propFlags = _pickleAtomData(tss, atom);
1773
0
  streamWrite(ss, propFlags);
1774
0
  ss.write(tss.str().c_str(), tss.str().size());
1775
0
  if (atom->hasQuery()) {
1776
0
    streamWrite(ss, BEGINQUERY);
1777
0
    pickleQuery(ss, static_cast<const QueryAtom *>(atom)->getQuery());
1778
0
    streamWrite(ss, ENDQUERY);
1779
0
  }
1780
0
  if (getAtomMapNumber(atom, tmpInt)) {
1781
0
    if (tmpInt >= 0 && tmpInt < 128) {
1782
0
      tmpChar = static_cast<char>(tmpInt);
1783
0
      streamWrite(ss, ATOM_MAPNUMBER, tmpChar);
1784
0
    } else {
1785
0
      tmpChar = static_cast<char>(255);
1786
0
      streamWrite(ss, ATOM_MAPNUMBER, tmpChar);
1787
0
      streamWrite(ss, tmpInt);
1788
0
    }
1789
0
  }
1790
0
  if (atom->hasProp(common_properties::dummyLabel)) {
1791
0
    streamWrite(ss, ATOM_DUMMYLABEL,
1792
0
                atom->getProp<std::string>(common_properties::dummyLabel));
1793
0
  }
1794
0
  if (atom->getMonomerInfo()) {
1795
0
    if (atom->getMonomerInfo()->getMonomerType() ==
1796
0
        AtomMonomerInfo::PDBRESIDUE) {
1797
0
      streamWrite(ss, BEGIN_PDB_RESIDUE);
1798
0
      pickleAtomPDBResidueInfo(
1799
0
          ss, static_cast<const AtomPDBResidueInfo *>(atom->getMonomerInfo()));
1800
0
      streamWrite(ss, END_PDB_RESIDUE);
1801
0
    } else {
1802
0
      streamWrite(ss, BEGIN_ATOM_MONOMER_INFO);
1803
0
      pickleAtomMonomerInfo(ss, atom->getMonomerInfo());
1804
0
      streamWrite(ss, END_ATOM_MONOMER_INFO);
1805
0
    }
1806
0
  }
1807
0
}
Unexecuted instantiation: void RDKit::MolPickler::_pickleAtom<int>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::Atom const*)
Unexecuted instantiation: void RDKit::MolPickler::_pickleAtom<unsigned char>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::Atom const*)
1808
1809
template <typename T, typename C>
1810
0
void MolPickler::_pickleConformer(std::ostream &ss, const Conformer *conf) {
1811
0
  PRECONDITION(conf, "empty conformer");
1812
0
  char tmpChr = static_cast<int>(conf->is3D());
1813
0
  streamWrite(ss, tmpChr);
1814
0
  auto tmpInt = static_cast<int32_t>(conf->getId());
1815
0
  streamWrite(ss, tmpInt);
1816
0
  T tmpT = static_cast<T>(conf->getNumAtoms());
1817
0
  streamWrite(ss, tmpT);
1818
0
  const RDGeom::POINT3D_VECT &pts = conf->getPositions();
1819
0
  for (const auto &pt : pts) {
1820
0
    C tmpFloat;
1821
0
    tmpFloat = static_cast<C>(pt.x);
1822
0
    streamWrite(ss, tmpFloat);
1823
0
    tmpFloat = static_cast<C>(pt.y);
1824
0
    streamWrite(ss, tmpFloat);
1825
0
    tmpFloat = static_cast<C>(pt.z);
1826
0
    streamWrite(ss, tmpFloat);
1827
0
  }
1828
0
}
Unexecuted instantiation: void RDKit::MolPickler::_pickleConformer<int, double>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::Conformer const*)
Unexecuted instantiation: void RDKit::MolPickler::_pickleConformer<int, float>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::Conformer const*)
Unexecuted instantiation: void RDKit::MolPickler::_pickleConformer<unsigned char, double>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::Conformer const*)
Unexecuted instantiation: void RDKit::MolPickler::_pickleConformer<unsigned char, float>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::Conformer const*)
1829
1830
template <typename T, typename C>
1831
123
Conformer *MolPickler::_conformerFromPickle(std::istream &ss, int version) {
1832
123
  C tmpFloat;
1833
123
  bool is3D = true;
1834
123
  if (version > 4000) {
1835
2
    char tmpChr;
1836
2
    streamRead(ss, tmpChr, version);
1837
2
    is3D = static_cast<bool>(tmpChr);
1838
2
  }
1839
123
  int tmpInt;
1840
123
  streamRead(ss, tmpInt, version);
1841
123
  auto cid = static_cast<unsigned int>(tmpInt);
1842
123
  T tmpT;
1843
123
  streamRead(ss, tmpT, version);
1844
123
  auto numAtoms = static_cast<unsigned int>(tmpT);
1845
123
  auto *conf = new Conformer(numAtoms);
1846
123
  conf->setId(cid);
1847
123
  conf->set3D(is3D);
1848
123
  try {
1849
22.7k
    for (unsigned int i = 0; i < numAtoms; i++) {
1850
22.6k
      streamRead(ss, tmpFloat, version);
1851
22.6k
      conf->getAtomPos(i).x = static_cast<double>(tmpFloat);
1852
22.6k
      streamRead(ss, tmpFloat, version);
1853
22.6k
      conf->getAtomPos(i).y = static_cast<double>(tmpFloat);
1854
22.6k
      streamRead(ss, tmpFloat, version);
1855
22.6k
      conf->getAtomPos(i).z = static_cast<double>(tmpFloat);
1856
22.6k
    }
1857
123
  } catch (...) {
1858
28
    delete conf;
1859
28
    throw;
1860
28
  }
1861
92
  return conf;
1862
123
}
RDKit::Conformer* RDKit::MolPickler::_conformerFromPickle<int, float>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, int)
Line
Count
Source
1831
61
Conformer *MolPickler::_conformerFromPickle(std::istream &ss, int version) {
1832
61
  C tmpFloat;
1833
61
  bool is3D = true;
1834
61
  if (version > 4000) {
1835
0
    char tmpChr;
1836
0
    streamRead(ss, tmpChr, version);
1837
0
    is3D = static_cast<bool>(tmpChr);
1838
0
  }
1839
61
  int tmpInt;
1840
61
  streamRead(ss, tmpInt, version);
1841
61
  auto cid = static_cast<unsigned int>(tmpInt);
1842
61
  T tmpT;
1843
61
  streamRead(ss, tmpT, version);
1844
61
  auto numAtoms = static_cast<unsigned int>(tmpT);
1845
61
  auto *conf = new Conformer(numAtoms);
1846
61
  conf->setId(cid);
1847
61
  conf->set3D(is3D);
1848
61
  try {
1849
10.2k
    for (unsigned int i = 0; i < numAtoms; i++) {
1850
10.2k
      streamRead(ss, tmpFloat, version);
1851
10.2k
      conf->getAtomPos(i).x = static_cast<double>(tmpFloat);
1852
10.2k
      streamRead(ss, tmpFloat, version);
1853
10.2k
      conf->getAtomPos(i).y = static_cast<double>(tmpFloat);
1854
10.2k
      streamRead(ss, tmpFloat, version);
1855
10.2k
      conf->getAtomPos(i).z = static_cast<double>(tmpFloat);
1856
10.2k
    }
1857
61
  } catch (...) {
1858
19
    delete conf;
1859
19
    throw;
1860
19
  }
1861
40
  return conf;
1862
61
}
RDKit::Conformer* RDKit::MolPickler::_conformerFromPickle<int, double>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, int)
Line
Count
Source
1831
60
Conformer *MolPickler::_conformerFromPickle(std::istream &ss, int version) {
1832
60
  C tmpFloat;
1833
60
  bool is3D = true;
1834
60
  if (version > 4000) {
1835
0
    char tmpChr;
1836
0
    streamRead(ss, tmpChr, version);
1837
0
    is3D = static_cast<bool>(tmpChr);
1838
0
  }
1839
60
  int tmpInt;
1840
60
  streamRead(ss, tmpInt, version);
1841
60
  auto cid = static_cast<unsigned int>(tmpInt);
1842
60
  T tmpT;
1843
60
  streamRead(ss, tmpT, version);
1844
60
  auto numAtoms = static_cast<unsigned int>(tmpT);
1845
60
  auto *conf = new Conformer(numAtoms);
1846
60
  conf->setId(cid);
1847
60
  conf->set3D(is3D);
1848
60
  try {
1849
12.1k
    for (unsigned int i = 0; i < numAtoms; i++) {
1850
12.1k
      streamRead(ss, tmpFloat, version);
1851
12.1k
      conf->getAtomPos(i).x = static_cast<double>(tmpFloat);
1852
12.1k
      streamRead(ss, tmpFloat, version);
1853
12.1k
      conf->getAtomPos(i).y = static_cast<double>(tmpFloat);
1854
12.1k
      streamRead(ss, tmpFloat, version);
1855
12.1k
      conf->getAtomPos(i).z = static_cast<double>(tmpFloat);
1856
12.1k
    }
1857
60
  } catch (...) {
1858
9
    delete conf;
1859
9
    throw;
1860
9
  }
1861
50
  return conf;
1862
60
}
RDKit::Conformer* RDKit::MolPickler::_conformerFromPickle<unsigned char, float>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, int)
Line
Count
Source
1831
2
Conformer *MolPickler::_conformerFromPickle(std::istream &ss, int version) {
1832
2
  C tmpFloat;
1833
2
  bool is3D = true;
1834
2
  if (version > 4000) {
1835
2
    char tmpChr;
1836
2
    streamRead(ss, tmpChr, version);
1837
2
    is3D = static_cast<bool>(tmpChr);
1838
2
  }
1839
2
  int tmpInt;
1840
2
  streamRead(ss, tmpInt, version);
1841
2
  auto cid = static_cast<unsigned int>(tmpInt);
1842
2
  T tmpT;
1843
2
  streamRead(ss, tmpT, version);
1844
2
  auto numAtoms = static_cast<unsigned int>(tmpT);
1845
2
  auto *conf = new Conformer(numAtoms);
1846
2
  conf->setId(cid);
1847
2
  conf->set3D(is3D);
1848
2
  try {
1849
341
    for (unsigned int i = 0; i < numAtoms; i++) {
1850
339
      streamRead(ss, tmpFloat, version);
1851
339
      conf->getAtomPos(i).x = static_cast<double>(tmpFloat);
1852
339
      streamRead(ss, tmpFloat, version);
1853
339
      conf->getAtomPos(i).y = static_cast<double>(tmpFloat);
1854
339
      streamRead(ss, tmpFloat, version);
1855
339
      conf->getAtomPos(i).z = static_cast<double>(tmpFloat);
1856
339
    }
1857
2
  } catch (...) {
1858
0
    delete conf;
1859
0
    throw;
1860
0
  }
1861
2
  return conf;
1862
2
}
Unexecuted instantiation: RDKit::Conformer* RDKit::MolPickler::_conformerFromPickle<unsigned char, double>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, int)
1863
1864
template <typename T>
1865
Atom *MolPickler::_addAtomFromPickle(std::istream &ss, ROMol *mol,
1866
431k
                                     RDGeom::Point3D &pos, int version, bool) {
1867
431k
  PRECONDITION(mol, "empty molecule");
1868
431k
  float x, y, z;
1869
431k
  char tmpChar;
1870
431k
  unsigned char tmpUchar;
1871
431k
  signed char tmpSchar;
1872
431k
  char flags;
1873
431k
  Tags tag;
1874
431k
  Atom *atom = nullptr;
1875
431k
  int atomicNum = 0;
1876
1877
431k
  streamRead(ss, tmpUchar, version);
1878
431k
  atomicNum = tmpUchar;
1879
1880
431k
  bool hasQuery = false;
1881
431k
  streamRead(ss, flags, version);
1882
431k
  if (version > 5000) {
1883
26.9k
    hasQuery = flags & 0x1 << 4;
1884
26.9k
  }
1885
431k
  if (!hasQuery) {
1886
417k
    atom = new Atom(atomicNum);
1887
417k
  } else {
1888
14.4k
    atom = new QueryAtom();
1889
14.4k
    if (atomicNum) {
1890
      // can't set this in the constructor because that builds a
1891
      // query and we're going to take care of that later:
1892
1.24k
      atom->setAtomicNum(atomicNum);
1893
1.24k
    }
1894
14.4k
  }
1895
431k
  atom->setIsAromatic(flags & 0x1 << 6);
1896
431k
  atom->setNoImplicit(flags & 0x1 << 5);
1897
1898
431k
  bool hasAtomMap = 0, hasDummyLabel = 0;
1899
431k
  if (version >= 6020) {
1900
26.9k
    hasAtomMap = flags & 0x1 << 3;
1901
26.9k
    hasDummyLabel = flags & 0x1 << 2;
1902
26.9k
  }
1903
431k
  bool hasMonomerInfo = 0;
1904
431k
  if (version >= 7020) {
1905
26.9k
    hasMonomerInfo = flags & 0x1 << 1;
1906
26.9k
  }
1907
1908
  // are coordinates present?
1909
431k
  if (flags & 0x1 << 7) {
1910
1.98k
    streamRead(ss, x, version);
1911
1.98k
    pos.x = static_cast<double>(x);
1912
1.98k
    streamRead(ss, y, version);
1913
1.98k
    pos.y = static_cast<double>(y);
1914
1.98k
    streamRead(ss, z, version);
1915
1.98k
    pos.z = static_cast<double>(z);
1916
1.98k
  }
1917
1918
431k
  if (version <= 5000 || !hasQuery) {
1919
417k
    if (version < 7000) {
1920
404k
      if (version < 6030) {
1921
404k
        streamRead(ss, tmpSchar, version);
1922
        // FIX: technically should be handling this in order to maintain true
1923
        // backwards compatibility
1924
        // atom->setMass(PeriodicTable::getTable()->getAtomicWeight(atom->getAtomicNum())+
1925
        //              static_cast<int>(tmpSchar));
1926
404k
      } else {
1927
0
        float tmpFloat;
1928
0
        streamRead(ss, tmpFloat, version);
1929
        // FIX: technically should be handling this in order to maintain true
1930
        // backwards compatibility
1931
        // atom->setMass(tmpFloat);
1932
0
      }
1933
1934
404k
      streamRead(ss, tmpSchar, version);
1935
404k
      atom->setFormalCharge(static_cast<int>(tmpSchar));
1936
1937
404k
      streamRead(ss, tmpChar, version);
1938
404k
      atom->setChiralTag(static_cast<Atom::ChiralType>(tmpChar));
1939
404k
      streamRead(ss, tmpChar, version);
1940
404k
      atom->setHybridization(static_cast<Atom::HybridizationType>(tmpChar));
1941
404k
      streamRead(ss, tmpChar, version);
1942
404k
      atom->setNumExplicitHs(static_cast<int>(tmpChar));
1943
404k
      streamRead(ss, tmpChar, version);
1944
404k
      atom->d_explicitValence = tmpChar;
1945
404k
      streamRead(ss, tmpChar, version);
1946
404k
      atom->d_implicitValence = tmpChar;
1947
404k
      if (version > 6000) {
1948
0
        streamRead(ss, tmpChar, version);
1949
0
        atom->d_numRadicalElectrons = static_cast<unsigned int>(tmpChar);
1950
0
      }
1951
404k
    } else {
1952
12.5k
      _unpickleAtomData(ss, atom, version);
1953
12.5k
    }
1954
1955
417k
  } else if (version > 5000) {
1956
    // we have a query
1957
14.4k
    if (version >= 9000) {
1958
14.4k
      _unpickleAtomData(ss, atom, version);
1959
14.4k
    }
1960
14.4k
    streamRead(ss, tag, version);
1961
14.4k
    if (tag != BEGINQUERY) {
1962
8
      throw MolPicklerException("Bad pickle format: BEGINQUERY tag not found.");
1963
8
    }
1964
14.4k
    static_cast<QueryAtom *>(atom)->setQuery(unpickleQuery(ss, atom, version));
1965
14.4k
    streamRead(ss, tag, version);
1966
14.4k
    if (tag != ENDQUERY) {
1967
1
      throw MolPicklerException("Bad pickle format: ENDQUERY tag not found.");
1968
1
    }
1969
    // atom->setNumExplicitHs(0);
1970
14.4k
  }
1971
1972
431k
  if (version > 5000) {
1973
12.9k
    if (version < 6020) {
1974
0
      unsigned int sPos = rdcast<unsigned int>(ss.tellg());
1975
0
      Tags tag;
1976
0
      streamRead(ss, tag, version);
1977
0
      if (tag == ATOM_MAPNUMBER) {
1978
0
        int32_t tmpInt;
1979
0
        streamRead(ss, tmpChar, version);
1980
0
        tmpInt = tmpChar;
1981
0
        atom->setProp(common_properties::molAtomMapNumber, tmpInt);
1982
0
      } else {
1983
0
        ss.seekg(sPos);
1984
0
      }
1985
12.9k
    } else {
1986
12.9k
      if (hasAtomMap) {
1987
0
        Tags tag;
1988
0
        streamRead(ss, tag, version);
1989
0
        if (tag != ATOM_MAPNUMBER) {
1990
0
          throw MolPicklerException(
1991
0
              "Bad pickle format: ATOM_MAPNUMBER tag not found.");
1992
0
        }
1993
0
        int tmpInt;
1994
0
        streamRead(ss, tmpChar, version);
1995
        // the test for tmpChar below seems redundant, but on at least
1996
        // the POWER8 architecture it seems that chars may be unsigned
1997
        // by default.
1998
0
#ifdef __GNUC__
1999
0
#pragma GCC diagnostic push
2000
0
#pragma GCC diagnostic ignored "-Wtype-limits"
2001
0
#endif
2002
0
        if ((tmpChar < 0 || tmpChar > 127) && version > 9000) {
2003
0
#ifdef __GNUC__
2004
0
#pragma GCC diagnostic pop
2005
0
#endif
2006
0
          streamRead(ss, tmpInt, version);
2007
0
        } else {
2008
0
          tmpInt = tmpChar;
2009
0
        }
2010
0
        atom->setProp(common_properties::molAtomMapNumber, tmpInt);
2011
0
      }
2012
12.9k
      if (hasDummyLabel) {
2013
0
        streamRead(ss, tag, version);
2014
0
        if (tag != ATOM_DUMMYLABEL) {
2015
0
          throw MolPicklerException(
2016
0
              "Bad pickle format: ATOM_DUMMYLABEL tag not found.");
2017
0
        }
2018
0
        std::string tmpStr;
2019
0
        streamRead(ss, tmpStr, version);
2020
0
        atom->setProp(common_properties::dummyLabel, tmpStr);
2021
0
      }
2022
12.9k
    }
2023
12.9k
  }
2024
431k
  if (version >= 7020) {
2025
12.9k
    if (hasMonomerInfo) {
2026
1.59k
      streamRead(ss, tag, version);
2027
1.59k
      if (tag == BEGIN_PDB_RESIDUE) {
2028
1.59k
        atom->setMonomerInfo(unpickleAtomPDBResidueInfo(ss, version));
2029
1.59k
      } else if (tag == BEGIN_ATOM_MONOMER_INFO) {
2030
0
        atom->setMonomerInfo(unpickleAtomMonomerInfo(ss, version));
2031
3
      } else {
2032
3
        throw MolPicklerException(
2033
3
            "Bad pickle format: BEGIN_PDB_RESIDUE or BEGIN_ATOM_MONOMER_INFO tag not found.");
2034
3
      }
2035
1.59k
    }
2036
12.9k
  }
2037
431k
  mol->addAtom(atom, false, true);
2038
431k
  return atom;
2039
431k
}
RDKit::Atom* RDKit::MolPickler::_addAtomFromPickle<int>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, RDGeom::Point3D&, int, bool)
Line
Count
Source
1866
431k
                                     RDGeom::Point3D &pos, int version, bool) {
1867
431k
  PRECONDITION(mol, "empty molecule");
1868
431k
  float x, y, z;
1869
431k
  char tmpChar;
1870
431k
  unsigned char tmpUchar;
1871
431k
  signed char tmpSchar;
1872
431k
  char flags;
1873
431k
  Tags tag;
1874
431k
  Atom *atom = nullptr;
1875
431k
  int atomicNum = 0;
1876
1877
431k
  streamRead(ss, tmpUchar, version);
1878
431k
  atomicNum = tmpUchar;
1879
1880
431k
  bool hasQuery = false;
1881
431k
  streamRead(ss, flags, version);
1882
431k
  if (version > 5000) {
1883
26.9k
    hasQuery = flags & 0x1 << 4;
1884
26.9k
  }
1885
431k
  if (!hasQuery) {
1886
417k
    atom = new Atom(atomicNum);
1887
417k
  } else {
1888
14.4k
    atom = new QueryAtom();
1889
14.4k
    if (atomicNum) {
1890
      // can't set this in the constructor because that builds a
1891
      // query and we're going to take care of that later:
1892
1.23k
      atom->setAtomicNum(atomicNum);
1893
1.23k
    }
1894
14.4k
  }
1895
431k
  atom->setIsAromatic(flags & 0x1 << 6);
1896
431k
  atom->setNoImplicit(flags & 0x1 << 5);
1897
1898
431k
  bool hasAtomMap = 0, hasDummyLabel = 0;
1899
431k
  if (version >= 6020) {
1900
26.9k
    hasAtomMap = flags & 0x1 << 3;
1901
26.9k
    hasDummyLabel = flags & 0x1 << 2;
1902
26.9k
  }
1903
431k
  bool hasMonomerInfo = 0;
1904
431k
  if (version >= 7020) {
1905
26.9k
    hasMonomerInfo = flags & 0x1 << 1;
1906
26.9k
  }
1907
1908
  // are coordinates present?
1909
431k
  if (flags & 0x1 << 7) {
1910
1.98k
    streamRead(ss, x, version);
1911
1.98k
    pos.x = static_cast<double>(x);
1912
1.98k
    streamRead(ss, y, version);
1913
1.98k
    pos.y = static_cast<double>(y);
1914
1.98k
    streamRead(ss, z, version);
1915
1.98k
    pos.z = static_cast<double>(z);
1916
1.98k
  }
1917
1918
431k
  if (version <= 5000 || !hasQuery) {
1919
417k
    if (version < 7000) {
1920
404k
      if (version < 6030) {
1921
404k
        streamRead(ss, tmpSchar, version);
1922
        // FIX: technically should be handling this in order to maintain true
1923
        // backwards compatibility
1924
        // atom->setMass(PeriodicTable::getTable()->getAtomicWeight(atom->getAtomicNum())+
1925
        //              static_cast<int>(tmpSchar));
1926
404k
      } else {
1927
0
        float tmpFloat;
1928
0
        streamRead(ss, tmpFloat, version);
1929
        // FIX: technically should be handling this in order to maintain true
1930
        // backwards compatibility
1931
        // atom->setMass(tmpFloat);
1932
0
      }
1933
1934
404k
      streamRead(ss, tmpSchar, version);
1935
404k
      atom->setFormalCharge(static_cast<int>(tmpSchar));
1936
1937
404k
      streamRead(ss, tmpChar, version);
1938
404k
      atom->setChiralTag(static_cast<Atom::ChiralType>(tmpChar));
1939
404k
      streamRead(ss, tmpChar, version);
1940
404k
      atom->setHybridization(static_cast<Atom::HybridizationType>(tmpChar));
1941
404k
      streamRead(ss, tmpChar, version);
1942
404k
      atom->setNumExplicitHs(static_cast<int>(tmpChar));
1943
404k
      streamRead(ss, tmpChar, version);
1944
404k
      atom->d_explicitValence = tmpChar;
1945
404k
      streamRead(ss, tmpChar, version);
1946
404k
      atom->d_implicitValence = tmpChar;
1947
404k
      if (version > 6000) {
1948
0
        streamRead(ss, tmpChar, version);
1949
0
        atom->d_numRadicalElectrons = static_cast<unsigned int>(tmpChar);
1950
0
      }
1951
404k
    } else {
1952
12.5k
      _unpickleAtomData(ss, atom, version);
1953
12.5k
    }
1954
1955
417k
  } else if (version > 5000) {
1956
    // we have a query
1957
14.4k
    if (version >= 9000) {
1958
14.4k
      _unpickleAtomData(ss, atom, version);
1959
14.4k
    }
1960
14.4k
    streamRead(ss, tag, version);
1961
14.4k
    if (tag != BEGINQUERY) {
1962
8
      throw MolPicklerException("Bad pickle format: BEGINQUERY tag not found.");
1963
8
    }
1964
14.4k
    static_cast<QueryAtom *>(atom)->setQuery(unpickleQuery(ss, atom, version));
1965
14.4k
    streamRead(ss, tag, version);
1966
14.4k
    if (tag != ENDQUERY) {
1967
1
      throw MolPicklerException("Bad pickle format: ENDQUERY tag not found.");
1968
1
    }
1969
    // atom->setNumExplicitHs(0);
1970
14.4k
  }
1971
1972
431k
  if (version > 5000) {
1973
12.9k
    if (version < 6020) {
1974
0
      unsigned int sPos = rdcast<unsigned int>(ss.tellg());
1975
0
      Tags tag;
1976
0
      streamRead(ss, tag, version);
1977
0
      if (tag == ATOM_MAPNUMBER) {
1978
0
        int32_t tmpInt;
1979
0
        streamRead(ss, tmpChar, version);
1980
0
        tmpInt = tmpChar;
1981
0
        atom->setProp(common_properties::molAtomMapNumber, tmpInt);
1982
0
      } else {
1983
0
        ss.seekg(sPos);
1984
0
      }
1985
12.9k
    } else {
1986
12.9k
      if (hasAtomMap) {
1987
0
        Tags tag;
1988
0
        streamRead(ss, tag, version);
1989
0
        if (tag != ATOM_MAPNUMBER) {
1990
0
          throw MolPicklerException(
1991
0
              "Bad pickle format: ATOM_MAPNUMBER tag not found.");
1992
0
        }
1993
0
        int tmpInt;
1994
0
        streamRead(ss, tmpChar, version);
1995
        // the test for tmpChar below seems redundant, but on at least
1996
        // the POWER8 architecture it seems that chars may be unsigned
1997
        // by default.
1998
0
#ifdef __GNUC__
1999
0
#pragma GCC diagnostic push
2000
0
#pragma GCC diagnostic ignored "-Wtype-limits"
2001
0
#endif
2002
0
        if ((tmpChar < 0 || tmpChar > 127) && version > 9000) {
2003
0
#ifdef __GNUC__
2004
0
#pragma GCC diagnostic pop
2005
0
#endif
2006
0
          streamRead(ss, tmpInt, version);
2007
0
        } else {
2008
0
          tmpInt = tmpChar;
2009
0
        }
2010
0
        atom->setProp(common_properties::molAtomMapNumber, tmpInt);
2011
0
      }
2012
12.9k
      if (hasDummyLabel) {
2013
0
        streamRead(ss, tag, version);
2014
0
        if (tag != ATOM_DUMMYLABEL) {
2015
0
          throw MolPicklerException(
2016
0
              "Bad pickle format: ATOM_DUMMYLABEL tag not found.");
2017
0
        }
2018
0
        std::string tmpStr;
2019
0
        streamRead(ss, tmpStr, version);
2020
0
        atom->setProp(common_properties::dummyLabel, tmpStr);
2021
0
      }
2022
12.9k
    }
2023
12.9k
  }
2024
431k
  if (version >= 7020) {
2025
12.9k
    if (hasMonomerInfo) {
2026
1.59k
      streamRead(ss, tag, version);
2027
1.59k
      if (tag == BEGIN_PDB_RESIDUE) {
2028
1.59k
        atom->setMonomerInfo(unpickleAtomPDBResidueInfo(ss, version));
2029
1.59k
      } else if (tag == BEGIN_ATOM_MONOMER_INFO) {
2030
0
        atom->setMonomerInfo(unpickleAtomMonomerInfo(ss, version));
2031
3
      } else {
2032
3
        throw MolPicklerException(
2033
3
            "Bad pickle format: BEGIN_PDB_RESIDUE or BEGIN_ATOM_MONOMER_INFO tag not found.");
2034
3
      }
2035
1.59k
    }
2036
12.9k
  }
2037
431k
  mol->addAtom(atom, false, true);
2038
431k
  return atom;
2039
431k
}
RDKit::Atom* RDKit::MolPickler::_addAtomFromPickle<unsigned char>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, RDGeom::Point3D&, int, bool)
Line
Count
Source
1866
6
                                     RDGeom::Point3D &pos, int version, bool) {
1867
6
  PRECONDITION(mol, "empty molecule");
1868
6
  float x, y, z;
1869
6
  char tmpChar;
1870
6
  unsigned char tmpUchar;
1871
6
  signed char tmpSchar;
1872
6
  char flags;
1873
6
  Tags tag;
1874
6
  Atom *atom = nullptr;
1875
6
  int atomicNum = 0;
1876
1877
6
  streamRead(ss, tmpUchar, version);
1878
6
  atomicNum = tmpUchar;
1879
1880
6
  bool hasQuery = false;
1881
6
  streamRead(ss, flags, version);
1882
6
  if (version > 5000) {
1883
5
    hasQuery = flags & 0x1 << 4;
1884
5
  }
1885
6
  if (!hasQuery) {
1886
3
    atom = new Atom(atomicNum);
1887
3
  } else {
1888
3
    atom = new QueryAtom();
1889
3
    if (atomicNum) {
1890
      // can't set this in the constructor because that builds a
1891
      // query and we're going to take care of that later:
1892
3
      atom->setAtomicNum(atomicNum);
1893
3
    }
1894
3
  }
1895
6
  atom->setIsAromatic(flags & 0x1 << 6);
1896
6
  atom->setNoImplicit(flags & 0x1 << 5);
1897
1898
6
  bool hasAtomMap = 0, hasDummyLabel = 0;
1899
6
  if (version >= 6020) {
1900
5
    hasAtomMap = flags & 0x1 << 3;
1901
5
    hasDummyLabel = flags & 0x1 << 2;
1902
5
  }
1903
6
  bool hasMonomerInfo = 0;
1904
6
  if (version >= 7020) {
1905
5
    hasMonomerInfo = flags & 0x1 << 1;
1906
5
  }
1907
1908
  // are coordinates present?
1909
6
  if (flags & 0x1 << 7) {
1910
0
    streamRead(ss, x, version);
1911
0
    pos.x = static_cast<double>(x);
1912
0
    streamRead(ss, y, version);
1913
0
    pos.y = static_cast<double>(y);
1914
0
    streamRead(ss, z, version);
1915
0
    pos.z = static_cast<double>(z);
1916
0
  }
1917
1918
6
  if (version <= 5000 || !hasQuery) {
1919
3
    if (version < 7000) {
1920
1
      if (version < 6030) {
1921
1
        streamRead(ss, tmpSchar, version);
1922
        // FIX: technically should be handling this in order to maintain true
1923
        // backwards compatibility
1924
        // atom->setMass(PeriodicTable::getTable()->getAtomicWeight(atom->getAtomicNum())+
1925
        //              static_cast<int>(tmpSchar));
1926
1
      } else {
1927
0
        float tmpFloat;
1928
0
        streamRead(ss, tmpFloat, version);
1929
        // FIX: technically should be handling this in order to maintain true
1930
        // backwards compatibility
1931
        // atom->setMass(tmpFloat);
1932
0
      }
1933
1934
1
      streamRead(ss, tmpSchar, version);
1935
1
      atom->setFormalCharge(static_cast<int>(tmpSchar));
1936
1937
1
      streamRead(ss, tmpChar, version);
1938
1
      atom->setChiralTag(static_cast<Atom::ChiralType>(tmpChar));
1939
1
      streamRead(ss, tmpChar, version);
1940
1
      atom->setHybridization(static_cast<Atom::HybridizationType>(tmpChar));
1941
1
      streamRead(ss, tmpChar, version);
1942
1
      atom->setNumExplicitHs(static_cast<int>(tmpChar));
1943
1
      streamRead(ss, tmpChar, version);
1944
1
      atom->d_explicitValence = tmpChar;
1945
1
      streamRead(ss, tmpChar, version);
1946
1
      atom->d_implicitValence = tmpChar;
1947
1
      if (version > 6000) {
1948
0
        streamRead(ss, tmpChar, version);
1949
0
        atom->d_numRadicalElectrons = static_cast<unsigned int>(tmpChar);
1950
0
      }
1951
2
    } else {
1952
2
      _unpickleAtomData(ss, atom, version);
1953
2
    }
1954
1955
3
  } else if (version > 5000) {
1956
    // we have a query
1957
3
    if (version >= 9000) {
1958
3
      _unpickleAtomData(ss, atom, version);
1959
3
    }
1960
3
    streamRead(ss, tag, version);
1961
3
    if (tag != BEGINQUERY) {
1962
0
      throw MolPicklerException("Bad pickle format: BEGINQUERY tag not found.");
1963
0
    }
1964
3
    static_cast<QueryAtom *>(atom)->setQuery(unpickleQuery(ss, atom, version));
1965
3
    streamRead(ss, tag, version);
1966
3
    if (tag != ENDQUERY) {
1967
0
      throw MolPicklerException("Bad pickle format: ENDQUERY tag not found.");
1968
0
    }
1969
    // atom->setNumExplicitHs(0);
1970
3
  }
1971
1972
6
  if (version > 5000) {
1973
2
    if (version < 6020) {
1974
0
      unsigned int sPos = rdcast<unsigned int>(ss.tellg());
1975
0
      Tags tag;
1976
0
      streamRead(ss, tag, version);
1977
0
      if (tag == ATOM_MAPNUMBER) {
1978
0
        int32_t tmpInt;
1979
0
        streamRead(ss, tmpChar, version);
1980
0
        tmpInt = tmpChar;
1981
0
        atom->setProp(common_properties::molAtomMapNumber, tmpInt);
1982
0
      } else {
1983
0
        ss.seekg(sPos);
1984
0
      }
1985
2
    } else {
1986
2
      if (hasAtomMap) {
1987
0
        Tags tag;
1988
0
        streamRead(ss, tag, version);
1989
0
        if (tag != ATOM_MAPNUMBER) {
1990
0
          throw MolPicklerException(
1991
0
              "Bad pickle format: ATOM_MAPNUMBER tag not found.");
1992
0
        }
1993
0
        int tmpInt;
1994
0
        streamRead(ss, tmpChar, version);
1995
        // the test for tmpChar below seems redundant, but on at least
1996
        // the POWER8 architecture it seems that chars may be unsigned
1997
        // by default.
1998
0
#ifdef __GNUC__
1999
0
#pragma GCC diagnostic push
2000
0
#pragma GCC diagnostic ignored "-Wtype-limits"
2001
0
#endif
2002
0
        if ((tmpChar < 0 || tmpChar > 127) && version > 9000) {
2003
0
#ifdef __GNUC__
2004
0
#pragma GCC diagnostic pop
2005
0
#endif
2006
0
          streamRead(ss, tmpInt, version);
2007
0
        } else {
2008
0
          tmpInt = tmpChar;
2009
0
        }
2010
0
        atom->setProp(common_properties::molAtomMapNumber, tmpInt);
2011
0
      }
2012
2
      if (hasDummyLabel) {
2013
0
        streamRead(ss, tag, version);
2014
0
        if (tag != ATOM_DUMMYLABEL) {
2015
0
          throw MolPicklerException(
2016
0
              "Bad pickle format: ATOM_DUMMYLABEL tag not found.");
2017
0
        }
2018
0
        std::string tmpStr;
2019
0
        streamRead(ss, tmpStr, version);
2020
0
        atom->setProp(common_properties::dummyLabel, tmpStr);
2021
0
      }
2022
2
    }
2023
2
  }
2024
6
  if (version >= 7020) {
2025
2
    if (hasMonomerInfo) {
2026
0
      streamRead(ss, tag, version);
2027
0
      if (tag == BEGIN_PDB_RESIDUE) {
2028
0
        atom->setMonomerInfo(unpickleAtomPDBResidueInfo(ss, version));
2029
0
      } else if (tag == BEGIN_ATOM_MONOMER_INFO) {
2030
0
        atom->setMonomerInfo(unpickleAtomMonomerInfo(ss, version));
2031
0
      } else {
2032
0
        throw MolPicklerException(
2033
0
            "Bad pickle format: BEGIN_PDB_RESIDUE or BEGIN_ATOM_MONOMER_INFO tag not found.");
2034
0
      }
2035
0
    }
2036
2
  }
2037
6
  mol->addAtom(atom, false, true);
2038
6
  return atom;
2039
6
}
2040
2041
//--------------------------------------
2042
//
2043
//            Bonds
2044
//
2045
//--------------------------------------
2046
2047
template <typename T>
2048
void MolPickler::_pickleBond(std::ostream &ss, const Bond *bond,
2049
0
                             std::map<int, int> &atomIdxMap) {
2050
0
  PRECONDITION(bond, "empty bond");
2051
0
  T tmpT;
2052
0
  char tmpChar;
2053
0
  char flags;
2054
2055
0
  tmpT = static_cast<T>(atomIdxMap[bond->getBeginAtomIdx()]);
2056
0
  streamWrite(ss, tmpT);
2057
0
  tmpT = static_cast<T>(atomIdxMap[bond->getEndAtomIdx()]);
2058
0
  streamWrite(ss, tmpT);
2059
2060
0
  flags = 0;
2061
0
  if (bond->getIsAromatic()) {
2062
0
    flags |= 0x1 << 6;
2063
0
  }
2064
0
  if (bond->getIsConjugated()) {
2065
0
    flags |= 0x1 << 5;
2066
0
  }
2067
0
  if (bond->hasQuery()) {
2068
0
    flags |= 0x1 << 4;
2069
0
  }
2070
0
  if (bond->getBondType() != Bond::SINGLE) {
2071
0
    flags |= 0x1 << 3;
2072
0
  }
2073
0
  if (bond->getBondDir() != Bond::NONE) {
2074
0
    flags |= 0x1 << 2;
2075
0
  }
2076
0
  if (bond->getStereo() != Bond::STEREONONE) {
2077
0
    flags |= 0x1 << 1;
2078
0
  }
2079
0
  std::string endpts;
2080
0
  if (bond->getPropIfPresent(common_properties::_MolFileBondEndPts, endpts)) {
2081
0
    flags |= 0x1;
2082
0
  }
2083
0
  streamWrite(ss, flags);
2084
2085
0
  if (bond->getBondType() != Bond::SINGLE) {
2086
0
    tmpChar = static_cast<char>(bond->getBondType());
2087
0
    streamWrite(ss, tmpChar);
2088
0
  }
2089
0
  if (bond->getBondDir() != Bond::NONE) {
2090
0
    tmpChar = static_cast<char>(bond->getBondDir());
2091
0
    streamWrite(ss, tmpChar);
2092
0
  }
2093
2094
  // write info about the stereochemistry:
2095
0
  if (bond->getStereo() != Bond::STEREONONE) {
2096
0
    tmpChar = static_cast<char>(bond->getStereo());
2097
0
    streamWrite(ss, tmpChar);
2098
0
    const INT_VECT &stereoAts = bond->getStereoAtoms();
2099
0
    tmpChar = rdcast<unsigned int>(stereoAts.size());
2100
0
    streamWrite(ss, tmpChar);
2101
0
    for (int stereoAt : stereoAts) {
2102
0
      tmpT = static_cast<T>(stereoAt);
2103
0
      streamWrite(ss, tmpT);
2104
0
    }
2105
0
  }
2106
0
  if (bond->hasQuery()) {
2107
0
    streamWrite(ss, BEGINQUERY);
2108
0
    pickleQuery(ss, static_cast<const QueryBond *>(bond)->getQuery());
2109
0
    streamWrite(ss, ENDQUERY);
2110
0
  }
2111
0
  if (!endpts.empty()) {
2112
0
    streamWrite(ss, endpts);
2113
0
    std::string attach = "ALL";
2114
0
    bond->getPropIfPresent(common_properties::_MolFileBondAttach, attach);
2115
0
    streamWrite(ss, attach);
2116
0
  }
2117
0
}
Unexecuted instantiation: void RDKit::MolPickler::_pickleBond<int>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::Bond const*, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&)
Unexecuted instantiation: void RDKit::MolPickler::_pickleBond<unsigned char>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::Bond const*, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&)
2118
2119
template <typename T>
2120
Bond *MolPickler::_addBondFromPickle(std::istream &ss, ROMol *mol, int version,
2121
22
                                     bool directMap) {
2122
22
  PRECONDITION(mol, "empty molecule");
2123
22
  char tmpChar;
2124
22
  char flags;
2125
22
  int begIdx, endIdx;
2126
22
  T tmpT;
2127
2128
22
  Bond *bond = nullptr;
2129
22
  streamRead(ss, tmpT, version);
2130
22
  if (directMap) {
2131
22
    begIdx = tmpT;
2132
22
  } else {
2133
0
    begIdx = mol->getAtomWithBookmark(static_cast<int>(tmpT))->getIdx();
2134
0
  }
2135
22
  streamRead(ss, tmpT, version);
2136
22
  if (directMap) {
2137
22
    endIdx = tmpT;
2138
2139
22
  } else {
2140
0
    endIdx = mol->getAtomWithBookmark(static_cast<int>(tmpT))->getIdx();
2141
0
  }
2142
22
  streamRead(ss, flags, version);
2143
22
  bool hasQuery = flags & 0x1 << 4;
2144
2145
22
  if (version <= 5000 || (version <= 7000 && !hasQuery) || version > 7000) {
2146
22
    bond = new Bond();
2147
22
    bond->setIsAromatic(flags & 0x1 << 6);
2148
22
    bond->setIsConjugated(flags & 0x1 << 5);
2149
2150
22
    if (version < 7000) {
2151
4
      streamReadPositiveChar(ss, tmpChar, version);
2152
4
      bond->setBondType(static_cast<Bond::BondType>(tmpChar));
2153
4
      streamReadPositiveChar(ss, tmpChar, version);
2154
4
      bond->setBondDir(static_cast<Bond::BondDir>(tmpChar));
2155
2156
4
      if (version > 3000) {
2157
4
        streamReadPositiveChar(ss, tmpChar, version);
2158
4
        auto stereo = static_cast<Bond::BondStereo>(tmpChar);
2159
4
        bond->setStereo(stereo);
2160
4
        if (stereo != Bond::STEREONONE) {
2161
1
          streamRead(ss, tmpChar, version);
2162
27
          for (char i = 0; i < tmpChar; ++i) {
2163
26
            streamRead(ss, tmpT, version);
2164
26
            bond->getStereoAtoms().push_back(static_cast<int>(tmpT));
2165
26
          }
2166
1
        }
2167
4
      }
2168
18
    } else {
2169
18
      if (flags & (0x1 << 3)) {
2170
0
        streamReadPositiveChar(ss, tmpChar, version);
2171
0
        bond->setBondType(static_cast<Bond::BondType>(tmpChar));
2172
18
      } else {
2173
18
        bond->setBondType(Bond::SINGLE);
2174
18
      }
2175
2176
18
      if (flags & (0x1 << 2)) {
2177
0
        streamReadPositiveChar(ss, tmpChar, version);
2178
0
        bond->setBondDir(static_cast<Bond::BondDir>(tmpChar));
2179
18
      } else {
2180
18
        bond->setBondDir(Bond::NONE);
2181
18
      }
2182
2183
18
      if (flags & (0x1 << 1)) {
2184
0
        streamReadPositiveChar(ss, tmpChar, version);
2185
0
        auto stereo = static_cast<Bond::BondStereo>(tmpChar);
2186
0
        streamRead(ss, tmpChar, version);
2187
0
        for (char i = 0; i < tmpChar; ++i) {
2188
0
          streamRead(ss, tmpT, version);
2189
0
          bond->getStereoAtoms().push_back(static_cast<int>(tmpT));
2190
0
        }
2191
0
        bond->setStereo(stereo);
2192
18
      } else {
2193
18
        bond->setStereo(Bond::STEREONONE);
2194
18
      }
2195
18
      if (flags & 0x1) {
2196
0
        std::string tmpStr;
2197
0
        streamRead(ss, tmpStr, version);
2198
0
        bond->setProp(common_properties::_MolFileBondEndPts, tmpStr);
2199
0
        streamRead(ss, tmpStr, version);
2200
0
        bond->setProp(common_properties::_MolFileBondAttach, tmpStr);
2201
0
      }
2202
18
    }
2203
22
  }
2204
22
  if (version > 5000 && hasQuery) {
2205
5
    Tags tag;
2206
5
    if (bond) {
2207
5
      Bond *tbond = bond;
2208
5
      bond = new QueryBond(*bond);
2209
5
      delete tbond;
2210
5
    } else {
2211
0
      bond = new QueryBond();
2212
0
    }
2213
2214
    // we have a query:
2215
5
    streamRead(ss, tag, version);
2216
5
    if (tag != BEGINQUERY) {
2217
0
      delete bond;
2218
0
      throw MolPicklerException("Bad pickle format: BEGINQUERY tag not found.");
2219
0
    }
2220
5
    static_cast<QueryBond *>(bond)->setQuery(unpickleQuery(ss, bond, version));
2221
5
    streamRead(ss, tag, version);
2222
5
    if (tag != ENDQUERY) {
2223
0
      delete bond;
2224
0
      throw MolPicklerException("Bad pickle format: ENDQUERY tag not found.");
2225
0
    }
2226
5
  }
2227
22
  if (bond) {
2228
17
    bond->setBeginAtomIdx(begIdx);
2229
17
    bond->setEndAtomIdx(endIdx);
2230
17
    mol->addBond(bond, true);
2231
17
  }
2232
22
  return bond;
2233
22
}
RDKit::Bond* RDKit::MolPickler::_addBondFromPickle<int>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, int, bool)
Line
Count
Source
2121
17
                                     bool directMap) {
2122
17
  PRECONDITION(mol, "empty molecule");
2123
17
  char tmpChar;
2124
17
  char flags;
2125
17
  int begIdx, endIdx;
2126
17
  T tmpT;
2127
2128
17
  Bond *bond = nullptr;
2129
17
  streamRead(ss, tmpT, version);
2130
17
  if (directMap) {
2131
17
    begIdx = tmpT;
2132
17
  } else {
2133
0
    begIdx = mol->getAtomWithBookmark(static_cast<int>(tmpT))->getIdx();
2134
0
  }
2135
17
  streamRead(ss, tmpT, version);
2136
17
  if (directMap) {
2137
17
    endIdx = tmpT;
2138
2139
17
  } else {
2140
0
    endIdx = mol->getAtomWithBookmark(static_cast<int>(tmpT))->getIdx();
2141
0
  }
2142
17
  streamRead(ss, flags, version);
2143
17
  bool hasQuery = flags & 0x1 << 4;
2144
2145
17
  if (version <= 5000 || (version <= 7000 && !hasQuery) || version > 7000) {
2146
17
    bond = new Bond();
2147
17
    bond->setIsAromatic(flags & 0x1 << 6);
2148
17
    bond->setIsConjugated(flags & 0x1 << 5);
2149
2150
17
    if (version < 7000) {
2151
4
      streamReadPositiveChar(ss, tmpChar, version);
2152
4
      bond->setBondType(static_cast<Bond::BondType>(tmpChar));
2153
4
      streamReadPositiveChar(ss, tmpChar, version);
2154
4
      bond->setBondDir(static_cast<Bond::BondDir>(tmpChar));
2155
2156
4
      if (version > 3000) {
2157
4
        streamReadPositiveChar(ss, tmpChar, version);
2158
4
        auto stereo = static_cast<Bond::BondStereo>(tmpChar);
2159
4
        bond->setStereo(stereo);
2160
4
        if (stereo != Bond::STEREONONE) {
2161
1
          streamRead(ss, tmpChar, version);
2162
27
          for (char i = 0; i < tmpChar; ++i) {
2163
26
            streamRead(ss, tmpT, version);
2164
26
            bond->getStereoAtoms().push_back(static_cast<int>(tmpT));
2165
26
          }
2166
1
        }
2167
4
      }
2168
13
    } else {
2169
13
      if (flags & (0x1 << 3)) {
2170
0
        streamReadPositiveChar(ss, tmpChar, version);
2171
0
        bond->setBondType(static_cast<Bond::BondType>(tmpChar));
2172
13
      } else {
2173
13
        bond->setBondType(Bond::SINGLE);
2174
13
      }
2175
2176
13
      if (flags & (0x1 << 2)) {
2177
0
        streamReadPositiveChar(ss, tmpChar, version);
2178
0
        bond->setBondDir(static_cast<Bond::BondDir>(tmpChar));
2179
13
      } else {
2180
13
        bond->setBondDir(Bond::NONE);
2181
13
      }
2182
2183
13
      if (flags & (0x1 << 1)) {
2184
0
        streamReadPositiveChar(ss, tmpChar, version);
2185
0
        auto stereo = static_cast<Bond::BondStereo>(tmpChar);
2186
0
        streamRead(ss, tmpChar, version);
2187
0
        for (char i = 0; i < tmpChar; ++i) {
2188
0
          streamRead(ss, tmpT, version);
2189
0
          bond->getStereoAtoms().push_back(static_cast<int>(tmpT));
2190
0
        }
2191
0
        bond->setStereo(stereo);
2192
13
      } else {
2193
13
        bond->setStereo(Bond::STEREONONE);
2194
13
      }
2195
13
      if (flags & 0x1) {
2196
0
        std::string tmpStr;
2197
0
        streamRead(ss, tmpStr, version);
2198
0
        bond->setProp(common_properties::_MolFileBondEndPts, tmpStr);
2199
0
        streamRead(ss, tmpStr, version);
2200
0
        bond->setProp(common_properties::_MolFileBondAttach, tmpStr);
2201
0
      }
2202
13
    }
2203
17
  }
2204
17
  if (version > 5000 && hasQuery) {
2205
0
    Tags tag;
2206
0
    if (bond) {
2207
0
      Bond *tbond = bond;
2208
0
      bond = new QueryBond(*bond);
2209
0
      delete tbond;
2210
0
    } else {
2211
0
      bond = new QueryBond();
2212
0
    }
2213
2214
    // we have a query:
2215
0
    streamRead(ss, tag, version);
2216
0
    if (tag != BEGINQUERY) {
2217
0
      delete bond;
2218
0
      throw MolPicklerException("Bad pickle format: BEGINQUERY tag not found.");
2219
0
    }
2220
0
    static_cast<QueryBond *>(bond)->setQuery(unpickleQuery(ss, bond, version));
2221
0
    streamRead(ss, tag, version);
2222
0
    if (tag != ENDQUERY) {
2223
0
      delete bond;
2224
0
      throw MolPicklerException("Bad pickle format: ENDQUERY tag not found.");
2225
0
    }
2226
0
  }
2227
17
  if (bond) {
2228
17
    bond->setBeginAtomIdx(begIdx);
2229
17
    bond->setEndAtomIdx(endIdx);
2230
17
    mol->addBond(bond, true);
2231
17
  }
2232
17
  return bond;
2233
17
}
RDKit::Bond* RDKit::MolPickler::_addBondFromPickle<unsigned char>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, int, bool)
Line
Count
Source
2121
5
                                     bool directMap) {
2122
5
  PRECONDITION(mol, "empty molecule");
2123
5
  char tmpChar;
2124
5
  char flags;
2125
5
  int begIdx, endIdx;
2126
5
  T tmpT;
2127
2128
5
  Bond *bond = nullptr;
2129
5
  streamRead(ss, tmpT, version);
2130
5
  if (directMap) {
2131
5
    begIdx = tmpT;
2132
5
  } else {
2133
0
    begIdx = mol->getAtomWithBookmark(static_cast<int>(tmpT))->getIdx();
2134
0
  }
2135
5
  streamRead(ss, tmpT, version);
2136
5
  if (directMap) {
2137
5
    endIdx = tmpT;
2138
2139
5
  } else {
2140
0
    endIdx = mol->getAtomWithBookmark(static_cast<int>(tmpT))->getIdx();
2141
0
  }
2142
5
  streamRead(ss, flags, version);
2143
5
  bool hasQuery = flags & 0x1 << 4;
2144
2145
5
  if (version <= 5000 || (version <= 7000 && !hasQuery) || version > 7000) {
2146
5
    bond = new Bond();
2147
5
    bond->setIsAromatic(flags & 0x1 << 6);
2148
5
    bond->setIsConjugated(flags & 0x1 << 5);
2149
2150
5
    if (version < 7000) {
2151
0
      streamReadPositiveChar(ss, tmpChar, version);
2152
0
      bond->setBondType(static_cast<Bond::BondType>(tmpChar));
2153
0
      streamReadPositiveChar(ss, tmpChar, version);
2154
0
      bond->setBondDir(static_cast<Bond::BondDir>(tmpChar));
2155
2156
0
      if (version > 3000) {
2157
0
        streamReadPositiveChar(ss, tmpChar, version);
2158
0
        auto stereo = static_cast<Bond::BondStereo>(tmpChar);
2159
0
        bond->setStereo(stereo);
2160
0
        if (stereo != Bond::STEREONONE) {
2161
0
          streamRead(ss, tmpChar, version);
2162
0
          for (char i = 0; i < tmpChar; ++i) {
2163
0
            streamRead(ss, tmpT, version);
2164
0
            bond->getStereoAtoms().push_back(static_cast<int>(tmpT));
2165
0
          }
2166
0
        }
2167
0
      }
2168
5
    } else {
2169
5
      if (flags & (0x1 << 3)) {
2170
0
        streamReadPositiveChar(ss, tmpChar, version);
2171
0
        bond->setBondType(static_cast<Bond::BondType>(tmpChar));
2172
5
      } else {
2173
5
        bond->setBondType(Bond::SINGLE);
2174
5
      }
2175
2176
5
      if (flags & (0x1 << 2)) {
2177
0
        streamReadPositiveChar(ss, tmpChar, version);
2178
0
        bond->setBondDir(static_cast<Bond::BondDir>(tmpChar));
2179
5
      } else {
2180
5
        bond->setBondDir(Bond::NONE);
2181
5
      }
2182
2183
5
      if (flags & (0x1 << 1)) {
2184
0
        streamReadPositiveChar(ss, tmpChar, version);
2185
0
        auto stereo = static_cast<Bond::BondStereo>(tmpChar);
2186
0
        streamRead(ss, tmpChar, version);
2187
0
        for (char i = 0; i < tmpChar; ++i) {
2188
0
          streamRead(ss, tmpT, version);
2189
0
          bond->getStereoAtoms().push_back(static_cast<int>(tmpT));
2190
0
        }
2191
0
        bond->setStereo(stereo);
2192
5
      } else {
2193
5
        bond->setStereo(Bond::STEREONONE);
2194
5
      }
2195
5
      if (flags & 0x1) {
2196
0
        std::string tmpStr;
2197
0
        streamRead(ss, tmpStr, version);
2198
0
        bond->setProp(common_properties::_MolFileBondEndPts, tmpStr);
2199
0
        streamRead(ss, tmpStr, version);
2200
0
        bond->setProp(common_properties::_MolFileBondAttach, tmpStr);
2201
0
      }
2202
5
    }
2203
5
  }
2204
5
  if (version > 5000 && hasQuery) {
2205
5
    Tags tag;
2206
5
    if (bond) {
2207
5
      Bond *tbond = bond;
2208
5
      bond = new QueryBond(*bond);
2209
5
      delete tbond;
2210
5
    } else {
2211
0
      bond = new QueryBond();
2212
0
    }
2213
2214
    // we have a query:
2215
5
    streamRead(ss, tag, version);
2216
5
    if (tag != BEGINQUERY) {
2217
0
      delete bond;
2218
0
      throw MolPicklerException("Bad pickle format: BEGINQUERY tag not found.");
2219
0
    }
2220
5
    static_cast<QueryBond *>(bond)->setQuery(unpickleQuery(ss, bond, version));
2221
5
    streamRead(ss, tag, version);
2222
5
    if (tag != ENDQUERY) {
2223
0
      delete bond;
2224
0
      throw MolPicklerException("Bad pickle format: ENDQUERY tag not found.");
2225
0
    }
2226
5
  }
2227
5
  if (bond) {
2228
0
    bond->setBeginAtomIdx(begIdx);
2229
0
    bond->setEndAtomIdx(endIdx);
2230
0
    mol->addBond(bond, true);
2231
0
  }
2232
5
  return bond;
2233
5
}
2234
2235
//--------------------------------------
2236
//
2237
//            Rings
2238
//
2239
//--------------------------------------
2240
template <typename T>
2241
void MolPickler::_pickleSSSR(std::ostream &ss, const RingInfo *ringInfo,
2242
0
                             std::map<int, int> &atomIdxMap) {
2243
0
  PRECONDITION(ringInfo, "missing ring info");
2244
0
  std::uint32_t nrings = ringInfo->numRings();
2245
0
  streamWrite(ss, nrings);
2246
0
  for (unsigned int i = 0; i < ringInfo->numRings(); i++) {
2247
0
    INT_VECT ring;
2248
0
    ring = ringInfo->atomRings()[i];
2249
0
    T tmpT = static_cast<T>(ring.size());
2250
0
    streamWrite(ss, tmpT);
2251
0
    for (int &j : ring) {
2252
0
      tmpT = static_cast<T>(atomIdxMap[j]);
2253
0
      streamWrite(ss, tmpT);
2254
0
    }
2255
0
  }
2256
0
}
Unexecuted instantiation: void RDKit::MolPickler::_pickleSSSR<int>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::RingInfo const*, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&)
Unexecuted instantiation: void RDKit::MolPickler::_pickleSSSR<unsigned char>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::RingInfo const*, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&)
2257
2258
template <typename T>
2259
void MolPickler::_addRingInfoFromPickle(std::istream &ss, ROMol *mol,
2260
                                        int version, bool directMap,
2261
26
                                        FIND_RING_TYPE ringType) {
2262
26
  PRECONDITION(mol, "empty molecule");
2263
26
  RingInfo *ringInfo = mol->getRingInfo();
2264
  // if (!ringInfo->isInitialized()) {
2265
26
  ringInfo->initialize(ringType);
2266
  //}
2267
2268
26
  std::uint32_t numRings;
2269
26
  if (version >= 13002) {
2270
0
    streamRead(ss, numRings, version);
2271
26
  } else {
2272
26
    T tmpV;
2273
26
    streamRead(ss, tmpV, version);
2274
26
    numRings = tmpV;
2275
26
  }
2276
2277
26
  if (numRings > 0) {
2278
25
    ringInfo->preallocate(mol->getNumAtoms(), mol->getNumBonds());
2279
11.8k
    for (unsigned int i = 0; i < static_cast<unsigned int>(numRings); i++) {
2280
11.8k
      T tmpT;
2281
11.8k
      T ringSize;
2282
11.8k
      streamRead(ss, ringSize, version);
2283
11.8k
      if (ringSize < 0) {
2284
8
        throw MolPicklerException("negative ring size");
2285
8
      }
2286
11.8k
      INT_VECT atoms(static_cast<int>(ringSize));
2287
11.8k
      INT_VECT bonds(static_cast<int>(ringSize));
2288
13.2k
      for (unsigned int j = 0; j < static_cast<unsigned int>(ringSize); j++) {
2289
1.40k
        streamRead(ss, tmpT, version);
2290
1.40k
        if (directMap) {
2291
1.40k
          atoms[j] = static_cast<int>(tmpT);
2292
1.40k
          if (atoms[j] < 0 ||
2293
1.40k
              static_cast<unsigned int>(atoms[j]) >= mol->getNumAtoms()) {
2294
13
            throw MolPicklerException("ring-atom index out of range");
2295
13
          }
2296
1.40k
        } else {
2297
1
          atoms[j] = mol->getAtomWithBookmark(static_cast<int>(tmpT))->getIdx();
2298
1
        }
2299
1.40k
      }
2300
11.8k
      if (version < 7000) {
2301
11.8k
        for (unsigned int j = 0; j < static_cast<unsigned int>(ringSize); j++) {
2302
2
          streamRead(ss, tmpT, version);
2303
2
          if (directMap) {
2304
2
            bonds[j] = static_cast<int>(tmpT);
2305
2
            if (bonds[j] < 0 ||
2306
2
                static_cast<unsigned int>(bonds[j]) >= mol->getNumBonds()) {
2307
2
              throw MolPicklerException("ring-bond index out of range");
2308
2
            }
2309
2310
2
          } else {
2311
0
            bonds[j] =
2312
0
                mol->getBondWithBookmark(static_cast<int>(tmpT))->getIdx();
2313
0
          }
2314
2
        }
2315
11.8k
      } else {
2316
1
        for (unsigned int j = 1; j < static_cast<unsigned int>(ringSize); ++j) {
2317
0
          bonds[j - 1] =
2318
0
              mol->getBondBetweenAtoms(atoms[j - 1], atoms[j])->getIdx();
2319
0
        }
2320
1
        bonds[ringSize - 1] =
2321
1
            mol->getBondBetweenAtoms(atoms[0], atoms[ringSize - 1])->getIdx();
2322
1
      }
2323
11.8k
      ringInfo->addRing(atoms, bonds);
2324
11.8k
    }
2325
25
  }
2326
26
}
void RDKit::MolPickler::_addRingInfoFromPickle<int>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, int, bool, RDKit::FIND_RING_TYPE)
Line
Count
Source
2261
26
                                        FIND_RING_TYPE ringType) {
2262
26
  PRECONDITION(mol, "empty molecule");
2263
26
  RingInfo *ringInfo = mol->getRingInfo();
2264
  // if (!ringInfo->isInitialized()) {
2265
26
  ringInfo->initialize(ringType);
2266
  //}
2267
2268
26
  std::uint32_t numRings;
2269
26
  if (version >= 13002) {
2270
0
    streamRead(ss, numRings, version);
2271
26
  } else {
2272
26
    T tmpV;
2273
26
    streamRead(ss, tmpV, version);
2274
26
    numRings = tmpV;
2275
26
  }
2276
2277
26
  if (numRings > 0) {
2278
25
    ringInfo->preallocate(mol->getNumAtoms(), mol->getNumBonds());
2279
11.8k
    for (unsigned int i = 0; i < static_cast<unsigned int>(numRings); i++) {
2280
11.8k
      T tmpT;
2281
11.8k
      T ringSize;
2282
11.8k
      streamRead(ss, ringSize, version);
2283
11.8k
      if (ringSize < 0) {
2284
8
        throw MolPicklerException("negative ring size");
2285
8
      }
2286
11.8k
      INT_VECT atoms(static_cast<int>(ringSize));
2287
11.8k
      INT_VECT bonds(static_cast<int>(ringSize));
2288
13.2k
      for (unsigned int j = 0; j < static_cast<unsigned int>(ringSize); j++) {
2289
1.40k
        streamRead(ss, tmpT, version);
2290
1.40k
        if (directMap) {
2291
1.40k
          atoms[j] = static_cast<int>(tmpT);
2292
1.40k
          if (atoms[j] < 0 ||
2293
1.40k
              static_cast<unsigned int>(atoms[j]) >= mol->getNumAtoms()) {
2294
13
            throw MolPicklerException("ring-atom index out of range");
2295
13
          }
2296
1.40k
        } else {
2297
1
          atoms[j] = mol->getAtomWithBookmark(static_cast<int>(tmpT))->getIdx();
2298
1
        }
2299
1.40k
      }
2300
11.8k
      if (version < 7000) {
2301
11.8k
        for (unsigned int j = 0; j < static_cast<unsigned int>(ringSize); j++) {
2302
2
          streamRead(ss, tmpT, version);
2303
2
          if (directMap) {
2304
2
            bonds[j] = static_cast<int>(tmpT);
2305
2
            if (bonds[j] < 0 ||
2306
2
                static_cast<unsigned int>(bonds[j]) >= mol->getNumBonds()) {
2307
2
              throw MolPicklerException("ring-bond index out of range");
2308
2
            }
2309
2310
2
          } else {
2311
0
            bonds[j] =
2312
0
                mol->getBondWithBookmark(static_cast<int>(tmpT))->getIdx();
2313
0
          }
2314
2
        }
2315
11.8k
      } else {
2316
1
        for (unsigned int j = 1; j < static_cast<unsigned int>(ringSize); ++j) {
2317
0
          bonds[j - 1] =
2318
0
              mol->getBondBetweenAtoms(atoms[j - 1], atoms[j])->getIdx();
2319
0
        }
2320
1
        bonds[ringSize - 1] =
2321
1
            mol->getBondBetweenAtoms(atoms[0], atoms[ringSize - 1])->getIdx();
2322
1
      }
2323
11.8k
      ringInfo->addRing(atoms, bonds);
2324
11.8k
    }
2325
25
  }
2326
26
}
Unexecuted instantiation: void RDKit::MolPickler::_addRingInfoFromPickle<unsigned char>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, int, bool, RDKit::FIND_RING_TYPE)
2327
2328
//--------------------------------------
2329
//
2330
//            SubstanceGroups
2331
//
2332
//--------------------------------------
2333
2334
template <typename T>
2335
void MolPickler::_pickleSubstanceGroup(std::ostream &ss,
2336
                                       const SubstanceGroup &sgroup,
2337
                                       std::map<int, int> &atomIdxMap,
2338
0
                                       std::map<int, int> &bondIdxMap) {
2339
0
  T tmpT;
2340
2341
0
  streamWriteProps<std::uint16_t>(ss, sgroup);
2342
2343
0
  const auto &atoms = sgroup.getAtoms();
2344
0
  streamWrite(ss, static_cast<T>(atoms.size()));
2345
0
  for (const auto &atom : atoms) {
2346
0
    tmpT = static_cast<T>(atomIdxMap[atom]);
2347
0
    streamWrite(ss, tmpT);
2348
0
  }
2349
2350
0
  const auto &p_atoms = sgroup.getParentAtoms();
2351
0
  streamWrite(ss, static_cast<T>(p_atoms.size()));
2352
0
  for (const auto &p_atom : p_atoms) {
2353
0
    tmpT = static_cast<T>(atomIdxMap[p_atom]);
2354
0
    streamWrite(ss, tmpT);
2355
0
  }
2356
2357
0
  const auto &bonds = sgroup.getBonds();
2358
0
  streamWrite(ss, static_cast<T>(bonds.size()));
2359
0
  for (const auto &bond : bonds) {
2360
0
    tmpT = static_cast<T>(bondIdxMap[bond]);
2361
0
    streamWrite(ss, tmpT);
2362
0
  }
2363
2364
0
  const auto &brackets = sgroup.getBrackets();
2365
0
  streamWrite(ss, static_cast<T>(brackets.size()));
2366
0
  for (const auto &bracket : brackets) {
2367
    // 3 point per bracket; 3rd point and all z are zeros,
2368
    // but this might change in the future.
2369
0
    for (const auto &pt : bracket) {
2370
0
      float tmpFloat;
2371
0
      tmpFloat = static_cast<float>(pt.x);
2372
0
      streamWrite(ss, tmpFloat);
2373
0
      tmpFloat = static_cast<float>(pt.y);
2374
0
      streamWrite(ss, tmpFloat);
2375
0
      tmpFloat = static_cast<float>(pt.z);
2376
0
      streamWrite(ss, tmpFloat);
2377
0
    }
2378
0
  }
2379
2380
0
  const auto &cstates = sgroup.getCStates();
2381
0
  streamWrite(ss, static_cast<T>(cstates.size()));
2382
0
  for (const auto &cstate : cstates) {
2383
    // Bond
2384
0
    tmpT = static_cast<T>(bondIdxMap[cstate.bondIdx]);
2385
0
    streamWrite(ss, tmpT);
2386
2387
    // Vector -- existence depends on SubstanceGroup type
2388
0
    if ("SUP" == sgroup.getProp<std::string>("TYPE")) {
2389
0
      float tmpFloat;
2390
0
      tmpFloat = static_cast<float>(cstate.vector.x);
2391
0
      streamWrite(ss, tmpFloat);
2392
0
      tmpFloat = static_cast<float>(cstate.vector.y);
2393
0
      streamWrite(ss, tmpFloat);
2394
0
      tmpFloat = static_cast<float>(cstate.vector.z);
2395
0
      streamWrite(ss, tmpFloat);
2396
0
    }
2397
0
  }
2398
2399
0
  const auto &attachPoints = sgroup.getAttachPoints();
2400
0
  streamWrite(ss, static_cast<T>(attachPoints.size()));
2401
0
  for (const auto &attachPoint : attachPoints) {
2402
    // aIdx -- always present
2403
0
    tmpT = static_cast<T>(atomIdxMap[attachPoint.aIdx]);
2404
0
    streamWrite(ss, tmpT);
2405
2406
    // lvIdx -- may be -1 if not used (0 in spec)
2407
0
    auto tmpInt = -1;
2408
0
    if (attachPoint.lvIdx != -1) {
2409
0
      tmpInt = static_cast<signed int>(atomIdxMap[attachPoint.lvIdx]);
2410
0
    }
2411
0
    streamWrite(ss, tmpInt);
2412
2413
    // id -- may be blank
2414
0
    auto tmpS = static_cast<const std::string>(attachPoint.id);
2415
0
    streamWrite(ss, tmpS);
2416
0
  }
2417
0
}
Unexecuted instantiation: void RDKit::MolPickler::_pickleSubstanceGroup<int>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::SubstanceGroup const&, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&)
Unexecuted instantiation: void RDKit::MolPickler::_pickleSubstanceGroup<unsigned char>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, RDKit::SubstanceGroup const&, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&)
2418
2419
template <typename T>
2420
SubstanceGroup MolPickler::_getSubstanceGroupFromPickle(std::istream &ss,
2421
                                                        ROMol *mol,
2422
47.6k
                                                        int version) {
2423
47.6k
  T tmpT;
2424
47.6k
  T numItems;
2425
47.6k
  float tmpFloat;
2426
47.6k
  int tmpInt = -1;
2427
47.6k
  std::string tmpS;
2428
2429
  // temporarily accept empty TYPE
2430
47.6k
  SubstanceGroup sgroup(mol, "");
2431
2432
  // Read RDProps, overriding ID, TYPE and COMPNO
2433
47.6k
  if (version >= 14000) {
2434
40.7k
    streamReadProps<std::uint16_t>(ss, sgroup,
2435
40.7k
                                   MolPickler::getCustomPropHandlers());
2436
40.7k
  } else {
2437
6.95k
    streamReadProps<unsigned int>(ss, sgroup,
2438
6.95k
                                  MolPickler::getCustomPropHandlers());
2439
6.95k
  }
2440
2441
47.6k
  streamRead(ss, numItems, version);
2442
50.4k
  for (int i = 0; i < numItems; ++i) {
2443
2.74k
    streamRead(ss, tmpT, version);
2444
2.74k
    sgroup.addAtomWithIdx(tmpT);
2445
2.74k
  }
2446
2447
47.6k
  streamRead(ss, numItems, version);
2448
48.0k
  for (int i = 0; i < numItems; ++i) {
2449
368
    streamRead(ss, tmpT, version);
2450
368
    sgroup.addParentAtomWithIdx(tmpT);
2451
368
  }
2452
2453
47.6k
  streamRead(ss, numItems, version);
2454
47.6k
  for (int i = 0; i < numItems; ++i) {
2455
6
    streamRead(ss, tmpT, version);
2456
6
    sgroup.addBondWithIdx(tmpT);
2457
6
  }
2458
2459
47.6k
  streamRead(ss, numItems, version);
2460
66.7k
  for (int i = 0; i < numItems; ++i) {
2461
19.0k
    SubstanceGroup::Bracket bracket;
2462
76.3k
    for (auto j = 0; j < 3; ++j) {
2463
57.2k
      streamRead(ss, tmpFloat, version);
2464
57.2k
      auto x = static_cast<double>(tmpFloat);
2465
57.2k
      streamRead(ss, tmpFloat, version);
2466
57.2k
      auto y = static_cast<double>(tmpFloat);
2467
57.2k
      streamRead(ss, tmpFloat, version);
2468
57.2k
      auto z = static_cast<double>(tmpFloat);
2469
57.2k
      bracket[j] = RDGeom::Point3D(x, y, z);
2470
57.2k
    }
2471
19.0k
    sgroup.addBracket(bracket);
2472
19.0k
  }
2473
2474
47.6k
  streamRead(ss, numItems, version);
2475
47.6k
  for (int i = 0; i < numItems; ++i) {
2476
5
    streamRead(ss, tmpT, version);
2477
5
    RDGeom::Point3D vector;
2478
2479
5
    if ("SUP" == sgroup.getProp<std::string>("TYPE")) {
2480
0
      streamRead(ss, tmpFloat, version);
2481
0
      vector.x = static_cast<double>(tmpFloat);
2482
0
      streamRead(ss, tmpFloat, version);
2483
0
      vector.y = static_cast<double>(tmpFloat);
2484
0
      streamRead(ss, tmpFloat, version);
2485
0
      vector.z = static_cast<double>(tmpFloat);
2486
0
    }
2487
2488
5
    sgroup.addCState(tmpT, vector);
2489
5
  }
2490
2491
47.6k
  streamRead(ss, numItems, version);
2492
58.8k
  for (int i = 0; i < numItems; ++i) {
2493
11.1k
    streamRead(ss, tmpT, version);
2494
11.1k
    unsigned int aIdx = tmpT;
2495
2496
11.1k
    streamRead(ss, tmpInt, version);
2497
11.1k
    int lvIdx = tmpInt;
2498
2499
11.1k
    std::string id;
2500
11.1k
    streamRead(ss, id, version);
2501
2502
11.1k
    sgroup.addAttachPoint(aIdx, lvIdx, id);
2503
11.1k
  }
2504
2505
47.6k
  return sgroup;
2506
47.6k
}
RDKit::SubstanceGroup RDKit::MolPickler::_getSubstanceGroupFromPickle<int>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, int)
Line
Count
Source
2422
6.49k
                                                        int version) {
2423
6.49k
  T tmpT;
2424
6.49k
  T numItems;
2425
6.49k
  float tmpFloat;
2426
6.49k
  int tmpInt = -1;
2427
6.49k
  std::string tmpS;
2428
2429
  // temporarily accept empty TYPE
2430
6.49k
  SubstanceGroup sgroup(mol, "");
2431
2432
  // Read RDProps, overriding ID, TYPE and COMPNO
2433
6.49k
  if (version >= 14000) {
2434
0
    streamReadProps<std::uint16_t>(ss, sgroup,
2435
0
                                   MolPickler::getCustomPropHandlers());
2436
6.49k
  } else {
2437
6.49k
    streamReadProps<unsigned int>(ss, sgroup,
2438
6.49k
                                  MolPickler::getCustomPropHandlers());
2439
6.49k
  }
2440
2441
6.49k
  streamRead(ss, numItems, version);
2442
9.23k
  for (int i = 0; i < numItems; ++i) {
2443
2.73k
    streamRead(ss, tmpT, version);
2444
2.73k
    sgroup.addAtomWithIdx(tmpT);
2445
2.73k
  }
2446
2447
6.49k
  streamRead(ss, numItems, version);
2448
6.85k
  for (int i = 0; i < numItems; ++i) {
2449
365
    streamRead(ss, tmpT, version);
2450
365
    sgroup.addParentAtomWithIdx(tmpT);
2451
365
  }
2452
2453
6.49k
  streamRead(ss, numItems, version);
2454
6.49k
  for (int i = 0; i < numItems; ++i) {
2455
4
    streamRead(ss, tmpT, version);
2456
4
    sgroup.addBondWithIdx(tmpT);
2457
4
  }
2458
2459
6.49k
  streamRead(ss, numItems, version);
2460
24.1k
  for (int i = 0; i < numItems; ++i) {
2461
17.6k
    SubstanceGroup::Bracket bracket;
2462
70.5k
    for (auto j = 0; j < 3; ++j) {
2463
52.8k
      streamRead(ss, tmpFloat, version);
2464
52.8k
      auto x = static_cast<double>(tmpFloat);
2465
52.8k
      streamRead(ss, tmpFloat, version);
2466
52.8k
      auto y = static_cast<double>(tmpFloat);
2467
52.8k
      streamRead(ss, tmpFloat, version);
2468
52.8k
      auto z = static_cast<double>(tmpFloat);
2469
52.8k
      bracket[j] = RDGeom::Point3D(x, y, z);
2470
52.8k
    }
2471
17.6k
    sgroup.addBracket(bracket);
2472
17.6k
  }
2473
2474
6.49k
  streamRead(ss, numItems, version);
2475
6.49k
  for (int i = 0; i < numItems; ++i) {
2476
3
    streamRead(ss, tmpT, version);
2477
3
    RDGeom::Point3D vector;
2478
2479
3
    if ("SUP" == sgroup.getProp<std::string>("TYPE")) {
2480
0
      streamRead(ss, tmpFloat, version);
2481
0
      vector.x = static_cast<double>(tmpFloat);
2482
0
      streamRead(ss, tmpFloat, version);
2483
0
      vector.y = static_cast<double>(tmpFloat);
2484
0
      streamRead(ss, tmpFloat, version);
2485
0
      vector.z = static_cast<double>(tmpFloat);
2486
0
    }
2487
2488
3
    sgroup.addCState(tmpT, vector);
2489
3
  }
2490
2491
6.49k
  streamRead(ss, numItems, version);
2492
15.8k
  for (int i = 0; i < numItems; ++i) {
2493
9.35k
    streamRead(ss, tmpT, version);
2494
9.35k
    unsigned int aIdx = tmpT;
2495
2496
9.35k
    streamRead(ss, tmpInt, version);
2497
9.35k
    int lvIdx = tmpInt;
2498
2499
9.35k
    std::string id;
2500
9.35k
    streamRead(ss, id, version);
2501
2502
9.35k
    sgroup.addAttachPoint(aIdx, lvIdx, id);
2503
9.35k
  }
2504
2505
6.49k
  return sgroup;
2506
6.49k
}
RDKit::SubstanceGroup RDKit::MolPickler::_getSubstanceGroupFromPickle<unsigned char>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, int)
Line
Count
Source
2422
41.1k
                                                        int version) {
2423
41.1k
  T tmpT;
2424
41.1k
  T numItems;
2425
41.1k
  float tmpFloat;
2426
41.1k
  int tmpInt = -1;
2427
41.1k
  std::string tmpS;
2428
2429
  // temporarily accept empty TYPE
2430
41.1k
  SubstanceGroup sgroup(mol, "");
2431
2432
  // Read RDProps, overriding ID, TYPE and COMPNO
2433
41.1k
  if (version >= 14000) {
2434
40.7k
    streamReadProps<std::uint16_t>(ss, sgroup,
2435
40.7k
                                   MolPickler::getCustomPropHandlers());
2436
40.7k
  } else {
2437
467
    streamReadProps<unsigned int>(ss, sgroup,
2438
467
                                  MolPickler::getCustomPropHandlers());
2439
467
  }
2440
2441
41.1k
  streamRead(ss, numItems, version);
2442
41.1k
  for (int i = 0; i < numItems; ++i) {
2443
3
    streamRead(ss, tmpT, version);
2444
3
    sgroup.addAtomWithIdx(tmpT);
2445
3
  }
2446
2447
41.1k
  streamRead(ss, numItems, version);
2448
41.1k
  for (int i = 0; i < numItems; ++i) {
2449
3
    streamRead(ss, tmpT, version);
2450
3
    sgroup.addParentAtomWithIdx(tmpT);
2451
3
  }
2452
2453
41.1k
  streamRead(ss, numItems, version);
2454
41.1k
  for (int i = 0; i < numItems; ++i) {
2455
2
    streamRead(ss, tmpT, version);
2456
2
    sgroup.addBondWithIdx(tmpT);
2457
2
  }
2458
2459
41.1k
  streamRead(ss, numItems, version);
2460
42.6k
  for (int i = 0; i < numItems; ++i) {
2461
1.46k
    SubstanceGroup::Bracket bracket;
2462
5.85k
    for (auto j = 0; j < 3; ++j) {
2463
4.38k
      streamRead(ss, tmpFloat, version);
2464
4.38k
      auto x = static_cast<double>(tmpFloat);
2465
4.38k
      streamRead(ss, tmpFloat, version);
2466
4.38k
      auto y = static_cast<double>(tmpFloat);
2467
4.38k
      streamRead(ss, tmpFloat, version);
2468
4.38k
      auto z = static_cast<double>(tmpFloat);
2469
4.38k
      bracket[j] = RDGeom::Point3D(x, y, z);
2470
4.38k
    }
2471
1.46k
    sgroup.addBracket(bracket);
2472
1.46k
  }
2473
2474
41.1k
  streamRead(ss, numItems, version);
2475
41.1k
  for (int i = 0; i < numItems; ++i) {
2476
2
    streamRead(ss, tmpT, version);
2477
2
    RDGeom::Point3D vector;
2478
2479
2
    if ("SUP" == sgroup.getProp<std::string>("TYPE")) {
2480
0
      streamRead(ss, tmpFloat, version);
2481
0
      vector.x = static_cast<double>(tmpFloat);
2482
0
      streamRead(ss, tmpFloat, version);
2483
0
      vector.y = static_cast<double>(tmpFloat);
2484
0
      streamRead(ss, tmpFloat, version);
2485
0
      vector.z = static_cast<double>(tmpFloat);
2486
0
    }
2487
2488
2
    sgroup.addCState(tmpT, vector);
2489
2
  }
2490
2491
41.1k
  streamRead(ss, numItems, version);
2492
42.9k
  for (int i = 0; i < numItems; ++i) {
2493
1.78k
    streamRead(ss, tmpT, version);
2494
1.78k
    unsigned int aIdx = tmpT;
2495
2496
1.78k
    streamRead(ss, tmpInt, version);
2497
1.78k
    int lvIdx = tmpInt;
2498
2499
1.78k
    std::string id;
2500
1.78k
    streamRead(ss, id, version);
2501
2502
1.78k
    sgroup.addAttachPoint(aIdx, lvIdx, id);
2503
1.78k
  }
2504
2505
41.1k
  return sgroup;
2506
41.1k
}
2507
2508
template <typename T>
2509
void MolPickler::_pickleStereo(std::ostream &ss,
2510
                               std::vector<StereoGroup> groups,
2511
                               std::map<int, int> &atomIdxMap,
2512
0
                               std::map<int, int> &bondIdxMap) {
2513
0
  T tmpT = static_cast<T>(groups.size());
2514
0
  streamWrite(ss, tmpT);
2515
0
  assignStereoGroupIds(groups);
2516
0
  for (auto &&group : groups) {
2517
0
    streamWrite(ss, static_cast<T>(group.getGroupType()));
2518
0
    if (group.getGroupType() != StereoGroupType::STEREO_ABSOLUTE) {
2519
0
      streamWrite(ss, static_cast<T>(group.getWriteId()));
2520
0
    }
2521
0
    auto &atoms = group.getAtoms();
2522
0
    streamWrite(ss, static_cast<T>(atoms.size()));
2523
0
    for (auto &&atom : atoms) {
2524
0
      tmpT = static_cast<T>(atomIdxMap[atom->getIdx()]);
2525
0
      streamWrite(ss, tmpT);
2526
0
    }
2527
2528
0
    auto &bonds = group.getBonds();
2529
0
    streamWrite(ss, static_cast<T>(bonds.size()));
2530
0
    for (auto &&bond : bonds) {
2531
0
      tmpT = static_cast<T>(bondIdxMap[bond->getIdx()]);
2532
0
      streamWrite(ss, tmpT);
2533
0
    }
2534
0
  }
2535
0
}
Unexecuted instantiation: void RDKit::MolPickler::_pickleStereo<int>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<RDKit::StereoGroup, std::__1::allocator<RDKit::StereoGroup> >, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&)
Unexecuted instantiation: void RDKit::MolPickler::_pickleStereo<unsigned char>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<RDKit::StereoGroup, std::__1::allocator<RDKit::StereoGroup> >, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&, std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, int> > >&)
2536
2537
template <typename T>
2538
24
void MolPickler::_depickleStereo(std::istream &ss, ROMol *mol, int version) {
2539
24
  T tmpT;
2540
24
  streamRead(ss, tmpT, version);
2541
24
  const auto numGroups = static_cast<unsigned>(tmpT);
2542
2543
24
  if (numGroups > 0u) {
2544
24
    std::vector<StereoGroup> groups;
2545
6.13k
    for (unsigned group = 0u; group < numGroups; ++group) {
2546
6.10k
      T tmpT;
2547
6.10k
      streamRead(ss, tmpT, version);
2548
6.10k
      const auto groupType = static_cast<RDKit::StereoGroupType>(tmpT);
2549
2550
6.10k
      unsigned gId = 0;
2551
6.10k
      if (version >= 14010 && groupType != StereoGroupType::STEREO_ABSOLUTE) {
2552
34
        streamRead(ss, tmpT, version);
2553
34
        gId = static_cast<unsigned>(tmpT);
2554
34
      }
2555
2556
6.10k
      streamRead(ss, tmpT, version);
2557
6.10k
      const auto numAtoms = static_cast<unsigned>(tmpT);
2558
2559
6.10k
      std::vector<Atom *> atoms;
2560
6.10k
      atoms.reserve(numAtoms);
2561
6.84k
      for (unsigned i = 0u; i < numAtoms; ++i) {
2562
740
        streamRead(ss, tmpT, version);
2563
740
        atoms.push_back(mol->getAtomWithIdx(tmpT));
2564
740
      }
2565
2566
6.10k
      std::vector<Bond *> bonds;
2567
6.10k
      if (version > 16000) {
2568
2.22k
        streamRead(ss, tmpT, version);
2569
2.22k
        const auto numBonds = static_cast<unsigned>(tmpT);
2570
2571
2.22k
        bonds.reserve(numBonds);
2572
2.80k
        for (unsigned i = 0u; i < numBonds; ++i) {
2573
577
          streamRead(ss, tmpT, version);
2574
577
          bonds.push_back(mol->getBondWithIdx(tmpT));
2575
577
        }
2576
2.22k
      }
2577
6.10k
      groups.emplace_back(groupType, std::move(atoms), std::move(bonds), gId);
2578
6.10k
    }
2579
2580
24
    mol->setStereoGroups(std::move(groups));
2581
24
  }
2582
24
}
void RDKit::MolPickler::_depickleStereo<int>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, int)
Line
Count
Source
2538
24
void MolPickler::_depickleStereo(std::istream &ss, ROMol *mol, int version) {
2539
24
  T tmpT;
2540
24
  streamRead(ss, tmpT, version);
2541
24
  const auto numGroups = static_cast<unsigned>(tmpT);
2542
2543
24
  if (numGroups > 0u) {
2544
24
    std::vector<StereoGroup> groups;
2545
6.13k
    for (unsigned group = 0u; group < numGroups; ++group) {
2546
6.10k
      T tmpT;
2547
6.10k
      streamRead(ss, tmpT, version);
2548
6.10k
      const auto groupType = static_cast<RDKit::StereoGroupType>(tmpT);
2549
2550
6.10k
      unsigned gId = 0;
2551
6.10k
      if (version >= 14010 && groupType != StereoGroupType::STEREO_ABSOLUTE) {
2552
34
        streamRead(ss, tmpT, version);
2553
34
        gId = static_cast<unsigned>(tmpT);
2554
34
      }
2555
2556
6.10k
      streamRead(ss, tmpT, version);
2557
6.10k
      const auto numAtoms = static_cast<unsigned>(tmpT);
2558
2559
6.10k
      std::vector<Atom *> atoms;
2560
6.10k
      atoms.reserve(numAtoms);
2561
6.84k
      for (unsigned i = 0u; i < numAtoms; ++i) {
2562
740
        streamRead(ss, tmpT, version);
2563
740
        atoms.push_back(mol->getAtomWithIdx(tmpT));
2564
740
      }
2565
2566
6.10k
      std::vector<Bond *> bonds;
2567
6.10k
      if (version > 16000) {
2568
2.22k
        streamRead(ss, tmpT, version);
2569
2.22k
        const auto numBonds = static_cast<unsigned>(tmpT);
2570
2571
2.22k
        bonds.reserve(numBonds);
2572
2.80k
        for (unsigned i = 0u; i < numBonds; ++i) {
2573
577
          streamRead(ss, tmpT, version);
2574
577
          bonds.push_back(mol->getBondWithIdx(tmpT));
2575
577
        }
2576
2.22k
      }
2577
6.10k
      groups.emplace_back(groupType, std::move(atoms), std::move(bonds), gId);
2578
6.10k
    }
2579
2580
24
    mol->setStereoGroups(std::move(groups));
2581
24
  }
2582
24
}
Unexecuted instantiation: void RDKit::MolPickler::_depickleStereo<unsigned char>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, RDKit::ROMol*, int)
2583
2584
//! unpickle standard properties
2585
void MolPickler::_unpickleProperties(std::istream &ss, RDProps &props,
2586
2
                                     int version) {
2587
2
  if (version >= 14000) {
2588
0
    streamReadProps<std::uint16_t>(ss, props,
2589
0
                                   MolPickler::getCustomPropHandlers());
2590
2
  } else {
2591
2
    streamReadProps<unsigned int>(ss, props,
2592
2
                                  MolPickler::getCustomPropHandlers());
2593
2
  }
2594
2
}
2595
2596
//--------------------------------------
2597
//
2598
//            Version 1 Pickler:
2599
//
2600
//  NOTE: this is not 64bit clean, but it shouldn't be used anymore anyway
2601
//
2602
//--------------------------------------
2603
2604
0
void MolPickler::_pickleV1(const ROMol *mol, std::ostream &ss) {
2605
0
  PRECONDITION(mol, "empty molecule");
2606
0
  ROMol::ConstAtomIterator atIt;
2607
0
  const Conformer *conf = nullptr;
2608
0
  if (mol->getNumConformers() > 0) {
2609
0
    conf = &(mol->getConformer());
2610
0
  }
2611
0
  for (const auto atom : mol->atoms()) {
2612
0
    streamWrite(ss, BEGINATOM);
2613
0
    streamWrite(ss, ATOM_NUMBER, atom->getAtomicNum());
2614
2615
0
    streamWrite(ss, ATOM_INDEX, atom->getIdx());
2616
2617
0
    streamWrite(ss, ATOM_POS);
2618
0
    RDGeom::Point3D p;
2619
0
    if (conf) {
2620
0
      p = conf->getAtomPos(atom->getIdx());
2621
0
    }
2622
0
    streamWrite(ss, p.x);
2623
0
    streamWrite(ss, p.y);
2624
0
    streamWrite(ss, p.z);
2625
2626
0
    if (atom->getFormalCharge() != 0) {
2627
0
      streamWrite(ss, ATOM_CHARGE, atom->getFormalCharge());
2628
0
    }
2629
0
    if (atom->getNumExplicitHs() != 0) {
2630
0
      streamWrite(ss, ATOM_NEXPLICIT, atom->getNumExplicitHs());
2631
0
    }
2632
0
    if (atom->getChiralTag() != 0) {
2633
0
      streamWrite(ss, ATOM_CHIRALTAG, atom->getChiralTag());
2634
0
    }
2635
0
    if (atom->getIsAromatic()) {
2636
0
      streamWrite(ss, ATOM_ISAROMATIC,
2637
0
                  static_cast<char>(atom->getIsAromatic()));
2638
0
    }
2639
0
    streamWrite(ss, ENDATOM);
2640
0
  }
2641
2642
0
  for (const auto bond : mol->bonds()) {
2643
0
    streamWrite(ss, BEGINBOND);
2644
0
    streamWrite(ss, BOND_INDEX, bond->getIdx());
2645
0
    streamWrite(ss, BOND_BEGATOMIDX, bond->getBeginAtomIdx());
2646
0
    streamWrite(ss, BOND_ENDATOMIDX, bond->getEndAtomIdx());
2647
0
    streamWrite(ss, BOND_TYPE, bond->getBondType());
2648
0
    if (bond->getBondDir()) {
2649
0
      streamWrite(ss, BOND_DIR, bond->getBondDir());
2650
0
    }
2651
0
    streamWrite(ss, ENDBOND);
2652
0
  }
2653
0
  streamWrite(ss, ENDMOL);
2654
0
}
2655
2656
102
void MolPickler::_depickleV1(std::istream &ss, ROMol *mol) {
2657
102
  PRECONDITION(mol, "empty molecule");
2658
102
  Tags tag;
2659
2660
102
  auto *conf = new Conformer();
2661
102
  mol->addConformer(conf);
2662
102
  streamRead(ss, tag, 1);
2663
1.01M
  while (tag != ENDMOL) {
2664
1.01M
    switch (tag) {
2665
1.01M
      case BEGINATOM:
2666
1.01M
        _addAtomFromPickleV1(ss, mol);
2667
1.01M
        break;
2668
2
      case BEGINBOND:
2669
2
        _addBondFromPickleV1(ss, mol);
2670
2
        break;
2671
0
      default:
2672
0
        UNDER_CONSTRUCTION("bad tag in pickle");
2673
1.01M
    }
2674
1.01M
    streamRead(ss, tag, 1);
2675
1.01M
  }
2676
91
  mol->clearAllAtomBookmarks();
2677
91
  mol->clearAllBondBookmarks();
2678
91
}
2679
2680
1.01M
void MolPickler::_addAtomFromPickleV1(std::istream &ss, ROMol *mol) {
2681
1.01M
  PRECONDITION(mol, "empty molecule");
2682
1.01M
  Tags tag;
2683
1.01M
  int intVar;
2684
1.01M
  double dblVar;
2685
1.01M
  char charVar;
2686
1.01M
  int version = 1;
2687
1.01M
  streamRead(ss, tag, version);
2688
1.01M
  auto *atom = new Atom();
2689
1.01M
  Conformer &conf = mol->getConformer();
2690
1.01M
  RDGeom::Point3D pos;
2691
1.05M
  while (tag != ENDATOM) {
2692
43.1k
    switch (tag) {
2693
10
      case ATOM_INDEX:
2694
10
        streamRead(ss, intVar, version);
2695
10
        mol->setAtomBookmark(atom, intVar);
2696
10
        break;
2697
3.14k
      case ATOM_NUMBER:
2698
3.14k
        streamRead(ss, intVar, version);
2699
3.14k
        atom->setAtomicNum(intVar);
2700
3.14k
        break;
2701
0
      case ATOM_POS:
2702
0
        streamRead(ss, pos.x, version);
2703
0
        streamRead(ss, pos.y, version);
2704
0
        streamRead(ss, pos.z, version);
2705
0
        break;
2706
0
      case ATOM_CHARGE:
2707
0
        streamRead(ss, intVar, version);
2708
0
        atom->setFormalCharge(intVar);
2709
0
        break;
2710
15.0k
      case ATOM_NEXPLICIT:
2711
15.0k
        streamRead(ss, intVar, version);
2712
15.0k
        atom->setNumExplicitHs(intVar);
2713
15.0k
        break;
2714
6.50k
      case ATOM_CHIRALTAG:
2715
6.50k
        streamRead(ss, intVar, version);
2716
6.50k
        atom->setChiralTag(static_cast<Atom::ChiralType>(intVar));
2717
6.50k
        break;
2718
0
      case ATOM_MASS:
2719
0
        streamRead(ss, dblVar, version);
2720
        // we don't need to set this anymore, but we do need to read it in
2721
        // order to maintain backwards compatibility
2722
0
        break;
2723
135
      case ATOM_ISAROMATIC:
2724
135
        streamRead(ss, charVar, version);
2725
135
        atom->setIsAromatic(charVar);
2726
135
        break;
2727
18.3k
      default:
2728
18.3k
        ASSERT_INVARIANT(0, "bad tag in atom block of pickle");
2729
43.1k
    }
2730
43.1k
    streamRead(ss, tag, version);
2731
43.1k
  }
2732
1.01M
  unsigned int id = mol->addAtom(atom, false, true);
2733
1.01M
  conf.setAtomPos(id, pos);
2734
1.01M
}
2735
2
void MolPickler::_addBondFromPickleV1(std::istream &ss, ROMol *mol) {
2736
2
  PRECONDITION(mol, "empty molecule");
2737
2
  Tags tag;
2738
2
  int intVar, idx = -1;
2739
2
  int version = 1;
2740
2
  Bond::BondType bt;
2741
2
  Bond::BondDir bd;
2742
2
  streamRead(ss, tag, version);
2743
2
  auto *bond = new Bond();
2744
7.94k
  while (tag != ENDBOND) {
2745
7.94k
    switch (tag) {
2746
970
      case BOND_INDEX:
2747
970
        streamRead(ss, idx, version);
2748
970
        break;
2749
972
      case BOND_BEGATOMIDX:
2750
972
        streamRead(ss, intVar, version);
2751
972
        bond->setBeginAtomIdx(mol->getAtomWithBookmark(intVar)->getIdx());
2752
972
        break;
2753
183
      case BOND_ENDATOMIDX:
2754
183
        streamRead(ss, intVar, version);
2755
183
        bond->setEndAtomIdx(mol->getAtomWithBookmark(intVar)->getIdx());
2756
183
        break;
2757
0
      case BOND_TYPE:
2758
0
        streamRead(ss, bt, version);
2759
0
        bond->setBondType(bt);
2760
0
        break;
2761
0
      case BOND_DIR:
2762
0
        streamRead(ss, bd, version);
2763
0
        bond->setBondDir(bd);
2764
0
        break;
2765
5.81k
      default:
2766
5.81k
        ASSERT_INVARIANT(0, "bad tag in bond block of pickle");
2767
7.94k
    }
2768
7.94k
    streamRead(ss, tag, version);
2769
7.94k
  }
2770
2
  mol->addBond(bond, true);
2771
2
}
2772
};  // namespace RDKit