vec_string_grow Subroutine

private pure subroutine vec_string_grow(self, needed, err)

Ensure capacity for at least needed elements, preserving the live ones. Capacity starts at PIC_VECTOR_MIN_CAPACITY and doubles, which keeps a run of push_back calls amortised O(1).

Arguments

Type IntentOptional Attributes Name
class(vector_string_t), intent(inout) :: self
integer(kind=default_int), intent(in) :: needed
type(error_t), intent(inout), optional :: err

Calls

proc~~vec_string_grow~~CallsGraph proc~vec_string_grow vec_string_grow proc~error_raise error_raise proc~vec_string_grow->proc~error_raise proc~vec_string_capacity vector_string_t%vec_string_capacity proc~vec_string_grow->proc~vec_string_capacity proc~error_set error_t%error_set proc~error_raise->proc~error_set

Called by

proc~~vec_string_grow~~CalledByGraph proc~vec_string_grow vec_string_grow proc~vec_string_append vector_string_t%vec_string_append proc~vec_string_append->proc~vec_string_grow proc~vec_string_push_back vector_string_t%vec_string_push_back proc~vec_string_push_back->proc~vec_string_grow proc~vec_string_reserve vector_string_t%vec_string_reserve proc~vec_string_reserve->proc~vec_string_grow proc~vec_string_resize vector_string_t%vec_string_resize proc~vec_string_resize->proc~vec_string_grow

Variables

Type Visibility Attributes Name Initial
type(string_type), private, allocatable :: bigger(:)
integer(kind=default_int), private :: new_capacity
integer, private :: stat

Source Code

   pure subroutine vec_string_grow(self, needed, err)
      !! Ensure capacity for at least `needed` elements, preserving the live
      !! ones. Capacity starts at PIC_VECTOR_MIN_CAPACITY and doubles, which
      !! keeps a run of `push_back` calls amortised O(1).
      class(vector_string_t), intent(inout) :: self
      integer(default_int), intent(in) :: needed
      type(error_t), intent(inout), optional :: err

      type(string_type), allocatable :: bigger(:)
      integer(default_int) :: new_capacity
      integer :: stat

      if (needed <= vec_string_capacity(self)) return

      ! `needed` is negative only if a caller's arithmetic wrapped on the way
      ! in. It cannot be compared against PIC_VECTOR_MAX_CAPACITY, which is
      ! `huge(0_default_int)` and so can never be exceeded by a value of that
      ! kind -- a guard written that way is dead code. The callers below check
      ! their headroom before adding; this catches anything that slips past.
      if (needed < 0_default_int) then
         call error_raise(err, ERROR_ALLOC, &
                          "vector_string_t: requested capacity overflowed.")
         return
      end if

      new_capacity = max(vec_string_capacity(self), PIC_VECTOR_MIN_CAPACITY)
      do while (new_capacity < needed)
         ! Doubling is done only when it cannot overflow default_int; past that
         ! point the clamp is the only remaining step, and `needed` is already
         ! known to fit.
         if (new_capacity > PIC_VECTOR_MAX_CAPACITY/2) then
            new_capacity = PIC_VECTOR_MAX_CAPACITY
            exit
         end if
         new_capacity = 2*new_capacity
      end do

      allocate (bigger(new_capacity), stat=stat)
      ! `allocated` rather than `stat`: nvfortran does not set stat reliably
      ! for every element type, while `allocated` always reports the truth.
      if (.not. allocated(bigger)) then
         call error_raise(err, ERROR_ALLOC, "vector_string_t: allocation of backing storage failed.")
         return
      end if

      if (self%n_items > 0) bigger(1:self%n_items) = self%items(1:self%n_items)
      call move_alloc(bigger, self%items)
   end subroutine vec_string_grow