# Copyright (c) 2023 Yuki Kimoto # MIT License class ShortList { use Fn; use Array; # Enumerations enum { DEFAULT_CAPACITY = 4, } # Fields has capacity : ro int; has length : ro int; has array : short[]; # Class methods static method new : ShortList ($array : short[] = undef, $capacity : int = -1) { my $length : int; if ($array) { $length = @$array; } else { $length = 0; } my $self = &new_len($length, $capacity); if ($array) { Array->memcpy_short($self->{array}, 0, $array, 0, $length); } return $self; } static method new_len : ShortList ($length : int, $capacity : int = -1) { my $self = new ShortList; unless ($length >= 0) { die "The \$length must be greater than or equal to 0."; } if ($capacity < 0) { $capacity = &DEFAULT_CAPACITY; } if ($length > $capacity) { $capacity = $length; } $self->{capacity} = $capacity; $self->{length} = $length; $self->{array} = new short[$capacity]; return $self; } # Instance methods method get : int ($index : int) { my $length = $self->length; unless ($index >= 0) { die "The \$index must be greater than or equal to 0."; } unless ($index < $length) { die "The \$index must be less than the length of the \$list."; } my $element = $self->{array}[$index]; return $element; } method insert : void ($index : int, $element : int) { my $length = $self->{length}; unless ($index >= 0) { die "The \$index must be greater than or equal to 0."; } unless ($index <= $length) { die "The \$index must be less than or equal to the length of the \$list."; } my $new_length = $length + 1; $self->_maybe_extend($new_length); my $elements = $self->{array}; if ($index != $length) { my $dist_index = $index + 1; my $move_length = $length - $index; Array->memmove_short($elements, $dist_index, $elements, $index, $move_length); } $elements->[$index] = (short)$element; $self->{length} = $new_length; } method pop : int () { my $length = $self->length; unless ($length > 0) { die "The length of the \$list must be greater than 0."; } my $element = $self->{array}[$length - 1]; $self->{array}[$length - 1] = 0; $self->{length}--; return $element; } method push : void ($element : int) { my $length = $self->{length}; my $new_length = $length + 1; $self->_maybe_extend($new_length); $self->{array}[$length] = (short)$element; $self->{length} = $new_length; } method remove : int ($index : int) { my $length = $self->{length}; unless ($index >= 0) { die "The \$index must be greater than or equal to 0."; } unless ($index < $length) { die "The \$index must be less than the length of the \$list."; } my $elements = $self->{array}; my $remove_value = $elements->[$index]; my $dist_index = $index; my $src_index = $index + 1; my $move_length = $length - $index - 1; Array->memmove_short($elements, $dist_index, $elements, $src_index, $move_length); $self->{length}--; return $remove_value; } method replace : void ($offset : int, $remove_length : int, $replace : short[]) { unless ($offset >= 0) { die "The \$offset must be greater than or equal to 0."; } unless ($remove_length >= 0) { die "The \$remove_length must be greater than or equal to 0."; } unless ($offset + $remove_length <= $self->{length}) { die "The \$offset + the \$removing lenght must be less than or equal to the length of the \$list."; } my $replace_length = 0; if ($replace) { $replace_length = @$replace; } my $new_length = $self->{length} - $remove_length + $replace_length; $self->_maybe_extend($new_length); my $move_length = $self->{length} - $offset - $remove_length; Array->memmove_short($self->{array}, $offset + $replace_length, $self->{array}, $offset + $remove_length, $move_length); if ($replace) { Array->memcpy_short($self->{array}, $offset, $replace, 0, $replace_length); } $self->{length} = $new_length; } method reserve : void ($new_capacity : int) { unless ($new_capacity >= 0) { die "The \$new_capacity must be greater than or equal to 0."; } my $capacity = $self->{capacity}; if ($new_capacity > $capacity) { my $length = $self->{length}; my $new_array = new short[$new_capacity]; Array->memcpy_short($new_array, 0, $self->{array}, 0, $length); $self->{array} = $new_array; $self->{capacity} = $new_capacity; } } method resize : void ($new_length : int) { unless ($new_length >= 0) { die "The \$new_length must be greater than or equal to 0."; } my $length = $self->{length}; if ($new_length > $length) { $self->_maybe_extend($new_length); Array->memset_short($self->{array}, 0, $length, $new_length - $length); } elsif ($new_length < $length) { Array->memset_short($self->{array}, 0, $new_length, $length - $new_length); } $self->{length} = $new_length; } method set : void ($index : int, $element : int) { my $length = $self->length; unless ($index >= 0) { die "The \$index must be greater than or equal to 0."; } unless ($index < $length) { die "The \$index must be less than the length of the \$list."; } $self->{array}[$index] = (short)$element; } method set_array : void ($array : short[]) { unless ($array) { die "The \$array must be defined."; } my $current_length = $self->length; my $set_length = @$array; unless ($set_length == $current_length) { die "The length of the \$array must be the \$same as the length of the \$list."; } Array->memcpy_short($self->{array}, 0, $array, 0, $current_length); } method shift : short () { my $length = $self->{length}; unless ($length > 0) { die "The length of the \$list must be greater than 0."; } my $elements = $self->{array}; my $element = $elements->[0]; Array->memmove_short($elements, 0, $elements, 1, $length - 1); $elements->[$length - 1] = 0; $self->{length}--; return $element; } method to_array : short[] () { my $length = $self->length; my $new_array = new short[$length]; my $elements = $self->{array}; Array->memcpy_short($new_array, 0, $elements, 0, $length); return $new_array; } method get_array_unsafe : short[] () { return $self->{array}; } method unshift : void ($element : int) { my $length = $self->{length}; my $new_length = $length + 1; $self->_maybe_extend($new_length); my $elements = $self->{array}; Array->memmove_short($elements, 1, $elements, 0, $length); $elements->[0] = (short)$element; $self->{length} = $new_length; } private method _maybe_extend : void ($min_capacity : int) { my $capacity = $self->{capacity}; unless ($min_capacity > $capacity) { return; } if ($capacity < $min_capacity) { $capacity = $min_capacity; } my $new_capacity = $capacity * 2; my $new_array = new short[$new_capacity]; my $length = $self->{length}; my $elements = $self->{array}; Array->memcpy_short($new_array, 0, $elements, 0, $length); $self->{array} = $new_array; $self->{capacity} = $new_capacity; } }