owlcpp  v0.3.3~
C++ library for working with OWL ontologies
 All Classes Namespaces Files Functions Macros Pages
map_node.hpp
Go to the documentation of this file.
1 
6 #ifndef MAP_NODE_BASE_HPP_
7 #define MAP_NODE_BASE_HPP_
8 #include <string>
9 #include <vector>
10 #include <memory>
11 #include "boost/assert.hpp"
12 #include "boost/ptr_container/ptr_vector.hpp"
13 #include "boost/ptr_container/indirect_fun.hpp"
14 #include "boost/unordered_map.hpp"
15 #include "boost/foreach.hpp"
16 #include "boost/concept_check.hpp"
17 
18 #include "owlcpp/rdf/node.hpp"
20 #include "owlcpp/rdf/node_iri.hpp"
22 #include "owlcpp/rdf/exception.hpp"
24 #include "owlcpp/doc_id.hpp"
25 #include "owlcpp/node_id.hpp"
26 #include "owlcpp/detail/iterator_member_pair.hpp"
27 #include "owlcpp/detail/datatype_impl.hpp"
28 #include "owlcpp/terms/detail/max_standard_id.hpp"
29 
30 namespace owlcpp{
31 
37 class Map_node {
38 public:
39  typedef Node_id id_type;
40  typedef Node node_type;
41 private:
42  typedef std::auto_ptr<node_type> ptr_t;
43  typedef boost::ptr_vector<boost::nullable<Node> > vector_t;
44  typedef boost::unordered_map<
45  Node const*,
46  Node_id,
47  boost::indirect_fun<boost::hash<Node> >,
48  boost::indirect_fun<std::equal_to<Node> >
49  > map_t;
50 
51  typedef map_t::iterator map_iter_t;
52  typedef map_t::const_iterator map_citer_t;
53  typedef std::pair<map_iter_t,bool> insert_t;
54  typedef std::pair<Node const*,Node_id> map_element_t;
55 
56 public:
57  typedef Iterator_member_pair<map_citer_t, Node_id const, 2> iterator;
58  typedef iterator const_iterator;
59 
60  struct Err : public Rdf_err {};
61 
62  Map_node() {}
63 
64  Map_node(Map_node const& mn)
65  : vid_(mn.vid_.size()), map_(), erased_(mn.erased_)
66  {
67  copy(mn);
68  }
69 
70  Map_node& operator=(Map_node const& mn) {
71  if( this != &mn) {
72  clear();
73  vid_.reserve(mn.vid_.size());
74  copy(mn);
75  erased_ = mn.erased_;
76  }
77  return *this;
78  }
79 
80  std::size_t size() const { return map_.size(); }
81  const_iterator begin() const {return map_.begin();}
82  const_iterator end() const {return map_.end();}
83  bool empty() const {return map_.empty();}
84 
85  Node const& operator[](const Node_id id) const {
86  const std::size_t n = vpos(id);
87  BOOST_ASSERT( n < vid_.size() );
88  BOOST_ASSERT( ! vid_.is_null(n) );
89  return vid_[n];
90  }
91 
92  Node const& at(const Node_id id) const {
93  if( Node const* node = find(id) ) return *node;
94  BOOST_THROW_EXCEPTION(
95  Err()
96  << Err::msg_t("invalid node ID")
97  << Err::int1_t(id())
98  );
99  }
100 
101  Node const* find(const Node_id id) const {
102  if(
103  id < detail::min_node_id() ||
104  id() >= vid_.size() + detail::min_node_id()()
105  ) return 0;
106  return &vid_[vpos(id)];
107  }
108 
109  Node_id const* find(Node const& node) const {
110  const map_citer_t i = map_.find(&node);
111  return i == map_.end() ? 0 : &i->second;
112  }
113 
114  Node_id const* find_iri(const Ns_id ns, std::string const& val) const {
115  return find(Node_iri(ns, val));
116  }
117 
118  Node_id const* find_literal(
119  std::string const& val, const Node_id dt, std::string const& lang
120  ) const {
121  switch(internal_type_id(dt)) {
122  case detail::Bool_tid:
123  return find(Node_bool(val, dt));
124  case detail::Int_tid:
125  return find(Node_int(val, dt));
126  case detail::Unsigned_tid:
127  return find(Node_unsigned(val, dt));
128  case detail::Double_tid:
129  return find(Node_double(val, dt));
130  case detail::String_tid:
131  case detail::Unknown_tid:
132  return find( Node_string(val, dt, lang) );
133  case detail::Empty_tid:
134  default:
135  return find( Node_string(val, lang) );
136  }
137  }
138 
139  Node_id const* find_blank(const unsigned n, const Doc_id doc) const {
140  return find(Node_blank(n, doc));
141  }
142 
144  Node_id insert(Node const& node) {
145  if( Node_id const* id = find(node) ) return *id;
146  Node* np = node.clone();
147 
148  //make new ID
149  if( erased_.empty() ) {
150  const Node_id id = nid(vid_.size());
151  vid_.push_back(np);
152  map_.emplace(np, id);
153  return id;
154  }
155  const Node_id id = erased_.back();
156  erased_.pop_back();
157  const std::size_t n = vpos(id);
158  BOOST_ASSERT(vid_.is_null(n));
159  vid_.replace(n, np);
160  map_.emplace(np, id);
161  return id;
162  }
163 
164  Node_id insert_iri(const Ns_id ns, std::string const& val) {
165  return insert(Node_iri(ns,val));
166  }
167 
168  Node_id insert_literal(
169  std::string const& val,
170  const Node_id dt,
171  std::string const& lang = ""
172  ) {
173  switch(internal_type_id(dt)) {
174  case detail::Bool_tid:
175  return insert( Node_bool(val, dt) );
176  case detail::Int_tid:
177  return insert( Node_int(val, dt) );
178  case detail::Unsigned_tid:
179  return insert( Node_unsigned(val, dt) );
180  case detail::Double_tid:
181  return insert( Node_double(val, dt) );
182  case detail::String_tid:
183  case detail::Unknown_tid:
184  return insert( Node_string(val, dt, lang) );
185  case detail::Empty_tid:
186  default:
187  return insert( Node_string(val, lang) );
188  }
189  }
190 
191  Node_id insert_blank(const unsigned n, const Doc_id doc) {
192  return insert(Node_blank(n, doc));
193  }
194 
195  std::auto_ptr<Node> remove(const Node_id id) {
196  BOOST_ASSERT(find(id));
197  const std::size_t n = map_.erase(&get(id));
198  boost::ignore_unused_variable_warning(n);
199  BOOST_ASSERT(n);
200 
201  erased_.push_back(id);
202  return ptr_t( vid_.replace(vpos(id), 0).release() );
203  }
204 
205  void clear() {
206  erased_.clear();
207  map_.clear();
208  vid_.clear();
209  }
210 
211 private:
212  vector_t vid_;
213  map_t map_;
214  std::vector<Node_id> erased_;
215 
216  std::size_t vpos(const Node_id id) const {
217  BOOST_ASSERT(id >= detail::min_node_id());
218  return id() - detail::min_node_id()();
219  }
220 
221  Node_id nid(const std::size_t n) const {return Node_id(n + detail::min_node_id()());}
222 
223  Node const& get(const Node_id id) const {return vid_[vpos(id)];}
224 
225  void check_insert(const Node_id id, ptr_t np) {
226  Node_id const* id0 = find(*np);
227  if( id0 ) {
228  if( *id0 == id ) return;
229  BOOST_THROW_EXCEPTION(
230  Err()
231  << Err::msg_t("node already exists")
232  << Err::node_id_t(*id0)
233  << Err::str1_t(to_string(*np))
234  );
235  }
236  if( find(id) ) BOOST_THROW_EXCEPTION(
237  Err()
238  << Err::msg_t("node ID is reserved")
239  << Err::int1_t(id())
240  );
241  insert(id, np.release());
242  }
243 
244  void insert(const Node_id id, Node* np) {
245  const std::size_t n = vpos(id);
246  if( n < vid_.size() ) {
247  vid_.replace(n, np);
248  } else {
249  vid_.reserve(n);
250  for( ; vid_.size() < n; vid_.push_back(0));
251  vid_.push_back(np);
252  }
253  map_.emplace(np, id);
254  }
255 
256  void copy(Map_node const& mn) {
257  BOOST_FOREACH(map_element_t const& p, mn.map_) {
258  Node* np = p.first->clone();
259  insert(p.second, np);
260  }
261  }
262 
263 };
264 
265 }//namespace owlcpp
266 #endif /* MAP_NODE_BASE_HPP_ */