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 ON_VIRTUAL_OBJECT_IMPLEMENT(ON_UserData,ON_Object,"850324A7-050E-11d4-BFFA-0010830122F0");
00020
00021 ON_UserData::ON_UserData()
00022 : m_userdata_uuid(ON_nil_uuid),
00023 m_application_uuid(ON_nil_uuid),
00024 m_userdata_copycount(0),
00025 m_userdata_xform(1),
00026 m_userdata_owner(0),
00027 m_userdata_next(0)
00028 {}
00029
00030 ON_UserData::ON_UserData(const ON_UserData& src)
00031 : ON_Object(src),
00032 m_userdata_uuid(src.m_userdata_uuid),
00033 m_application_uuid(src.m_application_uuid),
00034 m_userdata_copycount(src.m_userdata_copycount),
00035 m_userdata_xform(src.m_userdata_xform),
00036 m_userdata_owner(0),
00037 m_userdata_next(0)
00038 {
00039 if ( m_userdata_copycount)
00040 {
00041 m_userdata_copycount++;
00042 if ( !m_userdata_copycount )
00043 m_userdata_copycount = 1;
00044 }
00045 }
00046
00047
00048 ON_BOOL32 ON_UserData::Archive() const
00049 {
00050
00051
00052 return false;
00053 }
00054
00055
00056 ON_BOOL32 ON_UserData::Transform(const ON_Xform& x )
00057 {
00058 m_userdata_xform = x*m_userdata_xform;
00059 return true;
00060 }
00061
00062 ON_UserData& ON_UserData::operator=(const ON_UserData& src)
00063 {
00064
00065
00066
00067
00068
00069
00070
00071
00072 if ( this != &src )
00073 {
00074 ON_Object::operator=(src);
00075 m_userdata_copycount = src.m_userdata_copycount;
00076 m_userdata_xform = src.m_userdata_xform;
00077 if ( 0 != m_userdata_copycount )
00078 {
00079 m_userdata_copycount++;
00080 if ( !m_userdata_copycount )
00081 m_userdata_copycount = 1;
00082 }
00083 }
00084
00085 return *this;
00086 }
00087
00088 ON_UserData::~ON_UserData()
00089 {
00090 ON_Object* owner = m_userdata_owner;
00091 if ( owner ) {
00092
00093 ON_UserData* prev = 0;
00094 ON_UserData* p;
00095 for ( p = owner->m_userdata_list; p; prev = p, p = p->m_userdata_next ) {
00096 if ( p == this ) {
00097 if ( prev ) {
00098 prev->m_userdata_next = p->m_userdata_next;
00099 }
00100 else {
00101 owner->m_userdata_list = p->m_userdata_next;
00102 }
00103 p->m_userdata_next = 0;
00104 p->m_userdata_owner = 0;
00105 break;
00106 }
00107 }
00108 }
00109 }
00110
00111 void ON_UserData::Dump( ON_TextLog& text_log ) const
00112 {
00113 text_log.Print("User Data:\n");
00114 text_log.PushIndent();
00115
00116
00117 ON_Object::Dump(text_log);
00118
00119
00120 ON_wString description;
00121 const_cast<ON_UserData*>(this)->GetDescription(description);
00122 if ( description.IsEmpty() )
00123 description = L"none";
00124 const wchar_t* ws = description;
00125 text_log.Print("user data description: %ls\n",ws);
00126 text_log.Print("user data uuid: ");
00127 text_log.Print(m_userdata_uuid);
00128 text_log.Print("\n");
00129 text_log.Print("user data copy count: %d\n",this->m_userdata_copycount);
00130
00131
00132 text_log.Print("user data saved in 3dm archive: %s\n",Archive() ? "yes" : "no");
00133
00134 text_log.PopIndent();
00135 }
00136
00137 unsigned int ON_UserData::SizeOf() const
00138 {
00139 unsigned int sz = ON_Object::SizeOf();
00140 sz += (sizeof(*this) - sizeof(ON_Object));
00141 return sz;
00142 }
00143
00144 ON_BOOL32 ON_UserData::IsValid( ON_TextLog* text_log ) const
00145 {
00146 if ( 0 == ON_UuidCompare( &m_userdata_uuid, &ON_nil_uuid ) )
00147 {
00148 if ( 0 != text_log )
00149 {
00150 text_log->Print("invalid userdata - m_userdata_uuid = nil\n");
00151 }
00152 return false;
00153 }
00154
00155 if ( 0 == ON_UuidCompare( m_userdata_uuid, ON_UserData::ClassId()->Uuid() ) )
00156 {
00157 if ( 0 != text_log )
00158 {
00159 text_log->Print("invalid userdata - m_userdata_uuid in use. Use guidgen to get a unique id.\n");
00160 }
00161 return false;
00162 }
00163
00164 if ( Archive() && 0 == ON_UuidCompare( ClassId()->Uuid(), ON_UserData::ClassId()->Uuid() ) )
00165 {
00166
00167
00168
00169
00170 if ( 0 != text_log )
00171 {
00172 text_log->Print("invalid userdata - classes derived from ON_UserData that get saved in 3dm archives must have a class id and name defined by ON_OBJECT_DECLARE/ON_OBJECT_IMPLEMENT.\n");
00173 }
00174 return false;
00175 }
00176
00177 return true;
00178 }
00179
00180 ON_Object* ON_UserData::Owner() const
00181 {
00182 return m_userdata_owner;
00183 }
00184
00185 ON_UserData* ON_UserData::Next() const
00186 {
00187 return m_userdata_next;
00188 }
00189
00190 ON_UUID ON_UserData::UserDataClassUuid() const
00191 {
00192 const ON_ClassId* cid = ClassId();
00193 return ( cid == &ON_UnknownUserData::m_ON_UnknownUserData_class_id )
00194 ? ((ON_UnknownUserData*)this)->m_unknownclass_uuid
00195 : cid->Uuid();
00196 }
00197
00198 ON_BOOL32 ON_UserData::IsUnknownUserData() const
00199 {
00200 return (ClassId() == &ON_UnknownUserData::m_ON_UnknownUserData_class_id)?true:false;
00201 }
00202
00203 ON_BOOL32 ON_UserData::GetDescription( ON_wString& description )
00204 {
00205 return true;
00206 }
00207
00208
00209 ON_OBJECT_IMPLEMENT(ON_UnknownUserData,ON_UserData,"850324A8-050E-11d4-BFFA-0010830122F0");
00210
00211 ON_UnknownUserData::ON_UnknownUserData()
00212 : m_unknownclass_uuid(ON_nil_uuid)
00213 , m_sizeof_buffer(0)
00214 , m_buffer(0)
00215 , m_3dm_version(0)
00216 , m_3dm_opennurbs_version(0)
00217 {}
00218
00219 ON_UnknownUserData::ON_UnknownUserData(const ON_UnknownUserData& src)
00220 : ON_UserData(src)
00221 , m_unknownclass_uuid(ON_nil_uuid)
00222 , m_sizeof_buffer(0)
00223 , m_buffer(0)
00224 , m_3dm_version(0)
00225 , m_3dm_opennurbs_version(0)
00226 {
00227 if ( m_userdata_copycount > 0 && src.m_sizeof_buffer > 0 && src.m_buffer )
00228 {
00229
00230
00231
00232
00233
00234
00235 m_userdata_uuid = src.m_userdata_uuid;
00236
00237 m_unknownclass_uuid = src.m_unknownclass_uuid;
00238 m_sizeof_buffer = src.m_sizeof_buffer;
00239 m_buffer = onmemdup( src.m_buffer, src.m_sizeof_buffer);
00240 m_3dm_version = src.m_3dm_version;
00241 m_3dm_opennurbs_version = src.m_3dm_opennurbs_version;
00242 }
00243 }
00244
00245 ON_UnknownUserData& ON_UnknownUserData::operator=(const ON_UnknownUserData& src)
00246 {
00247 if ( this != &src )
00248 {
00249 m_sizeof_buffer = 0;
00250 if ( 0 != m_buffer )
00251 {
00252 onfree(m_buffer);
00253 m_buffer = 0;
00254 }
00255
00256
00257
00258 ON_UserData::operator=(src);
00259
00260
00261
00262
00263
00264
00265
00266 m_userdata_uuid = src.m_userdata_uuid;
00267 m_application_uuid = src.m_application_uuid;
00268
00269 if ( m_userdata_copycount > 0 && src.m_sizeof_buffer > 0 && src.m_buffer )
00270 {
00271 m_unknownclass_uuid = src.m_unknownclass_uuid;
00272 m_sizeof_buffer = src.m_sizeof_buffer;
00273 m_buffer = onmemdup( src.m_buffer, src.m_sizeof_buffer);
00274 m_3dm_version = src.m_3dm_version;
00275 m_3dm_opennurbs_version = src.m_3dm_opennurbs_version;
00276 }
00277 else
00278 {
00279
00280 m_userdata_uuid = ON_nil_uuid;
00281 m_unknownclass_uuid = ON_nil_uuid;
00282 m_sizeof_buffer = 0;
00283 m_buffer = 0;
00284 m_3dm_version = 0;
00285 m_3dm_opennurbs_version = 0;
00286 }
00287 }
00288 return *this;
00289 }
00290
00291 ON_UnknownUserData::~ON_UnknownUserData()
00292 {
00293 if ( m_buffer )
00294 onfree(m_buffer);
00295 }
00296
00297 unsigned int ON_UnknownUserData::SizeOf() const
00298 {
00299 return ON_UserData::SizeOf()
00300 + (sizeof(ON_UnknownUserData)-sizeof(ON_UserData))
00301 + m_sizeof_buffer;
00302 }
00303
00304 ON_BOOL32 ON_UnknownUserData::GetDescription( ON_wString& s )
00305 {
00306 s = "Unknown user data. (Definition of class was not available when object was read.)";
00307 return true;
00308 }
00309
00310 ON_BOOL32 ON_UnknownUserData::IsValid( ON_TextLog* text_log ) const
00311 {
00312 ON_BOOL32 rc = ON_UserData::IsValid(text_log);
00313
00314
00315 if (rc)
00316 rc = (m_sizeof_buffer>0);
00317 if (rc)
00318 rc = (m_buffer != NULL);
00319
00320
00321 if (rc)
00322 rc = ON_UuidCompare( &m_unknownclass_uuid, &ON_nil_uuid );
00323
00324
00325 if (rc) {
00326 ON_UUID ON_UnknownUserData_classuuid = ON_UnknownUserData::m_ON_UnknownUserData_class_id.Uuid();
00327 rc = ON_UuidCompare( &m_unknownclass_uuid, &ON_UnknownUserData_classuuid );
00328 }
00329 return rc?true:false;
00330 }
00331
00332 void ON_UnknownUserData::Dump( ON_TextLog& dump ) const
00333 {
00334 ON_UserData::Dump(dump);
00335 dump.PushIndent();
00336 dump.Print( "unknown class uuid: ");
00337 dump.Print( m_unknownclass_uuid );
00338 dump.Print( "\n");
00339 dump.Print( "Data size in 3dm archive: %d bytes\n",m_sizeof_buffer);
00340 dump.PopIndent();
00341 }
00342
00343 ON_BOOL32 ON_UnknownUserData::Archive() const
00344 {
00345
00346
00347
00348 return true;
00349 }
00350
00351 ON_BOOL32 ON_UnknownUserData::Write( ON_BinaryArchive& file ) const
00352 {
00353 return file.WriteByte(m_sizeof_buffer,m_buffer);
00354 }
00355
00356 ON_BOOL32 ON_UnknownUserData::Read( ON_BinaryArchive& file )
00357 {
00358 m_buffer = onrealloc( m_buffer, m_sizeof_buffer );
00359 m_3dm_version = file.Archive3dmVersion();
00360 return file.ReadByte(m_sizeof_buffer,m_buffer);
00361 }
00362
00363
00364 class ON_UnknownUserDataArchive : public ON_BinaryArchive
00365 {
00366
00367
00368
00369 public:
00370 ON_UnknownUserDataArchive( const ON_UnknownUserData& );
00371 ~ON_UnknownUserDataArchive();
00372
00373
00374 size_t CurrentPosition(
00375 ) const;
00376 bool SeekFromCurrentPosition(
00377 int
00378 );
00379 bool SeekFromStart(
00380 size_t
00381 );
00382 bool AtEnd() const;
00383
00384 protected:
00385 size_t Read( size_t, void* );
00386 size_t Write( size_t, const void* );
00387 bool Flush();
00388
00389 private:
00390 ON_UnknownUserDataArchive();
00391
00392 size_t m_sizeof_buffer;
00393 const unsigned char* m_buffer;
00394 size_t m_buffer_position;
00395 };
00396
00397 ON_UnknownUserDataArchive::ON_UnknownUserDataArchive( const ON_UnknownUserData& ud ) : ON_BinaryArchive( ON::read3dm )
00398 {
00399 SetArchive3dmVersion(ud.m_3dm_version);
00400 m_sizeof_buffer = ud.m_sizeof_buffer;
00401 m_buffer = (const unsigned char*)ud.m_buffer;
00402 m_buffer_position = 0;
00403 }
00404
00405 ON_UnknownUserDataArchive::~ON_UnknownUserDataArchive()
00406 {
00407 }
00408
00409 size_t ON_UnknownUserDataArchive::CurrentPosition() const
00410 {
00411 return m_buffer_position;
00412 }
00413
00414 bool ON_UnknownUserDataArchive::SeekFromCurrentPosition( int offset )
00415 {
00416 bool rc = false;
00417 if ( offset >= 0 || m_buffer_position >= ((size_t)(-offset)) )
00418 {
00419 size_t newpos = m_buffer_position + offset;
00420 if ( newpos < m_sizeof_buffer )
00421 {
00422 m_buffer_position = newpos;
00423 rc = true;
00424 }
00425 }
00426 return rc;
00427 }
00428
00429 bool ON_UnknownUserDataArchive::SeekFromStart( size_t offset )
00430 {
00431 bool rc = false;
00432 if ( offset < m_sizeof_buffer )
00433 {
00434 if ( offset > 0 )
00435 m_buffer_position = offset;
00436 else
00437 m_buffer_position = 0;
00438 rc = true;
00439 }
00440 return rc;
00441 }
00442
00443 bool ON_UnknownUserDataArchive::AtEnd() const
00444 {
00445 return (m_buffer_position >= m_sizeof_buffer) ? true : false;
00446 }
00447
00448 size_t ON_UnknownUserDataArchive::Read( size_t count, void* buffer )
00449 {
00450 size_t maxcount = 0;
00451
00452 if ( m_sizeof_buffer > m_buffer_position )
00453 {
00454 maxcount = m_sizeof_buffer - m_buffer_position;
00455 }
00456
00457 if ( count > maxcount )
00458 {
00459 count = maxcount;
00460 }
00461
00462 if ( count > 0 )
00463 {
00464 memcpy( buffer, m_buffer+m_buffer_position, count );
00465 m_buffer_position += count;
00466 }
00467
00468 return count;
00469 }
00470
00471 size_t ON_UnknownUserDataArchive::Write( size_t, const void* )
00472 {
00473
00474 return 0;
00475 }
00476
00477 bool ON_UnknownUserDataArchive::Flush()
00478 {
00479
00480 return false;
00481 }
00482
00483 ON_UserData* ON_UnknownUserData::Convert() const
00484 {
00485 ON_UserData* ud = NULL;
00486 if ( IsValid() ) {
00487 const ON_ClassId* pID = ON_ClassId::ClassId( m_unknownclass_uuid );
00488
00489
00490 if ( pID ) {
00491
00492
00493
00494 ON_Object* pObject = pID->Create();
00495 if ( pObject ) {
00496 ud = ON_UserData::Cast(pObject);
00497 if ( !ud )
00498 delete pObject;
00499 else
00500 {
00501
00502 ON_UnknownUserDataArchive file(*this);
00503
00504 ud->m_userdata_copycount = m_userdata_copycount;
00505 ud->m_userdata_xform = m_userdata_xform;
00506 ud->Read(file);
00507 }
00508 }
00509 }
00510 }
00511 return ud;
00512 }
00513
00514 bool ON_UserDataHolder::MoveUserDataFrom( const ON_Object& source_object )
00515 {
00516 PurgeUserData();
00517 MoveUserData(*const_cast<ON_Object*>(&source_object));
00518 return (0 != FirstUserData());
00519 }
00520
00521 bool ON_UserDataHolder::MoveUserDataTo( const ON_Object& source_object, bool bAppend )
00522 {
00523 if ( !bAppend )
00524 {
00525 const_cast<ON_Object*>(&source_object)->PurgeUserData();
00526 }
00527 const_cast<ON_Object*>(&source_object)->MoveUserData(*this);
00528 PurgeUserData();
00529 return (0 != source_object.FirstUserData());
00530 }
00531
00532 ON_BOOL32 ON_UserDataHolder::IsValid( ON_TextLog* text_log ) const
00533 {
00534 return true;
00535 }
00536
00537
00539
00540
00541
00542
00543
00544
00545 ON_UserString::ON_UserString()
00546 {
00547 }
00548
00549 ON_UserString::~ON_UserString()
00550 {
00551 }
00552
00553
00554 bool ON_UserString::Write(ON_BinaryArchive& archive) const
00555 {
00556 bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
00557 if (!rc)
00558 return false;
00559
00560 for(;;)
00561 {
00562 rc = archive.WriteString(m_key);
00563 if (!rc) break;
00564 rc = archive.WriteString(m_string_value);
00565 if (!rc) break;
00566
00567 break;
00568 }
00569
00570 if ( !archive.EndWrite3dmChunk() )
00571 rc = false;
00572
00573 return rc;
00574 }
00575
00576 bool ON_UserString::Read(ON_BinaryArchive& archive)
00577 {
00578 m_key.Empty();
00579 m_string_value.Empty();
00580
00581 int major_version = 0;
00582 int minor_version = 0;
00583 bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
00584 if (!rc)
00585 return false;
00586
00587 for(;;)
00588 {
00589 rc = ( 1 == major_version );
00590 if (!rc) break;
00591 rc = archive.ReadString(m_key);
00592 if (!rc) break;
00593 rc = archive.ReadString(m_string_value);
00594 if (!rc) break;
00595
00596 break;
00597 }
00598
00599 if ( !archive.EndRead3dmChunk() )
00600 rc = false;
00601
00602 return rc;
00603 }
00604
00605 void ON_UserString::Dump(ON_TextLog& text_log) const
00606 {
00607 const wchar_t* ws = m_key;
00608 if ( !ws )
00609 ws = L"";
00610 text_log.Print("Key: %ls\n", ws);
00611
00612 ws = m_string_value;
00613 if ( !ws )
00614 ws = L"";
00615 text_log.Print("Value: %ls\n",ws);
00616 }
00617
00618 ON_OBJECT_IMPLEMENT(ON_UserStringList,ON_UserData,"CE28DE29-F4C5-4faa-A50A-C3A6849B6329");
00619
00620 ON_UserStringList::ON_UserStringList()
00621 {
00622 m_userdata_uuid = ON_UserStringList::m_ON_UserStringList_class_id.Uuid();
00623 m_application_uuid = ON_opennurbs4_id;
00624
00625
00626 m_userdata_copycount = 1;
00627 }
00628
00629 ON_UserStringList::~ON_UserStringList()
00630 {
00631 }
00632
00633 ON_BOOL32 ON_UserStringList::GetDescription( ON_wString& description )
00634 {
00635 description.Format("User text (%d entries)",m_e.Count());
00636 return true;
00637 }
00638
00639 ON_BOOL32 ON_UserStringList::Archive() const
00640 {
00641 return true;
00642 }
00643
00644 unsigned int ON_UserStringList::SizeOf() const
00645 {
00646 unsigned int sz = ON_UserData::SizeOf();
00647 sz += sizeof(*this) - sizeof(ON_UserData);
00648 sz += m_e.SizeOfArray();
00649 int i = m_e.Count();
00650 while (i--)
00651 sz += m_e[i].m_string_value.Length()*sizeof(wchar_t);
00652 return sz;
00653 }
00654
00655
00656 ON__UINT32 ON_UserStringList::DataCRC(ON__UINT32 current_remainder) const
00657 {
00658 int count = m_e.Count();
00659 for ( int i = 0; i < count; i++ )
00660 {
00661 current_remainder = m_e[i].m_key.DataCRC(current_remainder);
00662 current_remainder = m_e[i].m_string_value.DataCRC(current_remainder);
00663 }
00664 return current_remainder;
00665 }
00666
00667
00668 void ON_UserStringList::Dump( ON_TextLog& text_log ) const
00669 {
00670 int i, count = m_e.Count();
00671 text_log.Print("%d entries\n",count);
00672 text_log.PushIndent();
00673 for ( i = 0; i < count; i++ )
00674 {
00675 m_e[i].Dump(text_log);
00676 }
00677 text_log.PopIndent();
00678 }
00679
00680 ON_BOOL32 ON_UserStringList::Write(ON_BinaryArchive& archive) const
00681 {
00682 bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
00683 if ( !rc )
00684 return false;
00685
00686 for(;;)
00687 {
00688 int count = m_e.Count();
00689 rc = archive.WriteInt(count);
00690 if(!rc) break;
00691
00692 for ( int i = 0; i < count && rc; i++ )
00693 {
00694 rc = m_e[i].Write(archive);
00695 }
00696 if (!rc) break;
00697
00698 break;
00699 }
00700
00701 if ( !archive.EndWrite3dmChunk() )
00702 rc = false;
00703
00704 return rc;
00705 }
00706
00707 ON_BOOL32 ON_UserStringList::Read(ON_BinaryArchive& archive)
00708 {
00709 int major_version = 0;
00710 int minor_version = 0;
00711 bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
00712 if ( !rc )
00713 return false;
00714
00715 for(;;)
00716 {
00717 rc = (1 == major_version);
00718 if (!rc) break;
00719
00720 int count = 0;
00721 rc = archive.ReadInt(&count);
00722 if(!rc) break;
00723
00724 for ( int i = 0; i < count; i++ )
00725 {
00726 rc = m_e.AppendNew().Read(archive);
00727 if ( !rc)
00728 {
00729 m_e.Remove();
00730 break;
00731 }
00732 }
00733 if (!rc) break;
00734
00735 break;
00736 }
00737
00738 if ( !archive.EndRead3dmChunk() )
00739 rc = false;
00740
00741 return rc;
00742 }
00743
00744
00745 bool ON_UserStringList::SetUserString( const wchar_t* key, const wchar_t* string_value )
00746 {
00747 if ( !key || !key[0] )
00748 return false;
00749
00750 int i, count = m_e.Count();
00751 for (i = 0; i < count; i++ )
00752 {
00753 if ( !m_e[i].m_key.CompareNoCase(key) )
00754 {
00755 if ( string_value && string_value[0] )
00756 {
00757 m_e[i].m_string_value = string_value;
00758 }
00759 else
00760 {
00761 m_e.Remove(i);
00762 }
00763 m_userdata_copycount++;
00764 return true;
00765 }
00766 }
00767
00768 if ( string_value && string_value[0] )
00769 {
00770 ON_UserString& e = m_e.AppendNew();
00771 e.m_key = key;
00772 e.m_string_value = string_value;
00773 m_userdata_copycount++;
00774 return true;
00775 }
00776
00777 return false;
00778 }
00779
00780 bool ON_UserStringList::GetUserString( const wchar_t* key, ON_wString& string_value ) const
00781 {
00782 if ( key && key[0] )
00783 {
00784 int i, count = m_e.Count();
00785 for (i = 0; i < count; i++ )
00786 {
00787 if ( !m_e[i].m_key.CompareNoCase(key) )
00788 {
00789 string_value = m_e[i].m_string_value;
00790 return true;
00791 }
00792 }
00793 }
00794
00795 string_value.Empty();
00796 return false;
00797 }
00798
00799 static int cmp_hash_2dex_ij(const void* a, const void* b)
00800 {
00801 const int* ai = (const int*)a;
00802 const int* bi = (const int*)b;
00803
00804
00805
00806
00807
00808
00809
00810
00815
00816 if ( ai[0] < bi[0] )
00817 return -1;
00818 if ( ai[0] > bi[0] )
00819 return 1;
00820 if ( ai[1] < bi[1] )
00821 return -1;
00822 if ( ai[1] > bi[1] )
00823 return 1;
00824 return 0;
00825 }
00826
00827 int ON_UserStringList::SetUserStrings( int count, const ON_UserString* us, bool bReplace )
00828 {
00829 int added_count = 0;
00830 int i;
00831
00832 if ( count <= 0 || 0 == us )
00833 return 0;
00834
00835 if ( 1 == count )
00836 {
00837
00838 if ( us[0].m_key.IsEmpty() )
00839 return 0;
00840 for ( i = 0; i < m_e.Count(); i++ )
00841 {
00842 if ( m_e[i].m_key.CompareNoCase(us[0].m_key ) )
00843 continue;
00844 if ( bReplace )
00845 {
00846 if ( us[0].m_string_value.IsEmpty() )
00847 m_e.Remove(i);
00848 else
00849 m_e[i] = us[0];
00850 added_count++;
00851 }
00852 break;
00853 }
00854 return added_count;
00855 }
00856
00857 size_t k0, k1;
00858 int count0 = m_e.Count();
00859 size_t count0_plus_count = (size_t)(count0 + count);
00860 ON_2dex* hash = (ON_2dex*)onmalloc( (count0_plus_count + count)*sizeof(hash[0]) );
00861 ON_2dex* hash1 = hash + (count0_plus_count);
00862 const ON_2dex* h;
00863 int deleted_count = 0;
00864
00865 for ( i = 0; i < count0; i++ )
00866 {
00867 hash[i].i = (int)m_e[i].m_key.DataCRCLower(0);
00868 hash[i].j = i;
00869 }
00870
00871 for ( i = 0; i < count; i++ )
00872 {
00873 hash1[i].i = (int)us[i].m_key.DataCRCLower(0);
00874 hash1[i].j = i;
00875 hash[i+count0].i = hash1[i].i;
00876 hash[i+count0].j = hash1[i].j+count0;
00877 }
00878 ON_qsort(hash,count0_plus_count,sizeof(hash[0]),cmp_hash_2dex_ij);
00879
00880 m_e.Reserve(count0+count);
00881 for ( i = 0; i < count; i++)
00882 {
00883 if ( us[i].m_key.IsEmpty() )
00884 continue;
00885
00886
00887
00888
00889 h = ON_BinarySearch2dexArray(hash1[i].i,hash,count0_plus_count);
00890 if ( 0 == h )
00891 {
00892 ON_ERROR("There is a bug in this function.");
00893 continue;
00894 }
00895 k0 = h-hash;
00896 while ( k0 > 0 && h[-1].i == h[0].i )
00897 {
00898
00899 k0--;
00900 h--;
00901 }
00902 for (k1 = k0+1; k1 < count0_plus_count; k1++ )
00903 {
00904 if ( hash[k1].i != hash[k0].i )
00905 break;
00906 if ( hash[k1].j > i+count0 )
00907 break;
00908 }
00909
00910 if ( hash[k0].j >= count0 )
00911 {
00912
00913
00914 if ( !us[i].m_string_value.IsEmpty() )
00915 {
00916 hash[k0].j = count0++;
00917 m_e.Append(us[i]);
00918 added_count++;
00919 }
00920 continue;
00921 }
00922
00923 for (; k0 < k1; k0++ )
00924 {
00925 if ( hash[k0].j < count0 )
00926 {
00927 if ( m_e[hash[k0].j].m_key.CompareNoCase(us[i].m_key) )
00928 continue;
00929 if ( bReplace )
00930 {
00931 m_e[hash[k0].j] = us[i];
00932 added_count++;
00933 if ( us[i].m_string_value.IsEmpty() )
00934 deleted_count++;
00935 }
00936 break;
00937 }
00938 }
00939
00940 if ( k0 >= k1 )
00941 {
00942
00943
00944 if ( !us[i].m_string_value.IsEmpty() )
00945 {
00946 hash[k0].j = count0++;
00947 m_e.Append(us[i]);
00948 added_count++;
00949 }
00950 }
00951 }
00952
00953 onfree(hash);
00954
00955
00956 i = m_e.Count();
00957 while ( i-- > 0 && deleted_count > 0 )
00958 {
00959 if ( m_e[i].m_string_value.IsEmpty() )
00960 {
00961 m_e.Remove(i);
00962 deleted_count--;
00963 }
00964 }
00965
00966 return added_count;
00967 }
00968
00969
00970
00971
00972
00973 bool ON_Object::SetUserString( const wchar_t* key, const wchar_t* string_value )
00974 {
00975 ON_UserStringList* us = ON_UserStringList::Cast(GetUserData(ON_UserStringList::m_ON_UserStringList_class_id.Uuid()));
00976 bool b = false;
00977 if ( !us )
00978 {
00979 us = new ON_UserStringList();
00980 if ( !AttachUserData(us) )
00981 {
00982 delete us;
00983 us = 0;
00984 }
00985 else
00986 {
00987 b = true;
00988 }
00989 }
00990
00991 if ( us )
00992 {
00993 if ( us->SetUserString(key,string_value) )
00994 {
00995 if ( b && 2 == us->m_userdata_copycount )
00996 {
00997
00998
00999
01000 us->m_userdata_copycount = 1;
01001 }
01002 b = true;
01003 }
01004 else if ( b )
01005 {
01006
01007
01008 delete us;
01009 us = 0;
01010 b = false;
01011 }
01012 }
01013 return b;
01014 }
01015
01016
01017 int ON_Object::SetUserStrings( int count, const ON_UserString* user_strings, bool bReplace )
01018 {
01019 if ( 0 == count || 0 == user_strings )
01020 return 0;
01021
01022 int add_count = 0;
01023 int del_count = 0;
01024 for ( int i = 0; i < count; i++ )
01025 {
01026 if ( user_strings[i].m_key.IsEmpty() )
01027 continue;
01028 if ( user_strings[i].m_string_value.IsEmpty() )
01029 del_count++;
01030 else
01031 add_count++;
01032 }
01033 if ( 0 == add_count && 0 == del_count )
01034 return 0;
01035
01036 ON_UserStringList* us = ON_UserStringList::Cast(GetUserData(ON_UserStringList::m_ON_UserStringList_class_id.Uuid()));
01037 if ( !us && add_count > 0)
01038 {
01039 us = new ON_UserStringList();
01040 if ( !AttachUserData(us) )
01041 {
01042 delete us;
01043 us = 0;
01044 }
01045 }
01046
01047 return us ? us->SetUserStrings(count,user_strings,bReplace ) : 0;
01048 }
01049
01050
01051 bool ON_Object::GetUserString( const wchar_t* key, ON_wString& string_value ) const
01052 {
01053 string_value.Empty();
01054 const ON_UserStringList* us = ON_UserStringList::Cast(GetUserData(ON_UserStringList::m_ON_UserStringList_class_id.Uuid()));
01055 return us ? us->GetUserString(key,string_value) : false;
01056 }
01057
01058 int ON_Object::UserStringCount() const
01059 {
01060 const ON_UserStringList* us = ON_UserStringList::Cast(GetUserData(ON_UserStringList::m_ON_UserStringList_class_id.Uuid()));
01061 return ( 0 != us )
01062 ? us->m_e.Count()
01063 : 0;
01064 }
01065
01066
01067 int ON_Object::GetUserStrings(
01068 ON_ClassArray<ON_UserString>& user_strings
01069 ) const
01070 {
01071 const int count0 = user_strings.Count();
01072 const ON_UserStringList* us = ON_UserStringList::Cast(GetUserData(ON_UserStringList::m_ON_UserStringList_class_id.Uuid()));
01073 if ( us )
01074 user_strings.Append(us->m_e.Count(),us->m_e.Array());
01075
01076 return user_strings.Count() - count0;
01077 }
01078
01079 int ON_Object::GetUserStringKeys(
01080 ON_ClassArray<ON_wString>& user_string_keys
01081 ) const
01082 {
01083 const int count0 = user_string_keys.Count();
01084 const ON_UserStringList* us = ON_UserStringList::Cast(GetUserData(ON_UserStringList::m_ON_UserStringList_class_id.Uuid()));
01085 if ( us )
01086 {
01087 user_string_keys.Reserve( count0 + us->m_e.Count() );
01088 for (int i = 0; i < us->m_e.Count(); i++ )
01089 {
01090 user_string_keys.Append(us->m_e[i].m_key);
01091 }
01092 }
01093
01094 return user_string_keys.Count() - count0;
01095 }
01096
01097 ON_OBJECT_IMPLEMENT(ON_DocumentUserStringList,ON_Object,"06F3218E-F5EC-4f6c-B74C-14583F0ED7BC");
01098
01099 ON_DocumentUserStringList::ON_DocumentUserStringList()
01100 {
01101 }
01102
01103 ON_DocumentUserStringList::~ON_DocumentUserStringList()
01104 {
01105 }
01106
01107 ON_BOOL32 ON_DocumentUserStringList::IsValid( ON_TextLog* text_log ) const
01108 {
01109 return true;
01110 }
01111
01112 void ON_DocumentUserStringList::Dump( ON_TextLog& ) const
01113 {
01114 }
01115
01116 ON__UINT32 ON_DocumentUserStringList::DataCRC(ON__UINT32 current_remainder) const
01117 {
01118 const ON_UserStringList* us = ON_UserStringList::Cast(GetUserData(ON_UserStringList::m_ON_UserStringList_class_id.Uuid()));
01119 if ( us )
01120 current_remainder = us->DataCRC(current_remainder);
01121 return current_remainder;
01122 }
01123
01124 ON_BOOL32 ON_DocumentUserStringList::Write(ON_BinaryArchive& binary_archive) const
01125 {
01126
01127
01128
01129
01130
01131
01132 unsigned char c = 1;
01133 bool rc = binary_archive.WriteChar(c);
01134
01142
01147
01148 return rc;
01149 }
01150
01151 ON_BOOL32 ON_DocumentUserStringList::Read(ON_BinaryArchive& binary_archive)
01152 {
01153
01154
01155 unsigned char c = 0;
01156 bool rc = binary_archive.ReadChar(&c);
01157 if ( !rc || c < 1 || c > 2 )
01158 return false;
01159
01160 if ( 2 == c )
01161 {
01162
01163
01164
01165
01166 int major_version = 0;
01167 int minor_version = 0;
01168 rc = binary_archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
01169 if (!rc)
01170 return false;
01171 for(;;)
01172 {
01173 rc = (1 == major_version);
01174 if (!rc) break;
01175
01178
01179 break;
01180 }
01181 if (!binary_archive.EndRead3dmChunk() )
01182 rc = false;
01183 }
01184
01185 return rc;
01186 }