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