Example #1
0
  Array* Array::concat(STATE, Array* other) {
    if(!LANGUAGE_18_ENABLED(state)) {
      if(is_frozen_p()) return force_as<Array>(Primitives::failure());
    }

    native_int osize = other->size();

    if(osize == 0) return this;
    if(LANGUAGE_18_ENABLED(state)) {
      if(is_frozen_p()) return force_as<Array>(Primitives::failure());
    }

    if(osize == 1) {
      set(state, size(), other->get(state, 0));
      return this;
    }

    native_int new_size = size() + osize;
    Tuple* nt = Tuple::create(state, new_size);
    nt->copy_from(state, tuple_, start_, total_, Fixnum::from(0));
    nt->copy_from(state, other->tuple(), other->start(), other->total(), total_);

    tuple(state, nt);
    start(state, Fixnum::from(0));
    total(state, Fixnum::from(new_size));

    return this;
  }
Example #2
0
  void test_copy_from_dest_out_of_range() {
    Tuple* tuple = new_tuple();
    Tuple* dest = Tuple::create(state, 2);
    TS_ASSERT_THROWS_ASSERT(dest->copy_from(state, tuple, Fixnum::from(0), Fixnum::from(1),
					    Fixnum::from(2)),
			    const RubyException &e,
			    TS_ASSERT(Exception::object_bounds_exceeded_error_p(state, e.exception)));
    TS_ASSERT_THROWS_ASSERT(dest->copy_from(state, tuple, Fixnum::from(0), Fixnum::from(1),
					    Fixnum::from(-1)),
			    const RubyException &e,
			    TS_ASSERT(Exception::object_bounds_exceeded_error_p(state, e.exception)));
  }
Example #3
0
  Object* Array::set(STATE, native_int idx, Object* val) {
    native_int tuple_size = tuple_->num_fields();
    native_int oidx = idx;
    idx += start_->to_native();

    if(idx >= tuple_size) {
      if(oidx < tuple_size) {
        // There is enough space in the tuple for this element
        tuple_->lshift_inplace(state, start_);
      } else {
        // Uses the same algo as 1.8 to resize the tuple
        native_int new_size = tuple_size / 2;
        if(new_size < 3) {
          new_size = 3;
        }

        Tuple* nt = Tuple::create(state, new_size+idx);
        nt->copy_from(state, tuple_, start_, total_, Fixnum::from(0));
        tuple(state, nt);
      }
      start(state, Fixnum::from(0));
      idx = oidx;
    }

    tuple_->put(state, idx, val);
    if(total_->to_native() <= oidx) {
      total(state, Fixnum::from(oidx+1));
    }
    return val;
  }
Example #4
0
  /** @todo   Should we queue thread? Probably unnecessary. --rue */
  void Thread::priority(STATE, Fixnum* new_priority) {
    /* This gets somewhat ugly to avoid existing lists. */
    if(new_priority->to_native() < 0) {
      Exception::argument_error(state, "Thread priority must be non-negative!");
    }

    Tuple* scheduled = state->globals.scheduled_threads.get();

    std::size_t desired = new_priority->to_ulong();
    std::size_t existing = scheduled->num_fields();

    if(desired >= existing) {
      Tuple* replacement = Tuple::create(state, (desired + 1));
      replacement->copy_from(state, scheduled, Fixnum::from(0),
			     Fixnum::from(scheduled->num_fields()),
			     Fixnum::from(0));

      for(std::size_t i = existing - 1; i <= desired; ++i) {
        if(replacement->at(state, i)->nil_p()) {
          replacement->put(state, i, List::create(state));
        }
      }

      state->globals.scheduled_threads.set(replacement);
      scheduled = replacement;
    }

    priority_ = new_priority;
  }
Example #5
0
  Object* Array::set(STATE, size_t idx, Object* val) {
    size_t tuple_size = tuple_->num_fields();
    size_t oidx = idx;
    idx += start_->to_native();

    if(idx >= tuple_size) {
      // Uses the same algo as 1.8 to resize the tuple
      size_t new_size = tuple_size / 2;
      if(new_size < 3) {
        new_size = 3;
      }

      Tuple* nt = Tuple::create(state, new_size+idx);
      nt->copy_from(state, tuple_, start_, total_, Fixnum::from(0));
      tuple(state, nt);
      start(state, Fixnum::from(0));
      idx = oidx;
    }

    tuple_->put(state, idx, val);
    if((size_t)total_->to_native() <= oidx) {
      total(state, Fixnum::from(oidx+1));
    }
    return val;
  }
Example #6
0
  void test_copy_from_length_exceeds_destination() {
    Tuple* tuple = new_tuple();
    Tuple* dest = Tuple::create(state, 2);
    TS_ASSERT_THROWS_ASSERT(dest->copy_from(state, tuple, Fixnum::from(0), Fixnum::from(3),
					    Fixnum::from(0)),
			    const RubyException &e,
			    TS_ASSERT(Exception::object_bounds_exceeded_error_p(state, e.exception)));
  }
Example #7
0
 void test_copy_from_other_empty() {
   Tuple* tuple = Tuple::create(state, 0);
   Tuple* dest = new_tuple();
   dest->copy_from(state, tuple, Fixnum::from(0), Fixnum::from(0), Fixnum::from(0));
   TS_ASSERT_EQUALS(Fixnum::from(1), as<Fixnum>(dest->at(state, 0)));
   TS_ASSERT_EQUALS(Fixnum::from(4), as<Fixnum>(dest->at(state, 1)));
   TS_ASSERT_EQUALS(Fixnum::from(9), as<Fixnum>(dest->at(state, 2)));
 }
Example #8
0
  void Array::unshift(STATE, Object* val) {
    native_int new_size = total_->to_native() + 1;
    native_int lend = start_->to_native();

    if(lend > 0) {
      tuple_->put(state, lend-1, val);
      start(state, Fixnum::from(lend-1));
      total(state, Fixnum::from(new_size));
    } else {
      Tuple* nt = Tuple::create(state, new_size);
      nt->copy_from(state, tuple_, start_, total_,
		    Fixnum::from(1));
      nt->put(state, 0, val);

      total(state, Fixnum::from(new_size));
      start(state, Fixnum::from(0));
      tuple(state, nt);
    }
  }
Example #9
0
 void test_copy_from_to_empty_this() {
   Tuple* tuple = new_tuple();
   Tuple* dest = Tuple::create(state, 0);
   dest->copy_from(state, tuple, Fixnum::from(0), Fixnum::from(0), Fixnum::from(0));
 }