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
00020 ON_Buffer::ON_Buffer()
00021 : m_buffer_size(0)
00022 , m_current_position(0)
00023 , m_first_segment(0)
00024 , m_last_segment(0)
00025 , m_current_segment(0)
00026 , m_heap(0)
00027 , m_error_handler(0)
00028 , m_last_error(0)
00029 {
00030 memset(m_reserved,0,sizeof(m_reserved));
00031 }
00032
00033
00034 void ON_Buffer::Destroy()
00035 {
00036 ChangeSize(0);
00037 }
00038
00039 void ON_Buffer::EmergencyDestroy()
00040 {
00041 m_buffer_size = 0;
00042 m_current_position = 0;
00043 m_first_segment = 0;
00044 m_last_segment = 0;
00045 m_current_segment = 0;
00046 m_heap = 0;
00047 m_error_handler = 0;
00048 m_last_error = 0;
00049 }
00050
00051 struct ON_BUFFER_SEGMENT
00052 {
00053 struct ON_BUFFER_SEGMENT* m_prev_segment;
00054 struct ON_BUFFER_SEGMENT* m_next_segment;
00055 ON__UINT64 m_segment_position0;
00056 ON__UINT64 m_segment_position1;
00057
00058
00059 unsigned char* m_segment_buffer;
00060 void* m_reserved;
00061 };
00062
00063 int ON_Buffer::Compare( const ON_Buffer& a, const ON_Buffer& b )
00064 {
00065 if ( &a == &b )
00066 return 0;
00067 if ( a.m_buffer_size < b.m_buffer_size )
00068 return -1;
00069 if ( a.m_buffer_size > b.m_buffer_size )
00070 return 1;
00071
00072 struct ON_BUFFER_SEGMENT* aseg = a.m_first_segment;
00073 struct ON_BUFFER_SEGMENT* bseg = b.m_first_segment;
00074 const ON__UINT64 buffer_size = a.m_buffer_size;
00075 ON__UINT64 size = 0;
00076 size_t aoffset = 0;
00077 size_t boffset = 0;
00078 size_t asegsize = 0;
00079 size_t bsegsize = 0;
00080 size_t asize = 0;
00081 size_t bsize = 0;
00082 size_t sz;
00083 int rc = 0;
00084
00085 while ( 0 != aseg && 0 != bseg && size < buffer_size )
00086 {
00087 if ( 0 == asegsize )
00088 {
00089 if ( aseg->m_segment_position0 >= aseg->m_segment_position1 )
00090 {
00091 aseg = aseg->m_next_segment;
00092 continue;
00093 }
00094 asegsize = (size_t)(aseg->m_segment_position1 - aseg->m_segment_position0);
00095 aoffset = 0;
00096 }
00097
00098 if ( 0 == bsegsize )
00099 {
00100 if ( bseg->m_segment_position0 >= bseg->m_segment_position1 )
00101 {
00102 bseg = bseg->m_next_segment;
00103 continue;
00104 }
00105 bsegsize = (size_t)(bseg->m_segment_position1 - bseg->m_segment_position0);
00106 boffset = 0;
00107 }
00108
00109 if ( aoffset >= asegsize )
00110 {
00111 asegsize = 0;
00112 aseg = aseg->m_next_segment;
00113 continue;
00114 }
00115
00116 if ( boffset >= bsegsize )
00117 {
00118 bsegsize = 0;
00119 bseg = bseg->m_next_segment;
00120 continue;
00121 }
00122
00123 if ( 0 == aseg->m_segment_buffer )
00124 {
00125 return (0 == bseg->m_segment_buffer) ? 0 : -1;
00126 }
00127
00128 if ( 0 == bseg->m_segment_buffer )
00129 {
00130 return 1;
00131 }
00132
00133 asize = asegsize - aoffset;
00134 bsize = bsegsize - boffset;
00135 sz = (asize <= bsize) ? asize : bsize;
00136 if ( size + sz > buffer_size )
00137 sz = (size_t)(buffer_size - size);
00138 rc = memcmp( aseg->m_segment_buffer + aoffset, bseg->m_segment_buffer + boffset, (size_t)sz );
00139 if ( 0 != rc )
00140 return ((rc<0)?-1:1);
00141 aoffset += sz;
00142 boffset += sz;
00143 size += sz;
00144 }
00145
00146 return 0;
00147 }
00148
00149
00150 ON_Buffer::~ON_Buffer()
00151 {
00152 ChangeSize(0);
00153 m_current_position = 0;
00154 }
00155
00156 ON_Buffer::ON_Buffer( const ON_Buffer& src )
00157 : m_buffer_size(0)
00158 , m_current_position(0)
00159 , m_first_segment(0)
00160 , m_last_segment(0)
00161 , m_current_segment(0)
00162 , m_heap(src.m_heap)
00163 , m_error_handler(0)
00164 , m_last_error(0)
00165 {
00166 memset(m_reserved,0,sizeof(m_reserved));
00167 Copy(src);
00168 }
00169
00170 ON_Buffer& ON_Buffer::operator=( const ON_Buffer& src )
00171 {
00172 if ( this != &src )
00173 {
00174 ChangeSize(0);
00175 m_current_position = 0;
00176 Copy(src);
00177 }
00178 return *this;
00179 }
00180
00181 bool ON_Buffer::Seek( ON__INT64 offset, int origin )
00182 {
00183 ON__UINT64 pos0, pos1;
00184
00185 switch(origin)
00186 {
00187 case 0:
00188 pos0 = 0;
00189 break;
00190
00191 case 1:
00192 pos0 = m_current_position;
00193 break;
00194
00195 case 2:
00196 pos0 = m_buffer_size;
00197 break;
00198
00199 default:
00200 {
00201 ON_ERROR("Invalid origin parameter");
00202 return false;
00203 }
00204 break;
00205 }
00206
00207 if ( offset < 0 )
00208 {
00209 if ( pos0 < (ON__UINT64)(-offset) )
00210 {
00211
00212 ON_ERROR("Attempt to seek before start of buffer.");
00213 return false;
00214 }
00215 pos1 = pos0 - (ON__UINT64)(-offset);
00216 }
00217 else if ( offset > 0 )
00218 {
00219
00220 pos1 = pos0 + (ON__UINT64)(offset);
00221 if ( pos1 <= pos0 )
00222 {
00223
00224 ON_ERROR("Attempt to seek to a position that is too large for 64-bit unsigned int storage.");
00225 return false;
00226 }
00227 }
00228 else
00229 {
00230 pos1 = pos0;
00231 }
00232
00233 if ( pos1 != m_current_position )
00234 {
00235 m_current_position = pos1;
00236 m_current_segment = 0;
00237 }
00238
00239 return true;
00240 }
00241
00242 bool ON_Buffer::SeekFromStart( ON__INT64 offset )
00243 {
00244 return Seek(offset,0);
00245 }
00246
00247 bool ON_Buffer::SeekFromCurrentPosition( ON__INT64 offset )
00248 {
00249 return Seek(offset,1);
00250 }
00251
00252 bool ON_Buffer::SeekFromEnd( ON__INT64 offset )
00253 {
00254 return Seek(offset,2);
00255 }
00256
00257 bool ON_Buffer::Compact()
00258 {
00259 bool rc = false;
00260 if ( 0 == m_buffer_size )
00261 {
00262 rc = ChangeSize(0);
00263 m_current_segment = 0;
00264 }
00265 else if ( 0 != m_last_segment
00266 && m_buffer_size > m_last_segment->m_segment_position0
00267 && m_buffer_size <= m_last_segment->m_segment_position1
00268 )
00269 {
00270 if ( m_buffer_size == m_last_segment->m_segment_position1 )
00271 rc = true;
00272 else
00273 {
00274 ON__UINT64 sizeof_segment_buffer = m_buffer_size - m_last_segment->m_segment_position0;
00275 struct ON_BUFFER_SEGMENT* prev_segment = m_last_segment->m_prev_segment;
00276 void* last_buffer = ( 0 != m_last_segment->m_segment_buffer && m_last_segment->m_segment_buffer != (unsigned char*)(m_last_segment+1) )
00277 ? m_last_segment->m_segment_buffer
00278 : 0;
00279 struct ON_BUFFER_SEGMENT* new_last_segment = (struct ON_BUFFER_SEGMENT*)onrealloc(m_last_segment,sizeof(*m_last_segment) + ((size_t)sizeof_segment_buffer));
00280 if ( 0 != new_last_segment )
00281 {
00282 if ( new_last_segment != m_last_segment || 0 != last_buffer )
00283 {
00284 new_last_segment->m_segment_buffer = (unsigned char*)(new_last_segment+1);
00285 if ( 0 != last_buffer )
00286 {
00287 memcpy(new_last_segment->m_segment_buffer,last_buffer,(size_t)sizeof_segment_buffer);
00288 onfree(last_buffer);
00289 last_buffer = 0;
00290 }
00291 new_last_segment->m_prev_segment = prev_segment;
00292 new_last_segment->m_next_segment = 0;
00293 if ( m_first_segment == m_last_segment )
00294 m_first_segment = new_last_segment;
00295 if ( m_current_segment == m_last_segment )
00296 m_current_segment = new_last_segment;
00297 m_last_segment = new_last_segment;
00298 if ( 0 != prev_segment )
00299 {
00300 prev_segment->m_next_segment = m_last_segment;
00301 }
00302 }
00303 m_last_segment->m_segment_position1 = m_buffer_size;
00304 rc = true;
00305 }
00306 }
00307 }
00308 return true;
00309 }
00310
00311 bool ON_Buffer::ChangeSize(ON__UINT64 buffer_size)
00312 {
00313 if ( buffer_size <= 0 )
00314 {
00315 struct ON_BUFFER_SEGMENT* p0 = m_last_segment;
00316 struct ON_BUFFER_SEGMENT* p1 = 0;
00317 m_buffer_size = 0;
00318 m_first_segment = 0;
00319 m_last_segment = 0;
00320 m_current_segment = 0;
00321
00322
00323 while ( 0 != p0 )
00324 {
00325 p1 = p0->m_prev_segment;
00326 if ( 0 != p0->m_segment_buffer && (void*)(p0->m_segment_buffer) != (void*)(p0+1) )
00327 onfree(p0->m_segment_buffer);
00328 onfree(p0);
00329 p0 = p1;
00330 }
00331 }
00332 else if ( buffer_size < m_buffer_size )
00333 {
00334 m_current_segment = 0;
00335
00336 if ( 0 == m_first_segment || 0 == m_last_segment )
00337 {
00338 ON_ERROR("Corrupt ON_Buffer");
00339 return false;
00340 }
00341
00342 while ( 0 != m_last_segment )
00343 {
00344 if ( m_last_segment->m_segment_position0 < buffer_size )
00345 {
00346 if ( buffer_size > m_last_segment->m_segment_position1 )
00347 {
00348 ON_ERROR("Corrupt ON_Buffer.");
00349
00350
00351
00352 if ( m_buffer_size > m_last_segment->m_segment_position1 )
00353 m_buffer_size = m_last_segment->m_segment_position1;
00354 m_last_segment->m_next_segment = 0;
00355 if ( m_current_position > m_buffer_size )
00356 m_current_position = m_buffer_size;
00357 return false;
00358 }
00359 if ( 0 != m_last_segment->m_segment_buffer && m_last_segment->m_segment_position1 > buffer_size )
00360 {
00361 memset(m_last_segment->m_segment_buffer + (buffer_size - m_last_segment->m_segment_position0),
00362 0,
00363 (size_t)(m_last_segment->m_segment_position1 - buffer_size)
00364 );
00365 }
00366 m_buffer_size = buffer_size;
00367 break;
00368 }
00369 struct ON_BUFFER_SEGMENT* p = m_last_segment->m_prev_segment;
00370 if ( 0 != p )
00371 p->m_next_segment = 0;
00372 if ( 0 != m_last_segment->m_segment_buffer && (void*)(m_last_segment->m_segment_buffer) != (void*)(m_last_segment+1) )
00373 onfree(m_last_segment->m_segment_buffer);
00374 onfree(m_last_segment);
00375 m_last_segment = p;
00376 }
00377 }
00378 else if ( buffer_size > m_buffer_size )
00379 {
00380
00381 const ON__UINT64 saved_pos = CurrentPosition();
00382 if ( SeekFromStart(buffer_size-1) )
00383 {
00384
00385
00386
00387
00388 const unsigned char zero_byte = 0;
00389 Write(1,&zero_byte);
00390 }
00391
00392 SeekFromStart(saved_pos);
00393 }
00394
00395 return (buffer_size == m_buffer_size);
00396 }
00397
00398 void ON_Buffer::Copy( const ON_Buffer& src )
00399 {
00400 const struct ON_BUFFER_SEGMENT* src_seg;
00401 struct ON_BUFFER_SEGMENT* dst_seg;
00402 for ( src_seg = src.m_first_segment; 0 != src_seg; src_seg = src_seg->m_next_segment )
00403 {
00404 if ( m_buffer_size != src_seg->m_segment_position0
00405 || src_seg->m_segment_position0 >= src.m_buffer_size
00406 )
00407 {
00408 ON_ERROR("Attempt to copy corrupt source.");
00409 break;
00410 }
00411 if ( src_seg->m_segment_position0 >= src_seg->m_segment_position1
00412 )
00413 {
00414 ON_ERROR("Attempt to copy corrupt source.");
00415 continue;
00416 }
00417 ON__UINT64 segment_buffer_size = ( 0 != src_seg->m_segment_buffer)
00418 ? src_seg->m_segment_position1 - src_seg->m_segment_position0
00419 : 0;
00420 dst_seg = (struct ON_BUFFER_SEGMENT*)onmalloc(sizeof(*dst_seg) + ((size_t)segment_buffer_size) );
00421 memset(dst_seg,0,sizeof(*dst_seg));
00422
00423 if ( segment_buffer_size > 0 )
00424 {
00425 dst_seg->m_segment_buffer = (unsigned char*)(dst_seg+1);
00426 memcpy( dst_seg->m_segment_buffer, src_seg->m_segment_buffer, (size_t)segment_buffer_size );
00427 }
00428
00429 if ( 0 == m_first_segment )
00430 m_first_segment = dst_seg;
00431 dst_seg->m_prev_segment = m_last_segment;
00432 if ( 0 != m_last_segment )
00433 m_last_segment->m_next_segment = dst_seg;
00434 m_last_segment = dst_seg;
00435 dst_seg->m_segment_position0 = src_seg->m_segment_position0;
00436 dst_seg->m_segment_position1 = src_seg->m_segment_position1;
00437 m_buffer_size = (src.m_buffer_size < dst_seg->m_segment_position1)
00438 ? src.m_buffer_size
00439 : dst_seg->m_segment_position1;
00440 }
00441 if ( src.m_current_position <= m_buffer_size )
00442 m_current_position = src.m_current_position;
00443
00444 }
00445
00446 static bool ON_Buffer_IsNotValid()
00447 {
00448 return false;
00449 }
00450
00451 bool ON_Buffer::IsValid( const ON_TextLog* text_log ) const
00452 {
00453
00454
00455
00456 if ( 0 == m_buffer_size )
00457 {
00458
00459 if ( 0 != m_first_segment )
00460 return ON_Buffer_IsNotValid();
00461 if ( 0 != m_last_segment )
00462 return ON_Buffer_IsNotValid();
00463 if ( 0 != m_current_segment )
00464 return ON_Buffer_IsNotValid();
00465
00466 return true;
00467 }
00468
00469
00470 if ( 0 == m_first_segment )
00471 return ON_Buffer_IsNotValid();
00472 if ( 0 != m_first_segment->m_prev_segment )
00473 return ON_Buffer_IsNotValid();
00474 if ( 0 == m_last_segment )
00475 return ON_Buffer_IsNotValid();
00476 if ( 0 != m_last_segment->m_next_segment )
00477 return ON_Buffer_IsNotValid();
00478
00479 bool bCurrentSegInList = (0 == m_current_segment);
00480 ON__UINT64 pos = 0;
00481 ON__UINT64 u;
00482 const struct ON_BUFFER_SEGMENT* prev_seg = 0;
00483 const struct ON_BUFFER_SEGMENT* seg;
00484 for ( seg = m_first_segment; seg != 0; seg = seg->m_next_segment )
00485 {
00486 if ( prev_seg != seg->m_prev_segment )
00487 return ON_Buffer_IsNotValid();
00488 if ( 0 != prev_seg && prev_seg->m_segment_position1 != seg->m_segment_position0 )
00489 return ON_Buffer_IsNotValid();
00490 if ( seg->m_segment_position1 <= seg->m_segment_position0 )
00491 return ON_Buffer_IsNotValid();
00492 if ( pos != seg->m_segment_position0 )
00493 return ON_Buffer_IsNotValid();
00494
00495 if ( m_current_segment == seg )
00496 bCurrentSegInList = true;
00497
00498
00499 u = pos + (seg->m_segment_position1 - seg->m_segment_position0);
00500 if ( pos >= u )
00501 return ON_Buffer_IsNotValid();
00502 pos = u;
00503 prev_seg = seg;
00504 }
00505
00506 if ( m_last_segment != prev_seg )
00507 return ON_Buffer_IsNotValid();
00508
00509 if ( pos < m_buffer_size )
00510 return ON_Buffer_IsNotValid();
00511
00512 if ( m_buffer_size <= m_last_segment->m_segment_position0
00513 || m_buffer_size > m_last_segment->m_segment_position1
00514 )
00515 return ON_Buffer_IsNotValid();
00516
00517 return true;
00518 }
00519
00520 bool ON_Buffer::AtEnd() const
00521 {
00522 return (m_current_position == m_buffer_size);
00523 }
00524
00525 ON__UINT64 ON_Buffer::Size() const
00526 {
00527 return m_buffer_size;
00528 }
00529
00530 ON__UINT32 ON_Buffer::CRC32( ON__UINT32 current_remainder ) const
00531 {
00532 ON__UINT64 size, seg_size;
00533 const struct ON_BUFFER_SEGMENT* prev_seg;
00534 const struct ON_BUFFER_SEGMENT* seg;
00535 const struct ON_BUFFER_SEGMENT* seg0 = 0;
00536
00537 size = 0;
00538 for ( seg = m_first_segment; 0 != seg; seg = seg->m_next_segment )
00539 {
00540
00541
00542 prev_seg = seg0;
00543 seg0 = seg;
00544
00545 if ( seg->m_segment_position0 > seg->m_segment_position1 )
00546 {
00547
00548
00549 ON_ERROR("corrupt buffer - segment's position values are invalid.");
00550 continue;
00551 }
00552
00553 if ( 0 == prev_seg )
00554 {
00555 if ( 0 != seg->m_segment_position0 )
00556 {
00557
00558
00559
00560
00561
00562 ON_ERROR("corrupt buffer - first segment has non-zero value for position0.");
00563 }
00564 }
00565 else if ( prev_seg->m_segment_position1 != seg->m_segment_position0 )
00566 {
00567
00568
00569
00570
00571
00572
00573 ON_ERROR("corrupt buffer - previous segment's position1 !- segment's position0.");
00574 }
00575
00576 seg_size = seg->m_segment_position1 - seg->m_segment_position0;
00577
00578 if ( 0 == seg_size )
00579 {
00580
00581
00582 ON_ERROR("corrupt buffer - empty segment buffer.");
00583 continue;
00584 }
00585
00586 if ( seg_size + size > m_buffer_size )
00587 {
00588 if ( seg != m_last_segment || seg->m_next_segment )
00589 {
00590
00591
00592 ON_ERROR("corrupt buffer - segments contain more bytes than m_buffer_size.");
00593 }
00594 seg_size = m_buffer_size - size;
00595 }
00596
00597 current_remainder = ON_CRC32(current_remainder,(size_t)seg_size,seg->m_segment_buffer);
00598 size += seg_size;
00599 if ( size >= m_buffer_size )
00600 {
00601 if ( seg != m_last_segment || 0 != seg->m_next_segment || size > m_buffer_size )
00602 {
00603
00604
00605 ON_ERROR("corrupt buffer - list of segments is too long.");
00606 }
00607 break;
00608 }
00609 }
00610
00611 return current_remainder;
00612 }
00613
00614
00615 ON__UINT64 ON_Buffer::CurrentPosition() const
00616 {
00617 return m_current_position;
00618 }
00619
00620 bool ON_Buffer::SetCurrentSegment( bool bWritePending )
00621 {
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 if ( 0 == m_current_segment )
00636 m_current_segment = (m_current_position <= m_buffer_size/2) ? m_first_segment : m_last_segment;
00637
00638 if ( !bWritePending && m_current_position >= m_buffer_size )
00639 {
00640 m_current_segment = 0;
00641 return false;
00642 }
00643
00644 if ( 0 != m_current_segment
00645 && m_current_segment->m_segment_position0 <= m_current_position
00646 && m_current_position < m_current_segment->m_segment_position1
00647 )
00648 {
00649
00650
00651
00652 return true;
00653 }
00654
00655 if ( 0 == m_first_segment )
00656 {
00657
00658 m_current_segment = 0;
00659 return bWritePending;
00660 }
00661
00662 if ( 0 == m_last_segment )
00663 {
00664 m_current_segment = 0;
00665 ON_ERROR("Corrupt ON_Buffer");
00666 return false;
00667 }
00668
00669 if ( m_current_position >= m_last_segment->m_segment_position1 )
00670 {
00671 m_current_segment = 0;
00672 return bWritePending;
00673 }
00674
00675 while ( m_current_position < m_current_segment->m_segment_position0 )
00676 {
00677 m_current_segment = m_current_segment->m_prev_segment;
00678 if ( 0 == m_current_segment )
00679 {
00680 ON_ERROR("Corrupt ON_Buffer");
00681 return false;
00682 }
00683 }
00684
00685 while ( m_current_position >= m_current_segment->m_segment_position1 )
00686 {
00687 m_current_segment = m_current_segment->m_next_segment;
00688 if ( 0 == m_current_segment )
00689 return bWritePending;
00690 }
00691
00692 return true;
00693 }
00694
00695 ON__UINT64 ON_Buffer::Write( ON__UINT64 size, const void* buffer )
00696 {
00697 if ( 0 == size )
00698 return 0;
00699
00700 if ( 0 == buffer )
00701 {
00702 ON_ERROR("size parameter > 0 and buffer parameter is null.");
00703 return 0;
00704 }
00705
00706 if ( !SetCurrentSegment(true) )
00707 {
00708 ON_ERROR("Corrupt ON_Buffer");
00709 return 0;
00710 }
00711
00712
00713
00714 ON__UINT64 rc = 0;
00715 while ( size > 0 )
00716 {
00717 if ( 0 == m_current_segment )
00718 {
00719
00720 const ON__UINT64 padding_size = 4*sizeof(void*);
00721 const ON__UINT64 header_size = sizeof(*m_current_segment);
00722 ON__UINT64 page_size = ON_MemoryPageSize();
00723 if ( page_size <= 4096 )
00724 page_size = 4096;
00725 const ON__UINT64 max_malloc_size = 16*page_size;
00726
00727 ON__UINT64 malloc_size = ( 0 != m_last_segment && m_last_segment->m_segment_position1 > m_last_segment->m_segment_position0 )
00728 ? padding_size + header_size + (m_last_segment->m_segment_position1 - m_last_segment->m_segment_position0)
00729 : 0;
00730 if ( malloc_size < page_size/2 )
00731 malloc_size = page_size/2;
00732 if ( malloc_size < max_malloc_size )
00733 malloc_size *= 2;
00734 while ( malloc_size < max_malloc_size && size > malloc_size - header_size - padding_size )
00735 malloc_size *= 2;
00736
00737 malloc_size -= padding_size;
00738
00739 m_current_segment = (struct ON_BUFFER_SEGMENT*)onmalloc((size_t)malloc_size);
00740 memset(m_current_segment,0,(size_t)malloc_size);
00741 m_current_segment->m_prev_segment = m_last_segment;
00742 m_current_segment->m_segment_buffer = (unsigned char*)(m_current_segment + 1);
00743 if ( 0 != m_last_segment )
00744 {
00745 m_last_segment->m_next_segment = m_current_segment;
00746 m_current_segment->m_segment_position0 = m_last_segment->m_segment_position1;
00747 }
00748 else
00749 m_first_segment = m_current_segment;
00750 m_last_segment = m_current_segment;
00751 m_current_segment->m_segment_position1 = m_current_segment->m_segment_position0 + (ON__UINT64)(malloc_size - header_size);
00752 }
00753
00754 if ( m_current_position < m_current_segment->m_segment_position0
00755 || m_current_segment->m_segment_position1 <= m_current_segment->m_segment_position0
00756 )
00757 {
00758 ON_ERROR("Corrupt ON_Buffer");
00759 return 0;
00760 }
00761
00762 if ( m_current_position >= m_current_segment->m_segment_position1 )
00763 {
00764
00765 if ( m_current_segment->m_segment_position1 > m_buffer_size )
00766 m_buffer_size = m_current_segment->m_segment_position1;
00767 m_current_segment = m_current_segment->m_next_segment;
00768 continue;
00769 }
00770
00771 ON__UINT64 offset = m_current_position - m_current_segment->m_segment_position0;
00772 ON__UINT64 sz = (m_current_segment->m_segment_position1 - m_current_position);
00773
00774 if ( sz > size )
00775 sz = size;
00776 memcpy( m_current_segment->m_segment_buffer + offset, buffer, (size_t)sz );
00777 m_current_position += sz;
00778 if ( m_buffer_size < m_current_position )
00779 {
00780
00781 m_buffer_size = m_current_position;
00782 }
00783 rc += sz;
00784 size -= sz;
00785 buffer = ((const unsigned char*)buffer) + sz;
00786 if ( size > 0 )
00787 m_current_segment = m_current_segment->m_next_segment;
00788 }
00789
00790 return rc;
00791 }
00792
00793 ON__UINT64 ON_Buffer::Read( ON__UINT64 size, void* buffer )
00794 {
00795 if ( 0 == size )
00796 {
00797
00798 return 0;
00799 }
00800
00801 if ( 0 == buffer )
00802 {
00803
00804 ON_ERROR("size parameter > 0 and buffer parameter is null.");
00805 return 0;
00806 }
00807
00808 if ( m_current_position >= m_buffer_size )
00809 {
00810
00811
00812
00813
00814
00815 if ( m_current_position > m_buffer_size )
00816 {
00817 ON_ERROR("Read attempted when current position > buffer size.");
00818 }
00819 return 0;
00820 }
00821
00822 if ( !SetCurrentSegment(false) )
00823 {
00824 ON_ERROR("Corrupt ON_Buffer");
00825 return 0;
00826 }
00827
00828 ON__UINT64 rc = 0;
00829 while ( size > 0 )
00830 {
00831 if( 0 == m_current_segment || 0 == m_current_segment->m_segment_buffer )
00832 {
00833 ON_ERROR("Corrupt ON_Buffer");
00834 return 0;
00835 }
00836
00837
00838 ON__UINT64 pos1 = (m_buffer_size < m_current_segment->m_segment_position1)
00839 ? m_buffer_size
00840 : m_current_segment->m_segment_position1;
00841 if ( m_current_position < m_current_segment->m_segment_position0 || m_current_position >= pos1 )
00842 {
00843 ON_ERROR("Corrupt ON_Buffer");
00844 return 0;
00845 }
00846
00847 ON__UINT64 offset = m_current_position - m_current_segment->m_segment_position0;
00848 ON__UINT64 sz = pos1 - m_current_position;
00849
00850 if ( sz > size )
00851 sz = size;
00852 memcpy( buffer, m_current_segment->m_segment_buffer + offset, (size_t)sz );
00853 m_current_position += sz;
00854 rc += sz;
00855 size -= sz;
00856 buffer = ((unsigned char*)buffer) + sz;
00857 if ( size > 0 )
00858 {
00859 if ( m_current_position == m_buffer_size && m_current_segment == m_last_segment )
00860 {
00861
00862
00863
00864
00865 break;
00866 }
00867 m_current_segment = m_current_segment->m_next_segment;
00868 }
00869 }
00870
00871 return rc;
00872 }
00873
00874 ON__UINT32 ON_Buffer::LastError() const
00875 {
00876 return m_last_error;
00877 }
00878
00879
00880 void ON_Buffer::ClearLastError()
00881 {
00882 m_last_error = 0;
00883 }
00884
00885
00886 ON_Buffer_ErrorHandler ON_Buffer::ErrorHandler() const
00887 {
00888 return m_error_handler;
00889 }
00890
00891 void ON_Buffer::SetErrorHandler(ON_Buffer_ErrorHandler error_handler)
00892 {
00893 m_error_handler = error_handler;
00894 }
00895
00896 bool ON_Buffer::WriteToBinaryArchive( ON_BinaryArchive& archive ) const
00897 {
00898
00899
00900
00901
00902 ON__UINT32 buffer_crc = CRC32(0);
00903
00904 if ( !archive.BeginWrite3dmChunk(TCODE_OPENNURBS_BUFFER,1,0) )
00905 return false;
00906
00907 bool rc = false;
00908 for(;;)
00909 {
00910 if ( !archive.WriteBigInt(m_buffer_size) )
00911 break;
00912 if ( !archive.WriteInt(buffer_crc) )
00913 break;
00914
00915 bool buffer_rc = true;
00916 ON__UINT64 size = 0;
00917 for ( struct ON_BUFFER_SEGMENT* seg = m_first_segment;
00918 0 != seg && size < m_buffer_size;
00919 seg = seg->m_next_segment
00920 )
00921 {
00922 if ( 0 == seg->m_segment_buffer )
00923 continue;
00924 if ( seg->m_segment_position1 <= seg->m_segment_position0 )
00925 continue;
00926 ON__UINT64 seg_size = (seg->m_segment_position1 - seg->m_segment_position0);
00927 if ( seg_size + size > m_buffer_size )
00928 seg_size = m_buffer_size - size;
00929 if ( !archive.WriteByte( (size_t)seg_size, seg->m_segment_buffer ) )
00930 {
00931 buffer_rc = false;
00932 break;
00933 }
00934 size += seg_size;
00935 }
00936
00937 rc = true;
00938 break;
00939 }
00940
00941 if ( !archive.EndWrite3dmChunk() )
00942 rc = false;
00943
00944 return rc;
00945 }
00946
00947
00948 bool ON_Buffer::ReadFromBinaryArchive( ON_BinaryArchive& archive )
00949 {
00950 Destroy();
00951
00952 int major_version = 0;
00953 int minor_version = 0;
00954 if ( !archive.BeginRead3dmChunk(TCODE_OPENNURBS_BUFFER,&major_version,&minor_version) )
00955 return false;
00956
00957 ON_3DM_BIG_CHUNK c0;
00958 memset(&c0,0,sizeof(c0));
00959 archive.GetCurrentChunk(c0);
00960
00961 ON__UINT64 saved_buffer_size = 0;
00962 ON__UINT32 saved_buffer_crc = 0;
00963 bool rc = false;
00964 void* a = 0;
00965 for(;;)
00966 {
00967 if ( 1 != major_version )
00968 break;
00969
00970 if ( !archive.ReadBigInt(&saved_buffer_size) )
00971 break;
00972
00973 if ( !archive.ReadInt(&saved_buffer_crc) )
00974 break;
00975
00976 const ON__UINT64 extra_size = 24;
00977
00978
00979
00980
00981
00982 if ( 0 == minor_version )
00983 {
00984 if ( c0.Length() != extra_size + saved_buffer_size )
00985 {
00986 ON_ERROR("corrupt archive");
00987 break;
00988 }
00989 }
00990 else if ( c0.Length() < extra_size + saved_buffer_size )
00991 {
00992
00993
00994
00995 ON_ERROR("corrupt archive");
00996 break;
00997 }
00998
00999 if ( saved_buffer_size > 0 )
01000 {
01001 ON__UINT64 a_capacity = saved_buffer_size;
01002 if ( a_capacity > 16*4096 )
01003 a_capacity = 16*4096;
01004 a = onmalloc((size_t)a_capacity);
01005 if ( 0 == a )
01006 break;
01007 ON__UINT64 size = 0;
01008 bool buffer_rc = true;
01009 while( size < saved_buffer_size )
01010 {
01011 ON__UINT64 read_size = a_capacity;
01012 if ( read_size > saved_buffer_size - size )
01013 read_size = saved_buffer_size - size;
01014 if ( !archive.ReadByte((size_t)read_size,a) )
01015 {
01016 buffer_rc = false;
01017 break;
01018 }
01019
01020 Write(read_size,a);
01021 size += read_size;
01022 }
01023
01024 if ( !buffer_rc )
01025 break;
01026 }
01027
01028 rc = true;
01029 break;
01030 }
01031
01032 if ( 0 != a )
01033 onfree(a);
01034
01035 if ( !archive.EndRead3dmChunk() )
01036 rc = false;
01037
01038 if ( rc )
01039 {
01040 Compact();
01041 const ON__UINT32 buffer_crc = CRC32(0);
01042 if ( buffer_crc != saved_buffer_crc || m_buffer_size != saved_buffer_size)
01043 {
01044
01045 ON_ERROR("The buffer contents were corrupted during, writing, storage or reading.");
01046 }
01047 }
01048 else
01049 {
01050 Destroy();
01051 }
01052
01053 return rc;
01054 }
01055
01056 static bool ON_Buffer_StreamCallback( void* context, ON__UINT32 size, const void* buffer )
01057 {
01058 return ( size == ((ON_Buffer*)context)->Write(size,buffer) );
01059 }
01060
01061 bool ON_Buffer::Compress( ON_Buffer& compressed_buffer ) const
01062 {
01063 bool rc = false;
01064 ON_CompressStream compressor;
01065 ON_Buffer* out = ( this == &compressed_buffer ) ? new ON_Buffer() : &compressed_buffer;
01066
01067 out->Destroy();
01068
01069 for (;;)
01070 {
01071 ON__UINT64 uncompressed_size = Size();
01072 if ( uncompressed_size <= 0 )
01073 break;
01074 if ( !compressor.SetCallback(ON_Buffer_StreamCallback,out) )
01075 break;
01076 if ( !compressor.Begin() )
01077 break;
01078
01079 struct ON_BUFFER_SEGMENT* prev_seg = 0;
01080 struct ON_BUFFER_SEGMENT* seg = 0;
01081 for ( seg = m_first_segment; 0 != seg; seg = seg->m_next_segment )
01082 {
01083 const ON__UINT64 pos1 = (uncompressed_size < seg->m_segment_position1)
01084 ? uncompressed_size
01085 : seg->m_segment_position1;
01086 if ( pos1 < seg->m_segment_position0 )
01087 break;
01088 if ( prev_seg != seg->m_prev_segment )
01089 break;
01090 if ( 0 == prev_seg )
01091 {
01092 if ( 0 != seg->m_segment_position0 )
01093 break;
01094 }
01095 else
01096 {
01097 if ( prev_seg->m_segment_position1 != seg->m_segment_position0 )
01098 break;
01099 }
01100 if ( !compressor.In(pos1 - seg->m_segment_position0,seg->m_segment_buffer) )
01101 break;
01102 prev_seg = seg;
01103 }
01104 if ( 0 != seg )
01105 break;
01106
01107 if ( !compressor.End() )
01108 break;
01109
01110 if ( compressor.InSize() != uncompressed_size )
01111 break;
01112 if ( compressor.InCRC() != CRC32(0) )
01113 break;
01114 if ( compressor.OutSize() != out->Size() )
01115 break;
01116 if ( compressor.OutCRC() != out->CRC32(0) )
01117 break;
01118
01119 rc = true;
01120 break;
01121 }
01122
01123 if ( !rc )
01124 {
01125 out->Destroy();
01126 if ( this == &compressed_buffer )
01127 delete out;
01128 }
01129 else
01130 {
01131 out->Compact();
01132 out->m_current_position = 0;
01133 out->m_current_segment = 0;
01134 if ( this == &compressed_buffer )
01135 {
01136
01137 compressed_buffer.Destroy();
01138 compressed_buffer.m_buffer_size = out->m_buffer_size;
01139 compressed_buffer.m_current_position = out->m_current_position;
01140 compressed_buffer.m_first_segment = out->m_first_segment;
01141 compressed_buffer.m_last_segment = out->m_last_segment;
01142 compressed_buffer.m_current_segment = out->m_current_segment;
01143 compressed_buffer.m_heap = out->m_heap;
01144 compressed_buffer.m_error_handler = out->m_error_handler;
01145 compressed_buffer.m_last_error = out->m_last_error;
01146
01147 out->m_first_segment = 0;
01148 out->m_last_segment = 0;
01149 out->m_current_segment = 0;
01150 out->m_buffer_size = 0;
01151 delete out;
01152 }
01153 }
01154
01155 return rc;
01156 }
01157
01158 bool ON_Buffer::Uncompress( ON_Buffer& uncompressed_buffer ) const
01159 {
01160 bool rc = false;
01161 ON_UncompressStream uncompressor;
01162 ON_Buffer* out = ( this == &uncompressed_buffer ) ? new ON_Buffer() : &uncompressed_buffer;
01163
01164 out->Destroy();
01165
01166 for (;;)
01167 {
01168 ON__UINT64 compressed_size = Size();
01169 if ( compressed_size <= 0 )
01170 break;
01171 if ( !uncompressor.SetCallback(ON_Buffer_StreamCallback,out) )
01172 break;
01173 if ( !uncompressor.Begin() )
01174 break;
01175
01176 struct ON_BUFFER_SEGMENT* prev_seg = 0;
01177 struct ON_BUFFER_SEGMENT* seg = 0;
01178 for ( seg = m_first_segment; 0 != seg; seg = seg->m_next_segment )
01179 {
01180 const ON__UINT64 pos1 = (compressed_size < seg->m_segment_position1)
01181 ? compressed_size
01182 : seg->m_segment_position1;
01183 if ( pos1 < seg->m_segment_position0 )
01184 break;
01185 if ( prev_seg != seg->m_prev_segment )
01186 break;
01187 if ( 0 == prev_seg )
01188 {
01189 if ( 0 != seg->m_segment_position0 )
01190 break;
01191 }
01192 else
01193 {
01194 if ( prev_seg->m_segment_position1 != seg->m_segment_position0 )
01195 break;
01196 }
01197 if ( !uncompressor.In(pos1 - seg->m_segment_position0,seg->m_segment_buffer) )
01198 break;
01199 prev_seg = seg;
01200 }
01201 if ( 0 != seg )
01202 break;
01203
01204 if ( !uncompressor.End() )
01205 break;
01206
01207 if ( uncompressor.InSize() != compressed_size )
01208 break;
01209 if ( uncompressor.InCRC() != CRC32(0) )
01210 break;
01211 if ( uncompressor.OutSize() != out->Size() )
01212 break;
01213 if ( uncompressor.OutCRC() != out->CRC32(0) )
01214 break;
01215
01216 rc = true;
01217 break;
01218 }
01219
01220 if ( !rc )
01221 {
01222 out->Destroy();
01223 if ( this == &uncompressed_buffer )
01224 delete out;
01225 }
01226 else
01227 {
01228 out->Compact();
01229 out->m_current_position = 0;
01230 out->m_current_segment = 0;
01231 if ( this == &uncompressed_buffer )
01232 {
01233
01234 uncompressed_buffer.Destroy();
01235 uncompressed_buffer.m_buffer_size = out->m_buffer_size;
01236 uncompressed_buffer.m_current_position = out->m_current_position;
01237 uncompressed_buffer.m_first_segment = out->m_first_segment;
01238 uncompressed_buffer.m_last_segment = out->m_last_segment;
01239 uncompressed_buffer.m_current_segment = out->m_current_segment;
01240 uncompressed_buffer.m_heap = out->m_heap;
01241 uncompressed_buffer.m_error_handler = out->m_error_handler;
01242 uncompressed_buffer.m_last_error = out->m_last_error;
01243
01244 out->m_first_segment = 0;
01245 out->m_last_segment = 0;
01246 out->m_current_segment = 0;
01247 out->m_buffer_size = 0;
01248 delete out;
01249 }
01250 }
01251
01252 return rc;
01253 }
01254
01255
01256
01257
01258 ON_OBJECT_IMPLEMENT( ON_EmbeddedFile, ON_Object, "1247BEC9-D9A9-46B3-900F-39DE7A355BD3");
01259
01260 bool ON_EmbeddedFile::Create(
01261 const wchar_t* file_full_path_name,
01262 bool bCompress
01263 )
01264 {
01265 Destroy();
01266
01267
01268 FILE* fp = ON_FileStream::Open(file_full_path_name,L"rb");
01269 if ( 0 == fp )
01270 return false;
01271
01272 bool rc = Create(fp,bCompress);
01273
01274 ON_FileStream::Close(fp);
01275 if ( rc )
01276 {
01277 ON_CreateUuid(m_id);
01278 m_full_file_name = file_full_path_name;
01279 }
01280
01281 return rc;
01282 }
01283
01284 ON_EmbeddedFile::ON_EmbeddedFile()
01285 : m_id(ON_nil_uuid)
01286 , m_reserved(0)
01287 , m_file_size(0)
01288 , m_file_time(0)
01289 , m_file_crc(0)
01290 , m_buffer_crc(0)
01291 , m_bCompressedBuffer(0)
01292 {
01293 m_reserved3[0] = 0;
01294 m_reserved3[1] = 0;
01295 m_reserved3[2] = 0;
01296 m_reserved3[3] = 0;
01297 m_reserved3[4] = 0;
01298 m_reserved3[5] = 0;
01299 m_reserved3[6] = 0;
01300 }
01301
01302 ON_EmbeddedFile::ON_EmbeddedFile(const ON_EmbeddedFile& src)
01303 : ON_Object(src)
01304 , m_id(src.m_id)
01305 , m_full_file_name(src.m_full_file_name)
01306 , m_relative_file_name(src.m_relative_file_name)
01307 , m_reserved(0)
01308 , m_file_size(src.m_file_size)
01309 , m_file_time(src.m_file_time)
01310 , m_file_crc(src.m_file_crc)
01311 , m_buffer_crc(src.m_buffer_crc)
01312 , m_buffer(src.m_buffer)
01313 , m_bCompressedBuffer(src.m_bCompressedBuffer)
01314 {
01315 m_reserved3[0] = 0;
01316 m_reserved3[1] = 0;
01317 m_reserved3[2] = 0;
01318 m_reserved3[3] = 0;
01319 m_reserved3[4] = 0;
01320 m_reserved3[5] = 0;
01321 m_reserved3[6] = 0;
01322 }
01323
01324 ON_EmbeddedFile& ON_EmbeddedFile::operator=(const ON_EmbeddedFile& src)
01325 {
01326 if ( this != &src )
01327 {
01328 Destroy();
01329
01330 ON_Object::operator=(src);
01331
01332 m_id = src.m_id;
01333
01334 m_full_file_name = src.m_full_file_name;
01335 m_relative_file_name = src.m_relative_file_name;
01336
01337 m_file_size = src.m_file_size;
01338 m_file_time = src.m_file_time;
01339 m_file_crc = src.m_file_crc;
01340 m_buffer_crc = src.m_buffer_crc;
01341 m_buffer = src.m_buffer;
01342 m_bCompressedBuffer = src.m_bCompressedBuffer;
01343 }
01344 return *this;
01345 }
01346
01347 ON_EmbeddedFile::~ON_EmbeddedFile()
01348 {
01349 Destroy();
01350 }
01351
01352 void ON_EmbeddedFile::EmergencyDestroy()
01353 {
01354 ON_Object::EmergencyDestroy();
01355 m_buffer.EmergencyDestroy();
01356 m_full_file_name.EmergencyDestroy();
01357 m_relative_file_name.EmergencyDestroy();
01358 Destroy();
01359 }
01360
01361 void ON_EmbeddedFile::Destroy()
01362 {
01363 ON_Object::PurgeUserData();
01364 DestroyBuffer();
01365 m_id = ON_nil_uuid;
01366 m_full_file_name.Destroy();
01367 m_relative_file_name.Destroy();
01368 m_file_size = 0;
01369 m_file_time = 0;
01370 m_file_crc = 0;
01371 m_buffer_crc = 0;
01372 }
01373
01374 void ON_EmbeddedFile::DestroyBuffer()
01375 {
01376 m_buffer.Destroy();
01377 m_buffer_crc = 0;
01378 m_bCompressedBuffer = false;
01379 }
01380
01381 static bool CompressedStreamHandler( void* context, ON__UINT32 size, const void* buffer )
01382 {
01383 return (size == ((ON_Buffer*)context)->Write(size,buffer) );
01384 }
01385
01386 bool ON_EmbeddedFile::Create(
01387 FILE* fp,
01388 bool bCompress
01389 )
01390 {
01391 Destroy();
01392
01393 if ( 0 == fp )
01394 return false;
01395 if ( !ON_FileStream::SeekFromStart(fp,0) )
01396 return false;
01397
01398 ON__UINT64 file_size = 0;
01399 ON__UINT64 file_create_time = 0;
01400 ON__UINT64 file_last_modified_time = 0;
01401 if ( !ON_FileStream::GetFileInformation(fp,&file_size,&file_create_time,&file_last_modified_time) )
01402 return false;
01403
01404
01405
01406 ON_Workspace ws;
01407 const size_t buffer_capacity = 4090;
01408 ON__UINT64 buffer_size;
01409 void* buffer = (void*)ws.GetMemory(buffer_capacity);
01410 if ( 0 == buffer )
01411 return false;
01412
01413 ON_CompressStream compress;
01414 if ( bCompress )
01415 {
01416 m_bCompressedBuffer = true;
01417 if ( !compress.SetCallback(CompressedStreamHandler,&m_buffer) )
01418 return false;
01419 if ( !compress.Begin() )
01420 return false;
01421 }
01422
01423 for(;;)
01424 {
01425 buffer_size = ON_FileStream::Read(fp,buffer_capacity,buffer);
01426 if ( buffer_size <= 0 )
01427 break;
01428 m_file_size += buffer_size;
01429 m_file_crc = ON_CRC32(m_file_crc,(size_t)buffer_size,buffer);
01430 if ( bCompress )
01431 {
01432 if ( !compress.In(buffer_size,buffer) )
01433 {
01434 Destroy();
01435 return false;
01436 }
01437 }
01438 else
01439 {
01440 if ( !m_buffer.Write(buffer_size,buffer) )
01441 {
01442 Destroy();
01443 return false;
01444 }
01445 }
01446 }
01447
01448 if ( bCompress )
01449 {
01450 if ( !compress.End() )
01451 {
01452 Destroy();
01453 return false;
01454 }
01455 if ( compress.InSize() != m_file_size
01456 || compress.InCRC() != m_file_crc
01457 || compress.OutSize() != m_buffer.Size()
01458 )
01459 {
01460 Destroy();
01461 return false;
01462 }
01463 }
01464
01465 m_buffer_crc = m_buffer.CRC32(0);
01466
01467 if ( bCompress )
01468 {
01469 if ( compress.OutCRC() != m_buffer_crc )
01470 {
01471 Destroy();
01472 return false;
01473 }
01474 }
01475
01476 m_buffer.SeekFromStart(0);
01477
01478 return true;
01479 }
01480
01481 bool ON_EmbeddedFile::Extract(
01482 const wchar_t* destination_filename
01483 ) const
01484 {
01485 if ( 0 == destination_filename || 0 == destination_filename[0] )
01486 return false;
01487 if ( m_buffer.Size() <= 0 )
01488 return false;
01489 FILE* fp = ON_FileStream::Open(destination_filename,L"wb");
01490 if ( 0 == fp )
01491 return false;
01492 bool rc = Extract(fp);
01493 ON_FileStream::Close(fp);
01494 return rc;
01495 }
01496
01497 static bool UncompressedToFileHandler( void* context, ON__UINT32 size, const void* buffer )
01498 {
01499 return ( size == ON_FileStream::Write((FILE*)context,size,buffer) );
01500 }
01501
01502 bool ON_EmbeddedFile::Extract(
01503 FILE* fp
01504 ) const
01505 {
01506 ON_Workspace ws;
01507
01508 if ( 0 == fp )
01509 return false;
01510 if ( m_buffer.Size() <= 0 )
01511 return false;
01512
01513 ON_UncompressStream uncompress;
01514
01515 if ( m_bCompressedBuffer )
01516 {
01517 if ( !uncompress.SetCallback(UncompressedToFileHandler,fp) )
01518 return false;
01519 if ( !uncompress.Begin() )
01520 return false;
01521 }
01522
01523 const size_t buffer_capacity = 4088;
01524 void* buffer = ws.GetMemory(buffer_capacity);
01525 ON__UINT64 file_size = 0;
01526 ON__UINT32 file_crc = 0;
01527 if ( !const_cast<ON_Buffer*>(&m_buffer)->SeekFromStart(0) )
01528 return false;
01529 for(;;)
01530 {
01531 ON__UINT64 buffer_size = const_cast<ON_Buffer*>(&m_buffer)->Read(buffer_capacity,buffer);
01532 if ( buffer_size <= 0 )
01533 break;
01534 if ( m_bCompressedBuffer )
01535 {
01536 if ( !uncompress.In(buffer_size,buffer) )
01537 return false;
01538 }
01539 else
01540 {
01541 file_size += buffer_size;
01542 file_crc = ON_CRC32(file_crc,(size_t)buffer_size,buffer);
01543 if ( !ON_FileStream::Write(fp,(size_t)buffer_size,buffer) )
01544 return false;
01545 }
01546 }
01547
01548 if ( m_bCompressedBuffer )
01549 {
01550 if ( !uncompress.End() )
01551 return false;
01552
01553 file_size = uncompress.OutSize();
01554 file_crc = uncompress.OutCRC();
01555 }
01556
01557 if ( file_size != m_file_size || file_crc != m_file_crc )
01558 return false;
01559
01560 return true;
01561 }
01562
01563
01564 struct BufferAndSize
01565 {
01566 ON__UINT64 buffer_size;
01567 void* buffer;
01568 };
01569
01570 static bool UncompressedToBufferHandler( void* context, ON__UINT32 size, const void* buffer )
01571 {
01572 struct BufferAndSize* bs = (struct BufferAndSize*)context;
01573 size_t sz = (bs->buffer_size < size) ? (size_t)bs->buffer_size : (size_t)size;
01574 if ( sz > 0 )
01575 {
01576 memcpy(bs->buffer,buffer,sz);
01577 bs->buffer_size -= sz;
01578 bs->buffer = ((unsigned char*)bs->buffer) + sz;
01579 }
01580 return ( sz == size );
01581 }
01582
01583 bool ON_EmbeddedFile::Extract(
01584 void* out_buffer
01585 ) const
01586 {
01587 ON_Workspace ws;
01588
01589 if ( m_buffer.Size() <= 0 )
01590 return false;
01591 if ( FileSize() <= 0 )
01592 return false;
01593 if ( 0 == out_buffer )
01594 return false;
01595
01596 BufferAndSize bs;
01597 bs.buffer = out_buffer;
01598 bs.buffer_size = FileSize();
01599
01600 ON_UncompressStream uncompress;
01601
01602 if ( m_bCompressedBuffer )
01603 {
01604 if ( !uncompress.SetCallback(UncompressedToBufferHandler,&bs) )
01605 return false;
01606 if ( !uncompress.Begin() )
01607 return false;
01608 }
01609
01610 const size_t buffer_capacity = 4088;
01611 void* buffer = ws.GetMemory(buffer_capacity);
01612 ON__UINT64 file_size = 0;
01613 ON__UINT32 file_crc = 0;
01614 if ( !const_cast<ON_Buffer*>(&m_buffer)->SeekFromStart(0) )
01615 return false;
01616 for(;;)
01617 {
01618 ON__UINT64 buffer_size = const_cast<ON_Buffer*>(&m_buffer)->Read(buffer_capacity,buffer);
01619 if ( buffer_size <= 0 )
01620 break;
01621 if ( m_bCompressedBuffer )
01622 {
01623 if ( !uncompress.In(buffer_size,buffer) )
01624 return false;
01625 }
01626 else
01627 {
01628 file_size += buffer_size;
01629 file_crc = ON_CRC32(file_crc,(size_t)buffer_size,buffer);
01630 size_t sz = (bs.buffer_size < buffer_size) ? (size_t)bs.buffer_size : (size_t)buffer_size;
01631 if ( sz > 0 )
01632 {
01633 memcpy(bs.buffer,buffer,sz);
01634 bs.buffer_size -= sz;
01635 bs.buffer = ((unsigned char*)bs.buffer) + sz;
01636 }
01637 if ( sz != buffer_size )
01638 return false;
01639 }
01640 }
01641
01642 if ( m_bCompressedBuffer )
01643 {
01644 if ( !uncompress.End() )
01645 return false;
01646
01647 file_size = uncompress.OutSize();
01648 file_crc = uncompress.OutCRC();
01649 }
01650
01651 if ( file_size != m_file_size || file_crc != m_file_crc )
01652 return false;
01653
01654 return true;
01655 }
01656
01657 const wchar_t* ON_EmbeddedFile::FullFileName() const
01658 {
01659 return m_full_file_name;
01660 }
01661
01662 const wchar_t* ON_EmbeddedFile::RelativeFileName() const
01663 {
01664 return m_relative_file_name;
01665 }
01666
01667 ON_UUID ON_EmbeddedFile::Id() const
01668 {
01669 return m_id;
01670 }
01671
01672 void ON_EmbeddedFile::SetFullFileName( const wchar_t* full_file_name )
01673 {
01674 m_full_file_name = full_file_name;
01675 }
01676
01677 void ON_EmbeddedFile::SetRelativeFileName( const wchar_t* relative_file_name )
01678 {
01679 m_relative_file_name = relative_file_name;
01680 }
01681
01682 void ON_EmbeddedFile::SetId( ON_UUID id )
01683 {
01684 m_id = id;
01685 }
01686
01687 ON__UINT64 ON_EmbeddedFile::FileSize() const
01688 {
01689 return m_file_size;
01690 }
01691
01692 ON__UINT64 ON_EmbeddedFile::FileLastModifiedTime() const
01693 {
01694 return m_file_time;
01695 }
01696
01697 ON__UINT32 ON_EmbeddedFile::FileCRC() const
01698 {
01699 return m_file_crc;
01700 }
01701
01702 static bool ON_EmbeddedFileIsNotValid()
01703 {
01704 return ON_IsNotValid();
01705 }
01706
01707 ON_BOOL32 ON_EmbeddedFile::IsValid( ON_TextLog* text_log ) const
01708 {
01709 if ( !m_buffer.IsValid(text_log) )
01710 {
01711 if ( 0 != text_log )
01712 text_log->Print("m_buffer is not valid.");
01713 return ON_EmbeddedFileIsNotValid();
01714 }
01715
01716 if ( m_buffer_crc != m_buffer.CRC32(0) )
01717 {
01718 if ( 0 != text_log )
01719 text_log->Print("m_buffer_crc != m_buffer.CRC32(0)");
01720 return ON_EmbeddedFileIsNotValid();
01721 }
01722
01723 if ( !m_bCompressedBuffer )
01724 {
01725 if ( m_file_size != m_buffer.Size() )
01726 {
01727 if ( 0 != text_log )
01728 text_log->Print("Uncompressed buffer - m_file_size != m_buffer.Size(0)");
01729 return ON_EmbeddedFileIsNotValid();
01730 }
01731 if ( m_file_crc != m_buffer_crc )
01732 {
01733 if ( 0 != text_log )
01734 text_log->Print("Uncompressed buffer - m_file_size != m_buffer.Size(0)");
01735 return ON_EmbeddedFileIsNotValid();
01736 }
01737 }
01738
01739 return true;
01740 }
01741
01742 ON_BOOL32 ON_EmbeddedFile::Write( ON_BinaryArchive& archive ) const
01743 {
01744 if ( !archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0) )
01745 return false;
01746
01747 bool rc = false;
01748 for(;;)
01749 {
01750
01751 if ( !archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0) )
01752 break;
01753 bool header_rc = false;
01754 for(;;)
01755 {
01756 if ( !archive.WriteUuid(m_id) )
01757 break;
01758 if ( !archive.WriteString(m_full_file_name) )
01759 break;
01760 if ( !archive.WriteString(m_relative_file_name) )
01761 break;
01762 if ( !archive.WriteBigInt(m_file_size) )
01763 break;
01764 if ( !archive.WriteBigInt(m_file_time) )
01765 break;
01766 if ( !archive.WriteInt(m_file_crc) )
01767 break;
01768 if ( !archive.WriteInt(m_buffer_crc) )
01769 break;
01770 if ( !archive.WriteChar(m_bCompressedBuffer) )
01771 break;
01772 header_rc = true;
01773 break;
01774 }
01775 if ( !archive.EndWrite3dmChunk() )
01776 break;
01777 if ( !header_rc )
01778 break;
01779
01780
01781
01782 if ( !m_buffer.WriteToBinaryArchive(archive) )
01783 break;
01784
01785 rc = true;
01786 break;
01787 }
01788
01789 if ( !archive.EndWrite3dmChunk() )
01790 rc = false;
01791
01792 return rc;
01793 }
01794
01795 ON_BOOL32 ON_EmbeddedFile::Read( ON_BinaryArchive& archive )
01796 {
01797 Destroy();
01798
01799 int major_version = 0;
01800 int minor_version = 0;
01801 if ( !archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version) )
01802 return false;
01803
01804 bool rc = false;
01805 for(;;)
01806 {
01807 if ( 1 != major_version )
01808 break;
01809
01810 int header_major_version = 0;
01811 int header_minor_version = 0;
01812 if ( !archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&header_major_version,&header_minor_version) )
01813 break;
01814 bool header_rc = false;
01815 for(;;)
01816 {
01817 if ( 1 != header_major_version )
01818 break;
01819 if ( !archive.ReadUuid(m_id) )
01820 break;
01821 if ( !archive.ReadString(m_full_file_name) )
01822 break;
01823 if ( !archive.ReadString(m_relative_file_name) )
01824 break;
01825
01826 if ( !archive.ReadBigInt(&m_file_size) )
01827 break;
01828 if ( !archive.ReadBigInt(&m_file_time) )
01829 break;
01830 if ( !archive.ReadInt(&m_file_crc) )
01831 break;
01832 if ( !archive.ReadInt(&m_buffer_crc) )
01833 break;
01834 if ( !archive.ReadChar(&m_bCompressedBuffer) )
01835 break;
01836 header_rc = true;
01837 break;
01838 }
01839 if ( !archive.EndRead3dmChunk() )
01840 break;
01841 if ( !header_rc )
01842 break;
01843
01844
01845
01846 if ( !m_buffer.ReadFromBinaryArchive(archive) )
01847 break;
01848
01849 rc = true;
01850 break;
01851 }
01852
01853 if ( !archive.EndRead3dmChunk() )
01854 rc = false;
01855
01856 return rc;
01857 }
01858
01859