PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/vm/builtin/list.cpp

https://github.com/ethansr/rubinius
C++ | 138 lines | 91 code | 36 blank | 11 comment | 16 complexity | 4e5d8a8d3f0d9b9089d91290759cbd5d MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1
  1. #include "vm.hpp"
  2. #include "objectmemory.hpp"
  3. #include "object_utils.hpp"
  4. #include "builtin/list.hpp"
  5. #include "builtin/class.hpp"
  6. #include "builtin/fixnum.hpp"
  7. #include "ontology.hpp"
  8. namespace rubinius {
  9. /* Returns true if the List is empty, contains no elements. */
  10. bool List::empty_p() {
  11. return count_->to_native() == 0;
  12. }
  13. /* Returns the number of elements in the List. */
  14. size_t List::size() {
  15. return count_->to_native();
  16. }
  17. /* Register the List and List::Node classes as globals */
  18. void List::init(STATE) {
  19. Class* cls;
  20. cls = ontology::new_class_under(state, "List", G(rubinius));
  21. GO(list).set(cls);
  22. cls->set_object_type(state, ListType);
  23. G(list)->name(state, state->symbol("Rubinius::List"));
  24. GO(list_node).set(ontology::new_class_under(state,
  25. "Node", cls));
  26. G(list_node)->set_object_type(state, ListNodeType);
  27. }
  28. /* Create a new List object, containing no elements. */
  29. List* List::create(STATE) {
  30. List* list = state->new_object<List>(G(list));
  31. list->count(state, Fixnum::from(0));
  32. return list;
  33. }
  34. /* Append +obj+ to the current List. */
  35. void List::append(STATE, Object* obj) {
  36. ListNode* node = state->new_object<ListNode>(G(list_node));
  37. node->object(state, obj);
  38. ListNode* cur_last = last_;
  39. if(!cur_last->nil_p()) {
  40. cur_last->next(state, node);
  41. }
  42. last(state, node);
  43. if(first_->nil_p()) {
  44. first(state, node);
  45. }
  46. count(state, Integer::from(state, count_->to_native() + 1));
  47. }
  48. /* Return the +index+ numbered element from the beginning. */
  49. Object* List::locate(STATE, size_t index) {
  50. ListNode* cur = first_;
  51. while(index > 0) {
  52. if(cur->nil_p()) return Qnil;
  53. cur = cur->next();
  54. index--;
  55. }
  56. if(cur->nil_p()) return Qnil;
  57. return cur->object();
  58. }
  59. /* Return the first element in the list and remove it, moving all
  60. * other elements forward. */
  61. Object* List::shift(STATE) {
  62. if(empty_p()) return Qnil;
  63. count(state, Integer::from(state, count_->to_native() - 1));
  64. ListNode* n = first_;
  65. first(state, first_->next());
  66. if(last_ == n) {
  67. last(state, nil<ListNode>());
  68. }
  69. return n->object();
  70. }
  71. /* Search the List for +obj+ and remove all instances of it.
  72. *
  73. * Returns the number of elements removed. */
  74. size_t List::remove(STATE, const Object* obj) {
  75. if(empty_p()) return 0;
  76. size_t deleted = 0, counted = 0;
  77. ListNode* node = first_;
  78. ListNode* lst = nil<ListNode>();
  79. ListNode* nxt = nil<ListNode>();
  80. while(!node->nil_p()) {
  81. nxt = node->next();
  82. if(node->object() == obj) {
  83. deleted++;
  84. if(lst->nil_p()) {
  85. first(state, nxt);
  86. } else {
  87. lst->next(state, nxt);
  88. }
  89. if(last_ == node) {
  90. last(state, lst);
  91. }
  92. lst = nil<ListNode>();
  93. } else {
  94. counted++;
  95. lst = node;
  96. }
  97. node = nxt;
  98. }
  99. count(state, Integer::from(state, counted));
  100. return deleted;
  101. }
  102. }