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