opennurbs_userdata.h
1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #if !defined(OPENNURBS_USERDATA_INC_)
18 #define OPENNURBS_USERDATA_INC_
19 
20 class ON_CLASS ON_UserData : public ON_Object
21 {
22  ON_OBJECT_DECLARE(ON_UserData);
23 public:
24  ON_UserData();
25  ON_UserData(const ON_UserData&);
27 
28  //////////
29  // The destructor automatically removes the user data
30  // from ON_Object::m_userdata_list.
31  ~ON_UserData();
32 
33  bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
34 
35  /*
36  Description:
37  Overrides virtual ON_Object::Dump().
38  Prints class name, description, and uuid.
39  Parameters:
40  text_log - [in] Information is sent to this text log.
41  Remarks:
42  */
43  void Dump( ON_TextLog& text_log ) const override;
44 
45  /*
46  Description:
47  Overrides virtual ON_Object::SizeOf().
48  Returns:
49  Approximate number of bytes this class uses.
50  */
51  unsigned int SizeOf() const override;
52 
53  ////////
54  // Returns object that owns the user data
55  ON_Object* Owner() const;
56 
57  ////////
58  // Used for traversing list of user data attached
59  // to an object.
60  ON_UserData* Next() const;
61 
62  ////////
63  // Returns the class id which is not necessarily the
64  // same as m_userdata_uuid.
65  ON_UUID UserDataClassUuid() const;
66 
67  //////////
68  // Returns true if the user data is anonymous. This happens
69  // when the user data class is not defined at the time the
70  // user data is read from an archive. For example, if a class
71  // derived from ON_UserData is defined in application A
72  // but is not defined in application B, then the class can be
73  // defined when an archive is written by A but not exist when
74  // an archive is read by B. In this case, the
75  // user data is not lost, it is just read as ON_UnknownUserData
76  // by application B. If application B saves the parent
77  // object in an archive, the unknown user data is resaved in
78  // a form that can be read by application A.
79  bool IsUnknownUserData() const;
80 
81  /*
82  Parameters:
83  description - [out] description of user data shown in
84  object properties dump.
85  Returns:
86  True if user data class is ready.
87  */
88  virtual
89  bool GetDescription( ON_wString& description );
90 
91  /*
92  Description:
93  If Archive() returns true, m_application_uuid is not nil,
94  and the virtual Read() and Write() are functions are overridden,
95  then this user data will be written to and read from 3dm archives.
96 
97  Returns:
98  true if user data should be saved in binary archives.
99  false if the user data should not be saved in binary archives.
100 
101  Remarks:
102  The default implementation returns false. If you override
103  ON_UserData::Archive so that it returns true, then your
104  constructor must set m_application_uuid, you must override
105  the virtual ON_Object::Read and ON_Object::Write functions and
106  you must CAREFULLY TEST your code.
107 
108  ON_UserData requires expert programming and testing skills.
109 
110  If you need to know more details about the archive or
111  parent object to determine if the userdata should be saved,
112  then override WriteToArchive().
113 
114  YOU SHOULD READ AND UNDERSTAND EVERY COMMENT IN THIS
115  HEADER FILE IN BEFORE ATTEMPTING TO USE ON_UserData.
116  */
117  virtual
118  bool Archive() const;
119 
120  /*
121  Description:
122  If WriteToArchive() returns true, m_application_uuid is not nil,
123  and the virtual Read() and Write() are functions are overridden,
124  then this user data will be written to and read from the
125  identified archive.
126 
127  Parameters:
128  archive - [in]
129  The archive being written to. Typically, you will test
130  archive.Archive3dmVersion() to deterime if your userdata
131  should be saved.
132  parent_object - [in]
133  The object managing this userdata.
134  Returns:
135  true if user data should be saved in the binary archives.
136  false if the user data should not be saved in binary archives.
137 
138  Remarks:
139  The default implementation calls the legacy Archive() function.
140  */
141  virtual
142  bool WriteToArchive(
143  const class ON_BinaryArchive& archive,
144  const class ON_Object* parent_object
145  ) const;
146 
147  /*
148  Description:
149  DeleteAfterWrite() is used when opennurbs is writing earlier
150  versions of 3dm archives that used some type of user data that
151  has since become obsolete.
152 
153  Parameters:
154  archive - [in]
155  archive that will be written to.
156  If needed, you can inspect the version of 3dm archive this
157  is being saved and other information that you may need to
158  determine the approprite return value.
159  parent_object - [in]
160  If needed, you can inspect the parent object to determine
161  the approprite return value.
162 
163  Returns:
164  True if the user data should be written the next
165  time the parent object is saved to a 3dm archive and
166  then deleted.
167 
168  Remarks:
169  Typically, DeleteAfterWrite() is used in the situation where
170  1) User data was used to add information to an opennurbs class
171  whose data fields could not be modified because the SDK
172  was fixed at the time.
173  2) Once the class data fields could be modified, the new data
174  fields were added to the class and the user data from step 1
175  became obsolete.
176  3) The class's Write function is called and the value of
177  ON_BinaryArchive::Archive3dmVersion() corresponds to
178  the version of the 3dm archive that was being saved in
179  step 1. The write function fills in and attaches the obsolete
180  user data to the class. When ON_BinaryArchive::WriteObject()
181  writes the obsolete user data to the earlier version file,
182  it then deletes it.
183  */
184  virtual
185  bool DeleteAfterWrite(
186  const class ON_BinaryArchive& archive,
187  const class ON_Object* parent_object
188  ) const;
189 
190  /*
191  Description:
192  DeleteAfterRead() is used when opennurbs is reading earlier
193  versions of 3dm archives that used some type of user data that
194  has since become obsolete.
195 
196  Parameters:
197  archive - [in]
198  archive that was read from.
199  If needed, you can inspect the version of 3dm archive this
200  is being saved and other information that you may need to
201  determine the approprite return value.
202  parent_object - [in]
203  If needed, you can inspect the parent object to determine
204  the approprite return value.
205 
206  Returns:
207  True if the user data should be deleted because the
208  information it contains has been added to the parent
209  object using the methods that are current.
210  */
211  virtual
212  bool DeleteAfterRead(
213  const class ON_BinaryArchive& archive,
214  class ON_Object* parent_object
215  ) const;
216 
217  /*
218  Description:
219  If Transform() return false, then the userdata is destroyed when
220  its parent object is transformed. The default Transform()
221  updates m_userdata_xform and returns true.
222  Carefully read the comments above m_userdata_xform
223  */
224  virtual
225  bool Transform( const ON_Xform& );
226 
227  /*
228  Description:
229  This uuid is the value that must be passed to
230  ON_Object::GetUserData() to retrieve
231  this piece of user data.
232  */
233  ON_UUID m_userdata_uuid;
234 
235  /*
236  Description:
237  This uuid is used to identify the application that
238  created this piece of user data. In the case of
239  Rhino, this is the id of the plug-in that created
240  the user data. User data with a nil application id
241  will not be saved in 3dm archives.
242  */
243  ON_UUID m_application_uuid;
244 
245  ////////
246  // If m_userdata_copycount is 0, user data is not copied when
247  // object is copied. If > 0, user data is copied and m_copycount
248  // is incremented when parent object is copied. The user data's
249  // operator=() is used to copy.
250  // The default ON_UserData::ON_UserData() constructor sets
251  // m_userdata_copycount to zero.
252  unsigned int m_userdata_copycount;
253 
254  ////////
255  // Updated if user data is attached to a piece of geometry that is
256  // transformed and the virtual ON_UserData::Transform() is not
257  // overridden. If you override ON_UserData::Transform() and want
258  // m_userdata_xform to be updated, then call the
259  // ON_UserData::Transform() in your override.
260  // The default constructor sets m_userdata_xform to the identity.
261  ON_Xform m_userdata_xform;
262 
263 private: // don't look and don't touch - these may change
264  friend class ON_Object;
265  friend int ON_BinaryArchive::ReadObject( ON_Object** );
266  friend bool ON_BinaryArchive::WriteObject( const ON_Object& );
268  friend bool ON_BinaryArchive::WriteObjectUserData( const ON_Object& );
269  ON_Object* m_userdata_owner;
270  ON_UserData* m_userdata_next;
271 };
272 
273 class ON_CLASS ON_UnknownUserData : public ON_UserData
274 {
275  ON_OBJECT_DECLARE(ON_UnknownUserData);
276  // used to hold user data when the application class is not loaded
277  // at time data is read
278 public:
283 
284  // ON_Object overrides
285 
286  bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
287  void Dump( ON_TextLog& ) const override;
288  bool Write( ON_BinaryArchive& ) const override;
289  bool Read( ON_BinaryArchive& ) override;
290 
291  unsigned int SizeOf() const override; // return amount of memory used by user data
292  bool GetDescription( ON_wString& ) override; // description of user data
293  bool Archive() const override;
294 
295  // Convert unknown user data to actual user data. Useful if
296  // definition of actual user data is dynamically linked after
297  // archive containing user data is read.
298  ON_UserData* Convert() const;
300  /*
301  Description:
302  This is the uuid of the missing class. This uuid
303  is the 3rd parameter to the ON_OBJECT_IMPLEMENT()
304  macro of the missing class.
305  */
306  ON_UUID m_unknownclass_uuid;
307  int m_sizeof_buffer;
308  void* m_buffer;
309 
310  // These version numbers are set when unknown user data is read
311  // from a file record the version of the 3dm archive and the
312  // version of opennurbs that were used when the plug-in wrote
313  // the user data.
314  // This information was added in to V5 opennurbs 200910190.
315  // For files written with earlier versions of opennurbs, these
316  // values are set from the archive containing the user data.
317  // The purpose of this version information is to have it accompany
318  // unknown user data so that if is is eventually read by the plug-in
319  // an ON_BinaryArchive with correct version information can be
320  // passed to the plug-in's reading code. In archives, these values
321  // are stored in the TCODE_USER_TABLE_RECORD_HEADER chunk.
322  int m_3dm_version; // 3dm archive version (0,1,2,3,4,5,50,...)
323 
325  // In V5 and earlier, m_3dm_opennurbs_version had the format YYYYMMDDN
326  // For V6 the unsigned int value is calculated by ON_VersionNumberConstruct()
327  // and has the high bit set (it will be negative if used as a signed int).
328  // When writing files in previous version formats (V5 or earlier) it is important
329  // to write a YYYYMMDDN version number in the file. Use ON_VersionNumberParse()
330  // get the YYYY, MM, DD and N values from m_3dm_opennurbs_version.
331  unsigned int m_3dm_opennurbs_version_number;
332 };
333 
334 class ON_CLASS ON_ObsoleteUserData : public ON_UserData
335 {
336  ON_OBJECT_DECLARE(ON_ObsoleteUserData);
337  // used to write obsolete user data when earlier versions
338  // of 3dm archives are written and the class id for the
339  // earlier version of the user data is still in use
340  // in the current version of opennurbs.
341 public:
343  virtual ~ON_ObsoleteUserData();
347  // This is the user data class id that will be saved in the 3dm archive.
348  ON_UUID m_archive_class_uuid;
349 };
350 
351 // Do not export this class
352 // It is used internally to read and write 3dm achives with versions < 60.
354 {
355  // NO ON_OBJECT_DECLARE() for classes derived from ON_ObsoleteUserData
356 private:
357  static const ON_UUID m_archive_class_id_ctor;
358  static const ON_UUID m_archive_userdata_uuid_ctor;
359  static const ON_UUID m_archive_application_uuid_ctor;
360  static const unsigned int m_userdata_copycount_ctor;
361  static const ON_Xform m_userdata_xform_ctor;
362 
363 public:
364  static bool IsRdkMaterialInstanceIdUserData(
365  ON_UUID class_id,
366  ON_UUID userdata_id,
367  ON_UUID app_id,
368  ON_Object* object
369  );
370 
375 
376  // virtual ON_Object override
377  bool Read(
379  ) override;
380 
381  // virtual ON_Object override
382  bool Write(
384  ) const override;
385 
386  // virtual ON_UserData override
387  bool GetDescription(ON_wString& description) override;
388 
389  // virtual ON_UserData override
390  bool WriteToArchive(
391  const class ON_BinaryArchive& archive,
392  const class ON_Object* parent_object
393  ) const override;
394 
395  // virtual ON_UserData override
396  bool DeleteAfterWrite(
397  const ON_BinaryArchive& archive,
398  const ON_Object* parent_object
399  ) const override;
401  // virtual ON_UserData override
402  bool DeleteAfterRead(
403  const ON_BinaryArchive& archive,
404  ON_Object* parent_object
405  ) const override;
406 
407  ON_UUID m_rdk_material_instance_id;
408 };
409 
410 class ON_CLASS ON_UserStringList : public ON_UserData
411 {
412  ON_OBJECT_DECLARE(ON_UserStringList);
413 public:
414 
417 
418  static ON_UserStringList* FromObject(
419  const ON_Object*
420  );
421 
422  // override virtual ON_Object::Dump function
423  void Dump( ON_TextLog& text_log ) const override;
424 
425  // override virtual ON_Object::SizeOf function
426  unsigned int SizeOf() const override;
427 
428  // override virtual ON_Object::DataCRC function
429  ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override;
430 
431  // override virtual ON_Object::Write function
432  bool Write(ON_BinaryArchive& binary_archive) const override;
433 
434  // override virtual ON_Object::Read function
435  bool Read(ON_BinaryArchive& binary_archive) override;
436 
437  // override virtual ON_UserData::GetDescription function
438  bool GetDescription( ON_wString& description ) override;
439 
440  // override virtual ON_UserData::Archive function
441  bool Archive() const override;
442 
443  /*
444  Description:
445  Add, replace or remove a user string.
446  Parameters:
447  key - [in]
448  must be a non-empty string. If an entry with the same key
449  (case insensitive compares are used) exists, the existing
450  entry is updated.
451  string_value - [in]
452  If string_value is empty and an entry with a matching key
453  exists, the entry is deleted.
454  Returns:
455  True if the key is valid.
456  */
457  bool SetUserString( const wchar_t* key, const wchar_t* string_value );
458 
459  bool GetUserString( const wchar_t* key, ON_wString& string_value ) const;
460 
461  /*
462  Description:
463  Append entries to the user string list
464  Parameters:
465  count - [in]
466  number of element in us[] array
467  us - [in]
468  entries to append.
469  bReplace - [in]
470  If bReplace is true, then existing entries with the same key are
471  updated with the new entry's value. If bReplace is false, then
472  existing entries are not updated.
473  Returns:
474  Number of entries added, deleted, or modified.
475  */
476  int SetUserStrings( int count, const ON_UserString* us, bool bReplace );
477 
479 };
480 
481 class ON_CLASS ON_UserDataHolder : public ON_Object
482 {
483 public:
484 
485  /*
486  Description:
487  Transfers the user data from source_object to "this".
488  When MoveUserDataFrom() returns source_object will not
489  have any user data. If "this" had user data when
490  MoveUserDataFrom() was called, then that user data is
491  destroyed.
492  Parameters:
493  source_object - [in] The "const" is a lie. It is
494  there because, in practice the source object is frequently
495  const and const_cast ends up being excessively used.
496  Returns:
497  Number of user data items that were moved from source_object to "this" ON_UserDataHolder.
498  */
499  unsigned int MoveUserDataFrom(
500  const ON_Object& source_object
501  );
502 
503 
504  /*
505  Description:
506  Copies the data from source_object with copy_count > 0 to "this" ON_UserDataHolder.
507  Parameters:
508  source_object - [in]
509  This object and it's user data are not modified.
510  user_data_item_id - [in]
511  If not nil, then only userdata with this item id will be coped
512  Returns:
513  Number of user data items that were copied from source_object to "this" ON_UserDataHolder.
514  */
515  unsigned int CopyUserDataFrom(
516  const ON_Object& source_object,
517  ON_UUID user_data_item_id
518  );
519 
520  /*
521  Description:
522  Moves the user data on "this" ON_UserDataHolder to destination_object.
523  When MoveUserDataTo() returns "this" ON_UserDataHolder will not have any user data.
524  Parameters:
525  destination_object - [in] The "const" is a lie. It is
526  there because, in practice the source object is generally
527  const and const_cast ends up being constantly used.
528  bAppend - [in]
529  true:
530  Existing user data on destination_object is left unchanged.
531  MoveUserDataTo( destination_object, true ) is identical to calling
532  MoveUserDataTo( destination_object, ON_Object::UserDataConflictResolution::destination_object).
533  false:
534  Existing user data on destination_object is destroyed.
535  Returns:
536  Number of user data items moved from "this" ON_UserDataHolder to destination_object.
537  */
538  unsigned int MoveUserDataTo(
539  const ON_Object& destination_object,
540  bool bAppend
541  );
542 
543  /*
544  Description:
545  Moves the user data on "this" ON_UserDataHolder to destination_object.
546  When MoveUserDataTo() returns "this" ON_UserDataHolder will not have any user data.
547  Parameters:
548  destination_object - [in]
549  The "const" is a lie. It is there because, in practice the source object is generally
550  const and const_cast ends up being constantly used.
551  user_data_item_id - [in]
552  If not nil, then only user data items with this id will be considered for moving.
553  userdata_conflict_resolution - [in]
554  If destination_object and "this" ON_UserDataHolder have the same
555  type of user data item, then userdata_conflict_resolution
556  is used to determine if that destination_object user data item
557  is replaced with the one on "this" ON_UserDataHolder.
558  Returns:
559  Number of user data items moved from "this" ON_UserDataHolder to destination_object.
560  */
561  unsigned int MoveUserDataTo(
562  const ON_Object& destination_object,
563  ON_UUID user_data_item_id,
564  ON_Object::UserDataConflictResolution userdata_conflict_resolution
565  );
566 
567 
568  bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
569 };
570 
571 /*
572 Description:
573  An ON_DocumentUserStringList object is saved in the list of user
574  tables. The Rhino SetDocumentText and GetDocumentText
575  commands use the ON_Object SetUserString, GetUserString,
576  GetUserStrings, GetUserStringKeys functions on an
577  ON_DocumentUserStringList class to manage the tag-value pairs of
578  strings.
579 */
580 class ON_CLASS ON_DocumentUserStringList : public ON_Object
581 {
582  ON_OBJECT_DECLARE(ON_DocumentUserStringList);
583 public:
586 
587  bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
588  void Dump( ON_TextLog& ) const override;
589  ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override;
590  bool Write(ON_BinaryArchive& binary_archive) const override;
591  bool Read(ON_BinaryArchive& binary_archive) override;
592 
593  // Use the
594  // ON_Object::SetUserString()
595  // ON_Object::GetUserString()
596  // ON_Object::GetUserStrings()
597  // ON_Object::GetUserStringKeys()
598  // ON_Object::UserStringCount()
599  // functions to access and modify user string information.
600 };
601 
602 #endif
unsigned int SizeOf() const override
Overrides virtual ON_Object::SizeOf().
Definition: opennurbs_object.h:425
ON_UUID is a 16 byte universally unique identifier.
Definition: opennurbs_uuid.h:32
virtual bool GetDescription(ON_wString &description)
Definition: opennurbs_userdata.h:267
void Dump(ON_TextLog &text_log) const override
Overrides virtual ON_Object::Dump(). Prints class name, description, and uuid.
Definition: opennurbs_string.h:2020
int ReadObject(ON_Object **ppObject)
Reads and object from a 3dm archive;
bool WriteObject(const ON_Object *)
UserDataConflictResolution
When a userdata item is copied or moved from a source object to a destination object, the ON_Object::UserDataConflictResolution enum values specify how conficts are resolved. Remark: A userdata item "conflict" occurs when both the destination and source object have a user data item with the same value of ON_UserData::m_userdata_uuid.
Definition: opennurbs_object.h:861
virtual bool Archive() const
If Archive() returns true, m_application_uuid is not nil, and the virtual Read() and Write() are func...
bool WriteObjectUserData(const ON_Object &object)
Low level tool to writes user data attached to the object. This function should never be called direc...
virtual unsigned int SizeOf() const
bool IsValid(class ON_TextLog *text_log=nullptr) const override
Tests an object to see if its data members are correctly initialized.
Definition: opennurbs_xform.h:28
Definition: opennurbs_userdata.h:472
Definition: opennurbs_userdata.h:346
virtual void Dump(ON_TextLog &) const
Creates a text dump of the object.
ON_Object & operator=(const ON_Object &)
virtual bool IsValid(class ON_TextLog *text_log=nullptr) const
Tests an object to see if its data members are correctly initialized.
An ON_DocumentUserStringList object is saved in the list of user tables. The Rhino SetDocumentText an...
Definition: opennurbs_userdata.h:568
Pure virtual base class for all classes that must provide runtime class id or support object level 3D...
Definition: opennurbs_object.h:460
Definition: opennurbs_userdata.h:327
Definition: opennurbs_textlog.h:20
ON_UserData & operator=(const ON_UserData &)
Definition: opennurbs_archive.h:1783
Definition: opennurbs_userdata.h:20
virtual bool Read(ON_BinaryArchive &binary_archive)
Low level archive writing tool used by ON_BinaryArchive::ReadObject().
bool ReadObjectUserData(ON_Object &object)
Low level tool to read user data and attach it to the object. This function should never be called di...
virtual bool Write(ON_BinaryArchive &binary_archive) const
Low level archive writing tool used by ON_BinaryArchive::WriteObject().
Definition: opennurbs_userdata.h:403