GL Studio C++ Runtime API
disti_metadata.h
Go to the documentation of this file.
1 /// \file
2 /// \brief The disti metadata.
3 ///
4 /// \par Copyright Information
5 ///
6 /// Copyright (c) 2017 by The DiSTI Corporation.<br>
7 /// 11301 Corporate Blvd; Suite 100<br>
8 /// Orlando, Florida 32817<br>
9 /// USA<br>
10 /// <br>
11 /// All rights reserved.<br>
12 ///
13 /// This Software contains proprietary trade secrets of DiSTI and may not be
14 /// reproduced, in whole or part, in any form, or by any means of electronic,
15 /// mechanical, or otherwise, without the written permission of DiSTI. Said
16 /// permission may be derived through the purchase of applicable DiSTI product
17 /// licenses which detail the distribution rights of this content and any
18 /// Derivative Works based on this or other copyrighted DiSTI Software.
19 ///
20 /// NO WARRANTY. THE SOFTWARE IS PROVIDED "AS-IS," WITHOUT WARRANTY OF ANY KIND,
21 /// AND ANY USE OF THIS SOFTWARE PRODUCT IS AT YOUR OWN RISK. TO THE MAXIMUM EXTENT
22 /// PERMITTED BY APPLICABLE LAW, DISTI AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES
23 /// AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24 /// IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY AND/OR FITNESS FOR A
25 /// PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT, WITH REGARD TO THE SOFTWARE.
26 ///
27 /// LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
28 /// IN NO EVENT SHALL DISTI OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
29 /// INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
30 /// DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
31 /// INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
32 /// INABILITY TO USE THE SOFTWARE, EVEN IF DISTI HAS BEEN ADVISED OF THE POSSIBILITY
33 /// OF SUCH DAMAGES. DISTI'S ENTIRE LIABILITY AND YOUR EXCLUSIVE REMEDY SHALL NOT
34 /// EXCEED FIVE DOLLARS (US$5.00).
35 ///
36 /// The aforementioned terms and restrictions are governed by the laws of the
37 /// State of Florida and the United States of America.
38 
39 #ifndef INCLUDED_DISTI_METADATA_H
40 #define INCLUDED_DISTI_METADATA_H
41 
42 #if defined( WIN32 )
43 # pragma warning( push )
44 # pragma warning( disable : 4786 )
45 # pragma warning( disable : 4251 ) // This may hide non-exported code.
46 #endif
47 
48 #include "disti_include.h"
49 #include "dynamic_array.h"
50 #include "gls_cpp_lang_support.h"
51 #include "scoped_ptr.h"
52 #include "unhide_globals.h"
53 #include "weak_reference.h"
55 
56 #include <cfloat>
57 #include <cstdarg>
58 #include <cstring>
59 #include <iostream>
60 #include <list>
61 #include <map>
62 #include <sstream>
63 
64 #if defined( LINUX )
65 # include <cstdlib>
66 # include <typeinfo>
67 #endif
68 
69 #define GLS_DEBUG_ATTRIBUTE_NAMES 0
70 #if GLS_DEBUG_ATTRIBUTE_NAMES
71 # define IF_GLS_DEBUG_ATTRIBUTE_NAMES( x ) x
72 #else
73 # define IF_GLS_DEBUG_ATTRIBUTE_NAMES( x )
74 #endif
75 
76 namespace disti
77 {
78 class CallbackMethodCallerBase;
79 const int MAX_ATTRIBUTE_NAME_LENGTH = 128;
80 /** AttributeName class can be treated like a std::string in some instances
81  * It creates static storage for any referenced name.
82  * This results in only one copy for each name which saves memory
83  * Very fast comparison between references to names
84  */
86 {
87 public:
88  /// Constructor
89  /// Explicit because construction of an AttributeName is an
90  /// expensive operation. If possible you should use a static
91  /// AttrbuteName object rather than constructing a new
92  /// one each time it is needed.
93  /// \param name the desired Name
94  DISTI_EXPORT explicit AttributeName( const std::string& name );
95 
96  /// Constructor
97  /// See comments on AttributeName(const std::string &name)
98  /// \param name the desired Name */
99  DISTI_EXPORT explicit AttributeName( const char* name );
100 
101  /// Constructor
102  /// \param stringIndex The index into the string map.
103  DISTI_EXPORT explicit AttributeName( long stringIndex );
104 
105  /// Copy constructor
106  AttributeName( const AttributeName& other ) DISTI_FUNC_NOEXCEPT
107  : _stringIndex( other._stringIndex )
108  {
109  IF_GLS_DEBUG_ATTRIBUTE_NAMES( _name = *this );
110  }
111 
112  /// Copy assignment
113  AttributeName& operator=( const AttributeName& other ) DISTI_FUNC_NOEXCEPT
114  {
115  _stringIndex = other._stringIndex;
116  IF_GLS_DEBUG_ATTRIBUTE_NAMES( _name = *this );
117  return *this;
118  }
119 
120  /// Returns the index to the string associate with this instance
121  long StringIndex() const { return _stringIndex; }
122 
123  /// Defines the cast operator to make this look like a std::string for reading
124  DISTI_EXPORT operator std::string() const;
125 
126 private:
127  long _stringIndex;
128 
129  // for easier debugging
130  IF_GLS_DEBUG_ATTRIBUTE_NAMES( std::string _name; )
131 
132  /** Attempts to find the specified name.
133  * If found _stringIndex is set to its index
134  * otherwise a new one is created and its index is saved */
135  void Initialize( const char* name );
136 };
137 
138 /// Defines the stream out operator
139 DISTI_EXPORT std::ostream& operator<<( std::ostream& outstr, const AttributeName& name );
140 
141 /// Compares this string to the specified AttributeName.
142 /// This compare is very fast compared to doing string compares, and is
143 /// one of the primary reasons for creating this class
144 inline bool operator==( const AttributeName& attr1, const AttributeName& attr2 )
145 {
146  return attr1.StringIndex() == attr2.StringIndex();
147 }
148 
149 /// Compares this string for inequality to the specified AttributeName.
150 /// This compare is very fast compared to doing string compares, and is
151 /// one of the primary reasons for creating this class
152 inline bool operator!=( const AttributeName& attr1, const AttributeName& attr2 )
153 {
154  return !( attr1 == attr2 );
155 }
156 
157 /// Defines various == operators which makes the users syntax easier
158 DISTI_EXPORT bool operator==( const AttributeName& lName, const char* rName );
159 DISTI_EXPORT bool operator==( const char* lName, const AttributeName& rName );
160 DISTI_EXPORT bool operator==( const std::string& lName, const AttributeName& rName );
161 DISTI_EXPORT bool operator==( const AttributeName& lName, const std::string& rName );
162 
163 /// Add a string literal suffix operator to allow "MyAttribute"_Attr for creation of attributes.
164 DISTI_IF_HAS_USER_DEFINED_LITERAL( inline AttributeName operator""_Attr( const char* str, std::size_t ) { return AttributeName( str ); } )
165 
166 class DistiAttributeBase;
167 
168 /** Class used to call a callback method that takes a DistiAttributeBase */
170 {
171 public:
172  /** call the callback with the provided display event */
173  virtual void Call( DistiAttributeBase& attr ) = 0;
174 
175  /** When IsValid is false, then this AttributeObserver can be deleted. */
176  virtual bool IsValid() const = 0;
177 
178  virtual ~AttributeObserver() {}
179 };
180 
181 class DistiAttributeObserverList;
182 
183 /** \class DistiAttributeBase
184  * This is the base class for all Disti Attributes.
185  */
187 {
188 private:
189  DistiAttributeBase( const DistiAttributeBase& ) DISTI_SPECIAL_MEM_FUN_DELETE;
190 
191 protected:
192  /** The name of this attribute */
193  AttributeName _name;
194  /** The callback which is called when the value of this object changes */
196 
197  /** The list of observers to be notified when this property changes. */
199 
200  /** _localStorage is true if this attributes data should be copied.
201  * It would typically be set false if the data is stored externally,
202  * and there is no need to copy the data through metadata.
203  * It is also used to determine if storage should be deleted.*/
205 
206 public:
207  /** Constructor
208  * \param callback The method to call when the value changes. A duplicate of the
209  CallbackMethodCallerBase is created and stored internally.
210  * \param name The name of the attribute
211  * \param localStorage True if this DistiAttribute contains actual storage,
212  rather than just a pointer to somebody elses storage*/
213  DISTI_EXPORT DistiAttributeBase( CallbackMethodCallerBase* callback, const AttributeName& name, bool localStorage );
214 
215  /** This will perform the copy using ReadValue() and WriteValue()
216  * It can be overridden by any dervied classes to do a smarter more efficent copy. */
217  virtual DISTI_EXPORT DistiAttributeBase& operator=( const DistiAttributeBase& oldClass );
218 
219  virtual DISTI_EXPORT ~DistiAttributeBase();
220 
221  /** Returns the name of this object */
222  DISTI_EXPORT const AttributeName& Name() const;
223 
224  /** Returns the name of this object */
225  DISTI_EXPORT AttributeName& Name();
226 
227  /** Returns true if this object has local storage */
228  DISTI_EXPORT bool LocalStorage() const;
229 
230  /** Its not a word, but it means able to be copied
231  * This should return true if it makes sense for the data to be copied.
232  * By default, will only copy if it contains local storage */
233  virtual DISTI_EXPORT bool Copyable() const;
234 
235  /** Returns true if this object is ready to have its WriteValue() called
236  * This SHOULD be overriden by any derived objects that may not be ready
237  * to write at any point.
238  * The reason for this is the data is often written "NAME: VALUE". If
239  * Value is not available, we don't want to write "NAME: " first, so before
240  * writting "NAME: ", OkToWrite() can be called to see if it will have a valid value */
241  virtual DISTI_EXPORT bool OkToWrite() const;
242 
243  /** Returns true if the object's value has changed since
244  * calling ResetValueChanged()
245  * However, it is not implmented in the base class and will
246  * always return true if not overridden */
247  virtual DISTI_EXPORT bool ValueChanged();
248 
249  /** Saves the current value for later comparison by ValueChanged()
250  * This does nothing in the base class */
251  virtual DISTI_EXPORT void ResetValueChanged();
252 
253  /** Returns the std::string version of the attribute data.
254  * Here in the base class it uses WriteValue()
255  * If this particular attribute's underlying type is a string, this returns the unencoded value, suitable for users.
256  * If a file encoded value is required, call WriteValue instead.
257  */
258  virtual DISTI_EXPORT std::string ValueString();
259 
260  /** Sets the value from a std::string argument.
261  * Here in the base class it uses ReadValue()
262  * If this particular attribute's underlying type is a string, this should not be set to an encoded value.
263  * If needing to set from an encoded value, call ReadValue instead.
264  */
265  virtual DISTI_EXPORT void ValueString( const std::string& s );
266 
267  /** Allows for faster access to integer types than the more generic
268  * stream operators. However, it is only faster if it is overridden. */
269  virtual DISTI_EXPORT long ValueInt();
270 
271  /** Allows for faster access to integer types than the more generic
272  * stream operator. However, it is only faster if it is overridden. */
273  virtual DISTI_EXPORT void ValueInt( long val );
274 
275  /** Allows for faster access to floating-point types than the more generic
276  * stream operators. However, it is only faster if it is overridden. */
277  virtual DISTI_EXPORT double ValueFloat();
278 
279  /** Allows for faster access to floating-point types than the more generic
280  * stream operator. However, it is only faster if it is overridden. */
281  virtual DISTI_EXPORT void ValueFloat( double val );
282 
283  /** Calls callback CallType3 if it has been set */
284  virtual DISTI_EXPORT void CallCallback();
285 
286  /** Pure virtual because this is specific to the data type to be contained.
287  * This should be overridden to write the data to the stream.
288  * The value written could be encoded for writing to a file as a single string,
289  * or have its own special encoding specific to its underlying type.
290  * In the case of attribute strings, this will be the GLS file encoded value.
291  * The user is responsible for decoding the value themselves, or using ReadValue
292  * which should perform decoding to maintain symmetry. */
293  virtual std::ostream& WriteValue( std::ostream& outstr ) = 0;
294  /** Pure virtual because this is specific to the data type to be contained.
295  * This should be overridden to read the data from the stream.
296  * The value read could be encoded for being read from a file as a single string,
297  * or have its own special encoding specific to its underlying type.
298  * In the case of attribute strings, this will be the GLS file encoded value.
299  * The user is responsible for encoding the value themselves, or using WriteValue
300  * which should perform encoding to maintain symmetry.
301  */
302  virtual std::istream& ReadValue( std::istream& instr ) = 0;
303 
304  /** Compares name and value
305  * This can be overriden to improve speed. */
306  virtual DISTI_EXPORT bool operator==( const DistiAttributeBase& r );
307 
308  /** Allow for generic access to some data types.
309  * This will NOT work for types which:
310  * s << val does not work.
311  * In general if the WriteValue is overridden, then it probably will not work.
312  */
313  template<class valType>
314  DistiAttributeBase& operator<<( const valType& val )
315  {
316  std::stringstream s;
317  // Ensure numeric values make it into the attribute's ReadValue implementation unmodified.
318  s.precision( MaxDigits10<long double>::value );
319  s << val;
320  ReadValue( s );
321  return *this;
322  }
323  /** Allows for generic access to some data types.
324  * This will NOT work for types which:
325  * s >> val does not work.
326  * In general if the ReadValue is overridden, then it probably will not work.
327  */
328  template<class valType>
330  {
331  std::stringstream s;
332  WriteValue( s );
333  s >> val;
334  return *this;
335  }
336 
337  /** Allows this class to send to a stream.
338  * Internally it uses WriteValue() */
339  friend DISTI_EXPORT std::ostream& operator<<( std::ostream& outstr, const DistiAttributeBase& attribute );
340  /** Allows this class to receive from a stream.
341  * Internally it uses ReadValue() */
342  friend DISTI_EXPORT std::istream& operator>>( std::istream& instr, DistiAttributeBase& attribute );
343 
344  /// Type for unique identifiers
345  typedef unsigned int CallbackID;
346 
347  /** Register a callback that is called when the value of the attribute changes. If multiple oservers are registered, they will be notified in the order they registered.
348  * DistiAttributeBase takes ownership of the observer and will delete it.
349  * \param observer the observer to notify. It is automatically unregistered and destroyed when it becomes invalid.
350  * \return an id that can be used to unregister the observer
351  */
352  virtual DISTI_EXPORT CallbackID RegisterObserver( AttributeObserver* observer );
353 
354  /** Unregister an observer
355  * \param id the id returned when the observer was registered
356  */
357  virtual DISTI_EXPORT void UnregisterObserver( CallbackID id );
358 
359  /** Triggers all observers to have their callbacks called. Typically called by the class that owns the DistiAttributeBase */
360  virtual DISTI_EXPORT void NotifyObservers();
361 };
362 
363 /** Template for an AttributeCallbackBase that will call a class method whenever the attribute changes. The class must implement WeakReferenceable.
364  * Don't use this directly, use CreateAttributeMethodCallback instead.
365  */
366 template<class T>
368 {
369 public:
370  typedef void ( T::*Callback )( DistiAttributeBase& attr );
371 
372  AttributeMethodCallback( T* object, Callback method )
373  : _method( method )
374  , _object( object )
375  {
376  GLS_VERIFY( NULL != method );
377  GLS_VERIFY( NULL != object );
378  }
379 
381  {
382  if( IsValid() )
383  {
384  ( _object.Get()->*( _method ) )( ev );
385  }
386  }
387 
388  virtual bool IsValid() const
389  {
390  return !_object.IsNull();
391  }
392 
393 protected:
394  Callback _method;
395  WeakRef<T> _object;
396 };
397 
398 /** Create an AttributeCallbackBase that will call a class method whenever the attribute changes.
399  * \param obj the object to call the method on
400  * \param method a class method pointer
401  */
402 template<class Class>
404  Class* const obj,
405  const typename AttributeMethodCallback<Class>::Callback method )
406 {
407  return new AttributeMethodCallback<Class>( obj, method );
408 }
409 
410 /** Template for an AttributeCallbackBase that will set another object's attribute whenever the attribute changes. The class must implement WeakReferenceable.
411  * Don't use this directly, use CreateAttributeResourceCallback instead.
412  */
413 template<class T>
415 {
416 public:
417  AttributeResourceCallback( T* object, const AttributeName& attributeName )
418  : _attributeName( attributeName )
419  , _object( object )
420  {
421  GLS_VERIFY( NULL != object );
422  }
423 
424  void Call( DistiAttributeBase& attr )
425  {
426  if( IsValid() )
427  {
428  if( DistiAttributeBase* objAttr = _object.Get()->Attributes().Get( _attributeName ) )
429  {
430  ( *objAttr ) << attr.ValueString();
431  }
432  }
433  }
434 
435  virtual bool IsValid() const
436  {
437  return !_object.IsNull();
438  }
439 
440 protected:
441  AttributeName _attributeName;
442  WeakRef<T> _object;
443 };
444 
445 /** Create an AttributeCallbackBase that will set another object's attribute whenever the attribute changes.
446  * \param obj the object to set the resource on
447  * \param attributeName the name of the property
448  */
449 template<class Class>
451  Class* const obj,
452  const char* attributeName )
453 {
454  return new AttributeResourceCallback<Class>( obj, AttributeName( attributeName ) );
455 }
456 
457 /** Interface for notifying when attributes have changed */
459 {
460 public:
461  /** Notify the class that the attribute has changed. Observers of the attribute will have their callbacks called
462  * \param name the name of the attribute
463  */
464  virtual DISTI_EXPORT void NotifyAttributeChanged( const AttributeName& name ) = 0;
465 
466  /** destructor */
468 };
469 
470 /** helper method to notify if an attribute has changed through a setter method
471  * \param object the object to notify
472  * \param property the storage for the data that is going to be set
473  * \param newValue the new value to set
474  * \param name the attribute name
475  */
476 template<class T>
477 void SetAndNotifyIfChanged( AttributeChangedNotifier* object, T& property, const T& newValue, const AttributeName& name )
478 {
479  if( newValue != property )
480  {
481  property = newValue;
482  object->NotifyAttributeChanged( name );
483  }
484 }
485 
486 /** \class DistiAttribute
487  * A templated class for creating attributes.
488  */
489 class DistiAttribDict;
490 template<class T>
492 {
493 protected:
494  /** Points to the actual storage */
496  /** Allows for setting of precision for floating point numbers */
498 
499 public:
500  /** Constructor
501  * Keeps a pointer to the specified type
502  * \param callback The method to call when the value changes. A duplicate of the
503  * CallbackMethodCallerBase is created and stored internally.
504  * \param name The name of the attribute
505  * \param attribPtr The address of the storage.
506  */
507  DistiAttribute( CallbackMethodCallerBase* callback, const AttributeName& name, T* attribPtr )
508  : DistiAttributeBase( callback, name, false )
509  , _attribPtr( attribPtr )
510  , _precision( MaxDigits10<T>::value )
511  {
512  }
513 
514  /** Constructor
515  * Actually creates storage of the specified type
516  * \param callback The method to call when the value changes. A duplicate of the
517  * CallbackMethodCallerBase is created and stored internally.
518  * \param name The name of the attribute
519  * \param initialValue The initial value of the intenally stored variable.
520  */
521  DistiAttribute( CallbackMethodCallerBase* callback, const AttributeName& name, const T& initialValue )
522  : DistiAttributeBase( callback, name, true /*Because we actually have storage*/ )
523  , _attribPtr( new T( initialValue ) )
524  , _precision( MaxDigits10<T>::value )
525  {
526  }
527  /** Its not a word, but it means able to be copied
528  * This should return true if it makes sense for the data to be copied.
529  * By default, will return true for this template.
530  * It is overridden here to allow for template specialization */
531  bool Copyable() const DISTI_METHOD_OVERRIDE { return true; }
532 
533  /** Gets the value as an integer. */
534  long ValueInt() DISTI_METHOD_OVERRIDE
535  {
537  }
538  /** Sets the value as an int */
539  void ValueInt( long val ) DISTI_METHOD_OVERRIDE
540  {
542  }
543 
544  /** Gets the value as a float */
545  double ValueFloat() DISTI_METHOD_OVERRIDE
546  {
548  }
549 
550  /** Sets the value as a float */
551  void ValueFloat( double val ) DISTI_METHOD_OVERRIDE
552  {
554  }
555 
556  /** This will perform the copy using Value() and Value(val) */
557  DistiAttributeBase& operator=( const DistiAttributeBase& oldClass ) DISTI_METHOD_OVERRIDE
558  {
559  DistiAttribute* ptr;
560 
561  ptr = dynamic_cast<DistiAttribute*>( const_cast<DistiAttributeBase*>( &oldClass ) );
562  if( ptr )
563  {
564  Value( ptr->Value() );
565  }
566  else
567  {
568  return DistiAttributeBase::operator=( oldClass );
569  }
570  return *this;
571  }
572 
573  /** Writes the data to the stream */
574  std::ostream& WriteValue( std::ostream& outstr ) DISTI_METHOD_OVERRIDE
575  {
576  if( _precision > 0 )
577  outstr.precision( _precision );
578 
579  //operator<<(outstr, *_attribPtr);
580  outstr << *_attribPtr;
581  return outstr;
582  };
583 
584  /** Reads the data from the stream
585  * The ReadValue call shall consume only what it needs. It is the responsibility of
586  * the calling function to read to the end of line, or to clean up from a bad read.
587  * The calling function will also ensure that the data starts as the next byte in the stream. */
588  std::istream& ReadValue( std::istream& instr ) DISTI_METHOD_OVERRIDE
589  {
590  return ReadValueImpl( instr );
591  };
592 
593  /** Allows for type specific access to the data */
594  virtual T Value()
595  {
596  return *_attribPtr;
597  }
598  /** Allows for type specific access to the data */
599  virtual void Value( const T& val )
600  {
601  *_attribPtr = val;
602  CallCallback();
603  }
604  /** Performs type specific comparison.
605  * This results in faster comparisons than the base class */
606  bool operator==( const DistiAttributeBase& rArg ) DISTI_METHOD_OVERRIDE
607  {
608  DistiAttribute<T>* r = dynamic_cast<DistiAttribute<T>*>( const_cast<DistiAttributeBase*>( &rArg ) );
609  if( !r )
610  return false;
611 
612  if( !( _name == r->_name ) )
613  return false;
614 
615  return Value() == r->Value();
616  }
617 
618  /** Destructor
619  * deletes local storage if we created it */
620  ~DistiAttribute() DISTI_METHOD_OVERRIDE
621  {
622  // Only delete it if we created it.
623  if( _localStorage )
624  {
625  delete _attribPtr;
626  }
627  _attribPtr = NULL;
628  }
629 
630 private:
631  std::istream& ReadValueImpl( std::istream& instr )
632  {
633  GLS_ASSERT( _attribPtr );
634  instr >> *_attribPtr;
635  CallCallback();
636 
637  return instr;
638  }
639 };
640 
641 /** Optimized ReadValueImpl for floating point types.
642  * Visual Studio 2012 (vc110) runtime performs much slower when using
643  * std::istream::operator>>( float& val )
644  */
645 template<>
646 inline std::istream& DistiAttribute<float>::ReadValueImpl( std::istream& instr )
647 {
648  char instrBuf[ 64 ];
649  instr >> instrBuf;
650  *_attribPtr = static_cast<float>( atof( instrBuf ) );
651  CallCallback();
652 
653  return instr;
654 }
655 
656 template<>
657 inline std::istream& DistiAttribute<double>::ReadValueImpl( std::istream& instr )
658 {
659  char instrBuf[ 64 ];
660  instr >> instrBuf;
661  *_attribPtr = atof( instrBuf );
662  CallCallback();
663 
664  return instr;
665 }
666 
667 /** The Attribute Dictionary is a container for DistiAttributeBase derived objects */
668 class DistiAttribDict DISTI_FINAL
669 {
670 public:
671  /** Allows for easy access to the contained class type */
673 
674  typedef std::list<Attr_t> List_t;
675  typedef std::multimap<long, Attr_t> Map_t;
676 
677  typedef List_t::const_iterator const_iterator;
678  typedef List_t::iterator iterator;
679 
680  /** Constructor */
681  DISTI_EXPORT DistiAttribDict();
682 
683  /** Destructor */
684  DISTI_EXPORT ~DistiAttribDict();
685 
686 #if defined( DISTI_HAS_RVAL_REFS )
687  /** Move constructor */
688  DISTI_EXPORT DistiAttribDict( DistiAttribDict&& other )
689  {
690  *this = std::move( other );
691  }
692 
693  /** Move Assignment */
694  DISTI_EXPORT DistiAttribDict& operator=( DistiAttribDict&& other )
695  {
696  if( this != &other )
697  {
698  _list = std::move( other._list );
699  _map = std::move( other._map );
700  }
701  return *this;
702  }
703 #endif
704 
705  /** Used as needed for version specific parsing
706  * Whenever a version is parsed, the results should be stored here.
707  * This does add order dependency.
708  *
709  * Note: These are not set or used by the DistiAttribDict class
710  * they are here to be set and accessed by the derived Attributes.
711  * Since they are shared by all instances of DistiAttribDict, they
712  * are only valid while the dictionary is parsing a file.
713  */
714  static DISTI_EXPORT unsigned int _currentFileVersionMajor;
715  /** \sa _currentFileVersionMajor */
716  static DISTI_EXPORT unsigned int _currentFileVersionMinor;
717  /** \sa _currentFileVersionMajor */
718  static DISTI_EXPORT unsigned int _currentFileVersionBuild;
719 
720  /** \deprecated Do not use. Will be removed in a later version. */
721  static DISTI_EXPORT double _currentFileVersionPrimary;
722  /** \deprecated Do not use. Will be removed in a later version. */
723  static DISTI_EXPORT long _currentFileVersionSecondary;
724 
725  /** Copies the values for all items which have matching names between this object and \a dict.
726  * All other values are ignored
727  * \deprecated Use CopyCommonValues() instead.
728  */
729  DISTI_DEPRECATED( "Renamed to CopyCommonValues() to better represent the action taken by this function." )
730  DISTI_EXPORT DistiAttribDict& operator=( const DistiAttribDict& dict )
731  {
732  CopyCommonValues( dict );
733  return *this;
734  }
735 
736  /** Copies the values for all items which have matching names between this object and \a dict.
737  * All other values are ignored */
738  DISTI_EXPORT void CopyCommonValues( const DistiAttribDict& dict );
739 
740  /** Equality operator
741  * Compares length, names and values.
742  * order does not matter */
743  DISTI_EXPORT bool operator==( const DistiAttribDict& other );
744 
745  /** Adds the specified Attribute to the list.
746  * The object passed in becomes the responsibility
747  * of this class, and should NOT be deleted by the
748  * caller. It will be deleted by this class as needed */
749  DISTI_EXPORT void Add( DistiAttributeBase* attr );
750 
751  const_iterator Begin() const { return _list.begin(); }
752  const_iterator End() const { return _list.end(); }
753  iterator Begin() { return _list.begin(); }
754  iterator End() { return _list.end(); }
755 
756  /** Returns the current number of elements in the dictionary */
757  int DISTI_EXPORT Count() const;
758 
759  /** Returns the number of elements with the same name in the dictionary */
760  int DISTI_EXPORT Count( const AttributeName& name ) const;
761 
762  /** Removes all elements in the list, deleting the data as it goes */
763  void DISTI_EXPORT Clear();
764 
765  /** Removes the attribute specified by name from the dictionary and
766  * deletes the data. This does actually delete the attribute.
767  */
768  DISTI_EXPORT void Delete( const AttributeName& name );
769 
770  /** Reads a stream, expecting each line to be of the form
771  * NAME: SomeStringValue
772  * For each line a new DistiAttribute<std::string> is created,
773  * and the remaining line is placed as it's value.
774  * This is intended for special uses and is not considered
775  * the 'normal' mode of operation */
776  DISTI_EXPORT void ReadStrings( std::istream& instr );
777 
778  /** Writes all items in the dictionary to the stream in the form:
779  * "NAME: VALUE"
780  * If changedDataOnly is true, only items which return ValueChanged() == true
781  * will be written.
782  */
783  DISTI_EXPORT void Write( std::ostream& outstr, bool changedDataOnly = false );
784 
785  /** Reads multiple attributes from the stream expecting the form:
786  * "NAME: VALUE"
787  * Returns true if something was found and set. */
788  DISTI_EXPORT bool Read( std::istream& instr );
789 
790  /** Reads multiple attributes from the stream expecting the form:
791  * "NAME: VALUE"
792  * missing stream is filled with attributes that were not in the dictionary
793  * Returns true if something was found and set. */
794  DISTI_EXPORT bool ReadAndCaptureMissing( std::istream& instr, std::stringstream* missingStream );
795 
796  /** Returns the std::string value of the attribute specified by name
797  * Returns "" if not found
798  * Internally it uses ValueString() from the attribute */
799  DISTI_EXPORT std::string ValueString( const AttributeName& name ) const;
800 
801  /** Sets the attribute of named 'name' to the value of 'val'
802  * If name is not found, there is no indication */
803  DISTI_EXPORT void ValueString( const AttributeName& name, const std::string& val );
804 
805  /** Gets the ValueInt() of the named attribute */
806  DISTI_EXPORT long ValueInt( const AttributeName& name ) const;
807 
808  /** Sets the ValueInt() of the named attribute */
809  DISTI_EXPORT void ValueInt( const AttributeName& name, long val );
810 
811  /** Calls WriteValue() for the attribute specified by name */
812  DISTI_EXPORT std::ostream& WriteValue( const AttributeName& name, std::ostream& outstr );
813 
814  /** Calls ReadValue() for the attribute specified by name */
815  DISTI_EXPORT std::istream& ReadValue( const AttributeName& name, std::istream& instr );
816 
817  /** Returns the DistiAttributeBase* for the specified name
818  * If not found it returns NULL */
819  DISTI_EXPORT DistiAttributeBase* Get( const AttributeName& name ) const;
820 
821  /** Retuns a comparison of val with ValueInt() of the attribute
822  * looked up by name
823  * Returns false if not found */
824  DISTI_EXPORT bool IsEqual( const AttributeName& name, const long val ) const;
825 
826  /** Static, data for formating output */
827  static DISTI_EXPORT int currentOutputSpacing; // Should be private
828 
829  /** Static, Increments the current spacing */
830  static DISTI_EXPORT void SpacingInc();
831 
832  /** Static, Decrements the current spacing */
833  static DISTI_EXPORT void SpacingDec();
834 
835  /** Static, Sets the spacing to zero */
836  static DISTI_EXPORT void SpacingZero();
837 
838  /** Static, Returns a string containing the current spacing */
839  static DISTI_EXPORT std::string SpacingString();
840 
841  /** Static method used for parsing a stream
842  * Used internally and Exposed here so others can use it.
843  */
844  static DISTI_EXPORT bool ScanToken( std::istream& instr, std::string& result );
845 
846  /** Removes the attribute specified by name
847  * This does NOT actually delete the attribute, just removes it from the
848  * dictionary.
849  */
850  DISTI_EXPORT void Remove( const AttributeName& name );
851 
852 private:
853  List_t _list;
854  Map_t _map;
855 
856  /** Disable copy construction.
857  * \note copy-assignment will also be disabled in the future.
858  * \sa CopyCommonValues(). */
859  DistiAttribDict( const DistiAttribDict& ) DISTI_SPECIAL_MEM_FUN_DELETE;
860 };
861 
862 /** Iterator interface for use in range-for loops etc. */
863 inline DistiAttribDict::const_iterator begin( const DistiAttribDict& dict ) { return dict.Begin(); }
864 inline DistiAttribDict::const_iterator end( const DistiAttribDict& dict ) { return dict.End(); }
865 inline DistiAttribDict::iterator begin( DistiAttribDict& dict ) { return dict.Begin(); }
866 inline DistiAttribDict::iterator end( DistiAttribDict& dict ) { return dict.End(); }
867 
868 ////////////////////////////////////////////////////////////
869 // Some useful derivations
870 ////////////////////////////////////////////////////////////
871 
872 /** \class DistiAttributeEnumStringPair
873  * A string to enumeration mapping
874  */
875 typedef struct
876 {
877  char _string[ 64 ];
878  int _enum;
880 
881 /** A list of enumeration definitions */
882 class DistiAttributeEnumDefList : public std::list<DistiAttributeEnumStringPair*>
883 {
884 public:
885  DISTI_EXPORT DistiAttributeEnumDefList( char* stringVal, ... );
886  virtual DISTI_EXPORT int EnumToInt( const std::string& string );
887  virtual DISTI_EXPORT ~DistiAttributeEnumDefList();
888 };
889 
890 /** \class DistiAttributeEnum
891  * A Disti Attribute which reads and writes enumerations.
892  */
893 template<class containerClass, class setType, class getType>
895 {
896 public:
897  typedef void ( containerClass::*SetMethodType )( setType );
898  typedef getType ( containerClass::*GetMethodType )();
899 
900  DistiAttributeEnumDefList* _pairList;
901  containerClass* _object; /* Object that contains the attribute */
902 
903  SetMethodType _setMethod; /* Set method member pointer */
904  GetMethodType _getMethod; /* Get method member pointer */
905 
906  DistiAttributeEnum( containerClass* object, SetMethodType setMethod, GetMethodType getMethod, const AttributeName& name )
907  : DistiAttributeBase( NULL, name, false )
908  , _object( object )
909  , _setMethod( setMethod )
910  , _getMethod( getMethod )
911  {
912  GLS_ASSERT( setMethod );
913  GLS_ASSERT( getMethod );
914  }
915 
916  virtual ~DistiAttributeEnum()
917  {
918  }
919 
920  virtual long ValueInt()
921  {
922  return (long)( _object->*_getMethod )();
923  }
924 
925  virtual void ValueInt( long val )
926  {
927  ( _object->*_setMethod )( (setType)val );
928  };
929 
930  virtual DistiAttributeBase& operator=( const DistiAttributeBase& oldClass )
931  {
933  if( ptr )
934  {
935  ValueInt( ptr->ValueInt() );
936  }
937  else
938  {
939  return DistiAttributeBase::operator=( oldClass );
940  }
941  return *this;
942  }
943 
944  virtual std::ostream& WriteValue( std::ostream& outstr )
945  {
946  bool foundIt = false;
947  getType value = ( _object->*_getMethod )();
948  DistiAttributeEnumDefList::iterator item = _pairList->begin();
949  while( item != _pairList->end() && *item )
950  {
951  if( ( *item )->_enum == value )
952  {
953  outstr << ( *item )->_string;
954  foundIt = true;
955  break;
956  }
957  ++item;
958  }
959  if( !foundIt )
960  {
961  //Didn't find it so just write the number
962  outstr << value;
963  }
964  return outstr;
965  }
966 
967  int EnumToInt( std::string& string )
968  {
969  bool foundIt = false;
970  int returnVal = 0;
971  DistiAttributeEnumDefList::iterator item = _pairList->begin();
972 
973  while( item != _pairList->end() && *item )
974  {
975  if( strcmp( ( *item )->_string, string.c_str() ) == 0 )
976  {
977  foundIt = true;
978  returnVal = ( *item )->_enum;
979  break;
980  }
981  ++item;
982  }
983  return returnVal;
984  }
985 
986  virtual std::istream& ReadValue( std::istream& instr )
987  {
988  char value[ 64 ];
989  instr >> value;
990 
991  bool foundIt = false;
992  DistiAttributeEnumDefList::iterator item = _pairList->begin();
993 
994  // First look by enumeration
995  while( item != _pairList->end() && *item )
996  {
997  if( strcmp( ( *item )->_string, value ) == 0 )
998  {
999  ( _object->*_setMethod )( ( setType )( *item )->_enum );
1000 
1001  foundIt = true;
1002  break;
1003  }
1004  ++item;
1005  }
1006 
1007  // If not found, assume that the numerical value is specified.
1008  if( !foundIt )
1009  {
1010  ( _object->*_setMethod )( (setType)atoi( value ) );
1011  }
1012  return instr;
1013  }
1014 };
1015 
1016 } // namespace disti
1017 
1018 #if defined( WIN32 )
1019 # pragma warning( pop )
1020 #endif
1021 
1022 #endif
The DistiUnhideGlobalsDummyClass class.
bool Copyable() const override
Definition: disti_metadata.h:531
bool IsEqual(const AttributeName &name, const long val) const
virtual DistiAttributeBase & operator=(const DistiAttributeBase &oldClass)
Definition: disti_metadata.h:930
virtual ~AttributeChangedNotifier()
Definition: disti_metadata.h:467
virtual void Call(DistiAttributeBase &attr)=0
virtual bool Copyable() const
virtual bool operator==(const DistiAttributeBase &r)
std::string ValueString(const AttributeName &name) const
DistiAttribDict & operator=(DistiAttribDict &&other)
Definition: disti_metadata.h:694
void CopyCommonValues(const DistiAttribDict &dict)
static long _currentFileVersionSecondary
Definition: disti_metadata.h:723
#define DISTI_DEPRECATED(msg)
Defines whether this compiler supports the C++14 deprecated attribute.
Definition: gls_cpp_lang_support.h:436
static int currentOutputSpacing
Definition: disti_metadata.h:827
bool LocalStorage() const
virtual long ValueInt()
Definition: disti_metadata.h:920
The disti::DynamicArray class. A templated array of objects capable of dynamically growing...
virtual void NotifyObservers()
std::istream & ReadValue(std::istream &instr) override
Definition: disti_metadata.h:588
bool operator!=(const AttributeName &attr1, const AttributeName &attr2)
Definition: disti_metadata.h:152
virtual DistiAttributeBase & operator=(const DistiAttributeBase &oldClass)
void Remove(const AttributeName &name)
AttributeObserver * CreateAttributeResourceCallback(Class *const obj, const char *attributeName)
Definition: disti_metadata.h:450
DistiAttributeBase & operator>>(valType &val)
Definition: disti_metadata.h:329
void ValueFloat(double val) override
Definition: disti_metadata.h:551
static double _currentFileVersionPrimary
Definition: disti_metadata.h:721
DistiAttributeBase & operator<<(const valType &val)
Definition: disti_metadata.h:314
virtual std::ostream & WriteValue(std::ostream &outstr)
Definition: disti_metadata.h:944
double ValueFloat() override
Definition: disti_metadata.h:545
std::istream & ReadValue(const AttributeName &name, std::istream &instr)
Definition: disti_metadata.h:414
std::ostream & WriteValue(std::ostream &outstr) override
Definition: disti_metadata.h:574
DistiAttributeBase & operator=(const DistiAttributeBase &oldClass) override
Definition: disti_metadata.h:557
virtual double ValueFloat()
weak reference and related classes
AttributeName(const std::string &name)
static void SpacingDec()
A file for all GL Studio files to include.
virtual bool ValueChanged()
virtual bool IsValid() const
Definition: disti_metadata.h:388
bool operator==(const DistiAttributeBase &rArg) override
Definition: disti_metadata.h:606
void Call(DistiAttributeBase &attr)
Definition: disti_metadata.h:424
DistiAttribDict(DistiAttribDict &&other)
Definition: disti_metadata.h:688
std::ostream & operator<<(std::ostream &outstr, const AttributeName &name)
Defines the stream out operator.
static std::string SpacingString()
DistiAttributeBase * Attr_t
Definition: disti_metadata.h:672
virtual std::string ValueString()
unsigned int CallbackID
Type for unique identifiers.
Definition: disti_metadata.h:345
void Write(std::ostream &outstr, bool changedDataOnly=false)
virtual bool IsValid() const =0
AttributeName & operator=(const AttributeName &other)
Copy assignment.
Definition: disti_metadata.h:113
Definition: disti_metadata.h:894
DistiAttribute(CallbackMethodCallerBase *callback, const AttributeName &name, T *attribPtr)
Definition: disti_metadata.h:507
virtual void CallCallback()
virtual bool OkToWrite() const
int _precision
Definition: disti_metadata.h:497
Definition: disti_metadata.h:367
#define GLS_ASSERT(exp)
Definition: disti_assert.h:135
bool operator==(const AttributeName &attr1, const AttributeName &attr2)
Definition: disti_metadata.h:144
T * _attribPtr
Definition: disti_metadata.h:495
Definition: disti_metadata.h:491
bool operator==(const DistiAttribDict &other)
virtual bool IsValid() const
Definition: disti_metadata.h:435
AttributeName(const AttributeName &other)
Copy constructor.
Definition: disti_metadata.h:106
~DistiAttribute() override
Definition: disti_metadata.h:620
#define GLS_VERIFY(exp)
Definition: disti_assert.h:155
virtual std::istream & ReadValue(std::istream &instr)
Definition: disti_metadata.h:986
virtual void ValueInt(long val)
Definition: disti_metadata.h:925
static void SpacingInc()
virtual T Value()
Definition: disti_metadata.h:594
ScopedPtr< DistiAttributeObserverList > _observerList
Definition: disti_metadata.h:198
Definition: disti_metadata.h:186
Definition: disti_metadata.h:169
static bool ScanToken(std::istream &instr, std::string &result)
void Call(DistiAttributeBase &ev)
Definition: disti_metadata.h:380
void ReadStrings(std::istream &instr)
Definition: disti_metadata.h:668
Definition: weak_referenceable_mixin.h:52
bool Read(std::istream &instr)
Definition: disti_metadata.h:882
void Delete(const AttributeName &name)
Definition: callback_caller_base.h:55
DistiAttribDict::const_iterator begin(const DistiAttribDict &dict)
Definition: disti_metadata.h:863
bool _localStorage
Definition: disti_metadata.h:204
void ValueInt(long val) override
Definition: disti_metadata.h:539
void SetAndNotifyIfChanged(AttributeChangedNotifier *object, T &property, const T &newValue, const AttributeName &name)
Definition: disti_metadata.h:477
Definition: weak_reference.h:91
long ValueInt(const AttributeName &name) const
static unsigned int _currentFileVersionMinor
Definition: disti_metadata.h:716
CallbackMethodCallerBase * _callback
Definition: disti_metadata.h:195
AttributeObserver * CreateAttributeMethodCallback(Class *const obj, const typename AttributeMethodCallback< Class >::Callback method)
Definition: disti_metadata.h:403
virtual void ResetValueChanged()
virtual CallbackID RegisterObserver(AttributeObserver *observer)
Definition: disti_metadata.h:458
AttributeName _name
Definition: disti_metadata.h:193
bool ReadAndCaptureMissing(std::istream &instr, std::stringstream *missingStream)
void Add(DistiAttributeBase *attr)
Definition: gls_cpp_lang_support.h:449
long StringIndex() const
Returns the index to the string associate with this instance.
Definition: disti_metadata.h:121
static void SpacingZero()
A smart pointer with unique ownership – poor man's std::unique_ptr.
DistiAttribute(CallbackMethodCallerBase *callback, const AttributeName &name, const T &initialValue)
Definition: disti_metadata.h:521
virtual void Value(const T &val)
Definition: disti_metadata.h:599
Definition: disti_metadata.h:875
std::ostream & WriteValue(const AttributeName &name, std::ostream &outstr)
DistiAttributeBase * Get(const AttributeName &name) const
Macros and helper code to determine what subset of C++11/14/17 is available.
virtual void NotifyAttributeChanged(const AttributeName &name)=0
static unsigned int _currentFileVersionBuild
Definition: disti_metadata.h:718
Definition: disti_metadata.h:85
static unsigned int _currentFileVersionMajor
Definition: disti_metadata.h:714
const AttributeName & Name() const
Definition: bmpimage.h:46
long ValueInt() override
Definition: disti_metadata.h:534
virtual std::istream & ReadValue(std::istream &instr)=0
virtual void UnregisterObserver(CallbackID id)
weak reference and related classes
virtual std::ostream & WriteValue(std::ostream &outstr)=0