ROSE  0.9.9.139
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 
162 SAWYER_EXPORT Id id(const std::string &name);
163 
170 SAWYER_EXPORT const std::string& name(Id);
171 
175 class SAWYER_EXPORT DoesNotExist: public Exception::NotFound {
176 public:
177  ~DoesNotExist() throw () {}
178 
180  explicit DoesNotExist(const std::string &attrName)
181  : Exception::NotFound(attrName + " does not exist in object") {}
182 };
183 
185 class SAWYER_EXPORT AlreadyExists: public Exception::AlreadyExists {
186 public:
187  ~AlreadyExists() throw () {}
188 
190  AlreadyExists(const std::string &attrName, Id id)
191  : Exception::AlreadyExists(attrName + " is already a declared attribute (id=" +
192  boost::lexical_cast<std::string>(id) + ")") {}
193 };
194 
196 typedef boost::bad_any_cast WrongQueryType;
197 
207 template<class SyncTag = SAWYER_THREAD_TAG>
208 class Storage {
209 public:
211 
212 private:
214  AttrMap values_;
215  mutable typename Sync::Mutex mutex_;
216 
217 public:
221  Storage() {}
222  ~Storage() {} // possibly required for MSVC linking
223 
227  Storage(const Storage &other) {
228  typename Sync::LockGuard lock(other.mutex_);
229  values_ = other.values_;
230  }
231 
235  Storage& operator=(const Storage &other) {
236  typename Sync::LockGuard2 lock(mutex_, other.mutex_);
237  values_ = other.values_;
238  return *this;
239  }
240 
246  bool attributeExists(Id id) const {
247  typename Sync::LockGuard lock(mutex_);
248  return values_.exists(id);
249  }
250 
257  void eraseAttribute(Id id) {
258  typename Sync::LockGuard lock(mutex_);
259  values_.erase(id);
260  }
261 
266  typename Sync::LockGuard lock(mutex_);
267  values_.clear();
268  }
269 
277  template<typename T>
278  void setAttribute(Id id, const T &value) {
279  typename Sync::LockGuard lock(mutex_);
280  values_.insert(id, boost::any(value));
281  }
282 
290  template<typename T>
291  bool setAttributeMaybe(Id id, const T &value) {
292  typename Sync::LockGuard lock(mutex_);
293  if (!values_.exists(id)) {
294  values_.insert(id, boost::any(value));
295  return true;
296  }
297  return false;
298  }
299 
307  template<typename T>
308  T getAttribute(Id id) const {
309  typename Sync::LockGuard lock(mutex_);
310  AttrMap::ConstNodeIterator found = values_.find(id);
311  if (found == values_.nodes().end()) {
312  std::string name = Attribute::name(id);
313  if (name.empty()) {
314  throw DoesNotExist("attribute id " + boost::lexical_cast<std::string>(id) + " [not declared]");
315  } else {
316  throw DoesNotExist(name);
317  }
318  }
319  checkBoost();
320  return boost::any_cast<T>(values_.getOptional(id).orDefault());
321  }
322 
330  template<typename T>
331  T attributeOrElse(Id id, const T &dflt) const {
332  typename Sync::LockGuard lock(mutex_);
333  checkBoost();
334  return boost::any_cast<T>(values_.getOptional(id).orElse(dflt));
335  }
336 
344  template<typename T>
345  T attributeOrDefault(Id id) const {
346  typename Sync::LockGuard lock(mutex_);
347  AttrMap::ConstNodeIterator found = values_.find(id);
348  if (found == values_.nodes().end())
349  return T();
350  return boost::any_cast<T>(found->value());
351  }
352 
358  template<typename T>
360  typename Sync::LockGuard lock(mutex_);
361  AttrMap::ConstNodeIterator found = values_.find(id);
362  if (found == values_.nodes().end())
363  return Sawyer::Nothing();
364  return boost::any_cast<T>(found->value());
365  }
366 
370  size_t nAttributes() const {
371  typename Sync::LockGuard lock(mutex_);
372  return values_.size();
373  }
374 
378  std::vector<Id> attributeIds() const {
379  typename Sync::LockGuard lock(mutex_);
380  std::vector<Id> retval;
381  retval.reserve(values_.size());
382  BOOST_FOREACH (Id id, values_.keys())
383  retval.push_back(id);
384  return retval;
385  }
386 };
387 
388 } // namespace
389 } // namespace
390 
391 #endif
bool attributeExists(Id id) const
Check attribute existence.
Definition: Attribute.h:246
void eraseAttribute(Id id)
Erase an attribute.
Definition: Attribute.h:257
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:377
Optional< Value > getOptional(const Key &key) const
Lookup and return a value or nothing.
Definition: Sawyer/Map.h:486
Exception for non-existing values.
Definition: Attribute.h:175
std::vector< Id > attributeIds() const
Returns ID numbers for all IDs stored in this container.
Definition: Attribute.h:378
Storage()
Default constructor.
Definition: Attribute.h:221
Value orDefault() const
Obtain a value or a default.
Definition: Optional.h:249
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:359
Storage & operator=(const Storage &other)
Assignment operator.
Definition: Attribute.h:235
AlreadyExists(const std::string &attrName, Id id)
Constructor taking an attribute name or description.
Definition: Attribute.h:190
void setAttribute(Id id, const T &value)
Store an attribute.
Definition: Attribute.h:278
Map & clear()
Remove all nodes.
Definition: Sawyer/Map.h:616
DoesNotExist(const std::string &attrName)
Constructor taking an attribute name or description.
Definition: Attribute.h:180
T attributeOrElse(Id id, const T &dflt) const
Return an attribute or a specified value.
Definition: Attribute.h:331
Name space for the entire library.
Definition: Access.h:11
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:308
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:370
boost::iterator_range< ConstKeyIterator > keys()
Iterators for container keys.
Definition: Sawyer/Map.h:284
Map & erase(const Key &key)
Remove a node with specified key.
Definition: Sawyer/Map.h:628
bool setAttributeMaybe(Id id, const T &value)
Store an attribute if not already present.
Definition: Attribute.h:291
NodeIterator find(const Key &key)
Find a node by key.
Definition: Sawyer/Map.h:364
Map & insert(const Key &key, const Value &value)
Insert or update a key/value pair.
Definition: Sawyer/Map.h:530
Exception thrown when redeclaring an existing attribute.
Definition: Attribute.h:185
API and storage for attributes.
Definition: Attribute.h:208
Represents no value.
Definition: Optional.h:32
boost::bad_any_cast WrongQueryType
Exception thrown when wrong data type is queried.
Definition: Attribute.h:196
boost::iterator_range< NodeIterator > nodes()
Iterators for container nodes.
Definition: Sawyer/Map.h:271
const Value & orElse(const Value &dflt) const
Obtain value or something else.
Definition: Optional.h:230
size_t size() const
Number of nodes, keys, or values in this container.
Definition: Sawyer/Map.h:322
void clearAttributes()
Erase all attributes.
Definition: Attribute.h:265
Storage(const Storage &other)
Copy constructor.
Definition: Attribute.h:227
Error for non-existing values.
T attributeOrDefault(Id id) const
Return an attribute or a default-constructed value.
Definition: Attribute.h:345