Mangrove
The C++ Object Document Mapper for MongoDB
deserializing_cursor.hpp
1 // Copyright 2016 MongoDB Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <mangrove/config/prelude.hpp>
18 
19 #include <iostream>
20 
21 #include <bsoncxx/builder/basic/document.hpp>
22 #include <bsoncxx/stdx/optional.hpp>
23 #include <mongocxx/cursor.hpp>
24 
25 #include <boson/mapping_functions.hpp>
26 
27 namespace mangrove {
28 MANGROVE_INLINE_NAMESPACE_BEGIN
29 
36 template <class T>
38  public:
39  deserializing_cursor(mongocxx::cursor&& c) : _c(std::move(c)) {
40  }
41 
42  class iterator;
43 
44  iterator begin() {
45  return iterator(_c.begin(), _c.end());
46  }
47 
48  iterator end() {
49  return iterator(_c.end(), _c.end());
50  }
51 
52  private:
53  mongocxx::cursor _c;
54 };
55 
56 template <class T>
57 class deserializing_cursor<T>::iterator : public std::iterator<std::input_iterator_tag, T> {
58  public:
59  iterator(mongocxx::cursor::iterator ci, mongocxx::cursor::iterator ci_end)
60  : _ci(ci), _ci_end(ci_end) {
61  skip_invalid_documents();
62  }
63 
64  iterator(const deserializing_cursor::iterator& dsi) : _ci(dsi._ci), _ci_end(dsi._ci_end) {
65  skip_invalid_documents();
66  }
67 
68  iterator& operator++() {
69  ++_ci;
70  _opt = mongocxx::stdx::nullopt;
71  skip_invalid_documents();
72  return *this;
73  }
74 
75  void operator++(int) {
76  operator++();
77  }
78 
79  bool operator==(const iterator& rhs) {
80  return _ci == rhs._ci;
81  }
82 
83  bool operator!=(const iterator& rhs) {
84  return _ci != rhs._ci;
85  }
86 
91  T operator*() {
92  return _opt.value();
93  }
94 
95  private:
96  mongocxx::cursor::iterator _ci;
97  // Keeps track of the end of the underlying cursor to enable skipping invalid documents.
98  mongocxx::cursor::iterator _ci_end;
99  // Cached object value. When this is non-empty, this always contains the current object pointed
100  // to by the cursor.
101  mongocxx::stdx::optional<T> _opt;
102 
111  void skip_invalid_documents() {
112  while (_ci != _ci_end) {
113  try {
114  if (!_opt) {
115  _opt = boson::to_obj<T>(*_ci);
116  }
117  return;
118  } catch (boson::Exception& e) {
119  ++_ci;
120  _opt = mongocxx::stdx::nullopt;
121  }
122  }
123  }
124 };
125 
126 MANGROVE_INLINE_NAMESPACE_END
127 } // namespace boson
128 
129 #include <mangrove/config/postlude.hpp>
An exception class thrown when things go wrong at runtime.
Definition: bson_archiver.hpp:75
Definition: deserializing_cursor.hpp:57
A class that wraps a mongocxx::cursor.
Definition: deserializing_cursor.hpp:37
Definition: collection_wrapper.hpp:28
T operator*()
Returns a deserialized object that corresponds to the current document pointed to by the underlying c...
Definition: deserializing_cursor.hpp:91