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 static bool IdIsNotZero(const ON_UUID* id)
00020 {
00021
00022
00023
00024 const unsigned char* p = (const unsigned char*)id;
00025 unsigned int i = (unsigned int)sizeof(ON_UUID);
00026 while (i--)
00027 {
00028 if (0 != *p++)
00029 return true;
00030 }
00031 return false;
00032 }
00033
00034 static ON__UINT16 IdCRC(const ON_UUID* id)
00035 {
00036
00037
00038 static const ON__UINT16 ON_CRC16_CCITT_TABLE[256] =
00039 {0x0000,0x1021,0x2042,0x3063,0x4084,0x50A5,0x60C6,0x70E7,0x8108,0x9129,0xA14A,0xB16B,0xC18C,0xD1AD,0xE1CE,0xF1EF,
00040 0x1231,0x0210,0x3273,0x2252,0x52B5,0x4294,0x72F7,0x62D6,0x9339,0x8318,0xB37B,0xA35A,0xD3BD,0xC39C,0xF3FF,0xE3DE,
00041 0x2462,0x3443,0x0420,0x1401,0x64E6,0x74C7,0x44A4,0x5485,0xA56A,0xB54B,0x8528,0x9509,0xE5EE,0xF5CF,0xC5AC,0xD58D,
00042 0x3653,0x2672,0x1611,0x0630,0x76D7,0x66F6,0x5695,0x46B4,0xB75B,0xA77A,0x9719,0x8738,0xF7DF,0xE7FE,0xD79D,0xC7BC,
00043 0x48C4,0x58E5,0x6886,0x78A7,0x0840,0x1861,0x2802,0x3823,0xC9CC,0xD9ED,0xE98E,0xF9AF,0x8948,0x9969,0xA90A,0xB92B,
00044 0x5AF5,0x4AD4,0x7AB7,0x6A96,0x1A71,0x0A50,0x3A33,0x2A12,0xDBFD,0xCBDC,0xFBBF,0xEB9E,0x9B79,0x8B58,0xBB3B,0xAB1A,
00045 0x6CA6,0x7C87,0x4CE4,0x5CC5,0x2C22,0x3C03,0x0C60,0x1C41,0xEDAE,0xFD8F,0xCDEC,0xDDCD,0xAD2A,0xBD0B,0x8D68,0x9D49,
00046 0x7E97,0x6EB6,0x5ED5,0x4EF4,0x3E13,0x2E32,0x1E51,0x0E70,0xFF9F,0xEFBE,0xDFDD,0xCFFC,0xBF1B,0xAF3A,0x9F59,0x8F78,
00047 0x9188,0x81A9,0xB1CA,0xA1EB,0xD10C,0xC12D,0xF14E,0xE16F,0x1080,0x00A1,0x30C2,0x20E3,0x5004,0x4025,0x7046,0x6067,
00048 0x83B9,0x9398,0xA3FB,0xB3DA,0xC33D,0xD31C,0xE37F,0xF35E,0x02B1,0x1290,0x22F3,0x32D2,0x4235,0x5214,0x6277,0x7256,
00049 0xB5EA,0xA5CB,0x95A8,0x8589,0xF56E,0xE54F,0xD52C,0xC50D,0x34E2,0x24C3,0x14A0,0x0481,0x7466,0x6447,0x5424,0x4405,
00050 0xA7DB,0xB7FA,0x8799,0x97B8,0xE75F,0xF77E,0xC71D,0xD73C,0x26D3,0x36F2,0x0691,0x16B0,0x6657,0x7676,0x4615,0x5634,
00051 0xD94C,0xC96D,0xF90E,0xE92F,0x99C8,0x89E9,0xB98A,0xA9AB,0x5844,0x4865,0x7806,0x6827,0x18C0,0x08E1,0x3882,0x28A3,
00052 0xCB7D,0xDB5C,0xEB3F,0xFB1E,0x8BF9,0x9BD8,0xABBB,0xBB9A,0x4A75,0x5A54,0x6A37,0x7A16,0x0AF1,0x1AD0,0x2AB3,0x3A92,
00053 0xFD2E,0xED0F,0xDD6C,0xCD4D,0xBDAA,0xAD8B,0x9DE8,0x8DC9,0x7C26,0x6C07,0x5C64,0x4C45,0x3CA2,0x2C83,0x1CE0,0x0CC1,
00054 0xEF1F,0xFF3E,0xCF5D,0xDF7C,0xAF9B,0xBFBA,0x8FD9,0x9FF8,0x6E17,0x7E36,0x4E55,0x5E74,0x2E93,0x3EB2,0x0ED1,0x1EF0};
00055
00056 const unsigned char* b = (const unsigned char*)id;
00057 ON__UINT16 current_remainder;
00058 ON__UINT16 r1;
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 current_remainder = *b++;
00072 current_remainder = (current_remainder << 8) ^ (*b++);
00073
00074 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00075 current_remainder = (current_remainder << 8) ^ (*b++);
00076 current_remainder ^= r1;
00077 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00078 current_remainder = (current_remainder << 8) ^ (*b++);
00079 current_remainder ^= r1;
00080 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00081 current_remainder = (current_remainder << 8) ^ (*b++);
00082 current_remainder ^= r1;
00083 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00084 current_remainder = (current_remainder << 8) ^ (*b++);
00085 current_remainder ^= r1;
00086 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00087 current_remainder = (current_remainder << 8) ^ (*b++);
00088 current_remainder ^= r1;
00089 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00090 current_remainder = (current_remainder << 8) ^ (*b++);
00091 current_remainder ^= r1;
00092 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00093 current_remainder = (current_remainder << 8) ^ (*b++);
00094 current_remainder ^= r1;
00095 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00096 current_remainder = (current_remainder << 8) ^ (*b++);
00097 current_remainder ^= r1;
00098 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00099 current_remainder = (current_remainder << 8) ^ (*b++);
00100 current_remainder ^= r1;
00101 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00102 current_remainder = (current_remainder << 8) ^ (*b++);
00103 current_remainder ^= r1;
00104 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00105 current_remainder = (current_remainder << 8) ^ (*b++);
00106 current_remainder ^= r1;
00107 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00108 current_remainder = (current_remainder << 8) ^ (*b++);
00109 current_remainder ^= r1;
00110 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00111 current_remainder = (current_remainder << 8) ^ (*b++);
00112 current_remainder ^= r1;
00113 r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
00114 current_remainder = (current_remainder << 8) ^ (*b);
00115 current_remainder ^= r1;
00116
00117 return current_remainder;
00118 }
00119
00120 ON_SerialNumberMap::ON_SerialNumberMap(ON_MEMORY_POOL* pool)
00121 {
00122 m_maxsn = 0;
00123 m_reserved = 0;
00124 m_pool = pool;
00125 m_sn_count = 0;
00126 m_sn_purged = 0;
00127 m_snblk_list = 0;
00128 m_snblk_list_capacity = 0;
00129 m_snblk_list_count = 0;
00130 m_e_blk = 0;
00131 m_sn_block0.EmptyBlock();
00132 m_bHashTableIsValid = true;
00133 m_active_id_count = 0;
00134 memset(&m_inactive_id,0,sizeof(m_inactive_id));
00135 memset(m_hash_table,0,sizeof(m_hash_table));
00136 }
00137
00138 ON_SerialNumberMap::~ON_SerialNumberMap()
00139 {
00140 EmptyList();
00141 }
00142
00143 void ON_SerialNumberMap::EmptyList()
00144 {
00145 m_maxsn = 0;
00146 m_sn_count = 0;
00147 m_sn_purged = 0;
00148 m_sn_block0.EmptyBlock();
00149 if (m_snblk_list)
00150 {
00151 size_t i = m_snblk_list_capacity;
00152 while(i--)
00153 {
00154 if ( 0 != m_snblk_list[i] )
00155 onfree(m_snblk_list[i]);
00156 }
00157 onfree(m_snblk_list);
00158 m_snblk_list = 0;
00159 m_snblk_list_capacity = 0;
00160 m_snblk_list_count = 0;
00161 }
00162 m_bHashTableIsValid = true;
00163 m_active_id_count = 0;
00164 memset(m_hash_table,0,sizeof(m_hash_table));
00165 }
00166
00167
00168 void ON_SerialNumberMap::SN_BLOCK::EmptyBlock()
00169 {
00170 m_count = 0;
00171 m_purged = 0;
00172 m_sorted = 1;
00173 m_sn0 = 0;
00174 m_sn1 = 0;
00175 }
00176
00177 void ON_SerialNumberMap::SN_BLOCK::CullBlockHelper()
00178 {
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 size_t i, j;
00189 for (i = 0; i < m_count; i++ )
00190 {
00191 if ( 0 == m_sn[i].m_sn_active )
00192 {
00193 for ( j = i+1; j < m_count; j++ )
00194 {
00195 if ( m_sn[j].m_sn_active )
00196 {
00197 m_sn[i++] = m_sn[j];
00198 }
00199 }
00200 if ( 0 == i )
00201 {
00202 EmptyBlock();
00203 }
00204 else
00205 {
00206 m_count = i;
00207 m_purged = 0;
00208 if ( m_sorted )
00209 {
00210 m_sn0 = m_sn[0].m_sn;
00211 m_sn1 = m_sn[m_count-1].m_sn;
00212 }
00213 }
00214 break;
00215 }
00216 }
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226 #define ON_SORT_TEMPLATE_COMPARE compare_SN_ELEMENT_sn
00227 #define ON_COMPILING_OPENNURBS_QSORT_FUNCTIONS
00228 #define ON_SORT_TEMPLATE_STATIC_FUNCTION
00229 #define ON_SORT_TEMPLATE_TYPE struct ON_SerialNumberMap::SN_ELEMENT
00230 #define ON_QSORT_FNAME ON_qsort_SN_ELEMENT
00231
00232 static int ON_SORT_TEMPLATE_COMPARE(const struct ON_SerialNumberMap::SN_ELEMENT * a, const struct ON_SerialNumberMap::SN_ELEMENT * b)
00233 {
00234 unsigned int asn, bsn;
00235 return ( ( (asn = a->m_sn) < (bsn = b->m_sn) ) ? -1 : (asn > bsn) ? 1 : 0 );
00236 }
00237
00238 #include "pcl/surface/3rdparty/opennurbs/opennurbs_qsort_template.h"
00239
00240 #undef ON_COMPILING_OPENNURBS_QSORT_FUNCTIONS
00241 #undef ON_SORT_TEMPLATE_STATIC_FUNCTION
00242 #undef ON_SORT_TEMPLATE_TYPE
00243 #undef ON_QSORT_FNAME
00244 #undef ON_SORT_TEMPLATE_COMPARE
00245
00246
00247 void ON_SerialNumberMap::SN_BLOCK::SortBlockHelper()
00248 {
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 if ( m_count > 1 )
00265 {
00266 #if 1
00267
00268 ON_qsort_SN_ELEMENT(m_sn, m_count);
00269 #else
00270
00271 size_t i, j, k, i_end;
00272 struct SN_ELEMENT e_tmp;
00273 struct SN_ELEMENT* e;
00274
00275 e = m_sn;
00276
00277 k = m_count >> 1;
00278 i_end = m_count-1;
00279 for (;;)
00280 {
00281 if (k)
00282 {
00283 --k;
00284 e_tmp = e[k];
00285 }
00286 else
00287 {
00288 e_tmp = e[i_end];
00289 e[i_end] = e[0];
00290 if (!(--i_end))
00291 {
00292 e[0] = e_tmp;
00293 break;
00294 }
00295 }
00296
00297 i = k;
00298 j = (k<<1) + 1;
00299 while (j <= i_end)
00300 {
00301 if (j < i_end && e[j].m_sn < e[j + 1].m_sn)
00302 j++;
00303 if (e_tmp.m_sn < e[j].m_sn)
00304 {
00305 e[i] = e[j];
00306 i = j;
00307 j = (j<<1) + 1;
00308 }
00309 else
00310 j = i_end + 1;
00311 }
00312 e[i] = e_tmp;
00313 }
00314 #endif
00315 m_sn0 = m_sn[0].m_sn;
00316 m_sn1 = m_sn[m_count-1].m_sn;
00317 }
00318 else
00319 {
00320 m_sn0 = m_sn1 = ((1 == m_count) ? m_sn[0].m_sn : 0);
00321 }
00322 m_sorted = 1;
00323 }
00324
00325
00326 static bool ON_SerialNumberMap_IsNotValidBlock()
00327 {
00328 return ON_IsNotValid();
00329 }
00330
00331 bool ON_SerialNumberMap::SN_BLOCK::IsValidBlock(ON_TextLog* textlog,
00332 struct SN_ELEMENT*const* hash_table,
00333 size_t* active_id_count) const
00334 {
00335 unsigned int sn0, sn;
00336 size_t i, pc, aidcnt;
00337
00338 if ( m_count > SN_BLOCK_CAPACITY )
00339 {
00340 if (textlog)
00341 textlog->Print("SN_BLOCK m_count = %u (should be >=0 and <%u).\n",
00342 m_count,SN_BLOCK_CAPACITY);
00343 return ON_SerialNumberMap_IsNotValidBlock();
00344 }
00345
00346 if ( m_purged > m_count )
00347 {
00348 if (textlog)
00349 textlog->Print("SN_BLOCK m_purged = %u (should be >0 and <=%u).\n",
00350 m_purged,m_count);
00351 return ON_SerialNumberMap_IsNotValidBlock();
00352 }
00353
00354 if ( m_count < 2 && 1 != m_sorted )
00355 {
00356 if (textlog)
00357 textlog->Print("SN_BLOCK m_count = %u but m_sorted is not 1.\n",m_count);
00358 return ON_SerialNumberMap_IsNotValidBlock();
00359 }
00360
00361 if ( 0 == m_count )
00362 {
00363 if ( 0 != m_sn0 )
00364 {
00365 if (textlog)
00366 textlog->Print("SN_BLOCK m_count = 0 but m_sn0 != 0.\n");
00367 return ON_SerialNumberMap_IsNotValidBlock();
00368 }
00369 if ( 0 != m_sn1 )
00370 {
00371 if (textlog)
00372 textlog->Print("SN_BLOCK m_count = 0 but m_sn1 != 0.\n");
00373 return ON_SerialNumberMap_IsNotValidBlock();
00374 }
00375 return true;
00376 }
00377
00378 if ( m_sn1 < m_sn0 )
00379 {
00380 if (textlog)
00381 textlog->Print("SN_BLOCK m_sn1 < m_sn0.\n");
00382 return ON_SerialNumberMap_IsNotValidBlock();
00383 }
00384
00385 if ( m_count > m_purged )
00386 {
00387 if ( m_sn1 - m_sn0 < m_count-m_purged-1 )
00388 {
00389 if (textlog)
00390 textlog->Print("SN_BLOCK m_sn1 < m_sn0.\n");
00391 return ON_SerialNumberMap_IsNotValidBlock();
00392 }
00393 }
00394
00395 sn0 = 0;
00396 pc = 0;
00397 aidcnt = 0;
00398 for (i = 0; i < m_count; i++)
00399 {
00400
00401 if (0 == m_sn[i].m_sn_active)
00402 {
00403
00404
00405 pc++;
00406 if ( 0 != m_sn[i].m_id_active )
00407 {
00408 if (textlog)
00409 textlog->Print("SN_BLOCK m_sn[%d].m_sn_active = 0 but m_id_active != 0.\n",i);
00410 return ON_SerialNumberMap_IsNotValidBlock();
00411 }
00412 }
00413 else if ( 0 != m_sn[i].m_id_active )
00414 {
00415
00416
00417 aidcnt++;
00418 if ( IdIsNotZero(&m_sn[i].m_id) )
00419 {
00420 const SN_ELEMENT* e;
00421 for (e = hash_table[IdCRC(&m_sn[i].m_id) % ID_HASH_TABLE_COUNT]; 0!=e; e = e->m_next)
00422 {
00423 if ( e == &m_sn[i] )
00424 {
00425
00426 break;
00427 }
00428 }
00429 if ( 0 == e )
00430 {
00431
00432
00433 if (textlog)
00434 textlog->Print("SN_BLOCK m_sn[%d].m_id_active != 0 but the element is not in m_hash_table[].\n",i);
00435 return ON_SerialNumberMap_IsNotValidBlock();
00436 }
00437 }
00438 else
00439 {
00440 if (textlog)
00441 textlog->Print("SN_BLOCK m_sn[%d].m_id_active != 0 but m_id = 0.\n",i);
00442 return ON_SerialNumberMap_IsNotValidBlock();
00443 }
00444 }
00445
00446
00447 sn = m_sn[i].m_sn;
00448 if ( sn < m_sn0 )
00449 {
00450 if (textlog)
00451 textlog->Print("SN_BLOCK m_sn[%d] < m_sn0.\n",i);
00452 return ON_SerialNumberMap_IsNotValidBlock();
00453 }
00454 if ( sn > m_sn1 )
00455 {
00456 if (textlog)
00457 textlog->Print("SN_BLOCK m_sn[%d] > m_sn1.\n",i);
00458 return ON_SerialNumberMap_IsNotValidBlock();
00459 }
00460
00461 if ( m_sorted )
00462 {
00463
00464 if (sn <= sn0 )
00465 {
00466 if (textlog)
00467 textlog->Print("SN_BLOCK m_sn[%d] > m_sn[%d].\n",i,i-1);
00468 return ON_SerialNumberMap_IsNotValidBlock();
00469 }
00470 sn0 = sn;
00471 }
00472 }
00473
00474 if ( pc != m_purged )
00475 {
00476 if (textlog)
00477 textlog->Print("SN_BLOCK m_purged = %u (should be %u)\n",m_purged,pc);
00478 return ON_SerialNumberMap_IsNotValidBlock();
00479 }
00480
00481
00482
00483 if ( 0 != active_id_count )
00484 *active_id_count += aidcnt;
00485
00486 return true;
00487 }
00488
00489 struct ON_SerialNumberMap::SN_ELEMENT* ON_SerialNumberMap::SN_BLOCK::BinarySearchBlockHelper(unsigned int sn)
00490 {
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 size_t i, j;
00501 struct SN_ELEMENT* e;
00502 unsigned int midsn;
00503
00504 i = m_count;
00505 e = m_sn;
00506 while (i > 0 )
00507 {
00508 midsn = e[(j=i/2)].m_sn;
00509 if ( sn < midsn )
00510 {
00511 i = j;
00512 }
00513 else if ( sn > midsn )
00514 {
00515 j++;
00516 e += j;
00517 i -= j;
00518 }
00519 else
00520 {
00521 return e + j;
00522 }
00523 }
00524 return 0;
00525 }
00526
00527 void ON_SerialNumberMap::UpdateMaxSNHelper()
00528 {
00529 m_maxsn = (m_snblk_list_count > 0) ? m_snblk_list[m_snblk_list_count-1]->m_sn1 : 0;
00530 if ( m_maxsn < m_sn_block0.m_sn1 )
00531 m_maxsn = m_sn_block0.m_sn1;
00532 }
00533
00534 struct ON_SerialNumberMap::SN_ELEMENT* ON_SerialNumberMap::FindElementHelper(unsigned int sn)
00535 {
00536 struct SN_BLOCK** eblk_array;
00537 struct SN_BLOCK* eblk;
00538 size_t i, j;
00539
00540 if ( m_maxsn < sn )
00541 return 0;
00542
00543 if ( sn <= 0 )
00544 return 0;
00545
00546
00547
00548 if ( sn <= m_sn_block0.m_sn1 && m_sn_block0.m_sn0 <= sn )
00549 {
00550 SN_ELEMENT* e;
00551
00552 m_e_blk = &m_sn_block0;
00553 if ( !m_sn_block0.m_sorted )
00554 {
00555
00556
00557
00558
00559
00560
00561
00562
00563 if ( m_sn_block0.m_purged > 0 )
00564 {
00565 InvalidateHashTableHelper();
00566 m_sn_count -= m_sn_block0.m_purged;
00567 m_sn_purged -= m_sn_block0.m_purged;
00568 m_sn_block0.CullBlockHelper();
00569 UpdateMaxSNHelper();
00570 }
00571 if ( m_sn_block0.m_count > 0 )
00572 {
00573 InvalidateHashTableHelper();
00574 m_sn_block0.SortBlockHelper();
00575 }
00576 e = ( sn <= m_sn_block0.m_sn1 && m_sn_block0.m_sn0 <= sn )
00577 ? m_sn_block0.BinarySearchBlockHelper(sn)
00578 : 0;
00579 }
00580 else if ( m_sn_block0.m_purged > m_sn_block0.m_count/SN_PURGE_RATIO )
00581 {
00582 InvalidateHashTableHelper();
00583 m_sn_count -= m_sn_block0.m_purged;
00584 m_sn_purged -= m_sn_block0.m_purged;
00585 m_sn_block0.CullBlockHelper();
00586 UpdateMaxSNHelper();
00587 e = ( sn <= m_sn_block0.m_sn1 && m_sn_block0.m_sn0 <= sn )
00588 ? m_sn_block0.BinarySearchBlockHelper(sn)
00589 : 0;
00590 }
00591 else
00592 {
00593 e = m_sn_block0.BinarySearchBlockHelper(sn);
00594 }
00595 if (e)
00596 return e;
00597 }
00598
00599
00600
00601
00602
00603 if ( 0 == (i = m_snblk_list_count) )
00604 {
00605 return 0;
00606 }
00607 eblk_array = m_snblk_list;
00608 while (i > 0 )
00609 {
00610 eblk = eblk_array[(j=i/2)];
00611
00612
00613
00614
00615
00616 if ( eblk->m_purged > eblk->m_count/SN_PURGE_RATIO )
00617 {
00618
00619 InvalidateHashTableHelper();
00620 m_sn_count -= eblk->m_purged;
00621 m_sn_purged -= eblk->m_purged;
00622 eblk->CullBlockHelper();
00623 if ( 0 == eblk->m_count )
00624 {
00625
00626 for( j += ((eblk_array-m_snblk_list)+1); j < m_snblk_list_count; j++ )
00627 {
00628 m_snblk_list[j-1] = m_snblk_list[j];
00629 }
00630 m_snblk_list_count--;
00631 m_snblk_list[m_snblk_list_count] = eblk;
00632 i--;
00633 UpdateMaxSNHelper();
00634 continue;
00635 }
00636 UpdateMaxSNHelper();
00637 }
00638
00639 if ( sn < eblk->m_sn0 )
00640 {
00641 i = j;
00642 }
00643 else if ( sn > eblk->m_sn1 )
00644 {
00645 j++;
00646 eblk_array += j;
00647 i -= j;
00648 }
00649 else
00650 {
00651 m_e_blk = eblk;
00652 return eblk->BinarySearchBlockHelper(sn);
00653 }
00654 }
00655
00656 return 0;
00657 }
00658
00659 size_t ON_SerialNumberMap::ActiveSerialNumberCount() const
00660 {
00661 return m_sn_count - m_sn_purged;
00662 }
00663
00664 size_t ON_SerialNumberMap::ActiveIdCount() const
00665 {
00666 return m_active_id_count;
00667 }
00668
00669 struct ON_SerialNumberMap::SN_ELEMENT* ON_SerialNumberMap::FirstElement() const
00670 {
00671 struct SN_ELEMENT* e=0;
00672 size_t i,j;
00673
00674
00675
00676 for(i = 0; i < m_snblk_list_count; i++)
00677 {
00678 if ( m_snblk_list[i]->m_count > m_snblk_list[i]->m_purged )
00679 {
00680 for ( j = 0; j < m_snblk_list[i]->m_count; j++ )
00681 {
00682 if ( m_snblk_list[i]->m_sn[j].m_sn_active )
00683 {
00684 e = &m_snblk_list[i]->m_sn[j];
00685 break;
00686 }
00687 }
00688 break;
00689 }
00690 }
00691
00692 if ( m_sn_block0.m_count > m_sn_block0.m_purged
00693 && (!e || m_sn_block0.m_sn0 < e->m_sn)
00694 )
00695 {
00696
00697 if ( m_sn_block0.m_purged > 0 )
00698 {
00699
00700 const_cast<ON_SerialNumberMap*>(this)->InvalidateHashTableHelper();
00701 const_cast<ON_SerialNumberMap*>(this)->m_sn_count -= m_sn_block0.m_purged;
00702 const_cast<ON_SerialNumberMap*>(this)->m_sn_purged -= m_sn_block0.m_purged;
00703 const_cast<ON_SerialNumberMap*>(this)->m_sn_block0.CullBlockHelper();
00704 }
00705 if ( !m_sn_block0.m_sorted )
00706 {
00707
00708 const_cast<ON_SerialNumberMap*>(this)->InvalidateHashTableHelper();
00709 const_cast<ON_SerialNumberMap*>(this)->m_sn_block0.SortBlockHelper();
00710 }
00711 if ( !e || m_sn_block0.m_sn0 < e->m_sn )
00712 {
00713
00714
00715 e = const_cast<struct SN_ELEMENT*>(&m_sn_block0.m_sn[0]);
00716 }
00717 }
00718 return e;
00719 }
00720
00721 struct ON_SerialNumberMap::SN_ELEMENT* ON_SerialNumberMap::LastElement() const
00722 {
00723 struct SN_ELEMENT* e=0;
00724 size_t i,j;
00725
00726
00727
00728 if ( m_sn_block0.m_count > m_sn_block0.m_purged )
00729 {
00730 if ( m_sn_block0.m_purged > 0 )
00731 {
00732
00733 const_cast<ON_SerialNumberMap*>(this)->InvalidateHashTableHelper();
00734 const_cast<ON_SerialNumberMap*>(this)->m_sn_count -= m_sn_block0.m_purged;
00735 const_cast<ON_SerialNumberMap*>(this)->m_sn_purged -= m_sn_block0.m_purged;
00736 const_cast<ON_SerialNumberMap*>(this)->m_sn_block0.CullBlockHelper();
00737 }
00738 if ( !m_sn_block0.m_sorted )
00739 {
00740
00741 const_cast<ON_SerialNumberMap*>(this)->InvalidateHashTableHelper();
00742 const_cast<ON_SerialNumberMap*>(this)->m_sn_block0.SortBlockHelper();
00743 }
00744 e = const_cast<struct SN_ELEMENT*>(&m_sn_block0.m_sn[m_sn_block0.m_count-1]);
00745 }
00746
00747 i = m_snblk_list_count;
00748 while(i--)
00749 {
00750 if ( m_snblk_list[i]->m_count > m_snblk_list[i]->m_purged )
00751 {
00752 if (e && e->m_sn > m_snblk_list[i]->m_sn1 )
00753 break;
00754 j = m_snblk_list[i]->m_count;
00755 while(j--)
00756 {
00757 if ( m_snblk_list[i]->m_sn[j].m_sn_active )
00758 {
00759 e = &m_snblk_list[i]->m_sn[j];
00760 break;
00761 }
00762 }
00763 break;
00764 }
00765 }
00766
00767 return e;
00768 }
00769
00770 struct ON_SerialNumberMap::SN_ELEMENT* ON_SerialNumberMap::FindSerialNumber(unsigned int sn) const
00771 {
00772 struct SN_ELEMENT* e = const_cast<ON_SerialNumberMap*>(this)->FindElementHelper(sn);
00773 return ( (e && e->m_sn_active) ? e : 0);
00774 }
00775
00776 struct ON_SerialNumberMap::SN_ELEMENT* ON_SerialNumberMap::FindId(ON_UUID id) const
00777 {
00778 struct SN_ELEMENT* e = 0;
00779 size_t i;
00780
00781 if ( m_active_id_count > 0 )
00782 {
00783 i = HashIndex(&id);
00784 if ( 0 != i || IdIsNotZero(&id) )
00785 {
00786 if ( !m_bHashTableIsValid )
00787 {
00788 const_cast<ON_SerialNumberMap*>(this)->BuildHashTableHelper();
00789 }
00790 e = m_hash_table[i];
00791 while(e)
00792 {
00793 if ( 0 == memcmp(&e->m_id,&id,sizeof(e->m_id)) )
00794 break;
00795 e = e->m_next;
00796 }
00797 }
00798 }
00799 return e;
00800 }
00801
00802
00803 size_t ON_SerialNumberMap::GetElements(
00804 unsigned int sn0,
00805 unsigned int sn1,
00806 size_t max_count,
00807 ON_SimpleArray<SN_ELEMENT>& elements
00808 ) const
00809 {
00810 size_t i,j,k,c;
00811 const SN_ELEMENT *ei, *ek;
00812
00813 const int elements_count0 = elements.Count();
00814
00815 if ( sn1 < sn0 || max_count <= 0 || m_sn_count <= m_sn_purged )
00816 return 0;
00817
00818 if ( sn0+3 <= sn1 )
00819 {
00820 elements.Reserve(elements_count0+3);
00821 while ( sn0 <= sn1 )
00822 {
00823 ei = const_cast<ON_SerialNumberMap*>(this)->FindElementHelper(sn0++);
00824 if ( ei && ei->m_sn_active )
00825 elements.Append(*ei);
00826 }
00827 return (elements.Count() - elements_count0);
00828 }
00829
00830 ek = 0;
00831 k = 0;
00832 for ( j = 0; j < m_snblk_list_count; j++ )
00833 {
00834 if ( m_snblk_list[j]->m_sn1 < sn0 )
00835 continue;
00836 if ( sn1 < m_snblk_list[j]->m_sn0 )
00837 break;
00838
00839 k = m_snblk_list[j]->m_count;
00840 ek = &m_snblk_list[j]->m_sn[0];
00841 while ( ek->m_sn < sn0 || !ek->m_sn_active )
00842 {
00843 if ( --k )
00844 {
00845 if ((++ek)->m_sn > sn1)
00846 {
00847 ek = 0;
00848 break;
00849 }
00850 }
00851 else if ( ++j < m_snblk_list_count && m_snblk_list[j]->m_sn0 <= sn1 )
00852 {
00853 k = m_snblk_list[j]->m_count;
00854 ek = &m_snblk_list[j]->m_sn[0];
00855 }
00856 else
00857 {
00858 ek = 0;
00859 break;
00860 }
00861 }
00862 if ( ek && ek->m_sn > sn1 )
00863 ek = 0;
00864 break;
00865 }
00866
00867
00868 if ( ek )
00869 {
00870 c = m_snblk_list[j]->ActiveElementEstimate(ek->m_sn,sn1);
00871 for ( i = j+1; i < m_snblk_list_count && m_snblk_list[i]->m_sn0 <= sn1; i++ )
00872 {
00873 c += m_snblk_list[j]->ActiveElementEstimate(ek->m_sn,sn1);
00874 }
00875 }
00876 else
00877 c = 0;
00878
00879
00880 i = 0;
00881 ei = 0;
00882 if ( m_sn_block0.m_count > m_sn_block0.m_purged
00883 && sn1 >= m_sn_block0.m_sn0
00884 && sn0 <= m_sn_block0.m_sn1
00885 && !m_sn_block0.m_sorted
00886 )
00887 {
00888 if ( !m_sn_block0.m_sorted )
00889 {
00890 if ( m_sn_block0.m_purged > 0 )
00891 {
00892 const_cast<ON_SerialNumberMap*>(this)->InvalidateHashTableHelper();
00893 const_cast<ON_SerialNumberMap*>(this)->m_sn_count -= m_sn_block0.m_purged;
00894 const_cast<ON_SerialNumberMap*>(this)->m_sn_purged -= m_sn_block0.m_purged;
00895 const_cast<ON_SerialNumberMap*>(this)->m_sn_block0.CullBlockHelper();
00896 const_cast<ON_SerialNumberMap*>(this)->UpdateMaxSNHelper();
00897 }
00898 if ( m_sn_block0.m_count > 0 )
00899 {
00900 const_cast<ON_SerialNumberMap*>(this)->InvalidateHashTableHelper();
00901 const_cast<ON_SerialNumberMap*>(this)->m_sn_block0.SortBlockHelper();
00902 if ( sn1 >= m_sn_block0.m_sn0 && sn0 <= m_sn_block0.m_sn1 )
00903 {
00904 i = m_sn_block0.m_count;
00905 ei = &m_sn_block0.m_sn[0];
00906 }
00907 }
00908 }
00909 else
00910 {
00911 i = m_sn_block0.m_count;
00912 ei = &m_sn_block0.m_sn[0];
00913 while ( ei->m_sn < sn0 || !ei->m_sn_active )
00914 {
00915 if ( --i )
00916 ei++;
00917 else
00918 {
00919 ei = 0;
00920 break;
00921 }
00922 }
00923 if ( ei && ei->m_sn > sn1 )
00924 {
00925 ei = 0;
00926 }
00927 }
00928 }
00929
00930
00931 if ( ei )
00932 c += m_sn_block0.ActiveElementEstimate(ei->m_sn,sn1);
00933 if (c > (sn1-sn0+1) )
00934 c = (sn1-sn0+1);
00935 if ( c > 2*4096 )
00936 c = 2*4096;
00937
00938
00939
00940 elements.Reserve(elements.Count()+((int)c));
00941
00942
00943 while (ei || ek)
00944 {
00945 if (ei && (!ek || ei->m_sn < ek->m_sn) )
00946 {
00947 if ( ei->m_sn_active )
00948 elements.Append(*ei);
00949 if ( --i )
00950 {
00951 if ( (++ei)->m_sn > sn1 )
00952 {
00953 ei = 0;
00954 }
00955 }
00956 else
00957 {
00958 ei = 0;
00959 }
00960 }
00961 else
00962 {
00963 if ( ek->m_sn_active )
00964 elements.Append(*ei);
00965 if ( --k )
00966 {
00967 if ( (++ek)->m_sn > sn1 )
00968 {
00969 ek = 0;
00970 }
00971 }
00972 else if (++j < m_snblk_list_count && sn1 <= m_snblk_list[j]->m_sn0 )
00973 {
00974 k = m_snblk_list[j]->m_count;
00975 ek = &m_snblk_list[j]->m_sn[0];
00976 }
00977 else
00978 {
00979 ek = 0;
00980 }
00981 }
00982 }
00983
00984 return (elements.Count() - elements_count0);
00985 }
00986
00987 struct ON_SerialNumberMap::SN_ELEMENT*
00988 ON_SerialNumberMap::RemoveSerialNumberAndId(unsigned int sn)
00989 {
00990 struct SN_ELEMENT* e = FindElementHelper(sn);
00991 if ( e && e->m_sn_active )
00992 {
00993 if ( e->m_id_active )
00994 {
00995 if ( m_bHashTableIsValid )
00996 {
00997
00998 size_t i = HashIndex(&e->m_id);
00999 struct SN_ELEMENT* prev = 0;
01000 struct SN_ELEMENT* h;
01001 for ( h = m_hash_table[i]; h; h = h->m_next )
01002 {
01003 if (h == e)
01004 {
01005 if ( prev )
01006 {
01007 prev->m_next = e->m_next;
01008 }
01009 else
01010 {
01011 m_hash_table[i] = e->m_next;
01012 }
01013 break;
01014 }
01015 prev = h;
01016 }
01017 }
01018 e->m_next = 0;
01019 e->m_id_active = 0;
01020 if ( m_active_id_count > 0 )
01021 {
01022 m_active_id_count--;
01023 }
01024 else
01025 {
01026 ON_ERROR("ON_SerialNumberMap - m_active_id_count corruption");
01027 }
01028
01029
01030
01031
01032 m_inactive_id = e->m_id;
01033 }
01034
01035 e->m_sn_active = 0;
01036 m_sn_purged++;
01037 if ( m_e_blk->m_count == ++m_e_blk->m_purged )
01038 {
01039
01040 if ( m_e_blk == &m_sn_block0 )
01041 {
01042
01043
01044 m_sn_count -= m_sn_block0.m_count;
01045 m_sn_purged -= m_sn_block0.m_count;
01046 m_sn_block0.EmptyBlock();
01047 }
01048 else if ( m_e_blk->m_count > 1 )
01049 {
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059 m_sn_count -= (m_e_blk->m_count-1);
01060 m_sn_purged -= (m_e_blk->m_count-1);
01061 m_e_blk->m_count = 1;
01062 m_e_blk->m_purged = 1;
01063 m_e_blk->m_sn0 = m_e_blk->m_sn1 = m_e_blk->m_sn[0].m_sn;
01064 }
01065 }
01066 return e;
01067 }
01068
01069 return 0;
01070 }
01071
01072 struct ON_SerialNumberMap::SN_ELEMENT*
01073 ON_SerialNumberMap::RemoveId(unsigned int sn, ON_UUID id)
01074 {
01075 struct SN_ELEMENT* e=0;
01076 struct SN_ELEMENT* prev;
01077 size_t i;
01078 if ( m_active_id_count > 0 )
01079 {
01080 i = HashIndex(&id);
01081 if ( i != 0 || IdIsNotZero(&id) )
01082 {
01083 if ( !m_bHashTableIsValid && sn > 0 )
01084 {
01085
01086
01087 e = FindSerialNumber(sn);
01088 if (e)
01089 {
01090 if (e->m_id_active && 0 == memcmp(&e->m_id,&id,sizeof(e->m_id)) )
01091 {
01092 e->m_next = 0;
01093 e->m_id_active = 0;
01094 m_active_id_count--;
01095 m_inactive_id = e->m_id;
01096 }
01097 else
01098 {
01099
01100 e = 0;
01101 }
01102 }
01103 }
01104 else
01105 {
01106 BuildHashTableHelper();
01107 prev = 0;
01108 for( e = m_hash_table[i]; e; e = e->m_next )
01109 {
01110 if ( 0 == memcmp(&e->m_id,&id,sizeof(e->m_id)) )
01111 {
01112 if ( prev )
01113 prev->m_next = e->m_next;
01114 else
01115 m_hash_table[i] = e->m_next;
01116 e->m_next = 0;
01117 e->m_id_active = 0;
01118 m_active_id_count--;
01119 m_inactive_id = e->m_id;
01120 break;
01121 }
01122 prev = e;
01123 }
01124 }
01125 }
01126 }
01127 return e;
01128 }
01129
01130
01131 int ON_SerialNumberMap::SN_BLOCK::CompareMaxSN(const void* a, const void* b)
01132 {
01133 const unsigned int sna = (*((const SN_BLOCK*const*)a))->m_sn1;
01134 const unsigned int snb = (*((const SN_BLOCK*const*)b))->m_sn1;
01135 if ( sna < snb )
01136 {
01137 return (0 == sna) ? 1 : -1;
01138 }
01139 if ( snb < sna )
01140 {
01141 return (0 == snb) ? -1 : 1;
01142 }
01143 return 0;
01144 }
01145
01146 size_t ON_SerialNumberMap::SN_BLOCK::ActiveElementEstimate(unsigned int sn0, unsigned int sn1) const
01147 {
01148 size_t c = m_count-m_purged;
01149 if ( c > 0 )
01150 {
01151 if ( sn0 < m_sn0 )
01152 sn0 = m_sn0;
01153 if ( sn1 > m_sn1 )
01154 sn1 = m_sn1;
01155 sn1 -= sn0;
01156 sn1++;
01157 if (c > sn1)
01158 c = sn1;
01159 }
01160 return c;
01161 }
01162
01163 static bool ON_SerialNumberMap_IsNotValid()
01164 {
01165 return ON_IsNotValid();
01166 }
01167
01168 bool ON_SerialNumberMap::IsValid(ON_TextLog* textlog) const
01169 {
01170 size_t i, c, pc, aic;
01171
01172 aic = 0;
01173
01174 const_cast<ON_SerialNumberMap*>(this)->BuildHashTableHelper();
01175
01176 if ( !m_sn_block0.IsValidBlock(textlog,m_hash_table,&aic) )
01177 {
01178 if ( textlog )
01179 textlog->Print("m_sn_block0 is not valid\n");
01180 return ON_SerialNumberMap_IsNotValid();
01181 }
01182
01183 c = m_sn_block0.m_count;
01184 pc = m_sn_block0.m_purged;
01185
01186 for ( i = 0; i < m_snblk_list_count; i++ )
01187 {
01188 if ( 0 == m_snblk_list[i]->m_count )
01189 {
01190 if ( textlog )
01191 textlog->Print("m_snblk_list[%d] is empty\n",i);
01192 return ON_SerialNumberMap_IsNotValid();
01193 }
01194 if ( 1 != m_snblk_list[i]->m_sorted )
01195 {
01196 if ( textlog )
01197 textlog->Print("m_snblk_list[%d] is not sorted\n",i);
01198 return ON_SerialNumberMap_IsNotValid();
01199 }
01200 if ( !m_snblk_list[i]->IsValidBlock(textlog,m_hash_table,&aic) )
01201 {
01202 if ( textlog )
01203 textlog->Print("m_snblk_list[%d] is not valid\n",i);
01204 return ON_SerialNumberMap_IsNotValid();
01205 }
01206 c += m_snblk_list[i]->m_count;
01207 pc += m_snblk_list[i]->m_purged;
01208 if ( i>0 && m_snblk_list[i]->m_sn0 <= m_snblk_list[i-1]->m_sn1 )
01209 {
01210 if ( textlog )
01211 textlog->Print("m_snblk_list[%d]->m_sn0 <= m_snblk_list[%d]->m_sn1\n",i,i-1);
01212 return ON_SerialNumberMap_IsNotValid();
01213 }
01214 }
01215
01216 if ( c != m_sn_count )
01217 {
01218 if ( textlog )
01219 textlog->Print("m_sn_count=%d (should be %d) is not correct\n",m_sn_count,c);
01220 return ON_SerialNumberMap_IsNotValid();
01221 }
01222
01223 if ( pc != m_sn_purged )
01224 {
01225 if ( textlog )
01226 textlog->Print("m_sn_purged=%d (should be %d) is not correct\n",m_sn_purged,pc);
01227 return ON_SerialNumberMap_IsNotValid();
01228 }
01229
01230 if ( m_active_id_count != aic )
01231 {
01232 if ( textlog )
01233 textlog->Print("m_active_id_count=%d (should be %d) is not correct\n",m_active_id_count,aic);
01234 return ON_SerialNumberMap_IsNotValid();
01235 }
01236
01237 if ( m_active_id_count + m_sn_purged > m_sn_count )
01238 {
01239 if ( textlog )
01240 textlog->Print("m_active_id_count=%d > %d = (m_sn_count-m_sn_purged)\n",m_active_id_count,m_sn_count-m_sn_purged);
01241 return ON_SerialNumberMap_IsNotValid();
01242 }
01243
01244 c = 0;
01245 for ( i = 0; i < ID_HASH_TABLE_COUNT; i++ )
01246 {
01247 const SN_ELEMENT* e;
01248 for (e = m_hash_table[i]; e && c <= m_active_id_count; e = e->m_next)
01249 {
01250 c++;
01251 }
01252 }
01253
01254 if ( c > m_active_id_count )
01255 {
01256 if ( textlog )
01257 textlog->Print("m_hash_table[] linked lists have too many elements.\n");
01258 return ON_SerialNumberMap_IsNotValid();
01259 }
01260
01261 return true;
01262 }
01263
01264 size_t ON_SerialNumberMap::GarbageCollectMoveHelper(ON_SerialNumberMap::SN_BLOCK* dst,ON_SerialNumberMap::SN_BLOCK* src)
01265 {
01266
01267
01268
01269 size_t i,j,n;
01270 if ( src && dst )
01271 {
01272 n = SN_BLOCK_CAPACITY - dst->m_count;
01273 if ( src->m_count < n )
01274 n = src->m_count;
01275 if ( n > 0 )
01276 {
01277 if ( 0 == dst->m_count )
01278 {
01279 dst->EmptyBlock();
01280 }
01281 if ( 0 == src->m_sorted )
01282 {
01283 dst->m_sorted = 0;
01284 if ( 0 == dst->m_count )
01285 {
01286 dst->m_sn0 = src->m_sn0;
01287 dst->m_sn1 = src->m_sn1;
01288 }
01289 }
01290 memcpy(&dst->m_sn[dst->m_count],&src->m_sn[0],n*sizeof(src->m_sn[0]));
01291 dst->m_count += n;
01292 if ( dst->m_sorted )
01293 {
01294 dst->m_sn0 = dst->m_sn[0].m_sn;
01295 dst->m_sn1 = dst->m_sn[dst->m_count-1].m_sn;
01296 }
01297 else
01298 {
01299 if ( dst->m_sn0 > src->m_sn0 )
01300 dst->m_sn0 = src->m_sn0;
01301 if ( dst->m_sn1 < src->m_sn1 )
01302 dst->m_sn1 = src->m_sn1;
01303 }
01304 i = 0; j = n;
01305 while ( j < src->m_count )
01306 {
01307 src->m_sn[i++] = src->m_sn[j++];
01308 }
01309 src->m_count = i;
01310 if ( src->m_count > 0 )
01311 {
01312 if ( src->m_sorted )
01313 src->m_sn0 = src->m_sn[0].m_sn;
01314 }
01315 else
01316 {
01317 src->EmptyBlock();
01318 }
01319 }
01320 }
01321 else
01322 {
01323 n = 0;
01324 }
01325 return n;
01326 }
01327
01328 void ON_SerialNumberMap::GarbageCollectHelper()
01329 {
01330 size_t i,j,k,n;
01331
01332
01333
01334
01335 InvalidateHashTableHelper();
01336
01337 if ( m_sn_block0.m_purged > 0 )
01338 {
01339 m_sn_count -= m_sn_block0.m_purged;
01340 m_sn_purged -= m_sn_block0.m_purged;
01341 m_sn_block0.CullBlockHelper();
01342 if ( !m_sn_block0.m_sorted )
01343 m_sn_block0.SortBlockHelper();
01344 if ( 0 == m_snblk_list_count )
01345 m_maxsn = m_sn_block0.m_sn1;
01346 if ( m_sn_block0.m_count < 7*(SN_BLOCK_CAPACITY/8) )
01347 return;
01348 }
01349 else if ( !m_sn_block0.m_sorted )
01350 {
01351 m_sn_block0.SortBlockHelper();
01352 if ( 0 == m_snblk_list_count )
01353 m_maxsn = m_sn_block0.m_sn1;
01354 }
01355
01356
01357
01358 m_sn_purged = 0;
01359 m_sn_count = m_sn_block0.m_count;
01360 i = m_snblk_list_count;
01361 while (i--)
01362 {
01363 if ( m_snblk_list[i]->m_purged > 0 )
01364 {
01365
01366 m_snblk_list[i]->CullBlockHelper();
01367 }
01368 m_sn_count += m_snblk_list[i]->m_count;
01369 }
01370
01371
01372 for ( i = 0; i < m_snblk_list_count; i++ )
01373 {
01374 if ( 0 == m_snblk_list[i]->m_count )
01375 {
01376
01377 for(j = i+1; j < m_snblk_list_count; j++ )
01378 {
01379 if ( m_snblk_list[j]->m_count > 0 )
01380 {
01381
01382 ON_qsort(m_snblk_list+i,m_snblk_list_count-i,sizeof(*m_snblk_list),SN_BLOCK::CompareMaxSN);
01383 break;
01384 }
01385 }
01386 while ( m_snblk_list_count > 0 && 0 == m_snblk_list[m_snblk_list_count-1]->m_count )
01387 m_snblk_list_count--;
01388 break;
01389 }
01390 }
01391
01392 if ( m_snblk_list_count > 0
01393 && m_snblk_list[m_snblk_list_count-1]->m_sn1 > m_sn_block0.m_sn0
01394 )
01395 {
01396
01397
01398
01399 size_t snarray_count = 0;
01400 struct SN_ELEMENT* snarray = (struct SN_ELEMENT*)onmalloc_from_pool(m_pool,2*SN_BLOCK_CAPACITY*sizeof(snarray[0]));
01401 for ( i = 0; i < m_snblk_list_count && m_sn_block0.m_count > 0; i++ )
01402 {
01403 if ( m_snblk_list[i]->m_sn1 < m_sn_block0.m_sn0 )
01404 continue;
01405
01406
01407
01408 SN_BLOCK* blk = m_snblk_list[i];
01409 const unsigned int sn1 = (i < m_snblk_list_count-1)
01410 ? m_snblk_list[i+1]->m_sn0
01411 : (m_sn_block0.m_sn1+1);
01412 snarray_count = j = k = 0;
01413 while(j < blk->m_count && k < m_sn_block0.m_count )
01414 {
01415 if ( blk->m_sn[j].m_sn < m_sn_block0.m_sn[k].m_sn )
01416 {
01417 snarray[snarray_count++] = blk->m_sn[j++];
01418 }
01419 else if ( m_sn_block0.m_sn[k].m_sn < sn1 )
01420 {
01421 snarray[snarray_count++] = m_sn_block0.m_sn[k++];
01422 }
01423 else
01424 {
01425
01426
01427
01428
01429 ON_ERROR("Bogus information - should never get here");
01430 break;
01431 }
01432 }
01433 n = blk->m_count-j;
01434 if ( n > 0 )
01435 {
01436 memcpy(&snarray[snarray_count],&blk->m_sn[j],n*sizeof(snarray[0]));
01437 snarray_count += n;
01438 }
01439 else
01440 {
01441 while ( k < m_sn_block0.m_count && m_sn_block0.m_sn[k].m_sn < sn1 )
01442 snarray[snarray_count++] = m_sn_block0.m_sn[k++];
01443 }
01444 n = (snarray_count > SN_BLOCK_CAPACITY)
01445 ? SN_BLOCK_CAPACITY
01446 : snarray_count;
01447 if ( k < m_sn_block0.m_count )
01448 {
01449 memcpy(&snarray[snarray_count],
01450 &m_sn_block0.m_sn[k],
01451 (m_sn_block0.m_count-k)*sizeof(snarray[0])
01452 );
01453 snarray_count += (m_sn_block0.m_count-k);
01454 }
01455 blk->m_count = n;
01456 memcpy(&blk->m_sn[0],snarray,blk->m_count*sizeof(blk->m_sn[0]));
01457 blk->m_sn0 = blk->m_sn[0].m_sn;
01458 blk->m_sn1 = blk->m_sn[blk->m_count-1].m_sn;
01459 if ( snarray_count > n )
01460 {
01461
01462
01463 m_sn_block0.m_count = (snarray_count-n);
01464 memcpy(&m_sn_block0.m_sn[0],
01465 &snarray[n],
01466 m_sn_block0.m_count*sizeof(m_sn_block0.m_sn[0])
01467 );
01468 m_sn_block0.m_sn0 = m_sn_block0.m_sn[0].m_sn;
01469 m_sn_block0.m_sn1 = m_sn_block0.m_sn[m_sn_block0.m_count-1].m_sn;
01470 }
01471 else
01472 {
01473 m_sn_block0.EmptyBlock();
01474 }
01475 }
01476 onfree(snarray);
01477 snarray = 0;
01478 }
01479
01480
01481 for ( i = 0; i < m_snblk_list_count; i++ )
01482 {
01483 for ( j = i+1; j < m_snblk_list_count; j++ )
01484 {
01485 if ( m_snblk_list[i]->m_count >= SN_BLOCK_CAPACITY )
01486 break;
01487 GarbageCollectMoveHelper(m_snblk_list[i],m_snblk_list[j]);
01488 }
01489 }
01490 while ( m_snblk_list_count > 0 && 0 == m_snblk_list[m_snblk_list_count-1]->m_count )
01491 {
01492 m_snblk_list_count--;
01493 }
01494
01495
01496 if ( m_sn_block0.m_count > SN_BLOCK_CAPACITY/4 )
01497 {
01498 if ( m_snblk_list_count > 0 )
01499 {
01500 GarbageCollectMoveHelper(m_snblk_list[m_snblk_list_count-1],&m_sn_block0);
01501 }
01502 if ( m_sn_block0.m_count > SN_BLOCK_CAPACITY/2 )
01503 {
01504
01505 if ( m_snblk_list_count == m_snblk_list_capacity )
01506 {
01507
01508 i = m_snblk_list_capacity;
01509 m_snblk_list_capacity += 32;
01510 n = m_snblk_list_capacity*sizeof(m_snblk_list[0]);
01511 m_snblk_list = (SN_BLOCK**)((0 == m_snblk_list)
01512 ? onmalloc_from_pool(m_pool,n)
01513 : onrealloc(m_snblk_list,n));
01514 while ( i < m_snblk_list_capacity )
01515 m_snblk_list[i++] = 0;
01516 }
01517 if ( 0 == m_snblk_list[m_snblk_list_count] )
01518 {
01519
01520 m_snblk_list[m_snblk_list_count] = (SN_BLOCK*)onmalloc_from_pool(m_pool,sizeof(*(m_snblk_list[m_snblk_list_count])));
01521 }
01522 *m_snblk_list[m_snblk_list_count++] = m_sn_block0;
01523 m_sn_block0.EmptyBlock();
01524 }
01525 }
01526 }
01527
01528 struct ON_SerialNumberMap::SN_ELEMENT* ON_SerialNumberMap::AddSerialNumber(unsigned int sn)
01529 {
01530 if ( sn <= 0 )
01531 return 0;
01532 struct SN_ELEMENT* e = FindElementHelper(sn);
01533 if ( e )
01534 {
01535 if ( 0 == e->m_sn_active )
01536 {
01537 m_sn_purged--;
01538 m_e_blk->m_purged--;
01539 memset(e,0,sizeof(*e));
01540 e->m_sn = sn;
01541 e->m_sn_active = 1;
01542 }
01543 }
01544 else
01545 {
01546 if ( SN_BLOCK_CAPACITY == m_sn_block0.m_count )
01547 {
01548
01549 GarbageCollectHelper();
01550 }
01551
01552 if ( 0 == m_sn_block0.m_count )
01553 {
01554 m_sn_block0.m_sn0 = m_sn_block0.m_sn1 = sn;
01555 m_sn_block0.m_sorted = 1;
01556 }
01557 else
01558 {
01559 if ( sn > m_sn_block0.m_sn1 )
01560 {
01561 m_sn_block0.m_sn1 = sn;
01562 }
01563 else
01564 {
01565 if ( sn < m_sn_block0.m_sn0 )
01566 m_sn_block0.m_sn0 = sn;
01567 m_sn_block0.m_sorted = 0;
01568 }
01569 }
01570 if ( sn > m_maxsn )
01571 m_maxsn = sn;
01572 m_sn_count++;
01573 e = &m_sn_block0.m_sn[m_sn_block0.m_count++];
01574 memset(e,0,sizeof(*e));
01575 e->m_sn = sn;
01576 e->m_sn_active = 1;
01577 }
01578
01579 return e;
01580 }
01581
01582 struct ON_SerialNumberMap::SN_ELEMENT* ON_SerialNumberMap::AddSerialNumberAndId(unsigned int sn,ON_UUID id)
01583 {
01584 struct SN_ELEMENT* e = AddSerialNumber(sn);
01585 size_t i;
01586
01587 if ( 0 != e && 0 == e->m_id_active )
01588 {
01589 if ( IdIsNotZero(&id) )
01590 {
01591 if ( m_active_id_count > 0
01592 && 0 != memcmp(&m_inactive_id,&id,sizeof(m_inactive_id))
01593 )
01594 {
01595
01596 BuildHashTableHelper();
01597 i = HashIndex(&id);
01598 for(const struct SN_ELEMENT* h = m_hash_table[i];h;h = h->m_next)
01599 {
01600 if ( 0 == memcmp(&h->m_id,&id,sizeof(h->m_id)) )
01601 {
01602
01603 ON_CreateUuid(id);
01604 break;
01605 }
01606 }
01607 }
01608 }
01609 else
01610 {
01611
01612 ON_CreateUuid(id);
01613 }
01614
01615
01616 e->m_id = id;
01617 e->m_id_active = 1;
01618 if ( m_bHashTableIsValid )
01619 {
01620
01621
01622
01623
01624
01625 i = HashIndex(&id);
01626 e->m_next = m_hash_table[i];
01627 m_hash_table[i] = e;
01628 }
01629 m_active_id_count++;
01630 memset(&m_inactive_id,0,sizeof(m_inactive_id));
01631 }
01632
01633 return e;
01634 }
01635
01636 size_t ON_SerialNumberMap::HashIndex(const ON_UUID* id) const
01637 {
01638
01639
01640 return (IdCRC(id) % ID_HASH_TABLE_COUNT);
01641 }
01642
01643 void ON_SerialNumberMap::InvalidateHashTableHelper()
01644 {
01645
01646
01647
01648
01649
01650
01651 if ( m_bHashTableIsValid )
01652 {
01653 m_bHashTableIsValid = false;
01654 memset(m_hash_table,0,sizeof(m_hash_table));
01655 }
01656 }
01657
01658 bool ON_SerialNumberMap::RemoveBlockFromHashTableHelper(const struct ON_SerialNumberMap::SN_BLOCK* blk)
01659 {
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685 bool rc = false;
01686 if ( m_bHashTableIsValid && m_active_id_count > 128*blk->m_count )
01687 {
01688 const SN_ELEMENT* e;
01689 SN_ELEMENT* h;
01690 SN_ELEMENT* prev;
01691 size_t i, hash_i;
01692 rc = true;
01693 for (e = blk->m_sn, i = blk->m_count; i--; e++)
01694 {
01695 if ( e->m_id_active )
01696 {
01697 prev = 0;
01698 hash_i = HashIndex(&e->m_id);
01699 for (h = m_hash_table[hash_i];h;h=h->m_next)
01700 {
01701 if (h == e)
01702 {
01703
01704
01705
01706 m_active_id_count--;
01707 if (prev)
01708 prev->m_next = h->m_next;
01709 else
01710 m_hash_table[hash_i] = h->m_next;
01711 break;
01712 }
01713 prev = h;
01714 }
01715 }
01716 }
01717 }
01718 return rc;
01719 }
01720
01721 void ON_SerialNumberMap::AddBlockToHashTableHelper(struct ON_SerialNumberMap::SN_BLOCK* blk)
01722 {
01723 if ( m_bHashTableIsValid )
01724 {
01725 SN_ELEMENT* e;
01726 size_t i, hash_i;
01727 for (e = blk->m_sn, i = blk->m_count; i--; e++)
01728 {
01729 if ( e->m_id_active )
01730 {
01731 hash_i = HashIndex(&e->m_id);
01732 e->m_next = m_hash_table[hash_i];
01733 m_hash_table[hash_i] = e;
01734 }
01735 }
01736 }
01737 }
01738
01739
01740 void ON_SerialNumberMap::BuildHashTableHelper()
01741 {
01742
01743
01744 if ( !m_bHashTableIsValid )
01745 {
01746
01747
01748
01749 m_bHashTableIsValid = true;
01750 if (m_active_id_count > 0)
01751 {
01752 struct SN_BLOCK* blk;
01753 struct SN_ELEMENT* e;
01754 size_t snblk_i, j, hash_i;
01755 for ( snblk_i = 0; snblk_i < m_snblk_list_count; snblk_i++ )
01756 {
01757 blk = m_snblk_list[snblk_i];
01758 if ( blk->m_purged < blk->m_count )
01759 {
01760 e = &blk->m_sn[0];
01761 for(j = blk->m_count; j--; e++ )
01762 {
01763 if ( e->m_id_active )
01764 {
01765 hash_i = HashIndex(&e->m_id);
01766 e->m_next = m_hash_table[hash_i];
01767 m_hash_table[hash_i] = e;
01768 }
01769 else
01770 {
01771 e->m_next = 0;
01772 }
01773 }
01774 }
01775 }
01776
01777 blk = &m_sn_block0;
01778 if ( blk->m_purged < blk->m_count )
01779 {
01780 e = &blk->m_sn[0];
01781 for(j = blk->m_count; j--; e++ )
01782 {
01783 if ( e->m_id_active )
01784 {
01785 hash_i = HashIndex(&e->m_id);
01786 e->m_next = m_hash_table[hash_i];
01787 m_hash_table[hash_i] = e;
01788 }
01789 else
01790 {
01791 e->m_next = 0;
01792 }
01793 }
01794 }
01795 }
01796 }
01797 }
01798
01799
01800 void ON_SerialNumberMap::SN_ELEMENT::Dump(ON_TextLog& text_log) const
01801 {
01802 text_log.Print("m_id = ");
01803 text_log.Print(m_id);
01804 text_log.Print("\nm_sn = %d\n",m_sn);
01805 text_log.Print("m_sn_active = %d\n",m_sn_active);
01806 text_log.Print("m_id_active = %d\n",m_id_active);
01807 }
01808
01809
01810 void ON_SerialNumberMap::SN_BLOCK::Dump(ON_TextLog& text_log) const
01811 {
01812 text_log.Print("m_count = %d\n",m_count);
01813 text_log.Print("m_purged = %d\n",m_purged);
01814 text_log.Print("m_sorted = %d\n",m_sorted);
01815 text_log.Print("m_sn0 = %d\n",m_sn0);
01816 text_log.Print("m_sn1 = %d\n",m_sn1);
01817 if ( m_count > 0 )
01818 {
01819 text_log.Print("m_sn[0]\n");
01820 text_log.PushIndent();
01821 m_sn[0].Dump(text_log);
01822 text_log.PopIndent();
01823 if ( m_count > 1 )
01824 {
01825 text_log.Print("m_sn[%d]\n",m_count-1);
01826 text_log.PushIndent();
01827 m_sn[m_count-1].Dump(text_log);
01828 text_log.PopIndent();
01829 }
01830 }
01831 }
01832
01833 void ON_SerialNumberMap::Dump(ON_TextLog& text_log) const
01834 {
01835 text_log.Print("m_maxsn = %d\n",m_maxsn);
01836 text_log.Print("m_sn_count = %d\n",m_sn_count);
01837 text_log.Print("m_sn_purged = %d\n",m_sn_purged);
01838 text_log.Print("m_active_id_count = %d\n",m_sn_purged);
01839 text_log.Print("m_bHashTableIsValid = %d\n",m_bHashTableIsValid);
01840 text_log.Print("m_snblk_list_capacity = %d\n",m_snblk_list_capacity);
01841 text_log.Print("m_snblk_list_count = %d\n",m_snblk_list_count);
01842
01843 text_log.Print("m_sn_block0\n");
01844 text_log.PushIndent();
01845 m_sn_block0.Dump(text_log);
01846 text_log.PopIndent();
01847
01848 for ( size_t i = 0; i < m_snblk_list_count; i++ )
01849 {
01850 text_log.Print("m_snblk_list[%d]\n",i);
01851 text_log.PushIndent();
01852 m_snblk_list[i]->Dump(text_log);
01853 text_log.PopIndent();
01854 }
01855 }