Opera 12.15 Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

VectorBase.cpp 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. /* -*- Mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
  2. **
  3. ** Copyright (C) 1995-2011 Opera Software ASA. All rights reserved.
  4. **
  5. ** This file is part of the Opera web browser.
  6. ** It may not be distributed under any circumstances.
  7. */
  8. #include "core/pch.h"
  9. #ifdef SEARCH_ENGINE
  10. #include "modules/search_engine/VectorBase.h"
  11. #define ALLOC_STEP_SIZE 12
  12. #define MAX_STEP_SIZE 1024
  13. // the size doubles for small numbers and increases with a constant for high numbers
  14. #define alloc_size(current_size) ((current_size) << 1) / (1 + (current_size) / MAX_STEP_SIZE) + ((current_size) + MAX_STEP_SIZE) / (1 + MAX_STEP_SIZE / ((current_size) + 1))
  15. VectorBase::VectorBase(const TypeDescriptor &allocator) : m_allocator(allocator)
  16. {
  17. m_items = NULL;
  18. m_size = 0;
  19. m_count = 0;
  20. }
  21. OP_STATUS VectorBase::DuplicateOf(const VectorBase& vec)
  22. {
  23. char* new_items;
  24. unsigned i;
  25. if (m_count > 0 || m_size < vec.m_size)
  26. {
  27. RETURN_OOM_IF_NULL(new_items = OP_NEWA(char, vec.m_size * m_allocator.size));
  28. Clear();
  29. }
  30. else // Reserve() can be used before
  31. new_items = m_items;
  32. for (i = 0; i < vec.m_count; ++i)
  33. RETURN_IF_ERROR(m_allocator.Assign(new_items + i * m_allocator.size, vec.m_items + i * vec.m_allocator.size));
  34. m_items = new_items;
  35. m_size = vec.m_size;
  36. m_count = vec.m_count;
  37. return OpStatus::OK;
  38. }
  39. void VectorBase::TakeOver(VectorBase &vec)
  40. {
  41. Clear();
  42. m_items = vec.m_items;
  43. vec.m_items = NULL;
  44. m_count = vec.m_count;
  45. vec.m_count = 0;
  46. m_size = vec.m_size;
  47. vec.m_size = 0;
  48. }
  49. void VectorBase::Clear(void)
  50. {
  51. if (m_items != NULL)
  52. {
  53. unsigned i;
  54. for (i = 0; i < m_count; ++i)
  55. m_allocator.Destruct(m_items + i * m_allocator.size);
  56. OP_DELETEA(m_items);
  57. m_items = NULL;
  58. }
  59. m_size = 0;
  60. m_count = 0;
  61. }
  62. OP_STATUS VectorBase::Reserve(UINT32 size)
  63. {
  64. if (m_size >= size)
  65. return OpStatus::OK;
  66. return Grow(size, m_count);
  67. }
  68. OP_STATUS VectorBase::SetCount(UINT32 count)
  69. {
  70. RETURN_IF_ERROR(Reserve(count));
  71. if ((m_count = count) == 0)
  72. Clear();
  73. return OpStatus::OK;
  74. }
  75. OP_STATUS VectorBase::Replace(UINT32 idx, const void *item)
  76. {
  77. m_allocator.Destruct(m_items + idx * m_allocator.size);
  78. return m_allocator.Assign(m_items + idx * m_allocator.size, item);
  79. }
  80. OP_STATUS VectorBase::Insert(UINT32 idx, const void *item)
  81. {
  82. if (m_count >= m_size)
  83. {
  84. RETURN_IF_ERROR(Grow(m_size == 0 ? ALLOC_STEP_SIZE : alloc_size(m_size), idx));
  85. }
  86. else if (idx < m_count)
  87. op_memmove(m_items + (idx + 1) * m_allocator.size, m_items + idx * m_allocator.size, (m_count - idx) * m_allocator.size);
  88. RETURN_IF_ERROR(m_allocator.Assign(m_items +idx * m_allocator.size, item));
  89. ++m_count;
  90. return OpStatus::OK;
  91. }
  92. OP_STATUS VectorBase::Insert(const void *item)
  93. {
  94. UINT32 idx;
  95. if (m_count == 0)
  96. return Insert(0, item);
  97. idx = Search(item);
  98. if (idx >= m_count || m_allocator.Compare(item, m_items + idx * m_allocator.size)) // not in the vector yet
  99. return Insert(idx, item);
  100. return OpStatus::OK; // this item is already inserted
  101. }
  102. BOOL VectorBase::RemoveByItem(const void *item)
  103. {
  104. INT32 idx;
  105. if ((idx = Find(item)) == -1)
  106. return FALSE;
  107. Remove(NULL, idx);
  108. return TRUE;
  109. }
  110. void VectorBase::Remove(void *item, INT32 idx)
  111. {
  112. UINT32 new_count;
  113. BOOL shrink_ok = FALSE;
  114. if (idx < 0)
  115. idx = m_count + idx;
  116. if (item != NULL)
  117. op_memcpy(item, m_items + idx * m_allocator.size, m_allocator.size);
  118. new_count = m_count - 1;
  119. if (alloc_size(new_count) < m_size && new_count >= ALLOC_STEP_SIZE)
  120. shrink_ok = OpStatus::IsSuccess(Shrink(new_count, idx));
  121. if (new_count == 0)
  122. {
  123. OP_DELETEA(m_items);
  124. m_items = NULL;
  125. m_size = 0;
  126. }
  127. else if (!shrink_ok && (UINT32)idx < new_count)
  128. op_memmove(m_items + idx * m_allocator.size, m_items + (idx + 1) * m_allocator.size, (new_count - idx) * m_allocator.size);
  129. m_count = new_count;
  130. }
  131. BOOL VectorBase::DeleteByItem(void *item)
  132. {
  133. INT32 idx;
  134. if ((idx = Find(item)) == -1)
  135. return FALSE;
  136. Delete(idx);
  137. return TRUE;
  138. }
  139. void VectorBase::Delete(INT32 idx, UINT32 count)
  140. {
  141. int i;
  142. UINT32 new_count;
  143. BOOL shrink_ok = FALSE;
  144. if (idx < 0)
  145. idx = m_count + idx;
  146. for (i = idx; i < idx + (INT32)count; ++i)
  147. m_allocator.Destruct(m_items + i * m_allocator.size);
  148. new_count = m_count - count;
  149. if (alloc_size(new_count) < m_size && new_count >= ALLOC_STEP_SIZE)
  150. shrink_ok = OpStatus::IsSuccess(Shrink(new_count, idx, count));
  151. if (new_count == 0)
  152. {
  153. OP_DELETEA(m_items);
  154. m_items = NULL;
  155. m_size = 0;
  156. }
  157. else if (!shrink_ok && idx < (INT32)m_count)
  158. op_memmove(m_items + idx * m_allocator.size, m_items + (idx + count) * m_allocator.size, (new_count - idx) * m_allocator.size);
  159. m_count = new_count;
  160. }
  161. INT32 VectorBase::Find(const void *item) const
  162. {
  163. UINT32 i;
  164. for (i = 0; i < m_count; ++i)
  165. {
  166. if (!m_allocator.Compare(m_items + i * m_allocator.size, item) && !m_allocator.Compare(item, m_items + i * m_allocator.size))
  167. return i;
  168. }
  169. return -1;
  170. }
  171. OP_STATUS VectorBase::Sort(void)
  172. {
  173. unsigned count;
  174. unsigned i;
  175. char *temp_array;
  176. if (m_count <= 1)
  177. return OpStatus::OK;
  178. temp_array = OP_NEWA(char, m_count * m_allocator.size);
  179. if (temp_array == NULL)
  180. { // fallback for out of memory - bubble sort
  181. unsigned j, k;
  182. char tmp_T;
  183. i = 1;
  184. while (i < m_count)
  185. {
  186. j = 1;
  187. while (j <= m_count - i)
  188. {
  189. if (m_allocator.Compare(m_items + j * m_allocator.size, m_items + (j - 1) * m_allocator.size))
  190. {
  191. for (k = 0; k < m_allocator.size; ++k)
  192. {
  193. tmp_T = (m_items + (j - 1) * m_allocator.size)[k];
  194. (m_items + (j - 1) * m_allocator.size)[k] = (m_items + j * m_allocator.size)[k];
  195. (m_items + j * m_allocator.size)[k] = tmp_T;
  196. }
  197. }
  198. else if (!m_allocator.Compare(m_items + (j - 1) * m_allocator.size, m_items + j * m_allocator.size)) // items are equal
  199. {
  200. Delete(j);
  201. --j;
  202. }
  203. ++j;
  204. }
  205. ++i;
  206. }
  207. return OpStatus::OK;
  208. }
  209. op_memcpy(temp_array, m_items, m_count * m_allocator.size);
  210. count = MergeSort(temp_array, m_items, 0, m_count - 1);
  211. if (alloc_size(count) < m_size && count >= ALLOC_STEP_SIZE)
  212. RETURN_IF_ERROR(Shrink(count, count, m_count - count));
  213. m_count = count;
  214. OP_DELETEA(temp_array);
  215. return OpStatus::OK;
  216. }
  217. INT32 VectorBase::Search(const void *item, UINT32 start, UINT32 end) const
  218. {
  219. int n2;
  220. while (end > start)
  221. {
  222. n2 = (end - start) / 2;
  223. if (m_allocator.Compare(m_items + (start + n2) * m_allocator.size, item))
  224. start = start + n2 + 1;
  225. else
  226. end = start + n2;
  227. }
  228. return start;
  229. }
  230. OP_STATUS VectorBase::Grow(UINT32 new_size, UINT32 hole)
  231. {
  232. char* new_items;
  233. RETURN_OOM_IF_NULL(new_items = OP_NEWA(char, new_size * m_allocator.size));
  234. if (m_size > 0)
  235. {
  236. // Copy elements before item.
  237. op_memcpy(new_items, m_items, hole * m_allocator.size);
  238. // Copy elements after item.
  239. if (hole < m_count)
  240. op_memcpy(new_items + (hole + 1) * m_allocator.size, m_items + hole * m_allocator.size, (m_count - hole) * m_allocator.size);
  241. }
  242. OP_DELETEA(m_items);
  243. m_size = new_size;
  244. m_items = new_items;
  245. return OpStatus::OK;
  246. }
  247. OP_STATUS VectorBase::Shrink(UINT32 new_size, UINT32 hole, UINT32 count)
  248. {
  249. char* new_items;
  250. if (new_size > 0)
  251. RETURN_OOM_IF_NULL(new_items = OP_NEWA(char, new_size * m_allocator.size));
  252. else new_items = NULL;
  253. if (new_size > 0)
  254. {
  255. // Copy elements before item.
  256. op_memcpy(new_items, m_items, hole * m_allocator.size);
  257. // Copy elements after item.
  258. if (hole < m_count)
  259. op_memcpy(new_items + hole * m_allocator.size, m_items + (hole + count) * m_allocator.size, (m_count - hole - count) * m_allocator.size);
  260. }
  261. OP_DELETEA(m_items);
  262. m_size = new_size;
  263. m_items = new_items;
  264. return OpStatus::OK;
  265. }
  266. INT32 VectorBase::MergeSort(char* array, char* temp_array, INT32 left, INT32 right)
  267. {
  268. INT32 left_end;
  269. INT32 temp_pos;
  270. INT32 center = (left + right) / 2;
  271. INT32 last_pos; // to remove duplicates
  272. INT32 shift;
  273. if (center > left)
  274. {
  275. if ((shift = MergeSort(temp_array, array, left, center)) <= center)
  276. {
  277. op_memmove(temp_array + shift * m_allocator.size, temp_array + (center + 1) * m_allocator.size, (right - center) * m_allocator.size);
  278. op_memmove(array + shift * m_allocator.size, array + (center + 1) * m_allocator.size, (right - center) * m_allocator.size);
  279. right -= center + 1 - shift;
  280. center = shift - 1;
  281. }
  282. right = MergeSort(temp_array, array, center + 1, right) - 1;
  283. }
  284. left_end = center;
  285. temp_pos = left;
  286. ++center;
  287. if (left <= left_end && center <= right) // first item, cannot check for duplicates
  288. {
  289. if (m_allocator.Compare(array + left * m_allocator.size, array + center * m_allocator.size))
  290. op_memcpy(temp_array + temp_pos++ * m_allocator.size, array + (last_pos = left++) * m_allocator.size, m_allocator.size);
  291. else
  292. op_memcpy(temp_array + temp_pos++ * m_allocator.size, array + (last_pos = center++) * m_allocator.size, m_allocator.size);
  293. }
  294. else {
  295. if (left <= left_end)
  296. op_memcpy(temp_array + temp_pos++ * m_allocator.size, array + left * m_allocator.size, m_allocator.size);
  297. else
  298. op_memcpy(temp_array + temp_pos++ * m_allocator.size, array + center * m_allocator.size, m_allocator.size);
  299. return temp_pos; // array sizes cannot differ by more than 1
  300. }
  301. while (left <= left_end && center <= right)
  302. {
  303. if (m_allocator.Compare(array + left * m_allocator.size, array + center * m_allocator.size))
  304. {
  305. if (m_allocator.Compare(array + last_pos * m_allocator.size, array + left * m_allocator.size))
  306. op_memcpy(temp_array + temp_pos++ * m_allocator.size, array + (last_pos = left++) * m_allocator.size, m_allocator.size);
  307. else
  308. m_allocator.Destruct(array + left++ * m_allocator.size);
  309. }
  310. else {
  311. if (m_allocator.Compare(array + last_pos * m_allocator.size, array + center * m_allocator.size))
  312. op_memcpy(temp_array + temp_pos++ * m_allocator.size, array + (last_pos = center++) * m_allocator.size, m_allocator.size);
  313. else
  314. m_allocator.Destruct(array + center++ * m_allocator.size);
  315. }
  316. }
  317. while (left <= left_end)
  318. {
  319. if (m_allocator.Compare(array + last_pos * m_allocator.size, array + left * m_allocator.size))
  320. op_memcpy(temp_array + temp_pos++ * m_allocator.size, array + (last_pos = left++) * m_allocator.size, m_allocator.size);
  321. else
  322. m_allocator.Destruct(array + left++ * m_allocator.size);
  323. }
  324. while (center <= right)
  325. {
  326. if (m_allocator.Compare(array + last_pos * m_allocator.size, array + center * m_allocator.size))
  327. op_memcpy(temp_array + temp_pos++ * m_allocator.size, array + (last_pos = center++) * m_allocator.size, m_allocator.size);
  328. else
  329. m_allocator.Destruct(array + center++ * m_allocator.size);
  330. }
  331. return temp_pos;
  332. }
  333. OP_STATUS VectorBase::Unite(const VectorBase &vec)
  334. {
  335. char *dst;
  336. UINT32 i, j, pos, len;
  337. if (vec.m_count == 0)
  338. return OpStatus::OK;
  339. if (m_count == 0)
  340. return DuplicateOf(vec);
  341. pos = 0;
  342. if (m_size >= m_count + vec.m_count)
  343. {
  344. i = 0;
  345. while (i < vec.m_count)
  346. {
  347. pos = Search(vec.Get(i), pos, m_count);
  348. while (pos < m_count && !m_allocator.Compare(Get(pos), vec.Get(i)) && !m_allocator.Compare(vec.Get(i), Get(pos))) // remove duplicates
  349. {
  350. if (++i >= vec.m_count)
  351. return OpStatus::OK;
  352. ++pos;
  353. }
  354. if (pos >= m_count)
  355. break;
  356. if (m_allocator.Compare(Get(pos), vec.Get(i)))
  357. continue;
  358. len = 1;
  359. while (i + len < vec.m_count && m_allocator.Compare(vec.Get(i + len), Get(pos)))
  360. ++len;
  361. op_memmove(m_items + (pos + len) * m_allocator.size, m_items + pos * m_allocator.size, (m_count - pos) * m_allocator.size);
  362. for (j = 0; j < len; ++j)
  363. {
  364. RETURN_IF_ERROR(m_allocator.Assign(m_items + (pos + j) * m_allocator.size, vec.Get(i + j)));
  365. }
  366. m_count += len;
  367. i += len;
  368. pos += len;
  369. }
  370. if (i < vec.m_count && !m_allocator.Compare(Get(m_count - 1), vec.Get(i)) && !m_allocator.Compare(vec.Get(i), Get(m_count - 1)))
  371. ++i;
  372. while (i < vec.m_count)
  373. {
  374. RETURN_IF_ERROR(m_allocator.Assign(m_items + m_count++ * m_allocator.size, vec.Get(i++)));
  375. }
  376. return OpStatus::OK;
  377. }
  378. RETURN_OOM_IF_NULL(dst = OP_NEWA(char, (m_count + vec.m_count) * m_allocator.size));
  379. m_size = m_count + vec.m_count;
  380. i = 0;
  381. j = 0;
  382. pos = 0;
  383. while (i < m_count && j < vec.m_count)
  384. {
  385. if (m_allocator.Compare(Get(i), vec.Get(j)))
  386. {
  387. RETURN_IF_ERROR(m_allocator.Assign(dst + pos++ * m_allocator.size, Get(i++)));
  388. }
  389. else if (m_allocator.Compare(vec.Get(j), Get(i)))
  390. {
  391. RETURN_IF_ERROR(m_allocator.Assign(dst + pos++ * m_allocator.size, vec.Get(j++)));
  392. }
  393. else {
  394. RETURN_IF_ERROR(m_allocator.Assign(dst + pos++ * m_allocator.size, Get(i)));
  395. ++i;
  396. ++j;
  397. }
  398. }
  399. while (i < m_count)
  400. {
  401. RETURN_IF_ERROR(m_allocator.Assign(dst + pos++ * m_allocator.size, Get(i++)));
  402. }
  403. while (j < vec.m_count)
  404. {
  405. RETURN_IF_ERROR(m_allocator.Assign(dst + pos++ * m_allocator.size, vec.Get(j++)));
  406. }
  407. if (m_items != NULL)
  408. OP_DELETEA(m_items);
  409. m_items = dst;
  410. m_count = pos;
  411. return OpStatus::OK;
  412. }
  413. OP_STATUS VectorBase::Unite(VectorBase &result, const VectorBase &vec1, const VectorBase &vec2)
  414. {
  415. UINT32 i,j;
  416. if (result.m_count > 0)
  417. result.Clear();
  418. RETURN_IF_ERROR(result.Reserve(vec1.m_count + vec2.m_count));
  419. i = 0;
  420. j = 0;
  421. result.m_count = 0;
  422. while (i < vec1.m_count && j < vec2.m_count)
  423. {
  424. if (result.m_allocator.Compare(vec1.Get(i), vec2.Get(j)))
  425. {
  426. RETURN_IF_ERROR(result.m_allocator.Assign(result.m_items + (result.m_count++) * result.m_allocator.size, vec1.Get(i++)));
  427. }
  428. else if (result.m_allocator.Compare(vec2.Get(j), vec1.Get(i)))
  429. {
  430. RETURN_IF_ERROR(result.m_allocator.Assign(result.m_items + (result.m_count++) * result.m_allocator.size, vec2.Get(j++)));
  431. }
  432. else {
  433. RETURN_IF_ERROR(result.m_allocator.Assign(result.m_items + (result.m_count++) * result.m_allocator.size, vec1.Get(i)));
  434. ++i;
  435. ++j;
  436. }
  437. }
  438. while (i < vec1.m_count)
  439. {
  440. RETURN_IF_ERROR(result.m_allocator.Assign(result.m_items + (result.m_count++) * result.m_allocator.size, vec1.Get(i++)));
  441. }
  442. while (j < vec2.m_count)
  443. {
  444. RETURN_IF_ERROR(result.m_allocator.Assign(result.m_items + (result.m_count++) * result.m_allocator.size, vec2.Get(j++)));
  445. }
  446. return OpStatus::OK;
  447. }
  448. void VectorBase::Differ(const VectorBase &vec)
  449. {
  450. UINT32 i, dpos1, dlen;
  451. if (m_count == 0 || vec.m_count == 0)
  452. return;
  453. i = 0;
  454. dpos1 = Search(vec.Get(i));
  455. while (dpos1 < m_count)
  456. {
  457. if (!m_allocator.Compare(vec.Get(i++), Get(dpos1)))
  458. {
  459. dlen = 1;
  460. while (dpos1 + dlen < m_count && i < vec.m_count && !m_allocator.Compare(Get(dpos1 + dlen), vec.Get(i)) && !m_allocator.Compare(vec.Get(i), Get(dpos1 + dlen)))
  461. {
  462. ++dlen;
  463. ++i;
  464. }
  465. Delete(dpos1, dlen);
  466. }
  467. if (i >= vec.m_count)
  468. return;
  469. dpos1 = Search(vec.Get(i), dpos1, m_count);
  470. }
  471. return;
  472. }
  473. OP_STATUS VectorBase::Differ(VectorBase &result, const VectorBase &vec1, const VectorBase &vec2)
  474. {
  475. UINT32 i,j;
  476. if (result.m_count > 0)
  477. result.Clear();
  478. RETURN_IF_ERROR(result.Reserve(vec1.m_count));
  479. i = 0;
  480. j = 0;
  481. result.m_count = 0;
  482. while (i < vec1.m_count && j < vec2.m_count)
  483. {
  484. if (result.m_allocator.Compare(vec1.Get(i), vec2.Get(j)))
  485. {
  486. RETURN_IF_ERROR(result.m_allocator.Assign(result.m_items + (result.m_count++) * result.m_allocator.size, vec1.Get(i++)));
  487. }
  488. else if (result.m_allocator.Compare(vec2.Get(j), vec1.Get(i)))
  489. ++j;
  490. else {
  491. ++i;
  492. ++j;
  493. }
  494. }
  495. while (i < vec1.m_count)
  496. {
  497. RETURN_IF_ERROR(result.m_allocator.Assign(result.m_items + (result.m_count++) * result.m_allocator.size, vec1.Get(i++)));
  498. }
  499. return OpStatus::OK;
  500. }
  501. OP_STATUS VectorBase::Intersect(const VectorBase &vec)
  502. {
  503. UINT32 vmin, i, dpos, dlen;
  504. if (m_count == 0 || vec.m_count == 0)
  505. {
  506. Clear();
  507. return OpStatus::OK;
  508. }
  509. vmin = 0;
  510. dpos = 0;
  511. dlen = 0;
  512. do {
  513. i = vec.Search(Get(dpos + dlen), vmin, vec.m_count);
  514. if (i < vec.m_count && !m_allocator.Compare(Get(dpos + dlen), vec.Get(i)))
  515. {
  516. vmin = i;
  517. if (dlen > 0)
  518. Delete(dpos, dlen);
  519. else
  520. ++dpos;
  521. dlen = 0;
  522. }
  523. else
  524. ++dlen;
  525. } while (dpos + dlen < m_count);
  526. if (dlen > 0)
  527. Delete(dpos, dlen);
  528. return OpStatus::OK;
  529. }
  530. OP_STATUS VectorBase::Intersect(VectorBase &result, const VectorBase &vec1, const VectorBase &vec2)
  531. {
  532. UINT32 i,j;
  533. if (result.m_count > 0)
  534. result.Clear();
  535. if (vec1.m_count == 0 || vec2.m_count == 0)
  536. return OpStatus::OK;
  537. RETURN_IF_ERROR(result.Reserve(vec1.m_count));
  538. i = 0;
  539. j = 0;
  540. while (i < vec1.m_count && j < vec2.m_count)
  541. {
  542. if (result.m_allocator.Compare(vec1.Get(i), vec2.Get(j)))
  543. ++i;
  544. else if (result.m_allocator.Compare(vec2.Get(j), vec1.Get(i)))
  545. ++j;
  546. else {
  547. RETURN_IF_ERROR(result.m_allocator.Assign(result.m_items + (result.m_count++) * result.m_allocator.size, vec1.Get(i)));
  548. ++i;
  549. ++j;
  550. }
  551. }
  552. return OpStatus::OK;
  553. }
  554. void VectorBase::Filter(BOOL (*matches)(const void* item, void* custom_data), void* custom_data)
  555. {
  556. if (!matches)
  557. return;
  558. /* This algorithm is O(n^2), repeatedly deleting from the middle and shifting down.
  559. * It could be optimized, but that does not make sense as long as Intersect is not.
  560. * It is probably waaay faster than a single disk access anyway. */
  561. for (int i = m_count-1; i >= 0; i--)
  562. if (!matches(Get(i), custom_data))
  563. Delete(i);
  564. }
  565. #ifdef ESTIMATE_MEMORY_USED_AVAILABLE
  566. size_t VectorBase::EstimateMemoryUsed() const
  567. {
  568. size_t sum = 0;
  569. if (m_items)
  570. {
  571. unsigned i;
  572. for (i = 0; i < m_count; ++i)
  573. sum += m_allocator.EstimateMemoryUsed(m_items + i * m_allocator.size);
  574. sum += 2*sizeof(size_t);
  575. }
  576. return sum +
  577. sizeof(m_items) +
  578. sizeof(m_allocator) +
  579. sizeof(m_size) +
  580. sizeof(m_count);
  581. }
  582. #endif
  583. #endif // SEARCH_ENGINE