opennurbs_archive.h
1 /*
2 //
3 // Copyright (c) 1993-2016 Robert McNeel & Associates. All rights reserved.
4 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
5 // McNeel & Associates.
6 //
7 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
8 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
9 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
10 //
11 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
12 //
13 ////////////////////////////////////////////////////////////////
14 */
15 
16 #if !defined(ON_ARCHIVE_INC_)
17 #define ON_ARCHIVE_INC_
18 
19 
20 /////////////////////////////////////////////////////////////////////
21 //
22 // ON_Buffer
23 //
24 
25 typedef void (*ON_Buffer_ErrorHandler)(class ON_Buffer*);
26 
27 class ON_CLASS ON_Buffer
28 {
29 public:
30  ON_Buffer();
31  ~ON_Buffer();
32 
33  ON_Buffer(const ON_Buffer& src);
34  ON_Buffer& operator=(const ON_Buffer& src);
35 
36  /*
37  Description:
38  Compare contents of buffers.
39  Paramters:
40  a - [in]
41  b - [in]
42  Returns:
43  -1: a < b
44  0: a == b
45  1: a > b
46  */
47  static int Compare( const ON_Buffer& a, const ON_Buffer& b );
48 
49  void Destroy();
50  void EmergencyDestroy();
51 
52  /*
53  Returns:
54  True if Size() == CurrentPosition().
55  Remarks:
56  It is possible to seek beyond the end of the buffer.
57  In this case, the current position will be past the end
58  of the buffer and AtEnd() will return false.
59  */
60  bool AtEnd() const;
61 
62  /*
63  Returns:
64  Number of bytes currently in the buffer.
65  Remarks:
66  It is possible to seek beyond the end of the buffer.
67  In this case, the current position will be past the end
68  of the buffer and CurrentPosition() will be greater than
69  Size().
70  */
71  ON__UINT64 Size() const;
72 
73  /*
74  Returns:
75  32-bit CRC of the buffer contents.
76  Remarks:
77 
78  */
79  ON__UINT32 CRC32( ON__UINT32 current_remainder ) const;
80 
81 
82  /*
83  Returns:
84  Current position in the buffer.
85  Remarks:
86  It is possible to seek beyond the end of the buffer.
87  In this case, the current position will be past the end
88  of the buffer and CurrentPosition() will be greater than
89  Size().
90  */
91  ON__UINT64 CurrentPosition() const;
92 
93  /*
94  Parameters:
95  size - [in]
96  number of bytes to write.
97  buffer - [in]
98  values to write.
99  Returns:
100  Number of bytes written buffer.
101  */
102  ON__UINT64 Write( ON__UINT64 size, const void* buffer );
103 
104  /*
105  Parameters:
106  size - [in]
107  number of bytes to read.
108  buffer - [out]
109  read values are returned in buffer.
110  Returns:
111  Number of bytes read into buffer. For example,
112  if CurrentPosition() <= Size() and
113  size > (Size() - CurrentPosition()) and
114  buffer is not null, then the value
115  (Size() - CurrentPosition()) is returned.
116  Remarks:
117  If the size parameter is zero, then nothing is done.
118  When CurrentPosition() <= Size(), attempts to read more
119  than (Size() - CurrentPosition()) bytes do not generate
120  an error. When CurrentPosition() > Size(), any attempt
121  to read generates an error.
122  */
123  ON__UINT64 Read( ON__UINT64 size, void* buffer );
124 
125  enum
126  {
127  seek_from_beginning_of_file = 0,
128  seek_from_current_position = 1,
129  seek_from_end_of_file = 2
130  };
131 
132  /*
133  Parameters:
134  offset - [in]
135  number of bytes to seek from origin
136  origin - [in]
137  initial position.
138  0 (SEEK_SET) Seek from beginning of file.
139  1 (SEEK_CUR) Seek from current position.
140  2 (SEEK_END) Seek from end of file.
141  Returns:
142  True if successful.
143  False if the seek would result in a file position
144  before the beginning of the file. If false is
145  returned, the current position is not changed.
146  Remarks:
147  Seeking beyond the end of the buffer is succeeds.
148  Seeking before the beginning of the buffer fails.
149  */
150  bool Seek(
151  ON__INT64 offset,
152  int origin
153  );
154 
155  /*
156  Parameters:
157  offset - [in] (>= 0)
158  number of bytes to seek from the start of the buffer.
159  Returns:
160  True if successful.
161  False if the seek would result in a file position
162  before the beginning of the file. If false is
163  returned, the current position is not changed.
164  Remarks:
165  Seeking beyond the end of the buffer is succeeds.
166  Seeking before the beginning of the buffer fails.
167  */
168  bool SeekFromStart( ON__INT64 offset );
169 
170  /*
171  Parameters:
172  offset - [in]
173  number of bytes to seek from the current position.
174  Returns:
175  True if successful.
176  False if the seek would result in a file position
177  before the beginning of the file. If false is
178  returned, the current position is not changed.
179  Remarks:
180  Seeking beyond the end of the buffer is succeeds.
181  Seeking before the beginning of the buffer fails.
182  */
183  bool SeekFromCurrentPosition( ON__INT64 offset );
184 
185  /*
186  Parameters:
187  offset - [in]
188  number of bytes to seek from the end fo the buffer.
189  Returns:
190  True if successful.
191  False if the seek would result in a file position
192  before the beginning of the file. If false is
193  returned, the current position is not changed.
194  Remarks:
195  Seeking beyond the end of the buffer is succeeds.
196  Seeking before the beginning of the buffer fails.
197  */
198  bool SeekFromEnd( ON__INT64 offset );
199 
200  /*
201  Parameters:
202  buffer_size - [in]
203  new size of buffer.
204  Returns:
205  True if successful.
206  Remarks:
207  The current position is not changed and may be beyond the
208  end of the file. Use Seek to set the current position after
209  calling ChangeSize().
210  */
211  bool ChangeSize( ON__UINT64 buffer_size );
212 
213  /*
214  Description:
215  Return unused memory to heap.
216  Remarks:
217  Call this function after creating an ON_Buffer that will persist for
218  and extended amount of time. There are never more than 16 pages of
219  unsued memory (16*4096 bytes on most computers) in an ON_Buffer.
220  Compact() can be called at any time, but calling Compact() the then
221  writing at the end of the buffer is not an efficient use of time
222  or memory.
223  */
224  bool Compact();
225 
226  /*
227  Returns
228  True if the ON_Buffer is valid.
229  */
230  bool IsValid( const ON_TextLog* text_log ) const;
231 
232  /*
233  Returns:
234  Value that identifies most recent error.
235  0: no error
236  1: attempt to seek to a negative position
237  */
238  ON__UINT32 LastError() const;
239 
240  void ClearLastError();
241 
242  ON_Buffer_ErrorHandler ErrorHandler() const;
243 
244  void SetErrorHandler(ON_Buffer_ErrorHandler error_handler);
245 
246  /*
247  Description:
248  Use WriteToBinaryArchive() to save an entire ON_Buffer inside
249  a binary archive. Use ReadFromBinaryArchive() to retrieve
250  the ON_Buffer from the ON_BinaryArchive.
251  */
252  bool WriteToBinaryArchive( ON_BinaryArchive& ) const;
253 
254  /*
255  Description:
256  Use ReadFromBinaryArchive() to retrieve an entire ON_Buffer
257  that was written using WriteToBinaryArchive().
258  */
259  bool ReadFromBinaryArchive( ON_BinaryArchive& );
260 
261  /*
262  Description:
263  Compress this buffer
264 
265  Parameters:
266  compressed_buffer - [out]
267  (The reference can be *this)
268 
269  Example:
270 
271  // compress a buffer in place
272  ON_Buffer buffer;
273  buffer = ...;
274  if ( !buffer.Compress(buffer) )
275  {
276  // compression failed
277  }
278  else
279  {
280  // buffer is now compressed
281  }
282 
283  Returns:
284  True if successful. False if failed.
285  */
286  bool Compress( ON_Buffer& compressed_buffer ) const;
287 
288  /*
289  Description:
290  Uncompress this buffer which must have been compressed using
291  ON_Buffer::Compress().
292 
293  Parameters:
294  uncompressed_buffer - [out]
295  (The reference can be *this)
296 
297  Example:
298  // silly example that compresses and then uncompresses a buffer in place
299  // to show how to call the functions.
300  ON_Buffer buffer;
301  buffer = ...; // buffer is in it uncompressed form
302  if ( buffer.Compress(buffer) )
303  {
304  // buffer is now compressed
305  if ( buffer.Uncompress(buffer) )
306  {
307  // buffer is uncompressed again.
308  }
309  }
310 
311  Returns:
312  True if successful. False if failed.
313  */
314  bool Uncompress( ON_Buffer& uncompressed_buffer ) const;
315 
316 private:
317 
318  ON__UINT64 m_buffer_size; // total number of bytes in the buffer
319  ON__UINT64 m_current_position;
320 
321  struct ON_BUFFER_SEGMENT* m_first_segment;
322  struct ON_BUFFER_SEGMENT* m_last_segment;
323  struct ON_BUFFER_SEGMENT* m_current_segment;
324  bool SetCurrentSegment(bool);
325  void Copy( const ON_Buffer& );
326 
327  ON_Buffer_ErrorHandler m_error_handler;
328 
329  ON__UINT32 m_last_error;
330  unsigned char m_reserved[12];
331 };
332 
333 /////////////////////////////////////////////////////////////////////
334 //
335 // ON_BinaryArchive
336 // virtual class for CPU independent serialization
337 //
338 // ON_BinaryFile
339 // simple class for CPU independent binary file I/O
340 // includes optional CRC support
341 //
342 
344 {
345  size_t m_offset; // In read or write_using_fseek mode, this is the
346  // file position of first byte after chunk's length.
347  // In write_using_buffer mode, this of the m_buffer[]
348  // position of first byte after chunk's length.
349  unsigned int m_typecode;
350  int m_value;
351  int m_do_length; // true if chunk is a long chunk with length
352  ON__UINT16 m_do_crc16; // 16 bit CRC using CCITT polynomial
353  ON__UINT16 m_crc16;
354  ON__UINT32 m_do_crc32; // 32 bit CRC
355  ON__UINT32 m_crc32;
356 };
357 
358 class ON_CLASS ON_3DM_BIG_CHUNK
359 {
360 public:
361  ON_3DM_BIG_CHUNK() = default;
362  ~ON_3DM_BIG_CHUNK() = default;
363  ON_3DM_BIG_CHUNK(const ON_3DM_BIG_CHUNK&) = default;
364  ON_3DM_BIG_CHUNK& operator=(const ON_3DM_BIG_CHUNK&) = default;
366 public:
367  ON__UINT64 m_start_offset=0; // When reading or writing 3dm archives, this is the
368  // archive offset (file position) of first byte of
369  // chunk information conent.
370 
371  ON__UINT64 m_end_offset=0; // When writing 3dm archives, this is the archive
372  // offset (file position) of the byte immediately after
373  // the farthest successful write.
374  // When reading 3dm archives, this the archive offset
375  // of the first byte after the chunk's information content.
376  // When reading, a 16 bit or 32 bit CRC can follow the chunk
377  // information content.
378  // During ordinary reading and writing, valid seek target
379  // positions satisfy
380  // m_start_offset <= seek target pos <= m_end_offset.
381 
382  /*
383  Returns:
384  Number of bytes in the chunk, including bytes used to store CRC values.
385  0 for short chunks.
386  0 for chunks currently being written.
387  Remarks:
388  For chunks being read,
389  m_start_offset + Length() = m_end_offset + SizeofCRC().
390  */
391  ON__UINT64 Length() const;
392 
393  /*
394  Parameters:
395  current_position - [in]
396  Value of ON_BinaryArchive.CurrentPosition()
397 
398  Returns:
399  Number of bytes that can be read when ON_BinaryArchive ReadMode() is true.
400  */
401  ON__UINT64 LengthRemaining(
402  ON__UINT64 current_position
403  ) const;
405  /*
406  Returns:
407  0: no CRC
408  4: 32 bit CRC (4 bytes)
409  2: 16 bit CRC (2 bytes)
410  */
411  ON__UINT64 SizeofCRC() const;
412 
413  ON__INT64 m_big_value=0;
414  ON__UINT32 m_typecode=0;
415  ON__UINT8 m_bLongChunk=0; // true if chunk is a long chunk and m_big_value is a length.
417 private:
418  ON__UINT8 m_reserved1=0;
419  ON__UINT8 m_reserved2=0;
420  ON__UINT8 m_reserved3=0;
421 
422 public:
423  // CRC settings
424  ON__UINT8 m_do_crc16=0; // true (1) if we are calculating 16 bit CRC
425  ON__UINT8 m_do_crc32=0; // true (1) if we are calculating 32 bit CRC
426  ON__UINT16 m_crc16=0; // current 16 bit CRC value
427  ON__UINT32 m_crc32=0; // current 32 bit CRC value
428 };
429 
430 bool ON_IsLongChunkTypecode(ON__UINT32 typecode);
431 
432 bool ON_IsShortChunkTypecode(ON__UINT32 typecode);
433 
434 #if defined(ON_DLL_TEMPLATE)
435 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_3DM_CHUNK>;
436 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_3DM_BIG_CHUNK>;
437 #endif
438 
439 // Used int ON_3dmProperties::Read() to set ON_BinaryArchive.m_3dm_opennurbs_version
440 // Do not call directly.
441 void ON_SetBinaryArchiveOpenNURBSVersion(ON_BinaryArchive&,unsigned int);
442 
443 class ON_CLASS ON_UserDataItemFilter
444 {
445 public:
447 
449  ON_UUID application_id,
450  bool bSerialize
451  );
452 
454  ON_UUID application_id,
455  ON_UUID item_id,
456  bool bSerialize
457  );
458 
459  static int Compare(
460  const class ON_UserDataItemFilter*,
461  const class ON_UserDataItemFilter*
462  );
463 
464  // The application id can be the id for a plug-in, Rhino or opennurbs
465  ON_UUID m_application_id;
466 
467  // The item id for object user data is the value of ON_UserData.m_userdata_uuid.
468  // The item id for user table is the application id.
469  // A nil item id indicates the setting is applied to all object user data
470  // and user table information for the specified application.
471  ON_UUID m_item_id;
472 
473  // If application id and item id match and m_bSerializeEnabled,
474  // does not match, then the ON_UserDataItemFilter with the
475  // largest value of m_precedence is used.
476  unsigned int m_precedence;
477 
478  // bSerializationEnabled is true if reading and writing are permitted.
479  // bSerializationEnabled is false if reading and writing are prevented.
480  bool m_bSerialize;
481 };
482 
483 #if defined(ON_DLL_TEMPLATE)
484 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_UserDataItemFilter>;
485 #endif
486 
487 class ON_CLASS ON_ComponentManifest
488 {
489 public:
490  // The default constructor would work prfectly,
491  // except there is a bug in Apple's CLANG that
492  // requires either an explicitly implemented constructor
493  // or an explicitly implemented copy constructor together
494  // with a hack to initialize the static ON_ComponentManifest::Empty.
495  // Apple CLANG BUG // ON_ComponentManifest() = default;
496  ON_ComponentManifest() ON_NOEXCEPT;
499 
500  static const ON_ComponentManifest Empty;
501 
502  void Reset();
503 
504  enum : int
505  {
506  UnsetComponentIndex = ON_UNSET_INT_INDEX
507  };
508 
509 private:
511  ON_ComponentManifest& operator=(const ON_ComponentManifest&) = delete;
512 
513 public:
514 
515  /*
516  Total number of items in the manifest, including items referencing system components and deleted items.
517  */
518  unsigned int ItemCount() const;
519 
520  /*
521  Parameters:
522  component_type - [in]
523  If component_type is ON_ModelComponent::Type::Unset or ON_ModelComponent::Type::Mixed,
524  then the every explict component type is counted.
525  Returns:
526  Total number of model components of the specified type in this manifest.
527  Remarks:
528  The count includes active, deleted, and system components.
529  */
530  unsigned int TotalComponentCount(
531  ON_ModelComponent::Type component_type
532  ) const;
533 
534  /*
535  Parameters:
536  component_type - [in]
537  If component_type is ON_ModelComponent::Type::Unset or ON_ModelComponent::Type::Mixed,
538  then the every explict component type is counted.
539  Returns:
540  Number of model components of the specified type in this manifest.
541  Remarks:
542  The count includes active and deleted components.
543  The count does not include system components (those added by calling AddSystemComponentToManifest()).
544  */
545  unsigned int ActiveAndDeletedComponentCount(
546  ON_ModelComponent::Type component_type
547  ) const;
548 
549  /*
550  Parameters:
551  component_type - [in]
552  If component_type is ON_ModelComponent::Type::Unset or ON_ModelComponent::Type::Mixed,
553  then the every explict component type is counted.
554  Returns:
555  Number of active model components of the specified type in this manifest.
556  Remarks:
557  The count does not include deleted components (IsDeleted() = true).
558  The count does not include system components (those added by calling AddSystemComponentToManifest()).
559  */
560  unsigned int ActiveComponentCount(
561  ON_ModelComponent::Type component_type
562  ) const;
563 
564  /*
565  Parameters:
566  component_type - [in]
567  If component_type is ON_ModelComponent::Type::Unset or ON_ModelComponent::Type::Mixed,
568  then the every explict component type is counted.
569  Returns:
570  Number of model components of the specified type in this manifest that have IsDeleted() = true.
571  Remarks:
572  System components cannot be deleted.
573  */
574  unsigned int DeletedComponentCount(
575  ON_ModelComponent::Type component_type
576  ) const;
577 
578  unsigned int SystemComponentCount(
579  ON_ModelComponent::Type component_type
580  ) const;
581 
582  /*
583  Parameters:
584  component_type - [in]
585  Returns:
586  If the component type is indexed, then all current manifest indices
587  for the component_type are >= 0 and < ComponentIndexLimit().
588  Otherwise 0 is returned.
589  */
590  int ComponentIndexLimit(
591  ON_ModelComponent::Type component_type
592  ) const;
593 
594  /*
595  Description:
596  Add a component to this manifest.
597  If the id is not set or not unique, the component will not be added.
598  If a unique name is required and the name is not set or not unique,
599  the component will not be added.
600  Parameters:
601  component - [in]
602  If you want to update the component id, index and name values to
603  match the ones assigned in the manifest, then call
604  component.SetIdentification(manifest_item),
605  where manifest_item is the information returned by this function.
606  bResolveIdAndNameCollisions - [in]
607  If false, then the component parameter id must not be used in the
608  manifest and, when required, the name must be set and unique.
609  If true and a new id or name is required, one will be assigned.
610  Note that the component parameter is const and its id and name
611  are not modified.
612  assigned_name - [out]
613  If not null, the assigned name is returned here.
614  Returns:
615  If an item is added to this manifest, then the assigned
616  identification information is returned.
617  Otherwise ON_ComponentManifestItem::Unset is returned.
618  Note the manifest index is generally different from component.Index().
619  Remarks:
620  Use
621  */
622  const class ON_ComponentManifestItem& AddComponentToManifest(
623  const class ON_ModelComponent& component,
624  bool bResolveIdAndNameCollisions,
625  ON_wString* assigned_name
626  );
627 
628  const class ON_ComponentManifestItem& AddSystemComponentToManifest(
629  const class ON_ModelComponent& component
630  );
631 
632 
633  /*
634  Description:
635  Add a component to this manifest.
636  Parameters:
637  component_type - [in]
638  Type of component.
639  component_serial_number - [in]
640  0 or the component's unique runtime serial number (ON_ModelComponent::RuntimeSerialNumber()).
641  component_id - [in]
642  component_name_hash - [in]
643  If the the component type requires a unique name and the name
644  is not valid or in use, the component will not be added.
645  Returns:
646  If an item is added to this manifest, then the identification
647  information is returned.
648  Otherwise ON_ComponentManifestItem::Unset is returned.
649  Note:
650  The manifest index is assigned to components that require an index.
651  */
652  const class ON_ComponentManifestItem& AddComponentToManifest(
653  ON_ModelComponent::Type component_type,
654  ON__UINT64 component_serial_number,
655  ON_UUID component_id,
656  const ON_NameHash& component_name_hash
657  );
658 
659  /*
660  Description:
661  Add a component to this manifest.
662  If the id is not set or in use, then a new one will be assigned.
663  If the component type requires a unique name and the name is not set or in use,
664  then a new one will be assigned.
665  Parameters:
666  component_type - [in]
667  Type of component.
668  component_serial_number - [in]
669  0 or the component's unique runtime serial number (ON_ModelComponent::RuntimeSerialNumber()).
670  component_id - [in]
671  If the id is nil or in use, a new id will be assigned.
672  component_name_hash - [in]
673  If the the component type requires a unique name and the name
674  is not valid or in use, the component will not be added.
675  original_name - [in/out]
676  If a new name needs to be assigned, the input value will be used
677  as a candidate and then as the root. Passing in the current name
678  is a good choice. The output value is the final assigned name.
679  Returns:
680  If an item is added to this manifest, then the identification
681  information is returned.
682  Otherwise ON_ComponentManifestItem::Unset is returned.
683  */
684  const class ON_ComponentManifestItem& AddComponentToManifest(
685  ON_ModelComponent::Type component_type,
686  ON__UINT64 component_serial_number,
687  ON_UUID component_parent_id,
688  ON_UUID component_id,
689  const ON_NameHash& component_name_hash,
690  const wchar_t* candidate_name,
691  ON_wString& assigned_name
692  );
693 
694  const class ON_ComponentManifestItem& AddComponentToManifest(
695  ON_ModelComponent::Type component_type,
696  ON__UINT64 component_serial_number,
697  ON_UUID component_parent_id,
698  ON_UUID component_id,
699  const wchar_t* original_name,
700  ON_wString& assigned_name
701  );
702 
703 
704  /*
705  Description:
706  Modify a manifest items's component name
707  Parameters:
708  item_id - [in]
709  Identifies the manifest item to modify.
710  component_parent_id - [in]
711  ON_ModelComponent.ParentId() value.
712  When ON_ModelComponent::UniqueNameIncludesParent(component_type) is true,
713  it is critical that component_parent_id be set correctly.
714  name - [in]
715  new name
716  Returns:
717  True if name was modified.
718  */
719  const class ON_ComponentManifestItem& ChangeComponentName(
720  ON_UUID item_id,
721  ON_ModelComponent::Type component_type,
722  ON_UUID component_parent_id,
723  const wchar_t* component_name
724  );
725 
726  /*
727  Description:
728  Modify a manifest items's component name
729  Parameters:
730  component - [in]
731  The component that is in the manifest with the new name set.
732  Returns:
733  True if name was modified.
734  */
735  const class ON_ComponentManifestItem& ChangeComponentName(
736  const class ON_ModelComponent& component
737  );
738 
739  /*
740  Description:
741  A function for expert users to directly set the
742  component's name hash. Generally, it is better
743  to use the ChangeComponentName() functions.
744  Parameters:
745  item_id - [in]
746  Identifies the manifest item to modify.
747  component_name_hash - [in]
748  new name hash
749  */
750  const class ON_ComponentManifestItem& ChangeComponentNameHash(
751  ON_UUID item_id,
752  const ON_NameHash& component_name_hash
753  );
754 
755  /*
756  Description:
757  Modify a manifest items's component m_component_runtime_serial_number,
758  m_original_index, m_original_id, and m_name_hash values.
759  Parameters:
760  manifest_id - [in]
761  identifies the manifest item to modify
762  component_runtime_serial_number - [in]
763  */
764  const class ON_ComponentManifestItem& ChangeComponentRuntimeSerialNumber(
765  ON_UUID item_id,
766  ON__UINT64 component_runtime_serial_number
767  );
768 
769  /*
770  Description:
771  Set a component's status to deleted.
772  */
773  const class ON_ComponentManifestItem& DeleteComponent(
774  ON_UUID item_id
775  );
776 
777  const class ON_ComponentManifestItem& DeleteComponent(
778  ON__UINT64 component_runtime_serial_number
779  );
780 
781  /*
782  Description:
783  Undelete a previously deleted component.
784  */
785  const class ON_ComponentManifestItem& UndeleteComponent(
786  ON_UUID item_id,
787  ON_UUID parent_id,
788  const wchar_t* candidate_name,
789  ON_wString& assigned_name
790  );
791 
792  /*
793  Description:
794  Undelete a previously deleted component with the same id and
795  change the serial number to new_component_runtime_serial_number.
796  Remarks:
797  Often when an object is modified, the original and new
798  object have the same id but different serial numbers. The original is
799  deleted. When the item is undeleted for the object, the runtime
800  serial number needs to be udated.
801  */
802  const class ON_ComponentManifestItem& UndeleteComponentAndChangeRuntimeSerialNumber(
803  ON_UUID item_id,
804  ON_UUID parent_id,
805  ON__UINT64 new_component_runtime_serial_number,
806  const wchar_t* candidate_name,
807  ON_wString& assigned_name
808  );
809 
810  bool RemoveComponent(
811  const ON_ModelComponent& component
812  );
813 
814  bool RemoveComponent(
815  ON__UINT64 component_runtime_serial_number
816  );
817 
818  bool RemoveComponent(
819  ON_UUID item_id
820  );
821 
822  bool RemoveIndexedComponent(
823  ON_ModelComponent::Type component_type,
824  int item_index
825  );
826 
827  bool RemoveAllComponents(
828  ON_ModelComponent::Type component_type,
829  bool bResetManifestIndex
830  );
831 
832  /*
833  Description:
834  Get a name that is currently not used in this manifest as either a component
835  or manifest name.
836  Parameters:
837  component_type - [in]
838  ON_ModelComponent::ComponentTypeIsValidAndNotMixed(component_type) must be true.
839  component_parent_id - [in]
840  If ON_ModelComponent::UniqueNameIncludesParent(component_type) is true and
841  candidate_name is not empty, then the component parent id must be accurate.
842  This is the case for ON_Layer names.
843  Otherwise, you may pass ON_nil_uuid.
844  candidate_name - [in]
845  If candidate_name is a valid and not it use,
846  then unused_component_name = candidate_name.
847  If ON_ModelComponent::UniqueNameIncludesParent(component_type) is true and
848  candidate_name is not empty, then component_parent_id must be accurate.
849  This is the case for ON_Layer names.
850  base_name - [in]
851  If base_name is empty or not valid,
852  then ON_ModelComponent::ComponentTypeToString(component_type) is used as base_name
853  suffix_separator - [in]
854  empty or the string to place between base_name and the suffix when searching for an
855  unsued name.
856  suffix0 - [in]
857  If a suffix needs to be appended, the search for a
858  unused name begins with the suffix values suffix0+1.
859  suffix_value - [out]
860  If nullptr != suffix_value, the value used to generate the
861  unique name suffix is returned.
862  Returns:
863  An component name that is not used in this manifest.
864  Remarks:
865  If candidate_name could not be used, then it has the form
866  base_name + suffix_separator + X, where X is an integer > suffix0.
867  */
868  const ON_wString UnusedName(
869  ON_ModelComponent::Type component_type,
870  ON_UUID component_parent_id,
871  const wchar_t* candidate_name,
872  const wchar_t* base_name,
873  const wchar_t* suffix_separator,
874  unsigned int suffix0,
875  unsigned int* suffix_value
876  ) const;
877 
878  /*
879  Description:
880  Get a name that is currently not used in this manifest as either a component
881  or manifest name.
882  Parameters:
883  model_component - [in]
884  The component type, id, parent id, and candidate name parameters for the
885  more complicated version of UnusedName() are taken from this parameter.
886  Returns:
887  An component name that is not used in this manifest.
888  Remarks:
889  If candidate_name could not be used, then it has the form
890  base_name + suffix_separator + X, where X is an integer > suffix0.
891  */
892  const ON_wString UnusedName(
893  const ON_ModelComponent& model_component
894  ) const;
895 
896  /*
897  Parameters:
898  component_type - [in]
899  ON_ModelComponent::ComponentTypeIsValidAndNotMixed(component_type)
900  must be true or false will be returned.
901  candidate_name_hash - [in]
902  candidate_name_hash.IsValidAndNotEmpty()
903  must be true or false will be returned.
904  Returns:
905  True if the candidate_name_hash a hash of a valid, non-empty name and the
906  name is currently not used as either a component or manifest name value.
907  */
908  bool NameIsAvailable(
909  ON_ModelComponent::Type component_type,
910  const ON_NameHash& candidate_name_hash
911  ) const;
912 
913  /*
914  Description:
915  Get an id that is not currently used in this manifest
916  Parameters:
917  component_type - [in]
918  ON_ModelComponent::ComponentTypeIsValidAndNotMixed(component_type) must be true.
919  candidate_id
920  If candidate_id is valid component id and not in use,
921  then its value is returned.
922  Returns:
923  An id that is valid and currently not used in this ON_Manifest as
924  either a component or a manifest id value.
925  Remarks:
926  If candidate_id cannot be used, then ON_CreateId() is used to create a new id.
927  */
928  ON_UUID UnusedId(
929  ON_UUID candidate_id
930  ) const;
931 
932  /*
933  Returns:
934  True if the id is valid and currently not used in this ON_Manifest as
935  either a component or a manifest id value.
936  */
937  bool IdIsAvailable(
938  ON_UUID id
939  ) const;
940 
941  //////////////////////////////////////////////////////////////////
942  //
943  // Query tools to get item identificaion information
944  //
945  //
946  const class ON_ComponentManifestItem& ItemFromId(
947  ON_UUID item_id
948  ) const;
949 
950  const class ON_ComponentManifestItem& ItemFromComponentRuntimeSerialNumber(
951  ON__UINT64 component_runtime_serial_number
952  ) const;
953 
954  /*
955  Description:
956  Returns the item if it has the required component type and id.
957  Remarks:
958  Every item has a unique manifest id. The component_type
959  parameter is provided if an additional check needs to be
960  made on component type.
961  */
962  const class ON_ComponentManifestItem& ItemFromId(
963  ON_ModelComponent::Type component_type,
964  ON_UUID item_id
965  ) const;
966 
967  /*
968  Parameters:
969  component_type - [in]
970  component_name_hash - [in]
971  The value of ON_ModelComponent::UniqueNameIgnoresCase(component_type) must be used
972  when creating the name hash (group names are case sensitive).
973 
974  If ON_ModelComponent::UniqueNameIncludesParent(component_type) is true,
975  then the parent_id must be used to calculate the name hash
976  (layer names require parent ids).
977  */
978  const class ON_ComponentManifestItem& ItemFromName(
979  const class ON_ModelComponent* model_component
980  ) const;
981 
982  const class ON_ComponentManifestItem& ItemFromName(
983  ON_ModelComponent::Type component_type,
984  ON_UUID parent_id,
985  const wchar_t* name
986  ) const;
987 
988  /*
989  Parameters:
990  component_type - [in]
991  component_name_hash - [in]
992  The value of ON_ModelComponent::UniqueNameIgnoresCase(component_type) must be used
993  when creating the name hash (group names are case sensitive).
994 
995  If ON_ModelComponent::UniqueNameIncludesParent(component_type) is true,
996  then the parent_id must be used to calculate the name hash
997  (layer names require parent ids).
998  */
999  const class ON_ComponentManifestItem& ItemFromNameHash(
1000  ON_ModelComponent::Type component_type,
1001  const ON_NameHash& component_name_hash
1002  ) const;
1003 
1004  const class ON_ComponentManifestItem& ItemFromIndex(
1005  ON_ModelComponent::Type component_type,
1006  int item_index
1007  ) const;
1008 
1009  const class ON_ComponentManifestItem& ItemFromUnsignedIndex(
1010  ON_ModelComponent::Type component_type,
1011  unsigned int unsigned_item_index
1012  ) const;
1013 
1014  const class ON_ComponentManifestItem& SystemItemFromNameHash(
1015  ON_ModelComponent::Type component_type,
1016  const ON_NameHash& system_item_name_hash
1017  ) const;
1018 
1019  const class ON_ComponentManifestItem& SystemItemFromIndex(
1020  ON_ModelComponent::Type component_type,
1021  int system_item_index
1022  ) const;
1023 
1024  const class ON_ComponentManifestItem* FirstItem(
1025  ON_ModelComponent::Type component_type
1026  ) const;
1027 
1028  const class ON_ComponentManifestItem* LastItem(
1029  ON_ModelComponent::Type component_type
1030  ) const;
1031 
1032  /*
1033  Returns:
1034  Next item in the manifest with the same component type.
1035  */
1036  const class ON_ComponentManifestItem* NextItem(
1037  const class ON_ComponentManifestItem* item
1038  ) const;
1039 
1040  /*
1041  Returns:
1042  Previous item in the manifest with the same component type.
1043  */
1044  const class ON_ComponentManifestItem* PreviousItem(
1045  const class ON_ComponentManifestItem* item
1046  ) const;
1048  /*
1049  Returns:
1050  Next item in the manifest with the same component type.
1051  */
1052  const class ON_ComponentManifestItem* NextItem(
1053  ON_UUID manifest_item_id
1054  ) const;
1055 
1056  /*
1057  Returns:
1058  Previous item in the manifest with the same component type.
1059  */
1060  const class ON_ComponentManifestItem* PreviousItem(
1061  ON_UUID manifest_item_id
1062  ) const;
1063 
1064  /*
1065  Description:
1066  This number is incremented every time the manifest changes.
1067  */
1068  ON__UINT64 ManifestContentVersionNumber() const;
1069 
1070 private:
1071  const class ON_ComponentManifestItem* Internal_AddItem(
1072  class ON_ComponentManifestItem& item,
1073  ON_UUID component_parent_id,
1074  bool bResolveIdAndNameCollisions,
1075  const wchar_t* candidate_name,
1076  ON_wString* assigned_name
1077  );
1078 
1079 private:
1080  class ON_ComponentManifestImpl* Impl() const;
1081  mutable class ON_ComponentManifestImpl* m_impl = nullptr;
1082 };
1083 
1084 class ON_CLASS ON_ComponentManifestItem
1085 {
1086 public:
1087  static const ON_ComponentManifestItem UnsetItem;
1088 
1089  static int CompareComponentType(
1090  const ON_ComponentManifestItem* a,
1091  const ON_ComponentManifestItem* b
1092  );
1093 
1094  static int CompareId(
1095  const ON_ComponentManifestItem*const* a,
1096  const ON_ComponentManifestItem*const* b
1097  );
1098 
1099  static int CompareNameHash(
1100  const ON_ComponentManifestItem*const* a,
1101  const ON_ComponentManifestItem*const* b
1102  );
1103 
1104  static int CompareIndex(
1105  const ON_ComponentManifestItem*const* a,
1106  const ON_ComponentManifestItem*const* b
1107  );
1108 
1109 public:
1110  // Assigns component type, index, id and name hash
1112  const class ON_ModelComponent& component
1113  );
1114 
1116  const class ON_ModelComponent& component,
1117  const ON_UUID& manifest_id,
1118  const class ON_NameHash& manifest_name_hash
1119  );
1120 
1122  ON_ModelComponent::Type component_type,
1123  ON__UINT64 m_component_runtime_serial_number,
1124  const ON_UUID& manifest_id,
1125  const class ON_NameHash& manifest_name_hash
1126  );
1127 
1129  const class ON_ModelComponent& component,
1130  int manifest_index,
1131  const ON_UUID& manifest_id,
1132  const class ON_NameHash& manifest_name_hash
1133  );
1134 
1136  ON_ModelComponent::Type component_type,
1137  ON__UINT64 m_component_runtime_serial_number,
1138  int manifest_index,
1139  const ON_UUID& manifest_id,
1140  const class ON_NameHash& manifest_name_hash
1141  );
1142 
1143  ON_ComponentManifestItem() = default;
1144  ~ON_ComponentManifestItem() = default;
1146  ON_ComponentManifestItem& operator=(const ON_ComponentManifestItem&) = default;
1147 
1148 public:
1149  /*
1150  Returns:
1151  true if m_component_type is not ON_ModelComponent::Type::Unset
1152  and the m_manifest_id is not nil.
1153  */
1154  bool IsValid() const;
1155 
1156  /*
1157  Returns:
1158  true if m_component_type is ON_ModelComponent::Type::Unset
1159  or the m_manifest_id is nil.
1160  */
1161  bool IsUnset() const;
1162 
1163  /*
1164  Returns:
1165  true if the item is in a deleted state.
1166  Name is erased.
1167  The component can be found by component serial number, id, or index.
1168  */
1169  bool IsDeleted() const;
1170 
1171  /*
1172  Returns:
1173  true if the item is a constant system component.
1174  */
1175  bool IsSystemComponent() const;
1176 
1177 public:
1178  /*
1179  Return:
1180  item component type. ON_ModelComponent::Type::Unset if it is not set.
1181  */
1182  ON_ModelComponent::Type ComponentType() const;
1183 
1184  void SetComponentType(
1185  ON_ModelComponent::Type component_type
1186  );
1187 
1188 public:
1189  /*
1190  Return:
1191  item id. ON_nil_uuid if is not set.
1192  */
1193  ON_UUID Id() const;
1195  void SetId(
1196  ON_UUID id
1197  );
1198 
1199 public:
1200  /*
1201  Return:
1202  item component runtime serial number. 0 if it is not set.
1203  */
1204  ON__UINT64 ComponentRuntimeSerialNumber() const;
1205 
1206  void SetComponentRuntimeSerialNumber(
1207  ON__UINT64 component_runtime_serial_number
1208  );
1209 
1210 public:
1211  /*
1212  Return:
1213  item name hash. ON_NameHash::UnsetNameHash if is not set.
1214  */
1215  const ON_NameHash& NameHash() const;
1216 
1217  void SetNameHash(
1218  const ON_NameHash& name_hash
1219  );
1220 
1221 public:
1222  /*
1223  Return:
1224  item index. ON_UNSET_INT_INDEX if it is not set.
1225  */
1226  int Index() const;
1227 
1228  void SetIndex(
1229  int index
1230  );
1231 
1232 private:
1233  friend class ON_ComponentManifestImpl;
1234 
1235  void Internal_SetDeletedState(
1236  bool bDeleted
1237  );
1238 
1239 private:
1240  ON__UINT32 m_status_bits = 0;
1242  ON__UINT8 m_reserved1 = 0;
1243  ON__UINT16 m_reserved2 = 0;
1244  ON__UINT32 m_reserved3 = 0;
1245  int m_index = ON_UNSET_INT_INDEX;
1246  ON__UINT64 m_component_runtime_serial_number = 0;
1247  ON_UUID m_id = ON_nil_uuid;
1249 };
1250 
1251 class ON_CLASS ON_ManifestMapItem
1252 {
1253 public:
1254  ON_ManifestMapItem() = default;
1255  ~ON_ManifestMapItem() = default;
1256  ON_ManifestMapItem(const ON_ManifestMapItem&) = default;
1257  ON_ManifestMapItem& operator=(const ON_ManifestMapItem&) = default;
1258 
1259 public:
1260  static const ON_ManifestMapItem Unset;
1261 
1262  /*
1263  Description:
1264  Compares type, indices and ids.
1265  */
1266  static int Compare(
1267  const ON_ManifestMapItem& a,
1268  const ON_ManifestMapItem& b
1269  );
1270 
1271  static int CompareTypeAndSourceIdAndIndex(
1272  const ON_ManifestMapItem& a,
1273  const ON_ManifestMapItem& b
1274  );
1275 
1276  static int CompareTypeAndDestinationIdAndIndex(
1277  const ON_ManifestMapItem& a,
1278  const ON_ManifestMapItem& b
1279  );
1280 
1281  static int CompareTypeAndSourceIndex(
1282  const ON_ManifestMapItem& a,
1283  const ON_ManifestMapItem& b
1284  );
1285 
1286  static int CompareTypeAndDestinationIndex(
1287  const ON_ManifestMapItem& a,
1288  const ON_ManifestMapItem& b
1289  );
1290 
1291  /*
1292  Description:
1293  32-bit hash for use in source id hash tables
1294  */
1295  static ON__UINT32 SourceIdHash32(
1296  const ON_UUID& source_component_id
1297  );
1298 
1299  /*
1300  Description:
1301  32-bit hash for use in source index hash tables
1302  */
1303  static ON__UINT32 SourceIndexHash32(
1304  ON_ModelComponent::Type component_type,
1305  int source_component_index
1306  );
1307 
1308  /*
1309  Returns:
1310  True if
1311  m_component_type is not ON_ModelComponent::Type::Unset
1312  and m_source_component_id is not nil
1313  and m_destination_component_id is not nil
1314  and no index is required or m_source_component_index and m_destination_component_index
1315  are not ON_UNSET_INT_INDEX.
1316  */
1317  bool SourceAndDestinationAreSet() const;
1318 
1319  bool SourceOrDestinationIsUnset() const;
1320 
1321  /*
1322  Returns:
1323  True if
1324  m_component_type is not ON_ModelComponent::Type::Unset
1325  and m_source_component_id is not nil
1326  and no index is required or m_source_component_index is not ON_UNSET_INT_INDEX.
1327  */
1328  bool SourceIsSet() const;
1329 
1330  bool SourceIsUnset() const;
1331 
1332  /*
1333  Returns:
1334  True if
1335  m_component_type is not ON_ModelComponent::Type::Unset
1336  and m_destination_component_id is not nil
1337  and no index is required or m_destination_component_index is not ON_UNSET_INT_INDEX.
1338  */
1339  bool DestinationIsSet() const;
1340 
1341  bool DestinationIsUnset() const;
1342 
1343  /*
1344  Returns:
1345  True if destination_manifest contains a manifest item that matches
1346  m_component_type, m_destination_component_id, and m_destination_component_index.
1347  */
1348  bool DestinationInManifest(
1349  const ON_ComponentManifest& destination_manifest
1350  ) const;
1351 
1352  /*
1353  Returns:
1354  True if destination_manifest contains a manifest item that matches
1355  m_component_type, m_source_component_id, and m_source_component_index.
1356  */
1357  bool SourceInManifest(
1358  const ON_ComponentManifest& source_manifest
1359  ) const;
1360 
1361  ON_ManifestMapItem SwapSourceAndDestiation() const;
1362 
1363  ON_ModelComponent::Type ComponentType() const;
1364  const ON_UUID& SourceId() const;
1365  const ON_UUID& DestinationId() const;
1366  int SourceIndex() const;
1367  int DestinationIndex() const;
1368 
1369  bool ClearSourceIdentification();
1370 
1371  bool ClearDestinationIdentification();
1372 
1373  /*
1374  Description:
1375  Set type and source identification.
1376  Parameters:
1377  component_type - [in]
1378  source_id - [in]
1379  source_index - [in]
1380  Returns:
1381  True if set.
1382  False destination type is set and different from component_type.
1383  */
1384  bool SetSourceIdentification(
1385  ON_ModelComponent::Type component_type,
1386  ON_UUID source_id,
1387  int source_index
1388  );
1389 
1390  /*
1391  Description:
1392  Set type and destination identification.
1393  Parameters:
1394  component_type - [in]
1395  source_id - [in]
1396  source_index - [in]
1397  Returns:
1398  True if set.
1399  False destination type is set and different from component_type.
1400  */
1401  bool SetDestinationIdentification(
1402  ON_ModelComponent::Type component_type,
1403  ON_UUID destination_id,
1404  int destination_index
1405  );
1406 
1407  /*
1408  Description:
1409  Set type and source identification to model_component identification.
1410  Parameters:
1411  model_component - [in]
1412  Returns:
1413  True if set.
1414  False destination type is set and different from model_component->ComponentType().
1415  */
1416  bool SetSourceIdentification(
1417  const class ON_ModelComponent* model_component
1418  );
1419 
1420  /*
1421  Description:
1422  Set type and destination identification to model_component identification.
1423  Parameters:
1424  model_component - [in]
1425  Returns:
1426  True if set.
1427  False source type is set and different from model_component->ComponentType().
1428  */
1429  bool SetDestinationIdentification(
1430  const class ON_ModelComponent* model_component
1431  );
1432 
1433  /*
1434  Description:
1435  Set type and source identification to manifest_item identification.
1436  Parameters:
1437  manifest_item - [in]
1438  Returns:
1439  True if set.
1440  False destination type is set and different from manifest_item->ComponentType().
1441  */
1442 
1443  bool SetSourceIdentification(
1444  const class ON_ComponentManifestItem* manifest_item
1445  );
1446 
1447  /*
1448  Description:
1449  Set type and destination identification to manifest_item identification.
1450  Parameters:
1451  manifest_item - [in]
1452  Returns:
1453  True if set.
1454  False source type is set and different from manifest_item->ComponentType().
1455  */
1456  bool SetDestinationIdentification(
1457  const class ON_ComponentManifestItem* manifest_item
1458  );
1459 
1460  /*
1461  Description:
1462  Copy type and source identification from map_item.
1463  Parameters:
1464  map_item - [in]
1465  Returns:
1466  True if set.
1467  False destination type is set and different from map_item->ComponentType().
1468  */
1469  bool SetSourceIdentification(
1470  const class ON_ManifestMapItem* map_item
1471  );
1472 
1473  /*
1474  Description:
1475  Copy type and destination identification from map_item.
1476  Parameters:
1477  map_item - [in]
1478  Returns:
1479  True if set.
1480  False source type is set and different from map_item->ComponentType().
1481  */
1482  bool SetDestinationIdentification(
1483  const class ON_ManifestMapItem* map_item
1484  );
1485 
1486 private:
1487  bool Internal_SetSourceOrDestinationIdentification(
1488  unsigned int which_identification, // 0 = source, 1 = destination
1489  ON_ModelComponent::Type component_type,
1490  ON_UUID id,
1491  int index
1492  );
1493 
1494 private:
1496 private:
1497  unsigned int m_reserved = 0;
1498 private:
1499  int m_source_index = ON_UNSET_INT_INDEX;
1500  int m_destination_index = ON_UNSET_INT_INDEX;
1501 private:
1502  ON_UUID m_source_id = ON_nil_uuid;
1503  ON_UUID m_destination_id = ON_nil_uuid;
1504 };
1505 
1506 ON_DECL
1507 bool operator==(const ON_ManifestMapItem& lhs,const ON_ManifestMapItem& rhs);
1508 
1509 ON_DECL
1510 bool operator!=(const ON_ManifestMapItem& lhs,const ON_ManifestMapItem& rhs);
1511 
1512 
1513 /*
1514 Description:
1515  ON_ManifestIdentificationMap is used to record a map from
1516  a source manifest to a destination manifest when the index or id
1517  values change. This is common when reading and writing archives
1518  and when merging models.
1519 */
1520 class ON_CLASS ON_ManifestMap
1521 {
1522 public:
1523  // The default constructor would work prfectly,
1524  // except there is a bug in Apple's CLANG that
1525  // requires either an explicitly implemented constructor
1526  // or an explicitly implemented copy constructor together
1527  // with a hack to initialize the static ON_ComponentManifest::Empty.
1528  // Apple CLANG BUG // ON_ManifestMap() = default;
1529  ON_ManifestMap() ON_NOEXCEPT;
1530 
1531  ~ON_ManifestMap();
1533  ON_ManifestMap& operator=(const ON_ManifestMap&);
1534 
1535 public:
1536  static const ON_ManifestMap Empty;
1537 
1538 public:
1539  bool AddMapItem(
1540  const class ON_ManifestMapItem& map_item
1541  );
1542 
1543  /*
1544  Parameters:
1545  map_item - [in]
1546  The source settings must exacty match source settings of an existing map.
1547  The destination settings are the new values to assign.
1548  Return:
1549  True if a mapping was successfully updated (even when the destation settings did not change).
1550  */
1551  bool UpdatetMapItemDestination(
1552  const class ON_ManifestMapItem& map_item
1553  );
1554 
1555  const class ON_ManifestMapItem& MapItemFromSourceId(
1556  const ON_UUID& source_item_id
1557  ) const;
1558 
1559  const class ON_ManifestMapItem& MapItemFromSourceIndex(
1560  ON_ModelComponent::Type component_type,
1561  int source_component_index
1562  ) const;
1563 
1564  bool GetAndValidateDestinationIndex(
1565  ON_ModelComponent::Type component_type,
1566  int source_component_index,
1567  const ON_ComponentManifest& destination_manifest,
1568  int* destination_component_index
1569  ) const;
1570 
1571  bool GetAndValidateDestinationIndex(
1572  ON_ModelComponent::Type component_type,
1573  const ON_UUID& source_component_id,
1574  const ON_ComponentManifest& destination_manifest,
1575  int* destination_component_index
1576  ) const;
1577 
1578  bool GetAndValidateDestinationId(
1579  ON_ModelComponent::Type component_type,
1580  const ON_UUID& source_component_id,
1581  const ON_ComponentManifest& destination_manifest,
1582  ON_UUID* destination_component_id
1583  ) const;
1584 
1585  /*
1586  Returns:
1587  True if there are no ON_ManifestMapItem elements.
1588  */
1589  bool IsEmpty() const;
1590 
1591  /*
1592  Returns:
1593  True if there is at least one ON_ManifestMapItem element.
1594  */
1595  bool IsNotEmpty() const;
1596 
1597  /*
1598  Returns:
1599  Number of map items.
1600  Remarks:
1601  Some of these items may not change id or index.
1602  */
1603  unsigned int MapItemCount() const;
1604 
1605 private:
1606  class ON_ManifestMapImpl* Impl();
1607  class ON_ManifestMapImpl* m_impl = nullptr;
1608 };
1609 
1610 
1611 enum class ON_3dmArchiveTableType : unsigned int
1612 {
1613  // The values of the table_type enums must increase in the order
1614  // the corresponding tables appear in well formed 3dm archives
1615  // and the bitwise or of distinct values must be zero because
1616  // bitfield filters are used in some reading operations.
1617 
1618  Unset = 0,
1619 
1620  // First section in any 3dm archive.
1621  start_section = 0x00000001U,
1622 
1623  properties_table = 0x00000002U,
1624  settings_table = 0x00000004U,
1625  bitmap_table = 0x00000008U,
1626  texture_mapping_table = 0x00000010U,
1627  material_table = 0x00000020U,
1628  linetype_table = 0x00000040U,
1629  layer_table = 0x00000080U,
1630  group_table = 0x00000100U,
1631  text_style_table = 0x00000200U,
1632  leader_style_table = 0x00000400U,
1633  dimension_style_table = 0x00000800U,
1634  light_table = 0x00001000U,
1635  hatchpattern_table = 0x00002000U,
1636  instance_definition_table = 0x00004000U,
1637  object_table = 0x00008000U,
1638  historyrecord_table = 0x00010000U,
1639  user_table = 0x00020000U,
1640 
1641  // Last section in any 3dm archive.
1642  end_mark = 0x40000000U
1643 };
1644 
1645 
1646 /*
1647 Description:
1648  Context for an annotation object. This context is required when
1649  converting current annotation objects to and from formats used
1650  in earlier versions and is typically used when reading and
1651  writing 3dm archives.
1652 */
1653 class ON_CLASS ON_3dmAnnotationContext
1654 {
1655 public:
1656  ON_3dmAnnotationContext() = default;
1660 
1661 public:
1662  static const ON_3dmAnnotationContext Default;
1663 
1664 public:
1665  ON::active_space ViewContext() const;
1666 
1667  void SetViewContext(
1668  ON::active_space
1669  );
1670 
1671  ON::LengthUnitSystem ModelLengthUnitSystem() const;
1672 
1673  void SetModelLengthUnitSystem(
1674  ON::LengthUnitSystem model_length_unit_system
1675  );
1676 
1677  ON::LengthUnitSystem PageLengthUnitSystem() const;
1678 
1679  void SetPageLengthUnitSystem(
1680  ON::LengthUnitSystem page_length_unit_system
1681  );
1682 
1683  const class ON_3dmAnnotationSettings& AnnotationSettings() const;
1684 
1685  /*
1686  Parameters:
1687  annotation_settings - [in]
1688  Annotation settings that are externally managed and will exist
1689  during the lifetime of the ON_3dmAnnotationContext class instance.
1690  */
1691  void SetReferencedAnnotationSettings(
1692  const class ON_3dmAnnotationSettings* annotation_settings
1693  );
1694 
1695  /*
1696  Parameters:
1697  annotation_settings - [in]
1698  A copy of annotation_settings is stored and manged by the ON_3dmAnnotationContext class instance.
1699  */
1700  void SetManagedAnnotationSettings(
1701  const class ON_3dmAnnotationSettings& annotation_settings
1702  );
1703 
1704  /*
1705  Returns:
1706  True if the annotation settings have been explicitly set.
1707  */
1708  bool AnnotationSettingsAreSet() const;
1709 
1710  /*
1711  This is the dimstyle the annotation object is question is using.
1712  It can be a "base" dimstyle from the dimstyle table or an
1713  "override" style attached used by a single instance of an annnotation
1714  object.
1715  */
1716  const class ON_DimStyle& DimStyle() const;
1717 
1718  const class ON_DimStyle& ParentDimStyle() const;
1719 
1720  /*
1721  Parameters:
1722  dim_style - [in]
1723  A dimension style that is externally managed and will exist
1724  during the lifetime of the ON_3dmAnnotationContext class instance.
1725  */
1726  void SetReferencedDimStyle(
1727  const class ON_DimStyle* parent_dim_style,
1728  const class ON_DimStyle* override_dim_style,
1729  int V5_3dm_archive_index
1730  );
1731 
1732  /*
1733  Parameters:
1734  dim_style - [in]
1735  A copy of a dim_style is stored and manged by the ON_3dmAnnotationContext class instance.
1736  */
1737  void SetManagedDimStyle(
1738  const class ON_DimStyle& parent_dim_style,
1739  const class ON_DimStyle* override_dim_style,
1740  int V5_3dm_archive_index
1741  );
1742 
1743  void UpdateReferencedDimStyle(
1744  const class ON_DimStyle* old_pointer,
1745  const class ON_DimStyle* new_pointer
1746  );
1748  /*
1749  Returns:
1750  True if the dimension style has been explicitly set.
1751  */
1752  bool DimStyleIsSet() const;
1753 
1754  /*
1755  Returns:
1756  If the dimstyle is not set or it has a nil parent id, then DimStyleId() is returned.
1757  Otherwise the parent id is returned.
1758  */
1759  ON_UUID ParentDimStyleId() const;
1760 
1761  /*
1762  Returns:
1763  3dm archive dimension style table index to use when writing a V5 3dm archive.
1764  This is often different from DimStyle().Index().
1765  */
1766  int V5_ArchiveDimStyleIndex() const;
1767 
1768  /*
1769  Parameters:
1770  bRequireSetOverrides - [in]
1771  true if explicit overrides are required.
1772  Returns:
1773  true if the context dim style is an override style (parent id is not nil) and
1774  it has overrides or bRequireSetOverrides is false.
1775  */
1776  bool IsOverrideDimStyle() const;
1777 
1778  const class ON_BinaryArchive* BinaryArchive() const;
1779 
1780  /*
1781  Parameters:
1782  binary_archive - [in]
1783  Binary archive that is externally managed and will exist
1784  during the lifetime of the ON_3dmAnnotationContext class instance.
1785  */
1786  void SetReferencedBinaryArchive(
1787  const class ON_BinaryArchive* binary_archive
1788  );
1789 
1790  /*
1791  Returns:
1792  True if the the target binary archive is set.
1793  */
1794  bool BinaryArchiveIsSet() const;
1795 
1796 private:
1797  const class ON_BinaryArchive* m_binary_archive = nullptr;
1798 
1799  // V6 table dimstyle. If an override dimstyle is in use,
1800  // this is the "parent dimstyle" referenced by the override.
1801  const class ON_DimStyle* m_parent_dim_style = nullptr;
1802  class ON_DimStyle* m_managed_parent_dim_style = nullptr;
1803 
1804  const class ON_DimStyle* m_override_dim_style = nullptr;
1805  class ON_DimStyle* m_managed_override_dim_style = nullptr;
1806 
1807  const class ON_3dmAnnotationSettings* m_annotation_settings = nullptr;
1808  class ON_3dmAnnotationSettings* m_managed_annotation_settings = nullptr;
1809  ON::active_space m_view_context = ON::active_space::no_space;
1810  ON::LengthUnitSystem m_model_length_unit_system = ON::LengthUnitSystem::None;
1811  ON::LengthUnitSystem m_page_length_unit_system = ON::LengthUnitSystem::None;
1812 
1813  // V5 archive dim style index
1814  int m_V5_3dm_archive_dim_style_index = ON_UNSET_INT_INDEX;
1815 
1816 private:
1817  void Internal_CopyFrom(const ON_3dmAnnotationContext& src);
1818  void Internal_Destroy();
1819 };
1820 
1821 
1822 class ON_CLASS ON_3dmArchiveTableStatus
1823 {
1824 public:
1825  ON_3dmArchiveTableStatus() = default;
1826  ~ON_3dmArchiveTableStatus() = default;
1828  ON_3dmArchiveTableStatus& operator=(const ON_3dmArchiveTableStatus&) = default;
1829 
1830  static const ON_3dmArchiveTableStatus Unset;
1831 
1832  ON_3dmArchiveTableType m_table_type = ON_3dmArchiveTableType::Unset;
1833 
1834  // number of table items
1835  unsigned int m_item_count = 0;
1836 
1837  // Number of crc errors found during archive reading.
1838  // If > 0, then the archive is corrupt. See the table
1839  // status information below to determine where the
1840  // errors occured.
1841  unsigned int m_crc_error_count = 0;
1842 
1843  // Number of other types of serious errors found during archive reading
1844  // or writing.
1845  // If > 0, then the archive is corrupt. See the table status information
1846  // below to determine where the errors occured.
1847  unsigned int m_critical_error_count = 0;
1848 
1849  // Number of other types of serious errors found during archive reading.
1850  // If > 0, then the archive is corrupt. See the table status information
1851  // below to determine where the errors occured.
1852  unsigned int m_recoverable_error_count = 0;
1853 
1854  enum class TableState : unsigned int
1855  {
1856  Unset = 0U,
1857  Started = 1U, // began to read the table
1858  InProgress = 2U,
1859  Finished = 3U, // finished reading the table
1860  NotFound = 4U // the table could not be located during reading
1861  };
1862 
1864 };
1865 
1866 class ON_CLASS ON_BinaryArchive // use for generic serialization of binary data
1867 {
1868 public:
1869  ON_BinaryArchive( ON::archive_mode );
1870  virtual ~ON_BinaryArchive();
1871 
1872 protected:
1873  virtual
1874  ON__UINT64 Internal_CurrentPositionOverride( // current offset (in bytes) into archive ( like ftell() )
1875  ) const = 0;
1876 
1877  virtual
1878  bool Internal_SeekFromCurrentPositionOverride( // seek from current position ( like fseek( ,SEEK_CUR) )
1879  int // byte offset ( >= -CurrentPostion() )
1880  ) = 0;
1881 
1882  virtual
1883  bool Internal_SeekToStartOverride( // seek from current position ( like fseek(0 ,SEEK_SET) )
1884  ) = 0;
1885 
1886 public:
1887  /*
1888  Returns:
1889  True if current position is at the end of the archive.
1890  */
1891  virtual
1892  bool AtEnd() const = 0;
1893 
1894 public:
1895  /*
1896  Returns:
1897  Number of bytes from start of archive to the current position.
1898  */
1899  ON__UINT64 CurrentPosition() const;
1900 
1901  /*
1902  Description:
1903  Set current position to bytes_from_start many bytes from the start of the archive.
1904  Parameters:
1905  bytes_from_start - [in]
1906  Returns:
1907  True: successful
1908  False: failure
1909  Remarks:
1910  Similar to fseek( ,SEEK_SET)
1911  */
1912  bool SeekFromStart(
1913  ON__UINT64 bytes_from_start
1914  );
1915 
1916  /*
1917  Description:
1918  Increase the archive's current position to bytes_forward from the current position.
1919  Parameters:
1920  bytes_forward - [in]
1921  Returns:
1922  True: successful
1923  False: failure
1924  */
1925  bool SeekForward(
1926  ON__UINT64 bytes_forward
1927  );
1928 
1929  /*
1930  Description:
1931  Reduce the archive's current position by bytes_backward from the current position.
1932  Parameters:
1933  bytes_backward - [in]
1934  Returns:
1935  True: successful
1936  False: failure
1937  */
1938  bool SeekBackward(
1939  ON__UINT64 bytes_backward
1940  );
1941 
1942 private:
1943  bool Internal_SeekCur(
1944  bool bFowrard,
1945  ON__UINT64 offset
1946  );
1947 
1948 public:
1949 
1950  /*
1951  Description:
1952  Tool for swapping bytes when doing I/O on
1953  using big endian CPUs.
1954  Remarks:
1955  3dm files are always saved with little endian byte order.
1956  See Also:
1957  ON_BinaryArchive::Endian
1958  */
1959  static
1960  bool ToggleByteOrder(
1961  size_t, // number of elements
1962  size_t, // size of element (2,4, or 8)
1963  const void*, // source buffer
1964  void* // destination buffer (can be same a source buffer)
1965  );
1966 
1967  static
1968  const char* TypecodeName( unsigned int tcode );
1969 
1970  static
1971  char* ON_TypecodeParse( unsigned int tcode, char* typecode_name, size_t max_length );
1972 
1973  /*
1974  Returns:
1975  Endian-ness of the cpu reading this file.
1976  Remarks:
1977  3dm files are alwasy saved with little endian byte order.
1978  */
1979  ON::endian Endian() const; // endian-ness of cpu
1980 
1981  bool ReadByte( size_t, void* ); // must fail if mode is not read or readwrite
1982 
1983  bool WriteByte( size_t, const void* ); // must fail if mode is not write or readwrite
1984 
1985  /*
1986  Description:
1987  Expert user function that uses Read() to load a buffer.
1988  Paramters:
1989  sizeof_buffer - [in] number of bytes to attempt to read.
1990  buffer - [out] read bytes are stored in this buffer
1991  Returns:
1992  Number of bytes actually read, which may be less than
1993  sizeof_buffer if the end of file is encountered.
1994  */
1995  ON__UINT64 ReadBuffer( ON__UINT64 sizeof_buffer, void* buffer );
1996 
1997  /*
1998  Description:
1999  Expert user function to control CRC calculation while reading and writing.
2000  Typically this is used when seeking around and reading/writing information
2001  in non-serial order.
2002  Parameters:
2003  bEnable - [in]
2004  Returns:
2005  Current state of CRC calculation. Use the returned value to restore the
2006  CRC calculation setting after you are finished doing your fancy pants
2007  expert IO.
2008  */
2009  bool EnableCRCCalculation( bool bEnable );
2010 
2011  // ReadCompressedBuffer()/WriteCompressedBuffer() use zlib 1.1.3
2012  // to inflate/deflate the data buffer.
2013  // Care must be used to get an endian independent file.
2014  // See ON_Mesh::Read()/ON_Mesh::Write() for an example of an endian
2015  // independent use of compression. See also ToggleByteOrder() and Endian().
2016  //
2017  // To read data archived by WriteCompressedBuffer( sizeof_buffer, buffer )
2018  // do something like:
2019  //
2020  // size_t sizeof_buffer = 0;
2021  // ReadCompressedBufferSize(&sizeof_buffer);
2022  // buffer = something with sizeof_buffer bytes.
2023  // int bFailedCRC = false;
2024  // bool ok = ReadCompressedBuffer( sizeof_buffer, buffer, &bFailedCRC );
2025  //
2026 
2027 
2028  /*
2029  Description:
2030  Red the size of a compressed buffer.
2031  Parameters:
2032  sizeof__outbuffer - [out] size of the uncompressed buffer in bytes
2033  Returns:
2034  True if read was successful.
2035  */
2036  bool ReadCompressedBufferSize( size_t* sizeof__outbuffer );
2037 
2038  /*
2039  Description:
2040  Read compressed information from an archive and uncompress it.
2041  Parameters:
2042  sizeof__outbuffer - [in] size of the uncompressed buffer in bytes
2043  outbuffer - [out] uncompressed buffer returned here
2044  bFailedCRC - [out] true if cyclic redundancy check fails
2045  on uncompressed buffer
2046 
2047  Example:
2048 
2049  size_t sizeof_buffer = 0;
2050  ReadCompressedBufferSize(&sizeof_buffer);
2051  buffer = ...; // something with sizeof_buffer bytes.
2052  int bFailedCRC = false;
2053  bool ok = ReadCompressedBuffer( sizeof_buffer, buffer, &bFailedCRC );
2054 
2055  Returns:
2056  True if read was successful. You need to check the value
2057  of bFailedCRC to see if the information that was read is valid.
2058  Remarks:
2059  Write your archive write/read code as if compression is always enabled.
2060  Do not vary what get written or read based on the value of UseBufferCompression().
2061  */
2062  bool ReadCompressedBuffer(
2063  size_t sizeof__outbuffer,
2064  void* outbuffer,
2065  bool* bFailedCRC
2066  );
2067 
2068  /*
2069  Description:
2070  Compress buffer and write the compressed information to the archive.
2071  Parameters:
2072  sizeof__inbuffer - [in] size of the uncompressed buffer in bytes
2073  inbuffer - [in] uncompressed buffer
2074  Returns:
2075  True if write was successful.
2076  Remarks:
2077  Write your archive write/read code as if compression is always enabled.
2078  Do not vary what get written or read based on the value of UseBufferCompression().
2079  */
2080  bool WriteCompressedBuffer(
2081  size_t sizeof__inbuffer,
2082  const void* inbuffer
2083  );
2084 
2085  bool ReadBool( bool* );
2086 
2087  bool ReadChar( // Read an array of 8 bit chars
2088  size_t, // number of chars to read
2089  char*
2090  );
2091  bool ReadChar( // Read an array of 8 bit unsigned chars
2092  size_t, // number of unsigned chars to read
2093  unsigned char*
2094  );
2095  bool ReadChar( // Read a single 8 bit char
2096  char*
2097  );
2098  bool ReadChar( // Read a single 8 bit unsigned char
2099  unsigned char*
2100  );
2101 
2102  bool ReadShort( // Read an array of 16 bit shorts
2103  size_t, // number of shorts to read
2104  short*
2105  );
2106  bool ReadShort( // Read an array of 16 bit unsigned shorts
2107  size_t, // number of shorts to read
2108  unsigned short*
2109  );
2110  bool ReadShort( // Read a single 16 bit short
2111  short*
2112  );
2113  bool ReadShort( // Read a single 16 bit unsigned short
2114  unsigned short*
2115  );
2116 
2117  bool ReadInt( // Read an array of 32 bit integers
2118  size_t, // number of ints to read
2119  int*
2120  );
2121  bool ReadInt( // Read an array of 32 bit integers
2122  size_t, // number of ints to read
2123  unsigned int*
2124  );
2125  bool ReadInt( // Read a single 32 bit integer
2126  int*
2127  );
2128  bool ReadInt( // Read a single 32 bit unsigned integer
2129  unsigned int*
2130  );
2131 
2132  bool ReadBigInt( // Read an array of 64 bit integers
2133  size_t, // number of ints to read
2134  ON__INT64*
2135  );
2136  bool ReadBigInt( // Read an array of 64 bit integers
2137  size_t, // number of ints to read
2138  ON__UINT64*
2139  );
2140  bool ReadBigInt( // Read a single 64 bit integer
2141  ON__INT64*
2142  );
2143  bool ReadBigInt( // Read a single 64 bit unsigned integer
2144  ON__UINT64*
2145  );
2146 
2147  bool ReadLong( // Read an array of 32 bit integers
2148  size_t, // number of ints to read
2149  long*
2150  );
2151  bool ReadLong( // Read an array of 32 bit integers
2152  size_t, // number of ints to read
2153  unsigned long*
2154  );
2155  bool ReadLong( // Read a single 32 bit integer
2156  long*
2157  );
2158  bool ReadLong( // Read a single 32 bit unsigned integer
2159  unsigned long*
2160  );
2161  bool ReadSize( // Read a single size_t
2162  size_t*
2163  );
2164 
2165  bool ReadBigSize( size_t* ); // 64 bits
2166 
2167  bool ReadBigTime( time_t* ); // UCT seconds since 1 January 1970 (64 bits)
2168 
2169 
2170  bool ReadFloat( // Read an array of floats
2171  size_t, // number of floats
2172  float*
2173  );
2174  bool ReadFloat( // Read a single float
2175  float*
2176  );
2177  bool ReadDouble( // Read an array of IEEE doubles
2178  size_t, // number of doubles
2179  double*
2180  );
2181  bool ReadDouble( // Read a single double
2182  double*
2183  );
2184 
2185  bool ReadColor(
2186  ON_Color&
2187  );
2188 
2189  bool ReadPoint (
2190  ON_2dPoint&
2191  );
2192  bool ReadPoint (
2193  ON_3dPoint&
2194  );
2195  bool ReadPoint (
2196  ON_4dPoint&
2197  );
2198  bool ReadVector (
2199  ON_2dVector&
2200  );
2201  bool ReadVector (
2202  ON_3dVector&
2203  );
2204 
2205  bool ReadBoundingBox(ON_BoundingBox&);
2206 
2207  bool ReadXform(ON_Xform&);
2208 
2209  bool ReadPlaneEquation(ON_PlaneEquation&);
2210 
2211  bool ReadPlane(ON_Plane&);
2212 
2213  bool ReadLine(ON_Line&);
2214 
2215  bool ReadArc(ON_Arc&);
2216 
2217  bool ReadCircle(ON_Circle&);
2218 
2219  bool ReadInterval( ON_Interval& );
2220 
2221  bool ReadUuid( ON_UUID& );
2222 
2223  bool ReadDisplayMaterialRef( ON_DisplayMaterialRef& );
2224 
2225  bool ReadLinetypeSegment( ON_LinetypeSegment& );
2226 
2227  // All times are stored in coordinated universal time
2228  // ( a.k.a GMT, UTC ). Use ANSI C time() and gmtime() calls.
2229  bool ReadTime( struct tm& );
2230 
2231  /*
2232  Parameters:
2233  str_array_count - [out]
2234  Number of elements in the string array. All ON_BinaryArchive string
2235  WriteString() functions write a null terminator to the file and
2236  the null terminator is included in the count. This means that
2237  if a string has a non-zero element, then str_array_count >= 2.
2238  Remarks:
2239  Modify your code to use ReadStringUTF8ElementCount() when reading
2240  UTF-8 encoded strings and ReadStringUTF16ElementCount()
2241  when reading UTF-16 encoded strings.
2242  */
2243  ON_DEPRECATED_MSG("Use either ReadStringUTF8ElementCount() or ReadStringUTF16ElementCount()")
2244  bool ReadStringSize(
2245  size_t* str_array_count
2246  );
2247 
2248  /*
2249  Parameters:
2250  string_utf8_element_count - [out]
2251  Number of bytes in the string array. All ON_BinaryArchive string
2252  WriteString() functions write a null terminator to the file and
2253  the null terminator is included in string_element_count. This means
2254  that if opennurbs wrote the string, either string_element_count = 0
2255  or string_element_count >= 2.
2256  */
2257  bool ReadStringUTF8ElementCount(
2258  size_t* string_utf8_element_count
2259  );
2260 
2261  /*
2262  Parameters:
2263  string_utf16_element_count - [out]
2264  Number of elements in the string array. All ON_BinaryArchive string
2265  WriteString() functions write a null terminator to the file and
2266  the null terminator is included in string_element_count. This means
2267  that if opennurbs wrote the string, either string_element_count = 0
2268  or string_element_count >= 2.
2269  */
2270  bool ReadStringUTF16ElementCount(
2271  size_t* string_utf16_element_count
2272  );
2273 
2274 
2275  /*
2276  Parameters:
2277  str_array_count - [in]
2278  Number of char elements in str_array[], including the null
2279  terminator. The value of str_array_count is returned by
2280  ReadCharStringElementCount().
2281  str_array - [in/out]
2282  Pass in an array with at least str_array_count elements.
2283  If true is returned and str_array_count > 0,
2284  then str_array[str_array_count-1] = 0. All strings with
2285  char elements written by Rhino are UTF-8 encoded
2286  unicode strings.
2287  */
2288  bool ReadString(
2289  size_t str_array_count,
2290  char* str_array
2291  );
2292 
2293  /*
2294  Parameters:
2295  str_array_count - [in]
2296  Number of unsignd char elements in str_array[], including
2297  the null terminator. The value of str_array_count is returned
2298  by ReadCharStringElementCount().
2299  str_array - [in/out]
2300  Pass in an array with at least str_array_count elements.
2301  If true is returned and str_array_count > 0,
2302  then str_array[str_array_count-1] = 0. All strings with
2303  unsigned char elements written by Rhino are UTF-8 encoded
2304  unicode strings.
2305  */
2306  bool ReadString(
2307  size_t str_array_count,
2308  unsigned char* str_array
2309  );
2310 
2311  /*
2312  Parameters:
2313  str_array_count - [in]
2314  Number of unsigned short elements in str_array[],
2315  including the null terminator. The value of
2316  str_array_count is returned by ReadWideCharStringElementCount().
2317  str_array - [in/out]
2318  Pass in an array with at least str_array_count elements.
2319  If true is returned and str_array_count > 0,
2320  then str_array[str_array_count-1] = 0. All strings with
2321  unsigned short elements written by Rhino are UTF-16 encoded
2322  unicode strings.
2323  */
2324  bool ReadString(
2325  size_t str_array_count,
2326  unsigned short* str_array
2327  );
2328 
2329  bool ReadString( ON_String& sUTF8 );
2330 
2331  bool ReadString( ON_wString& s );
2332 
2333  bool ReadComponentIndex( ON_COMPONENT_INDEX& );
2334 
2335  bool ReadArray( ON_SimpleArray<bool>& );
2336  bool ReadArray( ON_SimpleArray<char>& );
2337  bool ReadArray( ON_SimpleArray<short>& );
2338  bool ReadArray( ON_SimpleArray<int>& );
2339  bool ReadArray( ON_SimpleArray<float>& );
2340  bool ReadArray( ON_SimpleArray<double>& );
2341  bool ReadArray( ON_SimpleArray<ON_Color>& );
2342  bool ReadArray( ON_SimpleArray<ON_2dPoint>& );
2343  bool ReadArray( ON_SimpleArray<ON_3dPoint>& );
2344  bool ReadArray( ON_SimpleArray<ON_4dPoint>& );
2345  bool ReadArray( ON_SimpleArray<ON_2dVector>& );
2346  bool ReadArray( ON_SimpleArray<ON_3dVector>& );
2347  bool ReadArray( ON_SimpleArray<ON_Xform>& );
2348  bool ReadArray( ON_SimpleArray<ON_2fPoint>& );
2349  bool ReadArray( ON_SimpleArray<ON_3fPoint>& );
2350  bool ReadArray( ON_SimpleArray<ON_4fPoint>& );
2351  bool ReadArray( ON_SimpleArray<ON_2fVector>& );
2352  bool ReadArray( ON_SimpleArray<ON_3fVector>& );
2353  bool ReadArray( ON_SimpleArray<ON_UUID>& );
2354  bool ReadArray( ON_SimpleArray<ON_UuidIndex>& );
2355  bool ReadArray( ON_SimpleArray<ON_UuidPtr>& );
2356  bool ReadArray( ON_SimpleArray<ON_SurfaceCurvature>& );
2357  bool ReadArray( ON_ClassArray<ON_String>& );
2358  bool ReadArray( ON_ClassArray<ON_wString>& );
2359  bool ReadArray( ON_SimpleArray<ON_DisplayMaterialRef>& );
2360  bool ReadArray( ON_SimpleArray<ON_LinetypeSegment>& );
2361  bool ReadArray( ON_SimpleArray<ON_MappingChannel>& );
2362  bool ReadArray( ON_ClassArray<ON_MaterialRef>& );
2363  bool ReadArray( ON_ClassArray<ON_MappingRef>& );
2364  bool ReadArray( ON_ClassArray<class ON_ObjRef>& );
2365  bool ReadArray( ON_SimpleArray<class ON_ObjRef_IRefID>& );
2366  bool ReadArray( ON_SimpleArray<class ON_ClippingPlaneInfo>& );
2367  bool ReadArray( ON_ObjectArray<class ON_Layer>& );
2368  bool ReadArray( ON_SimpleArray<class ON_Layer*>& );
2369 
2370  bool WriteBool( bool );
2371 
2372 #if defined(ON_COMPILER_MSC) && defined(NDEBUG)
2373  // Work around Release build optimization bug in Visual Studio 2017.
2374  __declspec(noinline)
2375 #endif
2376  bool WriteBoolTrue();
2377 
2378 #if defined(ON_COMPILER_MSC) && defined(NDEBUG)
2379  // Work around Release build optimization bug in Visual Studio 2017.
2380  __declspec(noinline)
2381 #endif
2382  bool WriteBoolFalse();
2383 
2384  bool WriteChar( // Write an array of 8 bit chars
2385  size_t, // number of chars to write
2386  const char*
2387  );
2388  bool WriteChar( // Write an array of 8 bit unsigned chars
2389  size_t, // number of unsigned chars to write
2390  const unsigned char*
2391  );
2392  bool WriteChar( // Write a single 8 bit char
2393  char
2394  );
2395  bool WriteChar( // Write a single 8 bit unsigned char
2396  unsigned char
2397  );
2398 
2399  bool WriteShort( // Write an array of 16 bit shorts
2400  size_t, // number of shorts to write
2401  const short*
2402  );
2403  bool WriteShort( // Write an array of 16 bit unsigned shorts
2404  size_t, // number of shorts to write
2405  const unsigned short*
2406  );
2407  bool WriteShort( // Write a single 16 bit short
2408  short
2409  );
2410  bool WriteShort( // Write a single 16 bit unsigned short
2411  unsigned short
2412  );
2413 
2414  bool WriteInt( // Write an array of 32 bit integers
2415  size_t, // number of ints to write
2416  const int*
2417  );
2418  bool WriteInt( // Write an array of 32 bit integers
2419  size_t, // number of ints to write
2420  const unsigned int*
2421  );
2422  bool WriteInt( // Write a single 32 bit integer
2423  int
2424  );
2425  bool WriteInt( // Write a single 32 bit unsigned integer
2426  unsigned int
2427  );
2428 
2429  bool WriteBigInt( // Write an array of 64 bit integers
2430  size_t, // number of ints to write
2431  const ON__INT64*
2432  );
2433  bool WriteBigInt( // Write an array of 64 bit integers
2434  size_t, // number of ints to write
2435  const ON__UINT64*
2436  );
2437  bool WriteBigInt( // Write a single 64 bit integer
2438  ON__INT64
2439  );
2440  bool WriteBigInt( // Write a single 64 bit unsigned integer
2441  ON__UINT64
2442  );
2443 
2444  bool WriteLong( // Write an array of 32 bit integers
2445  size_t, // number of ints to write
2446  const long*
2447  );
2448  bool WriteLong( // Write an array of 32 bit integers
2449  size_t, // number of ints to write
2450  const unsigned long*
2451  );
2452  bool WriteLong( // Write a single 32 bit integer
2453  long
2454  );
2455  bool WriteLong( // Write a single 32 bit unsigned integer
2456  unsigned long
2457  );
2458  bool WriteSize( // Write a single size_t
2459  size_t
2460  );
2461 
2462  bool WriteBigSize( size_t ); // 64 bits
2463 
2464  bool WriteBigTime( time_t ); // UCT seconds since 1 January 1970 (64 bits)
2465 
2466  bool WriteFloat( // Write a number of IEEE floats
2467  size_t, // number of doubles
2468  const float*
2469  );
2470  bool WriteFloat( // Write a single float
2471  float
2472  );
2473  bool WriteDouble( // Write a single double
2474  size_t,
2475  const double*
2476  );
2477  bool WriteDouble( // Write a single double
2478  double
2479  );
2480 
2481  bool WriteColor (
2482  const ON_Color&
2483  );
2484 
2485  bool WritePoint (
2486  const ON_2dPoint&
2487  );
2488  bool WritePoint (
2489  const ON_3dPoint&
2490  );
2491  bool WritePoint (
2492  const ON_4dPoint&
2493  );
2494  bool WriteVector (
2495  const ON_2dVector&
2496  );
2497  bool WriteVector (
2498  const ON_3dVector&
2499  );
2500 
2501  bool WriteBoundingBox(const ON_BoundingBox&);
2502 
2503  bool WriteXform(const ON_Xform&);
2504 
2505  bool WritePlaneEquation(const ON_PlaneEquation&);
2506 
2507  bool WritePlane(const ON_Plane&);
2508 
2509  bool WriteLine(const ON_Line&);
2510 
2511  bool WriteArc(const ON_Arc&);
2512 
2513  bool WriteCircle(const ON_Circle&);
2514 
2515  bool WriteInterval( const ON_Interval& );
2516 
2517  bool WriteUuid( const ON_UUID& );
2518 
2519  bool WriteDisplayMaterialRef( const ON_DisplayMaterialRef& );
2520 
2521  bool WriteLinetypeSegment( const ON_LinetypeSegment& );
2522 
2523  // All times are stored in universal coordinated time
2524  // ( a.k.a GMT, UCT ). Use ANSI C time() and gmtime() calls.
2525  bool WriteTime( const struct tm& );
2526 
2527  /*
2528  Parameters:
2529  sUTF8 - [in]
2530  A null terminated UTF-8 encoded unicode string.
2531  Remarks:
2532  To read a string written with WriteString(const char*),
2533  call ReadStringUTF8ElementCount(&string_utf8_element_count)
2534  to get the number of char elements written in the file,
2535  obtain a buffer with at least string_utf8_element_count
2536  char elements and then call
2537  ReadString(string_utf8_element_count,buffer) to read the
2538  char elements.
2539 
2540  If 0 == sUTF8 or 0 == SUTF8[0], a 4 byte int with
2541  value = 0 is written, otherwise a 4 byte int with
2542  value = strlen + 1 is written, followed by the string,
2543  followed by the null terminator.
2544  */
2545  bool WriteString(
2546  const char* sUTF8
2547  );
2548 
2549  /*
2550  Parameters:
2551  sUTF8 - [in]
2552  A null terminated UTF-8 encoded unicode string.
2553  Remarks:
2554  To read a string written with WriteString(const unsigned char*),
2555  call ReadStringUTF8ElementCount(&string_utf8_element_count) to
2556  get the number of unsigned char elements written in the file,
2557  obtain a buffer with at least string_utf8_element_count
2558  unsigned char elements and then call
2559  ReadString(string_utf8_element_count,buffer) to read the
2560  unsigned charelements.
2561 
2562  If 0 == sUTF8 or 0 == SUTF8[0], a 4 byte int with
2563  value = 0 is written, otherwise a 4 byte int with
2564  value = strlen + 1 is written, followed by the string,
2565  followed by the null terminator.
2566  */
2567  bool WriteString(
2568  const unsigned char* sUTF8
2569  );
2570 
2571  /*
2572  Parameters:
2573  sUTF16 - [in]
2574  A null terminated UTF-16 encoded unicode string.
2575  Remarks:
2576  To read a string written with WriteString(const unsigned short*),
2577  call ReadStringUTF16ElementCount(&string_utf16_element_count) to
2578  get the number of unsigned short elements written in the file,
2579  obtain a buffer with at least string_utf16_element_count
2580  unsigned short elements and then call
2581  ReadString(string_utf16_element_count,buffer) to read the
2582  unsigned short elements.
2583 
2584  If 0 == sUTF8 or 0 == SUTF8[0], a 4 byte int with
2585  value = 0 is written, otherwise a 4 byte int with
2586  value = strlen + 1 is written, followed by the string,
2587  followed by the null terminator.
2588  */
2589  bool WriteUTF16String(
2590  const unsigned short* sUTF16
2591  );
2592 
2593  /*
2594  Description:
2595  Write a wide string as a UTF-8 encoded string.
2596  */
2597  bool WriteWideString(
2598  const wchar_t* sWideChar,
2599  int sWideChar_count
2600  );
2601 
2602  /*
2603  Description:
2604  Write a wide string as a UTF-8 encoded string.
2605  */
2606  bool WriteWideString(
2607  const ON_wString& wide_string
2608  );
2609 
2610  /*
2611  Description:
2612  Read a wide string written with the WriteWideString() function.
2613  */
2614  bool ReadWideString(
2615  ON_wString& wide_string
2616  );
2617 
2618  bool WriteString( const ON_String& sUTF8 );
2619 
2620  bool WriteString( const ON_wString& s);
2621 
2622  bool WriteComponentIndex( const ON_COMPONENT_INDEX& );
2623 
2624  bool WriteArray( const ON_SimpleArray<bool>& );
2625  bool WriteArray( const ON_SimpleArray<char>& );
2626  bool WriteArray( const ON_SimpleArray<short>& );
2627  bool WriteArray( const ON_SimpleArray<int>& );
2628  bool WriteArray( const ON_SimpleArray<float>& );
2629  bool WriteArray( const ON_SimpleArray<double>& );
2630 
2631  bool WriteArray( const ON_SimpleArray<ON_Color>& );
2632 
2633  bool WriteArray( const ON_SimpleArray<ON_2dPoint>& );
2634  bool WriteArray( const ON_SimpleArray<ON_3dPoint>& );
2635  bool WriteArray( const ON_SimpleArray<ON_4dPoint>& );
2636  bool WriteArray( const ON_SimpleArray<ON_2dVector>& );
2637  bool WriteArray( const ON_SimpleArray<ON_3dVector>& );
2638 
2639  bool WriteArray( const ON_SimpleArray<ON_2fPoint>& );
2640  bool WriteArray( const ON_SimpleArray<ON_3fPoint>& );
2641  bool WriteArray( const ON_SimpleArray<ON_4fPoint>& );
2642  bool WriteArray( const ON_SimpleArray<ON_2fVector>& );
2643  bool WriteArray( const ON_SimpleArray<ON_3fVector>& );
2644  bool WriteArray( const ON_SimpleArray<ON_Xform>& );
2645  bool WriteArray( const ON_SimpleArray<ON_UUID>& );
2646  bool WriteArray( const ON_SimpleArray<ON_UuidIndex>& );
2647  bool WriteArray( const ON_SimpleArray<ON_UuidPtr>& );
2648  bool WriteArray( const ON_SimpleArray<ON_SurfaceCurvature>& );
2649  bool WriteArray( const ON_ClassArray<ON_String>& );
2650  bool WriteArray( const ON_ClassArray<ON_wString>& );
2651  bool WriteArray( const ON_SimpleArray<ON_DisplayMaterialRef>& );
2652  bool WriteArray( const ON_SimpleArray<ON_LinetypeSegment>& );
2653  bool WriteArray( const ON_SimpleArray<ON_MappingChannel>& );
2654  bool WriteArray( const ON_ClassArray<ON_MaterialRef>& );
2655  bool WriteArray( const ON_ClassArray<ON_MappingRef>& );
2656  bool WriteArray( const ON_ClassArray<class ON_ObjRef>& );
2657  bool WriteArray( const ON_SimpleArray<class ON_ObjRef_IRefID>& );
2658  bool WriteArray( const ON_SimpleArray<class ON_ClippingPlaneInfo>& );
2659  bool WriteArray( int count, const class ON_Layer* );
2660  bool WriteArray( int count, const class ON_Layer*const* );
2661 
2662  /////////////////////////////////////////////////////
2663  //
2664  // Read/Write classes derived from ON_Object
2665  //
2666 
2667  /*
2668  Description:
2669  Reads and object from a 3dm archive;
2670  Parameters:
2671  ppObject - [out] object is allocated and a pointer to the
2672  allocated object is returned as *ppObject;
2673  Returns:
2674  0: failure - unable to read object because of file IO problems
2675  1: success
2676  3: unable to read object because it's UUID is not registered
2677  this could happen in cases where old code is attempting to read
2678  new objects.
2679  */
2680  int ReadObject(
2681  ON_Object** ppObject
2682  );
2683 
2684 
2685  /*
2686  Description:
2687  Reads and object from a 3dm archive.
2688  Parameters:
2689  object - [in] The value of object.ON_ClassId()->Uuid() must
2690  exactly match the class uuid in of the next
2691  object in the archive.
2692  Returns:
2693  0: failure - unable to read object because of file IO problems.
2694  1: success
2695  2: unable to read object because the class id in the archive
2696  did not match pObject->ClassId.
2697  */
2698  int ReadObject(
2699  ON_Object& object
2700  );
2701 
2702  bool WriteObject( const ON_Object* ); // writes object definition
2703  bool WriteObject( const ON_Object& ); // writes object definition
2704 
2705 private:
2706  bool Internal_WriteObject(
2707  const ON_Object& model_object
2708  );
2709  bool Internal_WriteV5AnnotationObject(
2710  const class ON_Annotation& V6_annotation,
2711  const class ON_3dmAnnotationContext* annotation_context
2712  );
2713  bool Internal_WriteV2AnnotationObject(
2714  const class ON_OBSOLETE_V5_Annotation& V5_annotation,
2715  const class ON_3dmAnnotationContext* annotation_context
2716  );
2717 public:
2718 
2719 
2720  ///////////////////////////////////////////////////////////////////
2721  ///////////////////////////////////////////////////////////////////
2722  //
2723  // 3DM Interface - ignore if not reading/writing a 3DM file
2724  // this is here so that the infrastructure
2725  // for writing 3dm archives is available for
2726  // any type of serialization device.
2727  //
2728 
2729  /*
2730  Description:
2731  Specify which types of objects (ON_Brep, ON_Extrusion, ON_SubD, ...)
2732  save render meshes in the 3dm file.
2733 
2734  Parameters:
2735  object_type_flags - [in]
2736  The bits in object_type_flags correspond to ON::object_type values
2737  and identify the object types the setting will be applied to.
2738 
2739  Remarks:
2740  Saving render meshes increases file size, sometimes dramatically.
2741 
2742  Creating ON_Brep analysis meshes is often slow.
2743  Disable saving ON_Brep analysis meshes when IO speed or file size is
2744  a critical issue, the time expense of recreating the ON_Brep meshes
2745  when the file is read is acceptable, and the file will be read by Rhino.
2746  Enable when the file size is not an issue or the file will be used by other
2747  applications that may not be able to create meshes.
2748 
2749  Creating ON_Extrusion meshes is fast. Disable when IO speed or file size
2750  is an issue and the file will be read by Rhino. Enable when the file
2751  will be used by other applications that may not be able to create meshes.
2752 
2753  Creating ON_SubD meshes is fast. Disable when IO speed or file size
2754  is an issue and the file will be read by Rhino. Enable when the file
2755  will be used by other applications that may not be able to create meshes.
2756  */
2757  void EnableSave3dmRenderMeshes(
2758  unsigned int object_type_flags,
2759  bool bSave3dmRenderMeshes
2760  );
2761 
2762  /*
2763  Description:
2764  Specify which types of objects (ON_Brep, ON_Extrusion, ON_SubD, ...)
2765  save render meshes in the 3dm file.
2766  Returns:
2767  The bits in the return value correspond to ON::object_type values
2768  and identify the object types save analysis meshes in the 3dm file.
2769  */
2770  unsigned int Save3dmRenderMeshObjectTypeFlags() const;
2771 
2772  /*
2773  Parameters:
2774  object_type - [in]
2775  Returns:
2776  true if render meshes for the specified object type will be
2777  saved in the .3dm file.
2778  */
2779  bool Save3dmRenderMesh(
2780  ON::object_type object_type
2781  ) const;
2782 
2783  /*
2784  Description:
2785  Specify which types of objects (ON_Brep, ON_Extrusion, ON_SubD, ...)
2786  save analysis meshes in the 3dm file.
2787 
2788  Parameters:
2789  object_type_flags - [in]
2790  The bits in object_type_flags correspond to ON::object_type values
2791  and identify the object types the setting will be applied to.
2792 
2793  Remarks:
2794  Saving analysis meshes increases file size, sometimes dramatically.
2795 
2796  Creating ON_Brep analysis meshes is often slow.
2797  Disable saving ON_Brep analysis meshes when IO speed or file size is
2798  a critical issue, the time expense of recreating the ON_Brep meshes
2799  when the file is read is acceptable, and the file will be read by Rhino.
2800  Enable when the file size is not an issue or the file will be used by other
2801  applications that may not be able to create meshes.
2802 
2803  Creating ON_Extrusion meshes is fast. Disable when IO speed or file size
2804  is an issue and the file will be read by Rhino. Enable when the file
2805  will be used by other applications that may not be able to create meshes.
2806 
2807  Creating ON_SubD meshes is fast. Disable when IO speed or file size
2808  is an issue and the file will be read by Rhino. Enable when the file
2809  will be used by other applications that may not be able to create meshes.
2810  */
2811  void EnableSave3dmAnalysisMeshes(
2812  unsigned int object_type_flags,
2813  bool bSave3dmAnalysisMeshes
2814  );
2815 
2816  void SetSave3dmPreviewImage(
2817  bool bSave3dmPreviewImage
2818  );
2819 
2820  /*
2821  Returns:
2822  true: (default)
2823  If a preview image is included in the ON_3dmProperties information, it will be saved.
2824  false:
2825  A preview imae, if it exists, will not be saved in the 3dm archive.
2826  This reduces archive size.
2827  When Save3dmPreviewImage() is false, generating a preview image can be skipped.
2828  */
2829  bool Save3dmPreviewImage() const;
2830 
2831  /*
2832  Description:
2833  Control when some information, like preview images and mesh information, is
2834  compressed when writing 3dm archives. The default is true.
2835  In special situations when the storage media is extremely fast and large file size
2836  is not a concern, disabling buffer compression can reduce file write time.
2837  Parameters:
2838  bUseBufferCompression - [in]
2839  Remarks:
2840  The default is true.
2841  */
2842  void SetUseBufferCompression(
2843  bool bUseBufferCompression
2844  );
2845 
2846  /*
2847  Returns:
2848  true: (default)
2849  Some information, including preview images and mesh information is compressed when
2850  writing 3dm archives. This reduces, sometimes dramatically, the size
2851  of the 3dm archive.
2852  false:
2853  No compression is performed. This increases, sometimes dramatically, the size
2854  of the 3dm archive.
2855  In special situations when the storage media is extremely fast and large file size
2856  is not a concern, disabling buffer compression can reduce file write time.
2857  */
2858  bool UseBufferCompression() const;
2859 
2860 
2861  /*
2862  Description:
2863  Specify which types of objects (ON_Brep, ON_Extrusion, ON_SubD, ...)
2864  save analysis meshes in the 3dm file.
2865  Returns:
2866  The bits in the return value correspond to ON::object_type values
2867  and identify the object types save analysis meshes in the 3dm file.
2868  */
2869  unsigned int Save3dmAnalysisMeshObjectTypeFlags() const;
2870 
2871  /*
2872  Parameters:
2873  object_type - [in]
2874  Returns:
2875  true if analysis meshes for the specified object type will be
2876  saved in the .3dm file.
2877  */
2878  bool Save3dmAnalysisMesh(
2879  ON::object_type object_type
2880  ) const;
2881 
2882 
2883  /*
2884  Returns:
2885  True if all user data and user tables should be read or written.
2886  False if some or no user data or user tables should be read or written.
2887  Remarks:
2888  AllUserDataSerializationIsEnabled() = (false == ShouldSerializeNoUserData() && false == ShouldSerializeSomeUserData())
2889  */
2890  bool ShouldSerializeAllUserData() const;
2891 
2892  /*
2893  Returns:
2894  True if no user data and user tables should be read or written.
2895  False if some or all user data or user tables should be read or written.
2896  Remarks:
2897  SerializeNoUserData() = (false == ShouldSerializeAllUserData() && false == ShouldSerializeSomeUserData())
2898  */
2899  bool ShouldSerializeNoUserData() const;
2900 
2901  /*
2902  Returns:
2903  True if some but not all user data or user tables should be
2904  read or written.
2905  False if all user data or no user data should be read or written.
2906  Remarks:
2907  SerializeSomeUserData() = (false == ShouldSerializeAllUserData() && false == ShouldSerializeNoUserData())
2908 
2909  Use ShouldSerializeUserDataItem(application_id,item_id) to
2910  determine if a specific object user data or user table should
2911  be read or written.
2912  */
2913  bool ShouldSerializeSomeUserData() const;
2914 
2915  /*
2916  Description:
2917  Determine if an application's (plug-in's) object user data
2918  or user table should be read or written.
2919  Parameters:
2920  application_id - [in]
2921  The application id (often a plug-in id) for the object user data
2922  or user table.
2923  item_id - [in]
2924  item_id identifies which user data items should be read or written.
2925  - To determine if a specific type of object user data should
2926  be read or written, pass the value of ON_UserData.m_userdata_uuid.
2927  - To determine if the user table for the application should
2928  be read or written, pass application_id.
2929  - To determine if all object user data and the user table
2930  for the application should be read or written, pass nil.
2931  Returns:
2932  True if the identified user data or user table should be read or written.
2933  */
2934  bool ShouldSerializeUserDataItem(
2935  ON_UUID application_id,
2936  ON_UUID item_id
2937  ) const;
2938 
2939  /*
2940  Description:
2941  Specify the serialization option for object user data and user tables
2942  that are not explicity set by SetShouldSerializeUserDataItem().
2943  Parameters:
2944  bSerialize - [in]
2945  Remarks:
2946  If no setting is specified, all user data is read and written.
2947  */
2948  bool SetShouldSerializeUserDataDefault(
2949  bool bSerialize
2950  );
2951 
2952  bool ShouldSerializeUserDataDefault() const;
2953 
2954 
2955  /*
2956  Description:
2957  Specify if an application's (plug-in's) object user data
2958  or user table should be read or written.
2959  Parameters:
2960  application_id - [in]
2961  The application id (often a plug-in id) for the object user data
2962  or user table.
2963  item_id - [in]
2964  item_id identifies which user data items should be read or written.
2965  - To determine if a specific type of object user data should
2966  be read or written, pass the value of ON_UserData.m_userdata_uuid.
2967  - To determine if the user table for the application should
2968  be read or written, pass application_id.
2969  - To determine if all object user data and the user table
2970  for the application should be read or written, pass nil.
2971  bSerializeUserDataItem - [in]
2972  True to enable reading and writing of the specified item.
2973  False to disable reading and writing of the specified item.
2974  Returns:
2975  True if the input was valid and the setting was applied.
2976  This function will not apply any settings after reading
2977  or writing begins.
2978  */
2979  bool SetShouldSerializeUserDataItem(
2980  ON_UUID application_id,
2981  ON_UUID item_id,
2982  bool bSerializeUserDataItem
2983  );
2984 
2985  /*
2986  Description:
2987  Determine if an object has user data that should be written.
2988  Parameters:
2989  object - [in]
2990  Returns:
2991  True if object has user data that should be written.
2992  */
2993  bool ObjectHasUserDataToWrite(
2994  const class ON_Object* object
2995  ) const;
2996 
2997  bool ShouldWriteUserDataItem(
2998  const class ON_Object* object,
2999  const class ON_UserData* object_user_data
3000  ) const;
3001 
3002  /*
3003  Returns:
3004  10*OPENNURBS_VERSION_MAJOR
3005  (The Rhino <OPENNURBS_VERSION_MAJOR> opennurbs file version.)
3006  This is the value of version to pass to ON_BinaryArchive
3007  functions like Write3dmStartSection() when you want to use the
3008  the current opennurbs version number and you do not want to have
3009  to update your code when this version number changes.
3010  */
3011  static int CurrentArchiveVersion();
3012 
3013  /*
3014  Description:
3015  As time passes, more tables have been added to 3dm archives.
3016  Parameters:
3017  table - [in]
3018  Returns:
3019  True if this archive has the specified table
3020  */
3021  bool ArchiveContains3dmTable(
3022  ON_3dmArchiveTableType table
3023  ) const;
3024 
3025  /*
3026  Parameters:
3027  archive_3dm_version - [in]
3028  1,2,3,4,5,50,60,...
3029  opennurbs_library_version - [in]
3030  a number > 100000000
3031  */
3032  static bool ArchiveContains3dmTable(
3033  ON_3dmArchiveTableType table,
3034  unsigned int archive_3dm_version,
3035  unsigned int opennurbs_library_version
3036  );
3037 
3038  bool WriteModelComponentName(
3039  const ON_ModelComponent& model_component
3040  );
3041 
3042  ///////////////////////////////////////////////////////////////////
3043  // Step 1: REQUIRED - Write/Read Start Section
3044  //
3045 
3046  /*
3047  Parameters:
3048  version - [in]
3049  0, 2, 3, 4, 5, 50 or 60 (5 is treated as 50)
3050 
3051  If version is 0, then the value of ON_BinaryArchive::CurrentArchiveVersion()
3052  is used.
3053 
3054  Use either 0 or the value of ON_BinaryArchive::CurrentArchiveVersion()
3055  for the version parameter when you want your code to write the most
3056  up to date file version.
3057 
3058  sStartSectionComment - [in]
3059  nullptr or a UTF-8 encoded string with application name, et cetera.
3060  This information is primarily used when debugging files
3061  that contain problems. McNeel and Associates stores
3062  application name, application version, compile date,
3063  and the OS in use when file was written.
3064  */
3065  bool Write3dmStartSection(
3066  int version,
3067  const char* sStartSectionComment
3068  );
3069 
3070  /*
3071  Parameters:
3072  version - [out]
3073  .3dm file version (2, 3, 4, 5, 50, 60)
3074  sStartSectionComment - [out]
3075  UTF-8 encoded string passed to Write3dmStartSection()
3076  destination_manifest - [in]
3077  manifest of the destination model
3078  */
3079  bool Read3dmStartSection(
3080  int* version,
3081  ON_String& sStartSectionComment
3082  );
3083 
3084  /*
3085  Returns:
3086  A copy of the start section comment written to or read from the archive.
3087  If this function is called before Write3dmStartSection() or Read3dmStartSection(),
3088  it returns ON_String:EmptyString;
3089  */
3090  const ON_String& Archive3dmStartSectionComment() const;
3091 
3092  ///////////////////////////////////////////////////////////////////
3093  // Step 2: REQUIRED - Write/Read properties table
3094  //
3095  bool Write3dmProperties(
3096  const class ON_3dmProperties&
3097  );
3098  bool Read3dmProperties(
3099  class ON_3dmProperties&
3100  );
3101 
3102  /*
3103  Returns:
3104  A copy of the ON_3dmProperties information written to or read from the archive.
3105  If this function is called before Write3dmProperties() or Read3dmProperties(),
3106  it returns ON_3dmProperties:Empty;
3107  */
3108  const class ON_3dmProperties& Archive3dmProperties() const;
3109 
3110  ///////////////////////////////////////////////////////////////////
3111  // Step 3: REQUIRED - Write/Read settings table
3112  //
3113  bool Write3dmSettings(
3114  const class ON_3dmSettings&
3115  );
3116  bool Read3dmSettings(
3117  class ON_3dmSettings&
3118  );
3119 
3120  /*
3121  Returns:
3122  A copy of the ON_3dmSettings information written to or read from the archive.
3123  If this function is called before Write3dmSettings() or Read3dmSettings(),
3124  it returns ON_3dmSettings:Default;
3125  */
3126  const class ON_3dmSettings& Archive3dmSettings() const;
3127 
3128  ///////////////////////////////////////////////////////////////////
3129  // Step 4: REQUIRED - Write/Read bitmap table (it can be empty)
3130  //
3131  bool BeginWrite3dmBitmapTable();
3132  bool Write3dmImageComponent(
3133  const class ON_ModelComponentReference& model_component_reference
3134  );
3135  bool Write3dmImageComponent(
3136  const class ON_ModelComponent* model_component
3137  );
3138  bool Write3dmBitmap( const class ON_Bitmap& );
3139  bool EndWrite3dmBitmapTable();
3140 
3141  bool BeginRead3dmBitmapTable();
3142  int Read3dmBitmap( // returns 0 at end of bitmap table
3143  // 1 bitmap successfully read
3144  class ON_Bitmap** // bitmap returned here
3145  );
3146  bool EndRead3dmBitmapTable();
3147 
3148  ///////////////////////////////////////////////////////////////////
3149  // Step 5: REQUIRED - Write/Read texture mapping table (it can be empty)
3150  //
3151  bool BeginWrite3dmTextureMappingTable();
3152  bool Write3dmTextureMappingComponent(
3153  const class ON_ModelComponentReference& model_component_reference
3154  );
3155  bool Write3dmTextureMappingComponent(
3156  const class ON_ModelComponent* model_component
3157  );
3158  bool Write3dmTextureMapping( const class ON_TextureMapping& );
3159  bool EndWrite3dmTextureMappingTable();
3160 
3161  bool BeginRead3dmTextureMappingTable();
3162  int Read3dmTextureMapping( // returns 0 at end of table
3163  class ON_TextureMapping** // testuremapping returned here
3164  );
3165  bool EndRead3dmTextureMappingTable();
3166 
3167  ///////////////////////////////////////////////////////////////////
3168  // Step 6: REQUIRED - Write/Read render material table (it can be empty)
3169  //
3170  bool BeginWrite3dmMaterialTable();
3171  bool Write3dmMaterialComponent(
3172  const class ON_ModelComponentReference& model_component_reference
3173  );
3174  bool Write3dmMaterialComponent(
3175  const class ON_ModelComponent* model_component
3176  );
3177  bool Write3dmMaterial( const class ON_Material& );
3178  bool EndWrite3dmMaterialTable();
3179 
3180  bool BeginRead3dmMaterialTable();
3181  int Read3dmMaterial( // returns 0 at end of table
3182  class ON_Material** // material returned here
3183  );
3184  bool EndRead3dmMaterialTable();
3185 
3186  ///////////////////////////////////////////////////////////////////
3187  // Step 7: REQUIRED - Write/Read linetype table (it can be empty)
3188  //
3189  bool BeginWrite3dmLinetypeTable();
3190  bool Write3dmLinePatternComponent(
3191  const class ON_ModelComponentReference& model_component_reference
3192  );
3193  bool Write3dmLinePatternComponent(
3194  const class ON_ModelComponent* model_component
3195  );
3196  bool Write3dmLinetype(
3197  const class ON_Linetype& line_pattern
3198  );
3199  bool EndWrite3dmLinetypeTable();
3200 
3201  bool BeginRead3dmLinetypeTable();
3202  int Read3dmLinetype(
3203  class ON_Linetype**
3204  );
3205  bool EndRead3dmLinetypeTable();
3206 
3207  ///////////////////////////////////////////////////////////////////
3208  // Step 8: REQUIRED - Write/Read layer table (it can be empty)
3209  //
3210  bool BeginWrite3dmLayerTable();
3211  bool Write3dmLayerComponent(
3212  const class ON_ModelComponentReference& model_component_reference
3213  );
3214  bool Write3dmLayerComponent(
3215  const class ON_ModelComponent* model_component
3216  );
3217  bool Write3dmLayer( const ON_Layer& );
3218  bool EndWrite3dmLayerTable();
3219 
3220  bool BeginRead3dmLayerTable();
3221  int Read3dmLayer( // returns 0 at end of table
3222  ON_Layer** // layer returned here
3223  );
3224  bool EndRead3dmLayerTable();
3225 
3226  ///////////////////////////////////////////////////////////////////
3227  // Step 9: REQUIRED - Write/Read group table (it can be empty)
3228  //
3229  bool BeginWrite3dmGroupTable();
3230  bool Write3dmGroupComponent(
3231  const class ON_ModelComponentReference& model_component_reference
3232  );
3233  bool Write3dmGroupComponent(
3234  const class ON_ModelComponent* model_component
3235  );
3236  bool Write3dmGroup( const class ON_Group& );
3237  bool EndWrite3dmGroupTable();
3238 
3239  bool BeginRead3dmGroupTable();
3240 
3241  // Description:
3242  // Reads groups from group table. If the group definition is
3243  // read, a group is created by calling new ON_Group(),
3244  // initialized with values stored in the archive, and
3245  // returned.
3246  //
3247  // Parameters:
3248  // ppGroup - If the group definition is
3249  // read, a group is created by calling new ON_Group(),
3250  // initialized with values stored in the archive, and
3251  // a pointer to the new group is returned in *ppGroup.
3252  //
3253  // Returns:
3254  //
3255  // @untitled table
3256  // 0 at the end of the group table
3257  // 1 group definition was successfully read
3258  // -1 archive is corrupt at this point
3259  //
3260  // Example:
3261  // Calls to Read3dmGroup need to be bracketed by calls
3262  // to BeginRead3dmGroupTable() / EndRead3dmGroupTable().
3263  //
3264  // archive.BeginRead3dmGroupTable();
3265  // ON_Group* pGroup;
3266  // int rc = 1;
3267  // while(rc==1)
3268  // { //
3269  // pGroup = 0;
3270  // archive.Read3dmGroup(&pGroup);
3271  // if ( pGroup )
3272  // do something with pGroup
3273  // } //
3274  // archive.EndRead3dmGroupTable();
3275  //
3276  int Read3dmGroup(
3277  class ON_Group** // ppGroup
3278  );
3279 
3280  bool EndRead3dmGroupTable();
3281 
3282 
3283  ///////////////////////////////////////////////////////////////////////
3284  ////// Step 10: REQUIRED - Write/Read text_style table (it can be empty)
3285  //////
3286  ////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.")
3287  ////bool BeginWrite3dmTextStyleTable();
3288  ////////bool Write3dmTextStyleComponent(
3289  //////// const class ON_ModelComponentReference& model_component_reference
3290  //////// );
3291  ////////bool Write3dmTextStyleComponent(
3292  //////// const class ON_ModelComponent* model_component
3293  //////// );
3294  ////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.")
3295  ////bool Write3dmTextStyle(
3296  //// const class ON_TextStyle&
3297  //// );
3298  ////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.")
3299  ////bool EndWrite3dmTextStyleTable();
3300 
3301 private:
3302  ////bool Internal_BeginWrite3dmTextStyleTable();
3303  bool Internal_Write3dmTextStyle(
3304  const class ON_TextStyle&
3305  );
3306  /////bool Internal_EndWrite3dmTextStyleTable();
3307 
3308 public:
3309 
3310  //////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.")
3311  //////bool BeginRead3dmTextStyleTable();
3312 
3313  //////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.")
3314  //////int Read3dmTextStyle(
3315  ////// class ON_TextStyle** // ppTextStyle
3316  ////// );
3317 
3318  //////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.")
3319  //////bool EndRead3dmTextStyleTable();
3320 
3321 private:
3322  int Internal_Read3dmTextStyle(
3323  class ON_TextStyle** // ppTextStyle
3324  );
3325 public:
3326 
3327  ///////////////////////////////////////////////////////////////////
3328  // Step 11: REQUIRED - Write/Read dimstyle table (it can be empty)
3329  //
3330  bool BeginWrite3dmDimStyleTable();
3331 
3332  bool Write3dmDimStyleComponent(
3333  const class ON_ModelComponentReference& model_component_reference
3334  );
3335  bool Write3dmDimStyleComponent(
3336  const class ON_ModelComponent* model_component
3337  );
3338  bool Write3dmDimStyle( const class ON_DimStyle& );
3339 
3340  bool EndWrite3dmDimStyleTable();
3341 
3342 private:
3343  bool Internal_Write3dmDimStyle( const class ON_DimStyle&, bool bUpdateManifest );
3344 public:
3345 
3346  bool BeginRead3dmDimStyleTable();
3347 
3348  // Description:
3349  // Reads annotation dimension styles from dimension style table.
3350  // If the dimension style definition is read,
3351  // a dimension style is created by calling new ON_DimStyle(),
3352  // initialized with values stored in the archive, and
3353  // returned.
3354  //
3355  // Parameters:
3356  // ppDimStyle - If the dimstyle definition is
3357  // read, a dimstyle is created by calling new ON_DimStyle(),
3358  // initialized with values stored in the archive, and
3359  // a pointer to the new dimstyle is returned in *ppDimStyle.
3360  //
3361  // Returns:
3362  //
3363  // @untitled table
3364  // 0 at the end of the dimension style table
3365  // 1 dimension style definition was successfully read
3366  // -1 archive is corrupt at this point
3367  //
3368  // Example:
3369  // Calls to Read3dmDimStyle need to be bracketed by calls
3370  // to BeginRead3dmDimStyleTable() / EndRead3dmDimStyleTable().
3371  //
3372  // archive.BeginRead3dmDimStyleTable();
3373  // int rc = 1;
3374  // ON_DimStyle* pDimStyle;
3375  // while(rc==1)
3376  // { //
3377  // pDimStyle = 0;
3378  // archive.Read3dmDimStyle(&pDimStyle);
3379  // if ( pDimStyle )
3380  // do something with pDimStyle
3381  // } //
3382  // archive.EndRead3dmDimStyleTable();
3383  //
3384  int Read3dmDimStyle(
3385  class ON_DimStyle** ppDimStyle
3386  );
3387 
3388 private:
3389  int Internal_Read3dmDimStyle(
3390  class ON_DimStyle** ppDimStyle
3391  );
3392 
3393  void Internal_ConvertTextStylesToDimStyles();
3394 
3395  double Internal_ArchiveModelSpaceTextScale() const;
3396 
3397  const ON_DimStyle* Internal_ArchiveCurrentDimStyle();
3398 
3399 public:
3400  bool EndRead3dmDimStyleTable();
3401 
3402  /*
3403  Internal_Read3dmDimStyleOverrides() is a public function on ON_BinaryArchive because
3404  it must be called from ON_Annotation::Internal_ReadAnnotation().
3405  There is no other reason to call this function.
3406  */
3407 public:
3408  bool Internal_Read3dmDimStyleOverrides(
3409  class ON_Annotation& annotation,
3410  bool bFromDimStyleTable
3411  );
3412 
3413  /*
3414  Internal_Write3dmDimStyleOverrides() is a public function on ON_BinaryArchive because
3415  it must be called from ON_Annotation::Internal_WriteAnnotation().
3416  There is no other reason to call this function.
3417  */
3418 public:
3419  bool Internal_Write3dmDimStyleOverrides(
3420  const class ON_Annotation& annotation,
3421  const class ON_DimStyle* dim_style_overrides
3422  );
3423 
3424 public:
3425  ///////////////////////////////////////////////////////////////////
3426  // Step 12: REQUIRED - Write/Read render light table (it can be empty)
3427  //
3428  bool BeginWrite3dmLightTable();
3429  bool Write3dmModelLightComponent(
3430  const class ON_ModelComponentReference& model_component_reference
3431  );
3432  bool Write3dmModelLightComponent(
3433  const class ON_ModelGeometryComponent* model_light
3434  );
3435  bool Write3dmLight(
3436  const class ON_Light&,
3437  const class ON_3dmObjectAttributes* // can be nullptr
3438  );
3439  bool EndWrite3dmLightTable();
3440 
3441  bool BeginRead3dmLightTable();
3442 
3443  // Call either Read3dmModelLight or Read3dmLight
3444  /*
3445  Parameters:
3446  model_light - [out]
3447  ON_ModelGeometryComponent returned here.
3448  nullptr returned at end of the table.
3449  object_filter - [in]
3450  optional filter made by setting ON::object_type bits
3451  Returns:
3452  0 at end of object table
3453  1 if object is read
3454  2 if object is skipped because it does not match filter
3455  -1 if file is corrupt
3456  */
3457  int Read3dmModelLight(
3458  class ON_ModelGeometryComponent** model_light
3459  );
3460 
3461  int Read3dmLight(
3462  class ON_Light** light,
3463  class ON_3dmObjectAttributes* attributes
3464  );
3465 
3466  bool EndRead3dmLightTable();
3467 
3468 
3469  ///////////////////////////////////////////////////////////////////
3470  // Step 13: REQUIRED - Write/Read hatch pattern table (it can be empty)
3471  //
3472  bool BeginWrite3dmHatchPatternTable();
3473  bool Write3dmHatchPatternComponent(
3474  const class ON_ModelComponentReference& model_component_reference
3475  );
3476  bool Write3dmHatchPatternComponent(
3477  const class ON_ModelComponent* model_component
3478  );
3479  bool Write3dmHatchPattern( const class ON_HatchPattern&);
3480  bool EndWrite3dmHatchPatternTable();
3481 
3482  bool BeginRead3dmHatchPatternTable();
3483  int Read3dmHatchPattern(class ON_HatchPattern**);
3484  bool EndRead3dmHatchPatternTable();
3485 
3486  ///////////////////////////////////////////////////////////////////
3487  // Step 14: REQUIRED - Write/Read instance definition table (it can be empty)
3488  //
3489  bool BeginWrite3dmInstanceDefinitionTable();
3490  bool Write3dmInstanceDefinitionComponent(
3491  const class ON_ModelComponentReference& model_component_reference
3492  );
3493  bool Write3dmInstanceDefinitionComponent(
3494  const class ON_ModelComponent* model_component
3495  );
3496  bool Write3dmInstanceDefinition( const class ON_InstanceDefinition& );
3497  bool EndWrite3dmInstanceDefinitionTable();
3498 
3499  bool BeginRead3dmInstanceDefinitionTable();
3500 
3501  /*
3502  Description:
3503  Reads instance definitions from instance defintion table.
3504 
3505  Parameters:
3506  ppInstanceDefinition - If an instance defintion is
3507  read, an instance defintion is created by calling new
3508  ON_InstanceDefinition(), initialized with values stored
3509  in the archive, and a pointer to the new instance defintion
3510  is returned in *ppInstanceDefinition.
3511 
3512  Returns:
3513 
3514  @untitled table
3515  0 at the end of the instance defintion table
3516  1 instance defintion was successfully read
3517  -1 archive is corrupt at this point
3518 
3519  Example:
3520  Calls to Read3dmInstanceDefinition need to be bracketed by calls
3521  to BeginRead3dmInstanceDefinitionTable() / EndRead3dmInstanceDefinitionTable().
3522 
3523  archive.BeginRead3dmInstanceDefinitionTable();
3524  int rc = 1;
3525  ON_InstanceDefinition* pInstanceDefinition;
3526  while(rc==1)
3527  {
3528  pInstanceDefinition = 0;
3529  archive.Read3dmInstanceDefinition(&pInstanceDefinition);
3530  if ( pInstanceDefinition )
3531  do something with pInstanceDefinition
3532  }
3533  archive.EndRead3dmInstanceDefinitionTable();
3534  */
3535  int Read3dmInstanceDefinition(
3536  class ON_InstanceDefinition** // ppInstanceDefinition
3537  );
3538 
3539  bool EndRead3dmInstanceDefinitionTable();
3540 
3541  ///////////////////////////////////////////////////////////////////
3542  // Step 15: REQUIRED - Write/Read geometry and annotation table (it can be empty)
3543  //
3544  bool BeginWrite3dmObjectTable();
3545  bool Write3dmModelGeometryComponent(
3546  const class ON_ModelComponentReference& model_component_reference
3547  );
3548  bool Write3dmModelGeometryComponent(
3549  const class ON_ModelGeometryComponent* model_geometry
3550  );
3551  bool Write3dmObject(
3552  const ON_Object&,
3553  const ON_3dmObjectAttributes* // optional
3554  );
3555  bool EndWrite3dmObjectTable();
3556 
3557  bool BeginRead3dmObjectTable();
3558 
3559  // Call either Read3dmModelGeometry or Read3dmObject
3560  /*
3561  Parameters:
3562  model_geometry - [out]
3563  ON_ModelGeometryComponent returned here.
3564  nullptr returned at end of the table.
3565  object_filter - [in]
3566  optional filter made by setting ON::object_type bits
3567  Returns:
3568  0 at end of object table
3569  1 if object is read
3570  2 if object is skipped because it does not match filter
3571  -1 if file is corrupt
3572  */
3573  int Read3dmModelGeometry(
3574  class ON_ModelGeometryComponent** model_geometry,
3575  unsigned int object_filter = 0
3576  );
3577 
3578  /*
3579  Parameters:
3580  bManageGeometry - [in]
3581  true: model_geometry will reference count and delete the ON_Geometry pointer.
3582  false: The caller must delete the ON_Geometry pointer.
3583  bManageAttributes - [in]
3584  true: model_geometry will reference count and delete the ON_3dmObjectAttributes pointer.
3585  false: The caller must delete the ON_3dmObjectAttributes pointer.
3586  model_geometry - [out]
3587  ON_ModelGeometryComponent returned here.
3588  nullptr returned at end of the table.
3589  object_filter - [in]
3590  optional filter made by setting ON::object_type bits
3591  0 = no filter.
3592  Returns:
3593  0 at end of object table
3594  1 if object is read
3595  2 if object is skipped because it does not match filter
3596  -1 if file is corrupt
3597  */
3598  int Read3dmModelGeometryForExperts(
3599  bool bManageGeometry,
3600  bool bManageAttributes,
3601  class ON_ModelGeometryComponent** model_geometry,
3602  unsigned int object_filter
3603  );
3604 
3605  /*
3606  Parameters:
3607  model_object - [out]
3608  nullptr returned at end of the table.
3609  attributes - [out]
3610  If not nullptr, then attributes are returned here
3611  object_filter - [in]
3612  optional filter made by setting ON::object_type bits
3613  Returns:
3614  0 at end of object table
3615  1 if object is read
3616  2 if object is skipped because it does not match filter
3617  -1 if file is corrupt
3618  */
3619  int Read3dmObject(
3620  ON_Object** model_object,
3621  ON_3dmObjectAttributes* attributes,
3622  unsigned int object_filter = 0
3623  );
3624 
3625 private:
3626  /*
3627  Description:
3628  In rare cases one object must be converted into another.
3629  Examples include reading obsolete objects and converting them into their
3630  current counterpart, converting WIP objects into a proxy for a commercial build,
3631  and converting a proxy object into a WIP object for a WIP build.
3632  */
3633  ON_Object* Internal_ConvertObject(
3634  const ON_Object* archive_object,
3635  const ON_3dmObjectAttributes* attributes
3636  ) const;
3637 
3638 public:
3639 
3640  bool EndRead3dmObjectTable();
3641 
3642  ///////////////////////////////////////////////////////////////////
3643  // Step 16: REQUIRED - Write/Read history record table (it can be empty)
3644  //
3645  bool BeginWrite3dmHistoryRecordTable();
3646  bool Write3dmHistoryRecordComponent(
3647  const class ON_ModelComponentReference& model_component_reference
3648  );
3649  bool Write3dmHistoryRecordComponent(
3650  const class ON_ModelComponent* model_component
3651  );
3652  bool Write3dmHistoryRecord(
3653  const class ON_HistoryRecord&
3654  );
3655  bool EndWrite3dmHistoryRecordTable();
3656 
3657  bool BeginRead3dmHistoryRecordTable();
3658 
3659  /*
3660  Returns:
3661  0 at end of object table
3662  1 if object is read
3663  -1 if file is corrupt
3664  */
3665  int Read3dmHistoryRecord(
3666  class ON_HistoryRecord*&
3667  );
3668  bool EndRead3dmHistoryRecordTable();
3669 
3670  ///////////////////////////////////////////////////////////////////
3671  // Step 17: OPTIONAL - Write/Read 0 or more user tables
3672  //
3673 
3674  /*
3675  Description:
3676  Write the user table header information that must precede
3677  the user table information written by a plug-in.
3678  Parameters:
3679  plugin_id - [in]
3680  bSavingGoo - [in]
3681  Set to false if a plug-in will be used to write
3682  the user table. Set to true if a user table written by
3683  a missing plug-in is being resaved. In this case,
3684  goo_3dm_version and goo_opennurbs_version must also be
3685  set. In practice, you should use Write3dmAnonymousUserTableRecord()
3686  to handle writing "goo" and use this function only when
3687  the plug-in in present.
3688  goo_3dm_version - [in]
3689  If bSavingGoo is false, this parameter must be zero and
3690  ON_BinaryArchive::Archive3dmVersion() will be used.
3691  If bSavingGoo is true, this parameter must be the version of
3692  the 3dm archive (1,2,3,4,5,50,...) the plug-in code used to
3693  write the user table.
3694  goo_opennurbs_version - [in]
3695  If bSavingGoo is false, this parameter must be zero and
3696  ON_BinaryArchive::ArchiveOpenNURBSVersion() will be used.
3697  If bSavingGoo is true, this parameter must be the version
3698  of the opennurbs the plug-in code used to write the
3699  user table.
3700  Returns:
3701  True if the the user information can be written.
3702  False if user informtion should not be written.
3703  */
3704  bool BeginWrite3dmUserTable(
3705  ON_UUID plugin_id,
3706  bool bSavingGoo,
3707  int goo_3dm_version,
3708  unsigned int goo_opennurbs_version
3709  );
3710 
3711  bool EndWrite3dmUserTable();
3712 
3713  /*
3714  Description:
3715  If Read3dmAnaonymousUserTable() was used to read ON_3dmGoo because a
3716  plug-in was not present, then use Write3dmAnonymousUserTableRecord()
3717  to put than information back into the archive.
3718  Write3dmAnonymousUserTableRecord() writes the entire record.
3719  Do NOT call BeginWrite3dmUserTable() / EndWrite3dmUserTable() when
3720  using Write3dmAnonymousUserTableRecord().
3721  Parameters:
3722  plugin_id - [in]
3723  goo_version - [in]
3724  The version of the archive (1,2,3,4,5,50,...) that was used when
3725  the plug-in wrote the user table.
3726  goo_opennurbs_version - [in]
3727  The version of opennurbs ( YYYMMDDN ) that was used when the
3728  plug-in wrote the user table.
3729  goo - [in]
3730  Returns:
3731  True if the goo was written or skipped because it could not be robustly
3732  saved. False if a catastrophic IO error occured.
3733  */
3734  bool Write3dmAnonymousUserTableRecord(
3735  ON_UUID plugin_id,
3736  int goo_3dm_version,
3737  unsigned int goo_opennurbs_version,
3738  const class ON_3dmGoo& goo
3739  );
3740 
3741  ON_DEPRECATED_MSG("use BeginWrite3dmUserTable(plugin_id, bSavingGoo, 3dm_version, opennurbs_version)")
3742  bool BeginWrite3dmUserTable( const ON_UUID& );
3743 
3744  ON_DEPRECATED_MSG("use Write3dmAnonymousUserTableRecord(plugin_id, ..., goo)")
3745  bool Write3dmAnonymousUserTable( const class ON_3dmGoo& );
3746 
3747  /*
3748  Parameters:
3749  plugin_id - [out]
3750  id of plug-in that wrote the user table
3751  bLastSavedAsGoo - [out]
3752  True if this table was saved into this archive as goo because
3753  the plug-in was not present at the time of the save.
3754  archive_3dm_version - [out]
3755  Version of the archive the plug-in wrote to. When bLastSavedAsGoo
3756  is true, this number can be different from Archive3dmVersion().
3757  archive_opennurbs_version - [out]
3758  Version of opennurbs the plug-in used to write the archive.
3759  When bLastSavedAsGoo is true, this number can be different
3760  from ArchiveOpenNURBSVersion().
3761  Returns:
3762  False when there are no more user tables or an IO error occurs.
3763  */
3764  bool BeginRead3dmUserTable(
3765  ON_UUID& plugin_id,
3766  bool* bLastSavedAsGoo,
3767  int* archive_3dm_version,
3768  unsigned int* archive_opennurbs_version
3769  );
3770 
3771  /*
3772  Description:
3773  If the plug-in that wrote the user table is not present and you need
3774  to read and resave the user table, then use Read3dmAnonymousUserTable()
3775  to load the information into "goo".
3776  If you do not need to resave the information, then simply call EndRead3dmUserTable()
3777  to skip over this table.
3778  */
3779  bool Read3dmAnonymousUserTable(
3780  int archive_3dm_version,
3781  unsigned int archive_opennurbs_version,
3782  ON_3dmGoo& goo
3783  );
3784 
3785  bool EndRead3dmUserTable();
3786 
3787  ///////////////////////////////////////////////////////////////////
3788  // Step 18: REQUIRED when writing / OPTIONAL when reading
3789  // Write end of file marker. This information is primarily
3790  // used when debugging files to make sure the end of the file
3791  // hasn't been cut off.
3792  //
3793 
3794  // Description:
3795  // Writes a TCODE_ENDOFFILE chunk that contains the number
3796  // of bytes in the archive.
3797  //
3798  // Returns:
3799  // true if successful, false if unable to write to archive.
3800  bool Write3dmEndMark();
3801 
3802  // Description:
3803  // Checks for a TCODE_ENDOFFILE chunk at the current position.
3804  // If it finds one, it reads it and returns the number
3805  // of bytes in the archive. Comparing this number with
3806  // the current file position can help detect files that
3807  // have been damaged by loosing sections.
3808  //
3809  // Parameters:
3810  // sizeof_archive - [out] number of bytes written to archive
3811  //
3812  // Returns:
3813  // true if successful, false if unable to find or read
3814  // a TCODE_ENDOFFILE chunk.
3815  bool Read3dmEndMark(
3816  size_t* // sizeof_archive
3817  );
3818 
3819  ///////////////////////////////////////////////////////////////////
3820  ///////////////////////////////////////////////////////////////////
3821  // Low level tools to Write/Read chunks. See opennurbs_3dm.h for details
3822  // about the structure of chunks. Every chunk must begin with a
3823  // call to BeginWrite/ReadChunk().
3824  // If BeginWriteChunk()/BeginReadChunk() returns true, then
3825  // you must call EndWrite/ReadChunk() or cease using the archive.
3826 
3827  // Description:
3828  // Writes a chunk header containing 4 byte typecode and value.
3829  //
3830  // Parameters:
3831  // typecode - [in] a TCODE_* number from opennurbs_3dm.h
3832  // value - [in] if (typecode&TCODE_SHORT) is nonzero, then
3833  // this is the value to be saved. Othewise, pass
3834  // a zero and the EndWrite3dmChunk() call will
3835  // store the length of the chunk.
3836  //
3837  // Returns:
3838  // true if write was successful.
3839  bool BeginWrite3dmChunk(
3840  unsigned int, // typecode
3841  int // value
3842  );
3843 
3844  bool BeginWrite3dmBigChunk(
3845  ON__UINT32 typecode,
3846  ON__INT64 value
3847  );
3848 
3849  /*
3850  Description:
3851  Begins writing a chunk.
3852  Parameters:
3853  tcode - [in] chunk's typecode from opennurbs_3dm.h. This cannot be a short tcode.
3854  major_version - [in] ( >= 1)
3855  minor_version - [in] ( >= 0 )
3856  Returns:
3857  True if input was valid and chunk was started. In this case
3858  You must call EndWrite3dmChunk(), even if something goes wrong
3859  while you attempt to write the contents of the chunk.
3860  False if input was not valid or the write failed.
3861  */
3862  bool BeginWrite3dmChunk(
3863  unsigned int tcode,
3864  int major_version,
3865  int minor_version
3866  );
3867 
3868  /*
3869  Description:
3870  If version >= 0, calls BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,version).
3871  */
3872  bool BeginWrite3dmAnonymousChunk(
3873  int version
3874  );
3875 
3876 
3877  // updates length in chunk header
3878  bool EndWrite3dmChunk();
3879 
3880  bool Write3dmGoo( const ON_3dmGoo& ); // call to write "goo"
3881 
3882  //ON_DEPRECATED_MSG("use BeginRead3dmBigChunk")
3883  //bool BeginRead3dmChunk(
3884  // unsigned int*, // typecode from opennurbs_3dm.h
3885  // int* // value
3886  // );
3887 
3888  // When the end of the 3dm file is reached, BeginReadChunk() will
3889  // return true with a typecode of TCODE_ENDOFFILE.
3890  bool BeginRead3dmBigChunk(
3891  unsigned int*, // typecode from opennurbs_3dm.h
3892  ON__INT64* // value
3893  );
3894  /*
3895  Description:
3896  Begins reading a chunk that must be in the archive at this location.
3897  Parameters:
3898  expected_tcode - [in] chunk's typecode from opennurbs_3dm.h
3899  major_version - [out]
3900  minor_version - [out]
3901  Returns:
3902  True if beginning of the chunk was read. In this case
3903  You must call EndRead3dmChunk(), even if something goes wrong
3904  while you attempt to read the interior of the chunk.
3905  False if the chunk did not exist at the current location in the file.
3906  */
3907  bool BeginRead3dmChunk(
3908  unsigned int expected_tcode,
3909  int* major_version,
3910  int* minor_version
3911  );
3912 
3913  /*
3914  Description:
3915  Calls BeginWRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version),
3916  checks that 1 == major_version, minor_version >= 0 and returns the value
3917  of minor_version as version.
3918  Parameters:
3919  version - [out]
3920  */
3921  bool BeginRead3dmAnonymousChunk(
3922  int* version
3923  );
3924 
3925  /*
3926  Description:
3927  Calling this will skip rest of stuff in chunk if it was only partially read.
3928  Parameters:
3929  bSupressPartiallyReadChunkWarning - [in]
3930  Generally, a call to ON_WARNING is made when a chunk is partially
3931  read. If bSupressPartiallyReadChunkWarning is true, then
3932  no warning is issued for partially read chunks.
3933  */
3934  bool EndRead3dmChunk();
3935  bool EndRead3dmChunk(bool bSupressPartiallyReadChunkWarning);
3936 
3937 
3938  ///////////////////////////////////////////////////////////////////
3939  //
3940  // Tools for dictionary IO (used in .NET)
3941  //
3942 
3943  /*
3944  Description:
3945  Begins writing a dictionary.
3946  Parameters:
3947  dictionary_id - [in]
3948  version - [in]
3949  It is suggested that you use ON_VersionNumberConstruct() to create
3950  a version number.
3951  dictionary_name - [in]
3952  You may pass nullptr.
3953  Remarks:
3954  Begins a new chunk with tcode TCODE_DICTIONARY and then writes
3955  a TCODE_DICTIONARY_ID chunk containing the id, version and name.
3956  After calling this function, you may either write entries by
3957  calling
3958  BeginWriteDictionaryEntry();
3959  write entry definition...
3960  EndWriteDictionaryEntry();
3961  or you may finish writing the dictionay by calling
3962  EndWriteDictionary();
3963  */
3964  bool BeginWriteDictionary(
3965  ON_UUID dictionary_id,
3966  unsigned int version,
3967  const wchar_t* dictionary_name
3968  );
3969  /*
3970  Description:
3971  Begins writing a dictionary entry.
3972  Parameters:
3973  de_type - [in]
3974  entry_name - [in]
3975  Returns:
3976  true
3977  Entry header was written and you must call EndWriteDictionary()
3978  after writing the entry data.
3979  false
3980  Failed to write entry header. Do not call EndWriteDictionary().
3981  Remarks:
3982  Begins a new chunk with tcode TCODE_DICTIONARY_ENTRY,
3983  then writes the int, and then writes the string.
3984  */
3985  bool EndWriteDictionary();
3986 
3987  /*
3988  Description:
3989  Begins writing a dictionary entry.
3990  Parameters:
3991  de_type - [in]
3992  entry_name - [in]
3993  Returns:
3994  true
3995  Entry header was written and you must call EndWriteDictionary()
3996  after writing the entry data.
3997  false
3998  Failed to write entry header. Do not call EndWriteDictionary().
3999  Remarks:
4000  Begins a new chunk with tcode TCODE_DICTIONARY_ENTRY,
4001  then writes the int, and then writes the string.
4002  */
4003  bool BeginWriteDictionaryEntry(
4004  int de_type,
4005  const wchar_t* entry_name
4006  );
4007  bool EndWriteDictionaryEntry();
4008 
4009  bool BeginReadDictionary(
4010  ON_UUID* dictionary_id,
4011  unsigned int* version,
4012  ON_wString& dictionary_name
4013  );
4014  bool EndReadDictionary();
4015 
4016  /*
4017  Description:
4018  Begin reading a dictionary entry.
4019  Parameters:
4020  de_type - [out]
4021  entry_name - [out]
4022  Returns:
4023  0: serious IO error
4024  1: success
4025  read information and then call EndReadDictionaryEntry()
4026  2: at end of dictionary
4027  */
4028  int BeginReadDictionaryEntry(
4029  int* de_type,
4030  ON_wString& entry_name
4031  );
4032  bool EndReadDictionaryEntry();
4033 
4034  bool Read3dmGoo( ON_3dmGoo& ); // Call to read "goo"
4035 
4036  ON_DEPRECATED_MSG("use PeekAt3dmBigChunkType")
4037  bool PeekAt3dmChunkType( // does not change file position
4038  unsigned int*, // typecode from opennurbs_3dm.h
4039  int* // value
4040  );
4041 
4042  bool PeekAt3dmBigChunkType( // does not change file position
4043  ON__UINT32* typecode,
4044  ON__INT64* big_value
4045  );
4046 
4047  bool Seek3dmChunkFromStart(
4048  // beginning at the start of the active chunk, search portion of
4049  // archive included in active chunk for the start of a subchunk
4050  // with the specified type.
4051  // if true is returned, then the position is set so the next call to
4052  // BeginRead3dmChunk() will read a chunk with the specified typecode
4053  unsigned int // typecode from opennurbs_3dm.h
4054  );
4055  bool Seek3dmChunkFromCurrentPosition(
4056  // beginning at the current position, search portion of archive
4057  // included in active chunk for the start of a subchunk with the
4058  // specified type.
4059  // if true is returned, then the position is set so the next call to
4060  // BeginRead3dmChunk() will read a chunk with the specified typecode
4061  unsigned int // typecode from opennurbs_3dm.h
4062  );
4063 
4064  // A chunk version is a single byte that encodes a major.minor
4065  // version number. Useful when creating I/O code for 3dm chunks
4066  // that may change in the future. Increment the minor version
4067  // number if new information is added to the end of the chunk.
4068  // Increment the major version if the format of the chunk changes
4069  // in some other way.
4070  bool Write3dmChunkVersion(
4071  int, // major // 0 to 15
4072  int // minor // 0 to 16
4073  );
4074  bool Read3dmChunkVersion(
4075  int*, // major // 0 to 15
4076  int* // minor // 0 to 16
4077  );
4078 
4079  /*
4080  Description:
4081  Low level tool to writes user data attached to the
4082  object. This function should never be called
4083  directly.
4084  Parameters:
4085  object - [in]
4086  Returns:
4087  True if successful.
4088  */
4089  bool WriteObjectUserData( const ON_Object& object );
4090 
4091  /*
4092  Description:
4093  Low level tool to read user data and attach it to
4094  the object. This function should never be called
4095  directly.
4096  Parameters:
4097  object - [in/out]
4098  Returns:
4099  True if successful.
4100  */
4101  bool ReadObjectUserData( ON_Object& object );
4102 
4103  /*
4104  Description:
4105  If a 3dm archive is being read or written, then this is the
4106  version of the 3dm archive format (1, 2, 3, 4, 5, 50, 60, ...).
4107  Returns:
4108  @untitle table
4109  0 a 3dm archive is not being read/written
4110  1 a version 1 3dm archive is being read/written
4111  2 a version 2 3dm archive is being read/written
4112  3 a version 3 3dm archive is being read/written
4113  4 a version 4 3dm archive is being read/written
4114  5 an old version 5 3dm archive is being read
4115  50 a version 5 3dm archive is being read/written
4116  60 a version 6 3dm archive is being read/written
4117  ...
4118  See Also:
4119  ON_BinaryArchive::ArchiveOpenNURBSVersion
4120  */
4121  int Archive3dmVersion() const;
4122 
4123  /*
4124  Description:
4125  If a 3dm archive is being read, then this is the version
4126  of openNURBS that was used to write the archive. This value
4127  is only available after ON_BinaryArchive::Read3dmProperties
4128  is called.
4129  See Also:
4130  ON_BinaryArchive::Archive3dmVersion
4131  ON_BinaryArchive::Read3dmProperties
4132  Returns:
4133  Version of openNURBS used to write the archive. The openNURBS
4134  version is the value returned by ON::Version.
4135  See Also:
4136  ON::Version
4137  ON_BinaryArchive::Read3dmProperties
4138  ON_BinaryArchive::Archive3dmVersion
4139  Remarks:
4140  This value is rarely needed. You probably want to
4141  use ON_BinaryArchive::Archive3dmVersion.
4142  */
4143  unsigned int ArchiveOpenNURBSVersion() const;
4144 
4145  /*
4146  Returns:
4147  The runtime environment where the archive was created.
4148  Remarks:
4149  When reading an archive, compare the values of
4150  ON_BinaryArchive::ArchiveRuntimeEnvironment()
4151  and
4152  ON::CurrentRuntimeEnvironment()
4153  to determine if adjustments need to be made to resources provided
4154  by runtime enviroments, like fonts.
4155  */
4156  ON::RuntimeEnvironment ArchiveRuntimeEnvironment() const;
4157 
4158  const ON_DimStyle& ArchiveCurrentDimStyle() const;
4159  const int ArchiveCurrentDimStyleIndex() const;
4160  const ON_UUID ArchiveCurrentDimStyleId() const;
4161 
4162  /*
4163  Description:
4164  If a 3dm archive is being written to a version 2,3,4 or 50 format,
4165  then new format opennurbs version numbers need to be saved in the
4166  old YYYYMMDDN format. This function returns the value that should
4167  be written in the file.
4168  Parameters:
4169  archive_3dm_version - [in]
4170  Version of the file that is being written (2, 3, 4, 50, 60, ...)
4171  opennurbs_version - [in]
4172  opennurbs version number
4173  Returns:
4174  Value to save in the file.
4175  */
4176  static unsigned int ArchiveOpenNURBSVersionToWrite(
4177  unsigned int archive_3dm_version,
4178  unsigned int opennurbs_version
4179  );
4180 
4181  /*
4182  Description:
4183  When a 3dm archive is saved from an MFC application that
4184  supports Windows linking/embedding, the first 5kb to 1mb
4185  of the file contains information that is put there by MFC.
4186  ArchiveStartOffset() returns the offset into the file where
4187  the 3dm archive actually begins. The call to
4188  ON_BinaryArchive::Read3dmStartSection() calculates this
4189  offset and stores the value in m_3dm_start_section_offset.
4190  Returns:
4191  Offset into the binary "file" where the actual 3dm archive
4192  begins.
4193  Remarks:
4194  Generally, this value can be ignored. This function is
4195  a diagnostice tool that is used to analyzed damaged files.
4196  */
4197  size_t ArchiveStartOffset() const;
4198 
4199  /*
4200  Description:
4201  Expert user function for reading damaged files.
4202  Parameters:
4203  chunk - [out] current chunk.
4204  Returns:
4205  Level of the chunk or 0 if there is no current
4206  chunk.
4207  */
4208  int GetCurrentChunk(ON_3DM_CHUNK& chunk) const;
4209  int GetCurrentChunk(ON_3DM_BIG_CHUNK& big_chunk) const;
4210 
4211  /*
4212  Description:
4213  Expert user function for reading damaged files. The search starts
4214  at the beginning of the file.
4215  Parameters:
4216  tcode_table - [in] typecode of the table
4217  tcode_record - [in] typecode of the record
4218  class_uuid - [in] id of the opennurbs class in the record
4219  min_length_data - [in] minimum size of the opennurbs class data
4220  Returns:
4221  True if the table start is found. In this case the current
4222  position of the archive is at the start of the table and
4223  the standared BeginRead3dm...Table() function can be used.
4224  False if the table start is not found.
4225  */
4226  bool FindTableInDamagedArchive(
4227  unsigned int tcode_table,
4228  unsigned int tcode_record,
4229  ON_UUID class_uuid,
4230  int min_length_data
4231  );
4232 
4233  /*
4234  Description:
4235  Expert user function for studying contents of a file.
4236  The primary use is as an aid to help dig through files
4237  that have been damaged (bad disks, transmission errors, etc.)
4238  If an error is found, a line that begins with the word
4239  "ERROR" is printed.
4240  Parameters:
4241  text_log - [in] place to print informtion
4242  recursion_depth - [in] simply a counter
4243  to aid in debugging.
4244  Returns:
4245  0 if something went wrong, otherwise the typecode
4246  of the chunk that was just studied.
4247  */
4248  unsigned int
4249  Dump3dmChunk(
4250  ON_TextLog& text_log,
4251  int recursion_depth = 0
4252  );
4253 
4254  enum class eStorageDeviceError : unsigned int
4255  {
4256  None = 0,
4257 
4258  // values from 1 through 0xFFFFFFF0 are used for IO device
4259  // specific exceptions that terminate reading or writing.
4260 
4261  WriteFailed = 0xFFFFFFF1, // writing to device failed
4262  SeekFailedDuringWriting = 0xFFFFFFF2, // virtual Seek() failed during writing
4263  ReadFailed = 0xFFFFFFF8, // reading from device failed
4264  SeekFailedDuringReading = 0xFFFFFFF9, // virtual Seek() failed during reading
4265  UnknownDeviceError = 0xFFFFFFFFU
4266  };
4267 
4268  static ON_BinaryArchive::eStorageDeviceError StorageDeviceErrorFromUnsigned(
4269  unsigned int storage_device_error_as_unsigned
4270  );
4271 
4272  /*
4273  Description:
4274  An error terminated reading or writing
4275  Returns:
4276  0: no error terminiated reading or writing
4277  !=0: See the ON_BinaryArchive::DeviceErrorType for values
4278  */
4279  unsigned int StorageDeviceError() const;
4280 
4281 private:
4282  /*
4283  Description:
4284  Works like the C runtrim fread().
4285  Returns:
4286  actual number of bytes read (like fread())
4287  */
4288  size_t Read(size_t, void*);
4289 protected:
4290  virtual size_t Internal_ReadOverride( size_t, void* ) = 0;
4291 
4292 private:
4293  /*
4294  Description:
4295  Works like the C runtrim fwrite().
4296  Returns:
4297  actual number of bytes written (like fwrite())
4298  */
4299  size_t Write( size_t, const void* );
4300 protected:
4301  virtual size_t Internal_WriteOverride( size_t, const void* ) = 0;
4302 
4303 public:
4304  /*
4305  Description:
4306  Force Write() to flush any buffered data to physical archive.
4307  Returns:
4308  True if succesful or if there is nothing to flush. False if
4309  information could not be flushed.
4310  */
4311  virtual bool Flush() = 0;
4312 
4313  /*
4314  Description:
4315  When ON_BinaryArchive::ReadObject() encounters userdata and
4316  the user data class id is not present, LoadUserDataApplication
4317  is called to load the application that created user data.
4318  Returns:
4319  0 - could not load the application
4320  1 - successfully loaded the application
4321  2 - the application was already loaded
4322  */
4323  virtual
4324  int LoadUserDataApplication(
4325  ON_UUID application_id
4326  );
4327 
4328  bool SetArchive3dmVersion(int);
4329 
4330  /*
4331  Description:
4332  A non-zero storage device error terminates reading or writing.
4333  See the ON_BinaryArchive::eStorageDeviceError for values.
4334  Parameter:
4335  storage_device_error - [in]
4336  A non-zero code that identifies an error the terminates
4337  reading or writing.
4338  See ON_BinaryArchive::CriticalErrorCodes for values
4339  Remarks:
4340  Once set, the storage_device_error value cannot be changed.
4341  */
4342  void SetStorageDeviceError(
4343  ON_BinaryArchive::eStorageDeviceError storage_device_error
4344  );
4345  void SetStorageDeviceError(
4346  unsigned int storage_device_error
4347  );
4348 
4349 private:
4350  // 16 bit integer IO
4351  bool WriteInt8( size_t, const ON__INT8* );
4352  bool ReadInt8( size_t, ON__INT8* );
4353 
4354  // 16 bit integer IO
4355  bool WriteInt16( size_t, const ON__INT16* );
4356  bool ReadInt16( size_t, ON__INT16* );
4357 
4358  // 32 bit integer IO
4359  bool WriteInt32( size_t, const ON__INT32* );
4360  bool ReadInt32( size_t, ON__INT32* );
4361 
4362  // 64 bit integer IO
4363  bool WriteInt64( size_t, const ON__INT64* );
4364  bool ReadInt64( size_t, ON__INT64* );
4365 
4366  bool BeginWrite3dmTable(
4367  unsigned int // tcode
4368  );
4369  bool EndWrite3dmTable(
4370  unsigned int // tcode
4371  );
4372  bool BeginRead3dmTable(
4373  unsigned int // tcode
4374  );
4375  bool EndRead3dmTable(
4376  unsigned int // tcode
4377  );
4378 
4379  bool Read3dmV1Layer( ON_Layer*& );
4380  int Read3dmV1Light( // returns 0 at end of light table
4381  // 1 light successfully read
4382  // -1 if file is corrupt
4383  ON_Light**, // light returned here
4384  ON_3dmObjectAttributes* // optional - if NOT nullptr, object attributes are
4385  // returned here
4386  );
4387  int Read3dmV1Material( ON_Material** );
4388  int Read3dmV1Object( // returns 0 at end of object table
4389  // 1 if object is read
4390  // 2 if object is skipped because it does not match filter
4391  // -1 if file is corrupt
4392  ON_Object**, // object returned here (nullptr if skipped)
4393  ON_3dmObjectAttributes*, // optional - if NOT nullptr, object attributes are
4394  // returned here
4395  unsigned int = 0 // optional filter made by setting ON::object_type bits
4396  ); // returns nullptr at end of object table
4397 
4398  bool Read3dmV1AttributesOrMaterial(
4399  ON_3dmObjectAttributes*, // attributes,
4400  ON_Material*, // material,
4401  bool&, // bHaveMat
4402  unsigned int, // end_mark_tcode
4403  class ON__3dmV1_XDATA* = 0 // v1 "xdata"
4404  );
4405  bool Read3dmV1String( ON_String& );
4406  int Read3dmV1LayerIndex( const char* ) const;
4407 
4408 public:
4409  // helpers for reading V1 objects
4410  bool ReadV1_TCODE_RH_POINT(ON_Object**,ON_3dmObjectAttributes*);
4411  bool ReadV1_TCODE_MESH_OBJECT(ON_Object**,ON_3dmObjectAttributes*);
4412  bool ReadV1_TCODE_LEGACY_CRV(ON_Object**,ON_3dmObjectAttributes*);
4413  bool ReadV1_TCODE_LEGACY_FAC(ON_Object**,ON_3dmObjectAttributes*);
4414  bool ReadV1_TCODE_LEGACY_SHL(ON_Object**,ON_3dmObjectAttributes*);
4415  bool ReadV1_TCODE_RHINOIO_OBJECT_NURBS_CURVE(ON_Object**,ON_3dmObjectAttributes*);
4416  bool ReadV1_TCODE_RHINOIO_OBJECT_NURBS_SURFACE(ON_Object**,ON_3dmObjectAttributes*);
4417  bool ReadV1_TCODE_RHINOIO_OBJECT_BREP(ON_Object**,ON_3dmObjectAttributes*);
4418  bool ReadV1_TCODE_ANNOTATION(unsigned int,ON_Object**,ON_3dmObjectAttributes*);
4419 
4420 private:
4421  void UpdateCRC( size_t, const void* );
4422  int ReadObjectHelper(ON_Object**);
4423 
4424  int m_3dm_version = 0; // 1,2,3,4,5 (obsolete 32-bit chunk sizes)
4425  // 50,60,... (64-bit chunk sizes)
4426 
4427  int m_3dm_v1_layer_index = 0;
4428  int m_3dm_v1_material_index = 0;
4429 
4430 
4431 
4432 
4433 protected:
4434  unsigned int ErrorMessageMask() const;
4435  /*
4436  Paramters:
4437  sizeof_request - [in]
4438  value of count parameter passed to virtual Read() function.
4439  sizeof_read - [in]
4440  number of bytes actually read by the virtual Read() function.
4441  Returns:
4442  True if a call to Read() is permitted to ask for more bytes
4443  than are left in the file. This value varies as the file
4444  is read and must be checked at each failure.
4445  */
4446  bool MaskReadError( ON__UINT64 sizeof_request, ON__UINT64 sizeof_read ) const;
4447 
4448 private:
4449 
4450 
4451  // When a 3DM archive is read, m_3dm_opennurbs_version records the version of
4452  // OpenNURBS used to create the archive. Otherwise, m_3dm_opennurbs_version
4453  // is zero.
4454  //
4455  // Read3dmProperties() sets this to the version of OpenNURBS that was
4456  // used to write file file. If the file was created using a version
4457  // of OpenNURBS before 200012210, this number will be zero.
4458  //
4459  // Write3dmProperties() stores the value returned by ON::Version() in
4460  // the archive's properties table.
4461  friend void ON_SetBinaryArchiveOpenNURBSVersion(ON_BinaryArchive&,unsigned int);
4462  unsigned int m_3dm_opennurbs_version = 0;
4463 
4464  ON::RuntimeEnvironment m_archive_runtime_environment = ON::RuntimeEnvironment::Unset;
4465 
4466  // When a 3dm archive is saved from an MFC application that supports
4467  // Windows linking/embedding, the first 5kb to 1mb of the file contains
4468  // information that is put there by MFC. m_3dm_start_section_offset
4469  // records the offset into the file where the 3dm archive actually begins.
4470  size_t m_3dm_start_section_offset = 0;
4471 
4472  /*Read3dmTableRecordBegin
4473  m_3dm_previous_table = 3dm archive table that was most recently read/written.
4474  m_3dm_active_table = 3dm archive table currently being read/written
4475  */
4476  ON_3dmArchiveTableType m_3dm_previous_table = ON_3dmArchiveTableType::Unset;
4477  ON_3dmArchiveTableType m_3dm_active_table = ON_3dmArchiveTableType::Unset;
4478  // If reading/writing a table fails, m_3dm_failed_table identifies the first failure.
4479  ON_3dmArchiveTableType m_3dm_first_failed_table = ON_3dmArchiveTableType::Unset;
4480 
4481  int m_user_data_depth = 0; // > 0 when user data is being read or written
4482 
4483  // 3dm archive status information
4484  class ON_3dmTableStatusLink* m_3dm_table_status_list = nullptr;
4485 
4486 private:
4487  bool Internal_Write3dmUpdateManifest(
4488  const ON_ModelComponent& model_component
4489  );
4490  bool Internal_Write3dmLightOrGeometryUpdateManifest(
4491  ON_ModelComponent::Type component_type,
4492  ON_UUID component_id,
4493  int component_index,
4494  const ON_wString & component_name
4495  );
4496  bool Internal_Read3dmUpdateManifest(
4497  ON_ModelComponent& model_component
4498  );
4499  bool Internal_Read3dmLightOrGeometryUpdateManifest(
4500  ON_ModelComponent::Type component_type,
4501  ON_UUID component_id,
4502  int component_index,
4503  const ON_wString & component_name
4504  );
4505 
4506 private:
4507  bool Internal_IncrementCurrentPosition(
4508  ON__UINT64 delta
4509  );
4510  bool Internal_DecrementCurrentPosition(
4511  ON__UINT64 delta
4512  );
4513  ON__UINT64 m_current_positionX = 0;
4514 
4515  /*
4516  Description:
4517  Increments m_crc_error_count and active table m_crc_error_count.
4518  */
4519  void Internal_ReportCRCError();
4520 
4521  unsigned int m_crc_error_count = 0; // number of chunks that have a bad crc
4522 
4523  /*
4524  Description:
4525  Increments m_critical_error_count and active table m_critical_error_count.
4526  */
4527  void Internal_ReportCriticalError();
4528 
4529  // Number of critical errors. These errors are more serious than a CRC error.
4530  // If a critical error occurs, the information being read or written is
4531  // so corrupted that chunk accounting is failing or the calling code is deeply flawed.
4532  unsigned int m_critical_error_count = 0;
4533 
4534  // ON_BinaryArchive::eStorageDeviceError values are used to set
4535  // m_storage_device_error.
4536  // ON_BinaryArchive::StorageDeviceError() returns the value.
4537  unsigned int m_storage_device_error = 0;
4538 
4539  // The bits in m_error_message_mask are used to mask errors
4540  // when we know we are doing something that may generate an
4541  // error.
4542  //
4543  // bit 0x00000001
4544  // Setting this bit masks an error when attempting to read 4 bytes
4545  // at the end of a file.
4546  // V1 files do not have a table structure and are read using
4547  // multiple passes and there are valid situations where a
4548  // 4 byte read is attempted at the end of a file.
4549  // This situation also occurs when a damaged file is missing a table
4550  // or contains tables in the wrong order and the table must be searched
4551  // for by typecode.
4552  //
4553  // bit 0x00000002
4554  // Some v1 files do not have an end mark. When reading
4555  // these v1 files bit 0x02 is set.
4556  //
4557  // bit 0x00000004
4558  // Requested read may go beyond end of file.
4559  // One situation where this happens is when a table is not at the
4560  // expected location in a file,
4561  unsigned int m_error_message_mask = 0;
4562 
4563 
4564 
4565  ON__UINT64 m_3dm_end_mark_length = 0;
4566 
4567  bool Begin3dmTable(
4568  ON::archive_mode expected_mode,
4569  ON_3dmArchiveTableType table
4570  );
4571  bool End3dmTable(
4572  ON_3dmArchiveTableType table,
4573  bool bSuccess
4574  );
4575  void Internal_Increment3dmTableItemCount();
4576  bool Read3dmTableRecord(
4577  ON_3dmArchiveTableType table,
4578  void** ptr
4579  );
4580  bool Internal_Begin3dmTableRecord(
4581  ON_3dmArchiveTableType table
4582  );
4583 
4584 public:
4585  /*
4586  Returns:
4587  Archive read/write mode
4588  */
4589  ON::archive_mode Mode() const;
4590 
4591  /*
4592  Returns:
4593  True if Mode() is an archive reading mode.
4594  */
4595  bool ReadMode() const;
4596 
4597  /*
4598  Returns:
4599  True if Mode() is an archive writing mode.
4600  */
4601  bool WriteMode() const;
4602 
4603  /*
4604  Returns:
4605  True if Mode() is not set to a valid read or write mode.
4606  */
4607  bool UnsetMode() const;
4608 
4609  /*
4610  Returns:
4611  If a 3dm archive is being read or written, the value of the archive
4612  section (table) being read is returned.
4613  ON_3dmArchiveTableType::Unset is returned if a table is
4614  not actively being read or written.
4615  Remarks:
4616  Use ON_BinaryArchive::Mode() to determine if a binary archive is being
4617  read or written.
4618  Use ON_BinaryArchive::Previous3dmTable() to determine the most recent
4619  table that was successfully read and finished.
4620  */
4621  ON_3dmArchiveTableType Active3dmTable() const;
4622 
4623  static ON_ModelComponent::Type TableComponentType(
4624  ON_3dmArchiveTableType table_type
4625  );
4626 
4627  /*
4628  Returns:
4629  If a 3dm archive is being read or written, the value of the most
4630  recently read or written archive section (table) is returned.
4631  Remarks:
4632  Use ON_BinaryArchive::Mode() to determine if a binary archive is being
4633  read or written.
4634  */
4635  ON_3dmArchiveTableType Previous3dmTable() const;
4636 
4637  /*
4638  Returns:
4639  If a 3dm archive is being read or written and a failure occurs,
4640  the first archive section (table) that failed to read or write
4641  is returned.
4642  */
4643  ON_3dmArchiveTableType FirstFailed3dmTable() const;
4644 
4645  /*
4646  Returns:
4647  Number of chunks read with a bad CRC
4648  */
4649  unsigned int BadCRCCount() const;
4650 
4651  /*
4652  Returns:
4653  Number of critical errors
4654  */
4655  unsigned int CriticalErrorCount() const;
4656 
4657  const ON_3dmArchiveTableStatus Archive3dmTableStatus(
4658  ON_3dmArchiveTableType table_type
4659  );
4660 
4661 private:
4662 
4663  ON_3dmArchiveTableType TableTypeFromTypecode( unsigned int ); // table type from tcode
4664 
4666 
4667  // stack of chunks
4668  bool PushBigChunk( ON__UINT32 typecode, ON__INT64 value );
4669 
4670  bool WriteChunkTypecode( ON__UINT32 );
4671  bool ReadChunkTypecode( ON__UINT32* );
4672  bool WriteChunkValue( ON__UINT32 typecode, ON__INT64 );
4673  bool WriteChunkLength( ON__UINT64 );
4674  bool ReadChunkValue( ON__UINT32 typecode, ON__INT64* value64 );
4675  bool FindMisplacedTable(
4676  ON__UINT64 filelength,
4677  const ON__UINT32 table_tocde,
4678  const ON__UINT32 table_record_record,
4679  const ON_UUID class_uuid,
4680  const ON__UINT64 min_length_data
4681  );
4682 
4683  bool ReadObjectUserDataAnonymousChunk(
4684  const ON__UINT64 length_TCODE_ANONYMOUS_CHUNK,
4685  const int archive_3dm_version,
4686  const unsigned int archive_opennurbs_version,
4687  class ON_UserData* ud );
4688 
4689 public:
4690  size_t SizeofChunkLength() const;
4691 
4692 private:
4693  bool WriteEOFSizeOfFile( ON__UINT64 );
4694  bool ReadEOFSizeOfFile( ON__UINT64* );
4695 
4696  bool m_bDoChunkCRC = false; // true if active chunk crc status should be checked
4697  // and updated.
4698  bool m_bChunkBoundaryCheck = false;
4699 
4700 public:
4701  /*
4702  Returns:
4703  true:
4704  All read, write, and seek operations check to make sure they stay within
4705  the current chunk boundary.
4706  */
4707  bool ChunkBoundaryCheck() const;
4708 
4709  /*
4710  Parameters:
4711  bChunkBoundaryCheck - [in]
4712  true:
4713  All read, write, and seek operations check to make sure they stay within
4714  the current chunk boundary.
4715  */
4716  void SetChunkBoundaryCheck(
4717  bool bChunkBoundaryCheck
4718  );
4719 
4720 
4721 private:
4722  class ON_CompressorImplementation* m_compressor = nullptr;
4723  class ON_CompressorImplementation& Compressor();
4724 
4725  // returns number of bytes written
4726  size_t WriteDeflate(
4727  size_t, // sizeof uncompressed input data
4728  const void* // uncompressed input data
4729  );
4730  bool ReadInflate(
4731  size_t, // sizeof uncompressed input data
4732  void* // buffer to hold uncompressed data
4733  );
4734  bool CompressionInit();
4735  void CompressionEnd();
4736 
4737 private:
4738  // endian-ness of the cpu reading this file.
4739  // 3dm files are alwasy saved with little endian byte order.
4740  const ON::endian m_endian = ON::Endian();
4741 
4742  const ON::archive_mode m_mode = ON::archive_mode::unset_archive_mode;
4743 
4744  // user data and user table reading and writing filter
4745  // If m_user_data_filter is empty, then all user data and user tables are read/written.
4746  // If m_user_data_filter is not empty, then the first element has both ids=nil, precedence=0,
4747  // and m_bSerialize = default setting. If there are any elements after the first element,
4748  // the must have m_application_id != nil and the value of m_bSerialize overrides the
4749  // default setting. If there are multiple elements with the same application and item id,
4750  // the most recently added element is used.
4751  ON_SimpleArray< ON_UserDataItemFilter > m_user_data_filter;
4752 
4753  /*
4754  Description:
4755  Sorts m_user_data_filter so items are ordered by
4756  application id (nil is first) and precedence (low to high)
4757  */
4758  void SortUserDataFilter();
4759 
4760 private:
4761  // 3dm write options
4762 
4763  // bits corresponed to ON::object_type flags.
4764  // If the bit is set, then the mesh will be saved in the 3dm file.
4765  // (RhinoCommon: if default is changed, sync with File3dmWriteOptions.RenderMeshesFlags)
4766  ON__UINT32 m_save_3dm_render_mesh_flags = 0xFFFFFFFFU;
4767  ON__UINT32 m_save_3dm_analysis_mesh_flags = 0xFFFFFFFFU;
4768 
4769  bool m_bSave3dmPreviewImage = true;
4770 
4771  bool m_bUseBufferCompression = true;
4772 
4773  bool m_bReservedA = false;
4774  bool m_bReservedB = false;
4775  bool m_bReservedC = false;
4776  bool m_bReservedD = false;
4777  bool m_bReservedE = false;
4778  bool m_bReservedF = false;
4779 
4780 public:
4781  /*
4782  Description:
4783  Specify model serial number attributes to assign to ON_ModelComponent
4784  classes when they are read.
4785  */
4786  void SetModelSerialNumber(
4787  unsigned int model_serial_number,
4788  unsigned int reference_model_serial_number,
4789  unsigned int instance_definition_model_serial_number
4790  );
4791  /*
4792  Description:
4793  Clear() information set by SetModelSerialNumber() do not modify
4794  ON_ModelComponent model serial number information when the classes
4795  are read.
4796  */ void ClearModelSerialNumber();
4797  unsigned int ModelSerialNumber() const;
4798  unsigned int ReferenceModelSerialNumber() const;
4799  unsigned int InstanceDefinitionModelSerialNumber() const;
4800 
4801  /*
4802  Description:
4803  Writes the attributes identified by the component_filter parameter.
4804  Parameters:
4805  model_component - [in]
4806  attributes_filter - [in]
4807  A bitfield that determines which attributes will be written.
4808  Returns:
4809  false: critical failure.
4810  true: writing can continue.
4811  */
4812  bool WriteModelComponentAttributes(
4813  const class ON_ModelComponent& model_component,
4814  unsigned int attributes_filter
4815  );
4816 
4817  /*
4818  Description:
4819  Reads the attributes the Write() function writes.
4820  Parameters:
4821  model_component - [in/out]
4822  component_filter - [out]
4823  A bitfield that reports which attributes were read.
4824  If the corresponding component on model_component is locked,
4825  the read value is discared.
4826  Returns:
4827  false: critical failure.
4828  true: reading can continue.
4829  Remarks:
4830  If locked attributes are read, thire values are ignored.
4831  */
4832  bool ReadModelComponentAttributes(
4833  ON_ModelComponent& model_component,
4834  unsigned int* attributes_filter
4835  );
4836 
4837  /*
4838  Description:
4839  When writing archives, the index of the component in the model is
4840  often different than the index of the component in the archive.
4841  WriteComponentIndex converts the model id or index into
4842  an archive index and writes the archive index value.
4843  Remarks:
4844  During writing, the m_manifest member stores
4845  the model id and index as the "Component" value and
4846  the 3dm archive id index as the "Manifest" value.
4847  */
4848  bool Write3dmReferencedComponentIndex(
4849  ON_ModelComponent::Type component_type,
4850  int model_component_index
4851  );
4852 
4853  /*
4854  Description:
4855  When writing archives, the index of the component in the model is
4856  often different than the index of the component in the archive.
4857  WriteComponentIndex converts the model id or index into
4858  an archive index and writes the archive index value.
4859  Remarks:
4860  During writing, the m_manifest member stores
4861  the model id and index as the "Component" value and
4862  the 3dm archive id index as the "Manifest" value.
4863  */
4864  bool Write3dmReferencedComponentIndex(
4865  ON_ModelComponent::Type component_type,
4866  ON_UUID model_component_id
4867  );
4868 
4869  /*
4870  Description:
4871  When writing archives, the index of the component in the model is
4872  often different than the index of the component in the archive.
4873  WriteComponentIndex converts the model id or index into
4874  an archive index and writes the archive index value.
4875  Remarks:
4876  During writing, the m_manifest member stores
4877  the model id and index as the "Component" value and
4878  the 3dm archive id index as the "Manifest" value.
4879  */
4880  bool Write3dmReferencedComponentIndex(
4881  const ON_ModelComponent& model_component
4882  );
4883 
4884  /*
4885  Description:
4886  When reading 3dm archives, model component indexes in the archive and
4887  in the destination model are typically different.
4888  This function basically reads and reverses the steps that WriteArchiveComponentIndex()
4889  uses to adjust and write a model component index.
4890  Parameters:
4891  component_type - [in]
4892  Type of the referenced component.
4893  component_index - [out]
4894  component reference index
4895  Returns:
4896  false - catestrophic read failure.
4897  */
4898  bool Read3dmReferencedComponentIndex(
4899  ON_ModelComponent::Type component_type,
4900  int* component_index
4901  );
4902 
4903  bool Read3dmReferencedComponentIndexArray(
4904  ON_ModelComponent::Type component_type,
4905  ON_SimpleArray<int>& component_index_array
4906  );
4907 
4908  /*
4909  Returns:
4910  True: (default state)
4911  Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will automatically
4912  adjust compoents index references so they are valid.
4913  False: (uncommon)
4914  Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will not
4915  adjust compoents index references so they are valid.
4916  */
4917  bool ReferencedComponentIndexMapping() const;
4918 
4919  /*
4920  Description:
4921  Set the archive's ReferencedComponentIndexMapping() state.
4922  Parameters:
4923  bEnableReferenceComponentIndexMapping - [in]
4924  True: (default state)
4925  Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will automatically
4926  adjust compoents index references so they are valid.
4927  False: (uncommon)
4928  Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will not
4929  adjust compoents index references so they are valid. This is only used with the
4930  component being read or written is not the model but is a copy of one
4931  in a different model (linked instance definitions being the common situation).
4932  */
4933  void SetReferencedComponentIndexMapping(
4934  bool bEnableReferenceComponentIndexMapping
4935  );
4936 
4937  /*
4938  Description:
4939  WriteComponentId converts the model ID into
4940  an archive ID and writes the archive Id value.
4941  Generally, the ID of the component in the model is
4942  identical to the ID of the component in the archive.
4943  In rare situations this is not the case.
4944  Remarks:
4945  During writing, the m_manifest member stores
4946  the model ID as the "Component" value and
4947  the 3dm archive ID as the "Manifest" value.
4948  */
4949  bool Write3dmReferencedComponentId(
4950  ON_ModelComponent::Type component_type,
4951  ON_UUID model_component_id
4952  );
4953 
4954  bool Write3dmReferencedComponentId(
4955  const ON_ModelComponent& model_component
4956  );
4957 
4958  /*
4959  Description:
4960  When reading 3dm archives, the model component ID in the archive
4961  and in the destination model are often identical, but sometimes
4962  different. For example, the when the same template is used
4963  to create multiple models and files and the models from those files
4964  are merged into a single file, there will be ID collisions.
4965  For components that are identified by name, like layers and dimension styles,
4966  this is not a problem. For components like instance definitions that have
4967  a more complicated set of merging rules, it is critical that
4968  references to instance definition ids be updated from values in the arcive
4969  to values in the model.
4970  uses to adjust and write a model component Id.
4971  Parameters:
4972  component_type - [in]
4973  Type of the referenced component.
4974  component_id - [out]
4975  component reference ID
4976  Returns:
4977  false - catestrophic read failure.
4978  */
4979  bool Read3dmReferencedComponentId(
4980  ON_ModelComponent::Type component_type,
4981  ON_UUID* component_id
4982  );
4983 
4984  /*
4985  Returns:
4986  True: (default state)
4987  Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will automatically
4988  adjust compoents Id references so they are valid.
4989  False: (uncommon)
4990  Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will not
4991  adjust compoents Id references so they are valid.
4992  */
4993  bool ReferencedComponentIdMapping() const;
4994 
4995  /*
4996  Description:
4997  Set the archive's ReferencedComponentIdMapping() state.
4998  Parameters:
4999  bEnableReferenceComponentIdMapping - [in]
5000  True: (default state)
5001  Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will automatically
5002  adjust compoents Id references so they are valid.
5003  False: (uncommon)
5004  Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will not
5005  adjust compoents Id references so they are valid. This is only used with the
5006  component being read or written is not the model but is a copy of one
5007  in a different model (linked instance definitions being the common situation).
5008  */
5009  void SetReferencedComponentIdMapping(
5010  bool bEnableReferenceComponentIdMapping
5011  );
5012 
5013 
5014 public:
5015  // Reading and writing operations fill in the manifest.
5016  // ON_ComponentManifest query tools can be used to look up
5017  // model and archive index and id information.
5018  //
5019  // The component and manifest id values are always identical
5020  // during reading and writing.
5021  //
5022  // When writing, the component indices are model indices
5023  // and the manifest indices are the archive indices that
5024  // were written in the file.
5025  //
5026  // When reading, the component indices are "index" values read
5027  // from the archive and the manifest indices are the order they
5028  // were read. When files are valid, these indices are the same.
5029  //
5030  // After reading is complete, the application can use
5031  // ON_ComponentManifest::UpdateManifestItem() to convert
5032  // the component index and id values to model index and
5033  // id values.
5034  const class ON_ComponentManifest& Manifest() const;
5035  const class ON_ManifestMap& ManifestMap() const;
5036  bool AddManifestMapItem(
5037  const class ON_ManifestMapItem& map_item
5038  );
5039 
5040  /*
5041  Description:
5042  When an application is reading an archive and changes the
5043  index or id of a model component as it is added to the model,
5044  then it needs to update the manifest map item destination settings.
5045  Parameters:
5046  map_item - [in]
5047  The source type, index and id match what was read from the 3dm archive.
5048  The destination index and id are the values assigned by the
5049  application reading the 3dm archive.
5050  */
5051  bool UpdateManifestMapItemDestination(
5052  const class ON_ManifestMapItem& map_item
5053  );
5054 
5055 private:
5056  // Reading:
5057  // m_manifest is a list of what has been read from the 3dm archive.
5058  // m_manifest_map is a map from the 3dm archive index and id to the
5059  // model index and id. The map is maintained by the application
5060  // reading the file calling AddManifestMapItem() when read items
5061  // are added to the model.
5062  // Writing:
5063  // m_manifest is a list of what has been written to the 3dm archive.
5064  // m_manifest_map maps model index and id to 3dm archive index and id.
5065  // m_manifest_map is automatically maintained by the ON_BinaryArchive
5066  // writing code because the index and id changes happen internally
5067  // in 3dm archive writing functions.
5068  ON_ComponentManifest m_manifest;
5069  ON_ManifestMap m_manifest_map;
5070 
5071  // True: (default state)
5072  // Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will automatically
5073  // adjust component index references so they are valid.
5074  // False: (uncommon)
5075  // Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will not
5076  // adjust component index references so they are valid.
5077  bool m_bReferencedComponentIndexMapping = true;
5078 
5079  // True: (default state)
5080  // Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will automatically
5081  // adjust component id references so they are valid.
5082  // False: (uncommon)
5083  // Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will not
5084  // adjust component id references so they are valid.
5085  bool m_bReferencedComponentIdMapping = true;
5086 
5087 private:
5088  // If the archive is a file system item (file), then
5089  // these strings specify the name of the file
5090  ON_wString m_archive_file_name;
5091  ON_wString m_archive_directory_name;
5092  ON_wString m_archive_full_path; // = archive_directory_name + path separator + archive_file_name
5093 
5094  // If the archive is being read, this is the name
5095  // of the file where it was written.
5096  // If false = ON_wString::EqualPath(m_archive_full_path,m_archive_saved_as_full_path),
5097  // then file has been moved or copied since it was saved.
5098  // When reading a file, this value is set by ON_BinaryArchive::Read3dmProperties()
5099  // When writing a file, this value is set by SetArchiveFullPath().
5100  ON_wString m_archive_saved_as_full_path;
5101 
5102  /*
5103  ON_BinaryArchive::Read3dmProperties() sets m_bArchiveMoved to true if
5104  the 3dm archive being read is not in the same file system location as where
5105  it was written. This piece of information is useful when attempting to find
5106  referenced files that are not where they were when the 3dm archive was saved.
5107  */
5108  bool m_b3dmArchiveMoved = false;
5109 
5110 public:
5111  const ON_wString& ArchiveFileName() const;
5112  const ON_wString& ArchiveDirectoryName() const;
5113  const ON_wString& ArchiveFullPath() const;
5114  const ON_wString& ArchiveSavedAsFullPath() const;
5115 
5116  const wchar_t* ArchiveFileNameAsPointer() const;
5117  const wchar_t* ArchiveDirectoryNameAsPointer() const;
5118  const wchar_t* ArchiveFullPathAsPointer() const;
5119  const wchar_t* ArchiveSavedAsFullPathPointer() const;
5120 
5121  /*
5122  Returns:
5123  true if the 3dm archive being read is not in the same file system
5124  location as where is was saved.
5125  */
5126  bool ArchiveFileMoved() const;
5127 
5128  /*
5129  Parameters:
5130  archive_full_path - [in]
5131  full path to file being read or written
5132  */
5133  void SetArchiveFullPath(
5134  const wchar_t* archive_full_path
5135  );
5136 
5137  /*
5138  Parameters:
5139  archive_directory_name - [in]
5140  full path file being written
5141  archive_file_name - [in]
5142  name of file being written
5143  */
5144  void SetArchiveFullPath(
5145  const wchar_t* archive_directory_name,
5146  const wchar_t* archive_file_name
5147  );
5148 
5149 private:
5150  bool m_SetModelComponentSerialNumbers = false;
5151  unsigned int m_model_serial_number = 0;
5152  unsigned int m_reference_model_serial_number = 0;
5153  unsigned int m_instance_definition_model_serial_number = 0;
5154  unsigned int m_reserved1 = 0;
5155  ON__UINT_PTR m_reserved2 = 0;
5156 
5157 private:
5158  // ids of plug-ins that support saving older (V3) versions
5159  // of user data. This information is filled in from the
5160  // list of plug-ins passed in whenteh settings are saved.
5161  ON_SimpleArray<ON_UUID> m_V3_plugin_id_list;
5162 
5163  struct ON__3dmV1LayerIndex* m_V1_layer_list = nullptr;
5164 
5165 private:
5166  // m_archive_text_style_table and m_archive_dim_style_table are private and not used by inline functions.
5167  // No DLL interface is required.
5168 
5169  mutable ON_3dmAnnotationContext m_annotation_context;
5170 
5171 #pragma ON_PRAGMA_WARNING_PUSH
5172 #pragma ON_PRAGMA_WARNING_DISABLE_MSC( 4251 )
5173  // The m_archive_text_style_table[] array is used when reading archives.
5174  // It contains the text styles read from the archive
5175  ON_SimpleArray< ON_TextStyle* > m_archive_text_style_table;
5176 
5177  // The m_dim_style_index_text_style_index[] is used when reading archives.
5178  // ON_2dex.i = text style archive index.
5179  // ON_2dex.j = dimension style archive index.
5180  ON_SimpleArray< ON_2dex > m_text_style_to_dim_style_archive_index_map;
5181 
5182  // This m_archive_dim_style_table[] array is used when reading
5183  // and writing archives. This information is required when reading
5184  // and writing archives from previous versions.
5185  // - When writing, the dimstyles are copies of the model dimstyles
5186  // and have model ids and indices.
5187  // - When reading, the dimstyles are copies of the archive dimstyles
5188  // and have archive ids and indices.
5189  ON_SimpleArray< ON_DimStyle* > m_archive_dim_style_table;
5190  ON_SimpleArray< ON_DimStyle* > m_DELETE_ME_archive_dim_style_overrides;
5191  bool m_bLegacyOverrideDimStylesInArchive = false;
5192 
5193  const ON_DimStyle* m_archive_current_dim_style = nullptr;
5194 
5195  // m_archive_dim_style_table_status values:
5196  // READING:
5197  // 0 = not started
5198  // 1 = BeginWrite3dmDimStyle() has been called,
5199  // m_archive_text_style_table[] is valid,
5200  // and Read3dmDimStyle() can be called.
5201  // 2 = All entries of m_archive_text_style_table[] have been read by Read3dmDimStyle().
5202  // 3 = EndRead3dmDimStyle() has been called.
5203  // WRITING:
5204  // 0 = not started
5205  // 1 = BeginWrite3dmDimStyle() has been called and Write3dmDimStyle() can be called.
5206  // 2 = Write3dmDimStyle() has saved at least one dimstyle
5207  // 3 = EndWrite3dmDimStyle() has been called.
5208  unsigned int m_archive_dim_style_table_status = 0;
5209 
5210  // index in m_archive_text_style_table[] where Read3dmDimStyle() should
5211  // begin searching for the next dimstyle to "read".
5212  unsigned int m_archive_dim_style_table_read_index = ON_UNSET_UINT_INDEX;
5213 
5214 #pragma ON_PRAGMA_WARNING_POP
5215 
5216 public:
5217  /*
5218  Description:
5219  When reading version 5 and earlier files that contain a text style
5220  table, this function can be used to get the archive text style from
5221  the archive text style index. This function is used when reading
5222  V5 and pre August 2016 V6 ON_DimStyle information.
5223  */
5224  const ON_TextStyle* ArchiveTextStyleFromArchiveTextStyleIndex(
5225  int archive_text_style_index
5226  ) const;
5227 
5228 private:
5229  ON_String m_archive_3dm_start_section_comment = ON_String::EmptyString;
5230  class ON_3dmProperties* m_archive_3dm_properties = nullptr;
5231  class ON_3dmSettings* m_archive_3dm_settings = nullptr;
5232 
5233 private:
5234  // prohibit default construction, copy construction, and operator=
5235  ON_BinaryArchive() = delete;
5236  ON_BinaryArchive( const ON_BinaryArchive& ) = delete; // no implementation
5237  ON_BinaryArchive& operator=( const ON_BinaryArchive& ) = delete; // no implementation
5238 };
5239 
5240 class ON_CLASS ON_3dmGoo
5241 {
5242  // used to store goo
5243 public:
5244  ON_3dmGoo();
5245  ~ON_3dmGoo();
5246  ON_3dmGoo( const ON_3dmGoo& );
5247  ON_3dmGoo& operator=( const ON_3dmGoo& );
5248 
5249  void Dump(ON_TextLog&) const;
5250 
5251  unsigned int m_typecode;
5252  int m_value;
5253  unsigned char* m_goo;
5254  ON_3dmGoo* m_next_goo;
5255  ON_3dmGoo* m_prev_goo;
5256 };
5257 
5258 
5259 class ON_CLASS ON_BinaryFile : public ON_BinaryArchive
5260 {
5261 public:
5262  ON_BinaryFile(
5263  ON::archive_mode archive_mode
5264  );
5265 
5266  /*
5267  Description:
5268  Create an ON_BinaryArchive that reads/writes from an ordinary file.
5269  Parameters:
5270  archive_mode - [in]
5271  fp - [in]
5272  If a file is being read, fp is the pointer returned
5273  from ON_FileStream::Open(...,"rb").
5274  If a file is being written, fp is the pointer returned
5275  from ON_FileStream::Open(...,"wb").
5276  */
5277  ON_BinaryFile(
5278  ON::archive_mode archive_mode,
5279  FILE* fp
5280  );
5281 
5282  /*
5283  Description:
5284  Create an ON_BinaryArchive that reads/writes from an ordinary file.
5285  Parameters:
5286  archive_mode - [in]
5287  file_system_path - [in]
5288  path to file being read or written.
5289  */
5290  ON_BinaryFile(
5291  ON::archive_mode archive_mode,
5292  const wchar_t* file_system_path
5293  );
5294 
5295  /*
5296  Description:
5297  Create an ON_BinaryArchive that reads/writes from an ordinary file.
5298  Parameters:
5299  archive_mode - [in]
5300  file_system_path - [in]
5301  path to file being read or written.
5302  */
5303  ON_BinaryFile(
5304  ON::archive_mode archive_mode,
5305  const char* file_system_path
5306  );
5307 
5308  ~ON_BinaryFile();
5309 
5310 protected:
5311  // ON_BinaryArchive overrides
5312  ON__UINT64 Internal_CurrentPositionOverride() const override;
5313  bool Internal_SeekFromCurrentPositionOverride(int byte_offset) override;
5314  bool Internal_SeekToStartOverride() override;
5315 
5316 public:
5317  // ON_BinaryArchive overrides
5318  bool AtEnd() const override;
5319 
5320 protected:
5321  // ON_BinaryArchive overrides
5322  size_t Internal_ReadOverride( size_t, void* ) override; // return actual number of bytes read (like fread())
5323  size_t Internal_WriteOverride( size_t, const void* ) override;
5324  bool Flush() override;
5325 
5326 public:
5327 
5328  //// fseek from end (since the file has an end)
5329  //bool SeekFromEnd( int );
5330 
5331  //////////
5332  // To use custom memory buffering instead of relying
5333  // on fread()/fwrite()'s build in buffering, call
5334  // EnableMemoryBuffer() with the buffer size immediately
5335  // after constructing the ON_BinaryFile. There appear
5336  // to be enough bugs in existing Windows NT/2000 NETWORK
5337  // I/O that using this hack will speed up I/O by factors
5338  // of 10 to 100.
5339  void EnableMemoryBuffer(
5340  int=16384 // capacity of memory buffer
5341  );
5342 
5343  /*
5344  Returns:
5345  True if a file stream is open (nullptr != m_fp).
5346  */
5347  bool FileIsOpen() const;
5348 
5349  void CloseFile();
5350 
5351 private:
5352  // Implementation
5353  FILE* m_fp = nullptr;
5354  bool m_bCloseFileInDestructor = false;
5355 
5356  // if m_memory_buffer_capacity is zero, then Write() uses
5357  // fwrite() directly. If m_memory_buffer_capacity is
5358  // greater than zero, then Write() buffers its results
5359  // into m_memory_buffer. This is provided to work around
5360  // bugs in some networks that result in extremely slow
5361  // performance when seeking is used.
5362  size_t m_memory_buffer_capacity = 0;
5363  size_t m_memory_buffer_size = 0;
5364  size_t m_memory_buffer_ptr = 0;
5365  unsigned char* m_memory_buffer = nullptr;
5366 
5367 private:
5368  // prohibit default construction, copy construction, and operator=
5369  ON_BinaryFile() = delete;
5370  ON_BinaryFile(const ON_BinaryFile&) = delete;
5371  ON_BinaryFile& operator=(const ON_BinaryFile&) = delete;
5372 };
5373 
5374 class ON_CLASS ON_BinaryArchiveBuffer : public ON_BinaryArchive
5375 {
5376 public:
5377  /*
5378  Description:
5379  Create an ON_BinaryArchive that reads/writes from an ON_Buffer.
5380  Parameters:
5381  mode - [in]
5382  buffer - [in]
5383  Remarks:
5384  If a non-null buffer is specifed, then do not call SetBuffer()
5385  */
5386  ON_BinaryArchiveBuffer( ON::archive_mode, ON_Buffer* buffer );
5387 
5388  virtual ~ON_BinaryArchiveBuffer();
5389 
5390  /*
5391  Description:
5392  If the ON_BinaryArchiveBuffer class is created with the constructor
5393  that has a single "mode" parameter, then use SetBuffer()
5394  to specify the buffer to read/write from before using
5395  the ON_BinaryArchiveBuffer.
5396  Parameters:
5397  buffer - [in]
5398  Returns:
5399  True if the buffer is set. Once the buffer is set it
5400  cannot be changed.
5401  */
5402  bool SetBuffer( ON_Buffer* buffer );
5403 
5404  /*
5405  Returns:
5406  Buffer being read/written.
5407  */
5408  ON_Buffer* Buffer() const;
5409 
5410 protected:
5411  // ON_BinaryArchive overrides
5412  ON__UINT64 Internal_CurrentPositionOverride() const override;
5413  bool Internal_SeekFromCurrentPositionOverride(int byte_offset) override;
5414  bool Internal_SeekToStartOverride() override;
5415 
5416 public:
5417  // ON_BinaryArchive overrides
5418  bool AtEnd() const override;
5419 
5420 protected:
5421  // ON_BinaryArchive overrides
5422  size_t Internal_ReadOverride( size_t, void* ) override; // return actual number of bytes read (like fread())
5423  size_t Internal_WriteOverride( size_t, const void* ) override;
5424  bool Flush() override;
5425 
5426 private:
5427  // Buffer being read/written.
5428  ON_Buffer* m_buffer;
5429 
5430 private:
5431  // prohibit use - you should specify a buffer.
5432  ON_BinaryArchiveBuffer( ON::archive_mode );
5433 private:
5434  // prohibit default construction, copy construction, and operator=
5435  ON_BinaryArchiveBuffer( ); // no implementation
5436  ON_BinaryArchiveBuffer( const ON_BinaryArchiveBuffer& ); // no implementation
5437  ON_BinaryArchiveBuffer& operator=( const ON_BinaryArchiveBuffer& ); // no implementation
5438 };
5439 
5440 
5441 class ON_CLASS ON_Read3dmBufferArchive : public ON_BinaryArchive
5442 {
5443 public:
5444 
5445  /*
5446  Description:
5447  Construct an ON_BinaryArchive for reading information from a memory buffer.
5448  Parameters:
5449  sizeof_buffer - [in] size of buffer in bytes (>0)
5450  buffer - [in] memory buffer containing binary archive
5451  bCopyBuffer - [in]
5452  true - copy the input buffer.
5453  Useful when the buffer may be destroyed while this class is still in use.
5454  false - Do not copy the input buffer.
5455  In this case you are responsible for making certain the input buffer
5456  is valid while this class is in use.
5457  archive_3dm_version - [in] (1,2,3,4,5,50,60,...)
5458  archive_opennurbs_version - [in]
5459  */
5461  size_t sizeof_buffer,
5462  const void* buffer,
5463  bool bCopyBuffer,
5464  int archive_3dm_version,
5465  unsigned int archive_opennurbs_version
5466  );
5467 
5469 
5470  /*
5471  Returns:
5472  value of m_sizeof_buffer
5473  */
5474  size_t SizeOfBuffer() const;
5475 
5476  /*
5477  Returns:
5478  value of m_buffer
5479  */
5480  const void* Buffer() const;
5481 
5482 protected:
5483  // ON_BinaryArchive overrides
5484  ON__UINT64 Internal_CurrentPositionOverride() const override;
5485  bool Internal_SeekFromCurrentPositionOverride(int byte_offset) override;
5486  bool Internal_SeekToStartOverride() override;
5487 
5488 public:
5489  // ON_BinaryArchive overrides
5490  bool AtEnd() const override;
5491 
5492 protected:
5493  // ON_BinaryArchive overrides
5494  size_t Internal_ReadOverride( size_t, void* ) override; // return actual number of bytes read (like fread())
5495  size_t Internal_WriteOverride( size_t, const void* ) override;
5496  bool Flush() override;
5498 private:
5499  void* m_p;
5500  const unsigned char* m_buffer;
5501  size_t m_sizeof_buffer;
5502  size_t m_buffer_position;
5503  ON__INT_PTR m_reserved1;
5504  ON__INT_PTR m_reserved2;
5505  ON__INT_PTR m_reserved3;
5506  ON__INT_PTR m_reserved4;
5507 
5508 private:
5509  // prohibit use - no implementation
5513 };
5514 
5515 class ON_CLASS ON_Write3dmBufferArchive : public ON_BinaryArchive
5516 {
5517 public:
5518 
5519  /*
5520  Description:
5521  Construct an ON_BinaryArchive for writing information to a memory buffer.
5522  Parameters:
5523  initial_sizeof_buffer - [in]
5524  initial size of buffer in bytes (>=0)
5525  If you are unable to estimate the size you will need, pass in zero.
5526  max_sizeof_buffer - [in]
5527  maximum size of buffer in bytes (>=0)
5528  If max_sizeof_buffer > 0 and the amount of information saved
5529  requires a buffer larger than this size, then writing fails.
5530  If max_sizeof_buffer <= 0, then no buffer size limits are enforced.
5531  archive_3dm_version - [in] (0, ,2,3,4,5,50,60,...)
5532  Pass 0 or ON_BinaryArchive::CurrentArchiveVersion() to write the
5533  version of opennurbs archives used by lastest version of Rhino.
5534  archive_opennurbs_version - [in]
5535  */
5537  size_t initial_sizeof_buffer,
5538  size_t max_sizeof_buffer,
5539  int archive_3dm_version,
5540  unsigned int archive_opennurbs_version
5541  );
5542 
5544 
5545  /*
5546  Returns:
5547  Size of the archive in bytes.
5548  */
5549  size_t SizeOfArchive() const;
5550 
5551  /*
5552  Returns:
5553  value of m_sizeof_buffer
5554  */
5555  size_t SizeOfBuffer() const;
5556 
5557  /*
5558  Returns:
5559  value of m_buffer.
5560  SizeOfArchive() reports the number of bytes
5561  written to this buffer.
5562  SizeOfBuffer() reports the number of bytes
5563  allocated in this buffer.
5564 
5565  */
5566  const void* Buffer() const;
5567 
5568  /*
5569  Returns:
5570  The pointer to the buffer and sets all
5571  members on this archive back to zero.
5572  The caller is responsible for calling onfree() on
5573  the pointer when finished with the buffer.
5574  */
5575  void* HarvestBuffer();
5576 
5577 protected:
5578  // ON_BinaryArchive overrides
5579  ON__UINT64 Internal_CurrentPositionOverride() const override;
5580  bool Internal_SeekFromCurrentPositionOverride(int byte_offset) override;
5581  bool Internal_SeekToStartOverride() override;
5582 
5583 public:
5584  // ON_BinaryArchive overrides
5585  bool AtEnd() const override;
5586 
5587 protected:
5588  // ON_BinaryArchive overrides
5589  size_t Internal_ReadOverride( size_t, void* ) override; // return actual number of bytes read (like fread())
5590  size_t Internal_WriteOverride( size_t, const void* ) override;
5591  bool Flush() override;
5592 
5593 private:
5594  void AllocBuffer(size_t);
5595  void* m_p;
5596  unsigned char* m_buffer;
5597  size_t m_sizeof_buffer;
5598  const size_t m_max_sizeof_buffer;
5599  size_t m_sizeof_archive;
5600  size_t m_buffer_position;
5601  ON__INT_PTR m_reserved1;
5602  ON__INT_PTR m_reserved2;
5603  ON__INT_PTR m_reserved3;
5604  ON__INT_PTR m_reserved4;
5605 
5606 private:
5607  // prohibit use - no implementation
5611 };
5612 
5613 /*
5614 Description:
5615  Create a simple archive that contains a single or multiple geometric object(s).
5616 Parameters:
5617  archive - [in] destination archive.
5618  version - [in] (0, 2, 3, 4,50,60,...) format version.archive version number.
5619  Version 2 format can be read by Rhino 2 and Rhino 3. Version
5620  3 format can be read by Rhino 3.
5621  Pass 0 or ON_BinaryArchive::CurrentArchiveVersion() to write
5622  the latest version of archives supported by Rhino.
5623  object - [in] object to be saved in the archive's object table.
5624  This is typically some type of ON_Curve, ON_Surface, ON_Mesh,
5625  or ON_Brep.
5626  object_list - [in] objects to be saved in the archive's object table.
5627  These are typically some type of ON_Curve, ON_Surface, ON_Mesh,
5628  or ON_Brep.
5629  object_list_count - [in] explicit count of number of objects in object_list.
5630 Returns:
5631  @untitled table
5632  true archive successfully written.
5633  false archive not successfully written.
5634 Example:
5635 
5636  const char* filename = "myfile.3dm";
5637  FILE* fp = ON::OpenFile( filename, "wb" );
5638  ON_BinaryFile file( fp, ON::archive_mode::write3dm );
5639  bool ok = ON_WriteArchive( archive, geometry );
5640  ON::CloseFile( fp );
5641 
5642 Remarks:
5643  For ON_WriteOneObjectArchive the object table in the archive will contain a single
5644  object.
5645 */
5646 ON_DECL
5647 bool ON_WriteOneObjectArchive(
5648  ON_BinaryArchive& archive,
5649  int version,
5650  const ON_Object& object
5651  );
5652 
5653 ON_DECL
5654 bool ON_WriteOneObjectArchive(
5655  const wchar_t* filename,
5656  const ON_Object& object
5657  );
5658 
5659 ON_DECL
5660 bool ON_WriteMultipleObjectArchive(
5661  ON_BinaryArchive& archive,
5662  int version,
5663  const ON_SimpleArray<const ON_Object* >& object_list
5664  );
5665 
5666 ON_DECL
5667 bool ON_WriteMultipleObjectArchive(
5668  ON_BinaryArchive& archive,
5669  int version,
5670  size_t object_list_count,
5671  const ON_Object* const* object_list
5672  );
5673 
5674 bool ON_WriteMultipleObjectArchive(
5675  const wchar_t* filename,
5676  int version,
5677  size_t object_list_count,
5678  const ON_Object* const* object_list
5679  );
5680 
5681 
5682 /*
5683 Opens a debug archive file
5684  Uses directory set by ON_SetDebugWriteObjectDirectory(const wchar_t* ).
5685  creates a file named "debug_file_nnnn.3dm"
5686 Example:
5687  ON_DebugWriteArchive debug;
5688  if(debug.m_Archive)
5689  ON_WriteArchive( *debug.m_Archive, geometry );
5690 
5691 */
5692 class ON_CLASS ON_DebugWriteArchive
5693 {
5694 public:
5695  /*
5696  Creates a file in N_DebugWriteObjectDirectory() and allocates archive to write to
5697  that file.
5698  */
5701 
5702  // check for nullptr before using
5703  // Destructor closes archive and deletes it.
5704 
5705  ON_BinaryArchive* Archive() const;
5706 
5707  // Name of the archive file.
5708  // = .../debug_file_NNNNN.3dm where N = Number().
5709  const ON_wString& FilePath() const;
5710 
5711  // the number of the archive or 0
5712  unsigned int Number() const;
5713 
5714 private:
5715  ON_BinaryArchive* m_archive = nullptr;
5716  FILE* m_fp = nullptr;
5717  unsigned int m_N = 0;
5718  ON_wString m_file_path;
5719 
5720 private:
5721  ON_DebugWriteArchive(const ON_DebugWriteArchive&) = delete;
5722  ON_DebugWriteArchive& operator=(const ON_DebugWriteArchive&) = delete;
5723 };
5724 
5725 #endif
Definition: opennurbs_annotationbase.h:23
Definition: opennurbs_plane.h:507
Definition: opennurbs_fpoint.h:556
Definition: opennurbs_material.h:25
Definition: opennurbs_fpoint.h:832
Definition: opennurbs_hatch.h:327
ON_UUID is a 16 byte universally unique identifier.
Definition: opennurbs_uuid.h:32
Definition: opennurbs_point.h:1933
Definition: opennurbs_object_history.h:71
An ON_Arc is a subcurve of 3d circle.
Definition: opennurbs_arc.h:33
The ON_ModelComponent class is a base class for all components in a model and manages the index...
Definition: opennurbs_model_component.h:24
Definition: opennurbs_3dm_properties.h:139
ON_ManifestIdentificationMap is used to record a map from a source manifest to a destination manifest...
Definition: opennurbs_archive.h:1464
Definition: opennurbs_mapchan.h:167
TableState
Definition: opennurbs_archive.h:1771
Objects can have per viewport display properties that override a viewport&#39;s default display propertie...
Definition: opennurbs_linestyle.h:45
Definition: opennurbs_array.h:36
static const ON_NameHash UnsetNameHash
Definition: opennurbs_string.h:3444
Definition: opennurbs_3dm_settings.h:1184
An ON_InstanceDefinition defines the geometry used by instance references.
Definition: opennurbs_instance.h:139
Definition: opennurbs_fpoint.h:211
Definition: opennurbs_light.h:20
Definition: opennurbs_group.h:20
ON_Object array is used to store lists of classes that are derived from ON_Object. It differs from ON_ClassArray in that the virtual ON_Object::MemoryRelocate function is called when growing the dynamic array requires changing the location of the memory buffer used to store the elements in the array.
Definition: opennurbs_array.h:725
Definition: opennurbs_string.h:2020
Definition: opennurbs_dimensionstyle.h:218
Definition: opennurbs_archive.h:337
ON_Circle is a circle in 3d. The cirle is represented by a radius and an orthonormal frame of the pla...
Definition: opennurbs_circle.h:32
Context for an annotation object. This context is required when converting current annotation objects...
Definition: opennurbs_archive.h:1592
Definition: opennurbs_color.h:24
ON_3dmObjectAttributes uses ON_MappingChannel to record which texture mapping function to use when ap...
Definition: opennurbs_mapchan.h:36
Definition: opennurbs_point.h:277
Definition: opennurbs_objref.h:100
Definition: opennurbs_archive.h:27
Definition: opennurbs_layer.h:20
class ON_LinetypeSegment
Definition: opennurbs_linestyle.h:88
Definition: opennurbs_archive.h:5060
Definition: opennurbs_3dm_settings.h:110
static const ON_String EmptyString
Definition: opennurbs_string.h:862
Definition: opennurbs_point.h:648
Definition: opennurbs_bounding_box.h:25
Definition: opennurbs_archive.h:5251
Definition: opennurbs_string.h:852
Definition: opennurbs_archive.h:1044
Definition: opennurbs_archive.h:5079
Definition: opennurbs_xform.h:28
Definition: opennurbs_bitmap.h:28
Definition: opennurbs_archive.h:1739
Type
The ON_ModelComponent::Type enum has a value for each explicit component type and two special values...
Definition: opennurbs_model_component.h:52
Definition: opennurbs_archive.h:434
Definition: opennurbs_archive.h:5321
Definition: opennurbs_archive.h:5497
Definition: opennurbs_archive.h:478
ON_3dmObjectAttributes uses ON_MaterialRef to record which rendering material and mappings a renderin...
Definition: opennurbs_mapchan.h:89
Definition: opennurbs_texture_mapping.h:37
Definition: opennurbs_line.h:20
Definition: opennurbs_text_style.h:19
Definition: opennurbs_archive.h:5187
eStorageDeviceError
Definition: opennurbs_archive.h:4097
Top level OpenNURBS objects have geometry and attributes. The geometry is stored in some class derive...
Definition: opennurbs_3dm_attributes.h:41
Used to store geometry table object definition and attributes in an ONX_Model.
Definition: opennurbs_model_geometry.h:22
Pure virtual base class for all classes that must provide runtime class id or support object level 3D...
Definition: opennurbs_object.h:460
An ON_NameHash is designed to help search for and compare attribute names like the ON_ModelComponent...
Definition: opennurbs_string.h:3434
class ON_Linetype
Definition: opennurbs_linetype.h:42
Definition: opennurbs_array.h:409
Definition: opennurbs_textlog.h:20
Definition: opennurbs_archive.h:1783
Definition: opennurbs_userdata.h:20
Definition: opennurbs_fpoint.h:38
Definition: opennurbs_model_component.h:1622
Definition: opennurbs_objref.h:163
Definition: opennurbs_point.h:460
Definition: opennurbs_archive.h:352
Definition: opennurbs_archive.h:1212
Definition: opennurbs_plane.h:20
Definition: opennurbs_fpoint.h:385
Typically the vector portion is a unit vector and m_d = -(x*P.x + y*P.y + z*P.z) for a point P on the...
Definition: opennurbs_point.h:1433
Definition: opennurbs_point.h:839
Definition: opennurbs_point.h:1152
Definition: opennurbs_point.h:46