/src/base/List.cpp

https://github.com/gehldp/OpenEaagles · C++ · 410 lines · 299 code · 38 blank · 73 comment · 109 complexity · aea743a8e6ca9ba5b0d719f2ac922512 MD5 · raw file

  1. #include "openeaagles/base/List.hpp"
  2. #include "openeaagles/base/Float.hpp"
  3. #include "openeaagles/base/Integer.hpp"
  4. #include "openeaagles/base/Pair.hpp"
  5. #include <cstdlib>
  6. namespace oe {
  7. namespace base {
  8. IMPLEMENT_EMPTY_SLOTTABLE_SUBCLASS(List, "List")
  9. List::List()
  10. {
  11. STANDARD_CONSTRUCTOR()
  12. }
  13. List::List(const double values[], const unsigned int nv)
  14. {
  15. STANDARD_CONSTRUCTOR()
  16. // Create Float's for each value and add to the list.
  17. for (unsigned int i = 0; i < nv; i++) {
  18. const auto p = new Float(values[i]);
  19. put(p);
  20. p->unref(); // ref() by put(), so we can unref().
  21. }
  22. }
  23. List::List(const int values[], const unsigned int nv)
  24. {
  25. STANDARD_CONSTRUCTOR()
  26. // Create Integer's for each value and add to the list.
  27. for (unsigned int i = 0; i < nv; i++) {
  28. const auto p = new Integer(values[i]);
  29. put(p);
  30. p->unref(); // ref() by put(), so we can unref().
  31. }
  32. }
  33. void List::copyData(const List& org, const bool)
  34. {
  35. BaseClass::copyData(org);
  36. // Clear the old list (if any)
  37. clear();
  38. // Copy the new list
  39. const Item* d = org.getFirstItem();
  40. for ( ; d != nullptr; d = d->getNext() ) {
  41. Object* p = d->getValue()->clone();
  42. if (p != nullptr) {
  43. addTail(p);
  44. p->unref(); // p is ref() by addTail(), so we can unref();
  45. }
  46. }
  47. }
  48. void List::deleteData()
  49. {
  50. clear();
  51. }
  52. //------------------------------------------------------------------------------
  53. // isValid() -- is this a valid List
  54. //------------------------------------------------------------------------------
  55. bool List::isValid() const
  56. {
  57. bool ok = Object::isValid();
  58. for (const Item* d = headP; ok && d != nullptr; d = d->getNext() ) {
  59. const Object* obj = d->getValue();
  60. if (obj != nullptr) {
  61. if (!obj->isValid()) ok = false;
  62. }
  63. else ok = false;
  64. }
  65. return ok;
  66. }
  67. //------------------------------------------------------------------------------
  68. // clear() -- clear out (or empty) the list
  69. //------------------------------------------------------------------------------
  70. void List::clear()
  71. {
  72. // Empty out the list ...
  73. while (!isEmpty()) {
  74. Object* p = removeHead(); // First remove them
  75. if (p != nullptr) {
  76. p->unref(); // and unref() them
  77. }
  78. }
  79. headP = nullptr;
  80. tailP = nullptr;
  81. num = 0;
  82. }
  83. //------------------------------------------------------------------------------
  84. // find(Object*) -- find object on the list
  85. //------------------------------------------------------------------------------
  86. unsigned int List::getIndex(const Object* const obj) const
  87. {
  88. const Item* p = nullptr;
  89. int idx = 0;
  90. for (const Item* d = headP; d != nullptr; d = d->getNext() ) {
  91. idx++;
  92. if ( obj == d->getValue() ) {
  93. p = d;
  94. break;
  95. }
  96. }
  97. return ((p != nullptr) ? idx : 0);
  98. }
  99. //------------------------------------------------------------------------------
  100. // addHead(Object*) -- Adds object to the head of the list.
  101. //------------------------------------------------------------------------------
  102. void List::addHead(Object* const obj)
  103. {
  104. if (obj == nullptr) return;
  105. const auto d = new Item;
  106. d->value = obj;
  107. obj->ref();
  108. addHead(d);
  109. }
  110. //------------------------------------------------------------------------------
  111. // addTail(Object*) -- Adds object to the tail of the list.
  112. //------------------------------------------------------------------------------
  113. void List::addTail(Object* const obj)
  114. {
  115. if (obj == nullptr) return;
  116. const auto d = new Item;
  117. d->value = obj;
  118. obj->ref();
  119. addTail(d);
  120. }
  121. //------------------------------------------------------------------------------
  122. // remove(Object*) -- Removes object from the list.
  123. //------------------------------------------------------------------------------
  124. bool List::remove(const Object* const obj)
  125. {
  126. bool ok = false;
  127. if (obj != nullptr) {
  128. Item* d = headP;
  129. for ( ; d != nullptr; d = d->getNext() ) {
  130. if ( obj == d->getValue() ) break;
  131. }
  132. if (d != nullptr) {
  133. remove(d);
  134. ok = true;
  135. }
  136. }
  137. if (ok) obj->unref();
  138. return ok;
  139. }
  140. //------------------------------------------------------------------------------
  141. // int getNumberList(float* values, int max)
  142. // int getNumberList(int* values, int max)
  143. // This routine is a method to retrieve an array of Numbers (or
  144. // Pairs that contain Numbers) from a list. A maximum
  145. // of 'max' items from the list are placed in the array 'values'.
  146. // A zero is placed in 'values' when the item is not a Number.
  147. // The number of values placed in 'values' is returned by
  148. // getNumberList().
  149. //------------------------------------------------------------------------------
  150. unsigned int List::getNumberList(double values[], const unsigned int max) const
  151. {
  152. unsigned int n = 0;
  153. for (const Item* p = getFirstItem(); p != nullptr && n < max; p = p->getNext() ) {
  154. const Object* p1 = p->getValue();
  155. const auto gp = dynamic_cast<const Pair*>(p1);
  156. if (gp != nullptr) {
  157. // when the item is a Pair, use the object it contains.
  158. p1 = gp->object();
  159. }
  160. const auto pp = dynamic_cast<const Number*>(p1);
  161. if (pp != nullptr) {
  162. // when we have a number
  163. values[n++] = pp->getDouble();
  164. }
  165. else {
  166. // when we do not have a number
  167. values[n++] = 0.0;
  168. }
  169. }
  170. return n;
  171. }
  172. unsigned int List::getNumberList(float values[], const unsigned int max) const
  173. {
  174. unsigned int n = 0;
  175. for (const Item* p = getFirstItem(); p != nullptr && n < max; p = p->getNext() ) {
  176. const Object* p1 = p->getValue();
  177. const auto gp = dynamic_cast<const Pair*>(p1);
  178. if (gp != nullptr) {
  179. // when the item is a Pair, use the object it contains.
  180. p1 = gp->object();
  181. }
  182. const auto pp = dynamic_cast<const Number*>(p1);
  183. if (pp != nullptr) {
  184. // when we have a number
  185. values[n++] = pp->getFloat();
  186. }
  187. else {
  188. // when we do not have a number
  189. values[n++] = 0.0f;
  190. }
  191. }
  192. return n;
  193. }
  194. unsigned int List::getNumberList(int values[], const unsigned int max) const
  195. {
  196. unsigned int n = 0;
  197. for (const Item* p = getFirstItem(); p != nullptr && n < max; p = p->getNext() ) {
  198. const Object* p1 = p->getValue();
  199. const auto gp = dynamic_cast<const Pair*>(p1);
  200. if (gp != nullptr) {
  201. // when the item is a Pair, use the object it contains.
  202. p1 = gp->object();
  203. }
  204. const auto pp = dynamic_cast<const Number*>(p1);
  205. if (pp != nullptr) {
  206. // when we have a number
  207. values[n++] = pp->getInt();
  208. }
  209. else {
  210. // when we do not have a number
  211. values[n++] = 0;
  212. }
  213. }
  214. return n;
  215. }
  216. //------------------------------------------------------------------------------
  217. // removeHead() -- Removes the item at the head of the list.
  218. // (Ownership passed to caller -- does not unref())
  219. //------------------------------------------------------------------------------
  220. Object* List::removeHead()
  221. {
  222. Object* p = nullptr;
  223. if (headP != nullptr) {
  224. Item* d = headP;
  225. headP = headP->next;
  226. p = d->getValue();
  227. num--;
  228. if (headP != nullptr) headP->previous = nullptr;
  229. else tailP = nullptr;
  230. delete d;
  231. }
  232. return p;
  233. }
  234. //------------------------------------------------------------------------------
  235. // removeTail() -- Removes the item at the tail of the list.
  236. // (Ownership passed to caller -- does not unref())
  237. //------------------------------------------------------------------------------
  238. Object* List::removeTail()
  239. {
  240. Object* p = nullptr;
  241. if (tailP != nullptr) {
  242. Item *d = tailP;
  243. tailP = tailP->previous;
  244. p = d->getValue();
  245. num--;
  246. if (tailP != nullptr) tailP->next = nullptr;
  247. else headP = nullptr;
  248. delete d;
  249. }
  250. return p;
  251. }
  252. //------------------------------------------------------------------------------
  253. // insert(Item*) -- insert a new item before 'refItem'. If 'refItem' is
  254. // null(0), the new item is added to the tail of the list.
  255. //------------------------------------------------------------------------------
  256. bool List::insert(List::Item* newItem, List::Item* refItem)
  257. {
  258. bool ok = true;
  259. if (refItem != nullptr) {
  260. if (refItem == headP) {
  261. addHead(newItem);
  262. }
  263. else {
  264. newItem->previous = refItem->previous;
  265. refItem->previous = newItem;
  266. newItem->previous->next = newItem;
  267. newItem->next = refItem;
  268. num++;
  269. }
  270. }
  271. else {
  272. addTail(newItem);
  273. }
  274. return ok;
  275. }
  276. //------------------------------------------------------------------------------
  277. // remove(Item*) -- Removes the Item from the list.
  278. // (Ownership passed to caller -- does not unref())
  279. //------------------------------------------------------------------------------
  280. Object* List::remove(List::Item* item)
  281. {
  282. Object* value = nullptr;
  283. if (headP == item)
  284. value = removeHead();
  285. else if (tailP == item)
  286. value = removeTail();
  287. else if (item != nullptr) {
  288. value = item->getValue();
  289. num--;
  290. Item* p = item->getPrevious();
  291. Item* n = item->getNext();
  292. n->previous = p;
  293. p->next = n;
  294. delete item;
  295. }
  296. return value;
  297. }
  298. //------------------------------------------------------------------------------
  299. // addHead(Item*) -- Adds the Item to the head of the list.
  300. //------------------------------------------------------------------------------
  301. void List::addHead(List::Item* item)
  302. {
  303. item->previous = nullptr;
  304. item->next = headP;
  305. if (headP != nullptr) headP->previous = item;
  306. headP = item;
  307. if (tailP == nullptr) tailP = item;
  308. num++;
  309. }
  310. //------------------------------------------------------------------------------
  311. // addTail(Item*) -- Adds the Item to the tail of the list.
  312. //------------------------------------------------------------------------------
  313. void List::addTail(List::Item* item)
  314. {
  315. item->next = nullptr;
  316. item->previous = tailP;
  317. if (tailP != nullptr) tailP->next = item;
  318. tailP = item;
  319. if (headP == nullptr) headP = item;
  320. num++;
  321. }
  322. //------------------------------------------------------------------------------
  323. // operator== Returns true if two lists are equal.
  324. //------------------------------------------------------------------------------
  325. bool List::operator==(const List& l) const
  326. {
  327. if (entries() != l.entries()) return false;
  328. const Item* tt = getFirstItem();
  329. const Item* ll = l.getFirstItem();
  330. while (tt != nullptr) {
  331. if (tt->getValue() != ll->getValue()) return false;
  332. tt = tt->getNext();
  333. ll = ll->getNext();
  334. }
  335. return true;
  336. }
  337. //------------------------------------------------------------------------------
  338. // operator!= Returns true if two lists are NOT equal.
  339. //------------------------------------------------------------------------------
  340. bool List::operator!=(const List& l) const
  341. {
  342. return !(*this == l);
  343. }
  344. //------------------------------------------------------------------------------
  345. // getPosition1() -- Returns the object at the n'th position; w/o next pointer
  346. //------------------------------------------------------------------------------
  347. const Object* List::getPosition1(const unsigned int n) const
  348. {
  349. if (n < 1 || n > num) return nullptr;
  350. unsigned int i = 1;
  351. const Item* p = getFirstItem();
  352. while (i < n && p != nullptr) {
  353. p = p->getNext();
  354. i++;
  355. }
  356. if (p != nullptr)
  357. return p->getValue();
  358. else
  359. return nullptr;
  360. }
  361. std::ostream& List::serialize(std::ostream& sout, const int, const bool) const
  362. {
  363. std::cout << "{" << std::endl;
  364. for (const Item* p = getFirstItem(); p != nullptr; p = p->getNext() ) {
  365. if (p->getValue() != nullptr) p->getValue()->serialize(sout,4);
  366. else std::cout << "<BAD VALUE>" << std::endl;
  367. }
  368. std::cout << "}" << std::endl;
  369. return sout;
  370. }
  371. }
  372. }