1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #if !defined(ON_ARCHIVE_INC_)
18 #define ON_ARCHIVE_INC_
19 
20 class ON_CLASS ON_FileStream
21 {
22 public:
23   /*
24   Description:
25     Portable wrapper for C runtime fopen().
26   Parameters:
27     filename - [in]
28     mode - [in]
29   Remarks:
30     Use the ON_FileStream static functions for reading, writing,
31     seeking, position finding with the FILE pointer returned
32     by this function.
33   */
34   static FILE* Open( const wchar_t* filename, const wchar_t* mode );
35 
36   /*
37   Description:
38     Portable wrapper for C runtime fopen().
39   Parameters:
40     filename - [in]
41     mode - [in]
42   Remarks:
43     Use the ON_FileStream static functions for reading, writing,
44     seeking, position finding with the FILE pointer returned
45     by this function.
46   */
47   static FILE* Open( const char* filename, const char* mode );
48 
49   /*
50   Description:
51     Portable wrapper for C runtime fclose().
52   Parameters:
53     fp - [in]
54       FILE pointer returned by ON_FileStream::Open().
55   Returns:
56        0: successful
57       -1: null fp parameter
58     != 0: fclose() failure code
59   */
60   static int Close( FILE* fp );
61 
62   /*
63   Description:
64     Portable wrapper for C runtime ftell().
65   Parameters:
66     fp - [in]
67       FILE pointer returned by ON_FileStream::Open().
68   Returns:
69     >= 0: current file position
70       -1: an error occured
71   */
72   static ON__INT64 CurrentPosition( FILE* fp );
73 
74   /*
75   Description:
76     Portable wrapper for C runtime fseek(fp,offset,SEEK_CUR).
77   Parameters:
78     fp - [in]
79       FILE pointer returned by ON_FileStream::Open().
80     offset - [in]
81   */
82   static bool SeekFromCurrentPosition( FILE* fp, ON__INT64 offset );
83 
84   /*
85   Description:
86     Portable wrapper for C runtime fseek(fp,offset,SEEK_SET).
87   Parameters:
88     fp - [in]
89       FILE pointer returned by ON_FileStream::Open().
90     offset - [in]
91   */
92   static bool SeekFromStart( FILE* fp, ON__INT64 offset );
93 
94   /*
95   Description:
96     Portable wrapper for C runtime fseek(fp,offset,SEEK_END).
97   Parameters:
98     fp - [in]
99       FILE pointer returned by ON_FileStream::Open().
100     offset - [in]
101   */
102   static bool SeekFromEnd( FILE* fp, ON__INT64 offset );
103 
104   /*
105   Description:
106     Portable wrapper for C runtime fseek(fp,offset,origin).
107   Parameters:
108     fp - [in]
109       FILE pointer returned by ON_FileStream::Open().
110     offset - [in]
111     origin - [in]
112       SEEK_SET (0): seek from beginning of file.
113       SEEK_CUR (1): seek from current position of file pointer.
114       SEEK_END (2): seek from end of file.
115   */
116   static bool Seek( FILE* fp, ON__INT64 offset, int orgin );
117 
118   /*
119   Description:
120     Portable wrapper for C runtime fread(buffer,1,count,fp).
121   Parameters:
122     fp - [in]
123       FILE pointer returned by ON_FileStream::Open()
124     count - [in]
125       number of bytes to read.
126     buffer - [out]
127       read bytes are stored in this buffer
128   Returns:
129     number of bytes read
130   */
131   static ON__UINT64 Read( FILE* fp, ON__UINT64 count, void* buffer );
132 
133   /*
134   Description:
135     Portable wrapper for C runtime fwrite(buffer,1,count,fp).
136   Parameters:
137     fp - [in]
138       FILE pointer returned by ON_FileStream::Open()
139     count - [in]
140       number of bytes to write
141     buffer - [in]
142       data to be written
143   Returns:
144     number of bytes written.
145   */
146   static ON__UINT64 Write( FILE* fp, ON__UINT64 count, const void* buffer );
147 
148   /*
149   Description:
150     Portable wrapper for C runtime fflush(fp).
151   Parameters:
152     fp - [in]
153       FILE pointer returned by ON_FileStream::Open().
154   Returns:
155     true if flush was successful.  False if an error occured.
156   */
157   static bool Flush( FILE* fp );
158 
159   /*
160   Description:
161     Portable wrapper for C runtime fstat().
162   Parameters:
163     fp - [in]
164       FILE pointer returned by ON_FileStream::Open().
165     file_size - [out]
166       If file_size is not null, the the size of the file
167       in bytes returned here
168     file_creation_time - [out]
169       If file_creation_time is not null, then the time the file
170       was created is returned here as the number of seconds since
171       midnight January 1, 1970.
172     file_last_modified_time - [out]
173       If file_last_modified_time is not null, then the time the file
174       was last modified is returned here as the number of seconds
175       since midnight January 1, 1970.
176   Returns:
177     true if the query was successful.  False if an error occured.
178   */
179   static bool GetFileInformation(
180     FILE* fp,
181     ON__UINT64* file_size,
182     ON__UINT64* file_create_time,
183     ON__UINT64* file_last_modified_time
184     );
185 };
186 
187 class ON_CLASS ON_FileIterator
188 {
189 public:
190   ON_FileIterator();
191   ~ON_FileIterator();
192   void Destroy();
193 
194   /*
195   Description:
196     Find the first matching file in the directory.
197   Parameters:
198     directory_name - [in]
199       The directory to look in.
200     file_name_filter - [in]
201       If this paramter is null, then the iteration
202       includes all names in the directory.
203       The file name to search for. This parameter can
204       include wildcard characters, such as an
205       asterisk (*) or a question mark (?). For example,
206       "\rootdir\subdir\*.*"  will iterate all files in
207       the \rootdir\subdir\ directory.
208 
209   Example:
210           // Iterate through the files in a directory named "\rootdir\subdir"
211           FILE* fp = 0;
212           ON_FileIterator fit;
213           const char* directory = "\\rootdir\\subdir";
214           for ( const wchar_t* filename = fit.FirstFile( directory, "*.3dm" );
215                 0 != filename;
216                 filename = fit.NextFile()
217               )
218           {
219             if ( fit.CurrentFileIsDirectory() )
220               continue;
221             ON_String fullpath = directory;
222             fullpath += '\\';
223             fullpath += filename;
224             FILE* fp = ON_FileStream::Open(fullpath,"rb");
225             if ( 0 == fp )
226             {
227               continue;
228             }
229             ...
230             ON_FileStream::Close(fp);
231             fp = 0;
232           }
233         }
234 
235   Returns:
236     NULL if no matching files are present in the directory.
237   */
238   const wchar_t* FirstFile(
239     const wchar_t* directory_name,
240     const wchar_t* file_name_filter
241     );
242 
243   const wchar_t* FirstFile(
244     const char* directory_name,
245     const char* file_name_filter
246     );
247 
248   /*
249   Description:
250     Find the next matching file in the directory.
251   Returns:
252     NULL if no more matching files are present in the directory.
253   */
254   const wchar_t* NextFile();
255 
256   const wchar_t* CurrentFileName() const;
257 
258   ON__UINT64 CurrentFileSize() const;
259 
260   /*
261   Returns
262     true if the current "file" is a directory.
263   */
264   bool CurrentFileIsDirectory() const;
265 
266   /*
267   Returns
268     true if the current file or directory is hidden.
269     This means its name begins with a '.' or it's
270     Windows hidden attribute is true.
271   */
272   bool CurrentFileIsHidden() const;
273 
274   bool GetCurrentFullPathFileName( ON_wString& filename ) const;
275 
276   /*
277   Returns:
278     File creation time in seconds since January 1, 1970
279   */
280   ON__UINT64 CurrentFileCreateTime() const;
281 
282   /*
283   Returns:
284     File last modified time in seconds since January 1, 1970
285   */
286   ON__UINT64 CurrentFileLastModifiedTime() const;
287 
288   /*
289   Returns:
290     File last access time in seconds since January 1, 1970
291   */
292   ON__UINT64 CurrentFileLastAccessTime() const;
293 
294   /*
295   Returns:
296     Number of matching files returned so far.
297   */
298   ON__UINT64 Count() const;
299 
300 private:
301   // Used by Windows ::Find
302   ON__UINT64 m_count;
303   ON_wString m_directory;
304 
305 #if defined(ON_COMPILER_MSC)
306   ON__UINT32 m_file_attributes_mask;
307   HANDLE m_h;
308   WIN32_FIND_DATA m_fd;
309 #else
310   ON_wString m_ws_file_name_filter;
311   ON_String m_utf8_file_name_filter;
312   DIR* m_dir;
313   struct dirent m_dirent;
314   char m_dirent_name_buffer[NAME_MAX+1]; // < this field provide storage for m_dirent.d_name[]
315 
316   // information about the current file
317   wchar_t m_current_name[1024];
318   ON__UINT64 m_current_file_attributes; // 1 = regular file, 2 = directory
319   ON__UINT64 m_current_file_size;
320   ON__UINT64 m_current_file_create_time;
321   ON__UINT64 m_current_last_modified_time;
322   ON__UINT64 m_current_last_access_time;
323 #endif
324 };
325 
326 
327 /////////////////////////////////////////////////////////////////////
328 //
329 // ON_Buffer
330 //
331 
332 typedef void (*ON_Buffer_ErrorHandler)(class ON_Buffer*);
333 
334 class ON_CLASS ON_Buffer
335 {
336 public:
337   ON_Buffer();
338   ~ON_Buffer();
339 
340   ON_Buffer(const ON_Buffer& src);
341   ON_Buffer& operator=(const ON_Buffer& src);
342 
343   /*
344   Description:
345     Compare contents of buffers.
346   Paramters:
347     a - [in]
348     b - [in]
349   Returns:
350     -1: a < b
351      0: a == b
352      1: a > b
353   */
354   static int Compare( const ON_Buffer& a, const ON_Buffer& b );
355 
356   void Destroy();
357   void EmergencyDestroy();
358 
359   /*
360   Returns:
361     True if Size() == CurrentPosition().
362   Remarks:
363     It is possible to seek beyond the end of the buffer.
364     In this case, the current position will be past the end
365     of the buffer and AtEnd() will return false.
366   */
367   bool AtEnd() const;
368 
369   /*
370   Returns:
371     Number of bytes currently in the buffer.
372   Remarks:
373     It is possible to seek beyond the end of the buffer.
374     In this case, the current position will be past the end
375     of the buffer and CurrentPosition() will be greater than
376     Size().
377   */
378   ON__UINT64 Size() const;
379 
380   /*
381   Returns:
382     32-bit CRC of the buffer contents.
383   Remarks:
384 
385   */
386   ON__UINT32 CRC32( ON__UINT32 current_remainder ) const;
387 
388 
389   /*
390   Returns:
391     Current position in the buffer.
392   Remarks:
393     It is possible to seek beyond the end of the buffer.
394     In this case, the current position will be past the end
395     of the buffer and CurrentPosition() will be greater than
396     Size().
397   */
398   ON__UINT64 CurrentPosition() const;
399 
400   /*
401   Parameters:
402     size - [in]
403       number of bytes to write.
404     buffer - [in]
405       values to write.
406   Returns:
407     Number of bytes written buffer.
408   */
409   ON__UINT64 Write( ON__UINT64 size, const void* buffer );
410 
411   /*
412   Parameters:
413     size - [in]
414       number of bytes to read.
415     buffer - [out]
416       read values are returned in buffer.
417   Returns:
418     Number of bytes read into buffer. For example,
419     if CurrentPosition() <= Size() and
420     size > (Size() - CurrentPosition()) and
421     buffer is not null, then the value
422     (Size() - CurrentPosition()) is returned.
423   Remarks:
424     If the size parameter is zero, then nothing is done.
425     When CurrentPosition() <= Size(), attempts to read more
426     than (Size() - CurrentPosition()) bytes do not generate
427     an error. When CurrentPosition() > Size(), any attempt
428     to read generates an error.
429   */
430   ON__UINT64 Read( ON__UINT64 size, void* buffer );
431 
432   enum
433   {
434     seek_from_beginning_of_file = 0,
435     seek_from_current_position = 1,
436     seek_from_end_of_file = 2
437   };
438 
439   /*
440   Parameters:
441     offset - [in]
442       number of bytes to seek from origin
443     origin - [in]
444       initial position.
445         0 (SEEK_SET) Seek from beginning of file.
446         1 (SEEK_CUR) Seek from current position.
447         2 (SEEK_END) Seek from end of file.
448   Returns:
449     True if successful.
450     False if the seek would result in a file position
451     before the beginning of the file. If false is
452     returned, the current position is not changed.
453   Remarks:
454     Seeking beyond the end of the buffer is succeeds.
455     Seeking before the beginning of the buffer fails.
456   */
457   bool Seek(
458     ON__INT64 offset,
459     int origin
460     );
461 
462   /*
463   Parameters:
464     offset - [in] (>= 0)
465       number of bytes to seek from the start of the buffer.
466   Returns:
467     True if successful.
468     False if the seek would result in a file position
469     before the beginning of the file. If false is
470     returned, the current position is not changed.
471   Remarks:
472     Seeking beyond the end of the buffer is succeeds.
473     Seeking before the beginning of the buffer fails.
474   */
475   bool SeekFromStart( ON__INT64 offset );
476 
477   /*
478   Parameters:
479     offset - [in]
480       number of bytes to seek from the current position.
481   Returns:
482     True if successful.
483     False if the seek would result in a file position
484     before the beginning of the file. If false is
485     returned, the current position is not changed.
486   Remarks:
487     Seeking beyond the end of the buffer is succeeds.
488     Seeking before the beginning of the buffer fails.
489   */
490   bool SeekFromCurrentPosition( ON__INT64 offset );
491 
492   /*
493   Parameters:
494     offset - [in]
495       number of bytes to seek from the end fo the buffer.
496   Returns:
497     True if successful.
498     False if the seek would result in a file position
499     before the beginning of the file. If false is
500     returned, the current position is not changed.
501   Remarks:
502     Seeking beyond the end of the buffer is succeeds.
503     Seeking before the beginning of the buffer fails.
504   */
505   bool SeekFromEnd( ON__INT64 offset );
506 
507   /*
508   Parameters:
509     buffer_size - [in]
510       new size of buffer.
511   Returns:
512     True if successful.
513   Remarks:
514     The current position is not changed and may be beyond the
515     end of the file. Use Seek to set the current position after
516     calling ChangeSize().
517   */
518   bool ChangeSize( ON__UINT64 buffer_size );
519 
520   /*
521   Description:
522     Return unused memory to heap.
523   Remarks:
524     Call this function after creating an ON_Buffer that will persist for
525     and extended amount of time. There are never more than 16 pages of
526     unsued memory (16*4096 bytes on most computers) in an ON_Buffer.
527     Compact() can be called at any time, but calling Compact() the then
528     writing at the end of the buffer is not an efficient use of time
529     or memory.
530   */
531   bool Compact();
532 
533   /*
534   Returns
535     True if the ON_Buffer is valid.
536   */
537   bool IsValid( const ON_TextLog* text_log ) const;
538 
539   /*
540   Returns:
541     Value that identifies most recent error.
542     0: no error
543     1: attempt to seek to a negative position
544   */
545   ON__UINT32 LastError() const;
546 
547   void ClearLastError();
548 
549   ON_Buffer_ErrorHandler ErrorHandler() const;
550 
551   void SetErrorHandler(ON_Buffer_ErrorHandler error_handler);
552 
553   /*
554   Description:
555     Use WriteToBinaryArchive() to save an entire ON_Buffer inside
556     a binary archive.  Use ReadFromBinaryArchive() to retrieve
557     the ON_Buffer from the ON_BinaryArchive.
558   */
559   bool WriteToBinaryArchive( ON_BinaryArchive& ) const;
560 
561   /*
562   Description:
563     Use ReadFromBinaryArchive() to retrieve an entire ON_Buffer
564     that was written using WriteToBinaryArchive().
565   */
566   bool ReadFromBinaryArchive( ON_BinaryArchive& );
567 
568   /*
569   Description:
570     Compress this buffer
571 
572   Parameters:
573     compressed_buffer - [out]
574       (The reference can be *this)
575 
576   Example:
577 
578         // compress a buffer in place
579         ON_Buffer buffer;
580         buffer = ...;
581         if ( !buffer.Compress(buffer) )
582         {
583            // compression failed
584         }
585         else
586         {
587            // buffer is now compressed
588         }
589 
590   Returns:
591     True if successful.  False if failed.
592   */
593   bool Compress( ON_Buffer& compressed_buffer ) const;
594 
595   /*
596   Description:
597     Uncompress this buffer which must have been compressed using
598     ON_Buffer::Compress().
599 
600   Parameters:
601     uncompressed_buffer - [out]
602       (The reference can be *this)
603 
604   Example:
605         // silly example that compresses and then uncompresses a buffer in place
606         // to show how to call the functions.
607         ON_Buffer buffer;
608         buffer = ...; // buffer is in it uncompressed form
609         if ( buffer.Compress(buffer) )
610         {
611            // buffer is now compressed
612            if ( buffer.Uncompress(buffer) )
613            {
614               // buffer is uncompressed again.
615            }
616         }
617 
618   Returns:
619     True if successful.  False if failed.
620   */
621   bool Uncompress( ON_Buffer& uncompressed_buffer ) const;
622 
623 private:
624 
625   ON__UINT64 m_buffer_size; // total number of bytes in the buffer
626   ON__UINT64 m_current_position;
627 
628   struct ON_BUFFER_SEGMENT* m_first_segment;
629   struct ON_BUFFER_SEGMENT* m_last_segment;
630   struct ON_BUFFER_SEGMENT* m_current_segment;
631   bool SetCurrentSegment(bool);
632   void Copy( const ON_Buffer& );
633 
634   ON_MEMORY_POOL* m_heap;
635   ON_Buffer_ErrorHandler m_error_handler;
636 
637   ON__UINT32 m_last_error;
638   unsigned char m_reserved[12];
639 };
640 
641 /////////////////////////////////////////////////////////////////////
642 //
643 // ON_BinaryArchive
644 //      virtual class for CPU independent serialization
645 //
646 // ON_BinaryFile
647 //      simple class for CPU independent binary file I/O
648 //      includes optional CRC support
649 //
650 
651 class ON_Object;
652 class ON_Group;
653 class ON_Font;
654 class ON_DimStyle;
655 class ON_Arc;
656 class ON_ObjectAttributes;
657 class ON_InstanceDefinition;
658 class ON_HatchPattern;
659 class ON_Linetype;
660 
661 struct ON_3DM_CHUNK
662 {
663   std::size_t m_offset; // In read or write_using_fseek mode, this is the
664                    // file position of first byte after chunk's length.
665                    // In write_using_buffer mode, this of the m_buffer[]
666                    // position of first byte after chunk's length.
667   unsigned int m_typecode;
668   int m_value;
669   int m_do_length; // true if chunk is a long chunk with length
670   ON__UINT16 m_do_crc16; // 16 bit CRC using CCITT polynomial
671   ON__UINT16 m_crc16;
672   ON__UINT32 m_do_crc32; // 32 bit CRC
673   ON__UINT32 m_crc32;
674 };
675 
676 struct ON_3DM_BIG_CHUNK
677 {
678   ON__UINT64 m_big_offset; // In read or write_using_fseek mode, this is the
679                            // file position of first byte after chunk's length.
680                            // In write_using_buffer mode, this of the m_buffer[]
681                            // position of first byte after chunk's length.
682 
683   ON__UINT64 Length() const; // 0 for short chunks
684 
685   ON__INT64 m_big_value;
686   ON__UINT32 m_typecode;
687 
688   ON__UINT8 m_bLongChunk; // true if chunk is a long chunk and m_big_value is a length.
689   ON__UINT8 m_reserved1;
690   ON__UINT8 m_reserved2;
691   ON__UINT8 m_reserved3;
692 
693   // CRC settings
694   ON__UINT8 m_do_crc16; // true (1) if we are calculating 16 bit CRC
695   ON__UINT8 m_do_crc32; // true (1) if we are calculating 32 bit CRC
696   ON__UINT16 m_crc16; // current 16 bit CRC value
697   ON__UINT32 m_crc32; // current 32 bit CRC value
698 };
699 
700 bool ON_IsLongChunkTypecode(ON__UINT32 typecode);
701 
702 bool ON_IsShortChunkTypecode(ON__UINT32 typecode);
703 
704 #if defined(ON_DLL_TEMPLATE)
705 // This stuff is here because of a limitation in the way Microsoft
706 // handles templates and DLLs.  See Microsoft's knowledge base
707 // article ID Q168958 for details.
708 #pragma warning( push )
709 #pragma warning( disable : 4231 )
710 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_3DM_CHUNK>;
711 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_3DM_BIG_CHUNK>;
712 #pragma warning( pop )
713 #endif
714 
715 class ON_Light;
716 class ON_Bitmap;
717 class ON_TextureMapping;
718 class ON_Material;
719 class ON_Layer;
720 class ON_3dmProperties;
721 class ON_3dmSettings;
722 class ON_3dmObjectAttributes;
723 class ON_3dmGoo;
724 
725 class ON_BinaryArchive;
726 
727 // Used int ON_3dmProperties::Read() to set ON_BinaryArchive.m_3dm_opennurbs_version
728 // Do not call directly.
729 void ON_SetBinaryArchiveOpenNURBSVersion(ON_BinaryArchive&,int);
730 
731 class ON_CLASS ON_BinaryArchive // use for generic serialization of binary data
732 {
733 public:
734   ON_BinaryArchive( ON::archive_mode );
735   virtual ~ON_BinaryArchive();
736 
737   virtual
738   std::size_t CurrentPosition( // current offset (in bytes) into archive ( like ftell() )
739                 ) const = 0;
740   virtual
741   bool SeekFromCurrentPosition( // seek from current position ( like fseek( ,SEEK_CUR) )
742                 int // byte offset ( >= -CurrentPostion() )
743                 ) = 0;
744   virtual
745   bool SeekFromStart(  // seek from current position ( like fseek( ,SEEK_SET) )
746                 std::size_t // byte offset ( >= 0 )
747                 ) = 0;
748   virtual
749   bool AtEnd() const = 0; // true if at end of file
750 
751   bool BigSeekFromStart( ON__UINT64 offset );
752   bool BigSeekForward( ON__UINT64 offset );
753   bool BigSeekBackward( ON__UINT64 offset );
754   bool BigSeekFromCurrentPosition( ON__INT64 offset );
755 
756   /*
757   Description:
758     Tool for swapping bytes when doing I/O on
759     using big endian CPUs.
760   Remarks:
761     3dm files are always saved with little endian byte order.
762   See Also:
763     ON_BinaryArchive::Endian
764   */
765   static
766   bool ToggleByteOrder(
767     int, // number of elements
768     int, // size of element (2,4, or 8)
769     const void*,  // source buffer
770     void*         // destination buffer (can be same a source buffer)
771     );
772 
773   static
774   const char* TypecodeName( unsigned int tcode );
775 
776   static
777   char* ON_TypecodeParse( unsigned int tcode, char* typecode_name, std::size_t max_length );
778 
779   bool ReadMode() const;  // true if reading is permitted
780   bool WriteMode() const; // true if writing is permitted
781 
782   /*
783   Returns:
784      Endian-ness of the cpu reading this file.
785   Remarks:
786     3dm files are alwasy saved with little endian byte order.
787   */
788   ON::endian Endian() const; // endian-ness of cpu
789 
790   int BadCRCCount() const; // number of chunks read with bad CRC
791 
792   bool ReadByte( std::size_t, void* ); // must fail if mode is not read or readwrite
793 
794   bool WriteByte( std::size_t, const void* ); // must fail if mode is not write or readwrite
795 
796   /*
797   Description:
798     Expert user function that uses Read() to load a buffer.
799   Paramters:
800     sizeof_buffer - [in] number of bytes to attempt to read.
801     buffer - [out] read bytes are stored in this buffer
802   Returns:
803     Number of bytes actually read, which may be less than
804     sizeof_buffer if the end of file is encountered.
805   */
806   ON__UINT64 ReadBuffer( ON__UINT64 sizeof_buffer, void* buffer );
807 
808   /*
809   Description:
810     Expert user function to control CRC calculation while reading and writing.
811     Typically this is used when seeking around and reading/writing information
812     in non-serial order.
813   Parameters:
814     bEnable  - [in]
815   Returns:
816     Current state of CRC calculation.  Use the returned value to restore the
817     CRC calculation setting after you are finished doing your fancy pants
818     expert IO.
819   */
820   bool EnableCRCCalculation( bool bEnable );
821 
822   // ReadCompressedBuffer()/WriteCompressedBuffer() use zlib 1.1.3
823   // to inflate/deflate the data buffer.
824   // Care must be used to get an endian independent file.
825   // See ON_Mesh::Read()/ON_Mesh::Write() for an example of an endian
826   // independent use of compression. See also ToggleByteOrder() and Endian().
827   //
828   // To read data archived by WriteCompressedBuffer( sizeof_buffer, buffer )
829   // do something like:
830   //
831   //   std::size_t sizeof_buffer = 0;
832   //   ReadCompressedBufferSize(&sizeof_buffer);
833   //   buffer = something with sizeof_buffer bytes.
834   //   int bFailedCRC = false;
835   //   bool ok = ReadCompressedBuffer( sizeof_buffer, buffer, &bFailedCRC );
836   //
837 
838 
839   /*
840   Description:
841     Red the size of a compressed buffer.
842   Parameters:
843     sizeof__outbuffer - [out] size of the uncompressed buffer in bytes
844   Returns:
845     True if read was successful.
846   */
847   bool ReadCompressedBufferSize( std::size_t* sizeof__outbuffer );
848 
849   /*
850   Description:
851     Read compressed information from an archive and uncompress it.
852   Parameters:
853     sizeof__outbuffer - [in] size of the uncompressed buffer in bytes
854     outbuffer - [out] uncompressed buffer returned here
855     bFailedCRC - [out] true if cyclic redundancy check fails
856                       on uncompressed buffer
857 
858   Example:
859 
860           std::size_t sizeof_buffer = 0;
861           ReadCompressedBufferSize(&sizeof_buffer);
862           buffer = ...; // something with sizeof_buffer bytes.
863           int bFailedCRC = false;
864           bool ok = ReadCompressedBuffer( sizeof_buffer, buffer, &bFailedCRC );
865 
866   Returns:
867     True if read was successful.  You need to check the value
868     of bFailedCRC to see if the information that was read is valid.
869   */
870   bool ReadCompressedBuffer(
871           std::size_t sizeof__outbuffer,
872           void* outbuffer,
873           int* bFailedCRC
874           );
875 
876   /*
877   Description:
878     Compress buffer and write the compressed information to the archive.
879   Parameters:
880     sizeof__inbuffer - [in] size of the uncompressed buffer in bytes
881     inbuffer - [in] uncompressed buffer
882   Returns:
883     True if write was successful.
884   */
885   bool WriteCompressedBuffer(
886     std::size_t sizeof__inbuffer,
887     const void* inbuffer
888     );
889 
890   bool ReadBool( bool* );
891 
892 	bool ReadChar(    // Read an array of 8 bit chars
893 			std::size_t,       // number of chars to read
894 			char*
895 			);
896 	bool ReadChar(    // Read an array of 8 bit unsigned chars
897 			std::size_t,       // number of unsigned chars to read
898 			unsigned char*
899 			);
900 	bool ReadChar(    // Read a single 8 bit char
901 			char*
902 			);
903 	bool ReadChar(    // Read a single 8 bit unsigned char
904 			unsigned char*
905 			);
906 
907 	bool ReadShort(   // Read an array of 16 bit shorts
908 			std::size_t,       // number of shorts to read
909 			short*
910 			);
911 	bool ReadShort(   // Read an array of 16 bit unsigned shorts
912 			std::size_t,       // number of shorts to read
913 			unsigned short*
914 			);
915 	bool ReadShort(   // Read a single 16 bit short
916 			short*
917 			);
918 	bool ReadShort(   // Read a single 16 bit unsigned short
919 			unsigned short*
920 			);
921 
922 	bool ReadInt( // Read an array of 32 bit integers
923 			std::size_t,	      // number of ints to read
924 			int*
925 			);
926 	bool ReadInt( // Read an array of 32 bit integers
927 			std::size_t,	      // number of ints to read
928 			unsigned int*
929 			);
930 	bool ReadInt( // Read a single 32 bit integer
931 			int*
932 			);
933 	bool ReadInt( // Read a single 32 bit unsigned integer
934 			unsigned int*
935 			);
936 
937 	bool ReadBigInt( // Read an array of 64 bit integers
938 			std::size_t,	      // number of ints to read
939 			ON__INT64*
940 			);
941 	bool ReadBigInt( // Read an array of 64 bit integers
942 			std::size_t,	      // number of ints to read
943 			ON__UINT64*
944 			);
945 	bool ReadBigInt( // Read a single 64 bit integer
946 			ON__INT64*
947 			);
948 	bool ReadBigInt( // Read a single 64 bit unsigned integer
949 			ON__UINT64*
950 			);
951 
952 	bool ReadLong( // Read an array of 32 bit integers
953 			std::size_t,	      // number of ints to read
954 			long*
955 			);
956 	bool ReadLong( // Read an array of 32 bit integers
957 			std::size_t,	      // number of ints to read
958 			unsigned long*
959 			);
960 	bool ReadLong( // Read a single 32 bit integer
961 			long*
962 			);
963 	bool ReadLong( // Read a single 32 bit unsigned integer
964 			unsigned long*
965 			);
966 	bool ReadSize( // Read a single std::size_t
967 			std::size_t*
968 			);
969 
970   bool ReadBigSize( std::size_t* ); // 64 bits
971 
972   bool ReadBigTime( time_t* ); // UCT seconds since 1 January 1970 (64 bits)
973 
974 
975 	bool ReadFloat(   // Read an array of floats
976 			std::size_t,       // number of floats
977 			float*
978 			);
979 	bool ReadFloat(   // Read a single float
980 			float*
981 			);
982 	bool ReadDouble(  // Read an array of IEEE doubles
983 			std::size_t,       // number of doubles
984 			double*
985 			);
986 	bool ReadDouble(  // Read a single double
987 			double*
988 			);
989 
990   bool ReadColor(
991     ON_Color&
992     );
993 
994   bool ReadPoint (
995     ON_2dPoint&
996     );
997   bool ReadPoint (
998     ON_3dPoint&
999     );
1000   bool ReadPoint (
1001     ON_4dPoint&
1002     );
1003   bool ReadVector (
1004     ON_2dVector&
1005     );
1006   bool ReadVector (
1007     ON_3dVector&
1008     );
1009 
1010   bool ReadBoundingBox(ON_BoundingBox&);
1011 
1012   bool ReadXform(ON_Xform&);
1013 
1014   bool ReadPlaneEquation(ON_PlaneEquation&);
1015 
1016   bool ReadPlane(ON_Plane&);
1017 
1018   bool ReadLine(ON_Line&);
1019 
1020   bool ReadArc(ON_Arc&);
1021 
1022   bool ReadCircle(ON_Circle&);
1023 
1024   bool ReadInterval( ON_Interval& );
1025 
1026   bool ReadUuid( ON_UUID& );
1027 
1028   bool ReadDisplayMaterialRef( ON_DisplayMaterialRef& );
1029 
1030   bool ReadLinetypeSegment( ON_LinetypeSegment& );
1031 
1032   // All times are stored in coordinated universal time
1033   // ( a.k.a GMT, UTC ).  Use ANSI C time() and gmtime() calls.
1034   bool ReadTime( struct tm& );
1035 
1036   /*
1037   Parameters:
1038     str_array_count - [out]
1039       Number of elements in the string array. All ON_BinaryArchive string
1040       WriteString() functions write a null terminator to the file and
1041       the null terminator is included in the count. This means that
1042       if a string has a non-zero element, then str_array_count >= 2.
1043   Remarks:
1044     Modify your code to use ReadStringUTF8ElementCount() when reading
1045     UTF-8 encoded strings and ReadStringUTF16ElementCount()
1046     when reading UTF-16 encoded strings.
1047   */
1048   ON_DEPRECATED bool ReadStringSize(
1049       std::size_t* str_array_count
1050       );
1051 
1052   /*
1053   Parameters:
1054     string_utf8_element_count - [out]
1055       Number of bytes in the string array. All ON_BinaryArchive string
1056       WriteString() functions write a null terminator to the file and
1057       the null terminator is included in string_element_count. This means
1058       that if opennurbs wrote the string, either string_element_count = 0
1059       or string_element_count >= 2.
1060   */
1061   bool ReadStringUTF8ElementCount(
1062     std::size_t* string_utf8_element_count
1063     );
1064 
1065   /*
1066   Parameters:
1067     string_utf16_element_count - [out]
1068       Number of elements in the string array. All ON_BinaryArchive string
1069       WriteString() functions write a null terminator to the file and
1070       the null terminator is included in string_element_count. This means
1071       that if opennurbs wrote the string, either string_element_count = 0
1072       or string_element_count >= 2.
1073   */
1074   bool ReadStringUTF16ElementCount(
1075     std::size_t* string_utf16_element_count
1076     );
1077 
1078 
1079   /*
1080   Parameters:
1081     str_array_count - [in]
1082       Number of char elements in str_array[], including the null
1083       terminator.  The value of str_array_count is returned by
1084       ReadCharStringElementCount().
1085     str_array - [in/out]
1086       Pass in an array with at least str_array_count elements.
1087       If true is returned and str_array_count > 0,
1088       then str_array[str_array_count-1] = 0. All strings with
1089       char elements written by Rhino are UTF-8 encoded
1090       unicode strings.
1091   */
1092   bool ReadString(
1093       std::size_t str_array_count,
1094       char* str_array
1095       );
1096 
1097   /*
1098   Parameters:
1099     str_array_count - [in]
1100       Number of unsignd char elements in str_array[], including
1101       the null terminator. The value of str_array_count is returned
1102       by ReadCharStringElementCount().
1103     str_array - [in/out]
1104       Pass in an array with at least str_array_count elements.
1105       If true is returned and str_array_count > 0,
1106       then str_array[str_array_count-1] = 0. All strings with
1107       unsigned char elements written by Rhino are UTF-8 encoded
1108       unicode strings.
1109   */
1110   bool ReadString(
1111       std::size_t str_array_count,
1112       unsigned char* str_array
1113       );
1114 
1115   /*
1116   Parameters:
1117     str_array_count - [in]
1118       Number of unsigned short elements in str_array[],
1119       including the null terminator. The value of
1120       str_array_count is returned by ReadWideCharStringElementCount().
1121     str_array - [in/out]
1122       Pass in an array with at least str_array_count elements.
1123       If true is returned and str_array_count > 0,
1124       then str_array[str_array_count-1] = 0. All strings with
1125       unsigned short elements written by Rhino are UTF-16 encoded
1126       unicode strings.
1127   */
1128   bool ReadString(
1129       std::size_t str_array_count,
1130       unsigned short*  str_array
1131       );
1132 
1133   bool ReadString( ON_String& sUTF8 );
1134 
1135   bool ReadString( ON_wString& s );
1136 
1137   bool ReadComponentIndex( ON_COMPONENT_INDEX& );
1138 
1139   bool ReadArray( ON_SimpleArray<bool>& );
1140   bool ReadArray( ON_SimpleArray<char>& );
1141   bool ReadArray( ON_SimpleArray<short>& );
1142   bool ReadArray( ON_SimpleArray<int>& );
1143   bool ReadArray( ON_SimpleArray<float>& );
1144   bool ReadArray( ON_SimpleArray<double>& );
1145   bool ReadArray( ON_SimpleArray<ON_Color>& );
1146   bool ReadArray( ON_SimpleArray<ON_2dPoint>& );
1147   bool ReadArray( ON_SimpleArray<ON_3dPoint>& );
1148   bool ReadArray( ON_SimpleArray<ON_4dPoint>& );
1149   bool ReadArray( ON_SimpleArray<ON_2dVector>& );
1150   bool ReadArray( ON_SimpleArray<ON_3dVector>& );
1151   bool ReadArray( ON_SimpleArray<ON_Xform>& );
1152   bool ReadArray( ON_SimpleArray<ON_2fPoint>& );
1153   bool ReadArray( ON_SimpleArray<ON_3fPoint>& );
1154   bool ReadArray( ON_SimpleArray<ON_4fPoint>& );
1155   bool ReadArray( ON_SimpleArray<ON_2fVector>& );
1156   bool ReadArray( ON_SimpleArray<ON_3fVector>& );
1157   bool ReadArray( ON_SimpleArray<ON_UUID>& );
1158   bool ReadArray( ON_SimpleArray<ON_UuidIndex>& );
1159   bool ReadArray( ON_SimpleArray<ON_SurfaceCurvature>& );
1160   bool ReadArray( ON_ClassArray<ON_String>& );
1161   bool ReadArray( ON_ClassArray<ON_wString>& );
1162   bool ReadArray( ON_SimpleArray<ON_DisplayMaterialRef>& );
1163   bool ReadArray( ON_SimpleArray<ON_LinetypeSegment>& );
1164   bool ReadArray( ON_SimpleArray<ON_MappingChannel>& );
1165   bool ReadArray( ON_ClassArray<ON_MaterialRef>& );
1166   bool ReadArray( ON_ClassArray<ON_MappingRef>& );
1167   bool ReadArray( ON_ClassArray<class ON_ObjRef>& );
1168   bool ReadArray( ON_SimpleArray<class ON_ObjRef_IRefID>& );
1169   bool ReadArray( ON_SimpleArray<class ON_ClippingPlaneInfo>& );
1170   bool ReadArray( ON_ObjectArray<class ON_Layer>& );
1171   bool ReadArray( ON_SimpleArray<class ON_Layer*>& );
1172 
1173   bool WriteBool( bool );
1174 
1175   bool WriteChar(    // Write an array of 8 bit chars
1176 			std::size_t,       // number of chars to write
1177 			const char*
1178 			);
1179 	bool WriteChar(    // Write an array of 8 bit unsigned chars
1180 			std::size_t,       // number of unsigned chars to write
1181 			const unsigned char*
1182 			);
1183 	bool WriteChar(    // Write a single 8 bit char
1184 			char
1185 			);
1186 	bool WriteChar(    // Write a single 8 bit unsigned char
1187 			unsigned char
1188 			);
1189 
1190 	bool WriteShort(   // Write an array of 16 bit shorts
1191 			std::size_t,       // number of shorts to write
1192 			const short*
1193 			);
1194 	bool WriteShort(   // Write an array of 16 bit unsigned shorts
1195 			std::size_t,       // number of shorts to write
1196 			const unsigned short*
1197 			);
1198 	bool WriteShort(   // Write a single 16 bit short
1199 			short
1200 			);
1201 	bool WriteShort(   // Write a single 16 bit unsigned short
1202 			unsigned short
1203 			);
1204 
1205 	bool WriteInt( // Write an array of 32 bit integers
1206 			std::size_t,	      // number of ints to write
1207 			const int*
1208 			);
1209 	bool WriteInt( // Write an array of 32 bit integers
1210 			std::size_t,	      // number of ints to write
1211 			const unsigned int*
1212 			);
1213 	bool WriteInt( // Write a single 32 bit integer
1214 			int
1215 			);
1216 	bool WriteInt( // Write a single 32 bit unsigned integer
1217 			unsigned int
1218 			);
1219 
1220 	bool WriteBigInt( // Write an array of 64 bit integers
1221 			std::size_t,	      // number of ints to write
1222 			const ON__INT64*
1223 			);
1224 	bool WriteBigInt( // Write an array of 64 bit integers
1225 			std::size_t,	      // number of ints to write
1226 			const ON__UINT64*
1227 			);
1228 	bool WriteBigInt( // Write a single 64 bit integer
1229 			ON__INT64
1230 			);
1231 	bool WriteBigInt( // Write a single 64 bit unsigned integer
1232 			ON__UINT64
1233 			);
1234 
1235 	bool WriteLong( // Write an array of 32 bit integers
1236 			std::size_t,	      // number of ints to write
1237 			const long*
1238 			);
1239 	bool WriteLong( // Write an array of 32 bit integers
1240 			std::size_t,	      // number of ints to write
1241 			const unsigned long*
1242 			);
1243 	bool WriteLong( // Write a single 32 bit integer
1244 			long
1245 			);
1246 	bool WriteLong( // Write a single 32 bit unsigned integer
1247 			unsigned long
1248 			);
1249 	bool WriteSize( // Write a single std::size_t
1250 			std::size_t
1251 			);
1252 
1253   bool WriteBigSize( std::size_t ); // 64 bits
1254 
1255   bool WriteBigTime( time_t ); // UCT seconds since 1 January 1970 (64 bits)
1256 
1257 	bool WriteFloat(   // Write a number of IEEE floats
1258 			std::size_t,       // number of doubles
1259 			const float*
1260 			);
1261 	bool WriteFloat(   // Write a single float
1262 			float
1263 			);
1264 	bool WriteDouble(  // Write a single double
1265       std::size_t,
1266 			const double*
1267 			);
1268 	bool WriteDouble(  // Write a single double
1269 			double
1270 			);
1271 
1272   bool WriteColor (
1273     const ON_Color&
1274     );
1275 
1276   bool WritePoint (
1277     const ON_2dPoint&
1278     );
1279   bool WritePoint (
1280     const ON_3dPoint&
1281     );
1282   bool WritePoint (
1283     const ON_4dPoint&
1284     );
1285   bool WriteVector (
1286     const ON_2dVector&
1287     );
1288   bool WriteVector (
1289     const ON_3dVector&
1290     );
1291 
1292   bool WriteBoundingBox(const ON_BoundingBox&);
1293 
1294   bool WriteXform(const ON_Xform&);
1295 
1296   bool WritePlaneEquation(const ON_PlaneEquation&);
1297 
1298   bool WritePlane(const ON_Plane&);
1299 
1300   bool WriteLine(const ON_Line&);
1301 
1302   bool WriteArc(const ON_Arc&);
1303 
1304   bool WriteCircle(const ON_Circle&);
1305 
1306   bool WriteInterval( const ON_Interval& );
1307 
1308   bool WriteUuid( const ON_UUID& );
1309 
1310   bool WriteDisplayMaterialRef( const ON_DisplayMaterialRef& );
1311 
1312   bool WriteLinetypeSegment( const ON_LinetypeSegment& );
1313 
1314   // All times are stored in universal coordinated time
1315   // ( a.k.a GMT, UCT ).  Use ANSI C time() and gmtime() calls.
1316   bool WriteTime( const struct tm& );
1317 
1318   /*
1319   Parameters:
1320     sUTF8 - [in]
1321       A null terminated UTF-8 encoded unicode string.
1322   Remarks:
1323     To read a string written with WriteString(const char*),
1324     call ReadStringUTF8ElementCount(&string_utf8_element_count)
1325     to get the number of char elements written in the file,
1326     obtain a buffer with at least string_utf8_element_count
1327     char elements and then call
1328     ReadString(string_utf8_element_count,buffer) to read the
1329     char elements.
1330 
1331     If 0 == sUTF8 or 0 == SUTF8[0], a 4 byte int with
1332     value = 0 is written, otherwise a 4 byte int with
1333     value = strlen + 1 is written, followed by the string,
1334     followed by the null terminator.
1335   */
1336   bool WriteString(
1337       const char* sUTF8
1338       );
1339 
1340   /*
1341   Parameters:
1342     sUTF8 - [in]
1343       A null terminated UTF-8 encoded unicode string.
1344   Remarks:
1345     To read a string written with WriteString(const unsigned char*),
1346     call ReadStringUTF8ElementCount(&string_utf8_element_count) to
1347     get the number of unsigned char elements written in the file,
1348     obtain a buffer with at least string_utf8_element_count
1349     unsigned char elements and then call
1350     ReadString(string_utf8_element_count,buffer) to read the
1351     unsigned charelements.
1352 
1353     If 0 == sUTF8 or 0 == SUTF8[0], a 4 byte int with
1354     value = 0 is written, otherwise a 4 byte int with
1355     value = strlen + 1 is written, followed by the string,
1356     followed by the null terminator.
1357   */
1358   bool WriteString(
1359       const unsigned char* sUTF8
1360       );
1361 
1362   /*
1363   Parameters:
1364     sUTF16 - [in]
1365       A null terminated UTF-16 encoded unicode string.
1366   Remarks:
1367     To read a string written with WriteString(const unsigned short*),
1368     call ReadStringUTF16ElementCount(&string_utf16_element_count) to
1369     get the number of unsigned short elements written in the file,
1370     obtain a buffer with at least string_utf16_element_count
1371     unsigned short elements and then call
1372     ReadString(string_utf16_element_count,buffer) to read the
1373     unsigned short elements.
1374 
1375     If 0 == sUTF8 or 0 == SUTF8[0], a 4 byte int with
1376     value = 0 is written, otherwise a 4 byte int with
1377     value = strlen + 1 is written, followed by the string,
1378     followed by the null terminator.
1379   */
1380   bool WriteString(
1381       const unsigned short* sUTF16
1382       );
1383 
1384   bool WriteString( const ON_String& sUTF8 );
1385 
1386   bool WriteString( const ON_wString& s);
1387 
1388   bool WriteComponentIndex( const ON_COMPONENT_INDEX& );
1389 
1390   bool WriteArray( const ON_SimpleArray<bool>& );
1391   bool WriteArray( const ON_SimpleArray<char>& );
1392   bool WriteArray( const ON_SimpleArray<short>& );
1393   bool WriteArray( const ON_SimpleArray<int>& );
1394   bool WriteArray( const ON_SimpleArray<float>& );
1395   bool WriteArray( const ON_SimpleArray<double>& );
1396 
1397   bool WriteArray( const ON_SimpleArray<ON_Color>& );
1398 
1399   bool WriteArray( const ON_SimpleArray<ON_2dPoint>& );
1400   bool WriteArray( const ON_SimpleArray<ON_3dPoint>& );
1401   bool WriteArray( const ON_SimpleArray<ON_4dPoint>& );
1402   bool WriteArray( const ON_SimpleArray<ON_2dVector>& );
1403   bool WriteArray( const ON_SimpleArray<ON_3dVector>& );
1404 
1405   bool WriteArray( const ON_SimpleArray<ON_2fPoint>& );
1406   bool WriteArray( const ON_SimpleArray<ON_3fPoint>& );
1407   bool WriteArray( const ON_SimpleArray<ON_4fPoint>& );
1408   bool WriteArray( const ON_SimpleArray<ON_2fVector>& );
1409   bool WriteArray( const ON_SimpleArray<ON_3fVector>& );
1410   bool WriteArray( const ON_SimpleArray<ON_Xform>& );
1411   bool WriteArray( const ON_SimpleArray<ON_UUID>& );
1412   bool WriteArray( const ON_SimpleArray<ON_UuidIndex>& );
1413   bool WriteArray( const ON_SimpleArray<ON_SurfaceCurvature>& );
1414   bool WriteArray( const ON_ClassArray<ON_String>& );
1415   bool WriteArray( const ON_ClassArray<ON_wString>& );
1416   bool WriteArray( const ON_SimpleArray<ON_DisplayMaterialRef>& );
1417   bool WriteArray( const ON_SimpleArray<ON_LinetypeSegment>& );
1418   bool WriteArray( const ON_SimpleArray<ON_MappingChannel>& );
1419   bool WriteArray( const ON_ClassArray<ON_MaterialRef>& );
1420   bool WriteArray( const ON_ClassArray<ON_MappingRef>& );
1421   bool WriteArray( const ON_ClassArray<class ON_ObjRef>& );
1422   bool WriteArray( const ON_SimpleArray<class ON_ObjRef_IRefID>& );
1423   bool WriteArray( const ON_SimpleArray<class ON_ClippingPlaneInfo>& );
1424   bool WriteArray( int count, const class ON_Layer* );
1425   bool WriteArray( int count, const class ON_Layer*const* );
1426 
1427   /////////////////////////////////////////////////////
1428   //
1429   // Read/Write classes derived from ON_Object
1430   //
1431 
1432   /*
1433   Description:
1434     Reads and object from a 3dm archive;
1435   Parameters:
1436     ppObject - [out]  object is allocated and a pointer to the
1437                       allocated object is returned as *ppObject;
1438   Returns:
1439     0: failure - unable to read object because of file IO problems
1440     1: success
1441     3: unable to read object because it's UUID is not registered
1442        this could happen in cases where old code is attempting to read
1443        new objects.
1444   */
1445   int ReadObject(
1446          ON_Object** ppObject
1447          );
1448 
1449 
1450   /*
1451   Description:
1452     Reads and object from a 3dm archive.
1453   Parameters:
1454     object - [in] The value of object.ON_ClassId()->Uuid() must
1455                   exactly match the class uuid in of the next
1456                   object in the archive.
1457   Returns:
1458     0: failure - unable to read object because of file IO problems.
1459     1: success
1460     2: unable to read object because the class id in the archive
1461        did not match pObject->ClassId.
1462   */
1463   int ReadObject(
1464          ON_Object& object
1465          );
1466 
1467   bool WriteObject( const ON_Object* ); // writes object definition
1468   bool WriteObject( const ON_Object& ); // writes object definition
1469 
1470 
1471   ///////////////////////////////////////////////////////////////////
1472   ///////////////////////////////////////////////////////////////////
1473   //
1474   // 3DM Interface - ignore if not reading/writing a 3DM file
1475   //                 this is here so that the infrastructure
1476   //                 for writing 3dm archives is available for
1477   //                 any type of serialization device.
1478   //
1479   bool EnableSave3dmRenderMeshes( ON_BOOL32 = true ); // returns previous state
1480   bool Save3dmRenderMeshes() const;
1481 
1482   bool EnableSave3dmAnalysisMeshes( ON_BOOL32 = true ); // returns previous state
1483   bool Save3dmAnalysisMeshes() const;
1484 
1485   bool EnableSaveUserData( ON_BOOL32 = true ); // returns previous state
1486   bool SaveUserData() const;
1487 
1488   /*
1489   Returns:
1490     50 (The Rhino 5.0 opennurbs file version.)
1491     This is the value of version to pass to ON_BinaryArchive
1492     functions like Write3dmStartSection() when you want to use the
1493     the current opennurbs version number and you do not want to have
1494     to update your code when this version number changes.
1495   */
1496   static int CurrentArchiveVersion();
1497 
1498   ///////////////////////////////////////////////////////////////////
1499   // Step 1: REQUIRED - Write/Read Start Section
1500   //
1501 
1502   /*
1503   Parameters:
1504     version - [in]
1505        0, 2, 3, 4, 5 or 50 (5 is treated as 50)
1506 
1507        If version is 0, then the value of ON_BinaryArchive::CurrentArchiveVersion()
1508        is used.
1509 
1510        Use either 0 or the value of ON_BinaryArchive::CurrentArchiveVersion()
1511        for the version parameter when you want your code to write the most
1512        up to date file version.
1513 
1514     sStartSectionComment - [in]
1515       NULL or ASCII string with application name, et cetera.
1516       This information is primarily used when debugging files
1517       that contain problems.  McNeel and Associates stores
1518       application name, application version, compile date,
1519       and the OS in use when file was written.
1520   */
1521   bool Write3dmStartSection(
1522         int version,
1523         const char* sStartSectionComment
1524         );
1525 
1526   /*
1527   Parameters:
1528     version - [out]
1529        .3dm file version (2, 3, 4, 5 or 50)
1530     sStartSectionComment - [out]
1531       string passed to Write3dmStartSection()
1532   */
1533   bool Read3dmStartSection(
1534         int* version,
1535         ON_String& sStartSectionComment
1536         );
1537 
1538   ///////////////////////////////////////////////////////////////////
1539   // Step 2: REQUIRED - Write/Read properties table
1540   //
1541   bool Write3dmProperties(
1542         const ON_3dmProperties&
1543         );
1544   bool Read3dmProperties(
1545         ON_3dmProperties&
1546         );
1547 
1548   ///////////////////////////////////////////////////////////////////
1549   // Step 3: REQUIRED - Write/Read settings table
1550   //
1551   bool Write3dmSettings(
1552         const ON_3dmSettings&
1553         );
1554   bool Read3dmSettings(
1555         ON_3dmSettings&
1556         );
1557 
1558   ///////////////////////////////////////////////////////////////////
1559   // Step 4: REQUIRED - Write/Read bitmap table (it can be empty)
1560   //
1561   bool BeginWrite3dmBitmapTable();
1562   bool Write3dmBitmap( const ON_Bitmap& );
1563   bool EndWrite3dmBitmapTable();
1564 
1565   bool BeginRead3dmBitmapTable();
1566   int  Read3dmBitmap(   // returns 0 at end of light table
1567                         //         1 bitmap successfully read
1568             ON_Bitmap** // bitmap returned here
1569             );
1570   bool EndRead3dmBitmapTable();
1571 
1572   ///////////////////////////////////////////////////////////////////
1573   // Step 5: REQUIRED - Write/Read render material table (it can be empty)
1574   //
1575   bool BeginWrite3dmTextureMappingTable();
1576   bool Write3dmTextureMapping( const ON_TextureMapping& );
1577   bool EndWrite3dmTextureMappingTable();
1578 
1579   bool BeginRead3dmTextureMappingTable();
1580   int  Read3dmTextureMapping( // returns 0 at end of table
1581             ON_TextureMapping** // layer returned here
1582             );
1583   bool EndRead3dmTextureMappingTable();
1584 
1585   ///////////////////////////////////////////////////////////////////
1586   // Step 6: REQUIRED - Write/Read render material table (it can be empty)
1587   //
1588   bool BeginWrite3dmMaterialTable();
1589   bool Write3dmMaterial( const ON_Material& );
1590   bool EndWrite3dmMaterialTable();
1591 
1592   bool BeginRead3dmMaterialTable();
1593   int  Read3dmMaterial( // returns 0 at end of table
1594             ON_Material** // layer returned here
1595             );
1596   bool EndRead3dmMaterialTable();
1597 
1598   ///////////////////////////////////////////////////////////////////
1599   // Step 7: REQUIRED - Write/Read linetype table (it can be empty)
1600   //
1601   bool BeginWrite3dmLinetypeTable();
1602   bool Write3dmLinetype( const ON_Linetype&);
1603   bool EndWrite3dmLinetypeTable();
1604 
1605   bool BeginRead3dmLinetypeTable();
1606   int  Read3dmLinetype(ON_Linetype**);
1607   bool EndRead3dmLinetypeTable();
1608 
1609   ///////////////////////////////////////////////////////////////////
1610   // Step 8: REQUIRED - Write/Read layer table (it can be empty)
1611   //
1612   bool BeginWrite3dmLayerTable();
1613   bool Write3dmLayer( const ON_Layer& );
1614   bool EndWrite3dmLayerTable();
1615 
1616   bool BeginRead3dmLayerTable();
1617   int  Read3dmLayer( // returns 0 at end of table
1618             ON_Layer** // layer returned here
1619             );
1620   bool EndRead3dmLayerTable();
1621 
1622   ///////////////////////////////////////////////////////////////////
1623   // Step 9: REQUIRED - Write/Read group table (it can be empty)
1624   //
1625   bool BeginWrite3dmGroupTable();
1626   bool Write3dmGroup( const ON_Group& );
1627   bool EndWrite3dmGroupTable();
1628 
1629   bool BeginRead3dmGroupTable();
1630 
1631   // Description:
1632   //   Reads groups from group table.  If the group definition is
1633   //   read, a group is created by calling new ON_Group(),
1634   //   initialized with values stored in the archive, and
1635   //   returned.
1636   //
1637   // Parameters:
1638   //   ppGroup - If the group definition is
1639   //   read, a group is created by calling new ON_Group(),
1640   //   initialized with values stored in the archive, and
1641   //   a pointer to the new group is returned in *ppGroup.
1642   //
1643   // Returns:
1644   //
1645   //   @untitled table
1646   //   0     at the end of the group table
1647   //   1     group definition was successfully read
1648   //   -1    archive is corrupt at this point
1649   //
1650   // Example:
1651   //   Calls to Read3dmGroup need to be bracketed by calls
1652   //   to BeginRead3dmGroupTable() / EndRead3dmGroupTable().
1653   //
1654   //           archive.BeginRead3dmGroupTable();
1655   //           ON_Group* pGroup;
1656   //           int rc = 1;
1657   //           while(rc==1)
1658   //           { //
1659   //             pGroup = 0;
1660   //             archive.Read3dmGroup(&pGroup);
1661   //             if ( pGroup )
1662   //               do something with pGroup
1663   //           } //
1664   //           archive.EndRead3dmGroupTable();
1665   //
1666   int  Read3dmGroup(
1667             ON_Group** // ppGroup
1668             );
1669 
1670   bool EndRead3dmGroupTable();
1671 
1672 
1673   ///////////////////////////////////////////////////////////////////
1674   // Step 10: REQUIRED - Write/Read font table (it can be empty)
1675   //
1676   bool BeginWrite3dmFontTable();
1677   bool Write3dmFont( const ON_Font& );
1678   bool EndWrite3dmFontTable();
1679 
1680   bool BeginRead3dmFontTable();
1681 
1682   // Description:
1683   //   Reads fonts from font table.  If the font definition is
1684   //   read, a font is created by calling new ON_Font(),
1685   //   initialized with values stored in the archive, and
1686   //   returned.
1687   //
1688   // Parameters:
1689   //   ppFont - If the font definition is
1690   //   read, a font is created by calling new ON_Font(),
1691   //   initialized with values stored in the archive, and
1692   //   a pointer to the new font is returned in *ppFont.
1693   //
1694   // Returns:
1695   //
1696   //   @untitled table
1697   //   0     at the end of the font table
1698   //   1     font definition was successfully read
1699   //   -1    archive is corrupt at this point
1700   //
1701   // Example:
1702   //   Calls to Read3dmFont need to be bracketed by calls
1703   //   to BeginRead3dmFontTable() / EndRead3dmFontTable().
1704   //
1705   //           archive.BeginRead3dmFontTable();
1706   //           int rc = 1;
1707   //           ON_Font* pFont;
1708   //           while(rc==1)
1709   //           { //
1710   //             pFont = 0;
1711   //             archive.Read3dmFont(&pFont);
1712   //             if ( pFont )
1713   //               do something with pFont
1714   //           } //
1715   //           archive.EndRead3dmFontTable();
1716   //
1717   int Read3dmFont(
1718             ON_Font** // ppFont
1719             );
1720 
1721   bool EndRead3dmFontTable();
1722 
1723 
1724   ///////////////////////////////////////////////////////////////////
1725   // Step 11: REQUIRED - Write/Read dimstyle table (it can be empty)
1726   //
1727   bool BeginWrite3dmDimStyleTable();
1728   bool Write3dmDimStyle( const ON_DimStyle& );
1729   bool EndWrite3dmDimStyleTable();
1730 
1731   bool BeginRead3dmDimStyleTable();
1732 
1733   // Description:
1734   //   Reads annotation dimension styles from dimension style table.
1735   //   If the dimension style definition is read,
1736   //   a dimension style is created by calling new ON_DimStyle(),
1737   //   initialized with values stored in the archive, and
1738   //   returned.
1739   //
1740   // Parameters:
1741   //   ppDimStyle - If the dimstyle definition is
1742   //   read, a dimstyle is created by calling new ON_DimStyle(),
1743   //   initialized with values stored in the archive, and
1744   //   a pointer to the new dimstyle is returned in *ppDimStyle.
1745   //
1746   // Returns:
1747   //
1748   //   @untitled table
1749   //   0     at the end of the dimension style table
1750   //   1     dimension style definition was successfully read
1751   //   -1    archive is corrupt at this point
1752   //
1753   // Example:
1754   //   Calls to Read3dmDimStyle need to be bracketed by calls
1755   //   to BeginRead3dmDimStyleTable() / EndRead3dmDimStyleTable().
1756   //
1757   //           archive.BeginRead3dmDimStyleTable();
1758   //           int rc = 1;
1759   //           ON_DimStyle* pDimStyle;
1760   //           while(rc==1)
1761   //           { //
1762   //             pDimStyle = 0;
1763   //             archive.Read3dmDimStyle(&pDimStyle);
1764   //             if ( pDimStyle )
1765   //               do something with pDimStyle
1766   //           } //
1767   //           archive.EndRead3dmDimStyleTable();
1768   //
1769   int Read3dmDimStyle(
1770             ON_DimStyle** // ppDimStyle
1771             );
1772 
1773   bool EndRead3dmDimStyleTable();
1774 
1775 
1776   ///////////////////////////////////////////////////////////////////
1777   // Step 12: REQUIRED - Write/Read render light table (it can be empty)
1778   //
1779   bool BeginWrite3dmLightTable();
1780   bool Write3dmLight( const ON_Light&,
1781          const ON_3dmObjectAttributes* // optional
1782          );
1783   bool EndWrite3dmLightTable();
1784 
1785   bool BeginRead3dmLightTable();
1786   int  Read3dmLight(  // returns 0 at end of light table
1787                       //         1 light successfully read
1788                       //        -1 if file is corrupt
1789             ON_Light**, // light returned here
1790             ON_3dmObjectAttributes* // optional - if NOT NULL, object attributes are
1791                                     //            returned here
1792             );
1793   bool EndRead3dmLightTable();
1794 
1795 
1796   ///////////////////////////////////////////////////////////////////
1797   // Step 13: REQUIRED - Write/Read hatch pattern table (it can be empty)
1798   //
1799   bool BeginWrite3dmHatchPatternTable();
1800   bool Write3dmHatchPattern( const ON_HatchPattern&);
1801   bool EndWrite3dmHatchPatternTable();
1802 
1803   bool BeginRead3dmHatchPatternTable();
1804   int  Read3dmHatchPattern(ON_HatchPattern**);
1805   bool EndRead3dmHatchPatternTable();
1806 
1807   ///////////////////////////////////////////////////////////////////
1808   // Step 14: REQUIRED - Write/Read instance definition table (it can be empty)
1809   //
1810   bool BeginWrite3dmInstanceDefinitionTable();
1811   bool Write3dmInstanceDefinition( const ON_InstanceDefinition& );
1812   bool EndWrite3dmInstanceDefinitionTable();
1813 
1814   bool BeginRead3dmInstanceDefinitionTable();
1815 
1816   /*
1817    Description:
1818      Reads instance definitions from instance defintion table.
1819 
1820    Parameters:
1821      ppInstanceDefinition - If an instance defintion is
1822      read, an instance defintion is created by calling new
1823      ON_InstanceDefinition(), initialized with values stored
1824      in the archive, and a pointer to the new instance defintion
1825      is returned in *ppInstanceDefinition.
1826 
1827    Returns:
1828 
1829      @untitled table
1830      0     at the end of the instance defintion table
1831      1     instance defintion was successfully read
1832      -1    archive is corrupt at this point
1833 
1834    Example:
1835      Calls to Read3dmInstanceDefinition need to be bracketed by calls
1836      to BeginRead3dmInstanceDefinitionTable() / EndRead3dmInstanceDefinitionTable().
1837 
1838              archive.BeginRead3dmInstanceDefinitionTable();
1839              int rc = 1;
1840              ON_InstanceDefinition* pInstanceDefinition;
1841              while(rc==1)
1842              {
1843                pInstanceDefinition = 0;
1844                archive.Read3dmInstanceDefinition(&pInstanceDefinition);
1845                if ( pInstanceDefinition )
1846                  do something with pInstanceDefinition
1847              }
1848              archive.EndRead3dmInstanceDefinitionTable();
1849   */
1850   int Read3dmInstanceDefinition(
1851             ON_InstanceDefinition** // ppInstanceDefinition
1852             );
1853 
1854   bool EndRead3dmInstanceDefinitionTable();
1855 
1856   ///////////////////////////////////////////////////////////////////
1857   // Step 15: REQUIRED - Write/Read geometry and annotation table (it can be empty)
1858   //
1859   bool BeginWrite3dmObjectTable();
1860   bool Write3dmObject(
1861          const ON_Object&,
1862          const ON_3dmObjectAttributes* // optional
1863          );
1864   bool EndWrite3dmObjectTable();
1865 
1866   bool BeginRead3dmObjectTable();
1867   int  Read3dmObject( // returns 0 at end of object table
1868                       //         1 if object is read
1869                       //         2 if object is skipped because it does not match filter
1870                       //        -1 if file is corrupt
1871           ON_Object**, // object returned here (NULL if skipped)
1872           ON_3dmObjectAttributes*, // optional - if NOT NULL, object attributes are
1873                                    //            returned here
1874           unsigned int = 0 // optional filter made by setting ON::object_type bits
1875           );  // returns NULL at end of object table
1876   bool EndRead3dmObjectTable();
1877 
1878   ///////////////////////////////////////////////////////////////////
1879   // Step 16: REQUIRED - Write/Read history record table (it can be empty)
1880   //
1881   bool BeginWrite3dmHistoryRecordTable();
1882   bool Write3dmHistoryRecord(
1883          const class ON_HistoryRecord&
1884          );
1885   bool EndWrite3dmHistoryRecordTable();
1886 
1887   bool BeginRead3dmHistoryRecordTable();
1888 
1889   /*
1890   Returns:
1891            0 at end of object table
1892            1 if object is read
1893           -1 if file is corrupt
1894   */
1895   int  Read3dmHistoryRecord(
1896           class ON_HistoryRecord*&
1897           );
1898   bool EndRead3dmHistoryRecordTable();
1899 
1900   ///////////////////////////////////////////////////////////////////
1901   // Step 17: OPTIONAL - Write/Read 0 or more user tables
1902   //
1903 
1904   /*
1905   Description:
1906     Write the user table header information that must precede
1907     the user table information written by a plug-in.
1908   Parameters:
1909     plugin_id - [in]
1910     bSavingGoo - [in]
1911       Set to false if a plug-in will be used to write
1912       the user table.  Set to true if a user table written by
1913       a missing plug-in is being resaved. In this case,
1914       goo_3dm_version and goo_opennurbs_version must also be
1915       set.  In practice, you should use Write3dmAnonymousUserTableRecord()
1916       to handle writing "goo" and use this function only when
1917       the plug-in in present.
1918     goo_3dm_version - [in]
1919       If bSavingGoo is false, this parameter must be zero and
1920       ON_BinaryArchive::Archive3dmVersion() will be used.
1921       If bSavingGoo is true, this parameter must be the version of
1922       the 3dm archive (1,2,3,4,5,50,...) the plug-in code used to
1923       write the user table.
1924     goo_opennurbs_version - [in]
1925       If bSavingGoo is false, this parameter must be zero and
1926       ON_BinaryArchive::ArchiveOpenNURBSVersion() will be used.
1927       If bSavingGoo is true, this parameter must be the version
1928       of the opennurbs (YYYYMMDDN) the plug-in code used to
1929       write the user table.
1930   Returns:
1931     True if the the user information can be written.
1932     False if user informtion should not be written.
1933   */
1934   bool BeginWrite3dmUserTable(
1935     const ON_UUID& plugin_id,
1936     bool bSavingGoo,
1937     int goo_3dm_version,
1938     int goo_opennurbs_version
1939     );
1940 
1941   bool EndWrite3dmUserTable();
1942 
1943   /*
1944   Description:
1945     If Read3dmAnaonymousUserTable() was used to read ON_3dmGoo because a
1946     plug-in was not present, then use Write3dmAnonymousUserTableRecord()
1947     to put than information back into the archive.
1948     Write3dmAnonymousUserTableRecord() writes the entire record.
1949     Do NOT call BeginWrite3dmUserTable() / EndWrite3dmUserTable() when
1950     using Write3dmAnonymousUserTableRecord().
1951   Parameters:
1952     plugin_id - [in]
1953     goo_version - [in]
1954       The version of the archive (1,2,3,4,5,50,...) that was used when
1955       the plug-in wrote the user table.
1956     goo_opennurbs_version - [in]
1957       The version of opennurbs ( YYYMMDDN ) that was used when the
1958       plug-in wrote the user table.
1959     goo - [in]
1960   Returns:
1961     True if the goo was written or skipped because it could not be robustly
1962     saved.  False if a catastrophic IO error occured.
1963   */
1964   bool Write3dmAnonymousUserTableRecord(
1965     const ON_UUID& plugin_id,
1966     int goo_3dm_version,
1967     int goo_opennurbs_version,
1968     const ON_3dmGoo& goo
1969     );
1970 
1971   // OBSOLETE - use BeginWrite3dmUserTable(plugin_id, bSavingGoo, 3dm_version, opennurbs_version )
1972   ON_DEPRECATED bool BeginWrite3dmUserTable( const ON_UUID& );
1973 
1974   // OBSOLETE - use Write3dmAnonymousUserTableRecord(plugin_id, ..., goo)
1975   ON_DEPRECATED bool Write3dmAnonymousUserTable( const ON_3dmGoo& );
1976 
1977   /*
1978   Parameters:
1979     plugin_id - [out]
1980       id of plug-in that wrote the user table
1981     bLastSavedAsGoo - [out]
1982       True if this table was saved into this archive as goo because
1983       the plug-in was not present at the time of the save.
1984     archive_3dm_version - [out]
1985       Version of the archive the plug-in wrote to.  When bLastSavedAsGoo
1986       is true, this number can be different from Archive3dmVersion().
1987     archive_opennurbs_version - [out]
1988       Version of opennurbs the plug-in used to write the archive.
1989       When bLastSavedAsGoo is true, this number can be different
1990       from ArchiveOpenNURBSVersion().
1991   Returns:
1992     False when there are no more user tables or an IO error occurs.
1993   */
1994   bool BeginRead3dmUserTable(
1995     ON_UUID& plugin_id,
1996     bool* bLastSavedAsGoo,
1997     int* archive_3dm_version,
1998     int* archive_opennurbs_version
1999     );
2000 
2001   /*
2002   Description:
2003     If the plug-in that wrote the user table is not present and you need
2004     to read and resave the user table, then use Read3dmAnonymousUserTable()
2005     to load the information into "goo".
2006     If you do not need to resave the information, then simply call EndRead3dmUserTable()
2007     to skip over this table.
2008   */
2009   bool Read3dmAnonymousUserTable(
2010     int archive_3dm_version,
2011     int archive_opennurbs_version,
2012     ON_3dmGoo& goo
2013     );
2014 
2015   bool EndRead3dmUserTable();
2016 
2017   // OBSOLETE - use BeginRead3dmUserTable( plugin_id, bLastSavedAsGoo, archive_3dm_version, ... )
2018   ON_DEPRECATED bool BeginRead3dmUserTable(
2019     ON_UUID&
2020     );
2021 
2022   // OBSOLETE - use Read3dmAnonymousUserTable( archive_3dm_version, archive_opennurbs_version, goo )
2023   ON_DEPRECATED bool Read3dmAnonymousUserTable( ON_3dmGoo& );
2024 
2025 
2026 
2027 
2028   ///////////////////////////////////////////////////////////////////
2029   // Step 18: REQUIRED when writing / OPTIONAL when reading
2030   //         Write end of file marker.  This information is primarily
2031   //         used when debugging files to make sure the end of the file
2032   //         hasn't been cut off.
2033   //
2034 
2035   // Description:
2036   //   Writes a TCODE_ENDOFFILE chunk that contains the number
2037   //   of bytes in the archive.
2038   //
2039   // Returns:
2040   //   true if successful, false if unable to write to archive.
2041   bool Write3dmEndMark();
2042 
2043   // Description:
2044   //   Checks for a TCODE_ENDOFFILE chunk at the current position.
2045   //   If it finds one, it reads it and returns the number
2046   //   of bytes in the archive.  Comparing this number with
2047   //   the current file position can help detect files that
2048   //   have been damaged by loosing sections.
2049   //
2050   // Parameters:
2051   //   sizeof_archive - [out] number of bytes written to archive
2052   //
2053   // Returns:
2054   //   true if successful, false if unable to find or read
2055   //   a TCODE_ENDOFFILE chunk.
2056   bool Read3dmEndMark(
2057            std::size_t* // sizeof_archive
2058            );
2059 
2060   ///////////////////////////////////////////////////////////////////
2061   ///////////////////////////////////////////////////////////////////
2062   // Low level tools to  Write/Read chunks. See opennurbs_3dm.h for details
2063   // about the structure of chunks.  Every chunk must begin with a
2064   // call to BeginWrite/ReadChunk().
2065   // If BeginWriteChunk()/BeginReadChunk() returns true, then
2066   // you must call EndWrite/ReadChunk() or cease using the archive.
2067 
2068   // Description:
2069   //   Writes a chunk header containing 4 byte typecode and value.
2070   //
2071   // Parameters:
2072   //   typecode - [in] a TCODE_* number from opennurbs_3dm.h
2073   //   value    - [in] if (typecode&TCODE_SHORT) is nonzero, then
2074   //              this is the value to be saved.  Othewise, pass
2075   //              a zero and the EndWrite3dmChunk() call will
2076   //              store the length of the chunk.
2077   //
2078   // Returns:
2079   //   true if write was successful.
2080   bool BeginWrite3dmChunk(
2081         unsigned int, // typecode
2082         int // value
2083         );
2084 
2085   bool BeginWrite3dmBigChunk(
2086         ON__UINT32 typecode,
2087         ON__INT64 value
2088         );
2089 
2090   /*
2091   Description:
2092     Begins writing a chunk.
2093   Parameters:
2094     tcode - [in] chunk's typecode from opennurbs_3dm.h.  This cannot be a short tcode.
2095     major_version - [in] ( >= 1)
2096     minor_version - [in] ( >= 0 )
2097   Returns:
2098     True if input was valid and chunk was started.  In this case
2099     You must call EndWrite3dmChunk(), even if something goes wrong
2100     while you attempt to write the contents of the chunk.
2101     False if input was not valid or the write failed.
2102   */
2103   bool BeginWrite3dmChunk(
2104         unsigned int tcode,
2105         int major_version,
2106         int minor_version
2107         );
2108 
2109 
2110   // updates length in chunk header
2111   bool EndWrite3dmChunk();
2112 
2113   bool Write3dmGoo( const ON_3dmGoo& ); // call to write "goo"
2114 
2115   // OBSOLETE - Use BeginRead3dmBigChunk()
2116   ON_DEPRECATED bool BeginRead3dmChunk(
2117         unsigned int*,   // typecode from opennurbs_3dm.h
2118         int*             // value
2119         );
2120 
2121   // When the end of the 3dm file is reached, BeginReadChunk() will
2122   // return true with a typecode of TCODE_ENDOFFILE.
2123   bool BeginRead3dmBigChunk(
2124         unsigned int*,   // typecode from opennurbs_3dm.h
2125         ON__INT64*       // value
2126         );
2127   /*
2128   Description:
2129     Begins reading a chunk that must be in the archive at this location.
2130   Parameters:
2131     expected_tcode - [in] chunk's typecode from opennurbs_3dm.h
2132     major_version - [out]
2133     minor_version - [out]
2134   Returns:
2135     True if beginning of the chunk was read.  In this case
2136     You must call EndRead3dmChunk(), even if something goes wrong
2137     while you attempt to read the interior of the chunk.
2138     False if the chunk did not exist at the current location in the file.
2139   */
2140   bool BeginRead3dmChunk(
2141         unsigned int expected_tcode,
2142         int* major_version,
2143         int* minor_version
2144         );
2145 
2146   /*
2147   Description:
2148     Calling this will skip rest of stuff in chunk if it was only partially read.
2149   Parameters:
2150     bSupressPartiallyReadChunkWarning - [in]
2151       Generally, a call to ON_WARNING is made when a chunk is partially
2152       read.  If bSupressPartiallyReadChunkWarning is true, then
2153       no warning is issued for partially read chunks.
2154   */
2155   bool EndRead3dmChunk();
2156   bool EndRead3dmChunk(bool bSupressPartiallyReadChunkWarning);
2157 
2158 
2159   ///////////////////////////////////////////////////////////////////
2160   //
2161   // Tools for dictionary IO (used in .NET)
2162   //
2163 
2164   /*
2165   Description:
2166     Begins writing a dictionary.
2167   Parameters:
2168     dictionary_id - [in]
2169     version - [in]
2170       It is suggested that you use YYYYMMDD as the version number.
2171     dictionary_name - [in]
2172       You may pass NULL.
2173   Remarks:
2174     Begins a new chunk with tcode TCODE_DICTIONARY and then writes
2175     a TCODE_DICTIONARY_ID chunk containing the id, version and name.
2176     After calling this function, you may either write entries by
2177     calling
2178       BeginWriteDictionaryEntry();
2179       write entry definition...
2180       EndWriteDictionaryEntry();
2181     or you may finish writing the dictionay by calling
2182       EndWriteDictionary();
2183   */
2184   bool BeginWriteDictionary(
2185           ON_UUID dictionary_id,
2186           unsigned int version,
2187           const wchar_t* dictionary_name
2188           );
2189   /*
2190   Description:
2191     Begins writing a dictionary entry.
2192   Parameters:
2193     de_type - [in]
2194     entry_name - [in]
2195   Returns:
2196     true
2197       Entry header was written and you must call EndWriteDictionary()
2198       after writing the entry data.
2199     false
2200       Failed to write entry header.  Do not call EndWriteDictionary().
2201   Remarks:
2202     Begins a new chunk with tcode TCODE_DICTIONARY_ENTRY,
2203     then writes the int, and then writes the string.
2204   */
2205   bool EndWriteDictionary();
2206 
2207   /*
2208   Description:
2209     Begins writing a dictionary entry.
2210   Parameters:
2211     de_type - [in]
2212     entry_name - [in]
2213   Returns:
2214     true
2215       Entry header was written and you must call EndWriteDictionary()
2216       after writing the entry data.
2217     false
2218       Failed to write entry header.  Do not call EndWriteDictionary().
2219   Remarks:
2220     Begins a new chunk with tcode TCODE_DICTIONARY_ENTRY,
2221     then writes the int, and then writes the string.
2222   */
2223   bool BeginWriteDictionaryEntry(
2224           int de_type,
2225           const wchar_t* entry_name
2226           );
2227   bool EndWriteDictionaryEntry();
2228 
2229   bool BeginReadDictionary(
2230           ON_UUID* dictionary_id,
2231           unsigned int* version,
2232           ON_wString& dictionary_name
2233           );
2234   bool EndReadDictionary();
2235 
2236   /*
2237   Description:
2238     Begin reading a dictionary entry.
2239   Parameters:
2240     de_type - [out]
2241     entry_name - [out]
2242   Returns:
2243     0: serious IO error
2244     1: success
2245         read information and then call EndReadDictionaryEntry()
2246     2: at end of dictionary
2247   */
2248   int BeginReadDictionaryEntry(
2249           int* de_type,
2250           ON_wString& entry_name
2251           );
2252   bool EndReadDictionaryEntry();
2253 
2254   bool Read3dmGoo( ON_3dmGoo& ); // Call to read "goo"
2255 
2256   // OBSOLETE - Use PeekAt3dmBigChunkType()
2257   ON_DEPRECATED bool PeekAt3dmChunkType( // does not change file position
2258         unsigned int*,   // typecode from opennurbs_3dm.h
2259         int*             // value
2260         );
2261 
2262   bool PeekAt3dmBigChunkType( // does not change file position
2263         ON__UINT32* typecode,
2264         ON__INT64* big_value
2265         );
2266 
2267   bool Seek3dmChunkFromStart(
2268         // beginning at the start of the active chunk, search portion of
2269         // archive included in active chunk for the start of a subchunk
2270         // with the specified type.
2271         // if true is returned, then the position is set so the next call to
2272         // BeginRead3dmChunk() will read a chunk with the specified typecode
2273         unsigned int    // typecode from opennurbs_3dm.h
2274         );
2275   bool Seek3dmChunkFromCurrentPosition(
2276         // beginning at the current position, search portion of archive
2277         // included in active chunk for the start of a subchunk with the
2278         // specified type.
2279         // if true is returned, then the position is set so the next call to
2280         // BeginRead3dmChunk() will read a chunk with the specified typecode
2281         unsigned int    // typecode from opennurbs_3dm.h
2282         );
2283 
2284   // A chunk version is a single byte that encodes a major.minor
2285   // version number.  Useful when creating I/O code for 3dm chunks
2286   // that may change in the future.  Increment the minor version
2287   // number if new information is added to the end of the chunk.
2288   // Increment the major version if the format of the chunk changes
2289   // in some other way.
2290   bool Write3dmChunkVersion(
2291     int, // major // 0 to 15
2292     int  // minor // 0 to 16
2293     );
2294   bool Read3dmChunkVersion(
2295     int*, // major // 0 to 15
2296     int*  // minor // 0 to 16
2297     );
2298 
2299   /*
2300   Description:
2301     Low level tool to writes user data attached to the
2302     object.  This function should never be called
2303     directly.
2304   Parameters:
2305     object - [in]
2306   Returns:
2307     True if successful.
2308   */
2309   bool WriteObjectUserData( const ON_Object& object );
2310 
2311   /*
2312   Description:
2313     Low level tool to read user data and attach it to
2314     the object.  This function should never be called
2315     directly.
2316   Parameters:
2317     object - [in/out]
2318   Returns:
2319     True if successful.
2320   */
2321   bool ReadObjectUserData( ON_Object& object );
2322 
2323   /*
2324   Description:
2325     If a 3dm archive is being read or written, then this is the
2326     version of the 3dm archive format (1, 2, 3, 4 or 5).
2327   Returns:
2328     @untitle table
2329     0     a 3dm archive is not being read/written
2330     1     a version 1 3dm archive is being read/written
2331     2     a version 2 3dm archive is being read/written
2332     3     a version 3 3dm archive is being read/written
2333     4     a version 4 3dm archive is being read/written
2334     5     an old version 5 3dm archive is being read
2335     50    a version 5 3dm archive is being read/written
2336   See Also:
2337     ON_BinaryArchive::ArchiveOpenNURBSVersion
2338   */
2339   int Archive3dmVersion() const;
2340 
2341   /*
2342   Description:
2343     If a 3dm archive is being read, then this is the version
2344     of openNURBS that was used to write the archive.  This value
2345     is only available after ON_BinaryArchive::Read3dmProperties
2346     is called.
2347   See Also:
2348     ON_BinaryArchive::Archive3dmVersion
2349     ON_BinaryArchive::Read3dmProperties
2350   Returns:
2351     Version of openNURBS used to write the archive.  The openNURBS
2352     version is the value returned by ON::Version.
2353   See Also:
2354     ON::Version
2355     ON_BinaryArchive::Read3dmProperties
2356     ON_BinaryArchive::Archive3dmVersion
2357   Remarks:
2358     This value is rarely needed.  You probably want to
2359     use ON_BinaryArchive::Archive3dmVersion.
2360   */
2361   int ArchiveOpenNURBSVersion() const;
2362 
2363   /*
2364   Description:
2365     When a 3dm archive is saved from an MFC application that
2366     supports Windows linking/embedding, the first 5kb to 1mb
2367     of the file contains information that is put there by MFC.
2368     ArchiveStartOffset() returns the offset into the file where
2369     the 3dm archive actually begins. The call to
2370     ON_BinaryArchive::Read3dmStartSection() calculates this
2371     offset and stores the value in m_3dm_start_section_offset.
2372   Returns:
2373     Offset into the binary "file" where the actual 3dm archive
2374     begins.
2375   Remarks:
2376     Generally, this value can be ignored. This function is
2377     a diagnostice tool that is used to analyzed damaged files.
2378   */
2379   std::size_t ArchiveStartOffset() const;
2380 
2381   enum table_type
2382   {
2383     no_active_table = 0,
2384     properties_table,
2385     settings_table,
2386     bitmap_table,
2387     texture_mapping_table,
2388     material_table,
2389     linetype_table,
2390     layer_table,
2391     light_table,
2392     object_table,
2393     group_table,
2394     font_table,
2395     dimstyle_table,
2396     hatchpattern_table,
2397     instance_definition_table,
2398     historyrecord_table,
2399     user_table
2400   };
2401 
2402   /*
2403   Description:
2404     Expert user function for reading damaged files.
2405   Parameters:
2406     chunk - [out] current chunk.
2407   Returns:
2408     Level of the chunk or 0 if there is no current
2409     chunk.
2410   */
2411   int GetCurrentChunk(ON_3DM_CHUNK& chunk) const;
2412   int GetCurrentChunk(ON_3DM_BIG_CHUNK& big_chunk) const;
2413 
2414   /*
2415   Description:
2416     Expert user function for reading damaged files.  The search starts
2417     at the beginning of the file.
2418   Parameters:
2419     tcode_table - [in] typecode of the table
2420     tcode_record - [in] typecode of the record
2421     class_uuid - [in] id of the opennurbs class in the record
2422     min_length_data - [in] minimum size of the opennurbs class data
2423   Returns:
2424     True if the table start is found.  In this case the current
2425     position of the archive is at the start of the table and
2426     the standared BeginRead3dm...Table() function can be used.
2427     False if the table start is not found.
2428   */
2429   bool FindTableInDamagedArchive(
2430           unsigned int tcode_table,
2431           unsigned int tcode_record,
2432           ON_UUID class_uuid,
2433           int min_length_data
2434           );
2435 
2436   /*
2437   Description:
2438     Expert user function for studying contents of a file.
2439     The primary use is as an aid to help dig through files
2440     that have been damaged (bad disks, transmission errors, etc.)
2441     If an error is found, a line that begins with the word
2442     "ERROR" is printed.
2443   Parameters:
2444     text_log - [in] place to print informtion
2445     recursion_depth - [in] simply a counter
2446         to aid in debugging.
2447   Returns:
2448     0 if something went wrong, otherwise the typecode
2449     of the chunk that was just studied.
2450   */
2451   unsigned int
2452   Dump3dmChunk(
2453         ON_TextLog& text_log,
2454         int recursion_depth = 0
2455         );
2456 
2457 protected:
2458 
2459   /*
2460   Description:
2461     Works like the C runtrim fread().
2462   Returns:
2463     actual number of bytes read (like fread())
2464   */
2465   virtual
2466   std::size_t Read( std::size_t, void* ) = 0;
2467 
2468   /*
2469   Description:
2470     Works like the C runtrim fwrite().
2471   Returns:
2472     actual number of bytes written (like fwrite())
2473   */
2474   virtual
2475   std::size_t Write( std::size_t, const void* ) = 0;
2476 
2477   /*
2478   Description:
2479     Force Write() to flush any buffered data to physical archive.
2480   Returns:
2481     True if successful or if there is nothing to flush.  False if
2482     information could not be flushed.
2483   */
2484   virtual
2485   bool Flush() = 0;
2486 
2487   /*
2488   Applications (like Rhino) override this function to load plug-ins
2489   Description:
2490     When ON_BinaryArchive::ReadObject() encounters userdata and
2491     the user data class id is not present,  LoadUserDataApplication
2492     is called to load the application that created user data.
2493   Returns:
2494     0 - could not load the application
2495     1 - successfully loaded the application
2496     2 - the application was already loaded
2497   */
2498   virtual
LoadUserDataApplication(ON_UUID)2499   int LoadUserDataApplication(
2500     ON_UUID /*application_id*/
2501     )
2502   {
2503     return 0;
2504   }
2505 
2506   bool SetArchive3dmVersion(int);
2507 
2508 private:
2509   // 16 bit integer IO
2510   bool WriteInt8( std::size_t, const ON__INT8* );
2511   bool ReadInt8( std::size_t, ON__INT8* );
2512 
2513   // 16 bit integer IO
2514   bool WriteInt16( std::size_t, const ON__INT16* );
2515   bool ReadInt16( std::size_t, ON__INT16* );
2516 
2517   // 32 bit integer IO
2518   bool WriteInt32( std::size_t, const ON__INT32* );
2519   bool ReadInt32( std::size_t, ON__INT32* );
2520 
2521   // 64 bit integer IO
2522   bool WriteInt64( std::size_t, const ON__INT64* );
2523   bool ReadInt64(  std::size_t, ON__INT64* );
2524 
2525   bool BeginWrite3dmTable(
2526     unsigned int // tcode
2527     );
2528   bool EndWrite3dmTable(
2529     unsigned int // tcode
2530     );
2531   bool BeginRead3dmTable(
2532     unsigned int // tcode
2533     );
2534   bool EndRead3dmTable(
2535     unsigned int // tcode
2536     );
2537 
2538   bool Read3dmV1Layer( ON_Layer*& );
2539   int  Read3dmV1Light(  // returns 0 at end of light table
2540                       //         1 light successfully read
2541                       //        -1 if file is corrupt
2542             ON_Light**, // light returned here
2543             ON_3dmObjectAttributes* // optional - if NOT NULL, object attributes are
2544                                     //            returned here
2545             );
2546   int Read3dmV1Material( ON_Material** );
2547   int  Read3dmV1Object( // returns 0 at end of object table
2548                       //         1 if object is read
2549                       //         2 if object is skipped because it does not match filter
2550                       //        -1 if file is corrupt
2551           ON_Object**, // object returned here (NULL if skipped)
2552           ON_3dmObjectAttributes*, // optional - if NOT NULL, object attributes are
2553                                    //            returned here
2554           unsigned int = 0 // optional filter made by setting ON::object_type bits
2555           );  // returns NULL at end of object table
2556 
2557   bool Read3dmV1AttributesOrMaterial(
2558             ON_3dmObjectAttributes*,    // attributes,
2559             ON_Material*,      // material,
2560             ON_BOOL32&,             // bHaveMat
2561             unsigned int,      // end_mark_tcode
2562             class ON__3dmV1_XDATA* = 0 // v1 "xdata"
2563             );
2564   bool Read3dmV1String( ON_String& );
2565   int  Read3dmV1LayerIndex( const char* ) const;
2566 
2567 public:
2568   // helpers for reading V1 objects
2569   bool ReadV1_TCODE_RH_POINT(ON_Object**,ON_3dmObjectAttributes*);
2570   bool ReadV1_TCODE_MESH_OBJECT(ON_Object**,ON_3dmObjectAttributes*);
2571   bool ReadV1_TCODE_LEGACY_CRV(ON_Object**,ON_3dmObjectAttributes*);
2572   bool ReadV1_TCODE_LEGACY_FAC(ON_Object**,ON_3dmObjectAttributes*);
2573   bool ReadV1_TCODE_LEGACY_SHL(ON_Object**,ON_3dmObjectAttributes*);
2574   bool ReadV1_TCODE_RHINOIO_OBJECT_NURBS_CURVE(ON_Object**,ON_3dmObjectAttributes*);
2575   bool ReadV1_TCODE_RHINOIO_OBJECT_NURBS_SURFACE(ON_Object**,ON_3dmObjectAttributes*);
2576   bool ReadV1_TCODE_RHINOIO_OBJECT_BREP(ON_Object**,ON_3dmObjectAttributes*);
2577   bool ReadV1_TCODE_ANNOTATION(unsigned int,ON_Object**,ON_3dmObjectAttributes*);
2578 
2579 private:
2580   ON::archive_mode Mode() const; // current read/write mode
2581   void UpdateCRC( std::size_t, const void* );
2582   int ReadObjectHelper(ON_Object**);
2583 
2584   int m_3dm_version;
2585   int m_3dm_v1_layer_index;
2586   int m_3dm_v1_material_index;
2587 
2588   // The bits in m_error_message_mask are used to mask errors
2589   // when we know we are doing something that may generate an
2590   // error.
2591   //
2592   // bit 0x00000001
2593   //   V1 files do not have a table structure and are read using
2594   //   multiple passes and there are valid situations where a
2595   //   4 byte read is attempted at the end of a file.
2596   //
2597   // bit 0x00000002
2598   //   Some v1 files do not have an end mark.  When reading
2599   //   these v1 files bit 0x02 is set.
2600   //
2601   // bit 0x00000004
2602   //   Requested read may go beyond end of file.
2603   //   One situation where this happens is when a table is not at the
2604   //   expected location in a file,
2605 
2606   unsigned int m_error_message_mask;
2607 protected:
2608   unsigned int ErrorMessageMask() const;
2609   /*
2610   Paramters:
2611     sizeof_request - [in]
2612       value of count parameter passed to virtual Read() function.
2613     sizeof_read - [in]
2614       number of bytes actually read by the virtual Read() function.
2615   Returns:
2616     True if a call to Read() is permitted to ask for more bytes
2617     than are left in the file.  This value varies as the file
2618     is read and must be checked at each failure.
2619   */
2620   bool MaskReadError( ON__UINT64 sizeof_request, ON__UINT64 sizeof_read ) const;
2621 private:
2622 
2623 
2624   // When a 3DM archive is read, m_3dm_opennurbs_version records the version of
2625   // OpenNURBS used to create the archive.  Otherwise, m_3dm_opennurbs_version
2626   // is zero.
2627   //
2628   // Read3dmProperties() sets this to the version of OpenNURBS that was
2629   // used to write file file.  If the file was created using a version
2630   // of OpenNURBS before 200012210, this number will be zero.
2631   //
2632   // Write3dmProperties() stores the value returned by ON::Version() in
2633   // the archive's properties table.
2634   friend void ON_SetBinaryArchiveOpenNURBSVersion(ON_BinaryArchive&,int);
2635   int m_3dm_opennurbs_version;
2636 
2637   // When a 3dm archive is saved from an MFC application that supports
2638   // Windows linking/embedding, the first 5kb to 1mb of the file contains
2639   // information that is put there by MFC.  m_3dm_start_section_offset
2640   // records the offset into the file where the 3dm archive actually begins.
2641   std::size_t m_3dm_start_section_offset;
2642 
2643   table_type m_active_table;
2644 
2645   table_type TableTypeFromTypecode( unsigned int ); // table type from tcode
2646 
2647   ON_SimpleArray<ON_3DM_BIG_CHUNK> m_chunk;
2648 
2649   // stack of chunks
2650   bool PushBigChunk( ON__UINT32 typecode, ON__INT64 value );
2651 
2652   bool WriteChunkTypecode( ON__UINT32 );
2653   bool ReadChunkTypecode( ON__UINT32* );
2654   bool WriteChunkValue( ON__UINT32 typecode, ON__INT64 );
2655   bool WriteChunkLength( ON__UINT64 );
2656   bool ReadChunkValue( ON__UINT32 typecode, ON__INT64* value64 );
2657   bool FindMisplacedTable(
2658         ON__UINT64 filelength,
2659         const ON__UINT32 table_tocde,
2660         const ON__UINT32 table_record_record,
2661         const ON_UUID class_uuid,
2662         const ON__UINT64 min_length_data
2663         );
2664 
2665   bool ReadObjectUserDataAnonymousChunk(
2666           const ON__UINT64 length_TCODE_ANONYMOUS_CHUNK,
2667           const int archive_3dm_version,
2668           const int archive_opennurbs_version,
2669           class ON_UserData* ud );
2670 
2671 public:
2672   std::size_t SizeofChunkLength() const;
2673 
2674 private:
2675   bool WriteEOFSizeOfFile( ON__UINT64 );
2676   bool ReadEOFSizeOfFile( ON__UINT64* );
2677 
2678   bool m_bDoChunkCRC; // true if active chunk crc status should be checked
2679                       // and updated.
2680   int m_bad_CRC_count; // number of chunks that have a bad crc
2681 
2682 
2683 private:
2684   // compressed buffer I/O uses zlib 1.1.3 inflate()/deflate()
2685   struct
2686   {
2687     ON::archive_mode mode; // ON::read = read and inflate,  ON::write = deflate and write
2688     enum
2689     {
2690       sizeof_x_buffer = 16384
2691     };
2692     unsigned char    buffer[sizeof_x_buffer];
2693     z_stream         strm;
2694   } m_zlib;
2695 
2696   // returns number of bytes written
2697   std::size_t WriteDeflate(
2698         std::size_t,         // sizeof uncompressed input data
2699         const void*  // uncompressed input data
2700         );
2701   bool ReadInflate(
2702         std::size_t,  // sizeof uncompressed input data
2703         void* // buffer to hold uncompressed data
2704         );
2705   bool CompressionInit();
2706   void CompressionEnd();
2707 
2708 private:
2709   // endian-ness of the cpu reading this file.
2710   // 3dm files are alwasy saved with little endian byte order.
2711   ON::endian m_endian;
2712 
2713   ON::archive_mode m_mode;
2714 
2715   // 3dm write options
2716   bool m_bSaveUserData; // true to save user data (increases file size)
2717   bool m_bSavePreviewImage;    // true to save 200x200 preview bitmap (increases file size)
2718   bool m_bEmbedTextureBitmaps; // true to embed texture, bump, trace, and wallpaper bitmaps (increases file size)
2719   bool m_bSaveRenderMeshes;    // true to save meshes used to render B-rep objects (increases file size)
2720   bool m_bSaveAnalysisMeshes;  // true to save meshes used in surface analysis (increases file size)
2721 
2722   // ids of plug-ins that support saving older (V3) versions
2723   // of user data.  This information is filled in from the
2724   // list of plug-ins passed in whenteh settings are saved.
2725   ON_SimpleArray< ON_UUID > m_V3_plugin_id_list;
2726 
2727   struct ON__3dmV1LayerIndex* m_V1_layer_list;
2728 
2729   // prohibit default construction, copy construction, and operator=
2730   ON_BinaryArchive();
2731   ON_BinaryArchive( const ON_BinaryArchive& ); // no implementation
2732   ON_BinaryArchive& operator=( const ON_BinaryArchive& ); // no implementation
2733 
2734 };
2735 
2736 class ON_CLASS ON_3dmGoo
2737 {
2738   // used to store goo
2739 public:
2740   ON_3dmGoo();
2741   ~ON_3dmGoo();
2742   ON_3dmGoo( const ON_3dmGoo& );
2743   ON_3dmGoo& operator=( const ON_3dmGoo& );
2744 
2745   void Dump(ON_TextLog&) const;
2746 
2747   unsigned int m_typecode;
2748   int m_value;
2749   unsigned char* m_goo;
2750   ON_3dmGoo* m_next_goo;
2751   ON_3dmGoo* m_prev_goo;
2752 };
2753 
2754 
2755 class ON_CLASS ON_BinaryFile : public ON_BinaryArchive
2756 {
2757 public:
2758   ON_BinaryFile( ON::archive_mode );
2759 
2760   /*
2761   Description:
2762     Create an ON_BinaryArchive that reads/writes from an ordinary file.
2763   Parameters:
2764     mode - [in]
2765     fp - [in]
2766       If a file is being read, fp is the pointer returned
2767       from ON_FileStream::Open(...,"rb").
2768       If a file is being written, fp is the pointer returned
2769       from ON_FileStream::Open(...,"wb").
2770   */
2771   ON_BinaryFile( ON::archive_mode, FILE* fp );
2772 
2773   virtual ~ON_BinaryFile();
2774 
2775   // ON_BinaryArchive overrides
2776   std::size_t CurrentPosition() const;
2777   bool SeekFromCurrentPosition(int);
2778   bool SeekFromStart(std::size_t);
2779   bool AtEnd() const;
2780 
2781   // fseek from end (since the file has an end)
2782   bool SeekFromEnd( int );
2783 
2784   //////////
2785   // To use custom memory buffering instead of relying
2786   // on fread()/fwrite()'s build in buffering, call
2787   // EnableMemoryBuffer() with the buffer size immediately
2788   // after constructing the ON_BinaryFile.  There appear
2789   // to be enough bugs in existing Windows NT/2000 NETWORK
2790   // I/O that using this hack will speed up I/O by factors
2791   // of 10 to 100.
2792   void EnableMemoryBuffer(
2793          int=16384 // capacity of memory buffer
2794          );
2795 
2796 protected:
2797   std::size_t Read( std::size_t, void* );
2798   std::size_t Write( std::size_t, const void* );
2799   bool Flush();
2800 
2801 private:
2802   // Implementation
2803   FILE* m_fp;
2804 
2805   // if m_memory_buffer_capacity is zero, then Write() uses
2806   // fwrite() directly.  If m_memory_buffer_capacity is
2807   // greater than zero, then Write() buffers its results
2808   // into m_memory_buffer.  This is provided to work around
2809   // bugs in some networks that result in extremely slow
2810   // performance when seeking is used.
2811   std::size_t m_memory_buffer_capacity;
2812   std::size_t m_memory_buffer_size;
2813   std::size_t m_memory_buffer_ptr;
2814   unsigned char* m_memory_buffer;
2815 
2816 private:
2817   // prohibit default construction, copy construction, and operator=
2818   ON_BinaryFile( ); // no implementation
2819   ON_BinaryFile( const ON_BinaryFile& ); // no implementation
2820   ON_BinaryFile& operator=( const ON_BinaryFile& ); // no implementation
2821 };
2822 
2823 class ON_CLASS ON_BinaryArchiveBuffer : public ON_BinaryArchive
2824 {
2825 public:
2826   /*
2827   Description:
2828     Create an ON_BinaryArchive that reads/writes from an ON_Buffer.
2829   Parameters:
2830     mode - [in]
2831     buffer - [in]
2832   Remarks:
2833     If a non-null buffer is specifed, then do not call SetBuffer()
2834   */
2835   ON_BinaryArchiveBuffer( ON::archive_mode, ON_Buffer* buffer );
2836 
2837   virtual ~ON_BinaryArchiveBuffer();
2838 
2839   /*
2840   Description:
2841     If the ON_BinaryArchiveBuffer class is created with the constructor
2842     that has a single "mode" parameter, then use SetBuffer()
2843     to specify the buffer to read/write from before using
2844     the ON_BinaryArchiveBuffer.
2845   Parameters:
2846     buffer - [in]
2847   Returns:
2848     True if the buffer is set.  Once the buffer is set it
2849     cannot be changed.
2850   */
2851   bool SetBuffer( ON_Buffer* buffer );
2852 
2853   /*
2854   Returns:
2855     Buffer being read/written.
2856   */
2857   ON_Buffer* Buffer() const;
2858 
2859   // virtual ON_BinaryArchive overrides
2860   std::size_t CurrentPosition() const;
2861   bool SeekFromCurrentPosition(int);
2862   bool SeekFromStart(std::size_t);
2863   bool AtEnd() const;
2864 
2865   bool SeekFromEnd( ON__INT64 );
2866 
2867 protected:
2868   std::size_t Read( std::size_t, void* );
2869   std::size_t Write( std::size_t, const void* );
2870   bool Flush();
2871 
2872 private:
2873   // Buffer being read/written.
2874   ON_Buffer* m_buffer;
2875 
2876 private:
2877   // prohibit use - you should specify a buffer.
2878   ON_BinaryArchiveBuffer( ON::archive_mode );
2879 private:
2880   // prohibit default construction, copy construction, and operator=
2881   ON_BinaryArchiveBuffer( ); // no implementation
2882   ON_BinaryArchiveBuffer( const ON_BinaryArchiveBuffer& ); // no implementation
2883   ON_BinaryArchiveBuffer& operator=( const ON_BinaryArchiveBuffer& ); // no implementation
2884 };
2885 
2886 
2887 class ON_CLASS ON_Read3dmBufferArchive : public ON_BinaryArchive
2888 {
2889 public:
2890 
2891   /*
2892   Description:
2893     Construct an ON_BinaryArchive for reading information from a memory buffer.
2894   Parameters:
2895     sizeof_buffer - [in] size of buffer in bytes (>0)
2896     buffer - [in] memory buffer containing binary archive
2897     bCopyBuffer - [in]
2898       true - copy the input buffer.
2899           Useful when the buffer may be destroyed while this class is still in use.
2900       false - Do not copy the input buffer.
2901           In this case you are responsible for making certain the input buffer
2902           is valid while this class is in use.
2903     archive_3dm_version  - [in] (1,2,3,4 or 5)
2904     archive_opennurbs_version - [in] YYYYMMDDn
2905   */
2906   ON_Read3dmBufferArchive(
2907     std::size_t sizeof_buffer,
2908     const void* buffer,
2909     bool bCopyBuffer,
2910     int archive_3dm_version,
2911     int archive_opennurbs_version
2912     );
2913 
2914   ~ON_Read3dmBufferArchive();
2915 
2916   /*
2917   Returns:
2918      value of m_sizeof_buffer
2919   */
2920   std::size_t SizeOfBuffer() const;
2921 
2922   /*
2923   Returns:
2924      value of m_buffer
2925   */
2926   const void* Buffer() const;
2927 
2928   // ON_BinaryArchive overrides
2929   std::size_t CurrentPosition() const;
2930   bool SeekFromCurrentPosition(int);
2931   bool SeekFromStart(std::size_t);
2932   bool AtEnd() const;
2933 
2934 protected:
2935   // ON_BinaryArchive overrides
2936   std::size_t Read( std::size_t, void* ); // return actual number of bytes read (like fread())
2937   std::size_t Write( std::size_t, const void* );
2938   bool Flush();
2939 
2940 private:
2941   void* m_p;
2942   const unsigned char* m_buffer;
2943   std::size_t m_sizeof_buffer;
2944   std::size_t m_buffer_position;
2945   ON__INT_PTR m_reserved1;
2946   ON__INT_PTR m_reserved2;
2947   ON__INT_PTR m_reserved3;
2948   ON__INT_PTR m_reserved4;
2949 
2950 private:
2951   // prohibit use - no implementation
2952   ON_Read3dmBufferArchive();
2953   ON_Read3dmBufferArchive( const ON_Read3dmBufferArchive& );
2954   ON_Read3dmBufferArchive& operator=(const ON_Read3dmBufferArchive&);
2955 };
2956 
2957 class ON_CLASS ON_Write3dmBufferArchive : public ON_BinaryArchive
2958 {
2959 public:
2960 
2961   /*
2962   Description:
2963     Construct an ON_BinaryArchive for writing information to a memory buffer.
2964   Parameters:
2965     initial_sizeof_buffer - [in]
2966       initial size of buffer in bytes (>=0)
2967       If you are unable to estimate the size you will need, pass in zero.
2968     max_sizeof_buffer - [in]
2969       maximum size of buffer in bytes (>=0)
2970       If max_sizeof_buffer > 0 and the amount of information saved
2971       requires a buffer larger than this size, then writing fails.
2972       If max_sizeof_buffer <= 0, then no buffer size limits are enforced.
2973     archive_3dm_version  - [in] (0, ,2,3,4 or 50)
2974       Pass 0 or ON_BinaryArchive::CurrentArchiveVersion() to write the
2975       version of opennurbs archives used by lastest version of Rhino.
2976     archive_opennurbs_version - [in] YYYYMMDDn
2977   */
2978   ON_Write3dmBufferArchive(
2979     std::size_t initial_sizeof_buffer,
2980     std::size_t max_sizeof_buffer,
2981     int archive_3dm_version,
2982     int archive_opennurbs_version
2983     );
2984 
2985   ~ON_Write3dmBufferArchive();
2986 
2987   /*
2988   Returns:
2989      Size of the archive in bytes.
2990   */
2991   std::size_t SizeOfArchive() const;
2992 
2993   /*
2994   Returns:
2995      value of m_sizeof_buffer
2996   */
2997   std::size_t SizeOfBuffer() const;
2998 
2999   /*
3000   Returns:
3001      value of m_buffer.
3002      SizeOfArchive() reports the number of bytes
3003      written to this buffer.
3004      SizeOfBuffer() reports the number of bytes
3005      allocated in this buffer.
3006 
3007   */
3008   const void* Buffer() const;
3009 
3010   /*
3011   Returns:
3012     The pointer to the buffer and sets all
3013     members on this archive back to zero.
3014     The caller is responsible for calling onfree() on
3015     the pointer when finished with the buffer.
3016   */
3017   void* HarvestBuffer();
3018 
3019   // ON_BinaryArchive overrides
3020   std::size_t CurrentPosition() const;
3021   bool SeekFromCurrentPosition(int);
3022   bool SeekFromStart(std::size_t);
3023   bool AtEnd() const;
3024 
3025 protected:
3026   // ON_BinaryArchive overrides
3027   std::size_t Read( std::size_t, void* );
3028   std::size_t Write( std::size_t, const void* ); // return actual number of bytes written (like fwrite())
3029   bool Flush();
3030 
3031 private:
3032   void AllocBuffer(std::size_t);
3033   void* m_p;
3034   unsigned char* m_buffer;
3035   std::size_t m_sizeof_buffer;
3036   const std::size_t m_max_sizeof_buffer;
3037   std::size_t m_sizeof_archive;
3038   std::size_t m_buffer_position;
3039   ON__INT_PTR m_reserved1;
3040   ON__INT_PTR m_reserved2;
3041   ON__INT_PTR m_reserved3;
3042   ON__INT_PTR m_reserved4;
3043 
3044 private:
3045   // prohibit use - no implementation
3046   ON_Write3dmBufferArchive();
3047   ON_Write3dmBufferArchive( const ON_Write3dmBufferArchive& );
3048   ON_Write3dmBufferArchive& operator=(const ON_Write3dmBufferArchive&);
3049 };
3050 
3051 /*
3052 Description:
3053   Create a simple archive that contains a single geometric object.
3054 Parameters:
3055   archive - [in] destination archive.
3056   version - [in] (0, 2, 3, 4, or 50) format version.archive version number.
3057       Version 2 format can be read by Rhino 2 and Rhino 3.  Version
3058       3 format can be read by Rhino 3.
3059       Pass 0 or ON_BinaryArchive::CurrentArchiveVersion() to write
3060       the latest version of archives supported by Rhino.
3061   object - [in] object to be saved in the archive's object table.
3062       This is typically some type of ON_Curve, ON_Surface, ON_Mesh,
3063       or ON_Brep.
3064 Returns:
3065   @untitled table
3066   true     archive successfully written.
3067   false    archive not successfully written.
3068 Example:
3069 
3070           const char* filename = "myfile.3dm";
3071           FILE* fp = ON::OpenFile( filename, "wb" );
3072           ON_BinaryFile file( fp, ON::write3dm );
3073           ON_BOOL32 ok = ON_WriteArchive( archive, geometry );
3074           ON::CloseFile( fp );
3075 
3076 Remarks:
3077   The object table in the archive will contain a single
3078   object.
3079 */
3080 ON_DECL
3081 bool ON_WriteOneObjectArchive(
3082           ON_BinaryArchive& archive,
3083           int version,
3084           const ON_Object& object
3085           );
3086 
3087 #endif
3088 
3089