00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00019 FILE* ON_FileStream::Open( const wchar_t* filename, const wchar_t* mode )
00020 {
00021 FILE* fp = 0;
00022
00023 if ( 0 == filename || 0 == filename[0] || 0 == mode || 0 == mode[0] )
00024 return fp;
00025
00026 #if defined(ON_OS_WINDOWS)
00027 errno_t e = _wfopen_s(&fp,filename,mode);
00028 if ( 0 != e && 0 == fp )
00029 fp = 0;
00030 #else
00031
00032
00033 ON_String fnameUTF8(filename);
00034 ON_String modeUTF8(mode);
00035 fp = fopen(fnameUTF8,modeUTF8);
00036 #endif
00037
00038 return fp;
00039 }
00040
00041 FILE* ON_FileStream::Open( const char* filename, const char* mode )
00042 {
00043 FILE* fp = 0;
00044
00045 if ( 0 == filename || 0 == filename[0] || 0 == mode || 0 == mode[0] )
00046 return fp;
00047
00048 #if defined(ON_OS_WINDOWS)
00049 errno_t e = fopen_s(&fp,filename,mode);
00050 if ( 0 != e && 0 == fp )
00051 fp = 0;
00052 #else
00053 fp = fopen(filename,mode);
00054 #endif
00055
00056 return fp;
00057 }
00058
00059 int ON_FileStream::Close( FILE* fp )
00060 {
00061 return ( ( 0 != fp ) ? fclose(fp) : -1 );
00062 }
00063
00064 ON__INT64 ON_FileStream::CurrentPosition( FILE* fp )
00065 {
00066 if ( 0 == fp )
00067 return -1;
00068 #if defined(ON_OS_WINDOWS)
00069 return _ftelli64(fp);
00070 #else
00071 return ftell(fp);
00072 #endif
00073 }
00074
00075 bool ON_FileStream::SeekFromCurrentPosition( FILE* fp, ON__INT64 offset )
00076 {
00077 return ON_FileStream::Seek(fp,offset,SEEK_CUR);
00078 }
00079
00080 bool ON_FileStream::SeekFromStart( FILE* fp, ON__INT64 offset )
00081 {
00082 return ON_FileStream::Seek(fp,offset,SEEK_SET);
00083 }
00084
00085 bool ON_FileStream::SeekFromEnd( FILE* fp, ON__INT64 offset )
00086 {
00087 return ON_FileStream::Seek(fp,offset,SEEK_END);
00088 }
00089
00090 bool ON_FileStream::Seek( FILE* fp, ON__INT64 offset, int origin )
00091 {
00092 if ( 0 == fp )
00093 return false;
00094
00095 if ( origin < 0 || origin > 2 )
00096 return false;
00097
00098 if ( 0 == offset )
00099 return true;
00100
00101 #if defined(ON_OS_WINDOWS)
00102
00103 if ( 0 != _fseeki64(fp,offset,origin) )
00104 return false;
00105
00106 #else
00107
00108 const int i = 2147483646;
00109 const ON__INT64 i64 = i;
00110 while ( offset > i64 )
00111 {
00112 if ( 0 != fseek( fp, i, origin ) )
00113 return false;
00114 offset -= i64;
00115 }
00116 while ( offset < -i64 )
00117 {
00118 if ( 0 != fseek( fp, -i, origin ) )
00119 return false;
00120 offset += i64;
00121 }
00122 if ( 0 != offset )
00123 {
00124 int ioffset = (int)offset;
00125 if ( 0 != fseek( fp, ioffset, origin ) )
00126 return false;
00127 }
00128
00129 #endif
00130
00131 return true;
00132 }
00133
00134 ON__UINT64 ON_FileStream::Read( FILE* fp, ON__UINT64 count, void* buffer )
00135 {
00136 ON__UINT64 rc = 0;
00137 if ( 0 == fp || count <= 0 || 0 == buffer )
00138 return rc;
00139
00140 if ( count <= ON_MAX_SIZE_T )
00141 {
00142 rc = (ON__UINT64)fread(buffer,1,(size_t)count,fp);
00143 }
00144 else
00145 {
00146 size_t sz, szread;
00147 while ( count > 0 )
00148 {
00149 sz = ( count > ON_MAX_SIZE_T ) ? ON_MAX_SIZE_T : ((size_t)count);
00150 szread = fread(buffer,1,sz,fp);
00151 rc += szread;
00152 if ( szread != sz )
00153 break;
00154 count -= sz;
00155 buffer = ((unsigned char*)buffer) + sz;
00156 }
00157 }
00158
00159 return rc;
00160 }
00161
00162 ON__UINT64 ON_FileStream::Write( FILE* fp, ON__UINT64 count, const void* buffer )
00163 {
00164 ON__UINT64 rc = 0;
00165 if ( 0 == fp || count <= 0 || 0 == buffer )
00166 return rc;
00167
00168 if ( count <= ON_MAX_SIZE_T )
00169 {
00170 rc = fwrite(buffer,1,(size_t)count,fp);
00171 }
00172 else
00173 {
00174 size_t sz, szwrite;
00175 while ( count > 0 )
00176 {
00177 sz = ( count > ON_MAX_SIZE_T ) ? ON_MAX_SIZE_T : ((size_t)count);
00178 szwrite = fwrite(buffer,1,sz,fp);
00179 rc += szwrite;
00180 if ( szwrite != sz )
00181 break;
00182 count -= sz;
00183 buffer = ((unsigned char*)buffer) + sz;
00184 }
00185 }
00186
00187 return rc;
00188 }
00189
00190 bool ON_FileStream::Flush( FILE* fp )
00191 {
00192 if ( 0 == fp )
00193 return false;
00194 if ( 0 != fflush(fp) )
00195 return false;
00196 return true;
00197 }
00198
00199
00200 bool ON_FileStream::GetFileInformation(
00201 FILE* fp,
00202 ON__UINT64* file_size,
00203 ON__UINT64* file_create_time,
00204 ON__UINT64* file_last_modified_time
00205 )
00206 {
00207 bool rc = false;
00208
00209 if (file_size)
00210 *file_size = 0;
00211 if (file_create_time)
00212 *file_create_time = 0;
00213 if (file_last_modified_time)
00214 *file_last_modified_time = 0;
00215
00216 if ( fp )
00217 {
00218
00219 #if defined(ON_COMPILER_MSC)
00220
00221
00222 int fd = _fileno(fp);
00223 #if (_MSC_VER >= 1400)
00224
00225
00226
00227 struct _stat64 sb;
00228 memset(&sb,0,sizeof(sb));
00229 int fstat_rc = _fstat64(fd, &sb);
00230 #else
00231
00232
00233 struct _stat sb;
00234 memset(&sb,0,sizeof(sb));
00235 int fstat_rc = _fstat(fd, &sb);
00236 #endif
00237
00238 #else
00239
00240 int fd = fileno(fp);
00241 struct stat sb;
00242 memset(&sb,0,sizeof(sb));
00243 int fstat_rc = fstat(fd, &sb);
00244 #endif
00245
00246
00247 if (0 == fstat_rc)
00248 {
00249 if (file_size)
00250 *file_size = (ON__UINT64)sb.st_size;
00251 if (file_create_time)
00252 *file_create_time = (ON__UINT64)sb.st_ctime;
00253 if (file_last_modified_time)
00254 *file_last_modified_time = (ON__UINT64)sb.st_mtime;
00255 rc = true;
00256 }
00257 }
00258
00259 return rc;
00260 }
00261
00262
00263 class ON_ReadChunkHelper
00264 {
00265 public:
00266 ON_ReadChunkHelper(ON_BinaryArchive&);
00267 ~ON_ReadChunkHelper();
00268
00269 ON_BinaryArchive& m_binary_archive;
00270 bool m_bReadSuccess;
00271 ON__UINT32 m_chunk_tcode;
00272 ON__INT64 m_chunk_value;
00273
00274 private:
00275 bool m_bCallEndRead3dmChunk;
00276
00277 ON_ReadChunkHelper();
00278 ON_ReadChunkHelper(const ON_ReadChunkHelper&);
00279 ON_ReadChunkHelper& operator=(const ON_ReadChunkHelper&);
00280 };
00281
00282 ON_ReadChunkHelper::ON_ReadChunkHelper(ON_BinaryArchive& binary_archive)
00283 : m_binary_archive(binary_archive)
00284 , m_bReadSuccess(0)
00285 , m_chunk_tcode(0)
00286 , m_chunk_value(0)
00287 , m_bCallEndRead3dmChunk(0)
00288 {
00289 m_bReadSuccess = m_binary_archive.BeginRead3dmBigChunk(&m_chunk_tcode,&m_chunk_value);
00290 if ( m_bReadSuccess )
00291 m_bCallEndRead3dmChunk = true;
00292 }
00293
00294 ON_ReadChunkHelper::~ON_ReadChunkHelper()
00295 {
00296 if ( m_bReadSuccess && !m_binary_archive.EndRead3dmChunk() )
00297 m_bReadSuccess = false;
00298 }
00299
00300 bool ON_IsUnsignedChunkTypecode( ON__UINT32 typecode )
00301 {
00302
00303 return ( 0 == (TCODE_SHORT & typecode)
00304 || TCODE_RGB == typecode
00305 || TCODE_RGBDISPLAY == typecode
00306 || TCODE_PROPERTIES_OPENNURBS_VERSION == typecode
00307 || TCODE_OBJECT_RECORD_TYPE == typecode
00308 );
00309 }
00310
00311 bool ON_IsLongChunkTypecode(ON__UINT32 typecode)
00312 {
00313
00314
00315 return (0 == (TCODE_SHORT & typecode));
00316 }
00317
00318 bool ON_IsShorChunkTypecode(ON__UINT32 typecode)
00319 {
00320 return (0 != (TCODE_SHORT & typecode));
00321 }
00322
00323 static
00324 bool DownSizeINT( ON__INT64 i64, ON__INT32* i32 )
00325 {
00326 const static ON__INT64 i32max = 2147483647;
00327 if ( i64 <= i32max && i64 >= (-i32max - 1) )
00328 {
00329 *i32 = (ON__INT32)i64;
00330 return true;
00331 }
00332
00333 ON_ERROR("i64 too big to convert to 4 byte signed int");
00334 *i32 = 0;
00335 return false;
00336 }
00337
00338 static
00339 bool DownSizeUINT( ON__UINT64 u64, ON__UINT32* u32 )
00340 {
00341 if ( u64 <= 0xFFFFFFFF )
00342 {
00343 *u32 = (ON__UINT32)u64;
00344 return true;
00345 }
00346
00347 ON_ERROR("u64 too big to convert to 4 byte unsigned int");
00348 *u32 = 0;
00349 return false;
00350 }
00351
00352 static
00353 bool DownSizeChunkValue( ON__UINT32 typecode, ON__INT64 v64, ON__INT32* v32 )
00354 {
00355 if ( 0 == v32 )
00356 return true;
00357 return ( ON_IsLongChunkTypecode(typecode) )
00358 ? DownSizeUINT( (ON__UINT64)v64, (ON__UINT32*)v32 )
00359 : DownSizeINT( v64, v32 );
00360 }
00361
00362
00363
00364 struct ON__3dmV1LayerIndex
00365 {
00366 int m_layer_index;
00367 int m_layer_name_length;
00368 char* m_layer_name;
00369 struct ON__3dmV1LayerIndex* m_next;
00370 };
00371
00372 ON_BinaryArchive::ON_BinaryArchive( ON::archive_mode mode )
00373 : m_3dm_version(0),
00374 m_3dm_v1_layer_index(0), m_3dm_v1_material_index(0),
00375 m_error_message_mask(0),
00376 m_3dm_opennurbs_version(0),
00377 m_3dm_start_section_offset(0),
00378 m_active_table(ON_BinaryArchive::no_active_table),
00379 m_bDoChunkCRC(0), m_bad_CRC_count(0),
00380 m_endian(ON::Endian()),
00381 m_mode(mode)
00382 {
00383
00384
00385
00386 m_bSaveUserData = true;
00387 m_bSavePreviewImage = false;
00388 m_bEmbedTextureBitmaps = false;
00389 m_bSaveRenderMeshes = false;
00390 m_bSaveAnalysisMeshes = false;
00391
00392 m_zlib.mode = ON::unknown_archive_mode;
00393 memset( &m_zlib.strm, 0, sizeof(m_zlib.strm) );
00394
00395 m_V1_layer_list = 0;
00396 }
00397
00398 ON_BinaryArchive::~ON_BinaryArchive()
00399 {
00400 if ( 0 != m_V1_layer_list )
00401 {
00402 struct ON__3dmV1LayerIndex* next = m_V1_layer_list;
00403 m_V1_layer_list = 0;
00404 for ( int i = 0; 0 != next && i < 1000; i++ )
00405 {
00406 struct ON__3dmV1LayerIndex* p = next;
00407 next = p->m_next;
00408 onfree(p);
00409 }
00410 }
00411
00412 CompressionEnd();
00413 }
00414
00415
00416 bool ON_BinaryArchive::ToggleByteOrder(
00417 int count,
00418 int sizeof_element,
00419 const void* src,
00420 void* dst
00421 )
00422 {
00423 unsigned char c[32];
00424 const unsigned char* a = (const unsigned char*)src;
00425 unsigned char* b = (unsigned char*)dst;
00426
00427 bool rc = (count==0 || (count>0&&src&&dst));
00428 if ( rc )
00429 {
00430
00431
00432 switch(sizeof_element)
00433 {
00434 case 2:
00435 while(count--)
00436 {
00437 c[0] = *a++;
00438 c[1] = *a++;
00439 *b++ = c[1];
00440 *b++ = c[0];
00441 }
00442 break;
00443
00444 case 4:
00445 while(count--)
00446 {
00447 c[0] = *a++;
00448 c[1] = *a++;
00449 c[2] = *a++;
00450 c[3] = *a++;
00451 *b++ = c[3];
00452 *b++ = c[2];
00453 *b++ = c[1];
00454 *b++ = c[0];
00455 }
00456 break;
00457
00458 case 8:
00459 while(count--)
00460 {
00461 c[0] = *a++;
00462 c[1] = *a++;
00463 c[2] = *a++;
00464 c[3] = *a++;
00465 c[4] = *a++;
00466 c[5] = *a++;
00467 c[6] = *a++;
00468 c[7] = *a++;
00469 *b++ = c[7];
00470 *b++ = c[6];
00471 *b++ = c[5];
00472 *b++ = c[4];
00473 *b++ = c[3];
00474 *b++ = c[2];
00475 *b++ = c[1];
00476 *b++ = c[0];
00477 }
00478 break;
00479
00480 default:
00481 if ( sizeof_element > 0 && sizeof_element < 32 )
00482 {
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 int i;
00493 while(count--)
00494 {
00495 for (i = 0; i < sizeof_element; i++)
00496 c[i] = *a++;
00497 while(i--)
00498 *b++ = c[i];
00499 }
00500 }
00501 else
00502 {
00503 rc = false;
00504 }
00505 break;
00506 }
00507 }
00508 return rc;
00509 }
00510
00511 bool ON_BinaryArchive::BigSeekFromStart( ON__UINT64 offset )
00512 {
00513
00514
00515
00516
00517
00518 return ( offset > 2147483632 )
00519 ? ( SeekFromStart(2147483632) && BigSeekForward(offset - 2147483632) )
00520 : SeekFromStart((size_t)offset);
00521 }
00522
00523
00524
00525 bool ON_BinaryArchive::BigSeekForward( ON__UINT64 offset )
00526 {
00527
00528
00529
00530
00531
00532 while ( offset > 2147483632 )
00533 {
00534 if ( !SeekFromCurrentPosition(2147483632) )
00535 return false;
00536 offset -= 2147483632;
00537 }
00538 if ( offset > 0 )
00539 {
00540 int ioffset32 = (int)((ON__INT64)offset);
00541 return SeekFromCurrentPosition(ioffset32);
00542 }
00543 return true;
00544 }
00545
00546
00547 bool ON_BinaryArchive::BigSeekBackward( ON__UINT64 offset )
00548 {
00549
00550
00551
00552
00553
00554 while ( offset > 2147483632 )
00555 {
00556 if ( !SeekFromCurrentPosition(-2147483632) )
00557 return false;
00558 offset -= 2147483632;
00559 }
00560 if ( offset > 0 )
00561 {
00562 int ioffset32 = (int)((ON__INT64)offset);
00563 return SeekFromCurrentPosition(-ioffset32);
00564 }
00565 return true;
00566 }
00567
00568
00569 bool ON_BinaryArchive::BigSeekFromCurrentPosition( ON__INT64 offset )
00570 {
00571
00572
00573
00574
00575
00576 return ( offset >= 0 )
00577 ? BigSeekForward((ON__UINT64)offset)
00578 : BigSeekBackward((ON__UINT64)(-offset));
00579 }
00580
00581 bool
00582 ON_BinaryArchive::ReadMode() const
00583 {
00584 return (m_mode & ON::read) ? true : false;
00585 }
00586
00587 bool
00588 ON_BinaryArchive::WriteMode() const
00589 {
00590 return (m_mode & ON::write) ? true : false;
00591 }
00592
00593 bool
00594 ON_BinaryArchive::ReadChar(
00595 size_t count,
00596 char* p
00597 )
00598 {
00599 return ReadByte( count, p );
00600 }
00601
00602 bool
00603 ON_BinaryArchive::ReadChar(
00604 size_t count,
00605 unsigned char* p
00606 )
00607 {
00608 return ReadByte( count, p );
00609 }
00610
00611 bool
00612 ON_BinaryArchive::ReadChar(
00613 char* p
00614 )
00615 {
00616 return ReadByte( 1, p );
00617 }
00618
00619 bool
00620 ON_BinaryArchive::ReadChar(
00621 unsigned char* p
00622 )
00623 {
00624 return ReadByte( 1, p );
00625 }
00626
00627 bool
00628 ON_BinaryArchive::ReadInt16(
00629 size_t count,
00630 ON__INT16* p
00631 )
00632 {
00633 bool rc = ReadByte( count<<1, p );
00634 if ( rc && m_endian == ON::big_endian )
00635 {
00636
00637 unsigned char* b= (unsigned char*) (p);
00638 unsigned char c;
00639 while(count--) {
00640 c = b[0]; b[0] = b[1]; b[1] = c;
00641 b += 2;
00642 }
00643 }
00644 return rc;
00645 }
00646
00647 bool
00648 ON_BinaryArchive::ReadShort(
00649 size_t count,
00650 short* p
00651 )
00652 {
00653 #if defined(ON_COMPILER_MSC)
00654 #pragma warning( push )
00655
00656
00657
00658 #pragma warning( disable : 4127 )
00659 #endif
00660
00661 bool rc = true;
00662
00663 if ( 2 == sizeof(*p) )
00664 {
00665 rc = ReadInt16( count, (ON__INT16*)p );
00666 }
00667 else
00668 {
00669 size_t j;
00670 ON__INT16 i16;
00671 for ( j = 0; j < count && rc; j++ )
00672 {
00673 rc = ReadInt16( 1, &i16 );
00674 *p++ = (short)i16;
00675 }
00676 }
00677 return rc;
00678
00679 #if defined(ON_COMPILER_MSC)
00680 #pragma warning( pop )
00681 #endif
00682 }
00683
00684 bool
00685 ON_BinaryArchive::ReadShort(
00686 size_t count,
00687 unsigned short* p
00688 )
00689 {
00690 return ReadShort( count, (short*)p );
00691 }
00692
00693 bool
00694 ON_BinaryArchive::ReadShort(
00695 short* p
00696 )
00697 {
00698 return ReadShort( 1, p );
00699 }
00700
00701 bool
00702 ON_BinaryArchive::ReadShort(
00703 unsigned short* p
00704 )
00705 {
00706 return ReadShort( 1, p );
00707 }
00708
00709 bool
00710 ON_BinaryArchive::ReadInt32(
00711 size_t count,
00712 ON__INT32* p
00713 )
00714 {
00715 bool rc = ReadByte( count<<2, p );
00716 if ( rc && m_endian == ON::big_endian )
00717 {
00718 unsigned char* b= (unsigned char*)p;
00719 unsigned char c;
00720 while(count--) {
00721 c = b[0]; b[0] = b[3]; b[3] = c;
00722 c = b[1]; b[1] = b[2]; b[2] = c;
00723 b += 4;
00724 }
00725 }
00726 return rc;
00727 }
00728
00729 bool
00730 ON_BinaryArchive::ReadInt(
00731 size_t count,
00732 int* p
00733 )
00734 {
00735 #if defined(ON_COMPILER_MSC)
00736 #pragma warning( push )
00737
00738
00739
00740 #pragma warning( disable : 4127 )
00741 #endif
00742
00743 bool rc;
00744 if ( 4 == sizeof(*p) )
00745 {
00746 rc = ReadInt32( count, (ON__INT32*)p );
00747 }
00748 else
00749 {
00750 rc = true;
00751 ON__INT32 i32;
00752 size_t j;
00753 for ( j = 0; j < count && rc; j++ )
00754 {
00755 rc = ReadInt32(1,&i32);
00756 if (rc)
00757 *p++ = (int)i32;
00758 }
00759 }
00760 return rc;
00761
00762 #if defined(ON_COMPILER_MSC)
00763 #pragma warning( pop )
00764 #endif
00765 }
00766
00767 bool
00768 ON_BinaryArchive::ReadInt(
00769 size_t count,
00770 unsigned int* p
00771 )
00772 {
00773 return ReadInt( count, (int*)p );
00774 }
00775
00776 bool
00777 ON_BinaryArchive::ReadInt(
00778 int* p
00779 )
00780 {
00781 return ReadInt( 1, p );
00782 }
00783
00784 bool
00785 ON_BinaryArchive::ReadInt(
00786 unsigned int* p
00787 )
00788 {
00789 return ReadInt( 1, p );
00790 }
00791
00792 bool ON_BinaryArchive::ReadBigInt(
00793 size_t count,
00794 ON__INT64* p
00795 )
00796 {
00797 return ReadInt64(1,p);
00798 }
00799
00800 bool ON_BinaryArchive::ReadBigInt(
00801 size_t count,
00802 ON__UINT64* p
00803 )
00804 {
00805 return ReadInt64(1,(ON__INT64*)p);
00806 }
00807
00808 bool ON_BinaryArchive::ReadBigInt(
00809 ON__INT64* p
00810 )
00811 {
00812 return ReadInt64(1,p);
00813 }
00814
00815 bool ON_BinaryArchive::ReadBigInt(
00816 ON__UINT64* p
00817 )
00818 {
00819 return ReadInt64(1,(ON__INT64*)p);
00820 }
00821
00822
00823
00824 bool
00825 ON_BinaryArchive::ReadLong(
00826 size_t count,
00827 long* p
00828 )
00829 {
00830 #if defined(ON_COMPILER_MSC)
00831 #pragma warning( push )
00832
00833
00834
00835 #pragma warning( disable : 4127 )
00836 #endif
00837
00838 bool rc;
00839 if ( 4 == sizeof(*p) )
00840 {
00841 rc = ReadInt32( count, (ON__INT32*)p );
00842 }
00843 else
00844 {
00845 rc = true;
00846 ON__INT32 i32;
00847 size_t j;
00848 for ( j = 0; j < count && rc; j++ )
00849 {
00850 rc = ReadInt32(1,&i32);
00851 if (rc)
00852 *p++ = (long)i32;
00853 }
00854 }
00855 return rc;
00856
00857 #if defined(ON_COMPILER_MSC)
00858 #pragma warning( pop )
00859 #endif
00860 }
00861
00862 bool
00863 ON_BinaryArchive::ReadLong(
00864 size_t count,
00865 unsigned long* p
00866 )
00867 {
00868 return ReadLong( count, (long*)p );
00869 }
00870
00871 bool
00872 ON_BinaryArchive::ReadLong(
00873 long* p
00874 )
00875 {
00876 return ReadLong( 1, (long*)p );
00877 }
00878
00879 bool
00880 ON_BinaryArchive::ReadLong(
00881 unsigned long* p
00882 )
00883 {
00884 return ReadLong( 1, (long*)p );
00885 }
00886
00887 bool
00888 ON_BinaryArchive::ReadFloat(
00889 size_t count,
00890 float* p
00891 )
00892 {
00893
00894 return ReadInt32( count, (ON__INT32*)p );
00895 }
00896
00897 bool
00898 ON_BinaryArchive::ReadFloat(
00899 float* p
00900 )
00901 {
00902 return ReadFloat( 1, p );
00903 }
00904
00905 bool
00906 ON_BinaryArchive::ReadDouble(
00907 size_t count,
00908 double* p
00909 )
00910 {
00911 bool rc = ReadByte( count<<3, p );
00912 if ( rc && m_endian == ON::big_endian )
00913 {
00914 unsigned char* b=(unsigned char*)p;
00915 unsigned char c;
00916 while(count--) {
00917 c = b[0]; b[0] = b[7]; b[7] = c;
00918 c = b[1]; b[1] = b[6]; b[6] = c;
00919 c = b[2]; b[2] = b[5]; b[5] = c;
00920 c = b[3]; b[3] = b[4]; b[4] = c;
00921 b += 8;
00922 }
00923 }
00924 return rc;
00925 }
00926
00927 bool
00928 ON_BinaryArchive::ReadDouble(
00929 double* p
00930 )
00931 {
00932 return ReadDouble( 1, p );
00933 }
00934
00935 bool
00936 ON_BinaryArchive::ReadColor( ON_Color& color )
00937 {
00938 unsigned int colorref = 0;
00939 bool rc = ReadInt( &colorref );
00940 color = colorref;
00941 return rc;
00942 }
00943
00944 bool
00945 ON_BinaryArchive::ReadPoint (
00946 ON_2dPoint& p
00947 )
00948 {
00949 return ReadDouble( 2, &p.x );
00950 }
00951
00952 bool
00953 ON_BinaryArchive::ReadPoint (
00954 ON_3dPoint& p
00955 )
00956 {
00957 return ReadDouble( 3, &p.x );
00958 }
00959
00960 bool
00961 ON_BinaryArchive::ReadPoint (
00962 ON_4dPoint& p
00963 )
00964 {
00965 return ReadDouble( 4, &p.x );
00966 }
00967
00968 bool
00969 ON_BinaryArchive::ReadVector (
00970 ON_2dVector& v
00971 )
00972 {
00973 return ReadDouble( 2, &v.x );
00974 }
00975
00976 bool
00977 ON_BinaryArchive::ReadVector (
00978 ON_3dVector& v
00979 )
00980 {
00981 return ReadDouble( 3, &v.x );
00982 }
00983
00984 bool ON_BinaryArchive::WriteBoundingBox(const ON_BoundingBox& bbox)
00985 {
00986 bool rc = WritePoint( bbox.m_min );
00987 if (rc) rc = WritePoint( bbox.m_max );
00988 return rc;
00989 }
00990
00991 bool ON_BinaryArchive::ReadBoundingBox(ON_BoundingBox& bbox)
00992 {
00993 bool rc = ReadPoint( bbox.m_min );
00994 if (rc) rc = ReadPoint( bbox.m_max );
00995 return rc;
00996 }
00997
00998 bool
00999 ON_BinaryArchive::WriteXform( const ON_Xform& x )
01000 {
01001 return WriteDouble( 16, &x.m_xform[0][0] );
01002 }
01003
01004 bool
01005 ON_BinaryArchive::ReadXform( ON_Xform& x )
01006 {
01007 return ReadDouble( 16, &x.m_xform[0][0] );
01008 }
01009 bool
01010 ON_BinaryArchive::WritePlaneEquation( const ON_PlaneEquation& plane_equation )
01011 {
01012 bool rc = WriteDouble( 4, &plane_equation.x );
01013 return rc;
01014 }
01015
01016 bool
01017 ON_BinaryArchive::ReadPlaneEquation( ON_PlaneEquation& plane_equation )
01018 {
01019 bool rc = ReadDouble( 4, &plane_equation.x );
01020 return rc;
01021 }
01022
01023 bool
01024 ON_BinaryArchive::WritePlane( const ON_Plane& plane )
01025 {
01026 bool rc = WritePoint( plane.origin );
01027 if (rc) rc = WriteVector( plane.xaxis );
01028 if (rc) rc = WriteVector( plane.yaxis );
01029 if (rc) rc = WriteVector( plane.zaxis );
01030 if (rc) rc = WriteDouble( 4, &plane.plane_equation.x );
01031 return rc;
01032 }
01033
01034 bool
01035 ON_BinaryArchive::ReadPlane( ON_Plane& plane )
01036 {
01037 bool rc = ReadPoint( plane.origin );
01038 if (rc) rc = ReadVector( plane.xaxis );
01039 if (rc) rc = ReadVector( plane.yaxis );
01040 if (rc) rc = ReadVector( plane.zaxis );
01041 if (rc) rc = ReadDouble( 4, &plane.plane_equation.x );
01042 return rc;
01043 }
01044
01045 bool
01046 ON_BinaryArchive::WriteLine( const ON_Line& line )
01047 {
01048 bool rc = WritePoint( line.from );
01049 if (rc) rc = WritePoint( line.to );
01050 return rc;
01051 }
01052
01053 bool
01054 ON_BinaryArchive::ReadLine( ON_Line& line )
01055 {
01056 bool rc = ReadPoint( line.from );
01057 if (rc) rc = ReadPoint( line.to );
01058 return rc;
01059 }
01060
01061 bool
01062 ON_BinaryArchive::WriteArc(const ON_Arc& arc )
01063 {
01064 bool rc = WriteCircle(arc);
01065 if (rc)
01066 rc = WriteInterval(arc.m_angle);
01067 return rc;
01068 }
01069
01070 bool
01071 ON_BinaryArchive::ReadArc( ON_Arc& arc )
01072 {
01073 bool rc = ReadCircle(arc);
01074 if (rc)
01075 rc = ReadInterval(arc.m_angle);
01076 return rc;
01077 }
01078
01079 bool
01080 ON_BinaryArchive::WriteCircle(const ON_Circle& circle)
01081 {
01082 bool rc = WritePlane( circle.plane );
01083 if (rc)
01084 rc = WriteDouble( circle.radius );
01085
01086 if (rc)
01087 rc = WritePoint( circle.PointAt(0.0) );
01088 if (rc)
01089 rc = WritePoint( circle.PointAt(0.5*ON_PI) );
01090 if (rc)
01091 rc = WritePoint( circle.PointAt(ON_PI) );
01092
01093
01094
01095
01096
01097
01098
01099
01100 return rc;
01101 }
01102
01103 bool
01104 ON_BinaryArchive::ReadCircle(ON_Circle& circle)
01105 {
01106 ON_3dPoint scratch;
01107 bool rc = ReadPlane( circle.plane );
01108 if (rc)
01109 rc = ReadDouble( &circle.radius );
01110
01111 if (rc)
01112 rc = ReadPoint( scratch );
01113 if (rc)
01114 rc = ReadPoint( scratch );
01115 if (rc)
01116 rc = ReadPoint( scratch );
01117
01118
01119
01120
01121
01122
01123
01124
01125 return rc;
01126 }
01127
01128
01129 bool
01130 ON_BinaryArchive::WriteInterval( const ON_Interval& t )
01131 {
01132 return WriteDouble( 2, t.m_t );
01133 }
01134
01135 bool
01136 ON_BinaryArchive::ReadInterval( ON_Interval& t )
01137 {
01138 return ReadDouble( 2, t.m_t );
01139 }
01140
01141 bool
01142 ON_BinaryArchive::ReadUuid( ON_UUID& uuid )
01143 {
01144 bool rc = ReadInt32( 1, (ON__INT32*)(&uuid.Data1) );
01145 if (rc) rc = ReadInt16( 1, (ON__INT16*)(&uuid.Data2) );
01146 if (rc) rc = ReadInt16( 1, (ON__INT16*)(&uuid.Data3) );
01147 if (rc) rc = ReadByte( 8, uuid.Data4 );
01148 return rc;
01149 }
01150
01151 bool ON_BinaryArchive::ReadDisplayMaterialRef( ON_DisplayMaterialRef& dmr )
01152 {
01153 bool rc = ReadUuid( dmr.m_viewport_id );
01154 if (rc)
01155 rc = ReadUuid( dmr.m_display_material_id );
01156 return rc;
01157 }
01158
01159 bool
01160 ON_BinaryArchive::ReadTime( struct tm& utc )
01161 {
01162
01163
01164 bool rc = ReadInt( &utc.tm_sec );
01165 if ( rc )
01166 rc = ReadInt( &utc.tm_min );
01167 if ( rc )
01168 rc = ReadInt( &utc.tm_hour );
01169 if ( rc )
01170 rc = ReadInt( &utc.tm_mday );
01171 if ( rc )
01172 rc = ReadInt( &utc.tm_mon );
01173 if ( rc )
01174 rc = ReadInt( &utc.tm_year );
01175 if ( rc )
01176 rc = ReadInt( &utc.tm_wday );
01177 if ( rc )
01178 rc = ReadInt( &utc.tm_yday );
01179 if ( rc ) {
01180 if ( utc.tm_sec < 0 || utc.tm_sec > 60 )
01181 rc = false;
01182 if ( utc.tm_min < 0 || utc.tm_min > 60 )
01183 rc = false;
01184 if ( utc.tm_hour < 0 || utc.tm_hour > 24 )
01185 rc = false;
01186 if ( utc.tm_mday < 0 || utc.tm_mday > 31 )
01187 rc = false;
01188 if ( utc.tm_mon < 0 || utc.tm_mon > 12 )
01189 rc = false;
01190
01191 if ( utc.tm_wday < 0 || utc.tm_wday > 7 )
01192 rc = false;
01193 if ( utc.tm_yday < 0 || utc.tm_yday > 366 )
01194 rc = false;
01195 if ( !rc ) {
01196 ON_ERROR("ON_BinaryArchive::ReadTime() - bad time in archive");
01197 }
01198 }
01199 return rc;
01200 }
01201
01202 bool
01203 ON_BinaryArchive::ReadStringSize(
01204 size_t* sizeof_string
01205 )
01206 {
01207 ON__UINT32 ui32 = 0;
01208 bool rc = ReadInt32(1,(ON__INT32*)&ui32);
01209
01210
01211
01212
01213
01214
01215 if (rc)
01216 {
01217
01218
01219
01220
01221 if ( 0 != (0xF000000 & ui32) )
01222 {
01223
01224 ON_ERROR("string element count is impossibly large");
01225 rc = false;
01226 }
01227 else if ( ui32 > 0 )
01228 {
01229
01230 const ON_3DM_BIG_CHUNK* curchunk = m_chunk.Last();
01231 if ( 0 != curchunk && 0 == (TCODE_SHORT & curchunk->m_typecode) )
01232 {
01233 if ( curchunk->m_big_value < 0
01234 || ((ON__INT64)ui32) > curchunk->m_big_value
01235 )
01236 {
01237 ON_ERROR("string element count exceeds current chunk size");
01238 rc = false;
01239 }
01240 }
01241 }
01242
01243 if (rc)
01244 {
01245 *sizeof_string = (size_t)ui32;
01246 }
01247 }
01248 return rc;
01249 }
01250
01251
01252 bool
01253 ON_BinaryArchive::ReadStringUTF8ElementCount(
01254 size_t* string_utf8_element_count
01255 )
01256 {
01257 ON__UINT32 ui32 = 0;
01258 bool rc = ReadInt32(1,(ON__INT32*)&ui32);
01259
01260
01261
01262
01263
01264
01265 if (rc)
01266 {
01267
01268
01269
01270
01271 if ( 0 != (0xF000000 & ui32) )
01272 {
01273
01274 ON_ERROR("string element count is impossibly large");
01275 rc = false;
01276 }
01277 else if ( ui32 > 0 )
01278 {
01279
01280 const ON_3DM_BIG_CHUNK* curchunk = m_chunk.Last();
01281 if ( 0 != curchunk && 0 == (TCODE_SHORT & curchunk->m_typecode) )
01282 {
01283 if ( curchunk->m_big_value < 0
01284 || ((ON__INT64)ui32) > curchunk->m_big_value
01285 )
01286 {
01287 ON_ERROR("string byte count exceeds current chunk size");
01288 rc = false;
01289 }
01290 }
01291 }
01292 }
01293 if (!rc)
01294 ui32 = 0;
01295 if ( string_utf8_element_count )
01296 *string_utf8_element_count = (size_t)ui32;
01297 return rc;
01298 }
01299
01300
01301 bool
01302 ON_BinaryArchive::ReadStringUTF16ElementCount(
01303 size_t* string_utf16_element_count
01304 )
01305 {
01306 ON__UINT32 ui32 = 0;
01307 bool rc = ReadInt32(1,(ON__INT32*)&ui32);
01308
01309
01310
01311
01312
01313
01314 if (rc)
01315 {
01316 if ( 0 != (0xF000000 & ui32) )
01317 {
01318
01319 ON_ERROR("string element count is impossibly large");
01320 rc = false;
01321 }
01322 else if ( ui32 > 0 )
01323 {
01324
01325 const ON_3DM_BIG_CHUNK* curchunk = m_chunk.Last();
01326 if ( 0 != curchunk && 0 == (TCODE_SHORT & curchunk->m_typecode) )
01327 {
01328
01329
01330 if ( curchunk->m_big_value < 0
01331 || ((ON__INT64)2*ui32) > curchunk->m_big_value
01332 )
01333 {
01334 ON_ERROR("string byte count exceeds current chunk size");
01335 rc = false;
01336 }
01337 }
01338 }
01339 }
01340
01341 if (!rc)
01342 ui32 = 0;
01343 if ( string_utf16_element_count )
01344 *string_utf16_element_count = (size_t)ui32;
01345 return rc;
01346 }
01347
01348 bool
01349 ON_BinaryArchive::ReadString(
01350 size_t string_utf8_element_count,
01351 char* p
01352 )
01353 {
01354 return ReadByte( string_utf8_element_count, p );
01355 }
01356
01357 bool
01358 ON_BinaryArchive::ReadString(
01359 size_t string_utf8_element_count,
01360 unsigned char* p
01361 )
01362 {
01363 return ReadByte( string_utf8_element_count, p );
01364 }
01365
01366 bool
01367 ON_BinaryArchive::ReadString(
01368 size_t string_utf16_element_count,
01369 unsigned short* p
01370 )
01371 {
01372 return ReadShort( string_utf16_element_count, p );
01373 }
01374
01375 bool
01376 ON_BinaryArchive::ReadString( ON_String& s )
01377 {
01378 s.Destroy();
01379 size_t string_utf8_element_count = 0;
01380 bool rc = ReadStringUTF8ElementCount( &string_utf8_element_count );
01381 if ( rc && string_utf8_element_count > 0 )
01382 {
01383 const int istring_utf8_element_count = (int)string_utf8_element_count;
01384 s.ReserveArray(istring_utf8_element_count);
01385 ReadString( string_utf8_element_count, s.Array() );
01386 s.SetLength( istring_utf8_element_count-1 );
01387 }
01388 return rc;
01389 }
01390
01391 bool
01392 ON_BinaryArchive::ReadString( ON_wString& s )
01393 {
01394 #if defined(ON_COMPILER_MSC)
01395 #pragma warning( push )
01396
01397
01398
01399 #pragma warning( disable : 4127 )
01400 #endif
01401
01402 s.Destroy();
01403 size_t string_utf16_element_count = 0;
01404 bool rc = ReadStringUTF16ElementCount( &string_utf16_element_count );
01405 if ( rc && string_utf16_element_count > 0 )
01406 {
01407
01408
01409
01410
01411
01412
01413
01414 const int istring_utf16_element_count = (int)string_utf16_element_count;
01415 if ( 2 == sizeof(wchar_t) )
01416 {
01417
01418
01419 s.ReserveArray( istring_utf16_element_count );
01420 rc = ReadInt16( string_utf16_element_count, (ON__INT16*)s.Array() );
01421 if (rc)
01422 s.SetLength( istring_utf16_element_count-1 );
01423 }
01424 else if ( 4 == sizeof(wchar_t) )
01425 {
01426
01427
01428
01429
01430
01431 const int istring_utf16_element_count = (int)string_utf16_element_count;
01432 ON_SimpleArray<ON__UINT16> utf16_buffer(istring_utf16_element_count);
01433 rc = ReadInt16(string_utf16_element_count,(ON__INT16*)utf16_buffer.Array());
01434 if(rc)
01435 {
01436
01437 utf16_buffer.SetCount(istring_utf16_element_count);
01438 utf16_buffer[istring_utf16_element_count-1] = 0;
01439 rc = false;
01440 const ON__UINT16* sUTF16 = utf16_buffer.Array();
01441 const int bTestByteOrder = false;
01442 const int sUTF16_count = istring_utf16_element_count-1;
01443 const ON__UINT32 error_code_point = 0xFFFD;
01444 const unsigned int error_mask = 0xFFFFFFFF;
01445 unsigned int error_status = 0;
01446
01447 const int utf32_array_count = ON_ConvertUTF16ToUTF32(
01448 bTestByteOrder,
01449 sUTF16,
01450 sUTF16_count,
01451 0,
01452 0,
01453 &error_status,
01454 error_mask,
01455 error_code_point,
01456 0
01457 );
01458
01459 if ( 0 == utf32_array_count )
01460 {
01461 rc = true;
01462 }
01463 else if ( utf32_array_count > 0 )
01464 {
01465 error_status = 0;
01466 s.ReserveArray(utf32_array_count+1);
01467 const int utf32_array_count1 = ON_ConvertUTF16ToUTF32(
01468 bTestByteOrder,
01469 sUTF16,
01470 sUTF16_count,
01471 (unsigned int*)s.Array(),
01472 utf32_array_count,
01473 &error_status,
01474 error_mask,
01475 error_code_point,
01476 0
01477 );
01478 if ( utf32_array_count1 == utf32_array_count )
01479 {
01480 s.SetLength( utf32_array_count );
01481 rc = true;
01482 }
01483 }
01484 }
01485 }
01486 if (!rc)
01487 s.Destroy();
01488 }
01489 return rc;
01490
01491 #if defined(ON_COMPILER_MSC)
01492 #pragma warning( pop )
01493 #endif
01494 }
01495
01496
01497 bool ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_MappingChannel>& a)
01498 {
01499 int i, count = a.Count();
01500 if ( count < 0 )
01501 count = 0;
01502 bool rc = WriteInt( count );
01503 for ( i = 0; i < count && rc; i++ )
01504 {
01505
01506 rc = a[i].Write(*this);
01507 }
01508 return rc;
01509 }
01510
01511 bool ON_BinaryArchive::WriteArray( const ON_ClassArray<ON_MaterialRef>& a)
01512 {
01513 int i, count = a.Count();
01514 if ( count < 0 )
01515 count = 0;
01516 bool rc = WriteInt( count );
01517 for ( i = 0; i < count && rc; i++ )
01518 {
01519
01520 rc = a[i].Write(*this);
01521 }
01522 return rc;
01523 }
01524
01525
01526 bool ON_BinaryArchive::WriteArray( int count, const ON_Layer* a)
01527 {
01528 int i;
01529 if ( count < 0 || 0 == a )
01530 count = 0;
01531 bool rc = WriteInt( count );
01532 for ( i = 0; i < count && rc; i++ )
01533 {
01534 rc = WriteObject(a[i]);
01535 }
01536 return rc;
01537 }
01538
01539 bool ON_BinaryArchive::WriteArray( int count, const ON_Layer*const* a)
01540 {
01541 int i;
01542 if ( count < 0 || 0 == a )
01543 count = 0;
01544 bool rc = WriteInt( count );
01545 for ( i = 0; i < count && rc; i++ )
01546 {
01547 rc = WriteObject(a[i]);
01548 }
01549 return rc;
01550 }
01551
01552 bool ON_BinaryArchive::WriteArray( const ON_ClassArray<ON_MappingRef>& a )
01553 {
01554 int i, count = a.Count();
01555 if ( count < 0 )
01556 count = 0;
01557 bool rc = WriteInt( count );
01558 for ( i = 0; i < count && rc; i++ )
01559 {
01560
01561 rc = a[i].Write(*this);
01562 }
01563 return rc;
01564 }
01565
01566
01567 bool ON_BinaryArchive::WriteArray( const ON_ClassArray<ON_ObjRef>& a)
01568 {
01569 int i, count = a.Count();
01570 if ( count < 0 )
01571 count = 0;
01572 bool rc = WriteInt( count );
01573 for ( i = 0; i < count && rc; i++ )
01574 {
01575
01576 rc = a[i].Write(*this);
01577 }
01578 return rc;
01579 }
01580
01581 bool ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_ObjRef_IRefID>& a)
01582 {
01583 int i, count = a.Count();
01584 if ( count < 0 )
01585 count = 0;
01586 bool rc = WriteInt( count );
01587 for ( i = 0; i < count && rc; i++ )
01588 {
01589
01590 rc = a[i].Write(*this);
01591 }
01592 return rc;
01593 }
01594
01595 bool ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_MappingChannel>& a )
01596 {
01597 a.Empty();
01598 int i, count;
01599 bool rc = ReadInt( &count );
01600 if (rc)
01601 {
01602 a.SetCapacity(count);
01603 for ( i = 0; i < count && rc; i++ )
01604 {
01605 rc = a.AppendNew().Read(*this);
01606 }
01607 }
01608 return rc;
01609 }
01610
01611 bool ON_BinaryArchive::ReadArray( ON_ClassArray<ON_MaterialRef>& a)
01612 {
01613 a.Empty();
01614 int i, count;
01615 bool rc = ReadInt( &count );
01616 if (rc)
01617 {
01618 a.SetCapacity(count);
01619 for ( i = 0; i < count && rc; i++ )
01620 {
01621 rc = a.AppendNew().Read(*this);
01622 }
01623 }
01624 return rc;
01625 }
01626
01627 bool ON_BinaryArchive::ReadArray( ON_ObjectArray<class ON_Layer>& a)
01628 {
01629 a.Empty();
01630 int i, count;
01631 bool rc = ReadInt( &count );
01632 if (rc)
01633 {
01634 a.SetCapacity(count);
01635 for ( i = 0; i < count && rc; i++ )
01636 {
01637 rc = (1 == ReadObject(a.AppendNew()));
01638 if (!rc)
01639 {
01640 a.Remove();
01641 break;
01642 }
01643 }
01644 }
01645 return rc;
01646 }
01647
01648
01649 bool ON_BinaryArchive::ReadArray( ON_SimpleArray<class ON_Layer*>& a)
01650 {
01651 a.Empty();
01652 ON_Layer* layer;
01653 int i, count;
01654 bool rc = ReadInt( &count );
01655 if (rc)
01656 {
01657 a.SetCapacity(count);
01658 for ( i = 0; i < count && rc; i++ )
01659 {
01660 layer = 0;
01661 ON_Object* p = 0;
01662 rc = (1==ReadObject(&p));
01663 if (rc)
01664 {
01665 layer = ON_Layer::Cast(p);
01666 }
01667 if (!rc || 0 == layer)
01668 {
01669 if ( p )
01670 delete p;
01671 rc = false;
01672 break;
01673 }
01674 a.Append(layer);
01675 }
01676 }
01677 return rc;
01678 }
01679
01680 bool ON_BinaryArchive::ReadArray( ON_ClassArray<ON_MappingRef>& a)
01681 {
01682 a.Empty();
01683 int i, count;
01684 bool rc = ReadInt( &count );
01685 if (rc)
01686 {
01687 a.SetCapacity(count);
01688 for ( i = 0; i < count && rc; i++ )
01689 {
01690 rc = a.AppendNew().Read(*this);
01691 }
01692 }
01693 return rc;
01694 }
01695
01696 bool ON_BinaryArchive::ReadArray( ON_ClassArray<ON_ObjRef>& a)
01697 {
01698 a.Empty();
01699 int i, count;
01700 bool rc = ReadInt( &count );
01701 if (rc)
01702 {
01703 a.SetCapacity(count);
01704 for ( i = 0; i < count && rc; i++ )
01705 {
01706 rc = a.AppendNew().Read(*this);
01707 }
01708 }
01709 return rc;
01710 }
01711
01712 bool ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_ObjRef_IRefID>& a)
01713 {
01714 a.Empty();
01715 int i, count;
01716 bool rc = ReadInt( &count );
01717 if (rc)
01718 {
01719 a.SetCapacity(count);
01720 for ( i = 0; i < count && rc; i++ )
01721 {
01722 rc = a.AppendNew().Read(*this);
01723 }
01724 }
01725 return rc;
01726 }
01727
01728
01729 bool ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_DisplayMaterialRef>& a )
01730 {
01731 a.Empty();
01732 int count = 0;
01733 bool rc = ReadInt( &count );
01734 if ( rc && count > 0 )
01735 {
01736 a.SetCapacity( count );
01737 int i;
01738 for ( i = 0; i < count && rc; i++ )
01739 {
01740 rc = ReadDisplayMaterialRef(a.AppendNew());
01741 }
01742 }
01743 return rc;
01744 }
01745
01746 bool
01747 ON_BinaryArchive::ReadArray( ON_ClassArray<ON_String>& a)
01748 {
01749 a.Empty();
01750 int count = 0;
01751 bool rc = ReadInt( &count );
01752 if ( rc && count > 0 )
01753 {
01754 a.SetCapacity( count );
01755 int i;
01756 for ( i = 0; i < count && rc; i++ )
01757 {
01758 rc = ReadString( a.AppendNew() );
01759 }
01760 }
01761 return rc;
01762 }
01763
01764 bool
01765 ON_BinaryArchive::ReadArray( ON_ClassArray<ON_wString>& a)
01766 {
01767 a.Empty();
01768 int count = 0;
01769 bool rc = ReadInt( &count );
01770 if ( rc && count > 0 )
01771 {
01772 a.SetCapacity( count );
01773 int i;
01774 for ( i = 0; i < count && rc; i++ )
01775 {
01776 rc = ReadString( a.AppendNew() );
01777 }
01778 }
01779 return rc;
01780 }
01781
01782 bool
01783 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_DisplayMaterialRef>& a )
01784 {
01785 int i, count = a.Count();
01786 if ( count < 0 )
01787 count = 0;
01788 bool rc = WriteInt( count );
01789 for ( i = 0; i < count && rc; i++ )
01790 {
01791 rc = WriteDisplayMaterialRef( a[i] );
01792 }
01793 return rc;
01794 }
01795
01796 bool
01797 ON_BinaryArchive::WriteArray( const ON_ClassArray<ON_String>& a )
01798 {
01799 int i, count = a.Count();
01800 if ( count < 0 )
01801 count = 0;
01802 bool rc = WriteInt( count );
01803 for ( i = 0; i < count && rc; i++ )
01804 {
01805 rc = WriteString( a[i] );
01806 }
01807 return rc;
01808 }
01809
01810 bool
01811 ON_BinaryArchive::WriteArray( const ON_ClassArray<ON_wString>& a )
01812 {
01813 int i, count = a.Count();
01814 if ( count < 0 )
01815 count = 0;
01816 bool rc = WriteInt( count );
01817 for ( i = 0; i < count && rc; i++ )
01818 {
01819 rc = WriteString( a[i] );
01820 }
01821 return rc;
01822 }
01823
01824 bool
01825 ON_BinaryArchive::ReadArray( ON_SimpleArray<bool>& a )
01826 {
01827 #if defined(ON_COMPILER_MSC)
01828
01829
01830
01831 #pragma warning( push )
01832 #pragma warning( disable : 4127 )
01833 #endif
01834
01835 a.Empty();
01836 int count = 0;
01837 bool rc = ReadInt( &count );
01838 if ( rc && count > 0 )
01839 {
01840 a.SetCapacity( count );
01841 char* c = 0;
01842 bool* b = a.Array();
01843 if ( sizeof(*c) == sizeof(*b) )
01844 {
01845
01846 c = (char*)b;
01847 }
01848 else if ( b )
01849 {
01850
01851 c = (char*)onmalloc(count*sizeof(*c));
01852 }
01853 rc = ReadChar( count, c );
01854 if ( rc )
01855 {
01856 if ( c == (char*)b )
01857 {
01858 a.SetCount(count);
01859 }
01860 else if ( c )
01861 {
01862 int i;
01863 for ( i = 0; i < count; i++ )
01864 {
01865 a.Append(c[i]?true:false);
01866 }
01867 onfree(c);
01868 }
01869 }
01870 }
01871 return rc;
01872
01873 #if defined(ON_COMPILER_MSC)
01874 #pragma warning( pop )
01875 #endif
01876
01877 }
01878
01879 bool
01880 ON_BinaryArchive::ReadArray( ON_SimpleArray<char>& a )
01881 {
01882 a.Empty();
01883 int count = 0;
01884 bool rc = ReadInt( &count );
01885 if ( rc && count > 0 ) {
01886 a.SetCapacity( count );
01887 rc = ReadChar( count, a.Array() );
01888 if ( rc )
01889 a.SetCount(count);
01890 }
01891 return rc;
01892 }
01893
01894 bool
01895 ON_BinaryArchive::ReadArray( ON_SimpleArray<short>& a )
01896 {
01897 a.Empty();
01898 int count = 0;
01899 bool rc = ReadInt( &count );
01900 if ( rc && count > 0 ) {
01901 a.SetCapacity( count );
01902 rc = ReadShort( count, a.Array() );
01903 if ( rc )
01904 a.SetCount(count);
01905 }
01906 return rc;
01907 }
01908
01909 bool
01910 ON_BinaryArchive::ReadArray( ON_SimpleArray<int>& a )
01911 {
01912 a.Empty();
01913 int count = 0;
01914 bool rc = ReadInt( &count );
01915 if ( rc && count > 0 ) {
01916 a.SetCapacity( count );
01917 rc = ReadInt( count, a.Array() );
01918 if ( rc )
01919 a.SetCount(count);
01920 }
01921 return rc;
01922 }
01923
01924 bool
01925 ON_BinaryArchive::ReadArray( ON_SimpleArray<float>& a )
01926 {
01927 a.Empty();
01928 int count = 0;
01929 bool rc = ReadInt( &count );
01930 if ( rc && count > 0 ) {
01931 a.SetCapacity( count );
01932 rc = ReadFloat( count, a.Array() );
01933 if ( rc )
01934 a.SetCount(count);
01935 }
01936 return rc;
01937 }
01938
01939 bool
01940 ON_BinaryArchive::ReadArray( ON_SimpleArray<double>& a )
01941 {
01942 a.Empty();
01943 int count = 0;
01944 bool rc = ReadInt( &count );
01945 if ( rc && count > 0 ) {
01946 a.SetCapacity( count );
01947 rc = ReadDouble( count, a.Array() );
01948 if ( rc )
01949 a.SetCount(count);
01950 }
01951 return rc;
01952 }
01953
01954 bool
01955 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_Color>& a )
01956 {
01957 a.Empty();
01958 int count = 0;
01959 bool rc = ReadInt( &count );
01960 if ( rc && count > 0 ) {
01961 a.SetCapacity( count );
01962 rc = ReadInt( count, (int*)a.Array() );
01963 if ( rc )
01964 a.SetCount(count);
01965 }
01966 return rc;
01967 }
01968
01969
01970 bool
01971 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_2dPoint>& a )
01972 {
01973 a.Empty();
01974 int count = 0;
01975 bool rc = ReadInt( &count );
01976 if ( rc && count > 0 ) {
01977 a.SetCapacity( count );
01978 rc = ReadDouble( 2*count, &a.Array()->x );
01979 if ( rc )
01980 a.SetCount(count);
01981 }
01982 return rc;
01983 }
01984
01985 bool
01986 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_3dPoint>& a )
01987 {
01988 a.Empty();
01989 int count = 0;
01990 bool rc = ReadInt( &count );
01991 if ( rc && count > 0 ) {
01992 a.SetCapacity( count );
01993 rc = ReadDouble( 3*count, &a.Array()->x );
01994 if ( rc )
01995 a.SetCount(count);
01996 }
01997 return rc;
01998 }
01999
02000 bool
02001 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_4dPoint>& a )
02002 {
02003 a.Empty();
02004 int count = 0;
02005 bool rc = ReadInt( &count );
02006 if ( rc && count > 0 ) {
02007 a.SetCapacity( count );
02008 rc = ReadDouble( 4*count, &a.Array()->x );
02009 if ( rc )
02010 a.SetCount(count);
02011 }
02012 return rc;
02013 }
02014
02015 bool
02016 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_2dVector>& a )
02017 {
02018 a.Empty();
02019 int count = 0;
02020 bool rc = ReadInt( &count );
02021 if ( rc && count > 0 ) {
02022 a.SetCapacity( count );
02023 rc = ReadDouble( 2*count, &a.Array()->x );
02024 if ( rc )
02025 a.SetCount(count);
02026 }
02027 return rc;
02028 }
02029
02030 bool
02031 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_3dVector>& a )
02032 {
02033 a.Empty();
02034 int count = 0;
02035 bool rc = ReadInt( &count );
02036 if ( rc && count > 0 ) {
02037 a.SetCapacity( count );
02038 rc = ReadDouble( 3*count, &a.Array()->x );
02039 if ( rc )
02040 a.SetCount(count);
02041 }
02042 return rc;
02043 }
02044
02045 bool
02046 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_Xform>& a )
02047 {
02048 a.Empty();
02049 int count = 0;
02050 bool rc = ReadInt( &count );
02051 if ( rc && count > 0 )
02052 {
02053 a.SetCapacity( count );
02054 int i;
02055 for ( i = 0; i < count && rc; i++ )
02056 {
02057 rc = ReadXform(a.AppendNew());
02058 }
02059 }
02060 return rc;
02061 }
02062
02063 bool
02064 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_2fPoint>& a )
02065 {
02066 a.Empty();
02067 int count = 0;
02068 bool rc = ReadInt( &count );
02069 if ( rc && count > 0 ) {
02070 a.SetCapacity( count );
02071 rc = ReadFloat( 2*count, &a.Array()->x );
02072 if ( rc )
02073 a.SetCount(count);
02074 }
02075 return rc;
02076 }
02077
02078 bool
02079 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_3fPoint>& a )
02080 {
02081 a.Empty();
02082 int count = 0;
02083 bool rc = ReadInt( &count );
02084 if ( rc && count > 0 ) {
02085 a.SetCapacity( count );
02086 rc = ReadFloat( 3*count, &a.Array()->x );
02087 if ( rc )
02088 a.SetCount(count);
02089 }
02090 return rc;
02091 }
02092
02093 bool
02094 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_4fPoint>& a )
02095 {
02096 a.Empty();
02097 int count = 0;
02098 bool rc = ReadInt( &count );
02099 if ( rc && count > 0 ) {
02100 a.SetCapacity( count );
02101 rc = ReadFloat( 4*count, &a.Array()->x );
02102 if ( rc )
02103 a.SetCount(count);
02104 }
02105 return rc;
02106 }
02107
02108 bool
02109 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_2fVector>& a )
02110 {
02111 a.Empty();
02112 int count = 0;
02113 bool rc = ReadInt( &count );
02114 if ( rc && count > 0 ) {
02115 a.SetCapacity( count );
02116 rc = ReadFloat( 2*count, &a.Array()->x );
02117 if ( rc )
02118 a.SetCount(count);
02119 }
02120 return rc;
02121 }
02122
02123 bool
02124 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_3fVector>& a )
02125 {
02126 a.Empty();
02127 int count = 0;
02128 bool rc = ReadInt( &count );
02129 if ( rc && count > 0 ) {
02130 a.SetCapacity( count );
02131 rc = ReadFloat( 3*count, &a.Array()->x );
02132 if ( rc )
02133 a.SetCount(count);
02134 }
02135 return rc;
02136 }
02137
02138 bool
02139 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_UUID>& a )
02140 {
02141 a.Empty();
02142 ON_UUID uuid;
02143 int i, count = 0;
02144 bool rc = ReadInt( &count );
02145 if ( rc && count > 0 )
02146 {
02147 a.SetCapacity( count );
02148 for ( i = 0; i < count && rc; i++ )
02149 {
02150 rc = ReadUuid( uuid );
02151 if ( rc )
02152 a.Append(uuid);
02153 }
02154 }
02155 return rc;
02156 }
02157
02158
02159
02160
02161 bool
02162 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_UuidIndex>& a )
02163 {
02164 a.Empty();
02165 ON_UuidIndex idi;
02166 int i, count = 0;
02167 bool rc = ReadInt( &count );
02168 if ( rc && count > 0 )
02169 {
02170 a.SetCapacity( count );
02171 for ( i = 0; i < count && rc; i++ )
02172 {
02173 rc = ReadUuid( idi.m_id );
02174 if ( rc )
02175 {
02176 rc = ReadInt(&idi.m_i);
02177 if(rc)
02178 a.Append(idi);
02179 }
02180 }
02181 }
02182 return rc;
02183 }
02184
02185
02186 bool
02187 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_UUID>& a )
02188 {
02189 int i, count = a.Count();
02190 if ( count < 0 )
02191 count = 0;
02192 bool rc = WriteInt( count );
02193 for ( i = 0; i < count && rc; i++ )
02194 {
02195 rc = WriteUuid( a[i] );
02196 }
02197 return rc;
02198 }
02199
02200
02201 bool
02202 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_UuidIndex>& a )
02203 {
02204 int i, count = a.Count();
02205 if ( count < 0 )
02206 count = 0;
02207 bool rc = WriteInt( count );
02208 for ( i = 0; i < count && rc; i++ )
02209 {
02210 rc = WriteUuid( a[i].m_id );
02211 if (rc)
02212 rc = WriteInt( a[i].m_i );
02213 }
02214 return rc;
02215 }
02216
02217
02218 bool
02219 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_LinetypeSegment>& a )
02220 {
02221 a.Empty();
02222 ON_LinetypeSegment seg;
02223 int i, count = 0;
02224 bool rc = ReadInt( &count );
02225 if ( rc && count > 0 )
02226 {
02227 a.SetCapacity( count );
02228 for ( i = 0; i < count && rc; i++ )
02229 {
02230 rc = ReadLinetypeSegment( seg );
02231 if ( rc )
02232 a.Append(seg);
02233 }
02234 }
02235 return rc;
02236 }
02237
02238 bool
02239 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_LinetypeSegment>& a )
02240 {
02241 int i, count = a.Count();
02242 if ( count < 0 )
02243 count = 0;
02244 bool rc = WriteInt( count );
02245 for ( i = 0; i < count && rc; i++ )
02246 {
02247 rc = WriteLinetypeSegment( a[i] );
02248 }
02249 return rc;
02250 }
02251
02252 bool ON_BinaryArchive::ReadLinetypeSegment(ON_LinetypeSegment& seg)
02253 {
02254 seg.m_length = 1.0;
02255 seg.m_seg_type = ON_LinetypeSegment::stLine;
02256 unsigned int i;
02257 bool rc = ReadDouble(&seg.m_length);
02258 if (rc)
02259 {
02260 rc = ReadInt(&i);
02261 if( ON_LinetypeSegment::stLine == i )
02262 seg.m_seg_type = ON_LinetypeSegment::stLine;
02263 else if ( ON_LinetypeSegment::stSpace == i )
02264 seg.m_seg_type = ON_LinetypeSegment::stSpace;
02265 }
02266 return rc;
02267 }
02268
02269
02270 bool ON_BinaryArchive::WriteLinetypeSegment( const ON_LinetypeSegment& seg)
02271 {
02272
02273 unsigned int i = seg.m_seg_type;
02274 bool rc = WriteDouble(seg.m_length);
02275 if (rc)
02276 rc = WriteInt(i);
02277 return rc;
02278 }
02279
02280
02281 bool
02282 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_SurfaceCurvature>& a )
02283 {
02284 a.Empty();
02285 int count = 0;
02286 bool rc = ReadInt( &count );
02287 if ( rc && count > 0 ) {
02288 a.SetCapacity( count );
02289 rc = ReadDouble( 2*count, &a.Array()->k1 );
02290 if ( rc )
02291 a.SetCount(count);
02292 }
02293 return rc;
02294 }
02295
02296
02297 bool
02298 ON_BinaryArchive::ReadArray( ON_SimpleArray<ON_ClippingPlaneInfo>& a )
02299 {
02300 a.Empty();
02301 int count = 0;
02302 bool rc = ReadInt( &count );
02303 if ( rc && count > 0 )
02304 {
02305 a.SetCapacity(count);
02306 for ( int i = 0; i < count && rc ; i++ )
02307 {
02308 rc = a.AppendNew().Read(*this);
02309 if (!rc)
02310 a.Remove();
02311 }
02312 }
02313 return rc;
02314 }
02315
02316
02317 bool ON_BinaryArchive::WriteBool( bool b )
02318 {
02319 unsigned char c = (b?1:0);
02320 return WriteChar(c);
02321 }
02322
02323 bool ON_BinaryArchive::ReadBool( bool *b )
02324 {
02325 unsigned char c;
02326 bool rc = ReadChar(&c);
02327 if (rc && b)
02328 {
02329 if ( c != 0 && c != 1 )
02330 {
02331
02332
02333
02334 ON_ERROR("ON_BinaryArchive::ReadBool - bool value != 0 and != 1");
02335 rc = false;
02336 }
02337 *b = c?true:false;
02338 }
02339 return rc;
02340 }
02341
02342 bool
02343 ON_BinaryArchive::WriteChar(
02344 size_t count,
02345 const char* p
02346 )
02347 {
02348 return WriteByte( count, p );
02349 }
02350
02351 bool
02352 ON_BinaryArchive::WriteChar(
02353 size_t count,
02354 const unsigned char* p
02355 )
02356 {
02357 return WriteByte( count, p );
02358 }
02359
02360 bool
02361 ON_BinaryArchive::WriteChar(
02362 char c
02363 )
02364 {
02365 return WriteByte( 1, &c );
02366 }
02367
02368 bool
02369 ON_BinaryArchive::WriteChar(
02370 unsigned char c
02371 )
02372 {
02373 return WriteByte( 1, &c );
02374 }
02375
02376 bool
02377 ON_BinaryArchive::WriteInt16(
02378 size_t count,
02379 const ON__INT16* p
02380 )
02381 {
02382 bool rc = true;
02383 if ( m_endian == ON::big_endian )
02384 {
02385 if ( count > 0 )
02386 {
02387 const char* b = (const char*)p;
02388 while ( rc && count-- )
02389 {
02390 rc = WriteByte( 1, b+1 );
02391 if (rc)
02392 rc = WriteByte( 1, b );
02393 b++;
02394 b++;
02395 }
02396 }
02397 }
02398 else
02399 {
02400 rc = WriteByte( count<<1, p );
02401 }
02402 return rc;
02403 }
02404
02405 bool
02406 ON_BinaryArchive::WriteShort(
02407 size_t count,
02408 const short* p
02409 )
02410 {
02411 #if defined(ON_COMPILER_MSC)
02412 #pragma warning( push )
02413
02414
02415
02416 #pragma warning( disable : 4127 )
02417 #endif
02418
02419 bool rc;
02420 if ( 2 == sizeof(*p) )
02421 {
02422 rc = WriteInt16( count, (const ON__INT16*)p );
02423 }
02424 else
02425 {
02426 rc = true;
02427 ON__INT16 i16;
02428 size_t j;
02429 for ( j = 0; j < count; j++ )
02430 {
02431 i16 = (ON__INT16)(*p++);
02432 rc = WriteInt16( 1, &i16);
02433 }
02434 }
02435 return rc;
02436
02437 #if defined(ON_COMPILER_MSC)
02438 #pragma warning( pop )
02439 #endif
02440 }
02441
02442 bool
02443 ON_BinaryArchive::WriteShort(
02444 size_t count,
02445 const unsigned short* p
02446 )
02447 {
02448 return WriteShort( count, (const short*)p );
02449 }
02450
02451 bool
02452 ON_BinaryArchive::WriteShort(
02453 short s
02454 )
02455 {
02456 return WriteShort( 1, &s );
02457 }
02458
02459 bool
02460 ON_BinaryArchive::WriteShort(
02461 unsigned short s
02462 )
02463 {
02464 return WriteShort( 1, &s );
02465 }
02466
02467 bool
02468 ON_BinaryArchive::WriteInt32(
02469 size_t count,
02470 const ON__INT32* p
02471 )
02472 {
02473 bool rc = true;
02474 if ( m_endian == ON::big_endian )
02475 {
02476 if ( count > 0 )
02477 {
02478 const char* b = (const char*)p;
02479 while ( rc && count-- )
02480 {
02481 rc = WriteByte( 1, b+3 );
02482 if (rc) rc = WriteByte( 1, b+2 );
02483 if (rc) rc = WriteByte( 1, b+1 );
02484 if (rc) rc = WriteByte( 1, b );
02485 b += 4;
02486 }
02487 }
02488 }
02489 else
02490 {
02491 rc = WriteByte( count<<2, p );
02492 }
02493 return rc;
02494 }
02495
02496 bool
02497 ON_BinaryArchive::ReadInt64(
02498 size_t count,
02499 ON__INT64* p
02500 )
02501 {
02502 bool rc = ReadByte( count<<3, p );
02503 if ( rc && m_endian == ON::big_endian )
02504 {
02505 unsigned char* b=(unsigned char*)p;
02506 unsigned char c;
02507 while(count--) {
02508 c = b[0]; b[0] = b[7]; b[7] = c;
02509 c = b[1]; b[1] = b[6]; b[6] = c;
02510 c = b[2]; b[2] = b[5]; b[5] = c;
02511 c = b[3]; b[3] = b[4]; b[4] = c;
02512 b += 8;
02513 }
02514 }
02515 return rc;
02516 }
02517
02518 bool
02519 ON_BinaryArchive::WriteInt64(
02520 size_t count,
02521 const ON__INT64* p
02522 )
02523 {
02524 bool rc = true;
02525 if ( m_endian == ON::big_endian )
02526 {
02527 if ( count > 0 )
02528 {
02529 const char* b = (const char*)p;
02530 while ( rc && count-- )
02531 {
02532 rc = WriteByte( 1, b+7 );
02533 if (rc) rc = WriteByte( 1, b+6 );
02534 if (rc) rc = WriteByte( 1, b+5 );
02535 if (rc) rc = WriteByte( 1, b+4 );
02536 if (rc) rc = WriteByte( 1, b+3 );
02537 if (rc) rc = WriteByte( 1, b+2 );
02538 if (rc) rc = WriteByte( 1, b+1 );
02539 if (rc) rc = WriteByte( 1, b );
02540 b += 8;
02541 }
02542 }
02543 }
02544 else
02545 {
02546 rc = WriteByte( count<<3, p );
02547 }
02548 return rc;
02549 }
02550
02551 bool
02552 ON_BinaryArchive::WriteInt(
02553 size_t count,
02554 const int* p
02555 )
02556 {
02557 #if defined(ON_COMPILER_MSC)
02558 #pragma warning( push )
02559
02560
02561
02562 #pragma warning( disable : 4127 )
02563 #endif
02564
02565 bool rc;
02566 if ( 4 == sizeof(*p) )
02567 {
02568 rc = WriteInt32( count, (const ON__INT32*)p );
02569 }
02570 else
02571 {
02572 ON__INT32 i32;
02573 size_t j;
02574 rc = true;
02575 for ( j = 0; j < count && rc; j++ )
02576 {
02577 i32 = (ON__INT32)(*p++);
02578 rc = WriteInt32( 1, &i32 );
02579 }
02580 }
02581 return rc;
02582
02583 #if defined(ON_COMPILER_MSC)
02584 #pragma warning( pop )
02585 #endif
02586 }
02587
02588 bool
02589 ON_BinaryArchive::WriteSize(size_t sz)
02590 {
02591 unsigned int u = (unsigned int)sz;
02592 return WriteInt(u);
02593 }
02594
02595 bool
02596 ON_BinaryArchive::ReadSize(size_t* sz)
02597 {
02598 unsigned int u = 0;
02599 bool rc = ReadInt(&u);
02600 if (rc)
02601 *sz = u;
02602 return rc;
02603 }
02604
02605 bool ON_BinaryArchive::WriteBigSize(size_t sz)
02606 {
02607 ON__UINT64 u = (ON__UINT64)sz;
02608 return WriteInt64(1,(ON__INT64*)&u);;
02609 }
02610
02611 bool ON_BinaryArchive::ReadBigSize( size_t* sz )
02612 {
02613 ON__UINT64 u;
02614 bool rc = ReadInt64(1,(ON__INT64*)&u);
02615 if (rc)
02616 *sz = (size_t)u;
02617 return rc;
02618 }
02619
02620 bool ON_BinaryArchive::WriteBigTime(time_t t)
02621 {
02622 ON__UINT64 u = (ON__UINT64)t;
02623 return WriteInt64(1,(ON__INT64*)&u);
02624 }
02625
02626 bool ON_BinaryArchive::ReadBigTime( time_t* t )
02627 {
02628 ON__UINT64 u;
02629 bool rc = ReadInt64(1,(ON__INT64*)&u);
02630 if (rc)
02631 *t = (time_t)u;
02632 return rc;
02633 }
02634
02635
02636 bool
02637 ON_BinaryArchive::WriteInt(
02638 size_t count,
02639 const unsigned int* p
02640 )
02641 {
02642 return WriteInt( count, (const int*)p );
02643 }
02644
02645 bool
02646 ON_BinaryArchive::WriteInt(
02647 int i
02648 )
02649 {
02650 return WriteInt( 1, &i );
02651 }
02652
02653 bool
02654 ON_BinaryArchive::WriteInt(
02655 unsigned int i
02656 )
02657 {
02658 return WriteInt( 1, &i );
02659 }
02660
02661 bool ON_BinaryArchive::WriteBigInt(
02662 size_t count,
02663 const ON__INT64* p
02664 )
02665 {
02666 return WriteInt64(count,p);
02667 }
02668
02669 bool ON_BinaryArchive::WriteBigInt(
02670 size_t count,
02671 const ON__UINT64* p
02672 )
02673 {
02674 return WriteInt64(count,(const ON__INT64*)p);
02675 }
02676
02677 bool ON_BinaryArchive:: WriteBigInt(
02678 ON__INT64 i
02679 )
02680 {
02681 return WriteInt64(1,&i);
02682 }
02683
02684 bool ON_BinaryArchive::WriteBigInt(
02685 ON__UINT64 u
02686 )
02687 {
02688 return WriteInt64(1,(const ON__INT64*)&u);
02689 }
02690
02691
02692
02693 bool
02694 ON_BinaryArchive::WriteLong(
02695 size_t count,
02696 const long* p
02697 )
02698 {
02699 #if defined(ON_COMPILER_MSC)
02700 #pragma warning( push )
02701
02702
02703
02704 #pragma warning( disable : 4127 )
02705 #endif
02706
02707 bool rc;
02708 if ( 4 == sizeof(*p) )
02709 {
02710 rc = WriteInt32( count, (const ON__INT32*)p );
02711 }
02712 else
02713 {
02714 ON__INT32 i32;
02715 size_t j;
02716 rc = true;
02717 for ( j = 0; j < count && rc; j++ )
02718 {
02719 i32 = (ON__INT32)(*p++);
02720 rc = WriteInt32( 1, &i32 );
02721 }
02722 }
02723 return rc;
02724
02725 #if defined(ON_COMPILER_MSC)
02726 #pragma warning( pop )
02727 #endif
02728 }
02729
02730 bool
02731 ON_BinaryArchive::WriteLong(
02732 size_t count,
02733 const unsigned long* p
02734 )
02735 {
02736 return WriteLong( count, (const long*)p );
02737 }
02738
02739 bool
02740 ON_BinaryArchive::WriteLong(
02741 long i
02742 )
02743 {
02744 return WriteLong( 1, &i );
02745 }
02746
02747 bool
02748 ON_BinaryArchive::WriteLong(
02749 unsigned long i
02750 )
02751 {
02752 return WriteLong( 1, &i );
02753 }
02754
02755
02756 bool
02757 ON_BinaryArchive::WriteFloat(
02758 size_t count,
02759 const float* p
02760 )
02761 {
02762
02763 return WriteInt( count, (const int*)p );
02764 }
02765
02766 bool
02767 ON_BinaryArchive::WriteFloat(
02768 float f
02769 )
02770 {
02771 return WriteFloat( 1, &f );
02772 }
02773
02774 bool
02775 ON_BinaryArchive::WriteDouble(
02776 size_t count,
02777 const double* p
02778 )
02779 {
02780 bool rc = true;
02781 if ( m_endian == ON::big_endian ) {
02782 if ( count > 0 ) {
02783 const char* b = (const char*)p;
02784 while ( rc && count-- ) {
02785 rc = WriteByte( 1, b+7 );
02786 if (rc) rc = WriteByte( 1, b+6 );
02787 if (rc) rc = WriteByte( 1, b+5 );
02788 if (rc) rc = WriteByte( 1, b+4 );
02789 if (rc) rc = WriteByte( 1, b+3 );
02790 if (rc) rc = WriteByte( 1, b+2 );
02791 if (rc) rc = WriteByte( 1, b+1 );
02792 if (rc) rc = WriteByte( 1, b );
02793 b += 8;
02794 }
02795 }
02796 }
02797 else {
02798 rc = WriteByte( count<<3, p );
02799 }
02800 return rc;
02801 }
02802
02803 bool
02804 ON_BinaryArchive::WriteComponentIndex(
02805 const ON_COMPONENT_INDEX& ci
02806 )
02807 {
02808 bool rc = WriteInt( ci.m_type );
02809 if (rc)
02810 rc = WriteInt( ci.m_index );
02811
02812 return rc;
02813 }
02814
02815 bool
02816 ON_BinaryArchive::ReadComponentIndex(
02817 ON_COMPONENT_INDEX& ci
02818 )
02819 {
02820 int t;
02821 ci.m_type = ON_COMPONENT_INDEX::invalid_type;
02822 ci.m_index = 0;
02823 bool rc = ReadInt( &t );
02824 if (rc)
02825 {
02826 rc = ReadInt( &ci.m_index );
02827 if (rc)
02828 {
02829 ci.m_type = ON_COMPONENT_INDEX::Type(t);
02830 }
02831
02832 }
02833 return rc;
02834 }
02835
02836 bool
02837 ON_BinaryArchive::WriteDouble(
02838 const double x
02839 )
02840 {
02841 return WriteDouble( 1, &x );
02842 }
02843
02844 bool
02845 ON_BinaryArchive::WriteColor( const ON_Color& color )
02846 {
02847 unsigned int colorref = color;
02848 return WriteInt( colorref );
02849 }
02850
02851 bool
02852 ON_BinaryArchive::WritePoint (
02853 const ON_2dPoint& p
02854 )
02855 {
02856 return WriteDouble( 2, &p.x );
02857 }
02858
02859 bool
02860 ON_BinaryArchive::WritePoint (
02861 const ON_3dPoint& p
02862 )
02863 {
02864 return WriteDouble( 3, &p.x );
02865 }
02866
02867 bool
02868 ON_BinaryArchive::WritePoint (
02869 const ON_4dPoint& p
02870 )
02871 {
02872 return WriteDouble( 4, &p.x );
02873 }
02874
02875 bool
02876 ON_BinaryArchive::WriteVector (
02877 const ON_2dVector& v
02878 )
02879 {
02880 return WriteDouble( 2, &v.x );
02881 }
02882
02883 bool
02884 ON_BinaryArchive::WriteVector (
02885 const ON_3dVector& v
02886 )
02887 {
02888 return WriteDouble( 3, &v.x );
02889 }
02890
02891 bool ON_BinaryArchive::WriteDisplayMaterialRef( const ON_DisplayMaterialRef& dmr )
02892 {
02893 bool rc = WriteUuid( dmr.m_viewport_id );
02894 if (rc) rc = WriteUuid( dmr.m_display_material_id );
02895 return rc;
02896 }
02897
02898 bool
02899 ON_BinaryArchive::WriteUuid( const ON_UUID& uuid )
02900 {
02901 bool rc = WriteInt32( 1, (const ON__INT32*)(&uuid.Data1) );
02902 if (rc) rc = WriteInt16( 1, (const ON__INT16*)(&uuid.Data2) );
02903 if (rc) rc = WriteInt16( 1, (const ON__INT16*)(&uuid.Data3) );
02904 if (rc) rc = WriteByte( 8, uuid.Data4 );
02905 return rc;
02906 }
02907
02908 bool
02909 ON_BinaryArchive::WriteTime( const struct tm& utc )
02910 {
02911
02912
02913
02914
02915
02916 int i;
02917 i = (int)utc.tm_sec; if ( i < 0 || i > 60 ) i = 0;
02918 bool rc = WriteInt( i );
02919 i = (int)utc.tm_min; if ( i < 0 || i > 60 ) i = 0;
02920 if ( rc )
02921 rc = WriteInt( i );
02922 i = (int)utc.tm_hour; if ( i < 0 || i > 24 ) i = 0;
02923 if ( rc )
02924 rc = WriteInt( i );
02925 i = (int)utc.tm_mday; if ( i < 0 || i > 31 ) i = 0;
02926 if ( rc )
02927 rc = WriteInt( i );
02928 i = (int)utc.tm_mon; if ( i < 0 || i > 12 ) i = 0;
02929 if ( rc )
02930 rc = WriteInt( i );
02931
02932
02933 i = (int)utc.tm_year;
02934 if ( rc )
02935 rc = WriteInt( i );
02936
02937 i = (int)utc.tm_wday; if ( i < 0 || i > 7 ) i = 0;
02938 if ( rc )
02939 rc = WriteInt( i );
02940 i = (int)utc.tm_yday; if ( i < 0 || i > 366 ) i = 0;
02941 if ( rc )
02942 rc = WriteInt( i );
02943 return rc;
02944 }
02945
02946 bool
02947 ON_BinaryArchive::WriteString(
02948 const char* sUTF8
02949 )
02950 {
02951 size_t string_utf8_element_count = 0;
02952 if ( sUTF8 )
02953 {
02954 while(sUTF8[string_utf8_element_count])
02955 string_utf8_element_count++;
02956 if ( string_utf8_element_count )
02957 string_utf8_element_count++;
02958 }
02959 ON__UINT32 ui32 = (ON__UINT32)string_utf8_element_count;
02960 bool rc = WriteInt32(1,(ON__INT32*)&ui32);
02961 if ( rc && string_utf8_element_count > 0 )
02962 rc = WriteByte( string_utf8_element_count, sUTF8 );
02963 return rc;
02964 }
02965
02966 bool
02967 ON_BinaryArchive::WriteString(
02968 const unsigned char* sUTF8
02969 )
02970 {
02971 return WriteString( (const char*)sUTF8 );
02972 }
02973
02974 bool
02975 ON_BinaryArchive::WriteString(
02976 const unsigned short* sUTF16
02977 )
02978 {
02979 size_t string_utf16_element_count = 0;
02980 if ( sUTF16 )
02981 {
02982 while(sUTF16[string_utf16_element_count])
02983 string_utf16_element_count++;
02984 if ( string_utf16_element_count )
02985 string_utf16_element_count++;
02986 }
02987 ON__UINT32 ui32 = (ON__UINT32)string_utf16_element_count;
02988 bool rc = WriteInt32(1,(ON__INT32*)&ui32);
02989 if ( rc && string_utf16_element_count > 0 )
02990 {
02991 rc = WriteShort( string_utf16_element_count, sUTF16 );
02992 }
02993 return rc;
02994 }
02995
02996 bool
02997 ON_BinaryArchive::WriteString( const ON_String& sUTF8 )
02998 {
02999 size_t string_utf8_element_count = sUTF8.Length();
03000 if ( string_utf8_element_count )
03001 string_utf8_element_count++;
03002 ON__UINT32 ui32 = (ON__UINT32)string_utf8_element_count;
03003 bool rc = WriteInt32(1,(ON__INT32*)&ui32);
03004 if ( rc && string_utf8_element_count > 0 )
03005 rc = WriteByte( string_utf8_element_count, sUTF8.Array() );
03006 return rc;
03007 }
03008
03009 bool
03010 ON_BinaryArchive::WriteString( const ON_wString& s )
03011 {
03012 #if defined(ON_COMPILER_MSC)
03013 #pragma warning( push )
03014
03015
03016
03017 #pragma warning( disable : 4127 )
03018 #endif
03019
03020 size_t string_element_count = s.Length();
03021 if ( string_element_count > 0)
03022 string_element_count++;
03023 bool rc = false;
03024 if ( string_element_count <= 1 )
03025 {
03026 ON__UINT32 ui32 = 0;
03027 rc = WriteInt32(1,(ON__INT32*)&ui32);
03028 }
03029 else if ( 2 == sizeof(wchar_t) && string_element_count > 0 )
03030 {
03031 ON__UINT32 ui32 = (ON__UINT32)string_element_count;
03032 rc = WriteInt32(1,(ON__INT32*)&ui32);
03033 if (rc)
03034 rc = WriteInt16( string_element_count, (const ON__INT16*)s.Array() );
03035 }
03036 else if ( 4 == sizeof(wchar_t) && string_element_count > 0 )
03037 {
03038
03039 const int bTestByteOrder = false;
03040 const ON__UINT32* sUTF32 = (const ON__UINT32*)s.Array();
03041 const int sUTF32_count = (int)(string_element_count-1);
03042 const unsigned int error_mask = 0xFFFFFFFF;
03043 const ON__UINT32 error_code_point = 0xFFFD;
03044 unsigned int error_status = 0;
03045
03046 const int sUTF16_count = ON_ConvertUTF32ToUTF16(
03047 bTestByteOrder,
03048 sUTF32,
03049 sUTF32_count,
03050 0,
03051 0,
03052 &error_status,
03053 error_mask,
03054 error_code_point,
03055 0
03056 );
03057
03058 if ( sUTF16_count > 0 )
03059 {
03060 error_status = 0;
03061 ON_SimpleArray<ON__UINT16> utf16_buffer(sUTF16_count+1);
03062 utf16_buffer.SetCount(sUTF16_count+1);
03063 const int sUTF16_count1 = ON_ConvertUTF32ToUTF16(
03064 bTestByteOrder,
03065 sUTF32,
03066 sUTF32_count,
03067 utf16_buffer.Array(),
03068 utf16_buffer.Count(),
03069 &error_status,
03070 error_mask,
03071 error_code_point,
03072 0
03073 );
03074 if ( sUTF16_count1 == sUTF16_count )
03075 {
03076 utf16_buffer[sUTF16_count] = 0;
03077 const ON__UINT32 ui32 = (ON__UINT32)(sUTF16_count+1);
03078 rc = WriteInt32(1,(const ON__INT32*)&ui32);
03079 if ( rc && ui32 > 0 )
03080 rc = WriteInt16( ui32, (const ON__INT16*)utf16_buffer.Array() );
03081 }
03082 }
03083 }
03084 return rc;
03085
03086 #if defined(ON_COMPILER_MSC)
03087 #pragma warning( pop )
03088 #endif
03089 }
03090
03091 bool ON_BinaryArchive::WriteArray( const ON_SimpleArray<bool>& a )
03092 {
03093 #if defined(ON_COMPILER_MSC)
03094 #pragma warning( push )
03095
03096
03097
03098 #pragma warning( disable : 4127 )
03099 #endif
03100
03101 int count = a.Count();
03102 if ( count < 0 )
03103 count = 0;
03104 bool rc = WriteInt( count );
03105
03106 if ( rc && count > 0 )
03107 {
03108 char* p = 0;
03109 const char* c = 0;
03110 const bool* b = a.Array();
03111 if ( sizeof(*c) == sizeof(*b) )
03112 {
03113
03114 c = (char*)(b);
03115 }
03116 else if ( b )
03117 {
03118
03119 p = (char*)onmalloc(count*sizeof(*p));
03120 int i;
03121 for ( i = 0; i < count; i++ )
03122 p[i] = (b[i]?1:0);
03123 c = p;
03124 }
03125 rc = WriteChar( count, c );
03126 if ( p )
03127 onfree(p);
03128 }
03129
03130 return rc;
03131
03132 #if defined(ON_COMPILER_MSC)
03133 #pragma warning( pop )
03134 #endif
03135 }
03136
03137 bool
03138 ON_BinaryArchive::WriteArray( const ON_SimpleArray<char>& a )
03139 {
03140 int count = a.Count();
03141 if ( count < 0 )
03142 count = 0;
03143 bool rc = WriteInt( count );
03144 if ( rc && count > 0 ) {
03145 rc = WriteChar( count, a.Array() );
03146 }
03147 return rc;
03148 }
03149
03150 bool
03151 ON_BinaryArchive::WriteArray( const ON_SimpleArray<short>& a )
03152 {
03153 int count = a.Count();
03154 if ( count < 0 )
03155 count = 0;
03156 bool rc = WriteInt( count );
03157 if ( rc && count > 0 ) {
03158 rc = WriteShort( count, a.Array() );
03159 }
03160 return rc;
03161 }
03162
03163 bool
03164 ON_BinaryArchive::WriteArray( const ON_SimpleArray<int>& a )
03165 {
03166 int count = a.Count();
03167 if ( count < 0 )
03168 count = 0;
03169 bool rc = WriteInt( count );
03170 if ( rc && count > 0 ) {
03171 rc = WriteInt( count, a.Array() );
03172 }
03173 return rc;
03174 }
03175
03176 bool
03177 ON_BinaryArchive::WriteArray( const ON_SimpleArray<float>& a )
03178 {
03179 int count = a.Count();
03180 if ( count < 0 )
03181 count = 0;
03182 bool rc = WriteInt( count );
03183 if ( rc && count > 0 ) {
03184 rc = WriteFloat( count, a.Array() );
03185 }
03186 return rc;
03187 }
03188
03189 bool
03190 ON_BinaryArchive::WriteArray( const ON_SimpleArray<double>& a )
03191 {
03192 int count = a.Count();
03193 if ( count < 0 )
03194 count = 0;
03195 bool rc = WriteInt( count );
03196 if ( rc && count > 0 ) {
03197 rc = WriteDouble( count, a.Array() );
03198 }
03199 return rc;
03200 }
03201
03202 bool
03203 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_Color>& a )
03204 {
03205 int count = a.Count();
03206 if ( count < 0 )
03207 count = 0;
03208 bool rc = WriteInt( count );
03209 if ( rc && count > 0 ) {
03210 rc = WriteInt( count, (int*)a.Array() );
03211 }
03212 return rc;
03213 }
03214
03215 bool
03216 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_2dPoint>& a )
03217 {
03218 int count = a.Count();
03219 if ( count < 0 )
03220 count = 0;
03221 bool rc = WriteInt( count );
03222 if ( rc && count > 0 ) {
03223 rc = WriteDouble( count*2, &a.Array()->x );
03224 }
03225 return rc;
03226 }
03227
03228 bool
03229 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_3dPoint>& a )
03230 {
03231 int count = a.Count();
03232 if ( count < 0 )
03233 count = 0;
03234 bool rc = WriteInt( count );
03235 if ( rc && count > 0 ) {
03236 rc = WriteDouble( count*3, &a.Array()->x );
03237 }
03238 return rc;
03239 }
03240
03241 bool
03242 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_4dPoint>& a )
03243 {
03244 int count = a.Count();
03245 if ( count < 0 )
03246 count = 0;
03247 bool rc = WriteInt( count );
03248 if ( rc && count > 0 ) {
03249 rc = WriteDouble( count*4, &a.Array()->x );
03250 }
03251 return rc;
03252 }
03253
03254 bool
03255 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_2dVector>& a )
03256 {
03257 int count = a.Count();
03258 if ( count < 0 )
03259 count = 0;
03260 bool rc = WriteInt( count );
03261 if ( rc && count > 0 ) {
03262 rc = WriteDouble( count*2, &a.Array()->x );
03263 }
03264 return rc;
03265 }
03266
03267
03268 bool
03269 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_3dVector>& a )
03270 {
03271 int count = a.Count();
03272 if ( count < 0 )
03273 count = 0;
03274 bool rc = WriteInt( count );
03275 if ( rc && count > 0 ) {
03276 rc = WriteDouble( count*3, &a.Array()->x );
03277 }
03278 return rc;
03279 }
03280
03281
03282 bool
03283 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_Xform>& a )
03284 {
03285 int count = a.Count();
03286 if ( count < 0 )
03287 count = 0;
03288 bool rc = WriteInt( count );
03289 if ( rc && count > 0 )
03290 {
03291 int i;
03292 for ( i = 0; i < count && rc; i++ )
03293 rc = WriteXform(a[i]);
03294 }
03295 return rc;
03296 }
03297
03298 bool
03299 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_2fPoint>& a )
03300 {
03301 int count = a.Count();
03302 if ( count < 0 )
03303 count = 0;
03304 bool rc = WriteInt( count );
03305 if ( rc && count > 0 ) {
03306 rc = WriteFloat( count*2, &a.Array()->x );
03307 }
03308 return rc;
03309 }
03310
03311 bool
03312 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_3fPoint>& a )
03313 {
03314 int count = a.Count();
03315 if ( count < 0 )
03316 count = 0;
03317 bool rc = WriteInt( count );
03318 if ( rc && count > 0 ) {
03319 rc = WriteFloat( count*3, &a.Array()->x );
03320 }
03321 return rc;
03322 }
03323
03324 bool
03325 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_4fPoint>& a )
03326 {
03327 int count = a.Count();
03328 if ( count < 0 )
03329 count = 0;
03330 bool rc = WriteInt( count );
03331 if ( rc && count > 0 ) {
03332 rc = WriteFloat( count*4, &a.Array()->x );
03333 }
03334 return rc;
03335 }
03336
03337 bool
03338 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_2fVector>& a )
03339 {
03340 int count = a.Count();
03341 if ( count < 0 )
03342 count = 0;
03343 bool rc = WriteInt( count );
03344 if ( rc && count > 0 ) {
03345 rc = WriteFloat( count*2, &a.Array()->x );
03346 }
03347 return rc;
03348 }
03349
03350 bool
03351 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_3fVector>& a )
03352 {
03353 int count = a.Count();
03354 if ( count < 0 )
03355 count = 0;
03356 bool rc = WriteInt( count );
03357 if ( rc && count > 0 ) {
03358 rc = WriteFloat( count*3, &a.Array()->x );
03359 }
03360 return rc;
03361 }
03362
03363
03364 bool
03365 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_SurfaceCurvature>& a )
03366 {
03367 int count = a.Count();
03368 if ( count < 0 )
03369 count = 0;
03370 bool rc = WriteInt( count );
03371 if ( rc && count > 0 ) {
03372 rc = WriteDouble( count*2, &a.Array()->k1 );
03373 }
03374 return rc;
03375 }
03376
03377 bool
03378 ON_BinaryArchive::WriteArray( const ON_SimpleArray<ON_ClippingPlaneInfo>& a )
03379 {
03380 int count = a.Count();
03381 if ( count < 0 )
03382 count = 0;
03383 bool rc = WriteInt( count );
03384 for ( int i = 0; i < count && rc ; i++ )
03385 {
03386 rc = a[i].Write(*this);
03387 }
03388 return rc;
03389 }
03390
03391
03395
03396 bool
03397 ON_BinaryArchive::WriteObject( const ON_Object* o )
03398 {
03399 bool rc = false;
03400 if ( o )
03401 rc = WriteObject(*o);
03402 else {
03403
03404 rc = BeginWrite3dmChunk( TCODE_OPENNURBS_CLASS, 0 );
03405 if (rc) {
03406 rc = BeginWrite3dmChunk( TCODE_OPENNURBS_CLASS_UUID, 0 );
03407 if ( rc ) {
03408 rc = WriteUuid( ON_nil_uuid );
03409 if ( !EndWrite3dmChunk() )
03410 rc = false;
03411 }
03412 if ( !EndWrite3dmChunk() )
03413 rc = false;
03414 }
03415 }
03416 return rc;
03417 }
03418
03419 static
03420 bool IsCriticalUserData( const ON_BinaryArchive& ar, const ON_UserData* ud )
03421 {
03422
03423 static const ON_UUID ON_MeshNgonUserData_ID =
03424 { 0x31F55AA3, 0x71FB, 0x49f5, { 0xA9, 0x75, 0x75, 0x75, 0x84, 0xD9, 0x37, 0xFF } };
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435 if ( 0 == ud )
03436 return false;
03437
03438 switch( ar.Archive3dmVersion() )
03439 {
03440 case 50:
03441 if ( ON_opennurbs5_id == ud->m_application_uuid )
03442 {
03443
03444
03445
03446 return true;
03447 }
03448
03449 if ( ON_opennurbs4_id == ud->m_application_uuid )
03450 {
03451
03452
03453
03454 if ( ON_MeshNgonUserData_ID == ud->m_userdata_uuid )
03455 return true;
03456 }
03457 break;
03458
03459 case 4:
03460 if ( ON_opennurbs4_id == ud->m_application_uuid )
03461 {
03462
03463
03464
03465 if ( ON_MeshNgonUserData_ID == ud->m_userdata_uuid )
03466 return true;
03467 }
03468 break;
03469 }
03470
03471 return false;
03472 }
03473
03474 static
03475 bool HasCriticalUserData( const ON_BinaryArchive& ar, const ON_Object* obj )
03476 {
03477 if ( 0 == obj )
03478 return false;
03479
03480 for ( const ON_UserData* ud = obj->FirstUserData(); 0 != ud; ud = ud->Next() )
03481 {
03482 if ( IsCriticalUserData(ar,ud) )
03483 return true;
03484 }
03485
03486 return false;
03487 }
03488
03489 static
03490 bool IsCoreUserData( const ON_UserData* ud )
03491 {
03492
03493 if ( 0 == ud )
03494 return false;
03495 if ( ud->m_application_uuid == ON_rhino4_id
03496 || ud->m_application_uuid == ON_rhino5_id
03497 || ud->m_application_uuid == ON_rhino_id
03498 || ud->m_application_uuid == ON_opennurbs4_id
03499 || ud->m_application_uuid == ON_opennurbs5_id
03500 || ud->m_application_uuid == ON_opennurbs_id
03501 )
03502 {
03503 return true;
03504 }
03505 return false;
03506 }
03507
03508 bool
03509 ON_BinaryArchive::WriteObject( const ON_Object& o )
03510 {
03511
03512
03513 ON_UUID uuid;
03514 bool rc = false;
03515 const ON_ClassId* pID = o.ClassId();
03516 if ( !pID ) {
03517 ON_ERROR("ON_BinaryArchive::WriteObject() o.ClassId() returned NULL.");
03518 return false;
03519 }
03520 uuid = pID->Uuid();
03521
03522 if ( m_3dm_version <= 2 )
03523 {
03524 if ( ON_Curve::Cast(&o) && !ON_NurbsCurve::Cast(&o) )
03525 {
03526 ON_NurbsCurve nc;
03527 const ON_Curve* curve = static_cast<const ON_Curve*>(&o);
03528 if ( curve->GetNurbForm(nc) )
03529 return WriteObject( nc );
03530 }
03531 else if ( ON_Surface::Cast(&o) && !ON_NurbsSurface::Cast(&o) )
03532 {
03533 ON_NurbsSurface ns;
03534 const ON_Surface* surface = static_cast<const ON_Surface*>(&o);
03535 if ( surface->GetNurbForm(ns) )
03536 return WriteObject( ns );
03537 }
03538 else if( ON_Annotation2::Cast(&o))
03539 {
03540
03541 ON_Annotation2* pA = (ON_Annotation2*)&o;
03542 switch( pA->Type())
03543 {
03544 case ON::dtNothing:
03545 break;
03546 case ON::dtDimLinear:
03547 case ON::dtDimAligned:
03548 {
03549 ON_LinearDimension dim;
03550 ((ON_LinearDimension2*)pA)->GetV2Form( dim);
03551 return WriteObject( dim);
03552 }
03553 case ON::dtDimAngular:
03554 {
03555 ON_AngularDimension dim;
03556 ((ON_AngularDimension2*)pA)->GetV2Form( dim);
03557 return WriteObject( dim);
03558 }
03559 case ON::dtDimDiameter:
03560 case ON::dtDimRadius:
03561 {
03562 ON_RadialDimension dim;
03563 ((ON_RadialDimension2*)pA)->GetV2Form( dim);
03564 return WriteObject( dim);
03565 }
03566 case ON::dtLeader:
03567 {
03568 ON_Leader leader;
03569 ((ON_Leader2*)pA)->GetV2Form( leader);
03570 return WriteObject( leader);
03571 }
03572 case ON::dtTextBlock:
03573 {
03574 ON_TextEntity text;
03575 ((ON_TextEntity2*)pA)->GetV2Form( text);
03576 return WriteObject( text);
03577 }
03578 case ON::dtDimOrdinate:
03579
03580
03581
03582
03583
03584
03585 break;
03586 }
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597 }
03598 }
03599
03600 if ( m_3dm_version <= 4 && ON::extrusion_object == o.ObjectType() )
03601 {
03602
03603
03604
03605 const ON_Extrusion* extrusion = ON_Extrusion::Cast(&o);
03606 if ( 0 != extrusion )
03607 {
03608 ON_Object* v4object = 0;
03609 if ( extrusion->IsCapped() || extrusion->ProfileCount() >= 2 )
03610 v4object = extrusion->BrepForm(0);
03611 if ( 0 == v4object )
03612 v4object = extrusion->SumSurfaceForm(0);
03613 if ( 0 == v4object )
03614 v4object = extrusion->NurbsSurface(0);
03615 if ( 0 != v4object
03616 && ON::extrusion_object != v4object->ObjectType()
03617 )
03618 {
03619
03620
03621
03622
03623
03624 rc = WriteObject( v4object );
03625
03626 delete v4object;
03627 return rc;
03628 }
03629 if ( 0 != v4object )
03630 delete v4object;
03631 }
03632 }
03633
03634 rc = BeginWrite3dmChunk( TCODE_OPENNURBS_CLASS, 0 );
03635 if (rc) {
03636
03637
03638 rc = BeginWrite3dmChunk( TCODE_OPENNURBS_CLASS_UUID, 0 );
03639 if ( rc ) {
03640 rc = WriteUuid( uuid );
03641 if ( !EndWrite3dmChunk() )
03642 rc = false;
03643 }
03644
03645
03646 if ( rc ) {
03647 rc = BeginWrite3dmChunk( TCODE_OPENNURBS_CLASS_DATA, 0 );
03648 if (rc)
03649 {
03650 rc = o.Write( *this )?true:false;
03651 if ( !rc ) {
03652 ON_ERROR("ON_BinaryArchive::WriteObject() o.Write() failed.");
03653 }
03654 if ( !EndWrite3dmChunk() )
03655 rc = false;
03656 }
03657 }
03658
03659 if (rc && (m_bSaveUserData || HasCriticalUserData(*this,&o) ) )
03660 {
03661
03662
03663 rc = WriteObjectUserData(o);
03664 }
03665
03666
03667 if ( BeginWrite3dmChunk( TCODE_OPENNURBS_CLASS_END, 0 ) ) {
03668 if ( !EndWrite3dmChunk() )
03669 rc = false;
03670 }
03671 else
03672 rc = false;
03673
03674 if ( !EndWrite3dmChunk() )
03675 rc = false;
03676 }
03677
03678 return rc;
03679 }
03680
03681 bool ON_BinaryArchive::WriteObjectUserData( const ON_Object& object )
03682 {
03683 if ( m_3dm_version < 3 )
03684 {
03685
03686 return true;
03687 }
03688
03689
03690 bool rc = true;
03691 const ON_UserData* ud;
03692 ON_UUID userdata_classid;
03693
03694 for (ud = object.m_userdata_list; ud && rc; ud = ud->m_userdata_next)
03695 {
03696 if ( !ud->Archive() )
03697 {
03698 continue;
03699 }
03700
03701 if ( false == m_bSaveUserData )
03702 {
03703
03704
03705
03706 if ( false == IsCriticalUserData(*this,ud) )
03707 continue;
03708 }
03709
03710
03711
03712 if ( 0 == ON_UuidCompare( ud->m_userdata_uuid, ON_nil_uuid ) )
03713 continue;
03714 if ( &object != ud->m_userdata_owner )
03715 continue;
03716 const ON_ClassId* cid = ud->ClassId();
03717 if ( 0 == cid )
03718 continue;
03719 if ( cid == &ON_UserData::m_ON_UserData_class_id )
03720 continue;
03721 if ( cid == &ON_UserData::m_ON_Object_class_id )
03722 continue;
03723
03724
03725
03726
03727
03728 userdata_classid = ud->UserDataClassUuid();
03729 if ( 0 == ON_UuidCompare( userdata_classid, ON_nil_uuid ) )
03730 continue;
03731 if ( 0 == ON_UuidCompare( userdata_classid, ON_UserData::m_ON_UserData_class_id.Uuid() ) )
03732 continue;
03733 if ( 0 == ON_UuidCompare( userdata_classid, ON_Object::m_ON_Object_class_id.Uuid() ) )
03734 continue;
03735 if ( 0 == ON_UuidCompare( userdata_classid, ON_UnknownUserData::m_ON_Object_class_id.Uuid() ) )
03736 continue;
03737
03738 if ( 3 == m_3dm_version )
03739 {
03740
03741
03742
03743 if ( m_V3_plugin_id_list.BinarySearch( &ud->m_application_uuid, ON_UuidCompare ) < 0 )
03744 continue;
03745 }
03746
03747 if ( ON_UuidIsNil( ud->m_application_uuid ) )
03748 {
03749
03750
03751
03752 ON_Error(__FILE__,__LINE__,"Not saving %s userdata - m_application_uuid is nil.",cid->ClassName());
03753 continue;
03754 }
03755
03756
03757
03758 const ON_UnknownUserData* unknown_ud = ON_UnknownUserData::Cast(ud);
03759 if ( 0 == unknown_ud )
03760 {
03761 if ( ud->IsUnknownUserData() )
03762 {
03763 ON_ERROR("ON_UnknownUserData::Cast(ud) is null and ud->IsUnknownUserData() is true.");
03764 continue;
03765 }
03766 }
03767 else
03768 {
03769 if ( !ud->IsUnknownUserData() )
03770 {
03771 ON_ERROR("ON_UnknownUserData::Cast(ud) is not null and ud->IsUnknownUserData() is false.");
03772 continue;
03773 }
03774 }
03775
03776 if ( 0 != unknown_ud )
03777 {
03778 if ( false == m_bSaveUserData )
03779 continue;
03780
03781 if ( unknown_ud->m_3dm_version <= 3 )
03782 continue;
03783
03784 if ( unknown_ud->m_3dm_version > 5 && unknown_ud->m_3dm_version < 50 )
03785 continue;
03786
03787 if ( unknown_ud->m_3dm_opennurbs_version < 200701010 )
03788 continue;
03789
03790 if ( unknown_ud->m_3dm_version >= 50 && m_3dm_version < 50 )
03791 {
03792
03793
03794
03795
03796
03797
03798 continue;
03799 }
03800 }
03801
03802
03803
03804 rc = BeginWrite3dmChunk( TCODE_OPENNURBS_CLASS_USERDATA, 0 );
03805 if (rc) {
03806 rc = Write3dmChunkVersion(2,2);
03807
03808 rc = BeginWrite3dmChunk( TCODE_OPENNURBS_CLASS_USERDATA_HEADER, 0 );
03809 if (rc)
03810 {
03811 if ( rc ) rc = WriteUuid( userdata_classid );
03812 if ( rc ) rc = WriteUuid( ud->m_userdata_uuid );
03813 if ( rc ) rc = WriteInt( ud->m_userdata_copycount );
03814 if ( rc ) rc = WriteXform( ud->m_userdata_xform );
03815
03816
03817 if ( rc ) rc = WriteUuid( ud->m_application_uuid );
03818
03819
03820 if ( rc )
03821 {
03822 rc = WriteBool( unknown_ud ? true : false );
03823 int ver = unknown_ud ? unknown_ud->m_3dm_version : m_3dm_version;
03824 rc = WriteInt( ver );
03825 ver = unknown_ud ? unknown_ud->m_3dm_opennurbs_version : m_3dm_opennurbs_version;
03826 if (rc) rc = WriteInt( ver );
03827 }
03828
03829 if ( !EndWrite3dmChunk() )
03830 rc = false;
03831 }
03832 if (rc)
03833 {
03834
03835 rc = BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 0 );
03836 if ( rc )
03837 {
03838 if ( 0 != unknown_ud )
03839 {
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852 m_chunk.Last()->m_do_crc16 = 0;
03853 m_chunk.Last()->m_do_crc32 = 0;
03854 m_bDoChunkCRC = false;
03855 }
03856 rc = ud->Write(*this)?true:false;
03857 if ( !EndWrite3dmChunk() )
03858 rc = false;
03859 }
03860 }
03861 if ( !EndWrite3dmChunk() )
03862 rc = false;
03863 }
03864 }
03865 return rc;
03866 }
03867
03868 int
03869 ON_BinaryArchive::LoadUserDataApplication( ON_UUID application_id )
03870 {
03871
03872
03873 return 0;
03874 }
03875
03876 int ON_BinaryArchive::ReadObject( ON_Object** ppObject )
03877 {
03878 if ( !ppObject )
03879 {
03880 ON_ERROR("ON_BinaryArchive::ReadObject() called with NULL ppObject.");
03881 return 0;
03882 }
03883 *ppObject = 0;
03884 return ReadObjectHelper(ppObject);
03885 }
03886
03887 int ON_BinaryArchive::ReadObject( ON_Object& object )
03888 {
03889 ON_Object* pObject = &object;
03890 return ReadObjectHelper(&pObject);
03891 }
03892
03893 int ON_BinaryArchive::ReadObjectHelper( ON_Object** ppObject )
03894 {
03895
03896
03897
03898
03899
03900 ON__UINT32 tcode;
03901 ON__INT64 length_TCODE_OPENNURBS_CLASS = 0;
03902 ON__INT64 length_TCODE_OPENNURBS_CLASS_UUID = 0;
03903 ON__INT64 length_TCODE_OPENNURBS_CLASS_DATA = 0;
03904 ON_UUID uuid;
03905 const ON_ClassId* pID = 0;
03906 ON_Object* pObject = *ppObject;
03907 int rc = 0;
03908 const ON__INT64 sizeof_chunk_header = (ON__INT64)(4 + SizeofChunkLength());
03909 const ON__INT64 expected_length_TCODE_OPENNURBS_CLASS_UUID = 20;
03910
03911
03912
03913
03914
03915 rc = BeginRead3dmBigChunk( &tcode, &length_TCODE_OPENNURBS_CLASS );
03916 if ( !rc )
03917 return 0;
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935
03936
03937
03938
03939
03940
03941
03942 if ( tcode != TCODE_OPENNURBS_CLASS )
03943 {
03944 ON_ERROR("ON_BinaryArchive::ReadObject() didn't find TCODE_OPENNURBS_CLASS block.");
03945 rc = 0;
03946 }
03947 else if ( length_TCODE_OPENNURBS_CLASS < expected_length_TCODE_OPENNURBS_CLASS_UUID + sizeof_chunk_header)
03948 {
03949 ON_ERROR("ON_BinaryArchive::ReadObject() TCODE_OPENNURBS_CLASS chunk length too small.");
03950 rc = 0;
03951 }
03952 else
03953 {
03954
03955 for (;;)
03956 {
03957
03958 rc = BeginRead3dmBigChunk( &tcode, &length_TCODE_OPENNURBS_CLASS_UUID );
03959 if ( !rc )
03960 break;
03961 if ( tcode != TCODE_OPENNURBS_CLASS_UUID )
03962 {
03963 ON_ERROR("ON_BinaryArchive::ReadObject() didn't find TCODE_OPENNURBS_CLASS_UUID block");
03964 rc = 0;
03965 }
03966 else if ( expected_length_TCODE_OPENNURBS_CLASS_UUID != length_TCODE_OPENNURBS_CLASS_UUID )
03967 {
03968 ON_ERROR("ON_BinaryArchive::ReadObject() TCODE_OPENNURBS_CLASS_UUID has invalid length");
03969 rc = 0;
03970 }
03971 else if ( !ReadUuid( uuid ) )
03972 {
03973 rc = 0;
03974 }
03975 if ( !EndRead3dmChunk() )
03976 {
03977 rc = 0;
03978 }
03979 if ( !rc ) {
03980 break;
03981 }
03983
03984 if ( !ON_UuidCompare( &uuid, &ON_nil_uuid ) ) {
03985
03986 rc = 1;
03987 break;
03988 }
03989
03990
03991 if ( pObject )
03992 {
03993 pID = pObject->ClassId();
03994 if ( uuid != pID->Uuid() )
03995 {
03996 ON_ERROR("ON_BinaryArchive::ReadObject() - uuid does not match intput pObject's class id.");
03997 pID = 0;
03998 rc = 2;
03999 break;
04000 }
04001 }
04002 else
04003 {
04004 pID = ON_ClassId::ClassId( uuid );
04005 }
04006 if ( !pID )
04007 {
04008
04009
04010
04011
04012
04013 ON_WARNING("ON_BinaryArchive::ReadObject() ON_ClassId::ClassId(uuid) returned NULL.");
04014 rc = 3;
04015 break;
04016 }
04018
04019
04020 rc = BeginRead3dmBigChunk( &tcode, &length_TCODE_OPENNURBS_CLASS_DATA );
04021 if ( !rc )
04022 break;
04023 if ( tcode != TCODE_OPENNURBS_CLASS_DATA )
04024 {
04025 ON_ERROR("ON_BinaryArchive::ReadObject() didn't find TCODE_OPENNURBS_CLASS_DATA block");
04026 rc = 0;
04027 }
04028 else if ( length_TCODE_OPENNURBS_CLASS_DATA <= 0 )
04029 {
04030 ON_ERROR("ON_BinaryArchive::ReadObject() TCODE_OPENNURBS_CLASS_DATA chunk length too small");
04031 rc = 0;
04032 }
04033 else
04034 {
04035 if ( !pObject )
04036 {
04037 pObject = pID->Create();
04038 }
04039
04040 if ( !pObject )
04041 {
04042 ON_ERROR("ON_BinaryArchive::ReadObject() pID->Create() returned NULL.");
04043 rc = 0;
04044 }
04045 else
04046 {
04047 rc = pObject->Read(*this);
04048 if ( !rc )
04049 {
04050 ON_ERROR("ON_BinaryArchive::ReadObject() pObject->Read() failed.");
04051 delete pObject;
04052
04053 }
04054 else
04055 {
04056 *ppObject = pObject;
04057 }
04058 }
04059 }
04060 if ( !EndRead3dmChunk() )
04061 {
04062 rc = 0;
04063 }
04064
04065 if ( rc && 0 != pObject )
04066 {
04067
04068
04069
04070 if (!ReadObjectUserData(*pObject))
04071 rc = 0;
04072 }
04073
04074 break;
04075 }
04076 }
04077 if ( !EndRead3dmChunk() )
04078 rc = 0;
04079
04080 return rc;
04081 }
04082
04083 bool ON_BinaryArchive::ReadObjectUserDataAnonymousChunk(
04084 const ON__UINT64 length_TCODE_ANONYMOUS_CHUNK,
04085 const int archive_3dm_version,
04086 const int archive_opennurbs_version,
04087 ON_UserData* ud )
04088 {
04089
04090
04091
04092 bool rc = false;
04093
04094 if ( 0 == ud )
04095 return false;
04096
04097 if ( ud->IsUnknownUserData()
04098 || (archive_3dm_version == Archive3dmVersion()
04099 && archive_opennurbs_version == ArchiveOpenNURBSVersion()
04100 && IsCoreUserData(ud))
04101 )
04102 {
04103
04104 ON_ReadChunkHelper ch(*this);
04105 if ( !ch.m_bReadSuccess
04106 || TCODE_ANONYMOUS_CHUNK != ch.m_chunk_tcode
04107 || length_TCODE_ANONYMOUS_CHUNK != (ON__UINT64)ch.m_chunk_value
04108 )
04109 {
04110 return false;
04111 }
04112 if ( ud->IsUnknownUserData() )
04113 {
04114
04115
04116
04117
04118 m_chunk.Last()->m_do_crc16 = false;
04119 m_chunk.Last()->m_do_crc32 = false;
04120 m_bDoChunkCRC = false;
04121 }
04122 rc = ud->Read(*this) ? true : false;
04123 }
04124 else
04125 {
04126
04127
04128
04129
04130 unsigned char stack_buffer[2048];
04131 const size_t sizeof_buffer = (size_t)(length_TCODE_ANONYMOUS_CHUNK + 4 + SizeofChunkLength());
04132 void* freeme = 0;
04133 void* buffer = (sizeof_buffer <= sizeof(stack_buffer))
04134 ? &stack_buffer[0]
04135 : (freeme = onmalloc(sizeof_buffer));
04136 if ( 0 != buffer
04137 && sizeof_buffer == ReadBuffer(sizeof_buffer,buffer)
04138 )
04139 {
04140 ON_Read3dmBufferArchive memory_archive(
04141 sizeof_buffer,
04142 buffer,
04143 false,
04144 archive_3dm_version,
04145 archive_opennurbs_version
04146 );
04147
04148
04149
04150
04151
04152
04153
04154
04155
04156 bool bTweakArchiveVersion = (memory_archive.SizeofChunkLength() != SizeofChunkLength());
04157 if ( bTweakArchiveVersion )
04158 memory_archive.SetArchive3dmVersion(Archive3dmVersion());
04159 ON_ReadChunkHelper ch(memory_archive);
04160 if ( bTweakArchiveVersion )
04161 memory_archive.SetArchive3dmVersion(archive_3dm_version);
04162
04163 if ( !ch.m_bReadSuccess
04164 || TCODE_ANONYMOUS_CHUNK != ch.m_chunk_tcode
04165 || length_TCODE_ANONYMOUS_CHUNK != (ON__UINT64)ch.m_chunk_value
04166 )
04167 rc = false;
04168 else
04169 rc = ud->Read(memory_archive) ? true : false;
04170 }
04171 if ( freeme )
04172 onfree(freeme);
04173 }
04174 return rc;
04175 }
04176
04177
04178 class CUserDataHeaderInfo
04179 {
04180 public:
04181 CUserDataHeaderInfo();
04182
04183 void Initialize();
04184
04185 ON_UUID m_classid;
04186 ON_UUID m_itemid;
04187 ON_UUID m_appid;
04188 int m_3dm_version;
04189 int m_3dm_opennurbs_version;
04190 int m_copycount;
04191 bool m_bLastSavedAsGoo;
04192 ON_Xform m_xform;
04193 };
04194
04195 CUserDataHeaderInfo::CUserDataHeaderInfo()
04196 {
04197 Initialize();
04198 }
04199
04200 void CUserDataHeaderInfo::Initialize()
04201 {
04202 memset(this,0,sizeof(*this));
04203 }
04204
04205 static
04206 bool ReadObjectUserDataHeaderHelper(
04207 ON_BinaryArchive& binary_archive,
04208 const int major_userdata_version,
04209 const int minor_userdata_version,
04210 CUserDataHeaderInfo& ud_header
04211 )
04212 {
04213 bool rc = true;
04214 ON__UINT32 t = 0;
04215 ON__INT64 length_TCODE_OPENNURBS_CLASS_USERDATA_HEADER = 0;
04216
04217 ud_header.Initialize();
04218
04219 if ( major_userdata_version == 2 )
04220 {
04221
04222
04223 rc = binary_archive.BeginRead3dmBigChunk( &t, &length_TCODE_OPENNURBS_CLASS_USERDATA_HEADER );
04224 if (!rc)
04225 return false;
04226 if ( t != TCODE_OPENNURBS_CLASS_USERDATA_HEADER )
04227 {
04228 ON_ERROR("version 2.0 TCODE_OPENNURBS_CLASS_USERDATA chunk is missing TCODE_OPENNURBS_CLASS_USERDATA_HEADER chunk.");
04229 binary_archive.EndRead3dmChunk();
04230 return false;
04231 }
04232 }
04233
04234 if (rc) rc = binary_archive.ReadUuid( ud_header.m_classid );
04235 if (rc) rc = binary_archive.ReadUuid( ud_header.m_itemid );
04236 if (rc) rc = binary_archive.ReadInt( &ud_header.m_copycount );
04237 if (rc) rc = binary_archive.ReadXform( ud_header.m_xform );
04238 if ( major_userdata_version == 2 )
04239 {
04240 if ( minor_userdata_version >= 1 )
04241 {
04242 if (rc) rc = binary_archive.ReadUuid( ud_header.m_appid );
04243 if ( minor_userdata_version >= 2 )
04244 {
04245
04246
04247 if (rc) rc = binary_archive.ReadBool( &ud_header.m_bLastSavedAsGoo );
04248 if (rc) rc = binary_archive.ReadInt( &ud_header.m_3dm_version );
04249 if (rc) rc = binary_archive.ReadInt( &ud_header.m_3dm_opennurbs_version );
04250 }
04251 }
04252 if ( !binary_archive.EndRead3dmChunk() )
04253 rc = 0;
04254 }
04255
04256 if (!rc)
04257 {
04258 ON_ERROR("Unable to read user data header information.");
04259 return false;
04260 }
04261
04262 if ( 0 == ud_header.m_3dm_version || 0 == ud_header.m_3dm_opennurbs_version )
04263 {
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275 if ( binary_archive.Archive3dmVersion() < 50 )
04276 {
04277 ud_header.m_3dm_version = binary_archive.Archive3dmVersion();
04278 }
04279 else
04280 {
04281
04282
04283
04284 ud_header.m_bLastSavedAsGoo = true;
04285 ud_header.m_3dm_version = 5;
04286 }
04287 ud_header.m_3dm_opennurbs_version = binary_archive.ArchiveOpenNURBSVersion();
04288 if ( ud_header.m_3dm_opennurbs_version >= 200910190 )
04289 {
04290 ud_header.m_3dm_opennurbs_version = 200910180;
04291 ud_header.m_bLastSavedAsGoo = true;
04292 }
04293 }
04294
04295 return rc;
04296 }
04297
04298 bool ON_BinaryArchive::ReadObjectUserData( ON_Object& object )
04299 {
04300 bool rc = true;
04301 while(rc)
04302 {
04303 ON_ReadChunkHelper ch(*this);
04304 if ( !ch.m_bReadSuccess )
04305 {
04306 rc = false;
04307 break;
04308 }
04309
04310 if ( TCODE_OPENNURBS_CLASS_END == ch.m_chunk_tcode )
04311 {
04312
04313 break;
04314 }
04315
04316 if ( TCODE_OPENNURBS_CLASS_USERDATA != ch.m_chunk_tcode )
04317 {
04318
04319 continue;
04320 }
04321
04322 if ( ch.m_chunk_value < (ON__INT64)(8 + 4 * SizeofChunkLength()) )
04323 {
04324 ON_ERROR("TCODE_OPENNURBS_CLASS_USERDATA chunk is too short");
04325 continue;
04326 }
04327
04328
04329 int major_userdata_version = 0;
04330 int minor_userdata_version = 0;
04331 rc = Read3dmChunkVersion( &major_userdata_version, &minor_userdata_version );
04332 if ( !rc )
04333 {
04334 ON_ERROR("Unable to read TCODE_OPENNURBS_CLASS_USERDATA chunk version numbers");
04335 break;
04336 }
04337
04338 if ( major_userdata_version < 1 || major_userdata_version > 2 )
04339 {
04340
04341 continue;
04342 }
04343
04344 CUserDataHeaderInfo ud_header;
04345 rc = ReadObjectUserDataHeaderHelper(*this,major_userdata_version,minor_userdata_version,ud_header);
04346 if (!rc)
04347 {
04348 ON_ERROR("Unable to read user data header information.");
04349 break;
04350 }
04351
04352
04353 ON__INT64 length_TCODE_ANONYMOUS_CHUNK = 0;
04354 for(;;)
04355 {
04356 ON__UINT32 t = 0;
04357 rc = PeekAt3dmBigChunkType( &t, &length_TCODE_ANONYMOUS_CHUNK );
04358 if (!rc)
04359 break;
04360 if ( t != TCODE_ANONYMOUS_CHUNK )
04361 {
04362 ON_ERROR("Reading object user data - unable to find TCODE_ANONYMOUS_CHUNK");
04363 rc = false;
04364 break;
04365 }
04366 if ( length_TCODE_ANONYMOUS_CHUNK < 4 )
04367 {
04368 ON_ERROR("Reading object user data - length of TCODE_ANONYMOUS_CHUNK < 4");
04369 rc = false;
04370 break;
04371 }
04372 break;
04373 }
04374 if (!rc)
04375 {
04376 break;
04377 }
04378
04379
04380 ON_UserData* ud = 0;
04381 for(;;)
04382 {
04383 const ON_ClassId* udId = ON_ClassId::ClassId( ud_header.m_classid );
04384 if ( 0 == udId )
04385 {
04386
04387 if ( !ON_UuidIsNil(ud_header.m_appid) )
04388 {
04389
04390 if ( 1 == LoadUserDataApplication(ud_header.m_appid) )
04391 {
04392
04393 udId = ON_ClassId::ClassId( ud_header.m_classid );
04394 }
04395 }
04396
04397 if ( 0 == udId )
04398 {
04399
04400
04401
04402
04403 udId = &ON_UnknownUserData::m_ON_UnknownUserData_class_id;
04404 }
04405 }
04406
04407 ON_Object* tmp = udId->Create();
04408 ud = ON_UserData::Cast(tmp);
04409 if ( 0 == ud )
04410 {
04411 ON_ERROR("Reading object user data - unable to create userdata class");
04412 if ( tmp )
04413 delete tmp;
04414 tmp = 0;
04415 break;
04416 }
04417 tmp = 0;
04418
04419 break;
04420 }
04421
04422 if ( 0 == ud )
04423 {
04424
04425
04426
04427 ON_ERROR("Unable to create object user data class. Flawed class id information.");
04428 continue;
04429 }
04430
04431 if ( ON_UuidIsNil(ud->m_application_uuid) )
04432 {
04433 if ( ON_UuidIsNil(ud_header.m_appid) )
04434 {
04435 switch( Archive3dmVersion())
04436 {
04437 case 2:
04438
04439
04440 ud_header.m_appid = ON_v2_userdata_id;
04441 break;
04442 case 3:
04443
04444
04445
04446 ud_header.m_appid = ON_v3_userdata_id;
04447 break;
04448 case 4:
04449 if ( ArchiveOpenNURBSVersion() < 200909190 )
04450 {
04451
04452
04453 ud_header.m_appid = ON_v4_userdata_id;
04454 }
04455 break;
04456 }
04457 }
04458 ud->m_application_uuid = ud_header.m_appid;
04459 }
04460 ud->m_userdata_uuid = ud_header.m_itemid;
04461 ud->m_userdata_copycount = ud_header.m_copycount;
04462 ud->m_userdata_xform = ud_header.m_xform;
04463 if ( ud->IsUnknownUserData() )
04464 {
04465 ON_UnknownUserData* uud = ON_UnknownUserData::Cast(ud);
04466 if ( uud )
04467 {
04468 uud->m_sizeof_buffer = (int)length_TCODE_ANONYMOUS_CHUNK;
04469 uud->m_unknownclass_uuid = ud_header.m_classid;
04470 uud->m_3dm_version = ud_header.m_3dm_version;
04471 uud->m_3dm_opennurbs_version = ud_header.m_3dm_opennurbs_version;
04472 }
04473 }
04474 ud->m_userdata_owner = &object;
04475 bool bReadUserData = ReadObjectUserDataAnonymousChunk(
04476 length_TCODE_ANONYMOUS_CHUNK,
04477 ud_header.m_3dm_version,
04478 ud_header.m_3dm_opennurbs_version,
04479 ud
04480 );
04481 ud->m_userdata_owner = 0;
04482 if (bReadUserData)
04483 {
04484 if ( !object.AttachUserData( ud ) )
04485 delete ud;
04486 }
04487 else
04488 {
04489 delete ud;
04490 }
04491 }
04492
04493 return rc;
04494 }
04495
04496 bool ON_BinaryArchive::Write3dmChunkVersion(
04497 int major_version,
04498 int minor_version
04499 )
04500 {
04501 const unsigned char v = (unsigned char)(major_version*16+minor_version);
04502 return WriteChar( v );
04503 }
04504
04505 bool ON_BinaryArchive::Read3dmChunkVersion(
04506 int* major_version,
04507 int* minor_version
04508 )
04509 {
04510 unsigned char v = 0;
04511 bool rc = ReadChar( &v );
04512 if ( minor_version) *minor_version = v%16;
04513
04514
04515
04516
04517 if ( major_version) *major_version = (v>>4);
04518 return rc;
04519 }
04520
04521 int ON_BinaryArchive::Archive3dmVersion() const
04522 {
04523 return m_3dm_version;
04524 }
04525
04526 int ON_BinaryArchive::ArchiveOpenNURBSVersion() const
04527 {
04528 return m_3dm_opennurbs_version;
04529 }
04530
04531 size_t ON_BinaryArchive::ArchiveStartOffset() const
04532 {
04533 return m_3dm_start_section_offset;
04534 }
04535
04539
04540 bool
04541 ON_BinaryArchive::BeginWrite3dmChunk( unsigned int typecode, int value )
04542 {
04543 ON__INT64 value64 = 0;
04544 if ( 0 != value )
04545 {
04546 if ( ON_IsUnsignedChunkTypecode(typecode) )
04547 {
04548
04549 ON__UINT32 u32 = (ON__UINT32)value;
04550 ON__UINT64 u64 = u32;
04551 value64 = (ON__INT64)u64;
04552 }
04553 else
04554 {
04555
04556 value64 = value;
04557 }
04558 }
04559 return BeginWrite3dmBigChunk(typecode,value);
04560 }
04561
04562 bool
04563 ON_BinaryArchive::BeginWrite3dmBigChunk( ON__UINT32 typecode, ON__INT64 value64 )
04564 {
04565 m_bDoChunkCRC = false;
04566 bool rc = WriteInt32( 1, (ON__INT32*)&typecode );
04567 if (rc)
04568 rc = WriteChunkValue( typecode, value64 );
04569 if (rc)
04570 rc = PushBigChunk( typecode, value64 );
04571 return rc;
04572 }
04573
04574 bool
04575 ON_BinaryArchive::BeginWrite3dmChunk(
04576 unsigned int tcode,
04577 int major_version,
04578 int minor_version
04579 )
04580 {
04581 bool rc = false;
04582 if ( 0 == tcode )
04583 {
04584 ON_ERROR("ON_BinaryArchive::BeginWrite3dmChunk - input tcode = 0");
04585 }
04586 else if ( 0 != (tcode & TCODE_SHORT) )
04587 {
04588 ON_ERROR("ON_BinaryArchive::BeginWrite3dmChunk - input tcode has short flag set.");
04589 }
04590 else if ( major_version <= 0 )
04591 {
04592 ON_ERROR("ON_BinaryArchive::BeginWrite3dmChunk - input major_version <= 0.");
04593 }
04594 else if ( minor_version < 0 )
04595 {
04596 ON_ERROR("ON_BinaryArchive::BeginWrite3dmChunk - input minor_version < 0.");
04597 }
04598 else
04599 {
04600 rc = BeginWrite3dmChunk(tcode,0);
04601 if (rc)
04602 {
04603 rc = WriteInt(major_version);
04604 if (rc)
04605 rc = WriteInt(minor_version);
04606 if ( !rc)
04607 EndWrite3dmChunk();
04608 }
04609 }
04610 return rc;
04611 }
04612
04613 bool
04614 ON_BinaryArchive::EndWrite3dmChunk()
04615 {
04616 bool rc = false;
04617 ON_3DM_BIG_CHUNK* c = m_chunk.Last();
04618 if ( c ) {
04619 if ( c->m_bLongChunk )
04620 {
04621 if ( c->m_do_crc16 )
04622 {
04623
04624 unsigned char two_zero_bytes[2] = {0,0};
04625 ON__UINT16 crc = ON_CRC16( c->m_crc16, 2, two_zero_bytes );
04626 rc = WriteInt16( 1, (ON__INT16*)&crc );
04627 if (c->m_crc16)
04628 {
04629
04630 m_bad_CRC_count++;
04631 ON_ERROR("ON_BinaryArchive::EndWrite3dmChunk: CRC16 computation error.");
04632 }
04633 }
04634 else if ( c->m_do_crc32 )
04635 {
04636
04637 const ON__UINT32 crc0 = c->m_crc32;
04638 rc = WriteInt32( 1, (ON__INT32*)&crc0 );
04639 }
04640 else {
04641 rc = true;
04642 }
04643
04644
04645 m_bDoChunkCRC = 0;
04646 const size_t offset = CurrentPosition();
04647 if ( offset < c->m_big_offset )
04648 {
04649 ON_ERROR("ON_BinaryArchive::EndWrite3dmChunk() - chunk length < 0");
04650 rc = false;
04651 }
04652 else
04653 {
04654 ON__UINT64 length = (offset - c->m_big_offset);
04655 if ( !BigSeekBackward( length + SizeofChunkLength() ) )
04656 {
04657 rc = false;
04658 }
04659 else
04660 {
04661 if ( !WriteChunkLength( length ) )
04662 {
04663 rc = false;
04664 }
04665 if ( !BigSeekForward( length ) )
04666 {
04667 rc = false;
04668 }
04669 }
04670 if ( CurrentPosition() != offset )
04671 {
04672 ON_ERROR("ON_BinaryArchive::EndWrite3dmChunk() - CurrentPosition() != offset");
04673 rc = false;
04674 }
04675 }
04676 }
04677 else
04678 {
04679
04680 rc = true;
04681 }
04682
04683 m_chunk.Remove();
04684 c = m_chunk.Last();
04685 if ( !c )
04686 {
04687 Flush();
04688 }
04689 m_bDoChunkCRC = c && (c->m_do_crc16 || c->m_do_crc32);
04690 }
04691 return rc;
04692 }
04693
04694 bool ON_BinaryArchive::Write3dmGoo( const ON_3dmGoo& goo )
04695 {
04696 bool rc = false;
04697
04698 if ( goo.m_typecode ) {
04699 const bool savedDoCRC = m_bDoChunkCRC;
04700 m_bDoChunkCRC = false;
04701 if ( 0 != (goo.m_typecode & TCODE_SHORT) ) {
04702 if ( goo.m_value == 0 || (goo.m_value > 0 && goo.m_goo) ) {
04703
04704
04705
04706 rc = WriteInt( goo.m_typecode );
04707 if (rc) rc = WriteInt( goo.m_value );
04708 if (rc && goo.m_value>0) rc = WriteByte( goo.m_value, goo.m_goo );
04709 }
04710 }
04711 else {
04712
04713 rc = WriteInt( goo.m_typecode );
04714 if (rc) rc = WriteInt( goo.m_value );
04715 }
04716 m_bDoChunkCRC = savedDoCRC;
04717 }
04718
04719 return rc;
04720 }
04721
04722 bool ON_BinaryArchive::PeekAt3dmChunkType( unsigned int* typecode, int* value )
04723 {
04724
04725 bool rc;
04726 unsigned int tc = 0;
04727 ON__INT64 i64 = 0;
04728 rc = PeekAt3dmBigChunkType(&tc,&i64);
04729 if ( rc )
04730 {
04731 if ( 0 != typecode )
04732 *typecode = tc;
04733 if ( 0 != value )
04734 {
04735 ON__INT32 i32 = 0;
04736 if ( ON_IsUnsignedChunkTypecode(tc) )
04737 rc = DownSizeUINT((ON__UINT64)i64,(ON__UINT32*)&i32);
04738 else
04739 rc = DownSizeINT(i64,&i32);
04740 *value = i32;
04741 }
04742 }
04743 return rc;
04744 }
04745
04746 bool ON_BinaryArchive::PeekAt3dmBigChunkType(
04747 unsigned int* typecode,
04748 ON__INT64* big_value
04749 )
04750 {
04751
04752
04753
04754
04755 bool bDoChunkCRC = m_bDoChunkCRC;
04756 m_bDoChunkCRC = false;
04757
04758 const ON__UINT64 pos0 = CurrentPosition();
04759 ON__UINT32 t = 0;
04760 ON__INT64 v = 0;
04761 bool rc = ReadChunkTypecode( &t );
04762 if (rc)
04763 {
04764 rc = ReadChunkValue( t, &v );
04765 }
04766 const ON__UINT64 pos1 = CurrentPosition();
04767 if ( pos1 > pos0 && !BigSeekBackward( pos1-pos0 ) )
04768 {
04769 rc = false;
04770 }
04771
04772 m_bDoChunkCRC = bDoChunkCRC;
04773
04774 if ( typecode )
04775 *typecode = t;
04776 if ( big_value )
04777 *big_value = v;
04778
04779 return rc;
04780 }
04781
04782
04783 bool ON_BinaryArchive::Seek3dmChunkFromStart(
04784
04785
04786
04787
04788
04789 unsigned int typecode
04790 )
04791 {
04792 bool rc = false;
04793 if ( ReadMode() )
04794 {
04795 const ON__UINT64 pos0 = CurrentPosition();
04796 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
04797 if ( c )
04798 {
04799
04800 if ( !ON_IsLongChunkTypecode(c->m_typecode) )
04801 {
04802 ON_ERROR("ON_BinaryArchive::Seek3dmChunkFromStart() - current chunk is not a long chunk");
04803 return false;
04804 }
04805 if ( c->m_big_value < 0 )
04806 {
04807 ON_ERROR("ON_BinaryArchive::Seek3dmChunkFromStart() called with an active chunk that has m_value < 0");
04808 return false;
04809 }
04810 if ( pos0 < c->m_big_offset || pos0 > c->m_big_offset + c->Length() )
04811 {
04812 ON_ERROR("ON_BinaryArchive::Seek3dmChunkFromStart() called with out of bounds current position");
04813 return false;
04814 }
04815 rc = BigSeekBackward( pos0 - c->m_big_offset );
04816 }
04817 else
04818 {
04819
04820
04821 size_t start_offset = ((m_3dm_start_section_offset > 0) ? m_3dm_start_section_offset : 0);
04822 rc = SeekFromStart( start_offset );
04823 if (!rc && start_offset > 0)
04824 {
04825 start_offset = 0;
04826 rc = SeekFromStart(start_offset);
04827 }
04828 char s3d[33];
04829 memset(s3d,0,sizeof(s3d));
04830 if (rc)
04831 rc = ReadByte(32,s3d);
04832
04833 if (rc)
04834 {
04835 rc = (0 == strncmp( s3d, "3D Geometry File Format ", 24));
04836 if ( !rc && start_offset > 0 )
04837 {
04838 start_offset = 0;
04839 rc = SeekFromStart(start_offset);
04840 if (rc) rc = ReadByte(32,s3d);
04841 rc = (0 == strncmp( s3d, "3D Geometry File Format ", 24));
04842 }
04843 }
04844
04845 if (rc)
04846 {
04847 if ( start_offset != m_3dm_start_section_offset )
04848 m_3dm_start_section_offset = start_offset;
04849 unsigned int t=0;
04850 ON__INT64 v=-1;
04851 rc = PeekAt3dmBigChunkType(&t,&v);
04852 if (rc && (t != 1 || v < 0) )
04853 rc = false;
04854 }
04855 }
04856
04857 if (rc)
04858 {
04859 rc = Seek3dmChunkFromCurrentPosition( typecode );
04860 }
04861
04862 if (!rc)
04863 {
04864 BigSeekFromStart(pos0);
04865 }
04866 }
04867 return rc;
04868 }
04869
04870 ON__UINT64 ON_3DM_BIG_CHUNK::Length() const
04871 {
04872 return (ON_IsLongChunkTypecode(m_typecode) && m_big_value >= 0 )
04873 ? ((ON__UINT64)m_big_value)
04874 : 0;
04875 }
04876
04877 bool ON_BinaryArchive::Seek3dmChunkFromCurrentPosition(
04878
04879
04880
04881
04882
04883 unsigned int typecode
04884 )
04885 {
04886 bool rc = false;
04887 if ( ReadMode() )
04888 {
04889 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
04890 const ON__UINT64 pos1 = c ? c->m_big_offset + c->Length() : 0;
04891 const size_t pos_start = CurrentPosition();
04892 size_t pos_prev = 0;
04893 size_t pos = 0;
04894 unsigned int t;
04895 ON__INT64 v64;
04896 bool bFirstTime = true;
04897 while(pos > pos_prev || bFirstTime)
04898 {
04899 bFirstTime = false;
04900 pos_prev = pos;
04901 pos = CurrentPosition();
04902 if ( pos1 && pos > pos1 )
04903 break;
04904 t = !typecode;
04905 if ( !PeekAt3dmBigChunkType( &t, 0 ) )
04906 break;
04907 if ( t == typecode )
04908 {
04909 rc = true;
04910 break;
04911 }
04912 if ( 0 == t )
04913 {
04914
04915 break;
04916 }
04917 if ( !BeginRead3dmBigChunk( &t, &v64 ) )
04918 break;
04919 if ( !EndRead3dmChunk() )
04920 break;
04921 if ( TCODE_ENDOFTABLE == t && 0 != v64 )
04922 {
04923
04924 break;
04925 }
04926 }
04927 if ( !rc )
04928 {
04929 SeekFromStart( pos_start );
04930 }
04931 }
04932 return rc;
04933 }
04934
04935 bool ON_BinaryArchive::BeginRead3dmChunk( unsigned int* typecode, int* value )
04936 {
04937 ON__UINT32 tc = 0;
04938 ON__INT64 v64 = 0;
04939 bool rc = BeginRead3dmBigChunk(&tc,&v64);
04940 if (rc)
04941 {
04942 if ( 0 != typecode )
04943 *typecode = tc;
04944 rc = DownSizeChunkValue(tc,v64,value);
04945 }
04946 return rc;
04947 }
04948
04949 bool ON_BinaryArchive::BeginRead3dmBigChunk( unsigned int* typecode, ON__INT64* value )
04950 {
04951 ON__UINT32 t = 0;
04952 ON__INT64 v = 0;
04953 m_bDoChunkCRC = false;
04954 const unsigned int saved_error_message_mask = m_error_message_mask;
04955 m_error_message_mask |= 0x0001;
04956 bool rc = ReadChunkTypecode( &t );
04957 m_error_message_mask = saved_error_message_mask;
04958 if (rc)
04959 {
04960 if ( t == TCODE_ENDOFFILE )
04961 {
04962
04963
04964 ON__UINT64 sizeof_file = 0;
04965 if ( rc )
04966 rc = ReadChunkValue( t, &v );
04967 if ( rc && v >= 0 && ((ON__UINT64)v) >= SizeofChunkLength() )
04968 {
04969 ON__UINT64 EOF_chunk_length = (ON__UINT64)v;
04970 ON__UINT64 pos0 = CurrentPosition();
04971 rc = ReadEOFSizeOfFile( &sizeof_file );
04972 ON__UINT64 pos1 = CurrentPosition();
04973 if ( pos0 > 0 && pos1 > pos0 )
04974 {
04975 if ( !BigSeekBackward(pos1-pos0) )
04976 rc = false;
04977 }
04978 if ( rc )
04979 {
04980 if ( BigSeekForward( EOF_chunk_length ) )
04981 {
04982 ON__UINT64 pos2 = CurrentPosition();
04983 if ( m_3dm_version <= 1 )
04984 {
04985 if ( !AtEnd() )
04986 {
04987
04988
04989
04990
04991 t = TCODE_ENDOFFILE_GOO;
04992 }
04993 }
04994 else
04995 {
04996
04997 if ( pos2 != sizeof_file ) {
04998 ON_ERROR("ON_BinaryArchive::BeginRead3dmChunk() - Rogue eof marker in v2 file.\n");
04999 }
05000 }
05001 rc = BigSeekBackward( EOF_chunk_length );
05002 }
05003 }
05004 if ( rc )
05005 rc = PushBigChunk( t, v );
05006 }
05007 else
05008 {
05009 ON_ERROR( "ON_BinaryArchive::BeginRead3dmChunk() - file is damaged." );
05010 rc = false;
05011 t = 0;
05012 }
05013 }
05014 else
05015 {
05016 if ( rc )
05017 rc = ReadChunkValue( t, &v );
05018 if ( rc )
05019 rc = PushBigChunk( t, v );
05020 }
05021 }
05022 if ( typecode )
05023 *typecode = t;
05024 if ( value )
05025 *value = v;
05026 return rc;
05027 }
05028
05029 bool
05030 ON_BinaryArchive::BeginRead3dmChunk(
05031 unsigned int expected_tcode,
05032 int* major_version,
05033 int* minor_version
05034 )
05035 {
05036 bool rc = false;
05037 if ( 0 == expected_tcode )
05038 {
05039 ON_ERROR("ON_BinaryArchive::BeginRead3dmChunk - input expected_tcode = 0");
05040 }
05041 else if ( 0 != (expected_tcode & TCODE_SHORT) )
05042 {
05043 ON_ERROR("ON_BinaryArchive::BeginRead3dmChunk - input expected_tcode has short flag set.");
05044 }
05045 else if ( 0 == major_version )
05046 {
05047 ON_ERROR("ON_BinaryArchive::BeginRead3dmChunk - input major_version NULL");
05048 }
05049 else if ( 0 == minor_version )
05050 {
05051 ON_ERROR("ON_BinaryArchive::BeginRead3dmChunk - input minor_version NULL");
05052 }
05053 else
05054 {
05055 *major_version = 0;
05056 *minor_version = 0;
05057 unsigned int tcode = 0;
05058 ON__INT64 value = 0;
05059 rc = PeekAt3dmBigChunkType(&tcode,&value);
05060 if ( expected_tcode != tcode )
05061 {
05062 ON_ERROR("ON_BinaryArchive::BeginRead3dmChunk - unexpected tcode");
05063 rc = false;
05064 }
05065 else if ( value < 8 )
05066 {
05067 ON_ERROR("ON_BinaryArchive::BeginRead3dmChunk - unexpected chunk length");
05068 rc = false;
05069 }
05070 else
05071 {
05072 tcode = 0;
05073 value = 0;
05074 rc = BeginRead3dmBigChunk(&tcode,&value);
05075 if (rc)
05076 {
05077 if ( expected_tcode != tcode || value < 8 )
05078 {
05079
05080 ON_ERROR("ON_BinaryArchive::BeginRead3dmChunk - unexpected tcode or chunk length - archive driver or device may be bad");
05081 rc = false;
05082 }
05083 else
05084 {
05085 rc = ReadInt(major_version);
05086 if ( rc && *major_version < 1 )
05087 {
05088 ON_ERROR("ON_BinaryArchive::BeginRead3dmChunk - major_version < 1");
05089 rc = false;
05090 }
05091 if (rc)
05092 {
05093 rc = ReadInt(minor_version);
05094 if ( rc && *minor_version < 0 )
05095 {
05096 ON_ERROR("ON_BinaryArchive::BeginRead3dmChunk - minor_version < 0");
05097 rc = false;
05098 }
05099 }
05100 }
05101
05102 if ( !rc )
05103 {
05104
05105 EndRead3dmChunk();
05106 }
05107 }
05108 }
05109 }
05110 return rc;
05111 }
05112 bool ON_BinaryArchive::EndRead3dmChunk()
05113 {
05114 return EndRead3dmChunk(false);
05115 }
05116
05117 bool ON_BinaryArchive::EndRead3dmChunk(bool bSupressPartiallyReadChunkWarning)
05118 {
05119
05120 bool rc = false;
05121 ON_3DM_BIG_CHUNK* c = m_chunk.Last();
05122 if ( c )
05123 {
05124 ON__UINT64 file_offset = CurrentPosition();
05125 ON__UINT64 end_offset = c->m_big_offset;
05126 if ( c->m_bLongChunk )
05127 {
05128 if ( c->m_big_value < 0 )
05129 {
05130 ON_ERROR("ON_BinaryArchive::EndRead3dmChunk - negative chunk length");
05131 }
05132 else
05133 {
05134 end_offset += ((ON__UINT64)c->m_big_value);
05135 }
05136 }
05137
05138 if ( c->m_bLongChunk )
05139 {
05140 if ( c->m_do_crc16 )
05141 {
05142 if ( file_offset+2 == end_offset )
05143 {
05144
05145 unsigned char two_crc_bytes[2] = {0,0};
05146 rc = ReadByte( 2, two_crc_bytes );
05147 if (rc)
05148 {
05149 file_offset+=2;
05150 if (c->m_crc16)
05151 {
05152 m_bad_CRC_count++;
05153 ON_ERROR("ON_BinaryArchive::EndRead3dmChunk: CRC16 error.");
05154 }
05155 }
05156 }
05157 else
05158 {
05159
05160 rc = true;
05161 }
05162 }
05163 else if ( c->m_do_crc32 )
05164 {
05165 if ( file_offset+4 == end_offset )
05166 {
05167
05168 ON__UINT32 crc1 = c->m_crc32;
05169 ON__UINT32 crc0;
05170 rc = ReadInt32( 1, (ON__INT32*)&crc0 );
05171 if (rc)
05172 {
05173 file_offset+=4;
05174 if (crc0 != crc1)
05175 {
05176 m_bad_CRC_count++;
05177 ON_ERROR("ON_BinaryArchive::EndRead3dmChunk: CRC32 error.");
05178 }
05179 }
05180 }
05181 else
05182 {
05183
05184 rc = true;
05185 }
05186 }
05187 else
05188 {
05189
05190 rc = true;
05191 }
05192 }
05193 else
05194 {
05195 rc = true;
05196 }
05197
05198
05199 if ( file_offset < c->m_big_offset )
05200 {
05201 ON_ERROR("ON_BinaryArchive::EndRead3dmChunk: current position before start of current chunk.");
05202 if ( !BigSeekFromStart( end_offset ) )
05203 rc = false;
05204 }
05205 else if ( file_offset > end_offset )
05206 {
05207 ON_ERROR("ON_BinaryArchive::EndRead3dmChunk: current position after end of current chunk.");
05208 if ( !BigSeekFromStart( end_offset ) )
05209 rc = false;
05210 }
05211 else if ( file_offset != end_offset )
05212 {
05213
05214
05215 if ( file_offset != c->m_big_offset )
05216 {
05217 if ( m_3dm_version != 1 || (m_error_message_mask&0x02) == 0 )
05218 {
05219
05220
05221
05222
05223
05224 const int app_opennurbs_version = ON::Version();
05225 const int filev_date = m_3dm_opennurbs_version/10;
05226 const int appv_date = app_opennurbs_version/10;
05227 int file_v = m_3dm_opennurbs_version%10;
05228 int app_v = app_opennurbs_version%10;
05229 if ( 9 == file_v || 9 == app_v )
05230 {
05231
05232 file_v = app_v = 0;
05233 }
05234 if ( file_v <= app_v && filev_date <= appv_date )
05235 {
05236
05237
05238
05239 if (!bSupressPartiallyReadChunkWarning)
05240 {
05241 ON_WARNING("ON_BinaryArchive::EndRead3dmChunk: partially read chunk - skipping bytes at end of current chunk.");
05242 }
05243 }
05244 }
05245 }
05246
05247
05248
05249
05250
05251 if ( end_offset > file_offset )
05252 {
05253 if ( !BigSeekForward(end_offset - file_offset) )
05254 rc = false;
05255 }
05256 else if ( end_offset < file_offset )
05257 {
05258 if ( !BigSeekBackward(file_offset - end_offset) )
05259 rc = false;
05260 }
05261 }
05262
05263 m_chunk.Remove();
05264 c = m_chunk.Last();
05265 m_bDoChunkCRC = (c && (c->m_do_crc16 || c->m_do_crc32));
05266 }
05267 return rc;
05268 }
05269
05270 bool ON_BinaryArchive::BeginWriteDictionary(
05271 ON_UUID dictionary_id,
05272 unsigned int version,
05273 const wchar_t* dictionary_name
05274 )
05275 {
05276 #if defined(ON_COMPILER_MSC)
05277
05278
05279
05280
05281 #pragma warning( push )
05282 #pragma warning( disable : 4127 )
05283 #endif
05284
05285 bool rc = BeginWrite3dmChunk(TCODE_DICTIONARY,1,0);
05286 if ( !rc )
05287 return rc;
05288
05289
05290 rc = BeginWrite3dmChunk(TCODE_DICTIONARY_ID,1,0);
05291 if ( rc )
05292 {
05293 for(;;)
05294 {
05295 rc = WriteUuid(dictionary_id);
05296 if (!rc) break;
05297 rc = WriteInt(version);
05298 if (!rc) break;
05299 if ( sizeof(unsigned short) == sizeof(*dictionary_name) )
05300 {
05301 rc = WriteString((const unsigned short*)dictionary_name);
05302 }
05303 else
05304 {
05305 ON_wString s(dictionary_name);
05306 rc = WriteString(s);
05307 }
05308 if (!rc) break;
05309 break;
05310 }
05311 if ( !EndWrite3dmChunk() )
05312 rc = false;
05313 }
05314
05315 if ( !rc )
05316 EndWrite3dmChunk();
05317 return rc;
05318
05319 #if defined(ON_COMPILER_MSC)
05320 #pragma warning( pop )
05321 #endif
05322 }
05323
05324 bool ON_BinaryArchive::EndWriteDictionary()
05325 {
05326 int chunk_count = m_chunk.Count();
05327 bool rc = ( chunk_count > 0 && TCODE_DICTIONARY == m_chunk[chunk_count-1].m_typecode );
05328 if (rc)
05329 {
05330 rc = BeginWrite3dmChunk(TCODE_DICTIONARY_END,0);
05331 if (rc)
05332 rc = EndWrite3dmChunk();
05333
05334 if ( !EndWrite3dmChunk() )
05335 rc = false;
05336 }
05337 return rc;
05338 }
05339
05340 bool ON_BinaryArchive::BeginWriteDictionaryEntry(
05341 int de_type,
05342 const wchar_t* entry_name
05343 )
05344 {
05345 #if defined(ON_COMPILER_MSC)
05346
05347
05348
05349
05350 #pragma warning( push )
05351 #pragma warning( disable : 4127 )
05352 #endif
05353
05354 bool rc = BeginWrite3dmChunk(TCODE_DICTIONARY_ENTRY,0);
05355 if ( rc )
05356 {
05357 for(;;)
05358 {
05359 rc = WriteInt(de_type);
05360 if (!rc) break;
05361 if ( sizeof(unsigned short) == sizeof(*entry_name) )
05362 {
05363 rc = WriteString((const unsigned short*)entry_name);
05364 }
05365 else
05366 {
05367 ON_wString s(entry_name);
05368 rc = WriteString(s);
05369 }
05370 if (!rc) break;
05371 break;
05372 }
05373 if ( !rc )
05374 EndWrite3dmChunk();
05375 }
05376 return rc;
05377
05378 #if defined(ON_COMPILER_MSC)
05379 #pragma warning( pop )
05380 #endif
05381 }
05382
05383 bool ON_BinaryArchive::EndWriteDictionaryEntry()
05384 {
05385 int chunk_count = m_chunk.Count();
05386 bool rc = ( chunk_count > 0 && TCODE_DICTIONARY_ENTRY == m_chunk[chunk_count-1].m_typecode )
05387 ? EndWrite3dmChunk()
05388 : false;
05389 return rc;
05390 }
05391
05392 bool ON_BinaryArchive::BeginReadDictionary(
05393 ON_UUID* dictionary_id,
05394 unsigned int* version,
05395 ON_wString& dictionary_name
05396 )
05397 {
05398 int major_version = 0;
05399 int minor_version = 0;
05400 bool rc = BeginRead3dmChunk(TCODE_DICTIONARY,&major_version,&minor_version);
05401 if ( rc )
05402 {
05403 for(;;)
05404 {
05405 rc = (1 == major_version);
05406 if (!rc) break;
05407
05408
05409 rc = BeginRead3dmChunk(TCODE_DICTIONARY_ID,&major_version,&minor_version);
05410 if ( !rc ) break;
05411 for(;;)
05412 {
05413 rc = (1==major_version);
05414 if (!rc) break;
05415 ON_UUID id;
05416 rc = ReadUuid(id);
05417 if (!rc) break;
05418 if ( dictionary_id )
05419 *dictionary_id = id;
05420 rc = ReadInt(version);
05421 if (!rc) break;
05422 rc = ReadString(dictionary_name);
05423 if (!rc) break;
05424 break;
05425 }
05426 if ( !EndRead3dmChunk() )
05427 rc = false;
05428 break;
05429 }
05430
05431 if ( !rc )
05432 EndRead3dmChunk();
05433 }
05434 return rc;
05435 }
05436
05437 bool ON_BinaryArchive::EndReadDictionary()
05438 {
05439 int chunk_count = m_chunk.Count();
05440 bool rc = ( chunk_count > 0 && TCODE_DICTIONARY == m_chunk[chunk_count-1].m_typecode )
05441 ? EndRead3dmChunk()
05442 : false;
05443 return rc;
05444 }
05445
05446 int ON_BinaryArchive::BeginReadDictionaryEntry(
05447 int* de_type,
05448 ON_wString& entry_name
05449 )
05450 {
05451 unsigned int tcode = 0;
05452 ON__INT64 chunk_length = 0;
05453 int chunk_count = m_chunk.Count();
05454 int rc = ( chunk_count > 0 && TCODE_DICTIONARY == m_chunk[chunk_count-1].m_typecode )
05455 ? (BeginRead3dmBigChunk(&tcode,&chunk_length)?1:0)
05456 : 0;
05457 if ( de_type )
05458 *de_type = 0;
05459 if ( rc )
05460 {
05461 if ( TCODE_DICTIONARY_ENTRY == tcode )
05462 {
05463 for(;;)
05464 {
05465 rc = 0;
05466 if ( !ReadInt(de_type) )
05467 {
05468 entry_name.Empty();
05469 break;
05470 }
05471 if ( !ReadString(entry_name) )
05472 {
05473 entry_name.Empty();
05474 break;
05475 }
05476 rc = 1;
05477 break;
05478 }
05479 }
05480 else
05481 {
05482 rc = (TCODE_DICTIONARY_END == tcode) ? 2 : 0;
05483 }
05484 if ( 1 != rc )
05485 {
05486 if ( !EndRead3dmChunk() )
05487 rc = 0;
05488 }
05489 }
05490 return rc;
05491 }
05492
05493 bool ON_BinaryArchive::EndReadDictionaryEntry()
05494 {
05495 int chunk_count = m_chunk.Count();
05496 bool rc = ( chunk_count > 0 && TCODE_DICTIONARY_ENTRY == m_chunk[chunk_count-1].m_typecode )
05497 ? EndRead3dmChunk()
05498 : false;
05499 return rc;
05500 }
05501
05502
05503
05504 bool ON_BinaryArchive::Read3dmGoo( ON_3dmGoo& goo )
05505 {
05506
05507
05508
05509 bool rc = false;
05510 if (goo.m_goo)
05511 {
05512 onfree(goo.m_goo);
05513 goo.m_goo = 0;
05514 }
05515 goo.m_typecode = 0;
05516 goo.m_value = 0;
05517 ON_3DM_BIG_CHUNK* c = m_chunk.Last();
05518 if (c)
05519 {
05520 goo.m_typecode = c->m_typecode;
05521 if ( c->m_bLongChunk )
05522 rc = DownSizeUINT(c->Length(),(ON__UINT32*)&goo.m_value);
05523 else
05524 rc = DownSizeINT(c->m_big_value,&goo.m_value);
05525 if ( rc && c->m_bLongChunk && c->m_big_value > 0 )
05526 {
05527 if ( CurrentPosition() == c->m_big_offset )
05528 {
05529
05530
05531
05532
05533
05534
05535 c->m_do_crc16 = 0;
05536 c->m_do_crc32 = 0;
05537 m_bDoChunkCRC = false;
05538 size_t sizeof_goo = (size_t)c->Length();
05539 goo.m_goo = (unsigned char*)onmalloc( sizeof_goo );
05540 rc = ReadByte( sizeof_goo, goo.m_goo );
05541 }
05542 }
05543 }
05544 return rc;
05545 }
05546
05547 bool ON_BinaryArchive::WriteChunkTypecode( ON__UINT32 typecode )
05548 {
05549 return WriteInt32(1,(ON__INT32*)&typecode);
05550 }
05551
05552 bool ON_BinaryArchive::ReadChunkTypecode( ON__UINT32* typecode )
05553 {
05554 ON__UINT32 tc = 0;
05555 bool rc = ReadInt32(1,(ON__INT32*)&tc);
05556 if (rc && typecode )
05557 *typecode = tc;
05558 return rc;
05559 }
05560
05561 bool ON_BinaryArchive::WriteChunkValue( ON__UINT32 typecode, ON__INT64 big_value )
05562 {
05563 bool rc;
05564 if ( 8 == SizeofChunkLength() )
05565 {
05566 rc = WriteInt64(1,&big_value);
05567 }
05568 else if ( ON_IsUnsignedChunkTypecode(typecode) )
05569 {
05570
05571 ON__UINT32 u32 = 0;
05572 rc = DownSizeUINT((ON__UINT64)big_value,&u32);
05573 if ( !WriteInt32(1,(ON__INT32*)&u32) )
05574 rc = false;
05575 }
05576 else
05577 {
05578
05579 ON__INT32 v32 = 0;
05580 rc = DownSizeINT(big_value,&v32);
05581 if ( !WriteInt32(1,&v32) )
05582 rc = false;
05583 }
05584 return rc;
05585 }
05586
05587
05588 bool ON_BinaryArchive::WriteChunkLength( ON__UINT64 length )
05589 {
05590 bool rc;
05591 if ( 8 == SizeofChunkLength() )
05592 {
05593 rc = WriteInt64(1,(ON__INT64*)&length);
05594 }
05595 else
05596 {
05597 ON__UINT32 u32 = 0;
05598 rc = DownSizeUINT(length,&u32);
05599 if ( !WriteInt32(1,(ON__INT32*)&u32) )
05600 rc = false;
05601 }
05602 return rc;
05603 }
05604
05605 bool ON_BinaryArchive::ReadEOFSizeOfFile( ON__UINT64* sizeof_file )
05606 {
05607 bool rc;
05608 ON__INT64 u64 = 0;
05609 if ( 8 == SizeofChunkLength() )
05610 {
05611
05612 rc = ReadInt64(1,(ON__INT64*)&u64);
05613 }
05614 else
05615 {
05616
05617 ON__UINT32 u32 = 0;
05618 rc = ReadInt32(1,(ON__INT32*)&u32);
05619 if ( rc )
05620 u64 = u32;
05621 }
05622 if ( rc && 0 != sizeof_file )
05623 *sizeof_file = u64;
05624 return rc;
05625 }
05626
05627 bool ON_BinaryArchive::WriteEOFSizeOfFile( ON__UINT64 sizeof_file )
05628 {
05629 bool rc;
05630 if ( 8 == SizeofChunkLength() )
05631 {
05632
05633 rc = WriteInt64(1,(ON__INT64*)&sizeof_file);
05634 }
05635 else
05636 {
05637
05638 ON__UINT32 u32=0;
05639 DownSizeUINT(sizeof_file,&u32);
05640 rc = WriteInt32(1,(ON__INT32*)&u32);
05641 }
05642 return rc;
05643 }
05644
05645 bool ON_BinaryArchive::ReadChunkValue( ON__UINT32 typecode, ON__INT64* value64 )
05646 {
05647 bool rc;
05648 ON__INT64 i64 = 0;
05649 if ( 8 == SizeofChunkLength() )
05650 {
05651
05652 rc = ReadInt64(1,&i64);
05653 }
05654 else
05655 {
05656
05657 if ( ON_IsUnsignedChunkTypecode(typecode) )
05658 {
05659
05660
05661
05662
05663 ON__UINT32 u32 = 0;
05664 ON__UINT64 u64 = 0;
05665 rc = ReadInt32(1,(ON__INT32*)&u32);
05666 if ( rc )
05667 u64 = u32;
05668 i64 = (ON__INT64)u64;
05669 }
05670 else
05671 {
05672
05673
05674
05675 ON__INT32 i32 = 0;
05676 rc = ReadInt32(1,&i32);
05677 i64 = i32;
05678 }
05679 }
05680 if ( rc && 0 != value64 )
05681 *value64 = i64;
05682 return rc;
05683 }
05684
05685 size_t ON_BinaryArchive::SizeofChunkLength() const
05686 {
05687
05688
05689
05690
05691 return (m_3dm_version < 50) ? 4 : 8;
05692 }
05693
05694 bool ON_BinaryArchive::PushBigChunk( ON__UINT32 typecode, ON__INT64 big_value )
05695 {
05696 ON_3DM_BIG_CHUNK c;
05697 memset(&c,0,sizeof(c));
05698 c.m_typecode = typecode;
05699 c.m_big_value = big_value;
05700
05701
05702
05703
05704 if ( 0 == ( TCODE_SHORT & typecode ) && (0 != typecode || 1 != Archive3dmVersion()) )
05705 {
05706 if ( m_3dm_version == 1 && 0 != (TCODE_LEGACY_GEOMETRY & typecode) )
05707 {
05708
05709 c.m_do_crc16 = 1;
05710 c.m_crc16 = 1;
05711 }
05712 else
05713 {
05714
05715 switch(typecode)
05716 {
05717
05718 case TCODE_SUMMARY:
05719 if ( m_3dm_version == 1 )
05720 {
05721 c.m_do_crc16 = 1;
05722 c.m_crc16 = 1;
05723 }
05724 break;
05725
05726 case TCODE_OPENNURBS_OBJECT | TCODE_CRC | 0x7FFD:
05727 if ( m_3dm_version == 1 )
05728 {
05729
05730 c.m_do_crc16 = 1;
05731 c.m_crc16 = 1;
05732 }
05733 else
05734 {
05735
05736 c.m_do_crc32 = 1;
05737 c.m_crc32 = 0;
05738 }
05739 break;
05740
05741 default:
05742 if ( m_3dm_version != 1 && 0 != (TCODE_CRC & typecode) )
05743 {
05744
05745 c.m_do_crc32 = 1;
05746 c.m_crc32 = 0;
05747 }
05748 break;
05749
05750 }
05751 }
05752 c.m_bLongChunk = 1;
05753 }
05754 c.m_big_offset = CurrentPosition();
05755 m_bDoChunkCRC = c.m_do_crc16 || c.m_do_crc32;
05756
05757 if ( m_chunk.Capacity() == 0 )
05758 m_chunk.Reserve(128);
05759 m_chunk.Append( c );
05760
05761 return true;
05762 }
05763
05764 bool ON_BinaryArchive::EnableSave3dmRenderMeshes( ON_BOOL32 b )
05765 {
05766 bool oldb = m_bSaveRenderMeshes;
05767 m_bSaveRenderMeshes = b?true:false;
05768 return oldb;
05769 }
05770
05771 bool ON_BinaryArchive::Save3dmRenderMeshes() const
05772 {
05773 return m_bSaveRenderMeshes;
05774 }
05775
05776 bool ON_BinaryArchive::EnableSave3dmAnalysisMeshes( ON_BOOL32 b )
05777 {
05778 bool oldb = m_bSaveAnalysisMeshes;
05779 m_bSaveAnalysisMeshes = b?true:false;
05780 return oldb;
05781 }
05782
05783 bool ON_BinaryArchive::Save3dmAnalysisMeshes() const
05784 {
05785 return m_bSaveAnalysisMeshes;
05786 }
05787
05788 bool ON_BinaryArchive::EnableSaveUserData( ON_BOOL32 b )
05789 {
05790 bool b0 = m_bSaveUserData;
05791 m_bSaveUserData = b?true:false;
05792 return b0;
05793 }
05794
05795 bool ON_BinaryArchive::SaveUserData() const
05796 {
05797 return m_bSaveUserData;
05798 }
05799
05800 int ON_BinaryArchive::CurrentArchiveVersion()
05801 {
05802
05803
05804 return 50;
05805 }
05806
05807 bool ON_BinaryArchive::Write3dmStartSection( int version, const char* sInformation )
05808 {
05809 if ( 0 == version )
05810 version = ON_BinaryArchive::CurrentArchiveVersion();
05811
05812
05813
05814
05815
05816
05817 if ( version >= 5 && version < 50 )
05818 version *= 10;
05819
05820 if ( version > ON_BinaryArchive::CurrentArchiveVersion() )
05821 {
05822 ON_ERROR("3dm archive version must be <= ON_BinaryArchive::CurrentArchiveVersion() ");
05823 return false;
05824 }
05825
05826 if ( version < 2
05827 || (version >= 5 && version < 50)
05828 || (version >= 50 && 0 != (version % 10))
05829 )
05830 {
05831 ON_ERROR("3dm archive version must be 2, 3, 4 or 50");
05832 return false;
05833 }
05834
05835 m_bad_CRC_count = 0;
05836 m_3dm_version = 0;
05837 m_3dm_opennurbs_version = ON::Version();
05838 m_3dm_version = version;
05839
05840 char sVersion[64];
05841 memset( sVersion, 0, sizeof(sVersion) );
05842 if ( version < 1 )
05843 version = ON_BinaryArchive::CurrentArchiveVersion();
05844 sprintf(sVersion,"3D Geometry File Format %8d",version);
05845 bool rc = WriteByte( 32, sVersion );
05846 if ( rc )
05847 rc = BeginWrite3dmBigChunk( TCODE_COMMENTBLOCK, 0 );
05848 if ( rc ) {
05849 if ( sInformation && sInformation[0] ) {
05850 rc = WriteByte( strlen(sInformation), sInformation );
05851 }
05852 if ( rc ) {
05853
05854 char s[2048];
05855 size_t s_len = 0;
05856 memset( s, 0, sizeof(s) );
05857 sprintf(s," 3DM I/O processor: OpenNURBS toolkit version %d",ON::Version());
05858 strcat(s," (compiled on ");
05859 strcat(s,__DATE__);
05860 strcat(s,")\n");
05861 s_len = strlen(s);
05862 s[s_len++] = 26;
05863 s[s_len++] = 0;
05864 rc = WriteByte( s_len, s );
05865 }
05866 if ( !EndWrite3dmChunk() )
05867 rc = false;
05868 }
05869 return rc;
05870 }
05871
05872 bool ON_BinaryArchive::Read3dmStartSection( int* version, ON_String& s )
05873 {
05874
05875
05876
05877
05878
05879
05880
05881 m_bad_CRC_count = 0;
05882 m_3dm_version = 0;
05883
05884
05885
05886 m_3dm_opennurbs_version = 0;
05887
05888 unsigned int typecode = 0;
05889 ON__INT64 length = -1;
05890 int ver = m_3dm_version;
05891 if ( version )
05892 *version = m_3dm_version;
05893 s.Destroy();
05894 char s3d[33];
05895 memset( s3d, 0, sizeof(s3d) );
05896 bool rc = ReadByte( 32, s3d );
05897 if ( rc )
05898 {
05899
05900 if ( strncmp( s3d, "3D Geometry File Format ", 24) )
05901 {
05902
05903
05904
05905
05906 rc = false;
05907 unsigned int n;
05908 int j;
05909 for ( n = 0; n < 33554432 && !rc; n++ )
05910 {
05911 for ( j = 0; j < 31; j++ )
05912 s3d[j] = s3d[j+1];
05913 if ( !ReadByte( 1, &s3d[31]) )
05914 break;
05915 if ( !strncmp( s3d, "3D Geometry File Format ", 24) )
05916 {
05917 m_3dm_start_section_offset = n+1;
05918 rc = true;
05919 break;
05920 }
05921 }
05922 }
05923
05924 if (rc) {
05925
05926
05927
05928 int i = 24;
05929 while (i < 32 && s3d[i] == ' ')
05930 i++;
05931 while (i < 32 && rc) {
05932
05933 if ( i == 31 && s3d[i] == 'X' ) {
05934 s3d[i] = '2';
05935 }
05936
05937 if ( s3d[i] < '0' || s3d[i] > '9' ) {
05938 rc = false;
05939 break;
05940 }
05941 ver = ver*10 + ((int)(s3d[i]-'0'));
05942 i++;
05943 }
05944 if ( rc ) {
05945 m_3dm_version = ver;
05946 if ( version )
05947 *version = ver;
05948 }
05949 }
05950 if ( rc ) {
05951 rc = BeginRead3dmBigChunk( &typecode, &length );
05952 if ( rc ) {
05953 if ( typecode != 1 ) {
05954 rc = false;
05955 }
05956 else if ( length > 0 )
05957 {
05958 if ( length > 0x00FFFFFF )
05959 {
05960 ON_ERROR("ON_BinaryArchive::Read3dmStartSection - start section string is unreasonably long.");
05961 rc = false;
05962 }
05963 else
05964 {
05965 int slen = (int)length;
05966 s.ReserveArray( slen+1 );
05967 s.SetLength( slen );
05968 s[slen] = 0;
05969 ReadByte( slen, s.Array() );
05970 while ( slen > 0 && (0 == s[slen-1] || 26 == s[slen-1]) )
05971 {
05972 s[slen-1] = 0;
05973 slen--;
05974 }
05975 s.SetLength(slen);
05976 }
05977 }
05978 }
05979 if ( !EndRead3dmChunk() )
05980 rc = false;
05981 if ( rc && m_3dm_version == 1 ) {
05982
05983
05984
05985
05986
05987
05988
05989
05990
05991
05992
05993
05994
05995 {
05996
05997 const ON__UINT64 pos1 = CurrentPosition();
05998
05999 bool bCheckChunks = true;
06000
06002 while(bCheckChunks) {
06003 if ( !PeekAt3dmBigChunkType(&typecode,&length) )
06004 break;
06005 switch(typecode)
06006 {
06007 case TCODE_SUMMARY:
06008 case TCODE_BITMAPPREVIEW:
06009 case TCODE_UNIT_AND_TOLERANCES:
06010 case TCODE_VIEWPORT:
06011 case TCODE_LAYER:
06012 case TCODE_RENDERMESHPARAMS:
06013 case TCODE_CURRENTLAYER:
06014 case TCODE_ANNOTATION_SETTINGS:
06015 case TCODE_NOTES:
06016 case TCODE_NAMED_CPLANE:
06017 case TCODE_NAMED_VIEW:
06018
06019 bCheckChunks = BeginRead3dmBigChunk( &typecode, &length );
06020 if ( bCheckChunks )
06021 bCheckChunks = EndRead3dmChunk();
06022 break;
06023
06024
06025
06026
06027
06028
06029
06030
06031
06032
06033 default:
06034 if ( TCODE_TABLE == (typecode & 0xFFFF0000) ) {
06035
06036 ON_WARNING("ON_BinaryArchive::Read3dmStartSection(): Archive has V1 header and V2 body. Continuing to read V2 body.");
06037 m_3dm_version = 2;
06038 if ( version )
06039 *version = 2;
06040 }
06041 bCheckChunks = false;
06042 break;
06043 }
06044 }
06045
06046 if ( m_3dm_version == 1 ) {
06047
06048 ON__UINT64 pos2 = CurrentPosition();
06049 if ( pos2 > pos1 )
06050 {
06051 BigSeekBackward(pos2 - pos1);
06052 }
06053 }
06054 }
06055 }
06056 }
06057 }
06058 return rc;
06059 }
06060
06061 bool ON_BinaryArchive::Write3dmProperties(
06062 const ON_3dmProperties& prop
06063 )
06064 {
06065 bool rc = false;
06066 if ( m_3dm_version == 1 )
06067 {
06068 ON_String s;
06069
06070 rc = true;
06071
06072 if ( rc && prop.m_RevisionHistory.IsValid() )
06073 {
06074 rc = BeginWrite3dmChunk(TCODE_SUMMARY,0);
06075 if (rc)
06076 {
06077
06078 s = prop.m_RevisionHistory.m_sCreatedBy;
06079 if (rc) rc = WriteString(s);
06080 if (rc) rc = WriteTime( prop.m_RevisionHistory.m_create_time );
06081 if (rc) rc = WriteInt(0);
06082 s = prop.m_RevisionHistory.m_sLastEditedBy;
06083 if (rc) rc = WriteString(s);
06084 if (rc) rc = WriteTime( prop.m_RevisionHistory.m_last_edit_time );
06085 if (rc) rc = WriteInt(0);
06086 if (rc) rc = WriteInt( prop.m_RevisionHistory.m_revision_count );
06087 if ( !EndWrite3dmChunk() )
06088 rc = false;
06089 }
06090 }
06091
06092 if ( rc && prop.m_Notes.IsValid() )
06093 {
06094 rc = BeginWrite3dmChunk(TCODE_NOTES,0);
06095
06096 if ( rc )
06097 {
06098 if ( rc ) rc = WriteInt( prop.m_Notes.m_bVisible );
06099 if ( rc ) rc = WriteInt( prop.m_Notes.m_window_left );
06100 if ( rc ) rc = WriteInt( prop.m_Notes.m_window_top );
06101 if ( rc ) rc = WriteInt( prop.m_Notes.m_window_right );
06102 if ( rc ) rc = WriteInt( prop.m_Notes.m_window_bottom );
06103 s = prop.m_Notes.m_notes;
06104 if ( rc ) rc = WriteString( s );
06105 if ( !EndWrite3dmChunk() )
06106 rc = false;
06107 }
06108 }
06109
06110 if ( rc && prop.m_PreviewImage.IsValid() )
06111 {
06112 rc = BeginWrite3dmChunk(TCODE_BITMAPPREVIEW,0);
06113 if (rc)
06114 {
06115
06116 prop.m_PreviewImage.Write(*this);
06117 if ( !EndWrite3dmChunk() )
06118 rc = false;
06119 }
06120 }
06121 }
06122 else
06123 {
06124
06125 rc = BeginWrite3dmChunk(TCODE_PROPERTIES_TABLE,0);
06126 if ( rc ) {
06127 rc = prop.Write( *this )?true:false;
06128 if ( !EndWrite3dmChunk() )
06129 rc = false;
06130 }
06131 }
06132 return rc;
06133 }
06134
06135 int on_strnicmp(const char * s1, const char * s2, int n)
06136 {
06137 #if defined(ON_OS_WINDOWS)
06138
06139 return _strnicmp(s1,s2,n);
06140 #else
06141 return strncasecmp(s1,s2,n);
06142 #endif
06143 }
06144
06145 bool ON_BinaryArchive::Read3dmProperties( ON_3dmProperties& prop )
06146 {
06147
06148
06149
06150
06151 m_3dm_opennurbs_version = 0;
06152
06153 prop.Default();
06154
06155 bool rc = true;
06156
06157
06158 const size_t pos0 = CurrentPosition();
06159 bool bHaveRevisionHistory = false;
06160 bool bHaveNotes = false;
06161 bool bHavePreviewImage = false;
06162 bool bDone = false;
06163 bool bRewindFilePointer = false;
06164
06165 ON__UINT32 tcode;
06166 ON__INT64 big_value;
06167 int version = 0;
06168
06169 if ( m_3dm_version != 1 ) {
06170 for(;;)
06171 {
06172 tcode = 0;
06173 big_value = 0;
06174 rc = BeginRead3dmBigChunk( &tcode, &big_value );
06175 if ( !rc ) {
06176 bRewindFilePointer = true;
06177 break;
06178 }
06179
06180 if ( tcode == TCODE_PROPERTIES_TABLE ) {
06181 rc = prop.Read(*this)?true:false;
06182 }
06183 else {
06184 bRewindFilePointer = true;
06185 }
06186
06187 if ( !EndRead3dmChunk() ) {
06188 rc = false;
06189 bRewindFilePointer = true;
06190 }
06191 if ( tcode == TCODE_PROPERTIES_TABLE || !rc )
06192 break;
06193 }
06194 }
06195 else {
06196
06197 rc = SeekFromStart(32)?true:false;
06198 bRewindFilePointer = true;
06199 for(;;)
06200 {
06201 tcode = 0;
06202 big_value = 0;
06203 rc = BeginRead3dmBigChunk( &tcode, &big_value );
06204 if ( !rc ) {
06205 rc = true;
06206 bRewindFilePointer = true;
06207 break;
06208 }
06209
06210 switch ( tcode ) {
06211
06212 case 1:
06213 if ( big_value > 1000000 )
06214 {
06215 ON_ERROR("Comment length > 1000000");
06216 }
06217 else if ( big_value > 1 )
06218 {
06219 int slen = (int)big_value;
06220 int i;
06221 char* name = 0;
06222 ON_String s;
06223 s.ReserveArray( slen+1 );
06224 s.SetLength( slen );
06225 s[slen] = 0;
06226 ReadByte( slen, s.Array() );
06227 while ( slen > 0 && (0 == s[slen-1] || 26 == s[slen-1]) )
06228 {
06229 s[slen-1] = 0;
06230 slen--;
06231 }
06232 s.SetLength(slen);
06233 name = s.Array();
06234 if ( name ) {
06235 while(*name) {
06236 if ( !on_strnicmp(name,"Interface:",10) ) {
06237 name += 10;
06238 break;
06239 }
06240 name++;
06241 }
06242 while(*name && *name <= 32 )
06243 name++;
06244 for ( i = 0; name[i] ; i++ ) {
06245 if ( name[i] == '(' ) {
06246 name[i] = 0;
06247 while ( i > 0 && (name[i] <= 32 || name[i] == '-') ) {
06248 name[i] = 0;
06249 i--;
06250 }
06251 break;
06252 }
06253 }
06254 if ( *name )
06255 {
06256 char* details = 0;
06257 if ( !on_strnicmp(name,"Rhinoceros",10) ) {
06258 prop.m_Application.m_application_URL = "http://www.rhino3d.com";
06259 details = name+10;
06260 while ( *details && *details <= 32 )
06261 details++;
06262 while ( (*details >= '0' && *details <= '9') || *details == '.' )
06263 details++;
06264 if ( *details && *details <= 32 ) {
06265 *details = 0;
06266 details++;
06267 while ( *details && (*details <= 32 ||*details == '-')) {
06268 details++;
06269 }
06270 }
06271 }
06272 if (*name)
06273 prop.m_Application.m_application_name = name;
06274 if (details && *details)
06275 prop.m_Application.m_application_details = details;
06276 }
06277 }
06278 }
06279 break;
06280
06281 case TCODE_SUMMARY:
06282
06283 version = 1;
06284 bHaveRevisionHistory = true;
06285 {
06286 int slength = 0;
06287 char* s = 0;
06288 if (rc) rc = ReadInt(&slength);
06289 if (rc && slength > 0 ) {
06290 s = (char*)onmalloc((slength+1)*sizeof(*s));
06291 memset( s, 0, (slength+1)*sizeof(*s) );
06292 if (rc) rc = ReadChar( slength, s );
06293 if ( rc )
06294 prop.m_RevisionHistory.m_sCreatedBy = s;
06295 onfree(s);
06296 slength = 0;
06297 s = 0;
06298 }
06299 if (rc) rc = ReadTime( prop.m_RevisionHistory.m_create_time );
06300 int i32 = 0;
06301 if (rc) rc = ReadInt(&i32);
06302 if (rc) rc = ReadInt(&slength);
06303 if ( rc && slength > 0 )
06304 {
06305 s = (char*)onmalloc((slength+1)*sizeof(*s));
06306 memset( s, 0, (slength+1)*sizeof(*s) );
06307 if (rc) rc = ReadChar( slength, s );
06308 if ( rc )
06309 prop.m_RevisionHistory.m_sLastEditedBy = s;
06310 onfree(s);
06311 slength = 0;
06312 s = 0;
06313 }
06314 if (rc) rc = ReadTime( prop.m_RevisionHistory.m_last_edit_time );
06315 if (rc) rc = ReadInt(&i32);
06316 if (rc) rc = ReadInt( &prop.m_RevisionHistory.m_revision_count );
06317 }
06318 break;
06319
06320 case TCODE_NOTES:
06321
06322 version = 1;
06323 bHaveNotes = true;
06324 for(;;)
06325 {
06326 int slength;
06327 char* s = 0;
06328 rc = ReadInt( &prop.m_Notes.m_bVisible );
06329 if(!rc) break;
06330 rc = ReadInt( &prop.m_Notes.m_window_left );
06331 if(!rc) break;
06332 rc = ReadInt( &prop.m_Notes.m_window_top );
06333 if(!rc) break;
06334 rc = ReadInt( &prop.m_Notes.m_window_right );
06335 if(!rc) break;
06336 rc = ReadInt( &prop.m_Notes.m_window_bottom );
06337 if(!rc) break;
06338 rc = ReadInt( &slength );
06339 if(!rc) break;
06340 if ( slength > 0 )
06341 {
06342 s = (char*)onmalloc( (slength+1)*sizeof(*s) );
06343 memset( s, 0, (slength+1)*sizeof(*s) );
06344 if ( rc ) rc = ReadChar( slength, s );
06345 if ( rc )
06346 {
06347 prop.m_Notes.m_notes = s;
06348 }
06349 onfree(s);
06350 slength = 0;
06351 s = 0;
06352 }
06353 break;
06354 }
06355 break;
06356
06357 case TCODE_BITMAPPREVIEW:
06358
06359 version = 1;
06360 rc = prop.m_PreviewImage.Read(*this)?true:false;
06361 bHavePreviewImage = rc;
06362 break;
06363
06364 case TCODE_CURRENTLAYER:
06365 case TCODE_LAYER:
06366
06367 bDone = true;
06368 bRewindFilePointer = true;
06369 break;
06370
06371 default:
06372
06373 bRewindFilePointer = true;
06374 break;
06375 }
06376
06377
06378 if ( !EndRead3dmChunk() ) {
06379 rc = false;
06380 bRewindFilePointer = true;
06381 }
06382
06383 if ( bHaveRevisionHistory && bHaveNotes && bHavePreviewImage )
06384 bDone = true;
06385
06386 if ( bDone || !rc )
06387 break;
06388 }
06389 }
06390
06391 if ( bRewindFilePointer ) {
06392
06393 const ON__UINT64 pos1 = CurrentPosition();
06394 if ( pos0 != pos1 )
06395 {
06396 if (pos1 > pos0)
06397 BigSeekBackward(pos1-pos0);
06398 else if ( pos1 < pos0 )
06399 BigSeekForward(pos0-pos1);
06400 }
06401 }
06402
06403 return rc;
06404 }
06405
06406 bool ON_BinaryArchive::Write3dmSettings(
06407 const ON_3dmSettings& settings
06408 )
06409 {
06410 bool rc = false;
06411 if ( m_3dm_version == 1 ) {
06412
06413 rc = settings.Write(*this)?true:false;
06414 }
06415 else
06416 {
06417
06418 rc = BeginWrite3dmChunk(TCODE_SETTINGS_TABLE,0);
06419 if ( rc ) {
06420 rc = settings.Write( *this );
06421 if ( !EndWrite3dmChunk() )
06422 rc = false;
06423 }
06424
06425 if ( rc && 3 == Archive3dmVersion() )
06426 {
06427
06428
06429
06430 int i, count = settings.m_plugin_list.Count();
06431 m_V3_plugin_id_list.SetCount(0);
06432 m_V3_plugin_id_list.SetCapacity( count+5 );
06433 for ( i = 0; i < count; i++ )
06434 {
06435 const ON_UUID& pid = settings.m_plugin_list[i].m_plugin_id;
06436 if ( !ON_UuidIsNil(pid) )
06437 m_V3_plugin_id_list.Append(pid);
06438 }
06439
06440
06441
06442 m_V3_plugin_id_list.Append( ON_v3_userdata_id );
06443 m_V3_plugin_id_list.Append( ON_v4_userdata_id );
06444 m_V3_plugin_id_list.Append( ON_opennurbs4_id );
06445 m_V3_plugin_id_list.Append( ON_opennurbs5_id );
06446 m_V3_plugin_id_list.Append( ON_rhino3_id );
06447 m_V3_plugin_id_list.Append( ON_rhino4_id );
06448 m_V3_plugin_id_list.Append( ON_rhino5_id );
06449 m_V3_plugin_id_list.QuickSort( ON_UuidCompare );
06450 }
06451 }
06452 return rc;
06453 }
06454
06455 bool ON_BinaryArchive::Read3dmSettings( ON_3dmSettings& settings )
06456 {
06457 bool rc = false;
06458 ON__UINT32 tcode;
06459 ON__INT64 big_value;
06460
06461 if ( m_3dm_version == 1 ) {
06462
06463 rc = settings.Read(*this);
06464 }
06465 else {
06466 rc = true;
06467 while(rc)
06468 {
06469 tcode = 0;
06470 big_value = 0;
06471 rc = BeginRead3dmBigChunk( &tcode, &big_value );
06472 if ( !rc )
06473 break;
06474 if ( tcode == TCODE_SETTINGS_TABLE ) {
06475
06476 rc = settings.Read(*this);
06477 }
06478 if ( !EndRead3dmChunk() ) {
06479 rc = false;
06480 break;
06481 }
06482 if ( TCODE_SETTINGS_TABLE == tcode )
06483 break;
06484 }
06485 }
06486
06487 return rc;
06488 }
06489
06490 ON_BinaryArchive::table_type ON_BinaryArchive::TableTypeFromTypecode( unsigned int typecode )
06491 {
06492 table_type tt = no_active_table;
06493 switch(typecode)
06494 {
06495 case TCODE_PROPERTIES_TABLE: tt = properties_table; break;
06496 case TCODE_SETTINGS_TABLE: tt = settings_table; break;
06497 case TCODE_BITMAP_TABLE: tt = bitmap_table; break;
06498 case TCODE_TEXTURE_MAPPING_TABLE: tt = texture_mapping_table; break;
06499 case TCODE_MATERIAL_TABLE: tt = material_table; break;
06500 case TCODE_LINETYPE_TABLE: tt = linetype_table; break;
06501 case TCODE_LAYER_TABLE: tt = layer_table; break;
06502 case TCODE_LIGHT_TABLE: tt = light_table; break;
06503 case TCODE_OBJECT_TABLE: tt = object_table; break;
06504 case TCODE_GROUP_TABLE: tt = group_table; break;
06505 case TCODE_FONT_TABLE: tt = font_table; break;
06506 case TCODE_DIMSTYLE_TABLE: tt = dimstyle_table; break;
06507 case TCODE_HATCHPATTERN_TABLE: tt = hatchpattern_table; break;
06508 case TCODE_INSTANCE_DEFINITION_TABLE: tt = instance_definition_table; break;
06509 case TCODE_HISTORYRECORD_TABLE: tt = historyrecord_table; break;
06510 case TCODE_USER_TABLE: tt = user_table; break;
06511 }
06512 return tt;
06513 }
06514
06515 bool ON_BinaryArchive::BeginWrite3dmTable( unsigned int typecode )
06516 {
06517 const table_type tt = TableTypeFromTypecode(typecode);
06518 if (tt == no_active_table) {
06519 ON_ERROR("ON_BinaryArchive::BeginWrite3dmTable() bad typecode");
06520 return false;
06521 }
06522 if ( m_active_table != no_active_table ) {
06523 ON_ERROR("ON_BinaryArchive::BeginWrite3dmTable() m_active_table != no_active_table");
06524 return false;
06525 }
06526 if ( m_chunk.Count() ) {
06527 ON_ERROR("ON_BinaryArchive::BeginWrite3dmTable() m_chunk.Count() > 0");
06528 return false;
06529 }
06530 bool rc = BeginWrite3dmChunk(typecode,0);
06531 if (rc)
06532 m_active_table = tt;
06533 return rc;
06534 }
06535
06536 bool ON_BinaryArchive::EndWrite3dmTable( unsigned int typecode )
06537 {
06538 const table_type tt = TableTypeFromTypecode(typecode);
06539 if (tt == no_active_table) {
06540 ON_ERROR("ON_BinaryArchive::EndWrite3dmTable() bad typecode");
06541 return false;
06542 }
06543 if ( m_active_table != tt ) {
06544 ON_ERROR("ON_BinaryArchive::EndWrite3dmTable() m_active_table != t");
06545 return false;
06546 }
06547 if ( m_chunk.Count() != 1 ) {
06548 ON_ERROR("ON_BinaryArchive::EndWrite3dmTable() m_chunk.Count() != 1");
06549 return false;
06550 }
06551 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
06552 if ( 0 == c || c->m_typecode != typecode ) {
06553 ON_ERROR("ON_BinaryArchive::EndWrite3dmTable() m_chunk.Last()->typecode != typecode");
06554 return false;
06555 }
06556 bool rc = BeginWrite3dmChunk( TCODE_ENDOFTABLE, 0 );
06557 if (rc) {
06558 if (!EndWrite3dmChunk())
06559 rc = false;
06560 }
06561 if (!EndWrite3dmChunk())
06562 rc = false;
06563 Flush();
06564 m_active_table = no_active_table;
06565 return rc;
06566 }
06567
06568 bool ON_BinaryArchive::BeginRead3dmTable( unsigned int typecode )
06569 {
06570 bool rc = false;
06571 const table_type tt = TableTypeFromTypecode(typecode);
06572 if (tt == no_active_table) {
06573 ON_ERROR("ON_BinaryArchive::BeginRead3dmTable() bad typecode");
06574 return false;
06575 }
06576 if ( m_active_table != no_active_table ) {
06577 ON_ERROR("ON_BinaryArchive::BeginRead3dmTable() m_active_table != no_active_table");
06578 return false;
06579 }
06580 if ( m_chunk.Count() ) {
06581 ON_ERROR("ON_BinaryArchive::BeginRead3dmTable() m_chunk.Count() > 0");
06582 return false;
06583 }
06584
06585 if ( m_3dm_version <= 1 )
06586 {
06587 if ( TCODE_USER_TABLE == typecode )
06588 return false;
06589
06590
06591
06592
06593 rc = SeekFromStart(32)?true:false;
06594 m_active_table = tt;
06595 }
06596 else
06597 {
06598 if ( TCODE_USER_TABLE == typecode && m_3dm_version <= 2 )
06599 return false;
06600
06601 bool bReadTable = true;
06602 ON__UINT32 tcode = !typecode;
06603 ON__INT64 big_value = 0;
06604 rc = PeekAt3dmBigChunkType( &tcode, &big_value );
06605 if ( rc ) {
06606 if ( tcode != typecode )
06607 {
06608 if ( typecode == TCODE_USER_TABLE )
06609 {
06610
06611 rc = false;
06612 bReadTable = false;
06613 }
06614 else if ( typecode == TCODE_GROUP_TABLE && m_3dm_opennurbs_version < 200012210 )
06615 {
06616
06617 rc = true;
06618 m_active_table = tt;
06619 bReadTable = false;
06620 }
06621 else if ( typecode == TCODE_FONT_TABLE && m_3dm_opennurbs_version < 200109180 )
06622 {
06623
06624 rc = true;
06625 m_active_table = tt;
06626 bReadTable = false;
06627 }
06628 else if ( typecode == TCODE_DIMSTYLE_TABLE && m_3dm_opennurbs_version < 200109260 )
06629 {
06630
06631 rc = true;
06632 m_active_table = tt;
06633 bReadTable = false;
06634 }
06635 else if ( typecode == TCODE_INSTANCE_DEFINITION_TABLE && m_3dm_opennurbs_version < 200205110 )
06636 {
06637
06638 rc = true;
06639 m_active_table = tt;
06640 bReadTable = false;
06641 }
06642 else if ( typecode == TCODE_HATCHPATTERN_TABLE && m_3dm_opennurbs_version < 200405030 )
06643 {
06644
06645 rc = true;
06646 m_active_table = tt;
06647 bReadTable = false;
06648 }
06649 else if ( typecode == TCODE_LINETYPE_TABLE && m_3dm_opennurbs_version < 200503170 )
06650 {
06651
06652 rc = true;
06653 m_active_table = tt;
06654 bReadTable = false;
06655 }
06656 else if ( typecode == TCODE_TEXTURE_MAPPING_TABLE && m_3dm_opennurbs_version < 200511110 )
06657 {
06658
06659 rc = true;
06660 m_active_table = tt;
06661 bReadTable = false;
06662 }
06663 else if ( typecode == TCODE_HISTORYRECORD_TABLE && m_3dm_opennurbs_version < 200601180 )
06664 {
06665
06666 rc = true;
06667 m_active_table = tt;
06668 bReadTable = false;
06669 }
06670 else
06671 {
06672
06673
06674
06675
06676 bool bSeekFromStart = true;
06677
06678 if ( TCODE_HATCHPATTERN_TABLE == tcode
06679 && TCODE_INSTANCE_DEFINITION_TABLE == typecode
06680 && 3 == m_3dm_version
06681 && 200405190 <= m_3dm_opennurbs_version )
06682 {
06683
06684
06685
06686
06687
06688
06689
06690
06691 tcode = 0;
06692 big_value = 0;
06693 if ( BeginRead3dmBigChunk( &tcode, &big_value ) )
06694 {
06695 if ( TCODE_HATCHPATTERN_TABLE == tcode )
06696 {
06697 bSeekFromStart = false;
06698 }
06699
06700 if ( !EndRead3dmChunk() )
06701 {
06702 bSeekFromStart = true;
06703 }
06704 else if ( !bSeekFromStart )
06705 {
06706 tcode = 0;
06707 big_value = 0;
06708 PeekAt3dmBigChunkType( &tcode, &big_value );
06709 if ( tcode != typecode )
06710 bSeekFromStart = true;
06711 }
06712 }
06713 }
06714
06715 if ( bSeekFromStart )
06716 {
06717 ON_ERROR("ON_BinaryArchive::BeginRead3dmTable() - current file position not at start of table - searching");
06718 rc = Seek3dmChunkFromStart( typecode );
06719 }
06720 }
06721 }
06722 if ( rc && bReadTable ) {
06723 tcode = !typecode;
06724 big_value = 0;
06725 rc = BeginRead3dmBigChunk( &tcode, &big_value );
06726 if ( rc && tcode != typecode ) {
06727 ON_ERROR("ON_BinaryArchive::BeginRead3dmTable() - corrupt table - skipping");
06728 rc = false;
06729 EndRead3dmChunk();
06730 }
06731 else if (rc) {
06732 m_active_table = tt;
06733 }
06734 }
06735 }
06736 }
06737
06738 return rc;
06739 }
06740
06741
06742 int ON_BinaryArchive::GetCurrentChunk(ON_3DM_CHUNK& chunk) const
06743 {
06744 ON_3DM_BIG_CHUNK big_chunk;
06745 memset(&chunk,0,sizeof(ON_3DM_CHUNK));
06746 memset(&big_chunk,0,sizeof(big_chunk));
06747 int rc = GetCurrentChunk(big_chunk);
06748 if ( rc > 0 )
06749 {
06750 chunk.m_offset = (size_t)big_chunk.m_big_offset;
06751 chunk.m_typecode = big_chunk.m_typecode;
06752
06753 ON__INT32 i32 = 0;
06754 if ( ON_IsLongChunkTypecode( big_chunk.m_typecode ) )
06755 DownSizeUINT( (ON__UINT64)big_chunk.m_big_value, (ON__UINT32*)&i32 );
06756 else
06757 DownSizeINT( big_chunk.m_big_value, &i32 );
06758 chunk.m_value = i32;
06759
06760 chunk.m_do_length = big_chunk.m_bLongChunk ? 1 : 0;
06761 chunk.m_do_crc16 = big_chunk.m_do_crc16 ? 1 : 0;
06762 chunk.m_do_crc32 = big_chunk.m_do_crc32 ? 1 : 0;
06763 chunk.m_crc16 = big_chunk.m_crc16;
06764 chunk.m_crc32 = big_chunk.m_crc32;
06765 }
06766 return rc;
06767 }
06768
06769
06770 int ON_BinaryArchive::GetCurrentChunk(ON_3DM_BIG_CHUNK& chunk) const
06771 {
06772 int rc = m_chunk.Count();
06773 if ( rc > 0 )
06774 {
06775 chunk = m_chunk[rc-1];
06776 }
06777 else
06778 {
06779 memset(&chunk,0,sizeof(ON_3DM_BIG_CHUNK));
06780 }
06781 return rc;
06782 }
06783
06784 static
06785 const unsigned char* BufferToUINT16(
06786 bool bReverseByteOrder,
06787 const unsigned char* buffer,
06788 const unsigned char* buffer_max,
06789 ON__UINT16* u16 )
06790 {
06791 if ( buffer >= buffer_max || buffer_max - buffer < 2 )
06792 return 0;
06793 if ( u16 )
06794 {
06795 unsigned char* dst = (unsigned char*)u16;
06796 if ( bReverseByteOrder )
06797 {
06798 dst[0] = buffer[1];
06799 dst[1] = buffer[0];
06800 }
06801 else
06802 {
06803 dst[0] = buffer[0];
06804 dst[1] = buffer[1];
06805 }
06806 }
06807 return buffer+2;
06808 }
06809
06810 static
06811 const unsigned char* BufferToUINT32(
06812 bool bReverseByteOrder,
06813 const unsigned char* buffer,
06814 const unsigned char* buffer_end,
06815 ON__UINT32* u32 )
06816 {
06817 if ( buffer >= buffer_end || buffer_end - buffer < 4 )
06818 return 0;
06819 if ( u32 )
06820 {
06821 unsigned char* dst = (unsigned char*)u32;
06822 if ( bReverseByteOrder )
06823 {
06824 dst[0] = buffer[3];
06825 dst[1] = buffer[2];
06826 dst[2] = buffer[1];
06827 dst[3] = buffer[0];
06828 }
06829 else
06830 {
06831 dst[0] = buffer[0];
06832 dst[1] = buffer[1];
06833 dst[2] = buffer[2];
06834 dst[3] = buffer[3];
06835 }
06836 }
06837 return buffer+4;
06838 }
06839
06840 static
06841 const unsigned char* BufferToINT64(
06842 bool bReverseByteOrder,
06843 const unsigned char* buffer,
06844 const unsigned char* buffer_end,
06845 ON__INT64* i64 )
06846 {
06847 if ( buffer >= buffer_end || buffer_end - buffer < 8 )
06848 return 0;
06849 if ( i64 )
06850 {
06851 unsigned char* dst = (unsigned char*)i64;
06852 if ( bReverseByteOrder )
06853 {
06854 dst[0] = buffer[7];
06855 dst[1] = buffer[6];
06856 dst[2] = buffer[5];
06857 dst[3] = buffer[4];
06858 dst[4] = buffer[3];
06859 dst[5] = buffer[2];
06860 dst[6] = buffer[1];
06861 dst[7] = buffer[0];
06862 }
06863 else
06864 {
06865 dst[0] = buffer[0];
06866 dst[1] = buffer[1];
06867 dst[2] = buffer[2];
06868 dst[3] = buffer[3];
06869 dst[4] = buffer[4];
06870 dst[5] = buffer[5];
06871 dst[6] = buffer[6];
06872 dst[7] = buffer[7];
06873 }
06874 }
06875 return buffer+8;
06876 }
06877
06878 static
06879 const unsigned char* BufferValidateTcode(
06880 bool bReverseByteOrder,
06881 const unsigned char* buffer,
06882 const unsigned char* buffer_end,
06883 ON__UINT32 expected_tcode )
06884 {
06885 ON__UINT32 tc = expected_tcode ? 0 : 1;
06886 buffer = BufferToUINT32(bReverseByteOrder,buffer,buffer_end,&tc);
06887 return ( 0 != buffer && tc == expected_tcode ) ? buffer : 0;
06888 }
06889
06890 static
06891 const unsigned char* BufferToChunkValue(
06892 bool bReverseByteOrder,
06893 size_t sizeof_chunk_value,
06894 const unsigned char* buffer,
06895 const unsigned char* buffer_end,
06896 ON__INT64* chunk_value )
06897 {
06898 if ( 8 == sizeof_chunk_value )
06899 {
06900 buffer = BufferToINT64(bReverseByteOrder,buffer,buffer_end,chunk_value);
06901 }
06902 else
06903 {
06904 ON__UINT32 u32;
06905 ON__UINT64 u64;
06906 buffer = BufferToUINT32(bReverseByteOrder,buffer,buffer_end,&u32);
06907 if ( buffer && chunk_value )
06908 {
06909
06910
06911 u64 = u32;
06912 *chunk_value = (ON__INT64)u64;
06913 }
06914 }
06915 return buffer;
06916 }
06917
06918 static
06919 const unsigned char* BufferToUuid(
06920 bool bReverseByteOrder,
06921 const unsigned char* buffer,
06922 const unsigned char* buffer_end,
06923 ON_UUID& uuid )
06924 {
06925 ON__UINT32 data1=0;
06926 ON__UINT16 data2=0, data3=0;
06927 if ( buffer >= buffer_end || buffer_end - buffer < 16 )
06928 return 0;
06929 buffer = BufferToUINT32(bReverseByteOrder,buffer,buffer_end,&data1);
06930 if (buffer)
06931 buffer = BufferToUINT16(bReverseByteOrder,buffer,buffer_end,&data2);
06932 if (buffer)
06933 buffer = BufferToUINT16(bReverseByteOrder,buffer,buffer_end,&data3);
06934 if (buffer)
06935 {
06936 if ( buffer >= buffer_end || buffer_end - buffer < 8 )
06937 buffer = 0;
06938 else
06939 {
06940 uuid.Data1 = data1;
06941 uuid.Data2 = data2;
06942 uuid.Data3 = data3;
06943 memcpy(&uuid.Data4,buffer,8);
06944 buffer += 8;
06945 }
06946 }
06947 return buffer;
06948 }
06949
06950 static
06951 const unsigned char* EmergencyFindTable_UuidHelper(
06952 bool bReverseByteOrder,
06953 size_t sizeof_chunk_value,
06954 const unsigned char* buffer,
06955 const unsigned char* buffer_end,
06956 const ON__UINT32 expected_tcode,
06957 const ON_UUID* expected_uuid
06958 )
06959 {
06960 ON__INT64 chunk_value;
06961 ON__UINT32 c, cc;
06962 ON_UUID uuid;
06963
06964
06965 buffer = BufferValidateTcode(bReverseByteOrder,buffer,buffer_end,expected_tcode);
06966 if ( 0 == buffer )
06967 return 0;
06968
06969
06970 chunk_value = -1;
06971 buffer = BufferToChunkValue( bReverseByteOrder,sizeof_chunk_value,buffer,buffer_end,&chunk_value );
06972 if ( 0 == buffer || chunk_value < 0 )
06973 return 0;
06974
06975
06976
06977
06978
06979
06980
06981
06982
06983
06984
06985 const bool bLookForUserTableRecordHeader = (TCODE_USER_TABLE_UUID == expected_tcode
06986 && ((ON__UINT64)chunk_value) >= (16+4+sizeof_chunk_value+21+4+4)
06987 );
06988 if ( !bLookForUserTableRecordHeader && 20 != chunk_value )
06989 return 0;
06990 buffer = BufferToUuid(bReverseByteOrder,buffer,buffer_end,uuid);
06991 if ( 0 == buffer )
06992 return 0;
06993 if( 0 != expected_uuid && uuid != *expected_uuid )
06994 return 0;
06995
06996 if ( bLookForUserTableRecordHeader )
06997 {
06998
06999 buffer = BufferValidateTcode(bReverseByteOrder,buffer,buffer_end,TCODE_USER_TABLE_RECORD_HEADER);
07000 if ( 0 == buffer )
07001 return 0;
07002
07003 ON__INT64 header_length = -1;
07004 buffer = BufferToChunkValue( bReverseByteOrder,sizeof_chunk_value,buffer,buffer_end,&header_length );
07005 if ( 0 == buffer )
07006 return 0;
07007 if ( header_length < 25 )
07008 return 0;
07009 if ( buffer >= buffer_end || buffer_end - buffer < header_length )
07010 return 0;
07011 buffer += header_length;
07012 }
07013
07014 buffer = BufferToUINT32(bReverseByteOrder,buffer,buffer_end,&c);
07015 if ( 0 == buffer )
07016 return 0;
07017 cc = ON_CRC32(0,4,&uuid.Data1);
07018 cc = ON_CRC32(cc,2,&uuid.Data2);
07019 cc = ON_CRC32(cc,2,&uuid.Data3);
07020 cc = ON_CRC32(cc,8,&uuid.Data4[0]);
07021 if ( c != cc )
07022 return 0;
07023
07024 return buffer;
07025 }
07026
07027
07028 bool ON_BinaryArchive::FindMisplacedTable(
07029 ON__UINT64 filelength,
07030 const ON__UINT32 table_tcode,
07031 const ON__UINT32 table_record_tcode,
07032 const ON_UUID class_uuid,
07033 const ON__UINT64 min_length_data
07034 )
07035 {
07036 bool rc = false;
07037 unsigned char buffer2048[2048];
07038 const ON__UINT64 pos0 = CurrentPosition();
07039 if ( filelength > 0 && pos0 >= filelength )
07040 return false;
07041
07042 ON__UINT32 tcode;
07043 ON__INT64 i64;
07044
07045 const bool bReverseByteOrder = (ON::big_endian == Endian());
07046 const size_t sizeof_chunk_typecode = 4;
07047 const size_t sizeof_chunk_value = SizeofChunkLength();
07048 const size_t sizeof_chunk_header = sizeof_chunk_typecode + sizeof_chunk_value;
07049 size_t length_of_user_uuid_and_header = 0;
07050 const bool bFindObjectTable = ( TCODE_OBJECT_TABLE == table_tcode
07051 && TCODE_OBJECT_RECORD == table_record_tcode );
07052 const bool bFindUserTable = ( TCODE_USER_TABLE == table_tcode
07053 && TCODE_USER_RECORD == table_record_tcode );
07054
07055 if ( TCODE_USER_TABLE == table_tcode && !bFindUserTable )
07056 return false;
07057 if ( TCODE_OBJECT_TABLE == table_tcode && !bFindObjectTable )
07058 return false;
07059 if ( bFindUserTable && ON_UuidIsNil(class_uuid) )
07060 {
07061
07062 ON_ERROR("ON_BinaryArchive::FindMisplacedTable - must provide plug-in id when searching for user tables");
07063 return false;
07064 }
07065
07066 if ( !SeekFromStart(0) )
07067 return false;
07068
07069 ON__UINT64 pos1 = CurrentPosition();
07070 ON__UINT64 pos;
07071 ON__UINT64 empty_table_pos = 0;
07072 int empty_table_status = 0;
07073
07074
07075 const size_t sizeof_buffer2048 = sizeof(buffer2048);
07076 bool bAtEOF = false;
07077
07078 while(!bAtEOF)
07079 {
07080 pos = CurrentPosition();
07081 if ( pos < pos1 )
07082 {
07083 break;
07084 }
07085 else if ( pos > pos1 )
07086 {
07087 if ( !BigSeekBackward(pos - pos1) )
07088 break;
07089 if ( pos1 != CurrentPosition() )
07090 break;
07091 }
07092
07093 memset(buffer2048,0,sizeof_buffer2048);
07094
07095
07096
07097
07098 const unsigned int saved_error_message_mask = m_error_message_mask;
07099 m_error_message_mask |= 0x04;
07100 const size_t sizeof_read = Read(sizeof_buffer2048,buffer2048);
07101 m_error_message_mask = saved_error_message_mask;
07102 if ( sizeof_read < sizeof_buffer2048 )
07103 {
07104
07105 bAtEOF = true;
07106 }
07107 if ( sizeof_read < 2*sizeof_chunk_header || sizeof_read > sizeof_buffer2048 )
07108 break;
07109 const unsigned char* buffer_end = (&buffer2048[0]) + sizeof_read;
07110 const unsigned char* buffer = buffer2048;
07111
07112 pos1++;
07113
07114
07115 tcode = !table_tcode;
07116 buffer = BufferToUINT32(bReverseByteOrder,buffer,buffer_end,&tcode);
07117 if ( 0 == buffer )
07118 break;
07119
07120 if ( table_tcode != tcode )
07121 {
07122
07123
07124
07125 for ( size_t i = 1; i <= sizeof_read - sizeof_chunk_typecode; i++ )
07126 {
07127 tcode = !table_tcode;
07128 buffer = BufferToUINT32(bReverseByteOrder,&buffer2048[i],buffer_end,&tcode);
07129 if ( 0 == buffer || table_tcode == tcode )
07130 {
07131 if ( bAtEOF && sizeof_read > 0 && 0 != buffer && table_tcode == tcode )
07132 {
07133
07134 bAtEOF = false;
07135 }
07136 break;
07137 }
07138 pos1++;
07139 }
07140 continue;
07141 }
07142
07143
07144 i64 = -1;
07145 buffer = BufferToChunkValue(bReverseByteOrder,sizeof_chunk_value,buffer,buffer_end,&i64);
07146 if ( 0 == buffer || i64 <= 0 )
07147 continue;
07148 const ON__UINT64 length_of_table = (ON__UINT64)i64;
07149
07150 if ( length_of_table < 2*sizeof_chunk_header + 4 + min_length_data )
07151 {
07152 if ( sizeof_chunk_header == length_of_table && 2 != empty_table_status )
07153 {
07154
07155 buffer = BufferValidateTcode(bReverseByteOrder,buffer,buffer_end,TCODE_ENDOFTABLE);
07156 if ( 0 != buffer )
07157 {
07158 i64 = -1;
07159 buffer = BufferToChunkValue(bReverseByteOrder,sizeof_chunk_value,buffer,buffer_end,&i64);
07160 if ( 0 == i64 )
07161 {
07162 if ( 0 == empty_table_status )
07163 {
07164 empty_table_pos = pos1-1;
07165 empty_table_status = 1;
07166 }
07167 else
07168 {
07169
07170 empty_table_status = 2;
07171 }
07172 }
07173 }
07174 }
07175 continue;
07176 }
07177
07178 if ( bFindUserTable )
07179 {
07180
07181
07182 const unsigned char* buffer0 = buffer;
07183 buffer = EmergencyFindTable_UuidHelper(bReverseByteOrder,sizeof_chunk_value,buffer,buffer_end,TCODE_USER_TABLE_UUID,&class_uuid);
07184 if ( 0 == buffer || buffer <= buffer0 )
07185 continue;
07186
07187 length_of_user_uuid_and_header = buffer - buffer0;
07188
07189 }
07190
07191
07192 buffer = BufferValidateTcode(bReverseByteOrder,buffer,buffer_end,table_record_tcode);
07193 if ( 0 == buffer )
07194 continue;
07195 i64 = -1;
07196 buffer = BufferToChunkValue( bReverseByteOrder, sizeof_chunk_value,buffer,buffer_end,&i64);
07197 if ( 0 == buffer || i64 <= 0 )
07198 continue;
07199 const ON__UINT64 length_of_record = (ON__UINT64)i64;
07200
07201
07202 if ( bFindUserTable )
07203 {
07204 ON__UINT64 expected_length_of_table = length_of_user_uuid_and_header
07205 + sizeof_chunk_header
07206 + length_of_record;
07207 if ( expected_length_of_table != length_of_table )
07208 continue;
07209 }
07210 else
07211 {
07212 if ( length_of_record < 4*sizeof_chunk_header + 20 + min_length_data )
07213 continue;
07214 if ( length_of_record + 2*sizeof_chunk_header > length_of_table)
07215 continue;
07216
07217 if (bFindObjectTable)
07218 {
07219 buffer = BufferValidateTcode(bReverseByteOrder,buffer,buffer_end,TCODE_OBJECT_RECORD_TYPE);
07220 if ( 0 == buffer )
07221 continue;
07222
07223
07224
07225 buffer = BufferToChunkValue(bReverseByteOrder,sizeof_chunk_value,buffer,buffer_end,0);
07226 if ( 0 == buffer )
07227 continue;
07228 }
07229
07230 buffer = BufferValidateTcode(bReverseByteOrder,buffer,buffer_end,TCODE_OPENNURBS_CLASS);
07231 if ( 0 == buffer )
07232 continue;
07233
07234 i64 = -1;
07235 buffer = BufferToChunkValue( bReverseByteOrder,sizeof_chunk_value,buffer,buffer_end,&i64);
07236 if ( 0 == buffer || i64 <= 0 )
07237 continue;
07238 const ON__UINT64 length_of_on_class = (ON__UINT64)i64;
07239
07240 if ( length_of_on_class < 3*sizeof_chunk_header + 20 + min_length_data )
07241 continue;
07242
07243 if ( length_of_on_class + sizeof_chunk_header + 4 > length_of_record)
07244 continue;
07245
07246 const unsigned char* buffer0 = buffer;
07247 buffer = EmergencyFindTable_UuidHelper(bReverseByteOrder,sizeof_chunk_value,buffer,buffer_end,TCODE_OPENNURBS_CLASS_UUID,(ON_UuidIsNil(class_uuid) ? NULL : &class_uuid));
07248 if ( 0 == buffer || buffer <= buffer0)
07249 continue;
07250 const size_t length_of_uuid_chunk = buffer-buffer0;
07251
07252 buffer = BufferValidateTcode(bReverseByteOrder,buffer,buffer_end,TCODE_OPENNURBS_CLASS_DATA);
07253 if ( 0 == buffer )
07254 continue;
07255
07256 i64 = -1;
07257 buffer = BufferToChunkValue( bReverseByteOrder,sizeof_chunk_value,buffer,buffer_end,&i64);
07258 if ( 0 == buffer || i64 < 0 )
07259 continue;
07260 const ON__UINT64 length_of_data = (ON__UINT64)i64;
07261
07262 if ( length_of_data < min_length_data )
07263 continue;
07264 if ( length_of_data + length_of_uuid_chunk + 2*sizeof_chunk_header > length_of_on_class)
07265 continue;
07266 }
07267
07268
07269 if ( !BigSeekBackward(sizeof_read) )
07270 break;
07271 pos = CurrentPosition();
07272 if ( pos+1 == pos1)
07273 rc = true;
07274 break;
07275 }
07276
07277 if ( !rc )
07278 {
07279
07280 if ( 1 == empty_table_status )
07281 {
07282
07283
07284 rc = BigSeekFromStart(empty_table_pos);
07285 }
07286 else
07287 {
07288
07289 BigSeekFromStart(pos0);
07290 }
07291 }
07292 return rc;
07293 }
07294
07295 bool ON_BinaryArchive::FindTableInDamagedArchive(
07296 const unsigned int tcode_table,
07297 const unsigned int tcode_record,
07298 const ON_UUID class_uuid,
07299 const int min_length_data
07300 )
07301 {
07302 bool rc = FindMisplacedTable(
07303 0,
07304 tcode_table,
07305 tcode_record,
07306 class_uuid,
07307 min_length_data
07308 );
07309 return rc;
07310 }
07311
07312
07313
07314
07315
07316
07317
07318
07319
07320
07321
07322
07323
07324
07325
07326 bool ON_BinaryArchive::EndRead3dmTable( unsigned int typecode )
07327 {
07328 bool rc = false;
07329 const table_type tt = TableTypeFromTypecode(typecode);
07330 if (tt == no_active_table) {
07331 ON_ERROR("ON_BinaryArchive::EndRead3dmTable() bad typecode");
07332 return false;
07333 }
07334 if ( m_active_table != tt ) {
07335 ON_ERROR("ON_BinaryArchive::EndRead3dmTable() m_active_table != t");
07336 return false;
07337 }
07338 if ( m_3dm_version == 1 ) {
07339 if ( m_chunk.Count() != 0 ) {
07340 ON_ERROR("ON_BinaryArchive::EndRead3dmTable() v1 file m_chunk.Count() != 0");
07341 return false;
07342 }
07343 rc = true;
07344 }
07345 else {
07346 if ( m_active_table == group_table && m_3dm_opennurbs_version < 200012210 )
07347 {
07348
07349 rc = true;
07350 }
07351 else if ( m_active_table == font_table && m_3dm_opennurbs_version < 200109180 )
07352 {
07353
07354 rc = true;
07355 }
07356 else if ( m_active_table == dimstyle_table && m_3dm_opennurbs_version < 200109260 )
07357 {
07358
07359 rc = true;
07360 }
07361 else if ( m_active_table == instance_definition_table && m_3dm_opennurbs_version < 200205110 )
07362 {
07363
07364 rc = true;
07365 }
07366 else if ( m_active_table == hatchpattern_table && m_3dm_opennurbs_version < 200405030 )
07367 {
07368
07369 rc = true;
07370 }
07371 else if ( m_active_table == linetype_table && m_3dm_opennurbs_version < 200503170 )
07372 {
07373
07374 rc = true;
07375 }
07376 else if ( m_active_table == texture_mapping_table && m_3dm_opennurbs_version < 200511110 )
07377 {
07378
07379 rc = true;
07380 }
07381 else if ( m_active_table == historyrecord_table && m_3dm_opennurbs_version < 200601180 )
07382 {
07383
07384 rc = true;
07385 }
07386 else
07387 {
07388 if ( m_chunk.Count() != 1 )
07389 {
07390 ON_ERROR("ON_BinaryArchive::EndRead3dmTable() v2 file m_chunk.Count() != 1");
07391 return false;
07392 }
07393 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
07394 if ( 0 == c || c->m_typecode != typecode )
07395 {
07396 ON_ERROR("ON_BinaryArchive::EndRead3dmTable() m_chunk.Last()->typecode != typecode");
07397 return false;
07398 }
07399 rc = EndRead3dmChunk();
07400 }
07401 }
07402 m_active_table = no_active_table;
07403 return rc;
07404 }
07405
07406 bool ON_BinaryArchive::BeginWrite3dmBitmapTable()
07407 {
07408 return BeginWrite3dmTable( TCODE_BITMAP_TABLE );
07409 }
07410
07411 bool ON_BinaryArchive::EndWrite3dmBitmapTable()
07412 {
07413 return EndWrite3dmTable( TCODE_BITMAP_TABLE );
07414 }
07415
07416 bool ON_BinaryArchive::Write3dmBitmap( const ON_Bitmap& bitmap )
07417 {
07418 bool rc = false;
07419 if ( m_3dm_version != 1 )
07420 {
07421 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
07422 if ( c && c->m_typecode == TCODE_BITMAP_TABLE )
07423 {
07424 rc = BeginWrite3dmChunk( TCODE_BITMAP_RECORD, 0 );
07425 if ( rc )
07426 {
07427 rc = WriteObject( bitmap );
07428 if ( !EndWrite3dmChunk() )
07429 rc = false;
07430 }
07431 }
07432 else
07433 {
07434 ON_ERROR("ON_BinaryArchive::Write3dmBitmap() must be called in BeginWrite3dmBitmapTable() block");
07435 rc = false;
07436 }
07437 }
07438 return rc;
07439 }
07440
07441 bool ON_BinaryArchive::BeginRead3dmBitmapTable()
07442 {
07443 bool rc = BeginRead3dmTable( TCODE_BITMAP_TABLE );
07444 if ( !rc )
07445 {
07446
07447
07448
07449
07450
07451 rc = FindMisplacedTable(
07452 0,
07453 TCODE_BITMAP_TABLE, TCODE_BITMAP_RECORD,
07454 ON_nil_uuid,
07455 40
07456 );
07457 if ( rc )
07458 {
07459 rc = BeginRead3dmTable( TCODE_BITMAP_TABLE );
07460 }
07461 }
07462 return rc;
07463 }
07464
07465 bool ON_BinaryArchive::EndRead3dmBitmapTable()
07466 {
07467 return EndRead3dmTable( TCODE_BITMAP_TABLE );
07468 }
07469
07470 int ON_BinaryArchive::Read3dmBitmap(
07471
07472 ON_Bitmap** ppBitmap
07473 )
07474 {
07475 if ( ppBitmap )
07476 *ppBitmap = 0;
07477 ON_Bitmap* bitmap = 0;
07478 int rc = 0;
07479 if ( m_3dm_version != 1 ) {
07480 ON__UINT32 tcode = 0;
07481 ON__INT64 big_value = 0;
07482 if ( BeginRead3dmBigChunk( &tcode, &big_value ) )
07483 {
07484 if ( tcode == TCODE_BITMAP_RECORD )
07485 {
07486 ON_Object* p = 0;
07487 if ( ReadObject( &p ) )
07488 {
07489 bitmap = ON_Bitmap::Cast(p);
07490 if ( !bitmap )
07491 delete p;
07492 else
07493 rc = 1;
07494 }
07495 if (!bitmap)
07496 {
07497 ON_ERROR("ON_BinaryArchive::Read3dmBitmap() - corrupt bitmap table");
07498 }
07499 if ( ppBitmap )
07500 *ppBitmap = bitmap;
07501 else if ( bitmap )
07502 delete bitmap;
07503 }
07504 else if ( tcode != TCODE_ENDOFTABLE )
07505 {
07506 ON_ERROR("ON_BinaryArchive::Read3dmBitmap() - corrupt bitmap table");
07507 }
07508 EndRead3dmChunk();
07509 }
07510 }
07511
07512 return rc;
07513 }
07514
07515
07516 bool ON_BinaryArchive::BeginWrite3dmLayerTable()
07517 {
07518 bool rc = false;
07519 if ( m_3dm_version != 1 ) {
07520 rc = BeginWrite3dmTable( TCODE_LAYER_TABLE );
07521 }
07522 else {
07523 if ( m_chunk.Count() ) {
07524 ON_ERROR("ON_BinaryArchive::BeginWrite3dmLayerTable() - chunk stack should be empty");
07525 return false;
07526 }
07527 if ( m_active_table != no_active_table ) {
07528 ON_ERROR("ON_BinaryArchive::BeginWrite3dmLayerTable() - m_active_table != no_active_table");
07529 }
07530 m_active_table = layer_table;
07531 rc = true;
07532 }
07533
07534 return rc;
07535 }
07536
07537 bool ON_BinaryArchive::Write3dmLayer( const ON_Layer& layer )
07538 {
07539 bool rc = false;
07540 if ( m_active_table != layer_table ) {
07541 ON_ERROR("ON_BinaryArchive::Write3dmLayer() - m_active_table != layer_table");
07542 }
07543
07544 if ( m_3dm_version == 1 ) {
07545
07546 if ( m_chunk.Count() ) {
07547 ON_ERROR("ON_BinaryArchive::Write3dmLayer() - version 1 - chunk stack should be empty");
07548 return false;
07549 }
07550 ON_String s = layer.LayerName();
07551 if ( !s.IsEmpty() ) {
07552 rc = BeginWrite3dmChunk( TCODE_LAYER, 0 );
07553
07554
07555 if (rc) {
07556 rc = BeginWrite3dmChunk( TCODE_LAYERNAME, 0 );
07557 if(rc) rc = WriteString(s);
07558 if (!EndWrite3dmChunk())
07559 rc = false;
07560 }
07561
07562
07563 if (rc) {
07564 rc = BeginWrite3dmChunk( TCODE_RGB, layer.Color() );
07565 if (!EndWrite3dmChunk())
07566 rc = false;
07567 }
07568
07569
07570 if (rc)
07571 {
07572 int mode;
07573 if ( layer.IsLocked() )
07574 mode = 2;
07575 else if ( layer.IsVisible() )
07576 mode = 0;
07577 else
07578 mode = 1;
07579 rc = BeginWrite3dmChunk( TCODE_LAYERSTATE, mode );
07580 if (!EndWrite3dmChunk())
07581 rc = false;
07582 }
07583
07584 if ( !BeginWrite3dmChunk( TCODE_ENDOFTABLE, 0 ) )
07585 rc = false;
07586 if ( !EndWrite3dmChunk() )
07587 rc = false;
07588
07589 if (!EndWrite3dmChunk())
07590 rc = false;
07591 }
07592 }
07593 else {
07594
07595 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
07596 if ( c && c->m_typecode == TCODE_LAYER_TABLE ) {
07597 rc = BeginWrite3dmChunk( TCODE_LAYER_RECORD, 0 );
07598 if ( rc ) {
07599 rc = WriteObject( layer );
07600 if ( !EndWrite3dmChunk() )
07601 rc = false;
07602 }
07603 }
07604 else {
07605 ON_ERROR("ON_BinaryArchive::Write3dmLayer() must be called in BeginWrite3dmLayerTable(2) block");
07606 rc = false;
07607 }
07608 }
07609
07610 return rc;
07611 }
07612
07613 bool ON_BinaryArchive::EndWrite3dmLayerTable()
07614 {
07615 bool rc = false;
07616 if ( m_3dm_version == 1 ) {
07617 if ( m_active_table != layer_table ) {
07618 ON_ERROR("ON_BinaryArchive::EndWrite3dmLayerTable() - m_active_table != layer_table");
07619 }
07620 rc = true;
07621 m_active_table = no_active_table;
07622 }
07623 else {
07624 rc = EndWrite3dmTable( TCODE_LAYER_TABLE );
07625 }
07626 return rc;
07627 }
07628
07629 bool ON_BinaryArchive::BeginRead3dmLayerTable()
07630 {
07631 bool rc = false;
07632 m_3dm_v1_layer_index = 0;
07633 rc = BeginRead3dmTable( TCODE_LAYER_TABLE );
07634 if ( !rc )
07635 {
07636
07637
07638
07639 rc = FindMisplacedTable(
07640 0,
07641 TCODE_LAYER_TABLE, TCODE_LAYER_RECORD,
07642 ON_Layer::m_ON_Layer_class_id.Uuid(),
07643 30
07644 );
07645 if ( rc )
07646 {
07647 rc = BeginRead3dmTable( TCODE_LAYER_TABLE );
07648 }
07649
07650 }
07651 else if ( rc && m_3dm_version == 1 ) {
07652 rc = Seek3dmChunkFromStart( TCODE_LAYER );
07653 rc = true;
07654 }
07655 return rc;
07656 }
07657
07658 int ON_BinaryArchive::Read3dmV1LayerIndex(const char* sV1LayerName) const
07659 {
07660
07661
07662 int layer_index = -1;
07663
07664 if ( ON::read3dm == m_mode
07665 && 0 == m_3dm_opennurbs_version
07666 && 1 == m_3dm_version
07667 && 0 != m_V1_layer_list
07668 && 0 != sV1LayerName
07669 && 0 != sV1LayerName[0]
07670 )
07671 {
07672 struct ON__3dmV1LayerIndex* p = m_V1_layer_list;
07673 int i;
07674 for ( i = 0; 0 != p && i < 1000; i++ )
07675 {
07676 if ( p->m_layer_index < 0 )
07677 break;
07678 if ( p->m_layer_name_length < 1 || p->m_layer_name_length>256)
07679 break;
07680 if ( 0 == p->m_layer_name )
07681 break;
07682 if ( 0 == p->m_layer_name[0] )
07683 break;
07684 if ( 0 != p->m_layer_name[p->m_layer_name_length] )
07685 break;
07686 if ( !on_stricmp(p->m_layer_name,sV1LayerName) )
07687 {
07688 layer_index = p->m_layer_index;
07689 break;
07690 }
07691 p = p->m_next;
07692 }
07693 }
07694
07695 return layer_index;
07696 }
07697
07698 bool ON_BinaryArchive::Read3dmV1Layer( ON_Layer*& layer )
07699 {
07700 ON_String s;
07701 bool rc = 0;
07702 ON__UINT32 tcode;
07703 ON__INT64 big_value;
07704 for (;;)
07705 {
07706 tcode = 0;
07707 big_value = 0;
07708 if (!BeginRead3dmBigChunk(&tcode,&big_value))
07709 break;
07710 if ( tcode == TCODE_LAYER ) {
07711 layer = new ON_Layer();
07712 layer->SetLayerIndex(m_3dm_v1_layer_index++);
07713 rc = 1;
07714 break;
07715 }
07716 if (!EndRead3dmChunk())
07717 break;
07718 }
07719 if ( layer ) {
07720 rc = false;
07721 for (;;)
07722 {
07723 tcode = 0;
07724 big_value = 0;
07725 if (!BeginRead3dmBigChunk(&tcode,&big_value))
07726 break;
07727 switch(tcode)
07728 {
07729 case TCODE_LAYERNAME:
07730 {
07731 int slen = 0;
07732 ReadInt(&slen);
07733 if ( slen < 0 || slen > 10000 )
07734 {
07735 ON_ERROR("ON_BinaryArchive::Read3dmV1Layer() - invalid layer name length");
07736 }
07737 else
07738 {
07739 s.SetLength(slen);
07740 if ( ReadByte( s.Length(), s.Array() ) )
07741 {
07742 layer->SetLayerName(s);
07743 }
07744 }
07745 }
07746 break;
07747 case TCODE_RGB:
07748 {
07749 ON__UINT64 rgb64 = (ON__UINT64)big_value;
07750 ON__UINT32 rgb32 = (ON__UINT32)rgb64;
07751 layer->SetColor( ON_Color((ON__UINT32)rgb32) );
07752 }
07753 break;
07754 case TCODE_LAYERSTATE:
07755 switch (big_value)
07756 {
07757 case 1:
07758 layer->SetVisible(false);
07759 layer->SetLocked(false);
07760 break;
07761 case 2:
07762 layer->SetVisible(true);
07763 layer->SetLocked(true);
07764 break;
07765 default:
07766 layer->SetVisible(true);
07767 layer->SetLocked(false);
07768 break;
07769 }
07770 break;
07771 }
07772 if (!EndRead3dmChunk())
07773 break;
07774 if ( TCODE_ENDOFTABLE == tcode ) {
07775 rc = true;
07776 break;
07777 }
07778 }
07779 if ( !EndRead3dmChunk() )
07780 rc = false;
07781 }
07782 if ( !rc && layer )
07783 {
07784 delete layer;
07785 layer = 0;
07786 }
07787 else if (rc && layer)
07788 {
07789 if ( ON::read3dm == m_mode
07790 && 0 == m_3dm_opennurbs_version
07791 && 1 == m_3dm_version
07792 )
07793 {
07794
07795 int s_length = s.Length();
07796 const char* s_name = s.Array();
07797 if ( layer->LayerIndex() >= 0
07798 && s_length > 0
07799 && s_length < 256
07800 && 0 != s_name
07801 && 0 != s_name[0]
07802 )
07803 {
07804 struct ON__3dmV1LayerIndex* p = (struct ON__3dmV1LayerIndex*)oncalloc(1, sizeof(*p) + (s_length+1)*sizeof(*p->m_layer_name) );
07805 p->m_layer_name = (char*)(p+1);
07806 p->m_layer_index = layer->LayerIndex();
07807 p->m_layer_name_length = s_length;
07808 memcpy(p->m_layer_name,s_name,s_length*sizeof(*p->m_layer_name));
07809 p->m_layer_name[s_length] = 0;
07810 p->m_next = m_V1_layer_list;
07811 m_V1_layer_list = p;
07812 }
07813 }
07814 }
07815 return rc;
07816 }
07817
07818 int ON_BinaryArchive::Read3dmLayer( ON_Layer** ppLayer )
07819 {
07820 if ( !ppLayer )
07821 return 0;
07822 *ppLayer = 0;
07823 if ( m_active_table != layer_table ) {
07824 ON_ERROR("ON_BinaryArchive::BeginRead3dmLayerTable() - m_active_table != no_active_table");
07825 }
07826 ON__UINT32 tcode;
07827 ON__INT64 big_value;
07828 ON_Layer* layer = NULL;
07829
07830 if ( m_3dm_version == 1 ) {
07831 Read3dmV1Layer(layer);
07832 }
07833 else {
07834
07835 tcode = 0;
07836 big_value = 0;
07837 if ( BeginRead3dmBigChunk( &tcode, &big_value ) ) {
07838 if ( tcode == TCODE_LAYER_RECORD ) {
07839 ON_Object* p = 0;
07840 if ( ReadObject( &p ) ) {
07841 layer = ON_Layer::Cast(p);
07842 if ( !layer )
07843 delete p;
07844 }
07845 if (!layer) {
07846 ON_ERROR("ON_BinaryArchive::Read3dmLayer() - corrupt layer table");
07847 }
07848 }
07849 else if ( tcode != TCODE_ENDOFTABLE ) {
07850 ON_ERROR("ON_BinaryArchive::Read3dmLayer() - corrupt layer table");
07851 }
07852 EndRead3dmChunk();
07853 }
07854 }
07855 if ( layer )
07856 layer->HasPerViewportSettings(ON_nil_uuid);
07857 *ppLayer = layer;
07858 return (layer) ? 1 : 0;
07859 }
07860
07861 bool ON_BinaryArchive::EndRead3dmLayerTable()
07862 {
07863 bool rc = false;
07864 if ( m_3dm_version == 1 ) {
07865 if ( m_active_table != layer_table ) {
07866 ON_ERROR("ON_BinaryArchive::EndRead3dmLayerTable() - m_active_table != no_active_table");
07867 rc = false;
07868 }
07869 else if ( m_chunk.Count() ) {
07870 ON_ERROR("ON_BinaryArchive::EndRead3dmLayerTable() - m_chunk.Count() > 0");
07871 rc = false;
07872 }
07873 else {
07874
07875 rc = SeekFromStart(32)?true:false;
07876 }
07877 m_active_table = no_active_table;
07878 }
07879 else {
07880 rc = EndRead3dmTable( TCODE_LAYER_TABLE );
07881 }
07882 return rc;
07883 }
07884
07885
07890
07891 bool ON_BinaryArchive::BeginWrite3dmGroupTable()
07892 {
07893 bool rc = false;
07894 rc = BeginWrite3dmTable( TCODE_GROUP_TABLE );
07895 return rc;
07896 }
07897
07898 bool ON_BinaryArchive::Write3dmGroup( const ON_Group& group )
07899 {
07900 bool rc = false;
07901 if ( m_active_table != group_table ) {
07902 ON_ERROR("ON_BinaryArchive::Write3dmGroup() - m_active_table != group_table");
07903 }
07904
07905 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
07906 if ( c && c->m_typecode == TCODE_GROUP_TABLE ) {
07907 rc = BeginWrite3dmChunk( TCODE_GROUP_RECORD, 0 );
07908 if ( rc ) {
07909 rc = WriteObject( group );
07910 if ( !EndWrite3dmChunk() )
07911 rc = false;
07912 }
07913 }
07914 else {
07915 ON_ERROR("ON_BinaryArchive::Write3dmGroup() must be called in BeginWrite3dmGroupTable() block");
07916 rc = false;
07917 }
07918
07919 return rc;
07920 }
07921
07922 bool ON_BinaryArchive::EndWrite3dmGroupTable()
07923 {
07924 bool rc = false;
07925 rc = EndWrite3dmTable( TCODE_GROUP_TABLE );
07926 return rc;
07927 }
07928
07929 bool ON_BinaryArchive::BeginRead3dmGroupTable()
07930 {
07931 if ( m_3dm_version == 1 ) {
07932 return true;
07933 }
07934 bool rc = false;
07935 rc = BeginRead3dmTable( TCODE_GROUP_TABLE );
07936
07937 if ( !rc )
07938 {
07939
07940
07941
07942
07943
07944 rc = FindMisplacedTable(
07945 0,
07946 TCODE_GROUP_TABLE, TCODE_GROUP_RECORD,
07947 ON_Group::m_ON_Group_class_id.Uuid(),
07948 20
07949 );
07950 if ( rc )
07951 {
07952 rc = BeginRead3dmTable( TCODE_GROUP_TABLE );
07953 }
07954 }
07955
07956 return rc;
07957 }
07958
07959 int ON_BinaryArchive::Read3dmGroup( ON_Group** ppGroup )
07960 {
07961 if ( !ppGroup )
07962 return 0;
07963 *ppGroup = 0;
07964 if ( m_3dm_version == 1 ) {
07965 return 0;
07966 }
07967 if ( m_active_table != group_table ) {
07968 ON_ERROR("ON_BinaryArchive::BeginRead3dmGroupTable() - m_active_table != no_active_table");
07969 }
07970 if ( m_3dm_opennurbs_version < 200012210 ) {
07971
07972 return 0;
07973 }
07974
07975 ON__UINT32 tcode = 0;
07976 ON__INT64 big_value = 0;
07977 ON_Group* group = NULL;
07978 if ( BeginRead3dmBigChunk( &tcode, &big_value ) )
07979 {
07980 if ( tcode == TCODE_GROUP_RECORD ) {
07981 ON_Object* p = 0;
07982 if ( ReadObject( &p ) ) {
07983 group = ON_Group::Cast(p);
07984 if ( !group )
07985 delete p;
07986 }
07987 if (!group) {
07988 ON_ERROR("ON_BinaryArchive::Read3dmGroup() - corrupt group table");
07989 }
07990 }
07991 else if ( tcode != TCODE_ENDOFTABLE ) {
07992 ON_ERROR("ON_BinaryArchive::Read3dmGroup() - corrupt group table");
07993 }
07994 EndRead3dmChunk();
07995 }
07996 *ppGroup = group;
07997 return (group) ? 1 : 0;
07998 }
07999
08000 bool ON_BinaryArchive::EndRead3dmGroupTable()
08001 {
08002 bool rc = false;
08003 if ( m_3dm_version == 1 ) {
08004 return true;
08005 }
08006 else {
08007 rc = EndRead3dmTable( TCODE_GROUP_TABLE );
08008 }
08009 return rc;
08010 }
08011
08016
08017 bool ON_BinaryArchive::BeginWrite3dmFontTable()
08018 {
08019 bool rc = false;
08020 rc = BeginWrite3dmTable( TCODE_FONT_TABLE );
08021 return rc;
08022 }
08023
08024 bool ON_BinaryArchive::Write3dmFont( const ON_Font& font )
08025 {
08026 bool rc = false;
08027 if ( m_active_table != font_table ) {
08028 ON_ERROR("ON_BinaryArchive::Write3dmFont() - m_active_table != font_table");
08029 }
08030
08031 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
08032 if ( c && c->m_typecode == TCODE_FONT_TABLE ) {
08033 rc = BeginWrite3dmChunk( TCODE_FONT_RECORD, 0 );
08034 if ( rc ) {
08035 rc = WriteObject( font );
08036 if ( !EndWrite3dmChunk() )
08037 rc = false;
08038 }
08039 }
08040 else {
08041 ON_ERROR("ON_BinaryArchive::Write3dmFont() must be called in BeginWrite3dmFontTable() block");
08042 rc = false;
08043 }
08044
08045 return rc;
08046 }
08047
08048 bool ON_BinaryArchive::EndWrite3dmFontTable()
08049 {
08050 bool rc = false;
08051 rc = EndWrite3dmTable( TCODE_FONT_TABLE );
08052 return rc;
08053 }
08054
08055 bool ON_BinaryArchive::BeginRead3dmFontTable()
08056 {
08057 if ( m_3dm_version <= 2 ) {
08058 return true;
08059 }
08060 bool rc = false;
08061 rc = BeginRead3dmTable( TCODE_FONT_TABLE );
08062
08063 if ( !rc )
08064 {
08065
08066
08067
08068
08069
08070 rc = FindMisplacedTable(
08071 0,
08072 TCODE_FONT_TABLE, TCODE_FONT_RECORD,
08073 ON_Font::m_ON_Font_class_id.Uuid(),
08074 30
08075 );
08076 if ( rc )
08077 {
08078 rc = BeginRead3dmTable( TCODE_FONT_TABLE );
08079 }
08080 }
08081
08082 return rc;
08083 }
08084
08085 int ON_BinaryArchive::Read3dmFont( ON_Font** ppFont )
08086 {
08087 if ( !ppFont )
08088 return 0;
08089 *ppFont = 0;
08090 if ( m_3dm_version <= 2 ) {
08091 return 0;
08092 }
08093 if ( m_active_table != font_table ) {
08094 ON_ERROR("ON_BinaryArchive::BeginRead3dmFontTable() - m_active_table != no_active_table");
08095 }
08096 if ( m_3dm_opennurbs_version < 200109180 ) {
08097
08098 return 0;
08099 }
08100
08101 ON__UINT32 tcode = 0;
08102 ON__INT64 big_value = 0;
08103 ON_Font* font = NULL;
08104 if ( BeginRead3dmBigChunk( &tcode, &big_value ) )
08105 {
08106 if ( tcode == TCODE_FONT_RECORD ) {
08107 ON_Object* p = 0;
08108 if ( ReadObject( &p ) ) {
08109 font = ON_Font::Cast(p);
08110 if ( !font )
08111 delete p;
08112 }
08113 if (!font) {
08114 ON_ERROR("ON_BinaryArchive::Read3dmFont() - corrupt font table");
08115 }
08116 }
08117 else if ( tcode != TCODE_ENDOFTABLE ) {
08118 ON_ERROR("ON_BinaryArchive::Read3dmFont() - corrupt font table");
08119 }
08120 EndRead3dmChunk();
08121 }
08122 *ppFont = font;
08123 return (font) ? 1 : 0;
08124 }
08125
08126 bool ON_BinaryArchive::EndRead3dmFontTable()
08127 {
08128 bool rc = false;
08129 if ( m_3dm_version <= 2 ) {
08130 return true;
08131 }
08132 else {
08133 rc = EndRead3dmTable( TCODE_FONT_TABLE );
08134 }
08135 return rc;
08136 }
08137
08142
08143 bool ON_BinaryArchive::BeginWrite3dmDimStyleTable()
08144 {
08145 bool rc = false;
08146 rc = BeginWrite3dmTable( TCODE_DIMSTYLE_TABLE );
08147 return rc;
08148 }
08149
08150 bool ON_BinaryArchive::Write3dmDimStyle( const ON_DimStyle& dimstyle )
08151 {
08152 bool rc = false;
08153 if ( m_active_table != dimstyle_table ) {
08154 ON_ERROR("ON_BinaryArchive::Write3dmDimStyle() - m_active_table != dimstyle_table");
08155 }
08156
08157 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
08158 if ( c && c->m_typecode == TCODE_DIMSTYLE_TABLE ) {
08159 rc = BeginWrite3dmChunk( TCODE_DIMSTYLE_RECORD, 0 );
08160 if ( rc ) {
08161 rc = WriteObject( dimstyle );
08162 if ( !EndWrite3dmChunk() )
08163 rc = false;
08164 }
08165 }
08166 else {
08167 ON_ERROR("ON_BinaryArchive::Write3dmDimStyle() must be called in BeginWrite3dmDimStyleTable() block");
08168 rc = false;
08169 }
08170
08171 return rc;
08172 }
08173
08174 bool ON_BinaryArchive::EndWrite3dmDimStyleTable()
08175 {
08176 bool rc = false;
08177 rc = EndWrite3dmTable( TCODE_DIMSTYLE_TABLE );
08178 return rc;
08179 }
08180
08181 bool ON_BinaryArchive::BeginRead3dmDimStyleTable()
08182 {
08183 if ( m_3dm_version <= 2 ) {
08184 return true;
08185 }
08186 bool rc = false;
08187 rc = BeginRead3dmTable( TCODE_DIMSTYLE_TABLE );
08188
08189 if ( !rc )
08190 {
08191
08192
08193
08194
08195
08196 rc = FindMisplacedTable(
08197 0,
08198 TCODE_DIMSTYLE_TABLE, TCODE_DIMSTYLE_RECORD,
08199 ON_DimStyle::m_ON_DimStyle_class_id.Uuid(),
08200 30
08201 );
08202 if ( rc )
08203 {
08204 rc = BeginRead3dmTable( TCODE_DIMSTYLE_TABLE );
08205 }
08206 }
08207
08208 return rc;
08209 }
08210
08211 int ON_BinaryArchive::Read3dmDimStyle( ON_DimStyle** ppDimStyle )
08212 {
08213 if ( !ppDimStyle )
08214 return 0;
08215 *ppDimStyle = 0;
08216 if ( m_3dm_version <= 2 ) {
08217 return 0;
08218 }
08219 if ( m_active_table != dimstyle_table ) {
08220 ON_ERROR("ON_BinaryArchive::BeginRead3dmDimStyleTable() - m_active_table != no_active_table");
08221 }
08222 if ( m_3dm_opennurbs_version < 200109260 ) {
08223
08224 return 0;
08225 }
08226
08227 ON__UINT32 tcode = 0;
08228 ON__INT64 big_value = 0;
08229 ON_DimStyle* dimstyle = NULL;
08230 tcode = 0;
08231 if ( BeginRead3dmBigChunk( &tcode, &big_value ) )
08232 {
08233 if ( tcode == TCODE_DIMSTYLE_RECORD ) {
08234 ON_Object* p = 0;
08235 if ( ReadObject( &p ) ) {
08236 dimstyle = ON_DimStyle::Cast(p);
08237 if ( !dimstyle )
08238 delete p;
08239 }
08240 if (!dimstyle) {
08241 ON_ERROR("ON_BinaryArchive::Read3dmDimStyle() - corrupt dimstyle table");
08242 }
08243 }
08244 else if ( tcode != TCODE_ENDOFTABLE ) {
08245 ON_ERROR("ON_BinaryArchive::Read3dmDimStyle() - corrupt dimstyle table");
08246 }
08247 EndRead3dmChunk();
08248 }
08249 *ppDimStyle = dimstyle;
08250 return (dimstyle) ? 1 : 0;
08251 }
08252
08253 bool ON_BinaryArchive::EndRead3dmDimStyleTable()
08254 {
08255 bool rc = false;
08256 if ( m_3dm_version <= 2 ) {
08257 return true;
08258 }
08259 else {
08260 rc = EndRead3dmTable( TCODE_DIMSTYLE_TABLE );
08261 }
08262 return rc;
08263 }
08264
08269
08270 bool ON_BinaryArchive::BeginWrite3dmHatchPatternTable()
08271 {
08272 bool rc = false;
08273 rc = BeginWrite3dmTable( TCODE_HATCHPATTERN_TABLE );
08274 return rc;
08275 }
08276
08277 bool ON_BinaryArchive::Write3dmHatchPattern( const ON_HatchPattern& pattern )
08278 {
08279 bool rc = false;
08280 if ( m_active_table != hatchpattern_table ) {
08281 ON_ERROR("ON_BinaryArchive::Write3dmHatchPattern() - m_active_table != hatchpattern_table");
08282 }
08283
08284 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
08285 if ( c && c->m_typecode == TCODE_HATCHPATTERN_TABLE )
08286 {
08287 rc = BeginWrite3dmChunk( TCODE_HATCHPATTERN_RECORD, 0 );
08288 if (rc)
08289 {
08290 rc = WriteObject( pattern );
08291 if ( !EndWrite3dmChunk() )
08292 rc = false;
08293 }
08294
08295
08296
08297
08298
08299
08300
08301
08302
08303
08304
08305
08306
08307
08308
08309
08310
08311 }
08312 else
08313 {
08314 ON_ERROR("ON_BinaryArchive::Write3dmHatchPattern() must be called in BeginWrite3dmHatchPatternTable() block");
08315 rc = false;
08316 }
08317
08318 return rc;
08319 }
08320
08321 bool ON_BinaryArchive::EndWrite3dmHatchPatternTable()
08322 {
08323 bool rc = false;
08324 rc = EndWrite3dmTable( TCODE_HATCHPATTERN_TABLE );
08325 return rc;
08326 }
08327
08328 bool ON_BinaryArchive::BeginRead3dmHatchPatternTable()
08329 {
08330 if ( m_3dm_version <= 3)
08331 {
08332 return true;
08333 }
08334 bool rc = BeginRead3dmTable( TCODE_HATCHPATTERN_TABLE );
08335
08336 if ( !rc && m_3dm_opennurbs_version >= 200511010 )
08337 {
08338
08339
08340
08341
08342
08343
08344 rc = FindMisplacedTable(
08345 0,
08346 TCODE_HATCHPATTERN_TABLE, TCODE_HATCHPATTERN_RECORD,
08347 ON_HatchPattern::m_ON_HatchPattern_class_id.Uuid(),
08348 30
08349 );
08350 if ( rc )
08351 {
08352 rc = BeginRead3dmTable( TCODE_HATCHPATTERN_TABLE );
08353 }
08354 }
08355
08356 return rc;
08357 }
08358
08359 int ON_BinaryArchive::Read3dmHatchPattern( ON_HatchPattern** ppPattern )
08360 {
08361 if( !ppPattern )
08362 return 0;
08363
08364 *ppPattern = 0;
08365 if( m_3dm_version <= 3)
08366 return 0;
08367
08368 if ( m_active_table != hatchpattern_table )
08369 {
08370 ON_ERROR("ON_BinaryArchive::BeginRead3dmHatchPatternTable() - m_active_table != hatchpattern_table");
08371 }
08372 if ( m_3dm_opennurbs_version < 200405030 )
08373 {
08374
08375 return 0;
08376 }
08377
08378 ON__UINT32 tcode = 0;
08379 ON__INT64 big_value = 0;
08380 ON_HatchPattern* pPat = NULL;
08381 if( BeginRead3dmBigChunk( &tcode, &big_value))
08382 {
08383 if ( tcode == TCODE_HATCHPATTERN_RECORD )
08384 {
08385 if ( m_3dm_opennurbs_version < 200511010 )
08386 {
08387
08388
08389 pPat = new ON_HatchPattern;
08390 if( !pPat->Read( *this))
08391 {
08392 delete pPat;
08393 pPat = NULL;
08394 ON_ERROR("ON_BinaryArchive::Read3dmHatchPattern() - corrupt hatch pattern table");
08395 }
08396 }
08397 else
08398 {
08399 ON_Object* p = 0;
08400 if ( ReadObject( &p ) )
08401 {
08402 pPat = ON_HatchPattern::Cast(p);
08403 if ( !pPat )
08404 delete p;
08405 }
08406 if (!pPat)
08407 {
08408 ON_ERROR("ON_BinaryArchive::Read3dmLayer() - corrupt layer table");
08409 }
08410 }
08411 }
08412 else if ( tcode != TCODE_ENDOFTABLE )
08413 {
08414 ON_ERROR("ON_BinaryArchive::Read3dmHatchPattern() - corrupt hatch pattern table");
08415 }
08416
08417 EndRead3dmChunk();
08418 }
08419 *ppPattern = pPat;
08420 return( pPat) ? 1 : 0;
08421 }
08422
08423 bool ON_BinaryArchive::EndRead3dmHatchPatternTable()
08424 {
08425 bool rc = false;
08426 if( m_3dm_version <= 3)
08427 {
08428 return true;
08429 }
08430 else
08431 {
08432 rc = EndRead3dmTable( TCODE_HATCHPATTERN_TABLE);
08433 }
08434 return rc;
08435 }
08436
08437
08438
08443
08444 bool ON_BinaryArchive::BeginWrite3dmLinetypeTable()
08445 {
08446 bool rc = BeginWrite3dmTable( TCODE_LINETYPE_TABLE );
08447 return rc;
08448 }
08449
08450 bool ON_BinaryArchive::Write3dmLinetype( const ON_Linetype& linetype )
08451 {
08452 bool rc = false;
08453
08454 if( m_active_table != linetype_table )
08455 {
08456 ON_ERROR("ON_BinaryArchive::Write3dmLinetype() - m_active_table != linetype_table");
08457 }
08458
08459 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
08460 if ( c && c->m_typecode == TCODE_LINETYPE_TABLE )
08461 {
08462 rc = BeginWrite3dmChunk( TCODE_LINETYPE_RECORD, 0 );
08463 if ( rc )
08464 {
08465 rc = WriteObject( linetype );
08466 if ( !EndWrite3dmChunk())
08467 rc = false;
08468 }
08469 }
08470 else
08471 {
08472 ON_ERROR("ON_BinaryArchive::Write3dmLinetype() must be called in BeginWrite3dmLinetypeTable() block");
08473 rc = false;
08474 }
08475
08476 return rc;
08477 }
08478
08479 bool ON_BinaryArchive::EndWrite3dmLinetypeTable()
08480 {
08481 bool rc = EndWrite3dmTable( TCODE_LINETYPE_TABLE );
08482 return rc;
08483 }
08484
08485 bool ON_BinaryArchive::BeginRead3dmLinetypeTable()
08486 {
08487 bool rc = false;
08488
08489 if ( m_3dm_version < 4 || m_3dm_opennurbs_version < 200503170 )
08490 {
08491 rc = true;
08492 }
08493 else
08494 {
08495 rc = BeginRead3dmTable( TCODE_LINETYPE_TABLE );
08496 if ( !rc )
08497 {
08498
08499
08500
08501
08502
08503 rc = FindMisplacedTable(
08504 0,
08505 TCODE_LINETYPE_TABLE, TCODE_LINETYPE_RECORD,
08506 ON_Linetype::m_ON_Linetype_class_id.Uuid(),
08507 20
08508 );
08509 if ( rc )
08510 {
08511 rc = BeginRead3dmTable( TCODE_LINETYPE_TABLE );
08512 }
08513 }
08514 }
08515
08516 return rc;
08517 }
08518
08519 int ON_BinaryArchive::Read3dmLinetype( ON_Linetype** ppLinetype )
08520 {
08521 if( !ppLinetype)
08522 return 0;
08523
08524 *ppLinetype = 0;
08525
08526 if( m_3dm_version < 4 || m_3dm_opennurbs_version < 200503170)
08527 return 0;
08528
08529 if ( m_active_table != linetype_table )
08530 {
08531 ON_ERROR("ON_BinaryArchive::BeginRead3dmLinetypeTable() - m_active_table != linetype_table");
08532 }
08533
08534 ON__UINT32 tcode = 0;
08535 ON__INT64 big_value = 0;
08536 ON_Linetype* linetype = NULL;
08537 int rc = -1;
08538 if( BeginRead3dmBigChunk( &tcode, &big_value))
08539 {
08540 if ( tcode == TCODE_LINETYPE_RECORD )
08541 {
08542 ON_Object* p = 0;
08543 if ( ReadObject( &p ) )
08544 {
08545 linetype = ON_Linetype::Cast(p);
08546 if (!linetype )
08547 delete p;
08548 else
08549 {
08550 if (ppLinetype)
08551 *ppLinetype = linetype;
08552 rc = 1;
08553 }
08554 }
08555 if (!linetype)
08556 {
08557 ON_ERROR("ON_BinaryArchive::Read3dmLinetype() - corrupt linetype table");
08558 }
08559 }
08560 else if ( tcode == TCODE_ENDOFTABLE )
08561 {
08562
08563 rc = 0;
08564 }
08565 else
08566 {
08567 ON_ERROR("ON_BinaryArchive::Read3dmLinetype() - corrupt linetype table");
08568 }
08569 if (!EndRead3dmChunk())
08570 rc = -1;
08571 }
08572
08573 return rc;
08574 }
08575
08576 bool ON_BinaryArchive::EndRead3dmLinetypeTable()
08577 {
08578 bool rc = false;
08579 if( m_3dm_version < 4 || m_3dm_opennurbs_version < 200503170)
08580 {
08581 rc = true;
08582 }
08583 else
08584 {
08585 rc = EndRead3dmTable( TCODE_LINETYPE_TABLE);
08586 }
08587 return rc;
08588 }
08589
08590
08596
08597 bool ON_BinaryArchive::BeginWrite3dmInstanceDefinitionTable()
08598 {
08599 bool rc = false;
08600 rc = BeginWrite3dmTable( TCODE_INSTANCE_DEFINITION_TABLE );
08601 return rc;
08602 }
08603
08604 bool ON_BinaryArchive::Write3dmInstanceDefinition( const ON_InstanceDefinition& idef )
08605 {
08606 bool rc = false;
08607 if ( m_active_table != instance_definition_table ) {
08608 ON_ERROR("ON_BinaryArchive::Write3dmInstanceDefinition() - m_active_table != instance_definition_table");
08609 }
08610
08611 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
08612 if ( c && c->m_typecode == TCODE_INSTANCE_DEFINITION_TABLE ) {
08613 rc = BeginWrite3dmChunk( TCODE_INSTANCE_DEFINITION_RECORD, 0 );
08614 if ( rc ) {
08615 rc = WriteObject( idef );
08616 if ( !EndWrite3dmChunk() )
08617 rc = false;
08618 }
08619 }
08620 else {
08621 ON_ERROR("ON_BinaryArchive::Write3dmInstanceDefinition() must be called in BeginWrite3dmInstanceDefinitionTable() block");
08622 rc = false;
08623 }
08624
08625 return rc;
08626 }
08627
08628 bool ON_BinaryArchive::EndWrite3dmInstanceDefinitionTable()
08629 {
08630 bool rc = false;
08631 rc = EndWrite3dmTable( TCODE_INSTANCE_DEFINITION_TABLE );
08632 return rc;
08633 }
08634
08635 bool ON_BinaryArchive::BeginRead3dmInstanceDefinitionTable()
08636 {
08637 if ( m_3dm_version <= 2 ) {
08638 return true;
08639 }
08640 bool rc = false;
08641 rc = BeginRead3dmTable( TCODE_INSTANCE_DEFINITION_TABLE );
08642
08643 if ( !rc )
08644 {
08645
08646
08647
08648
08649
08650 rc = FindMisplacedTable(
08651 0,
08652 TCODE_INSTANCE_DEFINITION_TABLE, TCODE_INSTANCE_DEFINITION_RECORD,
08653 ON_InstanceDefinition::m_ON_InstanceDefinition_class_id.Uuid(),
08654 30
08655 );
08656 if ( rc )
08657 {
08658 rc = BeginRead3dmTable( TCODE_INSTANCE_DEFINITION_TABLE );
08659 }
08660 }
08661
08662 return rc;
08663 }
08664
08665 int ON_BinaryArchive::Read3dmInstanceDefinition( ON_InstanceDefinition** ppInstanceDefinition )
08666 {
08667 if ( !ppInstanceDefinition )
08668 return 0;
08669 *ppInstanceDefinition = 0;
08670 if ( m_3dm_version <= 2 ) {
08671 return 0;
08672 }
08673 if ( m_active_table != instance_definition_table )
08674 {
08675 ON_ERROR("ON_BinaryArchive::BeginRead3dmInstanceDefinitionTable() - m_active_table != no_active_table");
08676 }
08677 if ( m_3dm_opennurbs_version < 200205110 )
08678 {
08679
08680 return 0;
08681 }
08682
08683 ON__UINT32 tcode = 0;
08684 ON__INT64 big_value = 0;
08685 ON_InstanceDefinition* idef = NULL;
08686 if ( BeginRead3dmBigChunk( &tcode, &big_value ) )
08687 {
08688 if ( tcode == TCODE_INSTANCE_DEFINITION_RECORD ) {
08689 ON_Object* p = 0;
08690 if ( ReadObject( &p ) ) {
08691 idef = ON_InstanceDefinition::Cast(p);
08692 if ( !idef )
08693 delete p;
08694 }
08695 if (!idef) {
08696 ON_ERROR("ON_BinaryArchive::Read3dmInstanceDefinition() - corrupt instance definition table");
08697 }
08698 }
08699 else if ( tcode != TCODE_ENDOFTABLE ) {
08700 ON_ERROR("ON_BinaryArchive::Read3dmInstanceDefinition() - corrupt instance definition table");
08701 }
08702 EndRead3dmChunk();
08703 }
08704 *ppInstanceDefinition = idef;
08705 return (idef) ? 1 : 0;
08706 }
08707
08708 bool ON_BinaryArchive::EndRead3dmInstanceDefinitionTable()
08709 {
08710 bool rc = false;
08711 if ( m_3dm_version <= 2 ) {
08712 return true;
08713 }
08714 else {
08715 rc = EndRead3dmTable( TCODE_INSTANCE_DEFINITION_TABLE );
08716 }
08717 return rc;
08718 }
08719
08725
08726 bool ON_BinaryArchive::BeginWrite3dmTextureMappingTable()
08727 {
08728 return BeginWrite3dmTable( TCODE_TEXTURE_MAPPING_TABLE );
08729 }
08730
08731 bool ON_BinaryArchive::Write3dmTextureMapping( const ON_TextureMapping& texture_mapping )
08732 {
08733 bool rc = false;
08734
08735 if ( m_active_table != texture_mapping_table )
08736 {
08737 ON_ERROR("ON_BinaryArchive::Write3dmTextureMapping() - m_active_table != texture_mapping_table");
08738 }
08739
08740 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
08741 if ( !c || c->m_typecode != TCODE_TEXTURE_MAPPING_TABLE )
08742 {
08743 ON_ERROR("ON_BinaryArchive::Write3dmTextureMapping() - active chunk typecode != TCODE_TEXTURE_MAPPING_TABLE");
08744 }
08745 else
08746 {
08747 rc = BeginWrite3dmChunk( TCODE_TEXTURE_MAPPING_RECORD, 0 );
08748 if (rc)
08749 {
08750 rc = WriteObject( texture_mapping );
08751 if ( !EndWrite3dmChunk() )
08752 rc = false;
08753 }
08754 }
08755 return rc;
08756 }
08757
08758 bool ON_BinaryArchive::EndWrite3dmTextureMappingTable()
08759 {
08760 return EndWrite3dmTable( TCODE_TEXTURE_MAPPING_TABLE );
08761 }
08762
08763 bool ON_BinaryArchive::BeginRead3dmTextureMappingTable()
08764 {
08765 if ( m_3dm_version < 4 || m_3dm_opennurbs_version < 200511110 )
08766 {
08767 return true;
08768 }
08769
08770 bool rc = BeginRead3dmTable( TCODE_TEXTURE_MAPPING_TABLE );
08771 if ( !rc )
08772 {
08773
08774
08775
08776
08777
08778
08779
08780
08781
08782
08783
08784 rc = FindMisplacedTable(
08785 0,
08786 TCODE_TEXTURE_MAPPING_TABLE, TCODE_TEXTURE_MAPPING_RECORD,
08787 ON_TextureMapping::m_ON_TextureMapping_class_id.Uuid(),
08788 sizeof(ON_TextureMapping)
08789 );
08790 if ( rc )
08791 {
08792 rc = BeginRead3dmTable( TCODE_TEXTURE_MAPPING_TABLE );
08793 }
08794 }
08795 return rc;
08796 }
08797
08798 int ON_BinaryArchive::Read3dmTextureMapping( ON_TextureMapping** ppTextureMapping )
08799 {
08800 int rc = 0;
08801 if ( !ppTextureMapping )
08802 return 0;
08803 *ppTextureMapping = 0;
08804 ON_TextureMapping* texture_mapping = NULL;
08805 ON__UINT32 tcode = 0;
08806 ON__INT64 big_value = 0;
08807 if ( m_3dm_version < 4 || m_3dm_opennurbs_version < 200511110 )
08808 {
08809
08810 return 0;
08811 }
08812
08813 rc = -1;
08814 if ( BeginRead3dmBigChunk( &tcode, &big_value ) )
08815 {
08816 if ( tcode == TCODE_TEXTURE_MAPPING_RECORD )
08817 {
08818 ON_Object* p = 0;
08819 if ( ReadObject( &p ) )
08820 {
08821 texture_mapping = ON_TextureMapping::Cast(p);
08822 if ( !texture_mapping )
08823 delete p;
08824 else
08825 {
08826 if ( ppTextureMapping )
08827 *ppTextureMapping = texture_mapping;
08828 rc = 1;
08829 }
08830 }
08831 if (!texture_mapping)
08832 {
08833 ON_ERROR("ON_BinaryArchive::Read3dmTextureMapping() - corrupt texture_mapping table");
08834 }
08835 }
08836 else if ( tcode == TCODE_ENDOFTABLE )
08837 {
08838
08839 rc = 0;
08840 }
08841 else
08842 {
08843 ON_ERROR("ON_BinaryArchive::Read3dmTextureMapping() - corrupt texture_mapping table");
08844 }
08845 if ( !EndRead3dmChunk() )
08846 rc = -1;
08847 }
08848
08849 return rc;
08850 }
08851
08852 bool ON_BinaryArchive::EndRead3dmTextureMappingTable()
08853 {
08854 bool rc = false;
08855 if ( m_3dm_version < 4 || m_3dm_opennurbs_version < 200511110 )
08856 {
08857 rc = true;
08858 }
08859 else
08860 {
08861 rc = EndRead3dmTable( TCODE_TEXTURE_MAPPING_TABLE );
08862 }
08863 return rc;
08864 }
08865
08871
08872 bool ON_BinaryArchive::BeginWrite3dmHistoryRecordTable()
08873 {
08874 return BeginWrite3dmTable( TCODE_HISTORYRECORD_TABLE );
08875 }
08876
08877 bool ON_BinaryArchive::Write3dmHistoryRecord( const ON_HistoryRecord& history_record )
08878 {
08879 bool rc = false;
08880
08881 if ( m_active_table != historyrecord_table )
08882 {
08883 ON_ERROR("ON_BinaryArchive::Write3dmHistoryRecord() - m_active_table != history_record_table");
08884 }
08885
08886 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
08887 if ( !c || c->m_typecode != TCODE_HISTORYRECORD_TABLE )
08888 {
08889 ON_ERROR("ON_BinaryArchive::Write3dmHistoryRecord() - active chunk typecode != TCODE_HISTORYRECORD_TABLE");
08890 }
08891 else
08892 {
08893 rc = BeginWrite3dmChunk( TCODE_HISTORYRECORD_RECORD, 0 );
08894 if (rc)
08895 {
08896 rc = WriteObject( history_record );
08897 if ( !EndWrite3dmChunk() )
08898 rc = false;
08899 }
08900 }
08901 return rc;
08902 }
08903
08904 bool ON_BinaryArchive::EndWrite3dmHistoryRecordTable()
08905 {
08906 return EndWrite3dmTable( TCODE_HISTORYRECORD_TABLE );
08907 }
08908
08909 bool ON_BinaryArchive::BeginRead3dmHistoryRecordTable()
08910 {
08911 if ( m_3dm_version < 4 || m_3dm_opennurbs_version < 200601180 )
08912 {
08913 return true;
08914 }
08915
08916 bool rc = BeginRead3dmTable( TCODE_HISTORYRECORD_TABLE );
08917 if ( !rc )
08918 {
08919
08920
08921
08922
08923
08924
08925
08926
08927
08928
08929
08930 rc = FindMisplacedTable(
08931 0,
08932 TCODE_HISTORYRECORD_TABLE, TCODE_HISTORYRECORD_RECORD,
08933 ON_HistoryRecord::m_ON_HistoryRecord_class_id.Uuid(),
08934 sizeof(ON_HistoryRecord)
08935 );
08936 if ( rc )
08937 {
08938 rc = BeginRead3dmTable( TCODE_HISTORYRECORD_TABLE );
08939 }
08940 }
08941 return rc;
08942 }
08943
08944 int ON_BinaryArchive::Read3dmHistoryRecord( ON_HistoryRecord*& history_record )
08945 {
08946 int rc = 0;
08947 history_record = 0;
08948 ON__UINT32 tcode = 0;
08949 ON__INT64 big_value = 0;
08950 if ( m_3dm_version < 4 || m_3dm_opennurbs_version < 200601180 )
08951 {
08952
08953 return 0;
08954 }
08955
08956 rc = -1;
08957 if ( BeginRead3dmBigChunk( &tcode, &big_value ) )
08958 {
08959 if ( tcode == TCODE_HISTORYRECORD_RECORD )
08960 {
08961 ON_Object* p = 0;
08962 if ( ReadObject( &p ) )
08963 {
08964 history_record = ON_HistoryRecord::Cast(p);
08965 if ( !history_record )
08966 {
08967 delete p;
08968 }
08969 else
08970 {
08971 rc = 1;
08972 }
08973 }
08974 if (!history_record)
08975 {
08976 ON_ERROR("ON_BinaryArchive::Read3dmHistoryRecord() - corrupt history_record table");
08977 }
08978 }
08979 else if ( tcode == TCODE_ENDOFTABLE )
08980 {
08981
08982 rc = 0;
08983 }
08984 else
08985 {
08986 ON_ERROR("ON_BinaryArchive::Read3dmHistoryRecord() - corrupt history_record table");
08987 }
08988 if ( !EndRead3dmChunk() )
08989 rc = -1;
08990 }
08991
08992 return rc;
08993 }
08994
08995 bool ON_BinaryArchive::EndRead3dmHistoryRecordTable()
08996 {
08997 bool rc = false;
08998 if ( m_3dm_version < 4 || m_3dm_opennurbs_version < 200601180 )
08999 {
09000 rc = true;
09001 }
09002 else
09003 {
09004 rc = EndRead3dmTable( TCODE_HISTORYRECORD_TABLE );
09005 }
09006 return rc;
09007 }
09008
09014
09015 bool ON_BinaryArchive::BeginWrite3dmMaterialTable()
09016 {
09017 return BeginWrite3dmTable( TCODE_MATERIAL_TABLE );
09018 }
09019
09020 bool ON_BinaryArchive::Write3dmMaterial( const ON_Material& material )
09021 {
09022 bool rc = false;
09023
09024 if ( m_active_table != material_table )
09025 {
09026 ON_ERROR("ON_BinaryArchive::Write3dmMaterial() - m_active_table != material_table");
09027 }
09028
09029 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
09030 if ( !c || c->m_typecode != TCODE_MATERIAL_TABLE )
09031 {
09032 ON_ERROR("ON_BinaryArchive::Write3dmMaterial() - active chunk typecode != TCODE_MATERIAL_TABLE");
09033 }
09034 else
09035 {
09036 rc = BeginWrite3dmChunk( TCODE_MATERIAL_RECORD, 0 );
09037 if (rc)
09038 {
09039 rc = WriteObject( material );
09040 if ( !EndWrite3dmChunk() )
09041 rc = false;
09042 }
09043 }
09044 return rc;
09045 }
09046
09047 bool ON_BinaryArchive::EndWrite3dmMaterialTable()
09048 {
09049 return EndWrite3dmTable( TCODE_MATERIAL_TABLE );
09050 }
09051
09052 bool ON_BinaryArchive::BeginRead3dmMaterialTable()
09053 {
09054 m_3dm_v1_material_index = 0;
09055 bool rc = BeginRead3dmTable( TCODE_MATERIAL_TABLE );
09056 if ( !rc )
09057 {
09058
09059
09060
09061
09062
09063
09064
09065
09066
09067
09068
09069 rc = FindMisplacedTable(
09070 0,
09071 TCODE_MATERIAL_TABLE, TCODE_MATERIAL_RECORD,
09072 ON_Material::m_ON_Material_class_id.Uuid(),
09073 114
09074 );
09075 if ( rc )
09076 {
09077 rc = BeginRead3dmTable( TCODE_MATERIAL_TABLE );
09078 }
09079 }
09080 return rc;
09081 }
09082
09083 bool ON_BinaryArchive::Read3dmV1String( ON_String& s )
09084 {
09085 int string_length = 0;
09086 s.Empty();
09087 bool rc = ReadInt( &string_length );
09088 if (rc) {
09089 s.ReserveArray(string_length+1);
09090 rc = ReadChar( string_length, s.Array() );
09091 if (rc)
09092 s.SetLength(string_length);
09093 }
09094 return rc;
09095 }
09096
09097
09098 class ON__3dmV1_XDATA
09099 {
09100
09101 public:
09102 enum
09103 {
09104 unknown_xdata = 0,
09105 hidden_object_layer_name,
09106 locked_object_layer_name,
09107 arrow_direction,
09108 dot_text
09109 }
09110 m_type;
09111 ON_String m_string;
09112 ON_3dVector m_vector;
09113 };
09114
09115 bool ON_BinaryArchive::Read3dmV1AttributesOrMaterial(
09116 ON_3dmObjectAttributes* attributes,
09117 ON_Material* material,
09118 ON_BOOL32& bHaveMat,
09119 unsigned int end_mark_tcode,
09120 ON__3dmV1_XDATA* xdata
09121 )
09122 {
09123
09124
09125 if ( 0 != xdata )
09126 {
09127 xdata->m_type = ON__3dmV1_XDATA::unknown_xdata;
09128 }
09129
09130 bool rc = false;
09131 unsigned int u;
09132 ON__UINT32 tcode = 0;
09133 ON__INT64 big_value = 0;
09134 ON_Color c;
09135 bHaveMat = false;
09136 bool bEndRead3dmChunk_rc;
09137
09138 const unsigned int saved_error_message_mask = m_error_message_mask;
09139
09140 int xdata_layer_index = -1;
09141
09142 if ( attributes )
09143 {
09144 attributes->Default();
09145 }
09146
09147 if ( material )
09148 {
09149 material->Default();
09150 material->m_diffuse.SetRGB(255,255,255);
09151 material->m_specular.SetRGB(255,255,255);
09152 material->m_ambient.SetRGB(0,0,0);
09153 }
09154
09155 for (;;)
09156 {
09157 m_error_message_mask = saved_error_message_mask;
09158
09159 if ( end_mark_tcode != TCODE_ENDOFTABLE ) {
09160 tcode = 0;
09161 big_value = 0;
09162 if ( !PeekAt3dmBigChunkType(&tcode,&big_value) ) {
09163 break;
09164 }
09165 if ( tcode == end_mark_tcode ) {
09166 rc = true;
09167 break;
09168 }
09169 }
09170 tcode = 0;
09171 big_value = 0;
09172 if ( !BeginRead3dmBigChunk(&tcode,&big_value) )
09173 break;
09174 if ( tcode == end_mark_tcode ) {
09175 rc = EndRead3dmChunk();
09176 break;
09177 }
09178
09179 switch( tcode )
09180 {
09181 case (TCODE_OPENNURBS_OBJECT | TCODE_CRC | 0x7FFD):
09182
09183 if ( attributes )
09184 ReadUuid( attributes->m_uuid );
09185 break;
09186
09187 case TCODE_LAYERREF:
09188 if ( attributes
09189 && (-1 == xdata_layer_index || attributes->m_layer_index != xdata_layer_index)
09190 && (big_value >= 0 && big_value < 0x7FFFFFFF)
09191 )
09192 {
09193 attributes->m_layer_index = (int)big_value;
09194 }
09195 break;
09196
09197 case TCODE_RGB:
09198 if ( big_value != 0xFFFFFF )
09199 {
09200 if ( material )
09201 {
09202 ON__UINT64 rgb64 = (ON__UINT64)big_value;
09203 ON__UINT32 rgb32 = (ON__UINT32)rgb64;
09204 u = rgb32;
09205 c.SetRGB( u%256,(u>>8)%256,(u>>16)%256 );
09206 material->SetDiffuse(c);
09207 material->SetShine((u >> 24)/100.0*ON_Material::MaxShine());
09208 }
09209 bHaveMat = true;
09210 }
09211 break;
09212
09213 case TCODE_RGBDISPLAY:
09214 if ( attributes )
09215 {
09216 ON__UINT64 rgb64 = (ON__UINT64)big_value;
09217 ON__UINT32 rgb32 = (ON__UINT32)rgb64;
09218 u = rgb32;
09219 attributes->m_color.SetRGB( u%256,(u>>8)%256,(u>>16)%256 );
09220 }
09221 break;
09222
09223 case TCODE_TRANSPARENCY:
09224 if ( big_value > 0 && big_value <= 255 )
09225 {
09226 if ( material )
09227 material->SetTransparency(big_value/255.0);
09228 bHaveMat = true;
09229 }
09230 break;
09231
09232 case TCODE_NAME:
09233 if ( attributes ) {
09234 ON_String s;
09235 Read3dmV1String(s);
09236 if( s.Length() > 0 )
09237 attributes->m_name = s;
09238 }
09239 break;
09240
09241 case TCODE_TEXTUREMAP:
09242 {
09243 ON_String s;
09244 Read3dmV1String(s);
09245 if ( s.Length() > 0 )
09246 {
09247 if ( material )
09248 {
09249 ON_Texture& tx = material->m_textures.AppendNew();
09250 tx.m_filename = s;
09251 tx.m_type = ON_Texture::bitmap_texture;
09252 }
09253 bHaveMat = true;
09254 }
09255 }
09256 break;
09257
09258 case TCODE_BUMPMAP:
09259 if ( material ) {
09260 ON_String s;
09261 Read3dmV1String(s);
09262 if ( s.Length() )
09263 {
09264 if ( material )
09265 {
09266 ON_Texture& tx = material->m_textures.AppendNew();
09267 tx.m_filename = s;
09268 tx.m_type = ON_Texture::bump_texture;
09269 }
09270 bHaveMat = true;
09271 }
09272 }
09273 break;
09274
09275 case TCODE_XDATA:
09276
09277 if ( attributes )
09278 {
09279 ON_String layer_name;
09280 ON_String xid;
09281 int sizeof_xid = 0;
09282 int sizeof_data = 0;
09283 ReadInt(&sizeof_xid);
09284 ReadInt(&sizeof_data);
09285 xid.SetLength(sizeof_xid);
09286 ReadByte(sizeof_xid,xid.Array());
09287 if ( !on_stricmp("RhHidePrevLayer",xid) )
09288 {
09289
09290 char* buffer = (char*)alloca((sizeof_data+1)*sizeof(buffer[0]));
09291 buffer[0] = 0;
09292 buffer[sizeof_data] = 0;
09293 if ( ReadByte(sizeof_data,buffer) )
09294 {
09295 if ( -1 == xdata_layer_index )
09296 {
09297 xdata_layer_index = Read3dmV1LayerIndex(buffer);
09298 if ( xdata_layer_index >= 0 )
09299 {
09300 attributes->m_layer_index = xdata_layer_index;
09301 attributes->SetVisible(false);
09302 }
09303 }
09304 else
09305 {
09306 xdata_layer_index = -2;
09307 }
09308
09309
09310
09311
09312
09313 }
09314 }
09315 else if ( !on_stricmp("RhFreezePrevLayer",xid) )
09316 {
09317
09318 char* buffer = (char*)alloca((sizeof_data+1)*sizeof(buffer[0]));
09319 buffer[0] = 0;
09320 buffer[sizeof_data] = 0;
09321 if ( ReadByte(sizeof_data,buffer) )
09322 {
09323 if ( -1 == xdata_layer_index )
09324 {
09325 xdata_layer_index = Read3dmV1LayerIndex(buffer);
09326 if ( xdata_layer_index >= 0 )
09327 {
09328 attributes->m_layer_index = xdata_layer_index;
09329 attributes->SetMode(ON::locked_object);
09330 }
09331 }
09332 else
09333 {
09334 xdata_layer_index = -2;
09335 }
09336
09337
09338
09339
09340
09341 }
09342 }
09343 else if ( !on_stricmp("RhAnnotateArrow",xid) && 24 == sizeof_data )
09344 {
09345
09346
09347
09348
09349 ON_3dVector arrow_direction;
09350 if ( ReadVector( arrow_direction ) && 0 != xdata )
09351 {
09352 xdata->m_type = ON__3dmV1_XDATA::arrow_direction;
09353 xdata->m_vector = arrow_direction;
09354 }
09355 }
09356 else if ( !on_stricmp("RhAnnotateDot",xid) )
09357 {
09358
09359
09360
09361 char* buffer = (char*)alloca((sizeof_data+1)*sizeof(buffer[0]));
09362 buffer[0] = 0;
09363 buffer[sizeof_data] = 0;
09364 if ( ReadByte(sizeof_data,buffer) && 0 != xdata )
09365 {
09366 xdata->m_type = ON__3dmV1_XDATA::dot_text;
09367 xdata->m_string = buffer;
09368 }
09369 }
09370 else
09371 {
09372 m_error_message_mask |= 0x0002;
09373 }
09374
09375 }
09376 break;
09377
09378 case TCODE_DISP_CPLINES:
09379 if ( big_value > 0 && big_value <= 0x7FFFFFFF && attributes )
09380 attributes->m_wire_density = (int)big_value;
09381 break;
09382
09383 case TCODE_RENDER_MATERIAL_ID:
09384 {
09385 int flag;
09386 ON_String s;
09387 ReadInt(&flag);
09388 if ( flag == 1 ) {
09389 Read3dmV1String(s);
09390 if ( s.Length() > 0 )
09391 {
09392 if ( material )
09393 material->m_material_name = s;
09394 bHaveMat = true;
09395 }
09396 }
09397 }
09398 break;
09399
09400 default:
09401
09402 m_error_message_mask |= 0x02;
09403 break;
09404 }
09405
09406 bEndRead3dmChunk_rc = EndRead3dmChunk();
09407 if ( !bEndRead3dmChunk_rc )
09408 break;
09409 }
09410
09411 m_error_message_mask = saved_error_message_mask;
09412
09413 if ( bHaveMat ) {
09414 if ( attributes )
09415 attributes->m_material_index = m_3dm_v1_material_index;
09416 if ( material )
09417 material->SetMaterialIndex(m_3dm_v1_material_index);
09418 m_3dm_v1_material_index++;
09419 }
09420
09421 return rc;
09422 }
09423
09424
09425
09426 int ON_BinaryArchive::Read3dmV1Material( ON_Material** ppMaterial )
09427 {
09428 int rc = 0;
09429
09430
09431
09432
09433 ON_Material material;
09434 ON__UINT32 tcode = 0;
09435 ON__INT64 big_value = 0;
09436 ON_BOOL32 bHaveMat;
09437 bool bEndReadChunk_rc;
09438
09439
09440 while( 0 == rc )
09441 {
09442 bHaveMat = false;
09443 rc = 0;
09444 tcode = 0;
09445 big_value = 0;
09446 if ( !BeginRead3dmBigChunk(&tcode,&big_value) )
09447 {
09448
09449 break;
09450 }
09451
09452 switch(tcode)
09453 {
09454 case TCODE_RH_POINT:
09455
09456 {
09457 ON_3DM_BIG_CHUNK* point_chunk = m_chunk.Last();
09458 ON__UINT64 pos0 = 0;
09459 if ( 0 != point_chunk
09460 && TCODE_RH_POINT == point_chunk->m_typecode
09461 && 0 == point_chunk->m_big_value )
09462 {
09463
09464
09465
09466
09467 pos0 = CurrentPosition();
09468 }
09469 else
09470 point_chunk = 0;
09471
09472 ON_3dPoint pt;
09473 bool bOK = ReadPoint( pt );
09474
09475 if ( bOK )
09476 bOK = Read3dmV1AttributesOrMaterial( NULL, &material, bHaveMat, TCODE_ENDOFTABLE );
09477
09478 if ( !bOK )
09479 rc = -1;
09480
09481
09482 if ( bOK
09483 && 0 != point_chunk
09484 && point_chunk == m_chunk.Last()
09485 && TCODE_RH_POINT == point_chunk->m_typecode
09486 && 0 == point_chunk->m_big_value )
09487 {
09488
09489 ON__UINT64 pos1 = CurrentPosition();
09490 ON__UINT64 chunk_length = (pos1 > pos0) ? (pos1 - pos0) : 0;
09491 if ( chunk_length >= 32 && chunk_length < 0x0FFFFFFF )
09492 point_chunk->m_big_value = (ON__INT64)chunk_length;
09493 }
09494 }
09495 break;
09496
09497 case TCODE_MESH_OBJECT:
09498
09499 {
09500 ON__UINT32 tc = 0;
09501 ON__INT64 i64 = 0;
09502 if ( !PeekAt3dmBigChunkType( &tc, &i64 ) )
09503 break;
09504 if ( tc != TCODE_COMPRESSED_MESH_GEOMETRY )
09505 break;
09506
09507 if ( !BeginRead3dmBigChunk(&tc,&i64) )
09508 break;
09509 if ( !EndRead3dmChunk() )
09510 break;
09511
09512 if ( !Read3dmV1AttributesOrMaterial( NULL, &material, bHaveMat, TCODE_ENDOFTABLE ) )
09513 rc = -1;
09514
09515 }
09516 break;
09517
09518 case TCODE_LEGACY_SHL:
09519
09520 if ( !Read3dmV1AttributesOrMaterial( NULL, &material, bHaveMat, TCODE_LEGACY_SHLSTUFF ) )
09521 rc = -1;
09522
09523 break;
09524 case TCODE_LEGACY_FAC:
09525
09526 if ( !Read3dmV1AttributesOrMaterial( NULL, &material, bHaveMat, TCODE_LEGACY_FACSTUFF ) )
09527 rc = -1;
09528
09529 break;
09530 case TCODE_LEGACY_CRV:
09531
09532 if ( !Read3dmV1AttributesOrMaterial( NULL, &material, bHaveMat, TCODE_LEGACY_CRVSTUFF ) )
09533 rc = -1;
09534
09535 break;
09536
09537 case TCODE_RHINOIO_OBJECT_NURBS_CURVE:
09538 case TCODE_RHINOIO_OBJECT_NURBS_SURFACE:
09539 case TCODE_RHINOIO_OBJECT_BREP:
09540
09541 {
09542 ON__UINT32 tc = 0;
09543 ON__INT64 i64 = 0;
09544 if ( !PeekAt3dmBigChunkType( &tc, &i64 ) )
09545 break;
09546 if ( tc != TCODE_RHINOIO_OBJECT_DATA )
09547 break;
09548
09549 if ( !BeginRead3dmBigChunk(&tc,&i64) )
09550 break;
09551 if ( !EndRead3dmChunk() )
09552 break;
09553 if ( !Read3dmV1AttributesOrMaterial( NULL, &material, bHaveMat, TCODE_RHINOIO_OBJECT_END ) )
09554 rc = -1;
09555
09556 }
09557 break;
09558 }
09559
09560 const unsigned int saved_error_message_mask = m_error_message_mask;
09561 m_error_message_mask |= 0x02;
09562 bEndReadChunk_rc = EndRead3dmChunk();
09563 m_error_message_mask = saved_error_message_mask;
09564 if (!bEndReadChunk_rc )
09565 {
09566 rc = -1;
09567 break;
09568 }
09569 if ( bHaveMat && ppMaterial)
09570 {
09571
09572 *ppMaterial = new ON_Material(material);
09573 rc = 1;
09574 break;
09575 }
09576 }
09577
09578 return rc;
09579 }
09580
09581
09582 int ON_BinaryArchive::Read3dmMaterial( ON_Material** ppMaterial )
09583 {
09584 int rc = 0;
09585 if ( !ppMaterial )
09586 return 0;
09587 *ppMaterial = 0;
09588 ON_Material* material = NULL;
09589 ON__UINT32 tcode = 0;
09590 ON__INT64 big_value = 0;
09591 if ( m_3dm_version == 1 )
09592 {
09593 rc = ON_BinaryArchive::Read3dmV1Material( ppMaterial );
09594 }
09595 else
09596 {
09597
09598 rc = -1;
09599 if ( BeginRead3dmBigChunk( &tcode, &big_value ) )
09600 {
09601 if ( tcode == TCODE_MATERIAL_RECORD )
09602 {
09603 ON_Object* p = 0;
09604 if ( ReadObject( &p ) )
09605 {
09606 material = ON_Material::Cast(p);
09607 if ( !material )
09608 delete p;
09609 else
09610 {
09611 if ( ppMaterial )
09612 *ppMaterial = material;
09613 rc = 1;
09614 }
09615 }
09616 if (!material)
09617 {
09618 ON_ERROR("ON_BinaryArchive::Read3dmMaterial() - corrupt material table");
09619 }
09620 }
09621 else if ( tcode == TCODE_ENDOFTABLE )
09622 {
09623
09624 rc = 0;
09625 }
09626 else
09627 {
09628 ON_ERROR("ON_BinaryArchive::Read3dmMaterial() - corrupt material table");
09629 }
09630 if ( !EndRead3dmChunk() )
09631 rc = -1;
09632 }
09633 }
09634 return rc;
09635 }
09636
09637 bool ON_BinaryArchive::EndRead3dmMaterialTable()
09638 {
09639 return EndRead3dmTable( TCODE_MATERIAL_TABLE );
09640 }
09641
09642
09643 bool ON_BinaryArchive::BeginWrite3dmLightTable()
09644 {
09645 return BeginWrite3dmTable( TCODE_LIGHT_TABLE );
09646 }
09647
09648 bool ON_BinaryArchive::Write3dmLight( const ON_Light& light, const ON_3dmObjectAttributes* attributes )
09649 {
09650 bool rc = false;
09651 if ( m_active_table != light_table ) {
09652 ON_ERROR("ON_BinaryArchive::Write3dmLight() - m_active_table != light_table");
09653 }
09654 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
09655 if ( c && c->m_typecode == TCODE_LIGHT_TABLE ) {
09656 rc = BeginWrite3dmChunk( TCODE_LIGHT_RECORD, 0 );
09657 if (rc) {
09658
09659 rc = WriteObject( light );
09660
09661
09662 if ( rc && attributes )
09663 {
09664 rc = BeginWrite3dmChunk( TCODE_LIGHT_RECORD_ATTRIBUTES, 0 );
09665 if (rc)
09666 {
09667 rc = attributes->Write( *this )?true:false;
09668 if (!EndWrite3dmChunk())
09669 rc = false;
09670 if( rc
09671 && (m_bSaveUserData || HasCriticalUserData(*this,attributes))
09672 && Archive3dmVersion() >= 4
09673 && 0 != attributes->FirstUserData()
09674 )
09675 {
09676
09677
09678 rc = BeginWrite3dmChunk( TCODE_LIGHT_RECORD_ATTRIBUTES_USERDATA, 0 );
09679 if (rc)
09680 {
09681
09682 rc = WriteObjectUserData(*attributes);
09683 if (rc)
09684 {
09685
09686
09687
09688
09689
09690
09691
09692
09693 rc = BeginWrite3dmChunk(TCODE_OPENNURBS_CLASS_END,0);
09694 if (rc)
09695 {
09696 if (!EndWrite3dmChunk())
09697 rc = false;
09698 }
09699 }
09700 if (!EndWrite3dmChunk())
09701 rc = false;
09702 }
09703 }
09704 }
09705 }
09706
09707
09708 if ( BeginWrite3dmChunk( TCODE_LIGHT_RECORD_END, 0 ) ) {
09709 if (!EndWrite3dmChunk())
09710 rc = false;
09711 }
09712 else {
09713 rc = false;
09714 }
09715
09716 if ( !EndWrite3dmChunk() )
09717 rc = false;
09718 }
09719 }
09720 else {
09721 ON_ERROR("ON_BinaryArchive::Write3dmMaterial() - active chunk typecode != TCODE_LIGHT_TABLE");
09722 }
09723 return rc;
09724 }
09725
09726 bool ON_BinaryArchive::EndWrite3dmLightTable()
09727 {
09728 return EndWrite3dmTable( TCODE_LIGHT_TABLE );
09729 }
09730
09731 bool ON_BinaryArchive::BeginRead3dmLightTable()
09732 {
09733 bool rc = BeginRead3dmTable( TCODE_LIGHT_TABLE );
09734
09735 if ( !rc )
09736 {
09737
09738
09739
09740
09741
09742 rc = FindMisplacedTable(
09743 0,
09744 TCODE_LIGHT_TABLE, TCODE_LIGHT_RECORD,
09745 ON_Light::m_ON_Light_class_id.Uuid(),
09746 30
09747 );
09748 if ( rc )
09749 {
09750 rc = BeginRead3dmTable( TCODE_LIGHT_TABLE );
09751 }
09752 }
09753
09754 return rc;
09755 }
09756
09757 int ON_BinaryArchive::Read3dmV1Light(
09758
09759
09760 ON_Light** ppLight,
09761 ON_3dmObjectAttributes* pAttributes
09762
09763 )
09764 {
09765 ON_BOOL32 bHaveMat;
09766 ON_Material material;
09767
09768 if ( m_chunk.Count() != 0 ) {
09769 ON_ERROR("ON_BinaryArchive::Read3dmV1Light() m_chunk.Count() != 0");
09770 return false;
09771 }
09772 ON_BOOL32 rc = false;
09773 ON__UINT32 tcode = 0;
09774 ON__INT64 big_value = 0;
09775
09776
09777 for(;;)
09778 {
09779 if ( !BeginRead3dmBigChunk(&tcode,&big_value) )
09780 break;
09781 if ( tcode == TCODE_RH_SPOTLIGHT ) {
09782 rc = 1;
09783 break;
09784 }
09785 if ( !EndRead3dmChunk() )
09786 break;
09787 }
09788 if (rc) {
09789 ON_3dPoint origin;
09790 ON_3dVector xaxis, yaxis;
09791 double radius;
09792 double height;
09793 double hotspot;
09794
09795 for(;;)
09796 {
09797 rc = ReadPoint( origin );
09798 if (!rc) break;
09799 rc = ReadVector( xaxis );
09800 if (!rc) break;
09801 rc = ReadVector( yaxis );
09802 if (!rc) break;
09803 rc = ReadDouble( &radius );
09804 if (!rc) break;
09805 rc = ReadDouble( &height );
09806 if (!rc) break;
09807 rc = ReadDouble( &hotspot );
09808 if (!rc) break;
09809 if (ppLight )
09810 {
09811 ON_3dVector Z = ON_CrossProduct( xaxis, yaxis );
09812 ON_3dPoint location = height*Z + origin;
09813 ON_3dVector direction = -Z;
09814
09815 if( height > 0.0)
09816 direction *= height;
09817 ON_Light* light = new ON_Light;
09818 light->SetStyle( ON::world_spot_light );
09819 light->SetLocation(location);
09820 light->SetDirection(direction);
09821 light->SetSpotExponent( 64.0);
09822 if( radius > 0.0 && height > 0.0 )
09823 light->SetSpotAngleRadians( atan( radius/height));
09824 *ppLight = light;
09825 }
09826 break;
09827 }
09828
09829 if (rc && ppLight && *ppLight) {
09830 bHaveMat = false;
09831 Read3dmV1AttributesOrMaterial(pAttributes,&material,bHaveMat,TCODE_ENDOFTABLE);
09832 if ( pAttributes )
09833 pAttributes->m_material_index = -1;
09834 if (bHaveMat)
09835 (*ppLight)->SetDiffuse(material.Diffuse());
09836 }
09837
09838 if ( !EndRead3dmChunk() )
09839 rc = false;
09840 }
09841
09842 return rc;
09843 }
09844
09845 int ON_BinaryArchive::Read3dmLight( ON_Light** ppLight, ON_3dmObjectAttributes* attributes )
09846 {
09847 if ( attributes )
09848 attributes->Default();
09849 int rc = -1;
09850 if ( !ppLight )
09851 return 0;
09852 *ppLight = 0;
09853 if ( m_active_table != light_table ) {
09854 ON_ERROR("ON_BinaryArchive::Read3dmLight() - m_active_table != light_table");
09855 }
09856 else if ( m_3dm_version == 1 ) {
09857 rc = Read3dmV1Light( ppLight, attributes );
09858 }
09859 else {
09860 ON_Light* light = NULL;
09861 ON__UINT32 tcode = 0;
09862 ON__INT64 big_value = 0;
09863 if ( BeginRead3dmBigChunk( &tcode, &big_value ) ) {
09864 if ( tcode == TCODE_LIGHT_RECORD ) {
09865 ON_Object* p = 0;
09866 if ( ReadObject( &p ) ) {
09867 light = ON_Light::Cast(p);
09868 if ( !light )
09869 delete p;
09870 }
09871 if (!light) {
09872 ON_ERROR("ON_BinaryArchive::Read3dmLight() - corrupt light table");
09873 }
09874 else {
09875 *ppLight = light;
09876 rc = 1;
09877 }
09878 }
09879 else if ( tcode != TCODE_ENDOFTABLE )
09880 {
09881 ON_ERROR("ON_BinaryArchive::Read3dmLight() - corrupt light table");
09882 }
09883 else
09884 rc = 0;
09885
09886 while(rc==1)
09887 {
09888 tcode = 0;
09889 big_value = 0;
09890 if (!BeginRead3dmBigChunk( &tcode, &big_value ))
09891 {
09892 rc = -1;
09893 break;
09894 }
09895 if ( tcode == TCODE_LIGHT_RECORD_ATTRIBUTES && attributes )
09896 {
09897 if ( !attributes->Read( *this ) )
09898 rc = -1;
09899 }
09900 else if ( tcode == TCODE_LIGHT_RECORD_ATTRIBUTES_USERDATA )
09901 {
09902 if ( 0 != attributes )
09903 {
09904
09905
09906 if ( !ReadObjectUserData(*attributes))
09907 rc = -1;
09908 }
09909 }
09910 if ( !EndRead3dmChunk() )
09911 {
09912 rc = -1;
09913 break;
09914 }
09915 if ( tcode == TCODE_LIGHT_RECORD_END )
09916 break;
09917 }
09918
09919 EndRead3dmChunk();
09920 }
09921 }
09922 return rc;
09923 }
09924
09925 bool ON_BinaryArchive::EndRead3dmLightTable()
09926 {
09927 return EndRead3dmTable( TCODE_LIGHT_TABLE );
09928 }
09929
09930 bool ON_BinaryArchive::BeginWrite3dmObjectTable()
09931 {
09932 return BeginWrite3dmTable( TCODE_OBJECT_TABLE );
09933 }
09934
09935 bool ON_BinaryArchive::Write3dmObject(
09936 const ON_Object& object,
09937 const ON_3dmObjectAttributes* attributes
09938 )
09939 {
09940 bool rc = false;
09941 if ( m_active_table != object_table ) {
09942 ON_ERROR("ON_BinaryArchive::Write3dmObject() - m_active_table != object_table");
09943 }
09944
09945 if ( Archive3dmVersion() <= 2 && object.ObjectType() == ON::pointset_object )
09946 {
09947
09948
09949
09950 const ON_PointCloud* pc = ON_PointCloud::Cast(&object);
09951 if ( 0 != pc )
09952 {
09953 int i, count = pc->PointCount();
09954 rc = true;
09955 for ( i = 0; i < count && rc ; i++ )
09956 {
09957 ON_Point pt( pc->m_P[i] );
09958 rc = Write3dmObject( pt, attributes );
09959 }
09960 return rc;
09961 }
09962 }
09963
09964 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
09965 if ( c && c->m_typecode == TCODE_OBJECT_TABLE )
09966 {
09967 Flush();
09968 rc = BeginWrite3dmChunk( TCODE_OBJECT_RECORD, 0 );
09969 if (rc) {
09970
09971
09972 rc = BeginWrite3dmChunk( TCODE_OBJECT_RECORD_TYPE, object.ObjectType() );
09973 if (rc) {
09974 if (!EndWrite3dmChunk())
09975 rc = false;
09976 }
09977
09978
09979 rc = WriteObject( object );
09980
09981
09982 if ( rc && attributes ) {
09983 rc = BeginWrite3dmChunk( TCODE_OBJECT_RECORD_ATTRIBUTES, 0 );
09984 if (rc) {
09985 rc = attributes->Write( *this )?true:false;
09986 if (!EndWrite3dmChunk())
09987 rc = false;
09988
09989 if( rc
09990 && (m_bSaveUserData || HasCriticalUserData(*this,attributes))
09991 && Archive3dmVersion() >= 4
09992 && 0 != attributes->FirstUserData()
09993 )
09994 {
09995
09996
09997 rc = BeginWrite3dmChunk( TCODE_OBJECT_RECORD_ATTRIBUTES_USERDATA, 0 );
09998 if (rc)
09999 {
10000
10001 rc = WriteObjectUserData(*attributes);
10002 if (rc)
10003 {
10004
10005
10006
10007
10008
10009
10010
10011
10012 rc = BeginWrite3dmChunk(TCODE_OPENNURBS_CLASS_END,0);
10013 if (rc)
10014 {
10015 if (!EndWrite3dmChunk())
10016 rc = false;
10017 }
10018 }
10019 if (!EndWrite3dmChunk())
10020 rc = false;
10021 }
10022 }
10023 }
10024 }
10025
10026
10027 if ( BeginWrite3dmChunk( TCODE_OBJECT_RECORD_END, 0 ) ) {
10028 if (!EndWrite3dmChunk())
10029 rc = false;
10030 }
10031 else {
10032 rc = false;
10033 }
10034
10035 if (!EndWrite3dmChunk())
10036 {
10037 rc = false;
10038 }
10039 if (!Flush())
10040 rc = false;
10041 }
10042 else {
10043 ON_ERROR("ON_BinaryArchive::Write3dmObject() - active chunk typecode != TCODE_OBJECT_TABLE");
10044 }
10045 }
10046 return rc;
10047 }
10048
10049 bool ON_BinaryArchive::EndWrite3dmObjectTable()
10050 {
10051 return EndWrite3dmTable( TCODE_OBJECT_TABLE );
10052 }
10053
10054 bool ON_BinaryArchive::BeginRead3dmObjectTable()
10055 {
10056 m_3dm_v1_material_index = 0;
10057 bool rc = BeginRead3dmTable( TCODE_OBJECT_TABLE );
10058 if ( !rc )
10059 {
10060
10061
10062
10063 rc = FindMisplacedTable(
10064 0,
10065 TCODE_OBJECT_TABLE, TCODE_OBJECT_RECORD,
10066 ON_nil_uuid,
10067 26
10068 );
10069 if ( rc )
10070 {
10071 rc = BeginRead3dmTable( TCODE_OBJECT_TABLE );
10072 }
10073
10074 }
10075 return rc;
10076 }
10077
10078 bool ON_BinaryArchive::ReadV1_TCODE_RH_POINT(
10079 ON_Object** ppObject,
10080 ON_3dmObjectAttributes* pAttributes
10081 )
10082 {
10083 ON__UINT64 pos0 = 0;
10084 ON_3DM_BIG_CHUNK* point_chunk = m_chunk.Last();
10085
10086 if ( 0 != point_chunk
10087 && TCODE_RH_POINT == point_chunk->m_typecode
10088 && 0 == point_chunk->m_big_value )
10089 {
10090
10091
10092
10093
10094 pos0 = CurrentPosition();
10095 }
10096 else
10097 point_chunk = 0;
10098
10099
10100 bool rc = false;
10101 ON_BOOL32 bHaveMat = false;
10102 ON_3dPoint pt;
10103 ON__3dmV1_XDATA xdata;
10104 rc = ReadPoint(pt);
10105 if (rc)
10106 {
10107 rc = Read3dmV1AttributesOrMaterial(pAttributes,NULL,bHaveMat,TCODE_ENDOFTABLE,&xdata);
10108
10109 switch ( xdata.m_type )
10110 {
10111 case ON__3dmV1_XDATA::arrow_direction:
10112 if ( xdata.m_vector.Length() > ON_ZERO_TOLERANCE )
10113 {
10114 ON_AnnotationArrow* arrow = new ON_AnnotationArrow();
10115 arrow->m_tail = pt;
10116 arrow->m_head = pt + xdata.m_vector;
10117 *ppObject = arrow;
10118 }
10119 else
10120 {
10121 *ppObject = new ON_Point(pt);
10122 }
10123 break;
10124
10125 case ON__3dmV1_XDATA::dot_text:
10126 {
10127 ON_AnnotationTextDot* dot = new ON_AnnotationTextDot();
10128 dot->point = pt;
10129 dot->m_text = xdata.m_string;
10130 if ( dot->m_text.IsEmpty() )
10131 dot->m_text = " ";
10132 *ppObject = dot;
10133 }
10134 break;
10135
10136 default:
10137 *ppObject = new ON_Point(pt);
10138 break;
10139 }
10140 }
10141
10142
10143 if ( rc && pos0 > 0 && 0 != point_chunk && point_chunk == m_chunk.Last() )
10144 {
10145 if ( TCODE_RH_POINT == point_chunk->m_typecode && 0 == point_chunk->m_big_value )
10146 {
10147
10148
10149
10150 ON__UINT64 pos1 = CurrentPosition();
10151 ON__UINT64 chunk_length = (pos1 > pos0) ? (pos1 - pos0) : 0;
10152 if ( chunk_length >= 32 && chunk_length < 0x0FFFFFFF )
10153 point_chunk->m_big_value = (ON__INT64)chunk_length;
10154 }
10155 }
10156
10157 return rc;
10158 }
10159
10160 static
10161 void TweakAnnotationPlane( ON_Plane& plane )
10162 {
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
10178
10179
10180
10181
10182
10183
10184
10185
10186
10187
10188
10189
10190
10191
10192
10193
10194 const double too_big = 1.0e10;
10195
10196 if( fabs( plane.origin.x ) > too_big )
10197 plane.origin.x = 0.0;
10198 if( fabs( plane.origin.y ) > too_big )
10199 plane.origin.y = 0.0;
10200 if( fabs( plane.origin.z ) > too_big )
10201 plane.origin.z = 0.0;
10202
10203 if( fabs( plane.xaxis.x ) > too_big )
10204 plane.xaxis.x = 1.0;
10205 if( fabs( plane.xaxis.y ) > too_big )
10206 plane.xaxis.y = 0.0;
10207 if( fabs( plane.xaxis.z ) > too_big )
10208 plane.xaxis.z = 0.0;
10209
10210 if( fabs( plane.yaxis.x ) > too_big )
10211 plane.yaxis.x = 0.0;
10212 if( fabs( plane.yaxis.y ) > too_big )
10213 plane.yaxis.y = 1.0;
10214 if( fabs( plane.yaxis.z ) > too_big )
10215 plane.yaxis.z = 0.0;
10216
10217 plane.xaxis.Unitize();
10218 plane.yaxis.Unitize();
10219 plane.zaxis = ON_CrossProduct(plane.xaxis,plane.yaxis);
10220 plane.zaxis.Unitize();
10221 plane.UpdateEquation();
10222 }
10223
10224
10225 #define RHINO_ANNOTATION_SETTINGS_VERSION_1 1
10226 #define RHINO_LINEAR_DIMENSION_VERSION_1 1
10227 #define RHINO_RADIAL_DIMENSION_VERSION_1 1
10228 #define RHINO_ANGULAR_DIMENSION_VERSION_1 1
10229 #define RHINO_TEXT_BLOCK_VERSION_1 1
10230 #define RHINO_TEXT_BLOCK_VERSION_2 2
10231 #define RHINO_ANNOTATION_LEADER_VERSION_1 1
10232
10233 #define BUFLEN 128
10234
10235 static bool ReadV1_TCODE_ANNOTATION_Helper( ON_BinaryArchive& archive, char* buffer, ON_wString& tc )
10236 {
10237 char* cp = 0;
10238 int j = 0;
10239 if( !archive.ReadInt( &j))
10240 return false;
10241 size_t sz = (j+1)*sizeof(cp[0]);
10242 if( j > BUFLEN - 1 || !buffer )
10243 {
10244 cp = (char*)onmalloc( sz );
10245 if( !cp)
10246 return false;
10247 }
10248 else
10249 {
10250 cp = buffer;
10251 }
10252
10253 memset( cp, 0, sz );
10254 if( !archive.ReadChar( j, cp))
10255 {
10256 if ( cp != buffer )
10257 onfree(cp);
10258 return false;
10259 }
10260
10261 cp[j] = 0;
10262 tc = cp;
10263 if ( cp != buffer )
10264 onfree( cp );
10265 return true;
10266 }
10267
10268 bool ON_BinaryArchive::ReadV1_TCODE_ANNOTATION(
10269 unsigned int tcode,
10270 ON_Object** ppObject,
10271 ON_3dmObjectAttributes* pAttributes
10272 )
10273 {
10274 enum RhAnnotationType
10275 {
10276 Nothing = 0,
10277 TextBlock = 1,
10278 DimHorizontal = 2,
10279 DimVertical = 3,
10280 DimAligned = 4,
10281 DimRotated = 5,
10282 DimAngular = 6,
10283 DimDiameter = 7 ,
10284 DimRadius = 8,
10285 Leader = 9,
10286 DimLinear = 10,
10287 };
10288
10289 bool rc = false;
10290 *ppObject = NULL;
10291 ON_wString tc;
10292 char buffer[BUFLEN];
10293 int i, j, k, byobject, version;
10294
10295 double d, d4[4];
10296
10297
10298 switch( tcode)
10299 {
10300 case TCODE_TEXT_BLOCK:
10301 {
10302
10303 rc = ReadInt( &version);
10304 if ( rc &&
10305 (version == RHINO_TEXT_BLOCK_VERSION_1 ||
10306 version == RHINO_TEXT_BLOCK_VERSION_2)
10307 )
10308 {
10309
10310
10311 rc = ReadInt( &i);
10312 if( !rc)
10313 return rc;
10314
10315 ON_TextEntity* text = new ON_TextEntity;
10316 text->SetType( ON::dtTextBlock);
10317
10318 ON_Plane plane;
10319
10320
10321 if( !ReadDouble( 3, &plane.origin.x))
10322 return false;
10323 if( !ReadDouble( 3, &plane.xaxis.x))
10324 return false;
10325 if( !ReadDouble( 3, &plane.yaxis.x))
10326 return false;
10327
10328
10329 TweakAnnotationPlane( plane );
10330
10331 text->SetPlane( plane);
10332
10333
10334 if ( !ReadV1_TCODE_ANNOTATION_Helper( *this, buffer, tc ) )
10335 return false;
10336 text->SetUserText( tc.Array());
10337
10338
10339 if( !ReadInt( 1, &j))
10340 return false;
10341
10342
10343 if( !ReadInt( 1, &byobject))
10344 return false;
10345
10346
10347
10348
10349 if ( !ReadV1_TCODE_ANNOTATION_Helper( *this, buffer, tc ) )
10350 return false;
10351 text->SetFaceName(tc);
10352
10353
10354 if( !ReadInt( 1, &j))
10355 return false;
10356 text->SetFontWeight( j);
10357
10358 if( !ReadDouble( 1, &d))
10359 return false;
10360 text->SetHeight( d);
10361
10362
10363 if( version == RHINO_TEXT_BLOCK_VERSION_1 )
10364 {
10365 if( !ReadDouble( 1, &d))
10366 return false;
10367 if( !ReadDouble( 1, &d))
10368 return false;
10369 }
10370
10371 if( text->UserText().Length() < 1 )
10372 {
10373 *ppObject = 0;
10374 return true;
10375 }
10376 *ppObject = text;
10377 rc = true;
10378 }
10379 }
10380 break;
10381
10382 case TCODE_ANNOTATION_LEADER:
10383 {
10384
10385 if( !ReadInt( &i))
10386 return false;
10387
10388 if( i == RHINO_ANNOTATION_LEADER_VERSION_1)
10389 {
10390
10391 if( !ReadInt( &i))
10392 return false;
10393
10394 ON_Leader* ldr = new ON_Leader;
10395 ldr->SetType( ON::dtLeader);
10396
10397 ON_Plane plane;
10398
10399
10400 if( !ReadDouble( 3, &plane.origin.x))
10401 return false;
10402 if( !ReadDouble( 3, &plane.xaxis.x))
10403 return false;
10404 if( !ReadDouble( 3, &plane.yaxis.x))
10405 return false;
10406
10407
10408 TweakAnnotationPlane( plane );
10409
10410 ldr->SetPlane( plane);
10411
10412
10413 if( !ReadInt( 1, &j))
10414 return false;
10415
10416
10417 if( !ReadInt( 1, &byobject))
10418 return false;
10419
10420
10421 if( !ReadInt( &k))
10422 return false;
10423
10424 if( k < 2)
10425 return true;
10426
10427 ON_SimpleArray<ON_2dPoint> points;
10428 for( j = 0; j < k; j++ )
10429 {
10430 double pt[3];
10431 if( !ReadDouble( 3, pt))
10432 return false;
10433 points.Append( ON_2dPoint( pt));
10434 }
10435 ldr->SetPoints( points);
10436
10437 *ppObject = ldr;
10438 rc = true;
10439 break;
10440 }
10441 }
10442 break;
10443 case TCODE_LINEAR_DIMENSION:
10444 {
10445
10446 if( !ReadInt( &i))
10447 return false;
10448
10449 if( i == RHINO_LINEAR_DIMENSION_VERSION_1)
10450 {
10451 if( !ReadInt( &i))
10452 return false;
10453
10454 ON_LinearDimension* dim = new ON_LinearDimension;
10455 switch( i )
10456 {
10457 case DimHorizontal:
10458 case DimVertical:
10459 case DimRotated:
10460 case DimLinear:
10461 dim->SetType( ON::dtDimLinear);
10462 break;
10463 default:
10464 dim->SetType( ON::dtDimAligned);
10465 break;
10466 }
10467
10468 ON_Plane plane;
10469
10470
10471 if( !ReadDouble( 3, &plane.origin.x))
10472 return false;
10473 if( !ReadDouble( 3, &plane.xaxis.x))
10474 return false;
10475 if( !ReadDouble( 3, &plane.yaxis.x))
10476 return false;
10477
10478
10479 TweakAnnotationPlane( plane );
10480
10481 dim->SetPlane( plane);
10482
10483
10484 ON_SimpleArray<ON_2dPoint> points;
10485 for( j = 0; j < 11; j++ )
10486 {
10487 double pt[3];
10488 if( !ReadDouble( 3, pt))
10489 return false;
10490 points.Append( ON_2dPoint( pt));
10491 }
10492 dim->SetPoints( points);
10493
10494
10495 if ( !ReadV1_TCODE_ANNOTATION_Helper( *this, buffer, tc ) )
10496 return false;
10497 dim->SetUserText( tc.Array());
10498
10499
10500
10501
10502
10503 if ( !ReadV1_TCODE_ANNOTATION_Helper( *this, buffer, tc ) )
10504 return false;
10505 dim->SetDefaultText( tc.Array());
10506
10507
10508 if( !ReadInt( &j))
10509 return false;
10510 dim->SetUserPositionedText( j);
10511
10512
10513 if( !ReadInt( 1, &j))
10514 return false;
10515
10516
10517 if( !ReadInt( 1, &byobject))
10518 return false;
10519
10520 *ppObject = dim;
10521 rc = true;
10522 break;
10523 }
10524 }
10525 break;
10526
10527 case TCODE_ANGULAR_DIMENSION:
10528 {
10529
10530 if( !ReadInt( &i))
10531 return false;
10532
10533 if( i == RHINO_ANGULAR_DIMENSION_VERSION_1)
10534 {
10535 if( !ReadInt( &i))
10536 return false;
10537
10538 ON_AngularDimension* dim = new ON_AngularDimension;
10539 dim->SetType( ON::dtDimAngular);
10540
10541 ON_Plane plane;
10542
10543
10544 if( !ReadDouble( 3, &plane.origin.x))
10545 return false;
10546 if( !ReadDouble( 3, &plane.xaxis.x))
10547 return false;
10548 if( !ReadDouble( 3, &plane.yaxis.x))
10549 return false;
10550
10551
10552 TweakAnnotationPlane( plane );
10553
10554 dim->SetPlane( plane);
10555
10556 if( !ReadDouble( &d))
10557 return false;
10558 dim->SetAngle( d);
10559
10560 if( !ReadDouble( &d))
10561 return false;
10562 dim->SetRadius( d);
10563
10564
10565 if( !ReadDouble( 4, d4))
10566 return false;
10567
10568
10569 ON_SimpleArray<ON_2dPoint> points;
10570 for( j = 0; j < 5; j++ )
10571 {
10572 double pt[3];
10573 if( !ReadDouble( 3, pt))
10574 return false;
10575 points.Append( ON_2dPoint( pt));
10576 }
10577 dim->SetPoints( points);
10578
10579
10580 if ( !ReadV1_TCODE_ANNOTATION_Helper( *this, buffer, tc ) )
10581 return false;
10582 dim->SetUserText( tc.Array());
10583
10584
10585
10586
10587
10588 if ( !ReadV1_TCODE_ANNOTATION_Helper( *this, buffer, tc ) )
10589 return false;
10590 dim->SetDefaultText( tc.Array());
10591
10592
10593 if( !ReadInt( &j))
10594 return false;
10595 dim->SetUserPositionedText( j);
10596
10597
10598
10599 if( !ReadInt( 1, &j))
10600 return false;
10601
10602
10603 if( !ReadInt( 1, &byobject))
10604 return false;
10605
10606
10607 *ppObject = dim;
10608 rc = true;
10609 break;
10610 }
10611 }
10612 break;
10613
10614 case TCODE_RADIAL_DIMENSION:
10615 {
10616
10617 if( !ReadInt( &i))
10618 return false;
10619
10620 if( i == RHINO_RADIAL_DIMENSION_VERSION_1)
10621 {
10622 if( !ReadInt( &i))
10623 return false;
10624
10625 ON_RadialDimension* dim = new ON_RadialDimension;
10626
10627 switch( i)
10628 {
10629 case DimDiameter:
10630 dim->SetType( ON::dtDimDiameter);
10631 break;
10632 case DimRadius:
10633 dim->SetType( ON::dtDimRadius);
10634 break;
10635 }
10636
10637 ON_Plane plane;
10638
10639
10640 if( !ReadDouble( 3, &plane.origin.x))
10641 return false;
10642 if( !ReadDouble( 3, &plane.xaxis.x))
10643 return false;
10644 if( !ReadDouble( 3, &plane.yaxis.x))
10645 return false;
10646
10647
10648 TweakAnnotationPlane( plane );
10649
10650 dim->SetPlane( plane);
10651
10652
10653 ON_SimpleArray<ON_2dPoint> points;
10654 for( j = 0; j < 5; j++ )
10655 {
10656 double pt[3];
10657 if( !ReadDouble( 3, pt))
10658 return false;
10659 points.Append( ON_2dPoint( pt));
10660 }
10661 dim->SetPoints( points);
10662
10663
10664 if ( !ReadV1_TCODE_ANNOTATION_Helper( *this, buffer, tc ) )
10665 return false;
10666 dim->SetUserText( tc.Array());
10667
10668
10669
10670
10671
10672 if ( !ReadV1_TCODE_ANNOTATION_Helper( *this, buffer, tc ) )
10673 return false;
10674 dim->SetDefaultText( tc.Array());
10675
10676
10677 if( !ReadInt( &j))
10678 return false;
10679 dim->SetUserPositionedText( j);
10680
10681
10682 if( !ReadInt( 1, &j))
10683 return false;
10684
10685
10686 if( !ReadInt( 1, &byobject))
10687 return false;
10688
10689
10690 *ppObject = dim;
10691 rc = true;
10692 break;
10693 }
10694
10695 }
10696 break;
10697
10698 default:
10699 return true;
10700 }
10701
10702 if( rc)
10703 {
10704 ON_BOOL32 bHaveMat = false;
10705 Read3dmV1AttributesOrMaterial(pAttributes,NULL,bHaveMat,TCODE_ENDOFTABLE);
10706 }
10707
10708 return rc;
10709
10710
10711
10712
10713
10714
10715
10716
10717
10718
10719 }
10720
10721
10722 bool ON_BinaryArchive::ReadV1_TCODE_MESH_OBJECT(
10723 ON_Object** ppObject,
10724 ON_3dmObjectAttributes* pAttributes
10725 )
10726 {
10727 ON_Mesh* mesh = 0;
10728 bool rc = false;
10729
10730 ON__UINT32 tcode = 0;
10731 ON__INT64 big_value = 0;
10732 int i;
10733 if ( !BeginRead3dmBigChunk(&tcode,&big_value) )
10734 return false;
10735
10736 if ( tcode == TCODE_COMPRESSED_MESH_GEOMETRY ) for(;;)
10737 {
10738
10739 int point_count = 0;
10740 int face_count = 0;
10741 ON_BOOL32 bHasVertexNormals = false;
10742 ON_BOOL32 bHasTexCoords = false;
10743 ON_BoundingBox bbox;
10744
10745 if (!ReadInt(&point_count) )
10746 break;
10747 if ( point_count <= 0 )
10748 break;
10749 if (!ReadInt(&face_count) )
10750 break;
10751 if ( face_count <= 0 )
10752 break;
10753 if (!ReadInt(&bHasVertexNormals) )
10754 break;
10755 if (!ReadInt(&bHasTexCoords) )
10756 break;
10757 if ( !ReadPoint(bbox.m_min) )
10758 break;
10759 if ( !ReadPoint(bbox.m_max) )
10760 break;
10761
10762 mesh = new ON_Mesh(face_count,
10763 point_count,
10764 bHasVertexNormals?true:false,
10765 bHasTexCoords?true:false
10766 );
10767
10768
10769 {
10770 ON_3dVector d = bbox.Diagonal();
10771 double dx = d.x / 65535.0;
10772 double dy = d.y / 65535.0;
10773 double dz = d.z / 65535.0;
10774 unsigned short xyz[3];
10775 ON_3fPoint pt;
10776 for ( i = 0; i < point_count; i++ ) {
10777 if ( !ReadShort(3,xyz) )
10778 break;
10779 pt.x = (float)(dx*xyz[0] + bbox.m_min.x);
10780 pt.y = (float)(dy*xyz[1] + bbox.m_min.y);
10781 pt.z = (float)(dz*xyz[2] + bbox.m_min.z);
10782 mesh->m_V.Append(pt);
10783 }
10784 }
10785 if ( mesh->m_V.Count() != point_count )
10786 break;
10787
10788
10789 if ( point_count < 65535 ) {
10790 unsigned short abcd[4];
10791 for ( i = 0; i < face_count; i++ ) {
10792 if ( !ReadShort(4,abcd) )
10793 break;
10794 ON_MeshFace& f = mesh->m_F.AppendNew();
10795 f.vi[0] = abcd[0];
10796 f.vi[1] = abcd[1];
10797 f.vi[2] = abcd[2];
10798 f.vi[3] = abcd[3];
10799 }
10800 }
10801 else {
10802 int abcd[4];
10803 for ( i = 0; i < face_count; i++ ) {
10804 if ( !ReadInt(4,abcd) )
10805 break;
10806 ON_MeshFace& f = mesh->m_F.AppendNew();
10807 f.vi[0] = abcd[0];
10808 f.vi[1] = abcd[1];
10809 f.vi[2] = abcd[2];
10810 f.vi[3] = abcd[3];
10811 }
10812 }
10813 if ( mesh->m_F.Count() != face_count )
10814 break;
10815
10816 if ( bHasVertexNormals ) {
10817 char xyz[3];
10818 ON_3fVector normal;
10819 for ( i = 0; i < point_count; i++ ) {
10820 if ( !ReadChar(3,xyz) )
10821 break;
10822 normal.x = (float)(((signed char)xyz[0])/127.0);
10823 normal.y = (float)(((signed char)xyz[1])/127.0);
10824 normal.z = (float)(((signed char)xyz[2])/127.0);
10825 mesh->m_N.Append(normal);
10826 }
10827 if ( mesh->m_N.Count() != mesh->m_V.Count() )
10828 break;
10829 }
10830
10831 if ( bHasTexCoords ) {
10832 unsigned short uv[2];
10833 ON_2fPoint t;
10834 for ( i = 0; i < point_count; i++ ) {
10835 if ( !ReadShort(2,uv) )
10836 break;
10837 t.x = (float)(uv[0]/65535.0);
10838 t.y = (float)(uv[1]/65535.0);
10839 mesh->m_T.Append(t);
10840 }
10841 if ( mesh->m_T.Count() != mesh->m_V.Count() )
10842 break;
10843 }
10844
10845 rc = true;
10846
10847 break;
10848 }
10849
10850 if ( !EndRead3dmChunk() )
10851 rc = false;
10852
10853 if ( rc && mesh ) {
10854 *ppObject = mesh;
10855 }
10856 else {
10857 if ( mesh )
10858 delete mesh;
10859 rc = false;
10860 }
10861
10862 if ( rc && mesh ) {
10863
10864 ON_BOOL32 bHaveMat = false;
10865 Read3dmV1AttributesOrMaterial(pAttributes,NULL,bHaveMat,TCODE_ENDOFTABLE);
10866 }
10867
10868 return rc;
10869 }
10870
10871 static bool BeginRead3dmLEGACYSTUFF( ON_BinaryArchive& file, unsigned int stuff_tcode )
10872 {
10873
10874 bool rc = false;
10875 ON__UINT32 tcode = !stuff_tcode;
10876 ON__INT64 big_value = 0;
10877 for (;;)
10878 {
10879 if ( !file.BeginRead3dmBigChunk(&tcode,&big_value) )
10880 break;
10881 if ( tcode == stuff_tcode ) {
10882 rc = true;
10883 break;
10884 }
10885 if ( !file.EndRead3dmChunk() )
10886 break;
10887 }
10888 return rc;
10889 }
10890
10891 static ON_NurbsCurve* ReadV1_TCODE_LEGACY_SPLSTUFF( ON_BinaryArchive& file )
10892 {
10893
10894 ON_NurbsCurve* pNurbsCurve = 0;
10895 int i, dim, is_rat, order, cv_count, is_closed, form;
10896 ON_BoundingBox bbox;
10897 char c;
10898
10899
10900 if ( !file.ReadChar(1,&c) )
10901 return NULL;
10902 if ( c != 2 && c != 3 )
10903 return NULL;
10904 dim = c;
10905 if ( !file.ReadChar(1,&c) )
10906 return NULL;
10907 if ( c != 0 && c != 1 && c != 2 )
10908 return NULL;
10909 is_rat = c;
10910 if ( !file.ReadChar(1,&c) )
10911 return NULL;
10912 if ( c < 2 )
10913 return NULL;
10914 order = c;
10915
10916 {
10917
10918
10919
10920
10921
10922
10923
10924
10925 unsigned short s;
10926 if ( !file.ReadShort(1,&s) )
10927 return NULL;
10928 unsigned int ui = s;
10929 cv_count = (int)ui;
10930 if ( cv_count < order )
10931 return NULL;
10932 }
10933
10934
10935
10936
10937 if ( !file.ReadByte(1,&c) )
10938 return NULL;
10939 if (c != 0 && c != 1 && c != 2)
10940 return NULL;
10941 is_closed = c;
10942 if ( !file.ReadByte(1,&c) )
10943 return NULL;
10944 form = c;
10945
10946
10947 if ( !file.ReadDouble( dim, bbox.m_min ) )
10948 return NULL;
10949 if ( !file.ReadDouble( dim, bbox.m_max ) )
10950 return NULL;
10951
10952 pNurbsCurve = new ON_NurbsCurve( dim, is_rat?true:false, order, cv_count );
10953
10954 ON_BOOL32 rc = false;
10955 for(;;) {
10956
10957
10958 const int knot_count = order+cv_count-2;
10959 int knot_index = 0;
10960 double knot;
10961
10962
10963 char clamped_end_knot_flag = 0;
10964 if ( order > 2 )
10965 file.ReadChar(1,&clamped_end_knot_flag);
10966
10967
10968 if ( !file.ReadDouble(&knot) )
10969 break;
10970 pNurbsCurve->m_knot[knot_index++] = knot;
10971 if (clamped_end_knot_flag % 2) {
10972
10973 while ( knot_index <= order-2 )
10974 pNurbsCurve->m_knot[knot_index++] = knot;
10975 }
10976
10977
10978 while ( knot_index <= cv_count-1 ) {
10979 if ( !file.ReadDouble(&knot) )
10980 break;
10981 pNurbsCurve->m_knot[knot_index++] = knot;
10982 }
10983 if ( knot_index <= cv_count-1 )
10984 break;
10985
10986
10987 if ( clamped_end_knot_flag >= 2 ) {
10988 while ( knot_index < knot_count )
10989 pNurbsCurve->m_knot[knot_index++] = knot;
10990 }
10991 else {
10992 while ( knot_index < knot_count ) {
10993 if ( !file.ReadDouble(&knot) )
10994 break;
10995 pNurbsCurve->m_knot[knot_index++] = knot;
10996 }
10997 if ( knot_index < knot_count )
10998 break;
10999 }
11000
11001
11002 const int cvdim = ( is_rat ) ? dim+1 : dim;
11003 for ( i = 0; i < cv_count; i++ ) {
11004 if ( !file.ReadDouble( cvdim, pNurbsCurve->CV(i) ) )
11005 break;
11006 }
11007 if ( i < cv_count )
11008 break;
11009 if ( is_rat ) {
11010
11011
11012 double w, *cv;
11013 int cv_index;
11014 for ( cv_index = 0; cv_index < cv_count; cv_index++ ) {
11015 cv = pNurbsCurve->CV(cv_index);
11016 w = cv[dim];
11017 for ( i = 0; i < dim; i++ )
11018 cv[i] *= w;
11019 }
11020 }
11021 if ( order == 2 && cv_count == 2 && pNurbsCurve->m_knot[0] > pNurbsCurve->m_knot[1] ) {
11022
11023 pNurbsCurve->m_knot[0] = -pNurbsCurve->m_knot[0];
11024 pNurbsCurve->m_knot[1] = -pNurbsCurve->m_knot[1];
11025 }
11026 rc = true;
11027
11028 break;
11029 }
11030 if ( !rc && pNurbsCurve ) {
11031 delete pNurbsCurve;
11032 pNurbsCurve = 0;
11033 }
11034 return pNurbsCurve;
11035 }
11036
11037 static ON_BOOL32 ReadV1_TCODE_LEGACY_SPL( ON_BinaryArchive& file,
11038 ON_NurbsCurve*& pNurbsCurve
11039 )
11040 {
11041
11042 pNurbsCurve = 0;
11043 ON_BOOL32 rc = BeginRead3dmLEGACYSTUFF(file, TCODE_LEGACY_SPLSTUFF );
11044 if ( !rc )
11045 return false;
11046 pNurbsCurve = ReadV1_TCODE_LEGACY_SPLSTUFF(file);
11047 if ( !file.EndRead3dmChunk() )
11048 rc = false;
11049 if ( !pNurbsCurve )
11050 rc = false;
11051 return rc;
11052 }
11053
11054 static ON_NurbsSurface* ReadV1_TCODE_LEGACY_SRFSTUFF( ON_BinaryArchive& file )
11055 {
11056
11057 ON_NurbsSurface* pNurbsSurface = 0;
11058 int i, j, dim=0, is_rat=0, order[2], cv_count[2], is_closed[2], is_singular[2], form;
11059 ON_BoundingBox bbox;
11060 char c;
11061
11062
11063 if ( !file.ReadChar(1,&c) )
11064 return NULL;
11065 if ( c != 2 && c != 3 )
11066 return NULL;
11067 dim = c;
11068 if ( !file.ReadByte(1,&c) )
11069 return NULL;
11070 form = c;
11071 if ( !file.ReadChar(1,&c) )
11072 return NULL;
11073 if ( c < 1 )
11074 return NULL;
11075 order[0] = c+1;
11076 if ( !file.ReadChar(1,&c) )
11077 return NULL;
11078 if ( c < 1 )
11079 return NULL;
11080 order[1] = c+1;
11081
11082 {
11083
11084
11085
11086
11087 unsigned short s;
11088 if ( !file.ReadShort(1,&s) )
11089 return NULL;
11090 if ( s < 1 )
11091 return NULL;
11092 unsigned int ui = s;
11093 cv_count[0] = order[0]-1+((int)ui);
11094 if ( !file.ReadShort(1,&s) )
11095 return NULL;
11096 if ( s < 1 )
11097 return NULL;
11098 ui = s;
11099 cv_count[1] = order[1]-1+((int)ui);
11100 }
11101
11102
11103 if ( !file.ReadChar(1,&c) )
11104 return NULL;
11105 if ( c == 1 ) is_rat = 1; else if ( c == 2 ) is_rat = 2;
11106
11107
11108 if ( !file.ReadChar(1,&c) )
11109 return NULL;
11110 if ( c == 1 ) is_rat = 1; else if ( c == 2 ) is_rat = 2;
11111
11112
11113
11114
11115 if ( !file.ReadByte(1,&c) )
11116 return NULL;
11117 if (c != 0 && c != 1 && c != 2)
11118 return NULL;
11119 is_closed[0] = c;
11120 if ( !file.ReadByte(1,&c) )
11121 return NULL;
11122 if (c != 0 && c != 1 && c != 2)
11123 return NULL;
11124 is_closed[1] = c;
11125
11126 if ( !file.ReadByte(1,&c) )
11127 return NULL;
11128 if (c != 0 && c != 1 && c != 2 && c != 3)
11129 return NULL;
11130 is_singular[0] = c;
11131 if ( !file.ReadByte(1,&c) )
11132 return NULL;
11133 if (c != 0 && c != 1 && c != 2 && c != 3)
11134 return NULL;
11135 is_singular[1] = c;
11136
11137
11138 if ( !file.ReadDouble( dim, bbox.m_min ) )
11139 return NULL;
11140 if ( !file.ReadDouble( dim, bbox.m_max ) )
11141 return NULL;
11142
11143 pNurbsSurface = new ON_NurbsSurface( dim, is_rat?true:false,
11144 order[0], order[1],
11145 cv_count[0], cv_count[1] );
11146
11147 ON_BOOL32 rc = false;
11148 for (;;) {
11149
11150
11151 if ( !file.ReadDouble( order[0]+cv_count[0]-2, pNurbsSurface->m_knot[0] ) )
11152 break;
11153 if ( !file.ReadDouble( order[1]+cv_count[1]-2, pNurbsSurface->m_knot[1] ) )
11154 break;
11155
11156
11157 const int cvdim = ( is_rat ) ? dim+1 : dim;
11158 for ( i = 0; i < cv_count[0]; i++ ) {
11159 for ( j = 0; j < cv_count[1]; j++ ) {
11160 if ( !file.ReadDouble( cvdim, pNurbsSurface->CV(i,j) ) )
11161 break;
11162 }
11163 if ( j < cv_count[1] )
11164 break;
11165 }
11166 if ( i < cv_count[0] )
11167 break;
11168 if ( is_rat == 1 ) {
11169 double w, *cv;
11170 int k;
11171 for ( i = 0; i < cv_count[0]; i++ ) for ( j = 0; j < cv_count[1]; j++ ) {
11172 cv = pNurbsSurface->CV(i,j);
11173 w = cv[dim];
11174 for ( k = 0; k < dim; k++ )
11175 cv[k] *= w;
11176 }
11177 }
11178 rc = true;
11179
11180 break;
11181 }
11182 if ( !rc ) {
11183 delete pNurbsSurface;
11184 pNurbsSurface = 0;
11185 }
11186
11187 return pNurbsSurface;
11188 }
11189
11190 static ON_BOOL32 ReadV1_TCODE_LEGACY_SRF( ON_BinaryArchive& file,
11191 ON_NurbsSurface*& pNurbsSurface
11192 )
11193 {
11194 pNurbsSurface = 0;
11195 ON_BOOL32 rc = BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_SRF );
11196 if ( rc ) {
11197 rc = BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_SRFSTUFF );
11198 if ( rc ) {
11199 pNurbsSurface = ReadV1_TCODE_LEGACY_SRFSTUFF( file );
11200 if ( !file.EndRead3dmChunk() )
11201 rc = false;
11202 }
11203 if ( !file.EndRead3dmChunk() )
11204 rc = false;
11205 }
11206 if ( !rc && pNurbsSurface ) {
11207 delete pNurbsSurface;
11208 pNurbsSurface = 0;
11209 }
11210 return rc;
11211 }
11212
11213 ON_Curve* ReadV1_TCODE_LEGACY_CRVSTUFF( ON_BinaryArchive& file )
11214 {
11215
11216 ON_Curve* curve = 0;
11217 ON_PolyCurve* polycurve = 0;
11218 ON_NurbsCurve* segment = 0;
11219 ON_BOOL32 rc = false;
11220 ON__UINT32 tcode = 0;
11221 ON__INT64 big_value = 0;
11222 int i;
11223 ON_BOOL32 bIsPolyline = false;
11224 ON_BoundingBox bbox;
11225
11226 for (;;) {
11227 char c;
11228 short s;
11229 int segment_count = 0;
11230 file.ReadChar(1,&c);
11231 if ( c != 2 && c != 3 )
11232 break;
11233 int dim = c;
11234 file.ReadChar(1,&c);
11235 if ( c != -1 && c != 0 && c != 1 && c != 2 )
11236 break;
11237
11238 file.ReadShort(&s);
11239 if ( s < 1 )
11240 break;
11241 file.ReadDouble( dim, bbox.m_min);
11242 file.ReadDouble( dim, bbox.m_max);
11243 segment_count = s;
11244 for ( i = 0; i < segment_count; i++ ) {
11245 segment = 0;
11246 tcode = 0;
11247 big_value = 0;
11248 if ( !file.BeginRead3dmBigChunk( &tcode, &big_value ) )
11249 break;
11250 if ( tcode == TCODE_LEGACY_SPL && big_value > 0 ) {
11251 ReadV1_TCODE_LEGACY_SPL(file,segment);
11252 }
11253 if ( !file.EndRead3dmChunk() ) {
11254 if ( segment ) {
11255 delete segment;
11256 segment = 0;
11257 }
11258 break;
11259 }
11260 if ( !segment )
11261 break;
11262 if ( i == 0 )
11263 polycurve = new ON_PolyCurve(segment_count);
11264 if ( segment->CVCount() > 2 || segment->Order() != 2 || segment->IsRational() )
11265 {
11266 if ( segment->Order() != 2 || segment->IsRational() )
11267 bIsPolyline = false;
11268 polycurve->Append(segment);
11269 }
11270 else
11271 {
11272 ON_LineCurve* line = new ON_LineCurve();
11273 line->m_t.Set( segment->m_knot[0], segment->m_knot[1] );
11274 segment->GetCV( 0, line->m_line.from );
11275 segment->GetCV( 1, line->m_line.to );
11276 line->m_dim = segment->m_dim;
11277 delete segment;
11278 segment = 0;
11279 polycurve->Append(line);
11280 }
11281 }
11282
11283
11284
11285
11286
11287 if ( 0 == polycurve )
11288 break;
11289 if ( polycurve->Count() != segment_count )
11290 break;
11291 rc = true;
11292 break;
11293 }
11294
11295 if ( rc && polycurve )
11296 {
11297 if ( polycurve->Count() == 1 )
11298 {
11299 curve = polycurve->HarvestSegment(0);
11300 delete polycurve;
11301 }
11302 else if ( bIsPolyline )
11303 {
11304 ON_PolylineCurve* pline = new ON_PolylineCurve();
11305 pline->m_dim = polycurve->Dimension();
11306 pline->m_t.Reserve(polycurve->Count()+1);
11307 pline->m_t.SetCount(polycurve->Count()+1);
11308 polycurve->GetSpanVector( pline->m_t.Array() );
11309 pline->m_pline.Reserve(polycurve->Count()+1);
11310 for ( i = 0; i < polycurve->Count(); i++ ) {
11311 pline->m_pline.Append(polycurve->SegmentCurve(i)->PointAtStart());
11312 }
11313 pline->m_pline.Append(polycurve->SegmentCurve(polycurve->Count()-1)->PointAtEnd());
11314 curve = pline;
11315 delete polycurve;
11316 }
11317 else
11318 {
11319 curve = polycurve;
11320 }
11321 }
11322 else
11323 {
11324 if ( polycurve )
11325 delete polycurve;
11326 rc = false;
11327 }
11328
11329 return curve;
11330 }
11331
11332 bool ON_Brep::ReadV1_LegacyTrimStuff( ON_BinaryArchive& file,
11333 ON_BrepFace&,
11334 ON_BrepLoop& loop )
11335 {
11336
11337 bool rc = false;
11338 int revedge, gcon, mono;
11339 int curve2d_index = -1, curve3d_index = -1, trim_index = -1;
11340 double tol_3d, tol_2d;
11341 ON_Curve* curve2d = NULL;
11342 ON_Curve* curve3d = NULL;
11343
11344 char c;
11345 file.ReadChar( &c );
11346
11347 ON_BOOL32 bHasEdge = (c % 2 );
11348 ON_BOOL32 bHasMate = (c & 6 );
11349 ON_BOOL32 bIsSeam = (c & 2 );
11350
11351 if ( !file.ReadInt(&revedge) )
11352 return false;
11353 if ( !file.ReadInt(&gcon) )
11354 return false;
11355 if ( !file.ReadInt(&mono) )
11356 return false;
11357 if ( !file.ReadDouble( &tol_3d ) )
11358 return false;
11359 if ( !file.ReadDouble( &tol_2d ) )
11360 return false;
11361
11362
11363 if ( !BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_CRV ) )
11364 return false;
11365 if ( BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_CRVSTUFF ) ) {
11366 curve2d = ReadV1_TCODE_LEGACY_CRVSTUFF(file);
11367 if ( !file.EndRead3dmChunk() )
11368 rc = false;
11369 }
11370 if ( !file.EndRead3dmChunk() )
11371 rc = false;
11372 if ( !curve2d )
11373 return false;
11374 curve2d_index = AddTrimCurve(curve2d);
11375 if ( curve2d_index < 0 ) {
11376 delete curve2d;
11377 return false;
11378 }
11379
11380
11381 if ( bHasEdge ) {
11382 if ( !BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_CRV ) )
11383 return false;
11384 if ( BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_CRVSTUFF ) ) {
11385 curve3d = ReadV1_TCODE_LEGACY_CRVSTUFF(file);
11386 if ( !file.EndRead3dmChunk() )
11387 rc = false;
11388 }
11389 if ( !file.EndRead3dmChunk() )
11390 rc = false;
11391 if ( !curve3d )
11392 return false;
11393 curve3d_index = AddEdgeCurve(curve3d);
11394 if ( curve3d_index < 0 ) {
11395 delete curve3d;
11396 return false;
11397 }
11398 ON_BrepEdge& edge = NewEdge(curve3d_index);
11399 ON_BrepTrim& trim = NewTrim( edge,
11400 revedge ? true : false,
11401 loop,
11402 curve2d_index
11403 );
11404 trim_index = trim.m_trim_index;
11405 }
11406 else {
11407 ON_BrepTrim& trim = NewTrim( revedge ? true : false,
11408 loop,
11409 curve2d_index
11410 );
11411 trim_index = trim.m_trim_index;
11412 }
11413 if ( trim_index >= 0 ) {
11414 ON_BrepTrim& trim = m_T[trim_index];
11415 trim.m__legacy_2d_tol = tol_2d;
11416 trim.m__legacy_3d_tol = tol_3d;
11417 trim.m__legacy_flags_Set(gcon,mono);
11418 if ( bIsSeam ) {
11419 trim.m_type = ON_BrepTrim::seam;
11420 }
11421 else if ( bHasMate ) {
11422 trim.m_type = ON_BrepTrim::mated;
11423 }
11424 else if ( bHasEdge ) {
11425 trim.m_type = ON_BrepTrim::boundary;
11426 }
11427 else {
11428 trim.m_type = ON_BrepTrim::singular;
11429 }
11430 }
11431
11432 return (trim_index>=0) ? true : false;
11433 }
11434
11435 bool ON_Brep::ReadV1_LegacyTrim( ON_BinaryArchive& file,
11436 ON_BrepFace& face,
11437 ON_BrepLoop& loop )
11438 {
11439 bool rc = false;
11440 if ( !BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_TRM ) )
11441 return false;
11442 rc = BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_TRMSTUFF );
11443 if ( rc ) {
11444 rc = ReadV1_LegacyTrimStuff( file, face, loop );
11445 if ( !file.EndRead3dmChunk() )
11446 rc = false;
11447 }
11448 if ( !file.EndRead3dmChunk() )
11449 rc = false;
11450 return rc;
11451 }
11452
11453
11454 bool ON_Brep::ReadV1_LegacyLoopStuff( ON_BinaryArchive& file,
11455 ON_BrepFace& face )
11456 {
11457
11458
11459 ON_BrepLoop::TYPE loop_type = ON_BrepLoop::unknown;
11460 int tedge_count, btype, lti;
11461 double pspace_box[2][2];
11462
11463 if ( !file.ReadInt( &tedge_count ) )
11464 return false;
11465 if ( tedge_count < 1 ) {
11466 return false;
11467 }
11468 if ( !file.ReadInt( &btype ) )
11469 return false;
11470 if ( btype < -1 || btype > 1 ) {
11471 return false;
11472 }
11473 if ( !file.ReadDouble( 4, &pspace_box[0][0] ) )
11474 return false;
11475 switch( btype ) {
11476 case -1:
11477 loop_type = ON_BrepLoop::slit;
11478 break;
11479 case 0:
11480 loop_type = ON_BrepLoop::outer;
11481 break;
11482 case 1:
11483 loop_type = ON_BrepLoop::inner;
11484 break;
11485 }
11486 ON_BrepLoop& loop = NewLoop( loop_type, face );
11487
11488 for ( lti = 0; lti < tedge_count; lti++ ) {
11489 if ( !ReadV1_LegacyTrim( file, face, loop ) )
11490 return false;
11491 }
11492
11493 return true;
11494 }
11495
11496 bool ON_Brep::ReadV1_LegacyLoop( ON_BinaryArchive& file,
11497 ON_BrepFace& face )
11498 {
11499 bool rc = false;
11500 if ( !BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_BND ) )
11501 return false;
11502 rc = BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_BNDSTUFF );
11503 if ( rc ) {
11504 rc = ReadV1_LegacyLoopStuff( file, face );
11505 if ( !file.EndRead3dmChunk() )
11506 rc = false;
11507 }
11508 if ( !file.EndRead3dmChunk() )
11509 rc = false;
11510 return rc;
11511 }
11512
11513 bool ON_Brep::ReadV1_LegacyFaceStuff( ON_BinaryArchive& file )
11514 {
11515
11516 ON_NurbsSurface* surface = 0;
11517 ON_Workspace ws;
11518 int flipnorm = 0;
11519 int ftype = 0;
11520 int bndcnt = 0;
11521 int twincnt = 0;
11522 ON_BOOL32 bHasOuter = false;
11523 ON_BoundingBox face_bbox;
11524
11525 int ti0 = m_T.Count();
11526
11527 bool rc = false;
11528
11529
11530 if ( !file.ReadInt(&flipnorm) )
11531 return false;
11532 if ( flipnorm < 0 || flipnorm > 1 )
11533 return false;
11534 if ( !file.ReadInt(&ftype) )
11535 return false;
11536 if ( !file.ReadInt(&bndcnt) )
11537 return false;
11538 bHasOuter = (bndcnt%2);
11539 bndcnt /= 2;
11540
11541
11542 if ( !file.ReadDouble( 3, face_bbox.m_min ) )
11543 return false;
11544 if ( !file.ReadDouble( 3, face_bbox.m_max ) )
11545 return false;
11546
11547
11548 if ( !file.ReadInt(&twincnt) )
11549 return false;
11550 short* glue = (twincnt > 0 ) ? (short*)ws.GetMemory(twincnt*sizeof(*glue)) : NULL;
11551 if (twincnt > 0) {
11552 if ( !file.ReadShort(twincnt,glue) )
11553 return false;
11554 }
11555
11556
11557 if ( !ReadV1_TCODE_LEGACY_SRF( file, surface ) )
11558 return false;
11559 if ( !surface )
11560 return false;
11561 const int srf_index = AddSurface(surface);
11562
11563
11564 ON_BrepFace& face = NewFace(srf_index);
11565 face.m_bRev = (flipnorm) ? true : false;
11566 face.m_li.Reserve(bndcnt);
11567
11568
11569 int loop_index = -1;
11570 if ( !bHasOuter ) {
11571
11572 face.m_li.Append(loop_index);
11573 }
11574 int bi;
11575 rc = true;
11576 for ( bi = 0; rc && bi < bndcnt; bi++ ) {
11577 rc = ReadV1_LegacyLoop( file, face );
11578 }
11579
11580 if ( twincnt > 0 ) {
11581
11582
11583
11584
11585 int si, ti;
11586 const int ti1 = m_T.Count();
11587 int* seam_i = (int*)ws.GetMemory(twincnt*sizeof(*seam_i));
11588 for ( ti = ti0, si = 0; ti < ti1 && si < twincnt; ti++ ) {
11589 if (m_T[ti].m_type != ON_BrepTrim::seam )
11590 continue;
11591 seam_i[si++] = ti;
11592 }
11593
11594 if ( si == twincnt ) {
11595
11596 for ( si = 0; si < twincnt; si++ ) {
11597 if ( glue[si] >= 0 && glue[si] < twincnt ) {
11598 const int i0 = seam_i[si];
11599 const int i1 = seam_i[glue[si]];
11600
11601 const int ei0 = m_T[i0].m_ei;
11602 const int ei1 = m_T[i1].m_ei;
11603 if ( ei0 == -1 && ei1 >= 0 ) {
11604 m_T[i0].m_ei = ei1;
11605 m_E[ei1].m_ti.Append(i0);
11606 }
11607 else if ( ei1 == -1 && ei0 >= 0 ) {
11608 m_T[i1].m_ei = ei0;
11609 m_E[ei0].m_ti.Append(i1);
11610 }
11611 }
11612 }
11613 }
11614 }
11615
11616 return rc;
11617 }
11618
11619 bool ON_Brep::ReadV1_LegacyShellStuff( ON_BinaryArchive& file )
11620 {
11621
11622 ON_Workspace ws;
11623 int outer = 0;
11624 int facecnt = 0;
11625 int twincnt = 0;
11626 ON_BoundingBox shell_bbox;
11627 const int ti0 = m_T.Count();
11628
11629
11630 file.ReadInt(&outer);
11631 file.ReadInt(&facecnt);
11632
11633
11634 file.ReadPoint( shell_bbox.m_min );
11635 file.ReadPoint( shell_bbox.m_max );
11636
11637
11638 file.ReadInt(&twincnt);
11639 short* glue = (twincnt > 0 ) ? (short*)ws.GetMemory(twincnt*sizeof(*glue)) : NULL;
11640 if (twincnt > 0)
11641 file.ReadShort(twincnt,glue);
11642
11643 bool rc = true;
11644 int fi;
11645 for ( fi = 0; rc && fi < facecnt; fi++ ) {
11646 rc = BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_FAC );
11647 if ( rc ) {
11648 rc = BeginRead3dmLEGACYSTUFF( file, TCODE_LEGACY_FACSTUFF );
11649 if ( rc ) {
11650 rc = ReadV1_LegacyFaceStuff( file );
11651 if ( !file.EndRead3dmChunk() )
11652 rc = false;
11653 }
11654 if ( !file.EndRead3dmChunk() )
11655 rc = false;
11656 }
11657 }
11658
11659 if ( twincnt > 0 ) {
11660
11661
11662
11663
11664 int si, ti;
11665 const int ti1 = m_T.Count();
11666 int* share_i = (int*)ws.GetMemory(twincnt*sizeof(*share_i));
11667 for ( ti = ti0, si = 0; ti < ti1 && si < twincnt; ti++ ) {
11668 if (m_T[ti].m_type != ON_BrepTrim::mated )
11669 continue;
11670 share_i[si++] = ti;
11671 }
11672
11673 if ( si == twincnt ) {
11674
11675 for ( si = 0; si < twincnt; si++ ) {
11676 if ( glue[si] >= 0 && glue[si] < twincnt ) {
11677 const int i0 = share_i[si];
11678 const int i1 = share_i[glue[si]];
11679
11680 const int ei0 = m_T[i0].m_ei;
11681 const int ei1 = m_T[i1].m_ei;
11682 if ( ei0 == -1 && ei1 >= 0 ) {
11683 m_T[i0].m_ei = ei1;
11684 m_E[ei1].m_ti.Append(i0);
11685 }
11686 else if ( ei1 == -1 && ei0 >= 0 ) {
11687 m_T[i1].m_ei = ei0;
11688 m_E[ei0].m_ti.Append(i1);
11689 }
11690 }
11691 }
11692 }
11693 }
11694
11695 return rc;
11696 }
11697
11698 bool ON_BinaryArchive::ReadV1_TCODE_LEGACY_CRV(
11699 ON_Object** ppObject,
11700 ON_3dmObjectAttributes* pAttributes
11701 )
11702 {
11703 ON_Curve* curve = NULL;
11704 bool rc = false;
11705 ON__UINT32 tcode = 0;
11706 ON__INT64 big_value = 0;
11707 ON_BOOL32 bHaveMat = false;
11708
11709 Read3dmV1AttributesOrMaterial(pAttributes,NULL,bHaveMat,TCODE_LEGACY_CRVSTUFF);
11710
11711 if ( !BeginRead3dmBigChunk( &tcode, &big_value ) )
11712 return false;
11713 if ( tcode == TCODE_LEGACY_CRVSTUFF )
11714 curve = ReadV1_TCODE_LEGACY_CRVSTUFF(*this);
11715 rc = EndRead3dmChunk();
11716 if ( !curve )
11717 rc = false;
11718 else
11719 *ppObject = curve;
11720 return rc;
11721 }
11722
11723
11724 bool ON_BinaryArchive::ReadV1_TCODE_LEGACY_FAC(
11725 ON_Object** ppObject,
11726 ON_3dmObjectAttributes* pAttributes
11727 )
11728 {
11729
11730 ON_BOOL32 bHaveMat = false;
11731 if ( !Read3dmV1AttributesOrMaterial(pAttributes,NULL,bHaveMat,TCODE_LEGACY_FACSTUFF) )
11732 return false;
11733 if ( !BeginRead3dmLEGACYSTUFF( *this, TCODE_LEGACY_FACSTUFF ) )
11734 return false;
11735 ON_Brep* brep = new ON_Brep();
11736 bool rc = brep->ReadV1_LegacyFaceStuff( *this );
11737 if ( !EndRead3dmChunk() )
11738 rc = false;
11739
11740 if ( !rc ) {
11741 delete brep;
11742 }
11743 else {
11744 brep->SetVertices();
11745 brep->SetTrimIsoFlags();
11746 brep->SetTolsFromLegacyValues();
11747 *ppObject = brep;
11748 }
11749
11750 return rc;
11751 }
11752
11753 bool ON_BinaryArchive::ReadV1_TCODE_LEGACY_SHL(
11754 ON_Object** ppObject,
11755 ON_3dmObjectAttributes* pAttributes
11756 )
11757 {
11758
11759 ON_BOOL32 bHaveMat = false;
11760 if ( !Read3dmV1AttributesOrMaterial(pAttributes,NULL,bHaveMat,TCODE_LEGACY_SHLSTUFF) )
11761 return false;
11762 if ( !BeginRead3dmLEGACYSTUFF( *this, TCODE_LEGACY_SHLSTUFF ) )
11763 return false;
11764 ON_Brep* brep = new ON_Brep();
11765 bool rc = brep->ReadV1_LegacyShellStuff( *this );
11766 if ( !EndRead3dmChunk() )
11767 rc = false;
11768
11769 if ( !rc ) {
11770 delete brep;
11771 }
11772 else {
11773 brep->SetVertices();
11774 brep->SetTrimIsoFlags();
11775 brep->SetTolsFromLegacyValues();
11776 *ppObject = brep;
11777 }
11778
11779 return rc;
11780 }
11781
11782
11783 static
11784 ON_NurbsCurve* ReadV1_RHINOIO_NURBS_CURVE_OBJECT_DATA( ON_BinaryArchive& file )
11785 {
11786
11787
11788
11789
11790 ON_NurbsCurve* curve = 0;
11791 ON_BOOL32 rc = false;
11792 ON__UINT32 tcode = 0;
11793 ON__INT64 big_value = 0;
11794 int version, dim, is_rat, order, cv_count, flag, i;
11795 if ( !file.BeginRead3dmBigChunk( &tcode, &big_value ) )
11796 return NULL;
11797 if ( tcode == TCODE_RHINOIO_OBJECT_DATA ) for (;;) {
11798 if ( !file.ReadInt(&version) )
11799 break;
11800
11801 version &= 0xFFFFFEFF;
11802 if ( version != 100 && version != 101 )
11803 break;
11804 file.ReadInt(&dim);
11805 if ( dim < 1 )
11806 break;
11807 file.ReadInt(&is_rat);
11808 if ( is_rat < 0 || is_rat > 1 )
11809 break;
11810 file.ReadInt(&order);
11811 if ( order < 2 )
11812 break;
11813 file.ReadInt(&cv_count);
11814 if ( cv_count < order )
11815 break;
11816 file.ReadInt(&flag);
11817 if ( flag != 0 )
11818 break;
11819
11820 curve = new ON_NurbsCurve(dim,is_rat,order,cv_count);
11821 if ( !file.ReadDouble( order+cv_count-2, curve->m_knot ) )
11822 break;
11823 int cvdim = is_rat ? dim+1 : dim;
11824 for ( i = 0; i < cv_count; i++ ) {
11825 if ( !file.ReadDouble( cvdim, curve->CV(i) ) )
11826 break;
11827 }
11828 if ( i < cv_count )
11829 break;
11830 rc = true;
11831 break;
11832 }
11833 if ( !file.EndRead3dmChunk() )
11834 rc = false;
11835 if ( !rc && curve ) {
11836 delete curve;
11837 curve = 0;
11838 }
11839
11840 return curve;
11841 }
11842
11843 static
11844 ON_NurbsSurface* ReadV1_RHINOIO_NURBS_SURFACE_OBJECT_DATA( ON_BinaryArchive& file )
11845 {
11846
11847
11848
11849
11850 bool rc = false;
11851 ON_NurbsSurface* surface = 0;
11852 ON__UINT32 tcode = 0;
11853 ON__INT64 big_value = 0;
11854 int version, dim, is_rat, order[2], cv_count[2], flag, i, j;
11855
11856 if ( !file.BeginRead3dmBigChunk( &tcode, &big_value ) )
11857 return NULL;
11858 if ( tcode == TCODE_RHINOIO_OBJECT_DATA ) for (;;) {
11859 if ( !file.ReadInt(&version) )
11860 break;
11861
11862 version &= 0xFFFFFEFF;
11863 if ( version != 100 && version != 101 )
11864 break;
11865 file.ReadInt(&dim);
11866 if ( dim < 1 )
11867 break;
11868 file.ReadInt(&is_rat);
11869 if ( is_rat < 0 || is_rat > 1 )
11870 break;
11871 file.ReadInt(&order[0]);
11872 if ( order[0] < 2 )
11873 break;
11874 file.ReadInt(&order[1]);
11875 if ( order[1] < 2 )
11876 break;
11877 file.ReadInt(&cv_count[0]);
11878 if ( cv_count[0] < order[0] )
11879 break;
11880 file.ReadInt(&cv_count[1]);
11881 if ( cv_count[1] < order[1] )
11882 break;
11883 file.ReadInt(&flag);
11884 if ( flag != 0 )
11885 break;
11886
11887 surface = new ON_NurbsSurface(dim,is_rat,order[0],order[1],cv_count[0],cv_count[1]);
11888 if ( !file.ReadDouble( order[0]+cv_count[0]-2, surface->m_knot[0] ) )
11889 break;
11890 if ( !file.ReadDouble( order[1]+cv_count[1]-2, surface->m_knot[1] ) )
11891 break;
11892 int cvdim = is_rat ? dim+1 : dim;
11893 for ( i = 0; i < cv_count[0]; i++ ) {
11894 for ( j = 0; j < cv_count[1]; j++ ) {
11895 if ( !file.ReadDouble( cvdim, surface->CV(i,j) ) )
11896 break;
11897 }
11898 if ( j < cv_count[1] )
11899 break;
11900 }
11901 if ( i < cv_count[0] )
11902 break;
11903 rc = true;
11904 break;
11905 }
11906 if ( !file.EndRead3dmChunk() )
11907 rc = false;
11908 if ( !rc && surface ) {
11909 delete surface;
11910 surface = 0;
11911 }
11912 return surface;
11913 }
11914
11915 bool ON_BinaryArchive::ReadV1_TCODE_RHINOIO_OBJECT_NURBS_CURVE(
11916 ON_Object** ppObject,
11917 ON_3dmObjectAttributes* pAttributes
11918 )
11919 {
11920
11921
11922 ON_NurbsCurve* curve = 0;
11923 bool rc = false;
11924 ON_BOOL32 bHaveMat = false;
11925
11926
11927 curve = ReadV1_RHINOIO_NURBS_CURVE_OBJECT_DATA(*this);
11928
11929 if ( curve ) {
11930 *ppObject = curve;
11931 rc = true;
11932 Read3dmV1AttributesOrMaterial(pAttributes,NULL,bHaveMat,TCODE_RHINOIO_OBJECT_END);
11933 }
11934
11935 return rc;
11936 }
11937
11938 bool ON_BinaryArchive::ReadV1_TCODE_RHINOIO_OBJECT_NURBS_SURFACE(
11939 ON_Object** ppObject,
11940 ON_3dmObjectAttributes* pAttributes
11941 )
11942 {
11943
11944
11945 ON_BOOL32 bHaveMat = false;
11946 bool rc = false;
11947 ON_NurbsSurface* surface = 0;
11948
11949 surface = ReadV1_RHINOIO_NURBS_SURFACE_OBJECT_DATA( *this );
11950
11951 if ( surface ) {
11952 *ppObject = surface;
11953 rc = true;
11954 Read3dmV1AttributesOrMaterial(pAttributes,NULL,bHaveMat,TCODE_RHINOIO_OBJECT_END);
11955 }
11956
11957 return rc;
11958 }
11959
11960 static
11961 ON_Curve* ReadV1_RHINOIO_BREP_CURVE( ON_BinaryArchive& file )
11962 {
11963 ON_Curve* curve = NULL;
11964 ON_PolyCurve* pcurve = NULL;
11965 ON_NurbsCurve* nurbs_curve = NULL;
11966 int segment_index, segment_count = 0;
11967 ON__UINT32 tcode = 0;
11968 ON__INT64 big_value = 0;
11969
11970 if ( !file.ReadInt(&segment_count) )
11971 return NULL;
11972 if ( segment_count < 1 )
11973 return NULL;
11974
11975 for ( segment_index = 0; segment_index < segment_count; segment_index++ ) {
11976 if ( !file.BeginRead3dmBigChunk(&tcode,&big_value) )
11977 break;
11978 if ( tcode == TCODE_RHINOIO_OBJECT_NURBS_CURVE ) {
11979 nurbs_curve = ReadV1_RHINOIO_NURBS_CURVE_OBJECT_DATA( file );
11980 }
11981 if ( !file.EndRead3dmChunk() )
11982 break;
11983 if ( !nurbs_curve )
11984 break;
11985 if ( segment_index == 0 ) {
11986 curve = nurbs_curve;
11987 nurbs_curve = 0;
11988 }
11989 else {
11990 if ( segment_index == 1 ) {
11991 pcurve = new ON_PolyCurve();
11992 pcurve->Append(curve);
11993 curve = pcurve;
11994 }
11995 pcurve->Append(nurbs_curve);
11996 nurbs_curve = NULL;
11997 }
11998 }
11999
12000 if ( segment_index < segment_count ) {
12001 if ( nurbs_curve ) {
12002 delete nurbs_curve;
12003 nurbs_curve = 0;
12004 }
12005 if ( curve ) {
12006 delete curve;
12007 curve = 0;
12008 }
12009 }
12010 return curve;
12011 }
12012
12013 bool ON_BinaryArchive::ReadV1_TCODE_RHINOIO_OBJECT_BREP(
12014 ON_Object** ppObject,
12015 ON_3dmObjectAttributes* pAttributes
12016 )
12017 {
12018 ON_3dPoint m_oldTrim_mP[2];
12019 ON_BOOL32 bHaveMat = false;
12020 bool rc = false;
12021 ON_Brep* brep = 0;
12022 ON__UINT32 tcode = 0;
12023 ON__INT64 big_value = 0;
12024 if ( !BeginRead3dmBigChunk( &tcode, &big_value ) )
12025 return false;
12026 if ( tcode == TCODE_RHINOIO_OBJECT_DATA ) for (;;) {
12027 int version = -1;
12028 int sz, i, j;
12029 double tol2d, tol3d;
12030 if ( !ReadInt( &version ) )
12031 break;
12032
12033
12034 if ( version != 100 && version != 101 ) {
12035 return false;
12036 }
12037
12038 brep = new ON_Brep();
12039
12040
12041 if ( !ReadInt( &sz ) )
12042 break;
12043 if ( sz < 1 ) {
12044 break;
12045 }
12046 brep->m_C2.Reserve(sz);
12047 for ( i = 0; i < sz; i++ ) {
12048 ON_Curve* curve = ReadV1_RHINOIO_BREP_CURVE( *this );
12049 if ( !curve )
12050 break;
12051 brep->m_C2.Append(curve);
12052 }
12053 if ( i < sz )
12054 break;
12055
12056
12057 if ( !ReadInt( &sz ) )
12058 break;
12059 if ( sz < 1 ) {
12060 break;
12061 }
12062 brep->m_C3.Reserve(sz);
12063 for ( i = 0; i < sz; i++ ) {
12064 ON_Curve* curve = ReadV1_RHINOIO_BREP_CURVE( *this );
12065 if ( !curve )
12066 break;
12067 brep->m_C3.Append(curve);
12068 }
12069 if ( i < sz )
12070 break;
12071
12072
12073 if ( !ReadInt( &sz ) )
12074 break;
12075 if ( sz < 1 ) {
12076 break;
12077 }
12078 brep->m_S.Reserve(sz);
12079 for ( i = 0; i < sz; i++ ) {
12080 ON_NurbsSurface* surface = 0;
12081 tcode = 0;
12082 big_value = 0;
12083 if ( !BeginRead3dmBigChunk(&tcode,&big_value) )
12084 break;
12085 if ( tcode == TCODE_RHINOIO_OBJECT_NURBS_SURFACE ) {
12086 surface = ReadV1_RHINOIO_NURBS_SURFACE_OBJECT_DATA( *this );
12087 }
12088 if ( !EndRead3dmChunk() )
12089 break;
12090 if ( !surface )
12091 break;
12092 brep->m_S.Append(surface);
12093 }
12094 if ( i < sz )
12095 break;
12096
12097
12098 ReadInt( &sz );
12099 brep->m_V.Reserve(sz);
12100 for ( i = 0; i < sz; i++ ) {
12101 ON_BrepVertex& vertex = brep->NewVertex();
12102 if ( !ReadInt( &vertex.m_vertex_index ) ) break;
12103 if ( !ReadPoint( vertex.point ) ) break;
12104 if ( !ReadArray( vertex.m_ei ) ) break;
12105 if ( !ReadDouble( &vertex.m_tolerance ) ) break;
12106 }
12107 if ( i < sz )
12108 break;
12109
12110
12111 ReadInt( &sz );
12112 brep->m_E.Reserve(sz);
12113 for ( i = 0; i < sz; i++ )
12114 {
12115 ON_Interval proxy_domain;
12116 ON_BrepEdge& edge = brep->NewEdge();
12117 if ( !ReadInt( &edge.m_edge_index ) ) break;
12118 if ( !ReadInt( &edge.m_c3i ) ) break;
12119 if ( !ReadInterval( proxy_domain ) ) break;
12120 edge.SetProxyCurveDomain(proxy_domain);
12121 if ( !ReadInt( 2, edge.m_vi ) ) break;
12122 if ( !ReadArray( edge.m_ti ) ) break;
12123 if ( !ReadDouble( &edge.m_tolerance ) ) break;
12124 }
12125 if ( i < sz )
12126 break;
12127
12128
12129 ReadInt( &sz );
12130 brep->m_T.Reserve(sz);
12131 for ( i = 0; i < sz; i++ ) {
12132 ON_BrepTrim& trim = brep->NewTrim();
12133 if ( !ReadInt( &trim.m_trim_index ) ) break;
12134 if ( !ReadInt( &trim.m_c2i ) ) break;
12135 ON_Interval d;
12136 if ( !ReadInterval( d ) )
12137 break;
12138 trim.SetProxyCurve(NULL,d);
12139 if ( !ReadInt( &trim.m_ei ) ) break;
12140 if ( !ReadInt( 2, trim.m_vi ) ) break;
12141 j = trim.m_bRev3d;
12142 if ( !ReadInt( &j ) ) break;
12143 trim.m_bRev3d = (j!=0);
12144 if ( !ReadInt( &j ) ) break;
12145 switch(j) {
12146 case 1: trim.m_type = ON_BrepTrim::boundary; break;
12147 case 2: trim.m_type = ON_BrepTrim::mated; break;
12148 case 3: trim.m_type = ON_BrepTrim::seam; break;
12149 case 4: trim.m_type = ON_BrepTrim::singular; break;
12150 }
12151 if ( !ReadInt( &j ) ) break;
12152 if ( !ReadInt( &trim.m_li ) ) break;
12153 if ( !ReadDouble( 2, trim.m_tolerance ) ) break;
12154 if ( !ReadPoint( m_oldTrim_mP[0] ) ) break;
12155 if ( !ReadPoint( m_oldTrim_mP[1] ) ) break;
12156 if ( !ReadDouble( &tol2d ) ) break;
12157 if ( !ReadDouble( &tol3d ) ) break;
12158 }
12159 if ( i < sz )
12160 break;
12161
12162
12163 ReadInt( &sz );
12164 brep->m_L.Reserve(sz);
12165 for ( i = 0; i < sz; i++ ) {
12166 ON_BrepLoop& loop = brep->NewLoop(ON_BrepLoop::unknown);
12167 if ( !ReadInt( &loop.m_loop_index ) ) break;
12168 if ( !ReadArray( loop.m_ti ) ) break;
12169 if ( !ReadInt( &j ) ) break;
12170 switch (j) {
12171 case 1: loop.m_type = ON_BrepLoop::outer; break;
12172 case 2: loop.m_type = ON_BrepLoop::inner; break;
12173 case 3: loop.m_type = ON_BrepLoop::slit; break;
12174 }
12175 if ( !ReadInt( &loop.m_fi ) ) break;
12176 }
12177 if ( i < sz )
12178 break;
12179
12180
12181 ReadInt( &sz );
12182 brep->m_F.Reserve(sz);
12183 for ( i = 0; i < sz; i++ ) {
12184 ON_BrepFace& face = brep->NewFace();
12185 if ( !ReadInt( &face.m_face_index ) ) break;
12186 if ( !ReadArray( face.m_li ) ) break;
12187 if ( !ReadInt( &face.m_si ) ) break;
12188 int k = face.m_bRev;
12189 if ( !ReadInt( &k ) ) break;
12190 face.m_bRev = (k!=0);
12191 }
12192 if ( i < sz )
12193 break;
12194
12195
12196 {
12197 ON_BoundingBox bbox;
12198 if ( !ReadPoint( bbox.m_min ) ) break;
12199 if ( !ReadPoint( bbox.m_max ) ) break;
12200 }
12201
12202 rc = true;
12203 break;
12204 }
12205 if ( !EndRead3dmChunk() )
12206 rc = false;
12207 if ( rc && brep ) {
12208 brep->SetTrimIsoFlags();
12209 *ppObject = brep;
12210 }
12211 else {
12212 if ( brep )
12213 delete brep;
12214 rc = false;
12215 }
12216
12217 if ( rc && brep ) {
12218 Read3dmV1AttributesOrMaterial(pAttributes,NULL,bHaveMat,TCODE_RHINOIO_OBJECT_END);
12219 }
12220
12221 return rc;
12222 }
12223
12224 int
12225 ON_BinaryArchive::Read3dmV1Object(
12226 ON_Object** ppObject,
12227 ON_3dmObjectAttributes* pAttributes,
12228 unsigned int object_filter
12229 )
12230 {
12231 int rc = 0;
12232
12233
12234
12235
12236
12237 ON__UINT32 tcode = 0;
12238 ON__INT64 big_value = 0;
12239
12240 for(;;)
12241 {
12242 tcode = 0;
12243 big_value = 0;
12244 if ( !BeginRead3dmBigChunk(&tcode,&big_value) ) {
12245 rc = 0;
12246 break;
12247 }
12248 switch(tcode)
12249 {
12250
12251 case TCODE_TEXT_BLOCK:
12252 case TCODE_ANNOTATION_LEADER:
12253 case TCODE_LINEAR_DIMENSION:
12254 case TCODE_ANGULAR_DIMENSION:
12255 case TCODE_RADIAL_DIMENSION:
12256 if ( 0 != (ON::annotation_object & object_filter) )
12257 {
12258 if ( ReadV1_TCODE_ANNOTATION( tcode, ppObject, pAttributes ) )
12259 rc = 1;
12260 else
12261 rc = -1;
12262 }
12263 else
12264 {
12265 rc = 2;
12266 }
12267 break;
12268
12269 case TCODE_RH_POINT:
12270
12271 if ( 0 != (ON::point_object & object_filter) ) {
12272 if (ReadV1_TCODE_RH_POINT( ppObject, pAttributes ))
12273 rc = 1;
12274 else
12275 rc = -1;
12276 }
12277 else {
12278 rc = 2;
12279 }
12280 break;
12281
12282 case TCODE_MESH_OBJECT:
12283
12284 if ( 0 != (ON::mesh_object & object_filter) ) {
12285 if ( ReadV1_TCODE_MESH_OBJECT( ppObject, pAttributes ) )
12286 rc = 1;
12287 else
12288 rc = -1;
12289 }
12290 else {
12291 rc = 2;
12292 }
12293 break;
12294
12295 case TCODE_LEGACY_SHL:
12296
12297 if ( 0 != (ON::mesh_object & object_filter) ) {
12298 if ( ReadV1_TCODE_LEGACY_SHL( ppObject, pAttributes ) )
12299 rc = 1;
12300 else
12301 rc = -1;
12302 }
12303 else {
12304 rc = 2;
12305 }
12306 break;
12307
12308 case TCODE_LEGACY_FAC:
12309
12310 if ( 0 != (ON::mesh_object & object_filter) ) {
12311 if ( ReadV1_TCODE_LEGACY_FAC( ppObject, pAttributes ) )
12312 rc = 1;
12313 else
12314 rc = -1;
12315 }
12316 else {
12317 rc = 2;
12318 }
12319 break;
12320
12321 case TCODE_LEGACY_CRV:
12322
12323 if ( 0 != (ON::mesh_object & object_filter) ) {
12324 if ( ReadV1_TCODE_LEGACY_CRV( ppObject, pAttributes ) )
12325 rc = 1;
12326 else
12327 rc = -1;
12328 }
12329 else {
12330 rc = 2;
12331 }
12332 break;
12333
12334 case TCODE_RHINOIO_OBJECT_NURBS_CURVE:
12335
12336 if ( 0 != (ON::mesh_object & object_filter) ) {
12337 if ( ReadV1_TCODE_RHINOIO_OBJECT_NURBS_CURVE( ppObject, pAttributes ) )
12338 rc = 1;
12339 else
12340 rc = -1;
12341 }
12342 else {
12343 rc = 2;
12344 }
12345 break;
12346
12347 case TCODE_RHINOIO_OBJECT_NURBS_SURFACE:
12348
12349 if ( 0 != (ON::mesh_object & object_filter) ) {
12350 if ( ReadV1_TCODE_RHINOIO_OBJECT_NURBS_SURFACE( ppObject, pAttributes ) )
12351 rc = 1;
12352 else
12353 rc = -1;
12354 }
12355 else {
12356 rc = 2;
12357 }
12358 break;
12359
12360 case TCODE_RHINOIO_OBJECT_BREP:
12361
12362 if ( 0 != (ON::mesh_object & object_filter) ) {
12363 if ( ReadV1_TCODE_RHINOIO_OBJECT_BREP( ppObject, pAttributes ) )
12364 rc = 1;
12365 else
12366 rc = -1;
12367 }
12368 else {
12369 rc = 2;
12370 }
12371 break;
12372 }
12373
12374 if (!EndRead3dmChunk() )
12375 break;
12376 if ( rc == 1 || rc == -1 )
12377 break;
12378 }
12379
12380 return rc;
12381 }
12382
12383 #if 1
12384 class ON_OBSOLETE_CCustomMeshUserData : public ON_UserData
12385 {
12386 public:
12387 ON_OBJECT_DECLARE(ON_OBSOLETE_CCustomMeshUserData);
12388 ON_OBSOLETE_CCustomMeshUserData();
12389 ~ON_OBSOLETE_CCustomMeshUserData();
12390 ON_BOOL32 GetDescription( ON_wString& );
12391 ON_BOOL32 Read(ON_BinaryArchive& binary_archive);
12392 bool m_bInUse;
12393 ON_MeshParameters m_mp;
12394 };
12395
12396 ON_OBJECT_IMPLEMENT(ON_OBSOLETE_CCustomMeshUserData, ON_UserData, "69F27695-3011-4FBA-82C1-E529F25B5FD9");
12397
12398 ON_OBSOLETE_CCustomMeshUserData::ON_OBSOLETE_CCustomMeshUserData()
12399 {
12400 m_userdata_copycount = 0;
12401 m_userdata_uuid = ON_OBSOLETE_CCustomMeshUserData::m_ON_OBSOLETE_CCustomMeshUserData_class_id.Uuid();
12402 m_application_uuid = ON_nil_uuid;
12403 m_bInUse = false;
12404 }
12405
12406 ON_OBSOLETE_CCustomMeshUserData::~ON_OBSOLETE_CCustomMeshUserData()
12407 {
12408 }
12409
12410 ON_BOOL32 ON_OBSOLETE_CCustomMeshUserData::Read(ON_BinaryArchive& ba)
12411 {
12412 int i = 0;
12413 if ( !ba.ReadInt( &i ) )
12414 return false;
12415 if( !ba.ReadBool( &m_bInUse ) )
12416 return false;
12417 return m_mp.Read( ba );
12418 }
12419
12420 ON_BOOL32 ON_OBSOLETE_CCustomMeshUserData::GetDescription( ON_wString& s )
12421 {
12422 s = "OBSOLETE CustomMeshUserData";
12423 return true;
12424 }
12425 #endif
12426
12427
12428 int
12429 ON_BinaryArchive::Read3dmObject(
12430 ON_Object** ppObject,
12431 ON_3dmObjectAttributes* pAttributes,
12432 unsigned int object_filter
12433 )
12434 {
12435
12436
12437
12438
12439
12440 ON_BOOL32 rc = -1;
12441 if ( pAttributes )
12442 pAttributes->Default();
12443 if ( !ppObject )
12444 return 0;
12445 *ppObject = 0;
12446 if ( !object_filter )
12447 object_filter = 0xFFFFFFFF;
12448
12449 if ( m_3dm_version == 1 ) {
12450 rc = Read3dmV1Object(ppObject,pAttributes,object_filter);
12451 }
12452 else
12453 {
12454 ON__UINT32 tcode = 0;
12455 ON__INT64 length_TCODE_OBJECT_RECORD = 0;
12456 ON__INT64 value_TCODE_OBJECT_RECORD_TYPE = 0;
12457 ON__INT64 length_TCODE_OBJECT_RECORD_ATTRIBUTES = 0;
12458 if ( BeginRead3dmBigChunk( &tcode, &length_TCODE_OBJECT_RECORD ) )
12459 {
12460 if ( tcode == TCODE_OBJECT_RECORD )
12461 {
12462 if (BeginRead3dmBigChunk( &tcode, &value_TCODE_OBJECT_RECORD_TYPE ))
12463 {
12464 if ( tcode != TCODE_OBJECT_RECORD_TYPE ) {
12465 rc = -1;
12466 ON_ERROR("ON_BinaryArchive::Read3dmObject() - missing TCODE_OBJECT_RECORD_TYPE chunk.");
12467 }
12468 else if ( 0 != value_TCODE_OBJECT_RECORD_TYPE && 0 == (value_TCODE_OBJECT_RECORD_TYPE | object_filter) )
12469 rc = 2;
12470 else
12471 rc = 1;
12472
12473 if ( !EndRead3dmChunk() )
12474 rc = -1;
12475
12476 switch(ReadObject(ppObject))
12477 {
12478 case 1:
12479 rc = 1;
12480 break;
12481 case 3:
12482 rc = 3;
12483 break;
12484 default:
12485 rc = -1;
12486 break;
12487 }
12488 }
12489 else
12490 rc = -1;
12491 }
12492 else if ( tcode != TCODE_ENDOFTABLE ) {
12493 ON_ERROR("ON_BinaryArchive::Read3dmObject() - corrupt object table");
12494 rc = -1;
12495 }
12496 else
12497 rc = 0;
12498
12499 while(rc==1)
12500 {
12501 tcode = 0;
12502 if (!BeginRead3dmBigChunk( &tcode, &length_TCODE_OBJECT_RECORD_ATTRIBUTES )) {
12503 rc = -1;
12504 break;
12505 }
12506 if ( tcode == TCODE_OBJECT_RECORD_ATTRIBUTES )
12507 {
12508 if ( 0 != pAttributes )
12509 {
12510 if ( !pAttributes->Read( *this ) )
12511 rc = -1;
12512 }
12513 }
12514 else if ( tcode == TCODE_OBJECT_RECORD_ATTRIBUTES_USERDATA )
12515 {
12516 if ( 0 != pAttributes )
12517 {
12518
12519
12520 if ( !ReadObjectUserData(*pAttributes))
12521 rc = -1;
12522 else
12523 {
12524 #if 1
12525
12526 ON_OBSOLETE_CCustomMeshUserData* ud = ON_OBSOLETE_CCustomMeshUserData::Cast(pAttributes->GetUserData(ON_OBSOLETE_CCustomMeshUserData::m_ON_OBSOLETE_CCustomMeshUserData_class_id.Uuid()));
12527 if ( ud )
12528 {
12529 ud->m_mp.m_bCustomSettingsEnabled = ud->m_bInUse ? true : false;
12530 pAttributes->SetCustomRenderMeshParameters(ud->m_mp);
12531 delete ud;
12532 }
12533 #endif
12534 }
12535 }
12536 }
12537
12538 if ( !EndRead3dmChunk() )
12539 {
12540 rc = -1;
12541 }
12542 if ( tcode == TCODE_OBJECT_RECORD_END )
12543 break;
12544 }
12545
12546 if ( !EndRead3dmChunk() )
12547 rc = -1;
12548 }
12549 }
12550
12551 return rc;
12552 }
12553
12554 bool ON_BinaryArchive::EndRead3dmObjectTable()
12555 {
12556 bool rc = EndRead3dmTable( TCODE_OBJECT_TABLE );
12557
12558 if ( 0 != m_V1_layer_list )
12559 {
12560 struct ON__3dmV1LayerIndex* next = m_V1_layer_list;
12561 m_V1_layer_list = 0;
12562 for ( int i = 0; 0 != next && i < 1000; i++ )
12563 {
12564 struct ON__3dmV1LayerIndex* p = next;
12565 next = p->m_next;
12566 onfree(p);
12567 }
12568 }
12569
12570 return rc;
12571 }
12572
12573 bool ON_BinaryArchive::BeginWrite3dmUserTable( const ON_UUID& usertable_uuid )
12574 {
12575 return BeginWrite3dmUserTable(usertable_uuid, false, 0, 0 );
12576 }
12577
12578 bool ON_BinaryArchive::BeginWrite3dmUserTable(
12579 const ON_UUID& plugin_id,
12580 bool bSavingGoo,
12581 int goo_3dm_version,
12582 int goo_opennurbs_version
12583 )
12584 {
12585 if ( m_active_table != no_active_table ) {
12586 ON_ERROR("ON_BinaryArchive::BeginWrite3dmUserTable() - m_active_table != no_active_table");
12587 }
12588 if ( !ON_UuidCompare( &ON_nil_uuid, &plugin_id ) ) {
12589 ON_ERROR("ON_BinaryArchive::BeginWrite3dmUserTable() - nil usertable_uuid not permitted.");
12590 return false;
12591 }
12592 if ( bSavingGoo )
12593 {
12594 if ( goo_3dm_version <= 3 )
12595 return false;
12596 if ( goo_opennurbs_version < 200601010 )
12597 return false;
12598 if ( goo_3dm_version >= 50 && Archive3dmVersion() < 50 )
12599 {
12600
12601
12602 return false;
12603 }
12604 }
12605 else
12606 {
12607 goo_3dm_version = Archive3dmVersion();
12608 goo_opennurbs_version = ArchiveOpenNURBSVersion();
12609 }
12610
12611 bool rc = BeginWrite3dmTable( TCODE_USER_TABLE);
12612 if (rc) {
12613 rc = BeginWrite3dmChunk( TCODE_USER_TABLE_UUID, 0 );
12614 if (rc)
12615 {
12616 rc = WriteUuid( plugin_id );
12617 if (rc)
12618 {
12619
12620
12621
12622
12623
12624 rc = BeginWrite3dmChunk( TCODE_USER_TABLE_RECORD_HEADER, 1, 0 );
12625 if ( rc )
12626 {
12627 if (rc) rc = WriteBool(bSavingGoo);
12628 if (rc) rc = WriteInt(goo_3dm_version);
12629 if (rc) rc = WriteInt(goo_opennurbs_version);
12630 if ( !EndWrite3dmChunk() )
12631 rc = false;
12632 }
12633 }
12634 if ( !EndWrite3dmChunk() )
12635 rc = false;
12636 }
12637 if (rc) {
12638 rc = BeginWrite3dmChunk( TCODE_USER_RECORD, 0 );
12639 }
12640 if ( !rc ) {
12641 EndWrite3dmTable( TCODE_USER_TABLE);
12642 }
12643 }
12644 return rc;
12645 }
12646
12647 bool ON_BinaryArchive::Write3dmAnonymousUserTableRecord(
12648 const ON_UUID& plugin_id,
12649 int goo_3dm_version,
12650 int goo_opennurbs_version,
12651 const ON_3dmGoo& goo
12652 )
12653 {
12654 if ( ON_UuidIsNil(plugin_id) )
12655 return false;
12656 if ( goo_3dm_version <= 3 )
12657 return false;
12658 if (goo_opennurbs_version < 200000000 )
12659 return false;
12660 if ( goo.m_typecode != TCODE_USER_RECORD )
12661 return false;
12662 if ( 0 == goo.m_value )
12663 return false;
12664 if ( 0 == goo.m_goo )
12665 return false;
12666 bool bSavingGoo = true;
12667 if ( !BeginWrite3dmUserTable( plugin_id, bSavingGoo, goo_3dm_version, goo_opennurbs_version ) )
12668 return false;
12669 bool rc = WriteByte( goo.m_value, goo.m_goo );
12670 if ( !EndWrite3dmUserTable() )
12671 rc = false;
12672 return rc;
12673 }
12674
12675
12676 bool ON_BinaryArchive::Write3dmAnonymousUserTable( const ON_3dmGoo& goo )
12677 {
12678 bool rc = false;
12679 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
12680 if ( !c || c->m_typecode != TCODE_USER_RECORD ) {
12681 ON_ERROR("ON_BinaryArchive::Write3dmAnonymousUserTable() - active chunk not a TCODE_USER_RECORD.");
12682 rc = false;
12683 }
12684 else if ( goo.m_typecode != TCODE_USER_RECORD ) {
12685 ON_ERROR("ON_BinaryArchive::Write3dmAnonymousUserTable() - goo chunk not a TCODE_USER_RECORD.");
12686 rc = false;
12687 }
12688 else {
12689 rc = ( goo.m_value > 0 ) ? WriteByte( goo.m_value, goo.m_goo ) : true;
12690 }
12691 return rc;
12692 }
12693
12694
12695 bool ON_BinaryArchive::EndWrite3dmUserTable()
12696 {
12697 bool rc = false;
12698 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
12699 if ( c && c->m_typecode == TCODE_USER_RECORD ) {
12700 rc = EndWrite3dmChunk();
12701 }
12702 else {
12703 ON_ERROR("ON_BinaryArchive::EndWrite3dmUserTable() - not in a TCODE_USER_RECORD chunk.");
12704 rc = false;
12705 }
12706 if ( !EndWrite3dmTable(TCODE_USER_TABLE) )
12707 rc = false;
12708 return rc;
12709 }
12710
12711 bool ON_BinaryArchive::BeginRead3dmUserTable( ON_UUID& usertable_uuid )
12712 {
12713
12714 bool bGoo = false;
12715 int archive_3dm_version = 0;
12716 int archive_opennurbs_version = 0;
12717 bool rc = BeginRead3dmUserTable( usertable_uuid, &bGoo, &archive_3dm_version, &archive_opennurbs_version );
12718 return rc;
12719 }
12720
12721 bool ON_BinaryArchive::BeginRead3dmUserTable(
12722 ON_UUID& plugin_id,
12723 bool* bLastSavedAsGoo,
12724 int* archive_3dm_version,
12725 int* archive_opennurbs_version
12726 )
12727 {
12728 bool bReadArchiveInfo = false;
12729 if ( bLastSavedAsGoo )
12730 *bLastSavedAsGoo = false;
12731 if ( archive_3dm_version )
12732 *archive_3dm_version = 0;
12733 if ( archive_opennurbs_version )
12734 *archive_opennurbs_version = 0;
12735
12736 if ( m_3dm_version == 1 )
12737 return false;
12738
12739 bool rc = BeginRead3dmTable( TCODE_USER_TABLE );
12740
12741
12742
12743
12744
12745
12746 if ( rc )
12747 {
12748
12749 ON__UINT32 tcode = 0;
12750 ON__INT64 big_value = 0;
12751 if (rc) rc = BeginRead3dmBigChunk( &tcode, &big_value );
12752 if (rc)
12753 {
12754 if ( tcode != TCODE_USER_TABLE_UUID )
12755 {
12756 ON_ERROR("ON_BinaryArchive::BeginRead3dmUserTable() - missing user table UUID");
12757 rc = false;
12758 }
12759 else
12760 {
12761 rc = ReadUuid( plugin_id );
12762
12763
12764
12765
12766
12767
12768
12769
12770
12771
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
12782 if ( rc
12783 && ArchiveOpenNURBSVersion() >= 200910190
12784 && 0 != c
12785 && TCODE_USER_TABLE_UUID == c->m_typecode
12786 && c->Length() >= 45 + SizeofChunkLength()
12787 )
12788 {
12789 int major_chunk_version = 0;
12790 int minor_chunk_version = 0;
12791 rc = BeginRead3dmChunk(TCODE_USER_TABLE_RECORD_HEADER,&major_chunk_version,&minor_chunk_version);
12792 if (rc)
12793 {
12794 bReadArchiveInfo = true;
12795 bool b = true;
12796 int arch_ver = 0;
12797 int on_ver = 0;
12798 rc = ReadBool(&b);
12799 if ( rc && bLastSavedAsGoo )
12800 *bLastSavedAsGoo = b;
12801 if (rc)
12802 rc = ReadInt(&arch_ver);
12803 if (rc && archive_3dm_version)
12804 *archive_3dm_version = arch_ver;
12805 if (rc)
12806 rc = ReadInt(&on_ver);
12807 if (rc && archive_opennurbs_version)
12808 *archive_opennurbs_version = on_ver;
12809 if ( !EndRead3dmChunk() )
12810 rc = false;
12811 }
12812 }
12813 }
12814 if ( !EndRead3dmChunk() )
12815 rc = false;
12816 }
12817
12818 tcode = 0;
12819 big_value = 0;
12820 if (rc) rc = BeginRead3dmBigChunk( &tcode, &big_value );
12821 if (rc) {
12822 if ( tcode != TCODE_USER_RECORD ) {
12823 ON_ERROR("ON_BinaryArchive::BeginRead3dmUserTable() - missing user table TCODE_USER_RECORD chunk.");
12824 EndRead3dmChunk();
12825 rc = false;
12826 }
12827 }
12828
12829 if (!rc)
12830 EndRead3dmTable(TCODE_USER_TABLE);
12831
12832 if ( rc && !bReadArchiveInfo )
12833 {
12834
12835
12836
12837
12838 if ( Archive3dmVersion() < 50 )
12839 {
12840 if (archive_3dm_version)
12841 *archive_3dm_version = Archive3dmVersion();
12842 if (archive_opennurbs_version)
12843 *archive_opennurbs_version = ArchiveOpenNURBSVersion();
12844 }
12845 else
12846 {
12847 if (archive_3dm_version)
12848 *archive_3dm_version = 5;
12849 if (archive_opennurbs_version)
12850 *archive_opennurbs_version = 200910180;
12851 }
12852 }
12853 }
12854
12855
12856 return rc;
12857 }
12858
12859 bool ON_BinaryArchive::Read3dmAnonymousUserTable( ON_3dmGoo& goo )
12860 {
12861 return Read3dmAnonymousUserTable(0,0,goo);
12862 }
12863
12864 bool ON_BinaryArchive::Read3dmAnonymousUserTable(
12865 int archive_3dm_version,
12866 int archive_opennurbs_version,
12867 ON_3dmGoo& goo
12868 )
12869 {
12870 if ( 0 == archive_3dm_version )
12871 {
12872 if ( Archive3dmVersion() < 50 )
12873 {
12874 archive_3dm_version = Archive3dmVersion();
12875 archive_opennurbs_version = ArchiveOpenNURBSVersion();
12876 }
12877 else
12878 {
12879
12880 archive_3dm_version = 5;
12881 archive_opennurbs_version = 200910190;
12882 }
12883 }
12884 bool rc = Read3dmGoo( goo );
12885 if (rc && goo.m_typecode != TCODE_USER_RECORD ) {
12886 ON_ERROR("ON_BinaryArchive::Read3dmAnonymousUserTable() do not read a TCODE_USER_RECORD chunk.");
12887 rc = false;
12888 }
12889 return rc;
12890 }
12891
12892 bool ON_BinaryArchive::EndRead3dmUserTable()
12893 {
12894 if ( m_chunk.Count() != 2 ) {
12895 ON_ERROR("ON_BinaryArchive::EndRead3dmUserTable() m_chunk.Count() != 2");
12896 return false;
12897 }
12898 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
12899 if ( 0 == c || c->m_typecode != TCODE_USER_RECORD ) {
12900 ON_ERROR("ON_BinaryArchive::EndRead3dmTable() m_chunk.Last()->typecode != TCODE_USER_RECORD");
12901 return false;
12902 }
12903
12904
12905
12906
12907
12908 bool rc = EndRead3dmChunk(true);
12909
12910 if (rc) {
12911
12912 unsigned int tcode = 0;
12913 ON__INT64 big_value = -1;
12914 rc = BeginRead3dmBigChunk( &tcode, &big_value );
12915 if ( rc ) {
12916 if ( tcode != TCODE_ENDOFTABLE ) {
12917 ON_ERROR("ON_BinaryArchive::EndRead3dmTable() missing TCODE_ENDOFTABLE marker.");
12918 }
12919 if ( !EndRead3dmChunk() )
12920 rc = false;
12921 }
12922 }
12923
12924 if ( !EndRead3dmTable(TCODE_USER_TABLE) )
12925 rc = false;
12926 return rc;
12927 }
12928
12929 bool ON_BinaryArchive::Write3dmEndMark()
12930 {
12931 Flush();
12932 if ( m_chunk.Count() != 0 ) {
12933 ON_ERROR( "ON_BinaryArchive::WriteEndMark() called with unfinished chunks.\n" );
12934 return false;
12935 }
12936 ON__UINT64 length = CurrentPosition();
12937
12938
12939 bool rc = BeginWrite3dmChunk( TCODE_ENDOFFILE, 0 );
12940 if ( rc )
12941 {
12942 size_t sizeof_chunk_length = SizeofChunkLength();
12943 size_t sizeoffile_length = (8==SizeofChunkLength()) ? 8 : 4;
12944 length += (4 + sizeof_chunk_length + sizeoffile_length );
12945 rc = WriteEOFSizeOfFile(length);
12946 if ( !EndWrite3dmChunk() )
12947 rc = false;
12948 }
12949 Flush();
12950
12951 return rc;
12952 }
12953
12954 bool ON_BinaryArchive::Read3dmEndMark( size_t* file_length )
12955 {
12956 unsigned int tcode=0;
12957 ON__INT64 value=0;
12958 if ( file_length )
12959 *file_length = 0;
12960
12961 const unsigned int saved_error_message_mask = m_error_message_mask;
12962 m_error_message_mask |= 0x0001;
12963 bool rc = PeekAt3dmBigChunkType(&tcode,&value);
12964 m_error_message_mask = saved_error_message_mask;
12965
12966 if (rc)
12967 {
12968 if ( tcode == TCODE_ENDOFFILE )
12969 {
12970 rc = BeginRead3dmBigChunk(&tcode,&value);
12971 if ( rc && value > 0 && ((ON__UINT64)value) >= SizeofChunkLength() )
12972 {
12973 ON__UINT64 u64 = 0;
12974 rc = ReadEOFSizeOfFile( &u64 );
12975 if ( rc && file_length )
12976 *file_length = (size_t)u64;
12977 if ( !EndRead3dmChunk() )
12978 rc = false;
12979 }
12980 }
12981 }
12982 return rc;
12983 }
12984
12988
12989 ON::endian
12990 ON_BinaryArchive::Endian() const
12991 {
12992 return m_endian;
12993 }
12994
12995 ON::archive_mode
12996 ON_BinaryArchive::Mode() const
12997 {
12998 return m_mode;
12999 }
13000
13001 void ON_BinaryArchive::UpdateCRC( size_t count, const void* p )
13002 {
13003 if ( m_bDoChunkCRC ) {
13004 ON_3DM_BIG_CHUNK* c = m_chunk.Last();
13005 if (c) {
13006 if ( c->m_do_crc16 )
13007 c->m_crc16 = ON_CRC16( c->m_crc16, count, p );
13008 if ( c->m_do_crc32 )
13009 c->m_crc32 = ON_CRC32( c->m_crc32, count, p );
13010 }
13011 }
13012 }
13013
13014 int ON_BinaryArchive::BadCRCCount() const
13015 {
13016 return m_bad_CRC_count;
13017 }
13018
13019 unsigned int ON_BinaryArchive::ErrorMessageMask() const
13020 {
13021 return m_error_message_mask;
13022 }
13023
13024 bool ON_BinaryArchive::MaskReadError( ON__UINT64 sizeof_request, ON__UINT64 sizeof_read ) const
13025 {
13026 if ( sizeof_request == sizeof_read )
13027 return true;
13028 if ( sizeof_request > sizeof_read )
13029 return false;
13030 if ( 0 != (0x04 & m_error_message_mask) )
13031 return true;
13032 if ( 0 != (0x01 & m_error_message_mask) && 4 == sizeof_request && 0 == sizeof_read )
13033 return true;
13034 return false;
13035 }
13036
13037 ON__UINT64 ON_BinaryArchive::ReadBuffer( ON__UINT64 sizeof_buffer, void* buffer )
13038 {
13039
13040
13041 if ( 0 == buffer )
13042 return 0;
13043 unsigned int saved_error_mask = m_error_message_mask;
13044 m_error_message_mask |= 0x04;
13045 ON__UINT64 sizeof_read = Read((size_t)sizeof_buffer,buffer);
13046 m_error_message_mask = saved_error_mask;
13047 return sizeof_read;
13048 }
13049
13050
13054
13055 ON_BinaryFile::ON_BinaryFile( ON::archive_mode mode )
13056 : ON_BinaryArchive( mode ),
13057 m_fp(0),
13058 m_memory_buffer_capacity(0),
13059 m_memory_buffer_size(0),
13060 m_memory_buffer_ptr(0),
13061 m_memory_buffer(0)
13062 {}
13063
13064 ON_BinaryFile::ON_BinaryFile( ON::archive_mode mode, FILE* fp )
13065 : ON_BinaryArchive( mode ),
13066 m_fp(fp),
13067 m_memory_buffer_capacity(0),
13068 m_memory_buffer_size(0),
13069 m_memory_buffer_ptr(0),
13070 m_memory_buffer(0)
13071 {}
13072
13073 ON_BinaryFile::~ON_BinaryFile()
13074 {
13075 EnableMemoryBuffer(0);
13076 }
13077
13078 bool
13079 ON_BinaryArchive::ReadByte( size_t count, void* p )
13080 {
13081 bool rc = false;
13082 if ( count > 0 ) {
13083 if ( !ReadMode() ) {
13084 ON_ERROR("ON_BinaryArchive::ReadByte() ReadMode() is false.");
13085 }
13086 else if ( p )
13087 {
13088
13089 #if defined(ON_DEBUG)
13090 {
13091
13092 const ON_3DM_BIG_CHUNK* c = m_chunk.Last();
13093 if ( c )
13094 {
13095 ON__UINT64 file_offset = CurrentPosition();
13096 if ( file_offset < c->m_big_offset )
13097 {
13098 ON_ERROR("ON_BinaryArchive::ReadByte will read before the start of the chunk.");
13099 }
13100 else if (c->m_big_offset + c->Length() < file_offset + count )
13101 {
13102 ON_ERROR("ON_BinaryArchive::ReadByte will read past end of the chunk");
13103 }
13104 }
13105 }
13106 #endif
13107
13108 size_t readcount = Read( count, p );
13109 if ( readcount == count )
13110 {
13111 UpdateCRC( count, p );
13112 rc = true;
13113 }
13114 else
13115 {
13116
13117 for(;;)
13118 {
13119 if ( 0 != (m_error_message_mask&0x01)
13120 && 0 == readcount && 4 == count
13121 )
13122 {
13123
13124
13125
13126 break;
13127 }
13128 if ( 0 == m_3dm_version
13129 && 0 == m_3dm_opennurbs_version
13130 && 0 == m_3dm_start_section_offset
13131 && ON_BinaryArchive::no_active_table == m_active_table
13132 && 0 == m_chunk
13133 && ON::read3dm == m_mode
13134 )
13135 {
13136
13137
13138
13139
13140
13141
13142
13143
13144 break;
13145 }
13146 ON_ERROR("ON_BinaryArchive::ReadByte() Read() failed.");
13147 break;
13148 }
13149 }
13150 }
13151 else
13152 {
13153 ON_ERROR("ON_BinaryArchive::ReadByte() NULL file or buffer.");
13154 }
13155 }
13156 else
13157 {
13158 rc = true;
13159 }
13160 return rc;
13161 }
13162
13163 bool
13164 ON_BinaryArchive::WriteByte( size_t count, const void* p )
13165 {
13166 bool rc = false;
13167 if ( count > 0 ) {
13168 if ( !WriteMode() ) {
13169 ON_ERROR("ON_BinaryArchive::WriteByte() WriteMode() is false.");
13170 }
13171 else if ( p ) {
13172 size_t writecount = (size_t)Write( count, p );
13173 if ( writecount == count ) {
13174 UpdateCRC( count, p );
13175 rc = true;
13176 }
13177 else {
13178 ON_ERROR("ON_BinaryArchive::WriteByte() fwrite() failed.");
13179 }
13180 }
13181 else {
13182 ON_ERROR("ON_BinaryArchive::WriteByte() NULL file or buffer.");
13183 }
13184 }
13185 else {
13186 rc = true;
13187 }
13188 return rc;
13189 }
13190
13191 bool ON_BinaryArchive::EnableCRCCalculation( bool bEnable )
13192 {
13193 bool rc = m_bDoChunkCRC;
13194 m_bDoChunkCRC = bEnable ? true : false;
13195 return rc;
13196 }
13197
13198 bool
13199 ON_BinaryArchive::SetArchive3dmVersion(int v)
13200 {
13201 bool rc = false;
13202
13203
13204
13205
13206
13207 if ( (v >= 1 && v <= 5) || ( v >= 50 && 0 == (v % 10) ) )
13208 {
13209 m_3dm_version = v;
13210 rc = true;
13211 }
13212 else
13213 {
13214 m_3dm_version = 0;
13215 ON_ERROR("ON_BinaryArchive::SetArchive3dmVersion - invalid version");
13216 }
13217 return rc;
13218 }
13219
13220 void
13221 ON_BinaryFile::EnableMemoryBuffer(
13222 int buffer_capacity
13223 )
13224 {
13225 if ( buffer_capacity > 0 && !m_memory_buffer) {
13226 m_memory_buffer = (unsigned char*)onmalloc(buffer_capacity);
13227 if ( m_memory_buffer ) {
13228 m_memory_buffer_capacity = buffer_capacity;
13229 m_memory_buffer_size = 0;
13230 m_memory_buffer_ptr = 0;
13231 }
13232 }
13233 else {
13234 if ( buffer_capacity == 0 && m_memory_buffer ) {
13235 Flush();
13236 onfree(m_memory_buffer);
13237 }
13238 m_memory_buffer = 0;
13239 m_memory_buffer_capacity = 0;
13240 m_memory_buffer_size = 0;
13241 m_memory_buffer_ptr = 0;
13242 }
13243 }
13244
13245
13246 size_t ON_BinaryFile::Read( size_t count, void* p )
13247 {
13248 return (m_fp) ? fread( p, 1, count, m_fp ) : 0;
13249 }
13250
13251 size_t ON_BinaryFile::Write( size_t count, const void* p )
13252 {
13253 size_t rc = 0;
13254 if ( m_fp )
13255 {
13256 if ( m_memory_buffer )
13257 {
13258 if ( count+m_memory_buffer_ptr >= m_memory_buffer_capacity ) {
13259 if ( !Flush() )
13260 return 0;
13261 rc = fwrite( p, 1, count, m_fp );
13262 }
13263 else
13264 {
13265
13266 memcpy( m_memory_buffer+m_memory_buffer_ptr, p, count );
13267 m_memory_buffer_ptr += count;
13268 if ( m_memory_buffer_ptr > m_memory_buffer_size )
13269 m_memory_buffer_size = m_memory_buffer_ptr;
13270 rc = count;
13271 }
13272 }
13273 else
13274 {
13275 rc = fwrite( p, 1, count, m_fp );
13276 }
13277 }
13278 return rc;
13279 }
13280
13281 bool ON_BinaryFile::Flush()
13282 {
13283 bool rc = true;
13284 if ( m_fp )
13285 {
13286 if ( m_memory_buffer && m_memory_buffer_size > 0 )
13287 {
13288 rc = ( m_memory_buffer_size == fwrite( m_memory_buffer, 1, m_memory_buffer_size, m_fp ));
13289 if ( rc && m_memory_buffer_ptr != m_memory_buffer_size )
13290 {
13291
13292 int delta = (m_memory_buffer_ptr >= m_memory_buffer_size)
13293 ? ((int)(m_memory_buffer_ptr - m_memory_buffer_size))
13294 : -((int)(m_memory_buffer_size - m_memory_buffer_ptr));
13295 if ( !fseek( m_fp, delta, SEEK_CUR ) )
13296 {
13297 rc = false;
13298 }
13299 }
13300 m_memory_buffer_size = 0;
13301 m_memory_buffer_ptr = 0;
13302 }
13303 }
13304 return rc;
13305 }
13306
13307 size_t ON_BinaryFile::CurrentPosition() const
13308 {
13309 size_t offset = 0;
13310
13311 if ( 0 != m_fp )
13312 {
13313
13314 #if defined(ON_COMPILER_MSC)
13315
13316 ON__INT64 offset64 = _ftelli64(m_fp);
13317 if ( offset64 < 0 )
13318 {
13319 ON_ERROR("ON_BinaryFile::CurrentPosition() - _ftelli64() failed");
13320 }
13321 else
13322 {
13323 offset = (size_t)((ON__UINT64)offset64);
13324 }
13325 #else
13326 offset = ftell(m_fp);
13327 #endif
13328
13329 if ( m_memory_buffer && m_memory_buffer_size > 0 )
13330 {
13331 offset += m_memory_buffer_ptr;
13332 }
13333 }
13334 else
13335 {
13336 ON_ERROR("ON_BinaryFile::CurrentPosition() NULL file.");
13337 }
13338
13339 return offset;
13340 }
13341
13342 bool ON_BinaryFile::AtEnd() const
13343 {
13344 bool rc = true;
13345 if ( m_fp ) {
13346 rc = false;
13347 if ( ReadMode() ) {
13348 if ( feof( m_fp ) ) {
13349 rc = true;
13350 }
13351 else
13352 {
13353 int buffer;
13354 fread( &buffer, 1, 1, m_fp );
13355 if ( feof( m_fp ) )
13356 {
13357 rc = true;
13358 }
13359 else
13360 {
13361
13362 fseek( m_fp, -1, SEEK_CUR );
13363 }
13364 }
13365 }
13366 }
13367 return rc;
13368 }
13369
13370 bool ON_BinaryFile::SeekFromCurrentPosition( int offset )
13371 {
13372
13373
13374
13375
13376
13377
13378
13379
13380
13381
13382
13383
13384
13385 bool rc = false;
13386 if ( m_fp )
13387 {
13388 if ( m_memory_buffer &&
13389 ((ON__INT_PTR)m_memory_buffer_ptr)+((ON__INT_PTR)offset) >= 0 &&
13390 m_memory_buffer_ptr+offset <= m_memory_buffer_size ) {
13391 m_memory_buffer_ptr += offset;
13392 rc = true;
13393 }
13394 else
13395 {
13396
13397
13398 Flush();
13399 if ( !fseek(m_fp,offset,SEEK_CUR) )
13400 {
13401 rc = true;
13402 }
13403 else
13404 {
13405 ON_ERROR("ON_BinaryFile::Seek() fseek(,SEEK_CUR) failed.");
13406 }
13407 }
13408 }
13409 return rc;
13410 }
13411
13412 bool ON_BinaryFile::SeekFromEnd( int offset )
13413 {
13414 bool rc = false;
13415 if ( m_fp )
13416 {
13417 Flush();
13418 if ( !fseek(m_fp,offset,SEEK_END) )
13419 {
13420 rc = true;
13421 }
13422 else
13423 {
13424 ON_ERROR("ON_BinaryFile::SeekFromEnd() fseek(,SEEK_END) failed.");
13425 }
13426 }
13427 return rc;
13428 }
13429
13430 bool ON_BinaryFile::SeekFromStart( size_t offset )
13431 {
13432 bool rc = false;
13433 if ( m_fp )
13434 {
13435 Flush();
13436 long loffset = (long)offset;
13437 if ( !fseek(m_fp,loffset,SEEK_SET) )
13438 {
13439 rc = true;
13440 }
13441 else
13442 {
13443 ON_ERROR("ON_BinaryFile::SeekFromStart() fseek(,SEEK_SET) failed.");
13444 }
13445 }
13446 return rc;
13447 }
13448
13449 ON_3dmGoo::ON_3dmGoo()
13450 : m_typecode(0),
13451 m_value(0),
13452 m_goo(0),
13453 m_next_goo(0),
13454 m_prev_goo(0)
13455 {}
13456
13457 ON_3dmGoo::~ON_3dmGoo()
13458 {
13459 if ( m_prev_goo )
13460 m_prev_goo->m_next_goo = m_next_goo;
13461 if ( m_next_goo )
13462 m_next_goo->m_prev_goo = m_prev_goo;
13463 if ( m_goo ) {
13464 onfree(m_goo);
13465 m_goo = 0;
13466 }
13467 }
13468
13469 ON_3dmGoo::ON_3dmGoo( const ON_3dmGoo& src )
13470 : m_typecode(0),
13471 m_value(0),
13472 m_goo(0),
13473 m_next_goo(0),
13474 m_prev_goo(0)
13475 {
13476 *this = src;
13477 }
13478
13479 ON_3dmGoo& ON_3dmGoo::operator=( const ON_3dmGoo& src )
13480 {
13481 if ( this != &src ) {
13482 if ( m_goo ) {
13483 onfree(m_goo);
13484 }
13485 m_typecode = src.m_typecode;
13486 m_value = src.m_value;
13487 m_goo = (m_value > 0 && src.m_goo) ? (unsigned char*)onmemdup( src.m_goo, m_value ) : 0;
13488 }
13489 return *this;
13490 }
13491
13492 void ON_3dmGoo::Dump(ON_TextLog& dump) const
13493 {
13494 dump.Print("typecode = %08x value = %d\n",m_typecode,m_value);
13495 }
13496
13497 bool ON_WriteOneObjectArchive(
13498 ON_BinaryArchive& archive,
13499 int version,
13500 const ON_Object& object
13501 )
13502 {
13503 bool rc = false;
13504
13505 const ON_Object* pObject = &object;
13506 {
13507 if ( ON_BrepEdge::Cast(pObject) )
13508 {
13509
13510 pObject = static_cast<const ON_BrepEdge*>(pObject)->Brep();
13511 }
13512 else if ( ON_BrepTrim::Cast(pObject) )
13513 {
13514 pObject = NULL;
13515 }
13516 else if ( ON_BrepLoop::Cast(pObject) )
13517 {
13518 pObject = static_cast<const ON_BrepLoop*>(pObject)->Brep();
13519 }
13520 else if ( ON_BrepFace::Cast(pObject) )
13521 {
13522
13523 pObject = static_cast<const ON_BrepFace*>(pObject)->Brep();
13524 }
13525 else if ( ON_CurveProxy::Cast(pObject) )
13526 {
13527
13528 pObject = static_cast<const ON_CurveProxy*>(pObject)->ProxyCurve();
13529 }
13530 else if ( ON_SurfaceProxy::Cast(pObject) )
13531 {
13532
13533 pObject = static_cast<const ON_SurfaceProxy*>(pObject)->ProxySurface();
13534 }
13535 }
13536
13537 ON_3dmProperties props;
13538 props.m_RevisionHistory.NewRevision();
13539
13540 ON_3dmSettings settings;
13541
13542
13543
13544
13545
13546 settings.m_ModelUnitsAndTolerances.m_unit_system.m_unit_system = ON::no_unit_system;
13547
13548 ON_Layer layer;
13549 ON_3dmObjectAttributes attributes;
13550
13551
13552 layer.SetLayerIndex(0);
13553 layer.SetLayerName(L"Default");
13554
13555
13556 attributes.m_layer_index = 0;
13557
13558 while(pObject)
13559 {
13560 rc = archive.Write3dmStartSection( version, "Archive created by ON_WriteOneObjectArchive "__DATE__" "__TIME__ );
13561 if ( !rc )
13562 break;
13563
13564 version = archive.Archive3dmVersion();
13565
13566 rc = archive.Write3dmProperties( props );
13567 if ( !rc )
13568 break;
13569
13570 rc = archive.Write3dmSettings( settings );
13571 if ( !rc )
13572 break;
13573
13574 rc = archive.BeginWrite3dmBitmapTable();
13575 if ( !rc )
13576 break;
13577 rc = archive.EndWrite3dmBitmapTable();
13578 if ( !rc )
13579 break;
13580
13581 if ( version >= 4 )
13582 {
13583 rc = archive.BeginWrite3dmTextureMappingTable();
13584 if ( !rc )
13585 break;
13586 rc = archive.EndWrite3dmTextureMappingTable();
13587 if ( !rc )
13588 break;
13589 }
13590
13591 rc = archive.BeginWrite3dmMaterialTable();
13592 if ( !rc )
13593 break;
13594 rc = archive.EndWrite3dmMaterialTable();
13595 if ( !rc )
13596 break;
13597
13598 if ( version >= 4 )
13599 {
13600 rc = archive.BeginWrite3dmLinetypeTable();
13601 if ( !rc )
13602 break;
13603 rc = archive.EndWrite3dmLinetypeTable();
13604 if ( !rc )
13605 break;
13606 }
13607
13608 rc = archive.BeginWrite3dmLayerTable();
13609 if ( !rc )
13610 break;
13611 {
13612 rc = archive.Write3dmLayer(layer);
13613 }
13614 if (!archive.EndWrite3dmLayerTable())
13615 rc = false;
13616 if ( !rc )
13617 break;
13618
13619 rc = archive.BeginWrite3dmGroupTable();
13620 if ( !rc )
13621 break;
13622 rc = archive.EndWrite3dmGroupTable();
13623 if ( !rc )
13624 break;
13625
13626 if ( version >= 3 )
13627 {
13628 rc = archive.BeginWrite3dmFontTable();
13629 if ( !rc )
13630 break;
13631 rc = archive.EndWrite3dmFontTable();
13632 if ( !rc )
13633 break;
13634 }
13635
13636 if ( version >= 3 )
13637 {
13638 rc = archive.BeginWrite3dmDimStyleTable();
13639 if ( !rc )
13640 break;
13641 rc = archive.EndWrite3dmDimStyleTable();
13642 if ( !rc )
13643 break;
13644 }
13645
13646 rc = archive.BeginWrite3dmLightTable();
13647 if ( !rc )
13648 break;
13649 rc = archive.EndWrite3dmLightTable();
13650 if ( !rc )
13651 break;
13652
13653 if ( version >= 4 )
13654 {
13655 rc = archive.BeginWrite3dmHatchPatternTable();
13656 if ( !rc )
13657 break;
13658 rc = archive.EndWrite3dmHatchPatternTable();
13659 if ( !rc )
13660 break;
13661 }
13662
13663 if ( version >= 3 )
13664 {
13665 rc = archive.BeginWrite3dmInstanceDefinitionTable();
13666 if ( !rc )
13667 break;
13668 rc = archive.EndWrite3dmInstanceDefinitionTable();
13669 if ( !rc )
13670 break;
13671 }
13672
13673 rc = archive.BeginWrite3dmObjectTable();
13674 if ( !rc )
13675 break;
13676 {
13677 rc = archive.Write3dmObject( *pObject, &attributes );
13678 }
13679 if ( !archive.EndWrite3dmObjectTable() )
13680 rc = false;
13681 if ( !rc )
13682 break;
13683
13684 if ( version >= 4 )
13685 {
13686 rc = archive.BeginWrite3dmHistoryRecordTable();
13687 if ( !rc )
13688 break;
13689 rc = archive.EndWrite3dmHistoryRecordTable();
13690 if ( !rc )
13691 break;
13692 }
13693
13694 rc = archive.Write3dmEndMark();
13695
13696 break;
13697 }
13698
13699 return rc;
13700 }
13701
13702 static
13703 void Dump3dmChunk_ErrorReportHelper( size_t offset, const char* msg, ON_TextLog& dump )
13704 {
13705 int ioffset = (int)offset;
13706 dump.Print("** ERROR near offset %d ** %s\n",ioffset,msg);
13707 }
13708 static
13709 bool DumpChunk_PrintHeaderInfo( size_t offset0, ON__UINT32 typecode, ON__INT64 big_value, const char* typecode_name, ON_TextLog& dump)
13710 {
13711 bool bShortChunk = (0 != (typecode & TCODE_SHORT));
13712 if ( 0 == typecode_name )
13713 typecode_name = ON_BinaryArchive::TypecodeName(typecode);
13714 if ( 0 == typecode_name )
13715 typecode_name = "unknown tcode";
13716 if ( bShortChunk )
13717 {
13718 dump.Print("%6d: %08X %s: value = %lld (%016llX)\n", offset0, typecode, typecode_name, big_value, big_value );
13719 }
13720 else
13721 {
13722
13723 if ( big_value < 0 )
13724 {
13725 Dump3dmChunk_ErrorReportHelper(offset0,"BeginRead3dmChunk() returned length < 0.",dump);
13726 return false;
13727 }
13728 dump.Print("%6d: %08X %s: length = %lld bytes\n", offset0, typecode, typecode_name, big_value );
13729 }
13730 return true;
13731 }
13732
13733 #define CASEtcode2string(tc) case tc: s = #tc ; break
13734
13735 const char* ON_BinaryArchive::TypecodeName( unsigned int tcode )
13736 {
13737
13738 const char* s;
13739 switch( tcode )
13740 {
13741 CASEtcode2string(TCODE_FONT_TABLE);
13742 CASEtcode2string(TCODE_FONT_RECORD);
13743 CASEtcode2string(TCODE_DIMSTYLE_TABLE);
13744 CASEtcode2string(TCODE_DIMSTYLE_RECORD);
13745 CASEtcode2string(TCODE_INSTANCE_DEFINITION_RECORD);
13746 CASEtcode2string(TCODE_COMMENTBLOCK);
13747 CASEtcode2string(TCODE_ENDOFFILE);
13748 CASEtcode2string(TCODE_ENDOFFILE_GOO);
13749 CASEtcode2string(TCODE_LEGACY_GEOMETRY);
13750 CASEtcode2string(TCODE_OPENNURBS_OBJECT);
13751 CASEtcode2string(TCODE_GEOMETRY);
13752 CASEtcode2string(TCODE_ANNOTATION);
13753 CASEtcode2string(TCODE_DISPLAY);
13754 CASEtcode2string(TCODE_RENDER);
13755 CASEtcode2string(TCODE_INTERFACE);
13756 CASEtcode2string(TCODE_TOLERANCE);
13757 CASEtcode2string(TCODE_TABLE);
13758 CASEtcode2string(TCODE_TABLEREC);
13759 CASEtcode2string(TCODE_USER);
13760 CASEtcode2string(TCODE_SHORT);
13761 CASEtcode2string(TCODE_CRC);
13762 CASEtcode2string(TCODE_ANONYMOUS_CHUNK);
13763 CASEtcode2string(TCODE_MATERIAL_TABLE);
13764 CASEtcode2string(TCODE_LAYER_TABLE);
13765 CASEtcode2string(TCODE_LIGHT_TABLE);
13766 CASEtcode2string(TCODE_OBJECT_TABLE);
13767 CASEtcode2string(TCODE_PROPERTIES_TABLE);
13768 CASEtcode2string(TCODE_SETTINGS_TABLE);
13769 CASEtcode2string(TCODE_BITMAP_TABLE);
13770 CASEtcode2string(TCODE_USER_TABLE);
13771 CASEtcode2string(TCODE_INSTANCE_DEFINITION_TABLE);
13772 CASEtcode2string(TCODE_HATCHPATTERN_TABLE);
13773 CASEtcode2string(TCODE_HATCHPATTERN_RECORD);
13774 CASEtcode2string(TCODE_LINETYPE_TABLE);
13775 CASEtcode2string(TCODE_LINETYPE_RECORD);
13776 CASEtcode2string(TCODE_OBSOLETE_LAYERSET_TABLE);
13777 CASEtcode2string(TCODE_OBSOLETE_LAYERSET_RECORD);
13778 CASEtcode2string(TCODE_TEXTURE_MAPPING_TABLE);
13779 CASEtcode2string(TCODE_TEXTURE_MAPPING_RECORD);
13780 CASEtcode2string(TCODE_HISTORYRECORD_TABLE);
13781 CASEtcode2string(TCODE_HISTORYRECORD_RECORD);
13782 CASEtcode2string(TCODE_ENDOFTABLE);
13783 CASEtcode2string(TCODE_PROPERTIES_REVISIONHISTORY);
13784 CASEtcode2string(TCODE_PROPERTIES_NOTES);
13785 CASEtcode2string(TCODE_PROPERTIES_PREVIEWIMAGE);
13786 CASEtcode2string(TCODE_PROPERTIES_COMPRESSED_PREVIEWIMAGE);
13787 CASEtcode2string(TCODE_PROPERTIES_APPLICATION);
13788 CASEtcode2string(TCODE_PROPERTIES_OPENNURBS_VERSION);
13789 CASEtcode2string(TCODE_SETTINGS_PLUGINLIST);
13790 CASEtcode2string(TCODE_SETTINGS_UNITSANDTOLS);
13791 CASEtcode2string(TCODE_SETTINGS_RENDERMESH);
13792 CASEtcode2string(TCODE_SETTINGS_ANALYSISMESH);
13793 CASEtcode2string(TCODE_SETTINGS_ANNOTATION);
13794 CASEtcode2string(TCODE_SETTINGS_NAMED_CPLANE_LIST);
13795 CASEtcode2string(TCODE_SETTINGS_NAMED_VIEW_LIST);
13796 CASEtcode2string(TCODE_SETTINGS_VIEW_LIST);
13797 CASEtcode2string(TCODE_SETTINGS_CURRENT_LAYER_INDEX);
13798 CASEtcode2string(TCODE_SETTINGS_CURRENT_MATERIAL_INDEX);
13799 CASEtcode2string(TCODE_SETTINGS_CURRENT_COLOR);
13800 CASEtcode2string(TCODE_SETTINGS__NEVER__USE__THIS);
13801 CASEtcode2string(TCODE_SETTINGS_CURRENT_WIRE_DENSITY);
13802 CASEtcode2string(TCODE_SETTINGS_RENDER);
13803 CASEtcode2string(TCODE_SETTINGS_GRID_DEFAULTS);
13804 CASEtcode2string(TCODE_SETTINGS_MODEL_URL);
13805 CASEtcode2string(TCODE_SETTINGS_CURRENT_FONT_INDEX);
13806 CASEtcode2string(TCODE_SETTINGS_CURRENT_DIMSTYLE_INDEX);
13807 CASEtcode2string(TCODE_SETTINGS_ATTRIBUTES);
13808 CASEtcode2string(TCODE_VIEW_RECORD);
13809 CASEtcode2string(TCODE_VIEW_CPLANE);
13810 CASEtcode2string(TCODE_VIEW_VIEWPORT);
13811 CASEtcode2string(TCODE_VIEW_VIEWPORT_USERDATA);
13812 CASEtcode2string(TCODE_VIEW_SHOWCONGRID);
13813 CASEtcode2string(TCODE_VIEW_SHOWCONAXES);
13814 CASEtcode2string(TCODE_VIEW_SHOWWORLDAXES);
13815 CASEtcode2string(TCODE_VIEW_TRACEIMAGE);
13816 CASEtcode2string(TCODE_VIEW_WALLPAPER);
13817 CASEtcode2string(TCODE_VIEW_WALLPAPER_V3);
13818 CASEtcode2string(TCODE_VIEW_TARGET);
13819 CASEtcode2string(TCODE_VIEW_DISPLAYMODE);
13820 CASEtcode2string(TCODE_VIEW_NAME);
13821 CASEtcode2string(TCODE_VIEW_POSITION);
13822 CASEtcode2string(TCODE_VIEW_ATTRIBUTES);
13823 CASEtcode2string(TCODE_BITMAP_RECORD);
13824 CASEtcode2string(TCODE_MATERIAL_RECORD);
13825 CASEtcode2string(TCODE_LAYER_RECORD);
13826 CASEtcode2string(TCODE_LIGHT_RECORD);
13827 CASEtcode2string(TCODE_LIGHT_RECORD_ATTRIBUTES);
13828 CASEtcode2string(TCODE_OBJECT_RECORD_ATTRIBUTES_USERDATA);
13829 CASEtcode2string(TCODE_OBJECT_RECORD_HISTORY);
13830 CASEtcode2string(TCODE_OBJECT_RECORD_HISTORY_HEADER);
13831 CASEtcode2string(TCODE_OBJECT_RECORD_HISTORY_DATA);
13832 CASEtcode2string(TCODE_LIGHT_RECORD_END);
13833 CASEtcode2string(TCODE_USER_TABLE_UUID);
13834 CASEtcode2string(TCODE_USER_TABLE_RECORD_HEADER);
13835 CASEtcode2string(TCODE_USER_RECORD);
13836 CASEtcode2string(TCODE_GROUP_TABLE);
13837 CASEtcode2string(TCODE_GROUP_RECORD);
13838 CASEtcode2string(TCODE_OBJECT_RECORD);
13839 CASEtcode2string(TCODE_OBJECT_RECORD_TYPE);
13840 CASEtcode2string(TCODE_OBJECT_RECORD_ATTRIBUTES);
13841 CASEtcode2string(TCODE_OBJECT_RECORD_END);
13842 CASEtcode2string(TCODE_OPENNURBS_CLASS);
13843 CASEtcode2string(TCODE_OPENNURBS_CLASS_UUID);
13844 CASEtcode2string(TCODE_OPENNURBS_CLASS_DATA);
13845 CASEtcode2string(TCODE_OPENNURBS_CLASS_USERDATA);
13846 CASEtcode2string(TCODE_OPENNURBS_CLASS_USERDATA_HEADER);
13847 CASEtcode2string(TCODE_OPENNURBS_CLASS_END);
13848 CASEtcode2string(TCODE_OPENNURBS_BUFFER);
13849 CASEtcode2string(TCODE_ANNOTATION_SETTINGS);
13850 CASEtcode2string(TCODE_TEXT_BLOCK);
13851 CASEtcode2string(TCODE_ANNOTATION_LEADER);
13852 CASEtcode2string(TCODE_LINEAR_DIMENSION);
13853 CASEtcode2string(TCODE_ANGULAR_DIMENSION);
13854 CASEtcode2string(TCODE_RADIAL_DIMENSION);
13855 CASEtcode2string(TCODE_RHINOIO_OBJECT_NURBS_CURVE);
13856 CASEtcode2string(TCODE_RHINOIO_OBJECT_NURBS_SURFACE);
13857 CASEtcode2string(TCODE_RHINOIO_OBJECT_BREP);
13858 CASEtcode2string(TCODE_RHINOIO_OBJECT_DATA);
13859 CASEtcode2string(TCODE_RHINOIO_OBJECT_END);
13860 CASEtcode2string(TCODE_LEGACY_ASM);
13861 CASEtcode2string(TCODE_LEGACY_PRT);
13862 CASEtcode2string(TCODE_LEGACY_SHL);
13863 CASEtcode2string(TCODE_LEGACY_FAC);
13864 CASEtcode2string(TCODE_LEGACY_BND);
13865 CASEtcode2string(TCODE_LEGACY_TRM);
13866 CASEtcode2string(TCODE_LEGACY_SRF);
13867 CASEtcode2string(TCODE_LEGACY_CRV);
13868 CASEtcode2string(TCODE_LEGACY_SPL);
13869 CASEtcode2string(TCODE_LEGACY_PNT);
13870 CASEtcode2string(TCODE_STUFF);
13871 CASEtcode2string(TCODE_LEGACY_ASMSTUFF);
13872 CASEtcode2string(TCODE_LEGACY_PRTSTUFF);
13873 CASEtcode2string(TCODE_LEGACY_SHLSTUFF);
13874 CASEtcode2string(TCODE_LEGACY_FACSTUFF);
13875 CASEtcode2string(TCODE_LEGACY_BNDSTUFF);
13876 CASEtcode2string(TCODE_LEGACY_TRMSTUFF);
13877 CASEtcode2string(TCODE_LEGACY_SRFSTUFF);
13878 CASEtcode2string(TCODE_LEGACY_CRVSTUFF);
13879 CASEtcode2string(TCODE_LEGACY_SPLSTUFF);
13880 CASEtcode2string(TCODE_LEGACY_PNTSTUFF);
13881 CASEtcode2string(TCODE_RH_POINT);
13882 CASEtcode2string(TCODE_RH_SPOTLIGHT);
13883 CASEtcode2string(TCODE_OLD_RH_TRIMESH);
13884 CASEtcode2string(TCODE_OLD_MESH_VERTEX_NORMALS);
13885 CASEtcode2string(TCODE_OLD_MESH_UV);
13886 CASEtcode2string(TCODE_OLD_FULLMESH);
13887 CASEtcode2string(TCODE_MESH_OBJECT);
13888 CASEtcode2string(TCODE_COMPRESSED_MESH_GEOMETRY);
13889 CASEtcode2string(TCODE_ANALYSIS_MESH);
13890 CASEtcode2string(TCODE_NAME);
13891 CASEtcode2string(TCODE_VIEW);
13892 CASEtcode2string(TCODE_CPLANE);
13893 CASEtcode2string(TCODE_NAMED_CPLANE);
13894 CASEtcode2string(TCODE_NAMED_VIEW);
13895 CASEtcode2string(TCODE_VIEWPORT);
13896 CASEtcode2string(TCODE_SHOWGRID);
13897 CASEtcode2string(TCODE_SHOWGRIDAXES);
13898 CASEtcode2string(TCODE_SHOWWORLDAXES);
13899 CASEtcode2string(TCODE_VIEWPORT_POSITION);
13900 CASEtcode2string(TCODE_VIEWPORT_TRACEINFO);
13901 CASEtcode2string(TCODE_SNAPSIZE);
13902 CASEtcode2string(TCODE_NEAR_CLIP_PLANE);
13903 CASEtcode2string(TCODE_HIDE_TRACE);
13904 CASEtcode2string(TCODE_NOTES);
13905 CASEtcode2string(TCODE_UNIT_AND_TOLERANCES);
13906 CASEtcode2string(TCODE_MAXIMIZED_VIEWPORT);
13907 CASEtcode2string(TCODE_VIEWPORT_WALLPAPER);
13908 CASEtcode2string(TCODE_SUMMARY);
13909 CASEtcode2string(TCODE_BITMAPPREVIEW);
13910 CASEtcode2string(TCODE_VIEWPORT_DISPLAY_MODE);
13911 CASEtcode2string(TCODE_LAYERTABLE);
13912 CASEtcode2string(TCODE_LAYERREF);
13913 CASEtcode2string(TCODE_XDATA);
13914 CASEtcode2string(TCODE_RGB);
13915 CASEtcode2string(TCODE_TEXTUREMAP);
13916 CASEtcode2string(TCODE_BUMPMAP);
13917 CASEtcode2string(TCODE_TRANSPARENCY);
13918 CASEtcode2string(TCODE_DISP_AM_RESOLUTION);
13919 CASEtcode2string(TCODE_RGBDISPLAY);
13920 CASEtcode2string(TCODE_RENDER_MATERIAL_ID);
13921 CASEtcode2string(TCODE_LAYER);
13922 CASEtcode2string(TCODE_LAYER_OBSELETE_1);
13923 CASEtcode2string(TCODE_LAYER_OBSELETE_2);
13924 CASEtcode2string(TCODE_LAYER_OBSELETE_3);
13925 CASEtcode2string(TCODE_LAYERON);
13926 CASEtcode2string(TCODE_LAYERTHAWED);
13927 CASEtcode2string(TCODE_LAYERLOCKED);
13928 CASEtcode2string(TCODE_LAYERVISIBLE);
13929 CASEtcode2string(TCODE_LAYERPICKABLE);
13930 CASEtcode2string(TCODE_LAYERSNAPABLE);
13931 CASEtcode2string(TCODE_LAYERRENDERABLE);
13932 CASEtcode2string(TCODE_LAYERSTATE);
13933 CASEtcode2string(TCODE_LAYERINDEX);
13934 CASEtcode2string(TCODE_LAYERMATERIALINDEX);
13935 CASEtcode2string(TCODE_RENDERMESHPARAMS);
13936 CASEtcode2string(TCODE_DISP_CPLINES);
13937 CASEtcode2string(TCODE_DISP_MAXLENGTH);
13938 CASEtcode2string(TCODE_CURRENTLAYER);
13939 CASEtcode2string(TCODE_LAYERNAME);
13940 CASEtcode2string(TCODE_LEGACY_TOL_FIT);
13941 CASEtcode2string(TCODE_LEGACY_TOL_ANGLE);
13942 CASEtcode2string(TCODE_DICTIONARY);
13943 CASEtcode2string(TCODE_DICTIONARY_ID);
13944 CASEtcode2string(TCODE_DICTIONARY_ENTRY);
13945 CASEtcode2string(TCODE_DICTIONARY_END);
13946 default:
13947
13948 s = 0;
13949 break;
13950 }
13951 return s;
13952 }
13953
13954 #undef CASEtcode2string
13955
13956 char* ON_BinaryArchive::ON_TypecodeParse( unsigned int tcode, char* typecode_name, size_t max_length )
13957 {
13958 char* s;
13959 const char* sub_name;
13960 const char* h = "0123456789ABCDEF";
13961 char c, c0;
13962 size_t slen;
13963
13964 if ( !typecode_name || max_length <= 0 )
13965 return 0;
13966 memset(typecode_name,0,max_length*sizeof(typecode_name[0]));
13967 slen = max_length-1;
13968 if ( slen <= 0 )
13969 return 0;
13970
13971 sub_name = ON_BinaryArchive::TypecodeName(tcode);
13972 if ( 0 != sub_name && 0 != sub_name[0] )
13973 {
13974 c0 = *sub_name++;
13975 s = typecode_name+1;
13976 slen--;
13977 while ( *sub_name )
13978 {
13979 if ( slen <= 0 )
13980 return 0;
13981 *s++ = *sub_name++;
13982 slen--;
13983 }
13984 typecode_name[0] = c0;
13985 return typecode_name;
13986 }
13987
13988 sub_name = ON_BinaryArchive::TypecodeName( tcode & 0x7FFF0000 );
13989 if ( !sub_name || 0 == sub_name[0] )
13990 return 0;
13991
13992 c0 = *sub_name++;
13993 s = typecode_name+1;
13994 slen--;
13995
13996 while ( *sub_name )
13997 {
13998 if ( slen <= 0 )
13999 return 0;
14000 *s++ = *sub_name++;
14001 slen--;
14002 }
14003
14004 sub_name = ON_BinaryArchive::TypecodeName( tcode & TCODE_SHORT );
14005 if ( sub_name )
14006 {
14007 if ( slen <= 0 ) return 0; *s++ = ' '; slen--;
14008 if ( slen <= 0 ) return 0; *s++ = '|'; slen--;
14009 if ( slen <= 0 ) return 0; *s++ = ' '; slen--;
14010 while ( *sub_name )
14011 {
14012 if ( slen <= 0 )
14013 return 0;
14014 *s++ = *sub_name++;
14015 slen--;
14016 }
14017 }
14018
14019 sub_name = ON_BinaryArchive::TypecodeName( tcode & TCODE_CRC );
14020 if ( sub_name )
14021 {
14022 if ( slen <= 0 ) return 0; *s++ = ' '; slen--;
14023 if ( slen <= 0 ) return 0; *s++ = '|'; slen--;
14024 if ( slen <= 0 ) return 0; *s++ = ' '; slen--;
14025 while ( *sub_name )
14026 {
14027 if ( slen <= 0 )
14028 return 0;
14029 *s++ = *sub_name++;
14030 slen--;
14031 }
14032 }
14033
14034 sub_name = ON_BinaryArchive::TypecodeName( tcode & 0x7FFF );
14035 if ( sub_name )
14036 {
14037 if ( slen <= 0 ) return 0; *s++ = ' '; slen--;
14038 if ( slen <= 0 ) return 0; *s++ = '|'; slen--;
14039 if ( slen <= 0 ) return 0; *s++ = ' '; slen--;
14040 while ( *sub_name )
14041 {
14042 if ( slen <= 0 )
14043 return 0;
14044 *s++ = *sub_name++;
14045 slen--;
14046 }
14047 }
14048 else
14049 {
14050 if ( slen <= 0 ) return 0; *s++ = ' '; slen--;
14051 if ( slen <= 0 ) return 0; *s++ = '|'; slen--;
14052 if ( slen <= 0 ) return 0; *s++ = ' '; slen--;
14053 if ( slen <= 0 ) return 0; *s++ = '0'; slen--;
14054 if ( slen <= 0 ) return 0; *s++ = 'x'; slen--;
14055 c = h[((tcode & 0x7000) / 0x1000) & 0xF];
14056 if ( slen > 0 ) {*s++ = c; slen--;}
14057 c = h[((tcode & 0xF00) / 0x100) & 0xF];
14058 if ( slen > 0 ) {*s++ = c; slen--;}
14059 c = h[((tcode & 0xF0) / 0x10) & 0xF];
14060 if ( slen > 0 ) {*s++ = c; slen--;}
14061 c = h[tcode & 0xF];
14062 if ( slen > 0 ) {*s++ = c; slen--;}
14063 }
14064
14065 *typecode_name = c0;
14066
14067 return typecode_name;
14068 }
14069
14070 static
14071 bool Dump3dmChunk_EndReadChunkHelper( ON_BinaryArchive& file, size_t offset0, ON__UINT32 tcode, ON__INT64 big_value, ON_TextLog& dump )
14072 {
14073 const bool bShortChunk = (0 != (tcode & TCODE_SHORT));
14074 const size_t offset1 = file.CurrentPosition();
14075 bool rc = file.EndRead3dmChunk();
14076 if ( !rc )
14077 {
14078 Dump3dmChunk_ErrorReportHelper(offset1,"EndRead3dmChunk() failed.",dump);
14079 }
14080 else if (!bShortChunk)
14081 {
14082
14083
14084 ON__INT64 sizeof_crc = (0 != (TCODE_CRC & tcode)) ? 4 : 0;
14085 ON__INT64 sizeof_chunk_header = 4+file.SizeofChunkLength();
14086 ON__INT64 delta = (offset1 > offset0)
14087 ? ((ON__INT64)(offset1 - offset0))
14088 : -((ON__INT64)(offset0 - offset1));
14089 const ON__INT64 extra = big_value - (delta+sizeof_crc-sizeof_chunk_header);
14090 if ( extra < 0 )
14091 {
14092 Dump3dmChunk_ErrorReportHelper(offset0,"Read beyond end of chunk.",dump);
14093 rc = false;
14094 }
14095 }
14096 return rc;
14097 }
14098
14099 static
14100 bool Dump3dmChunk_UserDataHeaderHelper( size_t offset, ON_BinaryArchive& file,
14101 int major_userdata_version, int minor_userdata_version,
14102 ON_TextLog& dump )
14103 {
14104
14105
14106
14107 ON_UUID userdata_classid = ON_nil_uuid;
14108 ON_UUID userdata_itemid = ON_nil_uuid;
14109 ON_UUID userdata_appid = ON_nil_uuid;
14110 int userdata_copycount = -1;
14111 ON_Xform userdata_xform;
14112 bool bLastSavedAsGoo = false;
14113 int ud_archive_3dm_version = 0;
14114 int ud_archive_opennurbs_version = 0;
14115
14116 bool rc = false;
14117 bool bCallEndRead3dmChunk = false;
14118
14119 ON__UINT32 tcode = 0;
14120 ON__INT64 big_value = 0;
14121 const size_t offset0 = file.CurrentPosition();
14122
14123 for(;;)
14124 {
14125 if ( 2 == major_userdata_version )
14126 {
14127 rc = file.PeekAt3dmBigChunkType(&tcode,&big_value);
14128 if ( !rc )
14129 {
14130 Dump3dmChunk_ErrorReportHelper(offset,"Unable to find the TCODE_OPENNURBS_CLASS_USERDATA_HEADER chunk header in a TCODE_OPENNURBS_CLASS_USERDATA chunk.",dump);
14131 break;
14132 }
14133 if ( TCODE_OPENNURBS_CLASS_USERDATA_HEADER != tcode )
14134 {
14135 Dump3dmChunk_ErrorReportHelper(offset,"Unable to find the TCODE_OPENNURBS_CLASS_USERDATA_HEADER chunk header in a TCODE_OPENNURBS_CLASS_USERDATA chunk.",dump);
14136 rc = false;
14137 break;
14138 }
14139 rc = file.BeginRead3dmBigChunk(&tcode,&big_value);
14140 if ( !rc )
14141 {
14142 Dump3dmChunk_ErrorReportHelper(offset,"Unable to read the TCODE_OPENNURBS_CLASS_USERDATA_HEADER chunk header in a TCODE_OPENNURBS_CLASS_USERDATA chunk.",dump);
14143 break;
14144 }
14145 if ( TCODE_OPENNURBS_CLASS_USERDATA_HEADER != tcode )
14146 {
14147 Dump3dmChunk_ErrorReportHelper(offset,"Missing TCODE_OPENNURBS_CLASS_USERDATA_HEADER chunk header in a TCODE_OPENNURBS_CLASS_USERDATA chunk.",dump);
14148 Dump3dmChunk_EndReadChunkHelper(file,offset0,tcode,big_value,dump);
14149 rc = false;
14150 break;
14151 }
14152 bCallEndRead3dmChunk = true;
14153 }
14154
14155 rc = file.ReadUuid( userdata_classid );
14156 if ( !rc )
14157 {
14158 Dump3dmChunk_ErrorReportHelper(offset,"ReadUuid() failed to read the user data class id.",dump);
14159 break;
14160 }
14161
14162 dump.Print("UserData class id = ");
14163 dump.Print( userdata_classid );
14164 const ON_ClassId* pUserDataClassId = ON_ClassId::ClassId(userdata_classid);
14165 if ( pUserDataClassId )
14166 {
14167 const char* sClassName = pUserDataClassId->ClassName();
14168 if ( sClassName )
14169 {
14170 dump.Print(" (%s)",sClassName);
14171 }
14172 }
14173 dump.Print("\n");
14174
14175 rc = file.ReadUuid( userdata_itemid );
14176 if ( !rc )
14177 {
14178 Dump3dmChunk_ErrorReportHelper(offset,"ReadUuid() failed to read the user data item id.",dump);
14179 break;
14180 }
14181 dump.Print("UserData item id = ");
14182 dump.Print( userdata_itemid );
14183 dump.Print("\n");
14184
14185 rc = file.ReadInt( &userdata_copycount );
14186 if ( !rc )
14187 {
14188 Dump3dmChunk_ErrorReportHelper(offset,"ReadInt() failed to read the user data copy count.",dump);
14189 break;
14190 }
14191 dump.Print("UserData copy count = %d\n",userdata_copycount);
14192
14193 rc = file.ReadXform( userdata_xform );
14194 if ( !rc )
14195 {
14196 Dump3dmChunk_ErrorReportHelper(offset,"ReadXform() failed to read the user data xform.",dump);
14197 break;
14198 }
14199
14200 if ( 2 != major_userdata_version )
14201 break;
14202 if ( minor_userdata_version < 1 )
14203 break;
14204 rc = file.ReadUuid( userdata_appid );
14205 if ( !rc)
14206 {
14207 Dump3dmChunk_ErrorReportHelper(offset,"ReadUuid() failed to read the user data app plug-in id.",dump);
14208 break;
14209 }
14210 dump.Print("UserData app plug-in id = ");
14211 dump.Print( userdata_appid );
14212 dump.Print("\n");
14213 if ( minor_userdata_version < 2 )
14214 break;
14215 rc = file.ReadBool(&bLastSavedAsGoo);
14216 if (!rc)
14217 {
14218 Dump3dmChunk_ErrorReportHelper(offset,"ReadBool() failed to read the user data header bSavedAsGoo value.",dump);
14219 break;
14220 }
14221 rc = file.ReadInt( &ud_archive_3dm_version );
14222 if (!rc)
14223 {
14224 Dump3dmChunk_ErrorReportHelper(offset,"ReadBool() failed to read the user data header bSavedAsGoo value.",dump);
14225 break;
14226 }
14227 rc = file.ReadInt( &ud_archive_opennurbs_version );
14228 if (!rc)
14229 {
14230 Dump3dmChunk_ErrorReportHelper(offset,"ReadBool() failed to read the user data header bSavedAsGoo value.",dump);
14231 break;
14232 }
14233 if ( bLastSavedAsGoo )
14234 dump.Print("Userdata originally written by opennurbs %d in 3dm version %d and saved as goo in this file.\n",ud_archive_opennurbs_version,ud_archive_3dm_version);
14235 else
14236 dump.Print("Userdata written by opennurbs %d in 3dm version %d.\n",ud_archive_opennurbs_version,ud_archive_3dm_version);
14237
14238 break;
14239 }
14240
14241 if ( bCallEndRead3dmChunk )
14242 {
14243 if (!Dump3dmChunk_EndReadChunkHelper(file,offset0,tcode,big_value,dump))
14244 {
14245 if (rc)
14246 {
14247 Dump3dmChunk_ErrorReportHelper(offset,"EndRead3dmChunk() failed to close the TCODE_OPENNURBS_CLASS_USERDATA_HEADER chunk.",dump);
14248 }
14249 rc = false;
14250 }
14251 }
14252
14253 return rc;
14254 }
14255
14256
14257 unsigned int
14258 ON_BinaryArchive::Dump3dmChunk( ON_TextLog& dump, int recursion_depth )
14259 {
14260
14261 const char* typecode_name = 0;
14262 bool bShortChunk = false;
14263 const size_t offset0 = CurrentPosition();
14264 unsigned int typecode = 0;
14265 ON__INT64 big_value;
14266 bool rc = BeginRead3dmBigChunk( &typecode, &big_value );
14267 if (!rc)
14268 {
14269 Dump3dmChunk_ErrorReportHelper(offset0,"BeginRead3dmChunk() failed.",dump);
14270 }
14271 else
14272 {
14273 if ( 0 == typecode )
14274 {
14275 Dump3dmChunk_ErrorReportHelper(offset0,"BeginRead3dmChunk() returned typecode = 0.",dump);
14276 EndRead3dmChunk();
14277 return 0;
14278 }
14279 else {
14280 if ( 0 == recursion_depth )
14281 {
14282 dump.Print("\n");
14283 }
14284
14286 typecode_name = ON_BinaryArchive::TypecodeName(typecode);
14287 bShortChunk = (0 != (typecode & TCODE_SHORT));
14288 if ( !DumpChunk_PrintHeaderInfo(offset0,typecode,big_value,typecode_name,dump) )
14289 {
14290 EndRead3dmChunk();
14291 return 0;
14292 }
14293
14294 int major_userdata_version = -1;
14295 int minor_userdata_version = -1;
14296
14297 switch( typecode )
14298 {
14299 case TCODE_PROPERTIES_TABLE:
14300 case TCODE_SETTINGS_TABLE:
14301 case TCODE_BITMAP_TABLE:
14302 case TCODE_MATERIAL_TABLE:
14303 case TCODE_LAYER_TABLE:
14304 case TCODE_GROUP_TABLE:
14305 case TCODE_LIGHT_TABLE:
14306 case TCODE_FONT_TABLE:
14307 case TCODE_DIMSTYLE_TABLE:
14308 case TCODE_HATCHPATTERN_TABLE:
14309 case TCODE_LINETYPE_TABLE:
14310 case TCODE_TEXTURE_MAPPING_TABLE:
14311 case TCODE_HISTORYRECORD_TABLE:
14312 case TCODE_USER_TABLE:
14313 case TCODE_INSTANCE_DEFINITION_TABLE:
14314 case TCODE_OBJECT_TABLE:
14315
14316 {
14317 dump.PushIndent();
14318 unsigned int record_typecode = 0;
14319 for (;;) {
14320 record_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14321 if ( !record_typecode ) {
14322 break;
14323 }
14324 if ( TCODE_ENDOFTABLE == record_typecode ) {
14325 break;
14326 }
14327 }
14328 dump.PopIndent();
14329 }
14330 break;
14331
14332 case TCODE_PROPERTIES_OPENNURBS_VERSION:
14333 {
14334 dump.PushIndent();
14335 dump.Print("Version of opennurbs that wrote this file: %lld\n",big_value);
14336 dump.PopIndent();
14337 if ( 0 == m_3dm_opennurbs_version && big_value > 0 && big_value <= 299999999 )
14338 ON_SetBinaryArchiveOpenNURBSVersion(*this,(ON__INT32)big_value);
14339 }
14340 break;
14341
14342 case TCODE_BITMAP_RECORD:
14343 {
14344 dump.PushIndent();
14345 unsigned int bitmap_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14346 if ( 0 == typecode )
14347 typecode = bitmap_chunk_typecode;
14348 dump.PopIndent();
14349 }
14350 break;
14351
14352 case TCODE_MATERIAL_RECORD:
14353 {
14354 dump.PushIndent();
14355 unsigned int material_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14356 if ( 0 == typecode )
14357 typecode = material_chunk_typecode;
14358 dump.PopIndent();
14359 }
14360 break;
14361
14362 case TCODE_LAYER_RECORD:
14363 {
14364 dump.PushIndent();
14365 unsigned int material_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14366 if ( 0 == typecode )
14367 typecode = material_chunk_typecode;
14368 dump.PopIndent();
14369 }
14370 break;
14371
14372 case TCODE_GROUP_RECORD:
14373 {
14374 dump.PushIndent();
14375 unsigned int group_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14376 if ( 0 == typecode )
14377 typecode = group_chunk_typecode;
14378 dump.PopIndent();
14379 }
14380 break;
14381
14382 case TCODE_FONT_RECORD:
14383 {
14384 dump.PushIndent();
14385 unsigned int font_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14386 if ( 0 == typecode )
14387 typecode = font_chunk_typecode;
14388 dump.PopIndent();
14389 }
14390 break;
14391
14392 case TCODE_DIMSTYLE_RECORD:
14393 {
14394 dump.PushIndent();
14395 unsigned int dimstyle_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14396 if ( 0 == typecode )
14397 typecode = dimstyle_chunk_typecode;
14398 dump.PopIndent();
14399 }
14400 break;
14401
14402 case TCODE_LIGHT_RECORD:
14403 {
14404 dump.PushIndent();
14405 unsigned int light_chunk_typecode = 0;
14406 for (;;) {
14407 light_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14408 if ( !light_chunk_typecode ) {
14409 break;
14410 }
14411 if ( TCODE_LIGHT_RECORD_END == light_chunk_typecode ) {
14412 break;
14413 }
14414 switch( light_chunk_typecode ) {
14415
14416 case TCODE_LIGHT_RECORD_ATTRIBUTES:
14417 case TCODE_LIGHT_RECORD_ATTRIBUTES_USERDATA:
14418 case TCODE_OPENNURBS_CLASS:
14419 break;
14420 default:
14421 {
14422 Dump3dmChunk_ErrorReportHelper(offset0,"Rogue chunk in light record.",dump);
14423 }
14424 }
14425 }
14426 dump.PopIndent();
14427 }
14428 break;
14429
14430 case TCODE_TEXTURE_MAPPING_RECORD:
14431 {
14432 dump.PushIndent();
14433 unsigned int mapping_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14434 if ( !typecode )
14435 typecode = mapping_chunk_typecode;
14436 dump.PopIndent();
14437 }
14438 break;
14439
14440 case TCODE_HISTORYRECORD_RECORD:
14441 {
14442 dump.PushIndent();
14443 unsigned int history_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14444 if ( !typecode )
14445 typecode = history_chunk_typecode;
14446 dump.PopIndent();
14447 }
14448 break;
14449
14450 case TCODE_HATCHPATTERN_RECORD:
14451 {
14452 dump.PushIndent();
14453 unsigned int hatch_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14454 if ( !typecode )
14455 typecode = hatch_chunk_typecode;
14456 dump.PopIndent();
14457 }
14458 break;
14459
14460 case TCODE_INSTANCE_DEFINITION_RECORD:
14461 {
14462 dump.PushIndent();
14463 unsigned int idef_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14464 if ( 0 == typecode )
14465 typecode = idef_chunk_typecode;
14466 dump.PopIndent();
14467 }
14468 break;
14469
14470 case TCODE_OBJECT_RECORD:
14471 {
14472 dump.PushIndent();
14473 unsigned int object_chunk_typecode = 0;
14474 for (;;) {
14475 object_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14476 if ( !object_chunk_typecode ) {
14477 break;
14478 }
14479 if ( TCODE_OBJECT_RECORD_END == object_chunk_typecode ) {
14480 break;
14481 }
14482 switch( object_chunk_typecode ) {
14483 case TCODE_OBJECT_RECORD_TYPE:
14484 case TCODE_OBJECT_RECORD_ATTRIBUTES:
14485 case TCODE_OBJECT_RECORD_ATTRIBUTES_USERDATA:
14486 case TCODE_OPENNURBS_CLASS:
14487 break;
14488 default:
14489 {
14490 Dump3dmChunk_ErrorReportHelper(offset0,"Rogue chunk in object record.",dump);
14491 }
14492 }
14493 }
14494 dump.PopIndent();
14495 }
14496 break;
14497
14498 case TCODE_OBJECT_RECORD_ATTRIBUTES:
14499 {
14500 dump.PushIndent();
14501 if ( big_value < 14 )
14502 {
14503 Dump3dmChunk_ErrorReportHelper(offset0,"Length of chunk is too small. Should be >= 14.",dump);
14504 }
14505 else
14506 {
14507 ON_UUID uuid = ON_nil_uuid;
14508 int layer_index = -99;
14509 int mj = -1;
14510 int mn = -1;
14511 if ( !Read3dmChunkVersion(&mj,&mn))
14512 {
14513 Dump3dmChunk_ErrorReportHelper(offset0,"Read3dmChunkVersion() failed.",dump);
14514 }
14515 else if (!ReadUuid(uuid))
14516 {
14517 Dump3dmChunk_ErrorReportHelper(offset0,"ReadUuid() failed.",dump);
14518 }
14519 else if ( !ReadInt(&layer_index) )
14520 {
14521 Dump3dmChunk_ErrorReportHelper(offset0,"ReadInt() failed to read layer index.",dump);
14522 }
14523 else
14524 {
14525 dump.Print("Rhino object uuid: ");
14526 dump.Print(uuid);
14527 dump.Print("\n");
14528 dump.Print("layer index: %d\n",layer_index);
14529 }
14530 }
14531 dump.PopIndent();
14532 }
14533 break;
14534
14535 case TCODE_OPENNURBS_CLASS:
14536 {
14537 dump.PushIndent();
14538 unsigned int opennurbs_object_chunk_typecode = 0;
14539 for (;;) {
14540 opennurbs_object_chunk_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14541 if ( !opennurbs_object_chunk_typecode ) {
14542 break;
14543 }
14544 if ( TCODE_OPENNURBS_CLASS_END == opennurbs_object_chunk_typecode ) {
14545 break;
14546 }
14547 switch( opennurbs_object_chunk_typecode )
14548 {
14549 case TCODE_OPENNURBS_CLASS_UUID:
14550 break;
14551 case TCODE_OPENNURBS_CLASS_DATA:
14552 break;
14553 case TCODE_OPENNURBS_CLASS_USERDATA:
14554 break;
14555 default:
14556 {
14557 Dump3dmChunk_ErrorReportHelper(offset0,"Rogue chunk in OpenNURBS class record.",dump);
14558 }
14559 }
14560 }
14561 dump.PopIndent();
14562 }
14563 break;
14564
14565 case TCODE_OPENNURBS_CLASS_USERDATA:
14566 {
14567 if ( !Read3dmChunkVersion(&major_userdata_version, &minor_userdata_version ) )
14568 {
14569 Dump3dmChunk_ErrorReportHelper(offset0,"Read3dmChunkVersion() failed to read TCODE_OPENNURBS_CLASS_USERDATA chunk version.",dump);
14570 }
14571 else
14572 {
14573 dump.PushIndent();
14574 dump.Print("UserData chunk version: %d.%d\n",
14575 major_userdata_version,
14576 minor_userdata_version
14577 );
14578 if ( 1 == major_userdata_version || 2 == major_userdata_version )
14579 {
14580 const size_t userdata_header_offset = CurrentPosition();
14581 switch ( major_userdata_version )
14582 {
14583 case 1:
14584 case 2:
14585 {
14586
14587
14588
14589
14590
14591 if ( Dump3dmChunk_UserDataHeaderHelper(
14592 userdata_header_offset, *this,
14593 major_userdata_version, minor_userdata_version,
14594 dump )
14595 )
14596 {
14597
14598 int anon_typecode = Dump3dmChunk( dump, recursion_depth+1 );
14599 if ( TCODE_ANONYMOUS_CHUNK != anon_typecode )
14600 {
14601 Dump3dmChunk_ErrorReportHelper( offset0,"Userdata Expected a TCODE_ANONYMOUS_CHUNK chunk.",dump);
14602 }
14603 }
14604 }
14605 break;
14606 default:
14607 if ( major_userdata_version < 3 )
14608 {
14609 }
14610 else
14611 {
14612 dump.Print("New user data format created after this diagnostic tool was written.\n");
14613 }
14614 break;
14615 }
14616 }
14617
14618 dump.PopIndent();
14619 }
14620 }
14621 break;
14622
14623 case TCODE_OPENNURBS_CLASS_UUID:
14624 case TCODE_USER_TABLE_UUID:
14625 {
14626 dump.PushIndent();
14627 ON_UUID uuid = ON_nil_uuid;
14628 const ON_ClassId* pClassId = 0;
14629 if ( !ReadUuid( uuid ) ) {
14630 Dump3dmChunk_ErrorReportHelper(offset0,"ReadUuid() failed.",dump);
14631 }
14632 else
14633 {
14634 if ( typecode == TCODE_OPENNURBS_CLASS_UUID )
14635 {
14636 dump.Print("OpenNURBS class id = ");
14637 pClassId = ON_ClassId::ClassId(uuid);
14638 }
14639 else if ( typecode == TCODE_USER_TABLE_UUID )
14640 {
14641 dump.Print("User table id = ");
14642 }
14643 else {
14644 dump.Print("UUID = ");
14645 }
14646 dump.Print( uuid );
14647 if ( pClassId )
14648 {
14649 const char* sClassName = pClassId->ClassName();
14650 if ( sClassName )
14651 {
14652 dump.Print(" (%s)",sClassName);
14653 }
14654 }
14655 dump.Print("\n");
14656 }
14657
14658 dump.PopIndent();
14659 }
14660 break;
14661
14662 case TCODE_OPENNURBS_CLASS_USERDATA_HEADER:
14663 {
14664
14665 Dump3dmChunk_ErrorReportHelper(offset0,"Encountered TCODE_OPENNURBS_CLASS_USERDATA_HEADER chunk outside a TCODE_OPENNURBS_CLASS_USERDATA chunk.",dump);
14666 }
14667 break;
14668
14669 case TCODE_ENDOFFILE:
14670 case TCODE_ENDOFFILE_GOO:
14671 {
14672 dump.PushIndent();
14673 if ( big_value < 4 ) {
14674 Dump3dmChunk_ErrorReportHelper(offset0,"TCODE_ENDOFFILE chunk withlength < 4.",dump);
14675 }
14676 else {
14677 ON__UINT64 sizeof_file = 0;
14678 ReadEOFSizeOfFile(&sizeof_file);
14679 dump.Print("current position = %d stored size = %llu\n",
14680 CurrentPosition(),
14681 sizeof_file
14682 );
14683 }
14684 dump.PopIndent();
14685 }
14686 break;
14687
14688 }
14689 }
14690
14691 const size_t offset1 = CurrentPosition();
14692 if ( !EndRead3dmChunk(true) )
14693 {
14694 Dump3dmChunk_ErrorReportHelper(offset1,"EndRead3dmChunk() failed.",dump);
14695 rc = false;
14696 }
14697 else if (!bShortChunk)
14698 {
14699 ON__INT64 delta = (offset1 > offset0)
14700 ? ((ON__INT64)(offset1 - offset0))
14701 : -((ON__INT64)(offset0 - offset1));
14702 const ON__INT64 extra = big_value - (delta-4-SizeofChunkLength());
14703 if ( extra < 0 )
14704 {
14705 Dump3dmChunk_ErrorReportHelper(offset0,"Read beyond end of chunk.",dump);
14706 }
14707 }
14708 }
14709 return typecode;
14710 }
14711
14712
14713
14714 ON_Read3dmBufferArchive::ON_Read3dmBufferArchive(
14715 size_t sizeof_buffer,
14716 const void* buffer,
14717 bool bCopyBuffer,
14718 int archive_3dm_version,
14719 int archive_opennurbs_version
14720 )
14721 : ON_BinaryArchive(ON::read3dm)
14722 , m_p(0)
14723 , m_buffer(0)
14724 , m_sizeof_buffer(0)
14725 , m_buffer_position(0)
14726 , m_reserved1(0)
14727 , m_reserved2(0)
14728 , m_reserved3(0)
14729 , m_reserved4(0)
14730 {
14731 if ( sizeof_buffer > 0 && 0 != buffer )
14732 {
14733 if ( bCopyBuffer )
14734 {
14735 m_p = onmalloc(sizeof_buffer);
14736 if ( 0 != m_p )
14737 memcpy(m_p,buffer,sizeof_buffer);
14738 m_buffer = (const unsigned char*)m_p;
14739 }
14740 else
14741 {
14742 m_buffer = (const unsigned char*)buffer;
14743 }
14744 if ( m_buffer )
14745 {
14746 m_sizeof_buffer = sizeof_buffer;
14747 SetArchive3dmVersion(archive_3dm_version);
14748 ON_SetBinaryArchiveOpenNURBSVersion(*this,archive_opennurbs_version);
14749 }
14750 }
14751 }
14752
14753 ON_Read3dmBufferArchive::~ON_Read3dmBufferArchive()
14754 {
14755 if ( m_p )
14756 onfree(m_p);
14757 }
14758
14759
14760 size_t ON_Read3dmBufferArchive::CurrentPosition() const
14761 {
14762 return m_buffer_position;
14763 }
14764
14765 bool ON_Read3dmBufferArchive::SeekFromCurrentPosition( int offset )
14766 {
14767 bool rc = false;
14768 if ( m_buffer )
14769 {
14770 if (offset >= 0 )
14771 {
14772 m_buffer_position += offset;
14773 rc = true;
14774 }
14775 else if ( size_t(-offset) <= m_buffer_position )
14776 {
14777 m_buffer_position -= (size_t(-offset));
14778 rc = true;
14779 }
14780 }
14781 return rc;
14782 }
14783
14784 bool ON_Read3dmBufferArchive::SeekFromStart( size_t offset )
14785 {
14786 bool rc = false;
14787 if ( m_buffer )
14788 {
14789 if ( offset > 0 )
14790 m_buffer_position = offset;
14791 else
14792 m_buffer_position = 0;
14793 rc = true;
14794 }
14795 return rc;
14796 }
14797
14798 bool ON_Read3dmBufferArchive::AtEnd() const
14799 {
14800 return (m_buffer_position >= m_sizeof_buffer) ? true : false;
14801 }
14802
14803 size_t ON_Read3dmBufferArchive::Read( size_t count, void* buffer )
14804 {
14805 if ( count <= 0 || 0 == buffer )
14806 return 0;
14807
14808 size_t maxcount = ( m_sizeof_buffer > m_buffer_position )
14809 ? (m_sizeof_buffer - m_buffer_position)
14810 : 0;
14811 if ( count > maxcount )
14812 count = maxcount;
14813
14814 if ( count > 0 )
14815 {
14816 memcpy( buffer, m_buffer+m_buffer_position, count );
14817 m_buffer_position += count;
14818 }
14819
14820 return count;
14821 }
14822
14823 size_t ON_Read3dmBufferArchive::Write( size_t, const void* )
14824 {
14825
14826 return 0;
14827 }
14828
14829 bool ON_Read3dmBufferArchive::Flush()
14830 {
14831
14832 return false;
14833 }
14834
14835
14836 size_t ON_Read3dmBufferArchive::SizeOfBuffer() const
14837 {
14838 return m_sizeof_buffer;
14839 }
14840
14841 const void* ON_Read3dmBufferArchive::Buffer() const
14842 {
14843 return (const void*)m_buffer;
14844 }
14845
14846
14847
14848
14849
14850 ON_Write3dmBufferArchive::ON_Write3dmBufferArchive(
14851 size_t initial_sizeof_buffer,
14852 size_t max_sizeof_buffer,
14853 int archive_3dm_version,
14854 int archive_opennurbs_version
14855 )
14856 : ON_BinaryArchive(ON::write3dm)
14857 , m_p(0)
14858 , m_buffer(0)
14859 , m_sizeof_buffer(0)
14860 , m_max_sizeof_buffer(max_sizeof_buffer)
14861 , m_sizeof_archive(0)
14862 , m_buffer_position(0)
14863 , m_reserved1(0)
14864 , m_reserved2(0)
14865 , m_reserved3(0)
14866 , m_reserved4(0)
14867 {
14868 if ( initial_sizeof_buffer > 0 )
14869 AllocBuffer(initial_sizeof_buffer);
14870 if ( archive_3dm_version < 2 )
14871 archive_3dm_version = ON_BinaryArchive::CurrentArchiveVersion();
14872 SetArchive3dmVersion(archive_3dm_version);
14873 ON_SetBinaryArchiveOpenNURBSVersion(*this,archive_opennurbs_version);
14874 }
14875
14876 ON_Write3dmBufferArchive::~ON_Write3dmBufferArchive()
14877 {
14878 if ( m_p )
14879 onfree(m_p);
14880 }
14881
14882 void ON_Write3dmBufferArchive::AllocBuffer( size_t sz )
14883 {
14884 if ( sz > m_sizeof_buffer
14885 && (m_max_sizeof_buffer <= 0 || sz <= m_max_sizeof_buffer)
14886 )
14887 {
14888 if ( sz < 2*m_sizeof_buffer )
14889 {
14890 sz = 2*m_sizeof_buffer;
14891 if ( sz > m_max_sizeof_buffer )
14892 sz = m_max_sizeof_buffer;
14893 }
14894
14895 m_p = onrealloc(m_p,sz);
14896 m_buffer = (unsigned char*)m_p;
14897
14898 if ( 0 != m_buffer )
14899 {
14900 memset( m_buffer + m_sizeof_buffer, 0, sz - m_sizeof_buffer );
14901 m_sizeof_buffer = sz;
14902 }
14903 else
14904 {
14905 m_sizeof_buffer = 0;
14906 }
14907
14908 }
14909 }
14910
14911
14912 size_t ON_Write3dmBufferArchive::CurrentPosition() const
14913 {
14914 return m_buffer_position;
14915 }
14916
14917 bool ON_Write3dmBufferArchive::SeekFromCurrentPosition( int offset )
14918 {
14919 bool rc = false;
14920 if ( m_buffer )
14921 {
14922 if (offset >= 0 )
14923 {
14924 m_buffer_position += offset;
14925 rc = true;
14926 }
14927 else if ( size_t(-offset) <= m_buffer_position )
14928 {
14929 m_buffer_position -= (size_t(-offset));
14930 rc = true;
14931 }
14932 }
14933 return rc;
14934 }
14935
14936 bool ON_Write3dmBufferArchive::SeekFromStart( size_t offset )
14937 {
14938 bool rc = false;
14939 if ( m_buffer )
14940 {
14941 if ( offset > 0 )
14942 m_buffer_position = offset;
14943 else
14944 m_buffer_position = 0;
14945 rc = true;
14946 }
14947 return rc;
14948 }
14949
14950 bool ON_Write3dmBufferArchive::AtEnd() const
14951 {
14952 return (m_buffer_position >= m_sizeof_buffer) ? true : false;
14953 }
14954
14955 size_t ON_Write3dmBufferArchive::Read( size_t count, void* buffer )
14956 {
14957 if ( count <= 0 || 0 == buffer )
14958 return 0;
14959
14960 size_t maxcount = ( m_sizeof_buffer > m_buffer_position )
14961 ? (m_sizeof_buffer - m_buffer_position)
14962 : 0;
14963 if ( count > maxcount )
14964 count = maxcount;
14965
14966 if ( count > 0 )
14967 {
14968 memcpy( buffer, m_buffer+m_buffer_position, count );
14969 m_buffer_position += count;
14970 }
14971
14972 return count;
14973 }
14974
14975 size_t ON_Write3dmBufferArchive::Write( size_t sz, const void* buffer )
14976 {
14977 if ( sz <= 0 || 0 == buffer )
14978 return 0;
14979
14980 if ( m_buffer_position + sz > m_sizeof_buffer )
14981 {
14982 AllocBuffer(m_buffer_position + sz);
14983 }
14984
14985 if ( m_buffer_position + sz > m_sizeof_buffer )
14986 return 0;
14987
14988 memcpy( m_buffer + m_buffer_position, buffer, sz );
14989 m_buffer_position += sz;
14990 if ( m_buffer_position > m_sizeof_archive )
14991 m_sizeof_archive = m_buffer_position;
14992
14993 return sz;
14994 }
14995
14996 bool ON_Write3dmBufferArchive::Flush()
14997 {
14998
14999 return true;
15000 }
15001
15002
15003 size_t ON_Write3dmBufferArchive::SizeOfBuffer() const
15004 {
15005 return m_sizeof_buffer;
15006 }
15007
15008 const void* ON_Write3dmBufferArchive::Buffer() const
15009 {
15010 return (const void*)m_buffer;
15011 }
15012
15013 void* ON_Write3dmBufferArchive::HarvestBuffer()
15014 {
15015 void* buffer = m_buffer;
15016
15017 m_p = 0;
15018 m_buffer = 0;
15019 m_sizeof_buffer = 0;
15020 m_sizeof_archive = 0;
15021 m_buffer_position = 0;
15022
15023 return buffer;
15024 }
15025
15026 size_t ON_Write3dmBufferArchive::SizeOfArchive() const
15027 {
15028 return m_sizeof_archive;
15029 }
15030
15031
15032
15033
15034 ON_BinaryArchiveBuffer::ON_BinaryArchiveBuffer( ON::archive_mode mode, ON_Buffer* buffer )
15035 : ON_BinaryArchive(mode)
15036 , m_buffer(buffer)
15037 {
15038 }
15039
15040 ON_BinaryArchiveBuffer::~ON_BinaryArchiveBuffer()
15041 {
15042 m_buffer = 0;
15043 }
15044
15045 bool ON_BinaryArchiveBuffer::SetBuffer( ON_Buffer* buffer )
15046 {
15047 if ( 0 == m_buffer )
15048 {
15049 m_buffer = buffer;
15050 return true;
15051 }
15052
15053 return false;
15054 }
15055
15056 ON_Buffer* ON_BinaryArchiveBuffer::Buffer() const
15057 {
15058 return m_buffer;
15059 }
15060
15061 size_t ON_BinaryArchiveBuffer::CurrentPosition() const
15062 {
15063 if ( 0 != m_buffer )
15064 return (size_t)m_buffer->CurrentPosition();
15065
15066 return 0;
15067 }
15068
15069 bool ON_BinaryArchiveBuffer::SeekFromCurrentPosition(int offset)
15070 {
15071 if ( 0 != m_buffer )
15072 return m_buffer->SeekFromCurrentPosition(offset);
15073
15074 return false;
15075 }
15076
15077 bool ON_BinaryArchiveBuffer::SeekFromStart(size_t offset)
15078 {
15079 if ( 0 != m_buffer )
15080 return m_buffer->SeekFromStart((ON__INT64)offset);
15081
15082 return false;
15083 }
15084
15085 bool ON_BinaryArchiveBuffer::AtEnd() const
15086 {
15087 if ( 0 != m_buffer )
15088 return m_buffer->AtEnd();
15089
15090 return false;
15091 }
15092
15093 bool ON_BinaryArchiveBuffer::SeekFromEnd( ON__INT64 offset )
15094 {
15095 if ( 0 != m_buffer )
15096 return m_buffer->SeekFromEnd(offset);
15097
15098 return false;
15099 }
15100
15101 size_t ON_BinaryArchiveBuffer::Read( size_t count, void* a )
15102 {
15103 if ( 0 != m_buffer )
15104 return (size_t)m_buffer->Read(count,a);
15105
15106 return 0;
15107 }
15108
15109 size_t ON_BinaryArchiveBuffer::Write( size_t count, const void* a )
15110 {
15111 if ( 0 != m_buffer )
15112 return (size_t)m_buffer->Write(count,a);
15113
15114 return 0;
15115 }
15116
15117 bool ON_BinaryArchiveBuffer::Flush()
15118 {
15119 if ( 0 != m_buffer )
15120 return true;
15121
15122 return false;
15123 }
15124
15125 ON_FileIterator::ON_FileIterator()
15126 : m_count(0)
15127 #if defined(ON_COMPILER_MSC)
15128 , m_file_attributes_mask(0)
15129 , m_h(0)
15130 #else
15131 , m_dir(0)
15132 , m_current_file_attributes(0)
15133 , m_current_file_size(0)
15134 , m_current_file_create_time(0)
15135 , m_current_last_modified_time(0)
15136 , m_current_last_access_time(0)
15137 #endif
15138 {
15139 Destroy();
15140 #if defined(ON_COMPILER_MSC)
15141 memset(&m_fd,0,sizeof(m_fd));
15142 #else
15143 memset(&m_dirent,0,sizeof(m_dirent));
15144 m_dirent.d_name[0] = 0;
15145 memset(&m_dirent_name_buffer[0],0,sizeof(m_dirent_name_buffer));
15146 memset(&m_current_name[0],0,sizeof(m_current_name));
15147 #endif
15148 }
15149
15150 ON_FileIterator::~ON_FileIterator()
15151 {
15152 Destroy();
15153 }
15154
15155 void ON_FileIterator::Destroy()
15156 {
15157 #if defined(ON_COMPILER_MSC)
15158 if ( 0 != m_h )
15159 {
15160 ::FindClose(m_h);
15161 m_h = 0;
15162 }
15163 m_file_attributes_mask = 0;
15164 memset(&m_fd,0,sizeof(m_fd));
15165 #else
15166 if ( 0 != m_dir )
15167 {
15168 closedir(m_dir);
15169 m_dir = 0;
15170 }
15171 memset(&m_dirent,0,sizeof(m_dirent));
15172 m_dirent.d_name[0] = 0;
15173 memset(&m_dirent_name_buffer[0],0,sizeof(m_dirent_name_buffer));
15174 m_ws_file_name_filter.Destroy();
15175 m_utf8_file_name_filter.Destroy();
15176 memset(&m_current_name[0],0,sizeof(m_current_name));
15177 m_current_file_attributes = 0;
15178 m_current_file_size = 0;
15179 m_current_file_create_time = 0;
15180 m_current_last_modified_time = 0;
15181 m_current_last_access_time = 0;
15182 #endif
15183 m_count = 0;
15184 m_directory.Empty();
15185 }
15186
15187 ON__UINT64 ON_FileIterator::Count() const
15188 {
15189 return m_count;
15190 }
15191
15192 #if defined(ON_COMPILER_MSC)
15193 static bool IsDotOrDotDotDir( const wchar_t* s )
15194 #else
15195 static bool IsDotOrDotDotDir( const char* s )
15196 #endif
15197 {
15198 bool rc = false;
15199 for (;;)
15200 {
15201 if ( 0 == s )
15202 break;
15203 if ( '.' != s[0] )
15204 break;
15205 if ( 0 != s[1] )
15206 {
15207 if ( '.' != s[1] )
15208 break;
15209 if ( 0 != s[2] )
15210 break;
15211 }
15212 rc = true;
15213 break;
15214 }
15215 return rc;
15216 }
15217
15218 const wchar_t* ON_FileIterator::FirstFile(
15219 const char* directory_name,
15220 const char* file_name_filter
15221 )
15222 {
15223
15224
15225
15226 ON_wString ws_directory_name = directory_name;
15227 ON_wString ws_file_name_filter = file_name_filter;
15228 const wchar_t* wchar_directory_name = ws_directory_name;
15229 const wchar_t* wchar_file_name_filter = ws_file_name_filter;
15230 return FirstFile(wchar_directory_name,wchar_file_name_filter);
15231 }
15232
15233 const wchar_t* ON_FileIterator::FirstFile(
15234 const wchar_t* directory_name,
15235 const wchar_t* file_name_filter
15236 )
15237 {
15238 ON_wString buffer(directory_name);
15239 {
15240 const wchar_t* dir_seps = L"/\\";
15241 buffer.TrimRight(dir_seps);
15242 if ( buffer.Length() <= 0 || buffer.IsEmpty() )
15243 buffer = directory_name;
15244 else
15245 directory_name = buffer;
15246 }
15247
15248 #if defined(ON_COMPILER_MSC)
15249 const ON__UINT32 saved_mask = m_file_attributes_mask;
15250 Destroy();
15251 m_file_attributes_mask = saved_mask;
15252
15253 ON_wString s(directory_name);
15254
15255
15256 if ( 0 == file_name_filter )
15257 {
15258
15259
15260
15261
15262
15263 file_name_filter = L"*.*";
15264 }
15265
15266 if ( 0 != file_name_filter[0] )
15267 {
15268 s += L"\\";
15269 s += file_name_filter;
15270 }
15271
15272 m_h = ::FindFirstFile(s, &m_fd);
15273 if ( 0 == m_h || INVALID_HANDLE_VALUE == m_h || 0 == m_fd.cFileName[0] )
15274 {
15275
15276 m_h = 0;
15277 Destroy();
15278 m_file_attributes_mask = saved_mask;
15279 return 0;
15280 }
15281
15282 m_directory = directory_name;
15283
15284 if ( IsDotOrDotDotDir(m_fd.cFileName) || 0 != (m_file_attributes_mask & m_fd.dwFileAttributes) )
15285 {
15286 return NextFile();
15287 }
15288
15289 m_count++;
15290 m_fd.cFileName[(sizeof(m_fd.cFileName)/sizeof(m_fd.cFileName[0]))-1] = 0;
15291 return m_fd.cFileName;
15292
15293 #else
15294
15295
15296 Destroy();
15297 m_directory = directory_name;
15298 m_ws_file_name_filter = file_name_filter;
15299 m_utf8_file_name_filter = file_name_filter;
15300 const ON_String utf8_str(m_directory);
15301 const char* s = utf8_str;
15302 m_dir = (0 != s && 0 != s[0]) ? opendir(s) : 0;
15303 if ( 0 != m_dir )
15304 return NextFile();
15305 Destroy();
15306 return 0;
15307
15308 #endif
15309 }
15310
15311 const wchar_t* ON_FileIterator::NextFile()
15312 {
15313 #if defined(ON_COMPILER_MSC)
15314 const ON__UINT32 saved_mask = m_file_attributes_mask;
15315 if ( 0 == m_h || INVALID_HANDLE_VALUE == m_h || 0 == m_fd.cFileName[0] )
15316 {
15317 Destroy();
15318 m_file_attributes_mask = saved_mask;
15319 return 0;
15320 }
15321
15322 for (;;)
15323 {
15324 if ( !::FindNextFile( m_h, &m_fd) || 0 == m_fd.cFileName[0] )
15325 {
15326 Destroy();
15327 m_file_attributes_mask = saved_mask;
15328 return 0;
15329 }
15330
15331 if ( IsDotOrDotDotDir(m_fd.cFileName) || 0 != (m_file_attributes_mask & m_fd.dwFileAttributes) )
15332 {
15333 continue;
15334 }
15335
15336 break;
15337 }
15338
15339 m_count++;
15340 m_fd.cFileName[(sizeof(m_fd.cFileName)/sizeof(m_fd.cFileName[0]))-1] = 0;
15341 return m_fd.cFileName;
15342 #else
15343
15344
15345 ON__UINT64 current_file_attributes = 0;
15346 wchar_t current_name[ sizeof(m_current_name)/sizeof(m_current_name[0]) ];
15347 for(;;)
15348 {
15349 current_file_attributes = 0;
15350 struct dirent* dp = 0;
15351 int readdir_errno = readdir_r(m_dir, &m_dirent, &dp);
15352 if ( 0 != readdir_errno )
15353 break;
15354 if ( 0 == dp )
15355 break;
15356 if ( 0 == m_dirent.d_name[0] )
15357 break;
15358
15359 if ( IsDotOrDotDotDir(m_dirent.d_name) )
15360 continue;
15361
15362 memset( current_name, 0, sizeof(current_name) );
15363 ON_ConvertUTF8ToWideChar(
15364 &m_dirent.d_name[0],-1,
15365 ¤t_name[0], ((int)(sizeof(current_name)/sizeof(current_name[0]))) - 1,
15366 0,
15367 (4|8|16),
15368 0,
15369 0
15370 );
15371
15372
15373
15374 ON_wString wpath = m_directory;
15375 wpath += '/';
15376 wpath += current_name;
15377
15378
15379 const ON_String utf8buffer(wpath);
15380 const char* utf8path = utf8buffer;
15381 if ( 0 == utf8path )
15382 continue;
15383
15384 struct stat buf;
15385 memset(&buf,0,sizeof(buf));
15386 int stat_errno = stat( utf8path, &buf);
15387 if ( 0 != stat_errno )
15388 continue;
15389
15390 if ( S_ISDIR(buf.st_mode) )
15391 {
15392 current_file_attributes = 2;
15393 }
15394 else if ( S_ISREG(buf.st_mode) )
15395 {
15396
15397 const wchar_t* file_name_filter = m_ws_file_name_filter;
15398 if ( 0 != file_name_filter
15399 && '*' == file_name_filter[0]
15400 && '.' == file_name_filter[1]
15401 && 0 != file_name_filter[2]
15402 && '*' != file_name_filter[2] )
15403 {
15404
15405 const wchar_t* current_name_ext = 0;
15406 on_wsplitpath(current_name,0,0,0,¤t_name_ext);
15407 if ( 0 == current_name_ext
15408 || 0 != wcscmp(file_name_filter+1,current_name_ext)
15409 )
15410 {
15411
15412 continue;
15413 }
15414 }
15415 current_file_attributes = 1;
15416 }
15417 else
15418 continue;
15419
15420
15421 memcpy( m_current_name, current_name, sizeof(m_current_name) );
15422 m_current_file_attributes = current_file_attributes;
15423 m_current_file_size = buf.st_size;
15424 m_current_file_create_time = buf.st_mtime;
15425 m_current_last_modified_time = buf.st_mtime;
15426 m_current_last_access_time = buf.st_atime;
15427
15428 return m_current_name;
15429 }
15430
15431 Destroy();
15432 return 0;
15433 #endif
15434 }
15435
15436
15437 const wchar_t* ON_FileIterator::CurrentFileName() const
15438 {
15439 #if defined(ON_COMPILER_MSC)
15440 return ( 0 != m_h && 0 != m_fd.cFileName[0] ) ? m_fd.cFileName : 0;
15441 #else
15442 return ( 0 != m_current_name[0] ) ? m_current_name : 0;
15443 #endif
15444 }
15445
15446 ON__UINT64 ON_FileIterator::CurrentFileSize() const
15447 {
15448 ON__UINT64 file_size = 0;
15449
15450 #if defined(ON_COMPILER_MSC)
15451 if ( 0 != CurrentFileName() )
15452 {
15453 file_size = m_fd.nFileSizeHigh;
15454 file_size *= ((ON__UINT64)0xFFFFFFFF);
15455 file_size += m_fd.nFileSizeLow;
15456 }
15457 #else
15458 file_size = m_current_file_size;
15459 #endif
15460
15461 return file_size;
15462 }
15463
15464 bool ON_FileIterator::CurrentFileIsDirectory() const
15465 {
15466 bool rc = false;
15467 const wchar_t* current_file_name = CurrentFileName();
15468 if ( 0 != current_file_name && 0 != current_file_name[0] )
15469 {
15470 #if defined(ON_COMPILER_MSC)
15471 if ( 0 != (FILE_ATTRIBUTE_DIRECTORY & m_fd.dwFileAttributes) )
15472 {
15473 rc = true;
15474 }
15475 #else
15476 if ( 2 == m_current_file_attributes)
15477 {
15478 rc = true;
15479 }
15480 #endif
15481 }
15482 return rc;
15483 }
15484
15485 bool ON_FileIterator::CurrentFileIsHidden() const
15486 {
15487 bool rc = false;
15488 const wchar_t* current_file_name = CurrentFileName();
15489 if ( 0 != current_file_name && 0 != current_file_name[0] )
15490 {
15491 if ( '.' == current_file_name[0] )
15492 {
15493 rc = true;
15494 }
15495 #if defined(ON_COMPILER_MSC)
15496 else if ( 0 != (FILE_ATTRIBUTE_HIDDEN & m_fd.dwFileAttributes) )
15497 {
15498 rc = true;
15499 }
15500 #endif
15501 }
15502 return rc;
15503 }
15504
15505
15506 bool ON_FileIterator::GetCurrentFullPathFileName( ON_wString& filename ) const
15507 {
15508 bool rc = false;
15509
15510 #if defined(ON_COMPILER_MSC)
15511 if ( 0 == m_h || 0 == m_fd.cFileName )
15512 {
15513 filename.Empty();
15514 }
15515 else
15516 {
15517 filename = m_directory;
15518 filename += L"\\";
15519 filename += m_fd.cFileName;
15520 rc = true;
15521 }
15522 #else
15523
15524
15525 if ( 0 == m_current_name[0] )
15526 {
15527 filename.Empty();
15528 }
15529 else
15530 {
15531 filename = m_directory;
15532 filename += L"/";
15533 filename += m_current_name;
15534 rc = true;
15535 }
15536
15537 #endif
15538
15539 return rc;
15540 }
15541
15542
15543 #if defined(ON_COMPILER_MSC)
15544 static ON__UINT64 SecondsSinceJanOne1970( FILETIME ft )
15545 {
15546
15547
15548
15549
15550
15551
15552
15553
15554
15555
15556
15557
15558
15559
15560
15561 ON__UINT64 ft_since_jan_1_1601 = ft.dwHighDateTime;
15562 ft_since_jan_1_1601 *= 0xFFFFFFFF;
15563 ft_since_jan_1_1601 += ft.dwLowDateTime;
15564
15565 ON__UINT64 hundrednanoseconds_per_second = 10000000;
15566
15567 ON__UINT64 seconds_since_jan_1_1601 = ft_since_jan_1_1601 / hundrednanoseconds_per_second;
15568
15569 ON__UINT64 seconds_since_jan_1_1970 = seconds_since_jan_1_1601 - 11644473600;
15570
15571 return seconds_since_jan_1_1970;
15572 }
15573 #endif
15574
15575 ON__UINT64 ON_FileIterator::CurrentFileCreateTime() const
15576 {
15577 #if defined(ON_COMPILER_MSC)
15578 return SecondsSinceJanOne1970(m_fd.ftCreationTime);
15579 #else
15580 return m_current_file_create_time;
15581 #endif
15582 }
15583
15584 ON__UINT64 ON_FileIterator::CurrentFileLastModifiedTime() const
15585 {
15586 #if defined(ON_COMPILER_MSC)
15587 return SecondsSinceJanOne1970(m_fd.ftLastWriteTime);
15588 #else
15589 return m_current_last_modified_time;
15590 #endif
15591 }
15592
15593 ON__UINT64 ON_FileIterator::CurrentFileLastAccessTime() const
15594 {
15595 #if defined(ON_COMPILER_MSC)
15596 return SecondsSinceJanOne1970(m_fd.ftLastAccessTime);
15597 #else
15598 return m_current_last_access_time;
15599 #endif
15600 }
15601