ROSE  0.11.145.0
Attribute.h
1 // WARNING: Changes to this file must be contributed back to Sawyer or else they will
2 // be clobbered by the next update from Sawyer. The Sawyer repository is at
3 // https://github.com/matzke1/sawyer.
4 
5 
6 
7 
8 // This header file originally came from the ROSE project, which is released under a BSD license that requires the following
9 // notification. All subsequent modifications are licensed as described in Sawyer's top-level "LICENSE" file.
10 //
11 // License for original version: Revised BSD License (non-advertising clause)
12 // License for original version:
13 // License for original version: This software is distributed under the revised Berkeley Software Distribution
14 // License for original version: (BSD) license by Lawrence Livermore National Laboratory LLNL (managed by the
15 // License for original version: University of California). The revised BSD license is the same as the original
16 // License for original version: BSD license, but without the famous advertising clause that was a problem
17 // License for original version: historically (see www.gnu.org/philosophy/bsd.html for details). Our goal
18 // License for original version: has been to select as liberal a license as possible for the ROSE project.
19 // License for original version:
20 // License for original version: Copyright (c) 2005, 2006, 2007, Regents of the University of California
21 // License for original version: All rights reserved.
22 // License for original version:
23 // License for original version: Revised BSD License:
24 // License for original version:
25 // License for original version: Redistribution and use in source and binary forms, with or without modification,
26 // License for original version: are permitted provided that the following conditions are met:
27 // License for original version:
28 // License for original version: * Redistributions of source code must retain the above copyright notice,
29 // License for original version: this list of conditions and the following disclaimer.
30 // License for original version: * Redistributions in binary form must reproduce the above copyright notice,
31 // License for original version: this list of conditions and the following disclaimer in the documentation
32 // License for original version: and/or other materials provided with the distribution.
33 // License for original version: * Neither the name of the University of California nor the names of its
34 // License for original version: contributors may be used to endorse or promote products derived from
35 // License for original version: this software without specific prior written permission.
36 // License for original version:
37 // License for original version: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
38 // License for original version: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39 // License for original version: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
40 // License for original version: IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
41 // License for original version: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
42 // License for original version: BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43 // License for original version: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44 // License for original version: OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45 // License for original version: OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46 // License for original version: OF THE POSSIBILITY OF SUCH DAMAGE.
47 
48 #ifndef Sawyer_Attribute_H
49 #define Sawyer_Attribute_H
50 
51 #include <boost/any.hpp>
52 #include <boost/foreach.hpp>
53 #include <boost/lexical_cast.hpp>
54 #include <Sawyer/Exception.h>
55 #include <Sawyer/Map.h>
56 #include <Sawyer/Optional.h>
57 #include <Sawyer/Sawyer.h>
58 #include <Sawyer/Synchronization.h>
59 #include <string>
60 #include <vector>
61 
62 namespace Sawyer {
63 
135 namespace Attribute {
136 
140 typedef size_t Id;
141 
143 SAWYER_EXPORT extern const Id INVALID_ID;
144 
154 SAWYER_EXPORT Id declare(const std::string &name);
155 
161 SAWYER_EXPORT Id declareMaybe(const std::string &name);
162 
169 SAWYER_EXPORT Id id(const std::string &name);
170 
177 SAWYER_EXPORT const std::string& name(Id);
178 
182 class SAWYER_EXPORT DoesNotExist: public Exception::NotFound {
183 public:
184  ~DoesNotExist() throw () {}
185 
187  explicit DoesNotExist(const std::string &attrName)
188  : Exception::NotFound(attrName + " does not exist in object") {}
189 };
190 
192 class SAWYER_EXPORT AlreadyExists: public Exception::AlreadyExists {
193 public:
194  ~AlreadyExists() throw () {}
195 
197  AlreadyExists(const std::string &attrName, Id id)
198  : Exception::AlreadyExists(attrName + " is already a declared attribute (id=" +
199  boost::lexical_cast<std::string>(id) + ")") {}
200 };
201 
203 typedef boost::bad_any_cast WrongQueryType;
204 
214 template<class SyncTag = SAWYER_THREAD_TAG>
215 class Storage {
216 public:
218 
219 private:
221  AttrMap values_;
222  mutable typename Sync::Mutex mutex_;
223 
224 public:
228  Storage() {}
229  ~Storage() {} // possibly required for MSVC linking
230 
234  Storage(const Storage &other) {
235  typename Sync::LockGuard lock(other.mutex_);
236  values_ = other.values_;
237  }
238 
242  Storage& operator=(const Storage &other) {
243  typename Sync::LockGuard2 lock(mutex_, other.mutex_);
244  values_ = other.values_;
245  return *this;
246  }
247 
253  bool attributeExists(Id id) const {
254  typename Sync::LockGuard lock(mutex_);
255  return values_.exists(id);
256  }
257 
264  void eraseAttribute(Id id) {
265  typename Sync::LockGuard lock(mutex_);
266  values_.erase(id);
267  }
268 
273  typename Sync::LockGuard lock(mutex_);
274  values_.clear();
275  }
276 
284  template<typename T>
285  void setAttribute(Id id, const T &value) {
286  typename Sync::LockGuard lock(mutex_);
287  values_.insert(id, boost::any(value));
288  }
289 
297  template<typename T>
298  bool setAttributeMaybe(Id id, const T &value) {
299  typename Sync::LockGuard lock(mutex_);
300  if (!values_.exists(id)) {
301  values_.insert(id, boost::any(value));
302  return true;
303  }
304  return false;
305  }
306 
314  template<typename T>
315  T getAttribute(Id id) const {
316  typename Sync::LockGuard lock(mutex_);
317  AttrMap::ConstNodeIterator found = values_.find(id);
318  if (found == values_.nodes().end()) {
319  std::string name = Attribute::name(id);
320  if (name.empty()) {
321  throw DoesNotExist("attribute id " + boost::lexical_cast<std::string>(id) + " [not declared]");
322  } else {
323  throw DoesNotExist(name);
324  }
325  }
326  checkBoost();
327  return boost::any_cast<T>(values_.getOptional(id).orDefault());
328  }
329 
337  template<typename T>
338  T attributeOrElse(Id id, const T &dflt) const {
339  typename Sync::LockGuard lock(mutex_);
340  checkBoost();
341  return boost::any_cast<T>(values_.getOptional(id).orElse(dflt));
342  }
343 
351  template<typename T>
352  T attributeOrDefault(Id id) const {
353  typename Sync::LockGuard lock(mutex_);
354  AttrMap::ConstNodeIterator found = values_.find(id);
355  if (found == values_.nodes().end())
356  return T();
357  return boost::any_cast<T>(found->value());
358  }
359 
365  template<typename T>
367  typename Sync::LockGuard lock(mutex_);
368  AttrMap::ConstNodeIterator found = values_.find(id);
369  if (found == values_.nodes().end())
370  return Sawyer::Nothing();
371  return boost::any_cast<T>(found->value());
372  }
373 
377  size_t nAttributes() const {
378  typename Sync::LockGuard lock(mutex_);
379  return values_.size();
380  }
381 
385  std::vector<Id> attributeIds() const {
386  typename Sync::LockGuard lock(mutex_);
387  std::vector<Id> retval;
388  retval.reserve(values_.size());
389  BOOST_FOREACH (Id id, values_.keys())
390  retval.push_back(id);
391  return retval;
392  }
393 };
394 
395 } // namespace
396 } // namespace
397 
398 #endif
bool attributeExists(Id id) const
Check attribute existence.
Definition: Attribute.h:253
void eraseAttribute(Id id)
Erase an attribute.
Definition: Attribute.h:264
const std::string & name(Id)
Returns the name for an attribute ID.
const Id INVALID_ID
Invalid attribute ID.
bool exists(const Key &key) const
Determine if a key exists.
Definition: Sawyer/Map.h:475
Optional< Value > getOptional(const Key &key) const
Lookup and return a value or nothing.
Definition: Sawyer/Map.h:584
Exception for non-existing values.
Definition: Attribute.h:182
std::vector< Id > attributeIds() const
Returns ID numbers for all IDs stored in this container.
Definition: Attribute.h:385
Storage()
Default constructor.
Definition: Attribute.h:228
Value orDefault() const
Obtain a value or a default.
Definition: Optional.h:273
STL namespace.
Holds a value or nothing.
Definition: Optional.h:49
Sawyer::Optional< T > optionalAttribute(Id id) const
Return the attribute as an optional value.
Definition: Attribute.h:366
Storage & operator=(const Storage &other)
Assignment operator.
Definition: Attribute.h:242
AlreadyExists(const std::string &attrName, Id id)
Constructor taking an attribute name or description.
Definition: Attribute.h:197
void setAttribute(Id id, const T &value)
Store an attribute.
Definition: Attribute.h:285
Map & clear()
Remove all nodes.
Definition: Sawyer/Map.h:714
DoesNotExist(const std::string &attrName)
Constructor taking an attribute name or description.
Definition: Attribute.h:187
T attributeOrElse(Id id, const T &dflt) const
Return an attribute or a specified value.
Definition: Attribute.h:338
Name space for the entire library.
Definition: FeasiblePath.h:767
void checkBoost()
Check for valid boost version or abort.
Traits for thread synchronization.
T getAttribute(Id id) const
Get an attribute that is known to exist.
Definition: Attribute.h:315
Error for existing values.
Id id(const std::string &name)
Returns the ID for an attribute name.
size_t Id
Attribute identification.
Definition: Attribute.h:140
Id declare(const std::string &name)
Register a new attribute key.
size_t nAttributes() const
Number of attributes stored.
Definition: Attribute.h:377
boost::iterator_range< ConstKeyIterator > keys()
Iterators for container keys.
Definition: Sawyer/Map.h:382
Map & erase(const Key &key)
Remove a node with specified key.
Definition: Sawyer/Map.h:726
bool setAttributeMaybe(Id id, const T &value)
Store an attribute if not already present.
Definition: Attribute.h:298
NodeIterator find(const Key &key)
Find a node by key.
Definition: Sawyer/Map.h:462
Map & insert(const Key &key, const Value &value)
Insert or update a key/value pair.
Definition: Sawyer/Map.h:628
Exception thrown when redeclaring an existing attribute.
Definition: Attribute.h:192
Id declareMaybe(const std::string &name)
Register a new attribute key if not already registered.
API and storage for attributes.
Definition: Attribute.h:215
Represents no value.
Definition: Optional.h:32
boost::bad_any_cast WrongQueryType
Exception thrown when wrong data type is queried.
Definition: Attribute.h:203
boost::iterator_range< NodeIterator > nodes()
Iterators for container nodes.
Definition: Sawyer/Map.h:369
const Value & orElse(const Value &dflt) const
Obtain value or something else.
Definition: Optional.h:235
size_t size() const
Number of nodes, keys, or values in this container.
Definition: Sawyer/Map.h:420
void clearAttributes()
Erase all attributes.
Definition: Attribute.h:272
Storage(const Storage &other)
Copy constructor.
Definition: Attribute.h:234
Error for non-existing values.
T attributeOrDefault(Id id) const
Return an attribute or a default-constructed value.
Definition: Attribute.h:352