class StringBuffer : precompile {
use Fn;
has value : ro mutable string;
has length : ro int;
static method new : StringBuffer () {
my $self = new StringBuffer;
my $default_capacity = StringBuffer->DEFAULT_CAPACITY();
$self->{value} = (mutable string)new_string_len($default_capacity);
$self->{length} = 0;
return $self;
}
method push : void ($string : string) {
my $length = length($string);
my $capacity = length $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;
}
method push_char : void ($char : byte) {
my $capacity = length $self->{value};
if ($self->{length} + 1 > $capacity) {
my $new_capacity = $capacity * 2;
$self->_reallocate($new_capacity);
}
$self->{value}[$self->{length}++] = $char;
}
method to_string : string () {
return (Fn->substr($self->{value}, 0, $self->{length}));
}
private enum {
DEFAULT_CAPACITY = 16,
}
# O($new_capacity)
private method _reallocate : void ($new_capacity : int) {
my $new_string = (mutable string)new_string_len($new_capacity);
for (my $i = 0; $i < $self->{length}; ++$i) {
$new_string->[$i] = $self->{value}[$i];
}
$self->{value} = $new_string;
}
}