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