package SPVM::StringBuffer : precompile {
use SPVM::ArrayUtil (copy_array_range_byte);
has value : byte[];
has length : ro int;
sub new : SPVM::StringBuffer () {
my $self = new SPVM::StringBuffer;
my $default_capacity = DEFAULT_CAPACITY();
$self->{value} = new byte [$default_capacity];
$self->{length} = 0;
return $self;
}
sub push : void ($self : self, $string : string) {
my $length = length($string);
my $capacity = @$self->{value};
if ($self->{length} + $length > $capacity) {
my $new_capacity : int;
if ($self->{length} + $length > $capacity * 2) {
$new_capacity = $self->{length} + $length;
} else {
$new_capacity = $capacity * 2;
}
$self->_reallocate($new_capacity);
}
for (my $i = 0; $i < $length; ++$i) {
$self->{value}[$self->{length} + $i] = $string->[$i];
}
$self->{length} += $length;
}
sub push_char : void ($self : self, $char : byte) {
my $capacity = @$self->{value};
if ($self->{length} + 1 > $capacity) {
my $new_capacity = $capacity * 2;
$self->_reallocate($new_capacity);
}
$self->{value}[$self->{length}++] = $char;
}
sub to_string : string ($self : self) {
return (string)(copy_array_range_byte($self->{value}, 0, $self->{length}));
}
private enum {
DEFAULT_CAPACITY = 16,
}
# O($new_capacity)
private sub _reallocate : void ($self : self, $new_capacity : int) {
my $new_string = new byte [$new_capacity];
for (my $i = 0; $i < $self->{length}; ++$i) {
$new_string->[$i] = $self->{value}[$i];
}
$self->{value} = $new_string;
}
}