Collection.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. #ifndef _Collection_h_
  2. #define _Collection_h_
  3. /* Collection.h
  4. *
  5. * Copyright (C) 1992-2011,2015,2016,2017 Paul Boersma
  6. *
  7. * This code is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * This code is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. * See the GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. /*
  21. * Collection objects contain a number of items whose class is a subclass of Thing or Daata.
  22. */
  23. #include "Simple.h"
  24. #pragma mark - class Collection
  25. /**
  26. An object of type Collection is a collection of objects of any class T*
  27. that is a subclass of Thing or Daata.
  28. These elements ("items") are either owned by the Collection, or they are references.
  29. You can access the items as `at [1]` through `at [size]`.
  30. There can be no null items.
  31. @param size the current number of items
  32. @param at[1..size] the items
  33. */
  34. template <typename T> struct CollectionOf;
  35. typedef CollectionOf<structDaata> _CollectionOfDaata;
  36. extern void _CollectionOfDaata_v_copy (_CollectionOfDaata* me, _CollectionOfDaata* thee);
  37. extern bool _CollectionOfDaata_v_equal (_CollectionOfDaata* me, _CollectionOfDaata* thee);
  38. extern bool _CollectionOfDaata_v_canWriteAsEncoding (_CollectionOfDaata* me, int outputEncoding);
  39. extern void _CollectionOfDaata_v_writeText (_CollectionOfDaata* me, MelderFile openFile);
  40. extern void _CollectionOfDaata_v_readText (_CollectionOfDaata* me, MelderReadText text, int formatVersion);
  41. extern void _CollectionOfDaata_v_writeBinary (_CollectionOfDaata* me, FILE *f);
  42. extern void _CollectionOfDaata_v_readBinary (_CollectionOfDaata* me, FILE *f, int formatVersion);
  43. extern struct structData_Description theCollectionOfDaata_v_description [3];
  44. template <typename T /*Melder_ENABLE_IF_ISA (T, structThing)*/>
  45. struct ArrayOf {
  46. T** _elements { nullptr };
  47. T*& operator[] (integer i) const {
  48. return our _elements [i];
  49. }
  50. };
  51. template <typename T /*Melder_ENABLE_IF_ISA (T, structThing)*/>
  52. struct CollectionOf : structDaata {
  53. ArrayOf <T> at;
  54. integer size { 0 };
  55. integer _capacity { 0 };
  56. bool _ownItems { true };
  57. bool _ownershipInitialized { false };
  58. CollectionOf () {
  59. extern ClassInfo classCollection;
  60. our classInfo = classCollection;
  61. our name. reset();
  62. }
  63. virtual ~ CollectionOf () {
  64. /*
  65. We cannot simply do
  66. //our v_destroy ();
  67. because C++ will implicitly call the destructor for structDaata,
  68. whereas structCollection::v_destroy explicitly calls structDaata::v_destroy;
  69. calling v_destroy here would therefore free structThing::name twice,
  70. which may not crash Praat (assuming that `name` is nulled the first time)
  71. but which is not how destruction should be organized.
  72. */
  73. if (our at._elements) {
  74. if (our _ownItems) {
  75. for (integer i = 1; i <= our size; i ++) {
  76. _Thing_forget (our at [i]);
  77. }
  78. }
  79. our at._elements ++; // convert from base-1 to base-0
  80. Melder_free (our at._elements);
  81. }
  82. }
  83. //explicit operator bool () const {
  84. // return !! our item;
  85. //}
  86. CollectionOf<T>& operator= (const CollectionOf<T>&) = delete; // disable copy assignment from an l-value of class T*
  87. template <class Y> CollectionOf<T>& operator= (const CollectionOf<Y>&) = delete; // disable copy assignment from an l-value of a descendant class of T*
  88. CollectionOf<T> (CollectionOf<T>&& other) noexcept :
  89. at (other. at),
  90. size (other. size),
  91. _capacity (other. _capacity),
  92. _ownItems (other. _ownItems),
  93. _ownershipInitialized (other. _ownershipInitialized)
  94. {
  95. other. at._elements = nullptr;
  96. other. size = 0;
  97. other. _capacity = 0;
  98. other. _ownItems = false;
  99. other. _ownershipInitialized = false;
  100. }
  101. template <class Y> CollectionOf<T> (CollectionOf<Y>&& other) noexcept :
  102. at (other. at),
  103. size (other. size),
  104. _capacity (other. _capacity),
  105. _ownItems (other. _ownItems),
  106. _ownershipInitialized (other. _ownershipInitialized)
  107. {
  108. other. at._elements = nullptr;
  109. other. size = 0;
  110. other. _capacity = 0;
  111. other. _ownItems = false;
  112. other. _ownershipInitialized = false;
  113. }
  114. CollectionOf<T>& operator= (CollectionOf<T>&& other) noexcept {
  115. if (other. at._elements != our at._elements) {
  116. if (our at._elements) {
  117. if (our _ownItems) {
  118. for (integer i = 1; i <= our size; i ++) {
  119. _Thing_forget (our at [i]);
  120. }
  121. }
  122. our at._elements ++; // convert from base-1 to base-0
  123. Melder_free (our at._elements);
  124. }
  125. }
  126. our at = other. at;
  127. our size = other. size;
  128. our _capacity = other. _capacity;
  129. our _ownItems = other. _ownItems;
  130. our _ownershipInitialized = other. _ownershipInitialized;
  131. other. at._elements = nullptr;
  132. other. size = 0;
  133. other. _capacity = 0;
  134. other. _ownItems = false;
  135. other. _ownershipInitialized = false;
  136. return *this;
  137. }
  138. template <class Y> CollectionOf<T>& operator= (CollectionOf<Y>&& other) noexcept {
  139. if (other. at_elements != our at_elements) {
  140. if (our at._elements) {
  141. if (our _ownItems) {
  142. for (integer i = 1; i <= our size; i ++) {
  143. _Thing_forget (our at [i]);
  144. }
  145. }
  146. our at._elements ++; // convert from base-1 to base-0
  147. Melder_free (our at._elements);
  148. }
  149. }
  150. our at = other. at;
  151. our size = other. size;
  152. our _capacity = other. _capacity;
  153. our _ownItems = other. _ownItems;
  154. our _ownershipInitialized = other. _ownershipInitialized;
  155. other. at._elements = nullptr;
  156. other. size = 0;
  157. other. _capacity = 0;
  158. other. _ownItems = false;
  159. other. _ownershipInitialized = false;
  160. return *this;
  161. }
  162. CollectionOf<T>&& move () noexcept { return static_cast <CollectionOf<T>&&> (*this); }
  163. void _initializeOwnership (bool ownItems) {
  164. if (our _ownershipInitialized) {
  165. Melder_assert (our _ownItems == ownItems);
  166. } else {
  167. our _ownItems = ownItems;
  168. our _ownershipInitialized = true;
  169. }
  170. }
  171. void _grow (integer newCapacity) {
  172. if (newCapacity <= our _capacity) return;
  173. T** oldItem_base0 = ( our at._elements ? our at._elements + 1 : nullptr ); // convert from base-1 to base-0
  174. T** newItem_base0 = (T**) Melder_realloc (oldItem_base0, newCapacity * (int64) sizeof (T*));
  175. our at._elements = newItem_base0 - 1; // convert from base-0 to base-1
  176. our _capacity = newCapacity;
  177. }
  178. void _makeRoomForOneMoreItem (integer pos) {
  179. if (our size >= our _capacity) {
  180. integer newCapacity = 2 * our _capacity + 30; // enough room to guarantee space for one more item, if _capacity >= 0
  181. T** oldItem_base0 = ( our at._elements ? our at._elements + 1 : nullptr ); // convert from base-1 to base-0
  182. T** newItem_base0 = (T**) Melder_realloc (oldItem_base0, newCapacity * (int64) sizeof (T*));
  183. our at._elements = newItem_base0 - 1; // convert from base-0 to base-1
  184. our _capacity = newCapacity;
  185. }
  186. our size ++;
  187. for (integer i = our size; i > pos; i --) our at [i] = our at [i - 1];
  188. }
  189. T* _insertItem_move (autoSomeThing <T> data, integer pos) {
  190. our _initializeOwnership (true);
  191. our _makeRoomForOneMoreItem (pos);
  192. return our at [pos] = data.releaseToAmbiguousOwner();
  193. }
  194. void _insertItem_ref (T* data, integer pos) {
  195. our _initializeOwnership (false);
  196. our _makeRoomForOneMoreItem (pos);
  197. our at [pos] = data;
  198. }
  199. /**
  200. Add `thing` to the collection.
  201. @pre
  202. !! thing;
  203. @post
  204. my size >= my old size
  205. You don't transfer ownership of `thing` to the Collection.
  206. You cannot call both addItem_move() and addItem_ref() on the same Collection.
  207. */
  208. void addItem_ref (T* thing) {
  209. Melder_assert (thing);
  210. integer index = our _v_position (thing);
  211. if (index != 0) {
  212. our _insertItem_ref (thing, index);
  213. } else {
  214. our _initializeOwnership (false);
  215. }
  216. }
  217. /**
  218. Add 'thing' to the collection.
  219. @pre
  220. !! thing;
  221. @post
  222. my size >= my old size
  223. You transfer ownership of 'thing' to the Collection.
  224. You cannot call both addItem_move() and addItem_ref() on the same Collection.
  225. For a SortedSet, this may mean that the Collection immediately disposes of 'item',
  226. if that item already occurred in the Collection.
  227. */
  228. T* addItem_move (autoSomeThing<T> thing) {
  229. T* thingRef = thing.get();
  230. integer index = our _v_position (thingRef);
  231. if (index != 0) {
  232. return our _insertItem_move (thing.move(), index);
  233. } else {
  234. our _initializeOwnership (true);
  235. thing.reset(); // could not insert; I am the owner, so I must dispose of the data
  236. return nullptr;
  237. }
  238. }
  239. /**
  240. Remove the item from the collection, without destroying it.
  241. @post
  242. item not found || my size == my old size - 1;
  243. Usage:
  244. this is the way in which an item can detach itself from a list;
  245. often used just before the item is destroyed, hence the name of this procedure.
  246. */
  247. void undangleItem (Thing thing) {
  248. for (integer i = our size; i > 0; i --) {
  249. if (our at [i] == thing) {
  250. for (integer j = i; j < our size; j ++) {
  251. our at [j] = our at [j + 1];
  252. }
  253. our size --;
  254. }
  255. }
  256. }
  257. /**
  258. For subtractItem_move(): FIXME
  259. Remove the item at 'position' from the collection and transfer ownership to the caller.
  260. Return value:
  261. the subtracted item; the caller is responsible for eventually removing it.
  262. Preconditions:
  263. 1 <= position <= my size;
  264. Postconditions:
  265. my size == my old size - 1;
  266. my _capacity not changed;
  267. */
  268. autoSomeThing<T> subtractItem_move (integer pos) {
  269. Melder_assert (pos >= 1 && pos <= our size);
  270. Melder_assert (our _ownItems);
  271. autoSomeThing<T> result;
  272. result. adoptFromAmbiguousOwner (our at [pos]);
  273. for (integer i = pos; i < our size; i ++)
  274. our at [i] = our at [i + 1];
  275. our size --;
  276. return result;
  277. }
  278. T* subtractItem_ref (integer pos) {
  279. Melder_assert (pos >= 1 && pos <= our size);
  280. Melder_assert (! our _ownItems);
  281. T* result = our at [pos];
  282. for (integer i = pos; i < our size; i ++)
  283. our at [i] = our at [i + 1];
  284. our size --;
  285. return result;
  286. }
  287. void replaceItem_ref (T* data, integer pos) {
  288. Melder_assert (pos >= 1 && pos <= our size);
  289. Melder_assert (! our _ownItems);
  290. our at [pos] = data;
  291. }
  292. T* replaceItem_move (autoSomeThing <T> data, integer pos) {
  293. Melder_assert (pos >= 1 && pos <= our size);
  294. Melder_assert (our _ownItems);
  295. _Thing_forget (our at [pos]);
  296. return our at [pos] = data.releaseToAmbiguousOwner();
  297. }
  298. /**
  299. Remove the item at 'position' from the collection and from memory.
  300. @pre
  301. 1 <= position <= my size;
  302. @post
  303. my size == my old size - 1;
  304. my _capacity not changed;
  305. */
  306. void removeItem (integer pos) {
  307. Melder_assert (pos >= 1 && pos <= our size);
  308. if (our _ownItems) _Thing_forget (our at [pos]);
  309. for (integer i = pos; i < our size; i ++)
  310. our at [i] = our at [i + 1];
  311. our size --;
  312. }
  313. /**
  314. Remove all items from the collection and from memory.
  315. @post
  316. my size == 0;
  317. my _capacity not changed;
  318. */
  319. void removeAllItems () {
  320. if (our _ownItems) {
  321. for (integer i = 1; i <= our size; i ++)
  322. _Thing_forget (our at [i]);
  323. }
  324. our size = 0;
  325. }
  326. /**
  327. Release as much memory as possible without affecting the items.
  328. @post
  329. my _capacity == max (my size, 1);
  330. */
  331. void shrinkToFit () {
  332. our _capacity = ( our size > 0 ? our size : 1 );
  333. our at ++;
  334. our at = (T**) Melder_realloc (our at, our _capacity * (int64) sizeof (Thing));
  335. our at --;
  336. }
  337. void sort (int (*compare) (T*, T*)) {
  338. integer l, r, j, i;
  339. T* k;
  340. T** a = our at._elements;
  341. integer n = our size;
  342. if (n < 2) return;
  343. l = (n >> 1) + 1;
  344. r = n;
  345. for (;;) {
  346. if (l > 1) {
  347. l --;
  348. k = a [l];
  349. } else {
  350. k = a [r];
  351. a [r] = a [1];
  352. r --;
  353. if (r == 1) { a [1] = k; return; }
  354. }
  355. j = l;
  356. for (;;) {
  357. i = j;
  358. j = j << 1;
  359. if (j > r) break;
  360. if (j < r && compare (a [j], a [j + 1]) < 0) j ++;
  361. if (compare (k, a [j]) >= 0) break;
  362. a [i] = a [j];
  363. }
  364. a [i] = k;
  365. }
  366. }
  367. /*
  368. Function:
  369. merge two Collections into a new one. The class is the same as the type of `me`.
  370. Postconditions:
  371. result->size >= my size;
  372. result->size >= thy size;
  373. */
  374. void merge (CollectionOf<T>* thee) {
  375. try {
  376. if (our classInfo != thy classInfo)
  377. Melder_throw (U"The two collections are of different classes.");
  378. if (our _ownershipInitialized && thy _ownershipInitialized && our _ownItems != thy _ownItems)
  379. Melder_throw (U"Cannot mix data and references.");
  380. if (! our _ownershipInitialized && ! thy _ownershipInitialized) {
  381. Melder_assert (our size == 0 && thy size == 0);
  382. return;
  383. }
  384. our _ownItems = ( our _ownershipInitialized ? our _ownItems : thy _ownItems );
  385. for (integer i = 1; i <= thy size; i ++) {
  386. T* item = thy at [i];
  387. if (our _ownItems) {
  388. if (! Thing_isa (item, classDaata))
  389. Melder_throw (U"Cannot copy item of class ", Thing_className (item), U".");
  390. our addItem_move (Data_copy (item));
  391. } else {
  392. our addItem_ref (item);
  393. }
  394. }
  395. } catch (MelderError) {
  396. Melder_throw (this, U" and ", thee, U" not merged." );
  397. }
  398. }
  399. /*
  400. CollectionOf overrides all virtual methods of Daata.
  401. They are defined in Collection.cpp (if not in this header file).
  402. These methods are needed only when a Collection object is used
  403. as an independent pointer-to-object created with XXX_create ().
  404. */
  405. void v_info () override {
  406. MelderInfo_writeLine (our size, U" items");
  407. }
  408. void v_destroy () noexcept override {
  409. /*
  410. The items are destroyed automatically by the destructor,
  411. which is called by delete, which is called by forget().
  412. So we only have to destroy the members of Daata,
  413. many of which are not destroyed automatically.
  414. */
  415. structDaata::v_destroy ();
  416. }
  417. void v_copy (Daata data_to) override { // copies all the items
  418. _CollectionOfDaata_v_copy (reinterpret_cast<_CollectionOfDaata*> (this), reinterpret_cast<_CollectionOfDaata*> (data_to));
  419. }
  420. bool v_equal (Daata data2) override { // compares 'my item [i]' with 'thy item [i]', i = 1..size
  421. return _CollectionOfDaata_v_equal (reinterpret_cast<_CollectionOfDaata*> (this), reinterpret_cast<_CollectionOfDaata*> (data2));
  422. }
  423. bool v_canWriteAsEncoding (int outputEncoding) override {
  424. return _CollectionOfDaata_v_canWriteAsEncoding (reinterpret_cast<_CollectionOfDaata*> (this), outputEncoding);
  425. }
  426. void v_writeText (MelderFile openFile) override {
  427. _CollectionOfDaata_v_writeText (reinterpret_cast<_CollectionOfDaata*> (this), openFile);
  428. }
  429. void v_readText (MelderReadText text, int formatVersion) override {
  430. _CollectionOfDaata_v_readText (reinterpret_cast<_CollectionOfDaata*> (this), text, formatVersion);
  431. }
  432. void v_writeBinary (FILE *f) override {
  433. _CollectionOfDaata_v_writeBinary (reinterpret_cast<_CollectionOfDaata*> (this), f);
  434. }
  435. void v_readBinary (FILE *f, int formatVersion) override {
  436. _CollectionOfDaata_v_readBinary (reinterpret_cast<_CollectionOfDaata*> (this), f, formatVersion);
  437. }
  438. Data_Description v_description () override {
  439. return & theCollectionOfDaata_v_description [0];
  440. }
  441. /*
  442. CollectionOf<> introduces one virtual method of its own (not counting the destructor).
  443. */
  444. virtual integer _v_position (T* /* data */) {
  445. return our size + 1; // at end
  446. };
  447. };
  448. #define _Collection_declare(klas,genericClass,itemClass) \
  449. typedef genericClass<struct##itemClass> struct##klas; \
  450. typedef genericClass<struct##itemClass> *klas; \
  451. typedef autoSomeThing <genericClass<struct##itemClass>> auto##klas; \
  452. extern struct structClassInfo theClassInfo_##klas; \
  453. extern ClassInfo class##klas; \
  454. static inline auto##klas klas##_create () { \
  455. auto##klas me; \
  456. me. adoptFromAmbiguousOwner (new genericClass<struct##itemClass>); \
  457. theTotalNumberOfThings += 1; \
  458. return me; \
  459. }
  460. _Collection_declare (Collection, CollectionOf, Thing);
  461. #pragma mark - class Ordered
  462. /*
  463. An Ordered is a Collection in which the order of the elements is crucial.
  464. It could also be called a List.
  465. */
  466. template <typename T>
  467. struct OrderedOf : CollectionOf <T /*Melder_ENABLE_IF_ISA (T, structDaata)*/> {
  468. OrderedOf () {
  469. extern ClassInfo classOrdered;
  470. our classInfo = classOrdered;
  471. }
  472. /**
  473. Function:
  474. insert an item at 'position'.
  475. If 'position' is less than 1 or greater than the current 'size',
  476. insert the item at the end.
  477. */
  478. T* addItemAtPosition_move (autoSomeThing <T> data, integer position) {
  479. Melder_assert (data);
  480. if (position < 1 || position > our size)
  481. position = our size + 1;
  482. return our _insertItem_move (data.move(), position);
  483. }
  484. OrderedOf<T>&& move () noexcept { return static_cast <OrderedOf<T>&&> (*this); }
  485. };
  486. _Collection_declare (Ordered, OrderedOf, Daata);
  487. #pragma mark - class Sorted
  488. /*
  489. A Sorted is a sorted Collection.
  490. Behaviour:
  491. Sorted::addItem inserts an item at such a position that the collection stays sorted.
  492. Sorted::merge yields a Sorted.
  493. */
  494. template <typename T /*Melder_ENABLE_IF_ISA (T, structDaata)*/>
  495. struct SortedOf : CollectionOf <T> {
  496. SortedOf () {
  497. extern ClassInfo classSorted;
  498. our classInfo = classSorted;
  499. }
  500. SortedOf<T>&& move () noexcept { return static_cast <SortedOf<T>&&> (*this); }
  501. /***** Two routines for optimization. ******/
  502. /* If you want to add a large group of items,
  503. it is best to call addItem_unsorted () repeatedly,
  504. and finish with Sorted::sort(), which uses the fast 'heapsort' algorithm,
  505. and, when appropriate, also SortedSet::unicize(), which has linear complexity.
  506. Calling addItem_move () repeatedly would be slower,
  507. because on average half the collection is moved in memory
  508. with every insertion.
  509. */
  510. /*
  511. Function:
  512. add an item to the collection, quickly at the end.
  513. Warning:
  514. this leaves the collection unsorted; follow by Sorted::sort ().
  515. */
  516. void addItem_unsorted_move (autoSomeThing <T> data) {
  517. our _insertItem_move (data.move(), our size + 1);
  518. }
  519. /* Call this after a number of calls to Sorted_addItem_unsorted (). */
  520. /* The procedure used is 'heapsort'. */
  521. void sort () {
  522. our CollectionOf<T>::sort (our v_getCompareHook ());
  523. }
  524. integer _v_position (T* data) override {
  525. typename SortedOf<T>::CompareHook compare = our v_getCompareHook ();
  526. if (our size == 0 || compare (data, our at [our size]) >= 0) return our size + 1;
  527. if (compare (data, our at [1]) < 0) return 1;
  528. /* Binary search. */
  529. integer left = 1, right = our size;
  530. while (left < right - 1) {
  531. integer mid = (left + right) / 2;
  532. if (compare (data, our at [mid]) >= 0) left = mid; else right = mid;
  533. }
  534. Melder_assert (right == left + 1);
  535. return right;
  536. }
  537. static int s_compareHook (T* /* data1 */, T* /* data2 */) noexcept { return 0; }
  538. typedef int (*CompareHook) (T*, T*);
  539. virtual CompareHook v_getCompareHook () { return s_compareHook; }
  540. // should compare the keys of two items; returns negative if me < thee, 0 if me == thee, and positive if me > thee
  541. };
  542. _Collection_declare (Sorted, SortedOf, Daata);
  543. #pragma mark - class SortedSet
  544. /*
  545. In a SortedSet, every item must be unique (by key).
  546. */
  547. template <typename T /*Melder_ENABLE_IF_ISA (T, structDaata)*/>
  548. struct SortedSetOf : SortedOf <T> {
  549. SortedSetOf () {
  550. extern ClassInfo classSortedSet;
  551. our classInfo = classSortedSet;
  552. }
  553. SortedSetOf<T>&& move () noexcept { return static_cast <SortedSetOf<T>&&> (*this); }
  554. /**
  555. @return
  556. 0 (refusal) if the key of `data` already occurs
  557. */
  558. integer _v_position (T* data) override {
  559. typename SortedOf<T>::CompareHook compare = our v_getCompareHook ();
  560. if (our size == 0) return 1; // empty set? then 'data' is going to be the first item
  561. int where = compare (data, our at [our size]); // compare with last item
  562. if (where > 0) return our size + 1; // insert at end
  563. if (where == 0) return 0;
  564. if (compare (data, our at [1]) < 0) return 1; // compare with first item
  565. integer left = 1, right = our size;
  566. while (left < right - 1) {
  567. integer mid = (left + right) / 2;
  568. if (compare (data, our at [mid]) >= 0)
  569. left = mid;
  570. else
  571. right = mid;
  572. }
  573. Melder_assert (right == left + 1);
  574. if (! compare (data, our at [left]) || ! compare (data, our at [right]))
  575. return 0;
  576. return right;
  577. }
  578. bool hasItem (T* item) {
  579. return our _v_position (item) == 0;
  580. }
  581. /**
  582. See the comments at Sorted::sort().
  583. @pre Must have been sorted beforehand.
  584. @post All elements are different (by key).
  585. */
  586. void unicize () {
  587. typename SortedOf<T>::CompareHook compare = our v_getCompareHook ();
  588. integer n = 0, ifrom = 1;
  589. for (integer i = 1; i <= our size; i ++) {
  590. if (i == our size || compare (our at [i], our at [i + 1]))
  591. {
  592. /*
  593. * Detected a change.
  594. */
  595. n ++;
  596. integer ito = i;
  597. /*
  598. * Move item 'ifrom' to 'n'.
  599. */
  600. Melder_assert (ifrom >= n);
  601. if (ifrom != n) {
  602. our at [n] = our at [ifrom]; // surface copy
  603. our at [ifrom] = nullptr; // undangle
  604. }
  605. /*
  606. * Purge items from 'ifrom'+1 to 'ito'.
  607. */
  608. if (our _ownItems) {
  609. for (integer j = ifrom + 1; j <= ito; j ++) {
  610. _Thing_forget (our at [j]);
  611. }
  612. }
  613. ifrom = ito + 1;
  614. }
  615. }
  616. our size = n;
  617. }
  618. };
  619. /* Behaviour:
  620. Collection_addItem (SortedSet) refuses to insert an item if this item already occurs.
  621. Equality is there when the compare routine returns 0.
  622. Collections_merge (SortedSet) yields a SortedSet that is the union of the two sources.
  623. */
  624. _Collection_declare (SortedSet, SortedSetOf, Daata);
  625. #pragma mark - class SortedSetOfInteger
  626. template <typename T Melder_ENABLE_IF_ISA (T, structSimpleInteger)>
  627. struct SortedSetOfIntegerOf : SortedSetOf <T> {
  628. SortedSetOfIntegerOf () {
  629. }
  630. SortedSetOfIntegerOf<T>&& move () noexcept { return static_cast <SortedSetOfIntegerOf<T>&&> (*this); }
  631. static int s_compareHook (SimpleInteger me, SimpleInteger thee) noexcept {
  632. if (my number < thy number) return -1;
  633. if (my number > thy number) return +1;
  634. return 0;
  635. }
  636. typename SortedOf<T>::CompareHook v_getCompareHook ()
  637. override { return (typename SortedOf<T>::CompareHook) our s_compareHook; }
  638. };
  639. #pragma mark - class SortedSetOfDouble
  640. template <typename T /*Melder_ENABLE_IF_ISA (T, structSimpleDouble)*/>
  641. struct SortedSetOfDoubleOf : SortedSetOf <T> {
  642. SortedSetOfDoubleOf () {
  643. }
  644. SortedSetOfDoubleOf<T>&& move () noexcept { return static_cast <SortedSetOfDoubleOf<T>&&> (*this); }
  645. static int s_compareHook (SimpleDouble me, SimpleDouble thee) noexcept {
  646. if (my number < thy number) return -1;
  647. if (my number > thy number) return +1;
  648. return 0;
  649. }
  650. typename SortedOf<T>::CompareHook v_getCompareHook ()
  651. override { return (typename SortedOf<T>::CompareHook) our s_compareHook; }
  652. };
  653. #pragma mark - class SortedSetOfString
  654. template <typename T Melder_ENABLE_IF_ISA (T, structSimpleString)>
  655. struct SortedSetOfStringOf : SortedSetOf <T> {
  656. SortedSetOfStringOf () {
  657. }
  658. SortedSetOfStringOf<T>&& move () noexcept { return static_cast <SortedSetOfStringOf<T>&&> (*this); }
  659. static int s_compareHook (SimpleString me, SimpleString thee) noexcept {
  660. return str32cmp (my string.get(), thy string.get());
  661. }
  662. typename SortedOf<T>::CompareHook v_getCompareHook ()
  663. override { return (typename SortedOf<T>::CompareHook) our s_compareHook; }
  664. integer lookUp (conststring32 string) {
  665. integer numberOfItems = our size;
  666. integer left = 1, right = numberOfItems;
  667. int atStart, atEnd;
  668. if (numberOfItems == 0) return 0;
  669. atEnd = str32cmp (string, our at [numberOfItems] -> string.get());
  670. if (atEnd > 0) return 0;
  671. if (atEnd == 0) return numberOfItems;
  672. atStart = str32cmp (string, our at [1] -> string.get());
  673. if (atStart < 0) return 0;
  674. if (atStart == 0) return 1;
  675. while (left < right - 1) {
  676. integer mid = (left + right) / 2;
  677. int here = str32cmp (string, our at [mid] -> string.get());
  678. if (here == 0) return mid;
  679. if (here > 0) left = mid; else right = mid;
  680. }
  681. Melder_assert (right == left + 1);
  682. return 0;
  683. }
  684. };
  685. #pragma mark - Collections of specific types
  686. #define Collection_define(klas,genericClass,itemClass) \
  687. Thing_declare (klas); \
  688. static inline auto##klas klas##_create () { return Thing_new (klas); } \
  689. struct struct##klas : genericClass<struct##itemClass>
  690. #pragma mark class DaataList
  691. Collection_define (DaataList, OrderedOf, /* generic */ Daata) {
  692. };
  693. #pragma mark class StringList
  694. Collection_define (StringList, OrderedOf, /* final */ SimpleString) {
  695. };
  696. #pragma mark class StringSet
  697. Collection_define (StringSet, SortedSetOfStringOf, /* final */ SimpleString) {
  698. void addString_copy (conststring32 string) {
  699. autoSimpleString newSimp = SimpleString_create (string);
  700. our addItem_move (newSimp.move());
  701. }
  702. };
  703. /* End of file Collection.h */
  704. #endif