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