PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/vm/builtin/list.cpp

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