diff --git a/README.md b/README.md index 227e04e..c343af9 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ All of these packages are partially implemented and do not support unicode chara - `Reader`: Buffered `io.Reader` - `Scanner`: Scanner interface to read data via tokens. - `bytes` - - `Buffer`: Buffer backed by `List[UInt8]`. - - `Reader`: Reader backed by `List[UInt8]`. + - `Buffer`: Buffer backed by `DTypePointer[DType.uint8]`. + - `Reader`: Reader backed by `DTypePointer[DType.uint8]`. - `io` - Traits: `Reader`, `Writer`, `Seeker`, `Closer`, `ReadWriter`, `ReadCloser`, `WriteCloser`, `ReadWriteCloser`, `ReadSeeker`, `ReadSeekCloser`, `WriteSeeker`, `ReadWriteSeeker`, `ReaderFrom`, `WriterReadFrom`, `WriterTo`, `ReaderWriteTo`, `ReaderAt`, `WriterAt`, `ByteReader`, `ByteScanner`, `ByteWriter`, `StringWriter` - `Reader` and `Writer` wrapper functions. diff --git a/gojo/bytes/buffer.mojo b/gojo/bytes/buffer.mojo index 964a48c..fd7dbed 100644 --- a/gojo/bytes/buffer.mojo +++ b/gojo/bytes/buffer.mojo @@ -1,5 +1,6 @@ import ..io from ..builtins import cap, copy, Byte, panic, index_byte +from algorithm.memory import parallel_memcpy alias Rune = Int32 @@ -35,7 +36,6 @@ alias ERR_NEGATIVE_READ = "buffer.Buffer: reader returned negative count from re alias ERR_SHORT_WRITE = "short write" -@value struct Buffer( Stringable, Sized, @@ -55,7 +55,7 @@ struct Buffer( fn __init__(inout self): self.capacity = 4096 self.size = 0 - self.data = DTypePointer[DType.uint8]().alloc(self.capacity) + self.data = DTypePointer[DType.uint8]().alloc(4096) self.offset = 0 self.last_read = OP_INVALID @@ -67,6 +67,19 @@ struct Buffer( self.offset = 0 self.last_read = OP_INVALID + @always_inline + fn __moveinit__(inout self, owned other: Self): + self.data = other.data + self.size = other.size + self.capacity = other.capacity + self.offset = other.offset + self.last_read = other.last_read + other.data = DTypePointer[DType.uint8]() + other.size = 0 + other.capacity = 0 + other.offset = 0 + other.last_read = OP_INVALID + @always_inline fn __del__(owned self): if self.data: @@ -88,11 +101,7 @@ struct Buffer( """Returns a list of bytes holding a copy of the unread portion of the buffer.""" var copy = UnsafePointer[UInt8]().alloc(self.size) memcpy(copy, self.data.offset(self.offset), self.size) - return List[UInt8]( - unsafe_pointer=copy, - size=self.size - self.offset, - capacity=self.size - self.offset, - ) + return List[UInt8](unsafe_pointer=copy, size=self.size - self.offset, capacity=self.size - self.offset) @always_inline fn _resize(inout self, capacity: Int) -> None: @@ -133,9 +142,7 @@ struct Buffer( return StringRef(copy, self.size) @always_inline - fn render( - self: Reference[Self], - ) -> StringSlice[self.is_mutable, self.lifetime]: + fn render(self: Reference[Self]) -> StringSlice[self.is_mutable, self.lifetime]: """ Return a StringSlice view of the data owned by the builder. Slightly faster than __str__, 10-20% faster in limited testing. @@ -241,11 +248,7 @@ struct Buffer( # Copy the data of the internal buffer from offset to len(buf) into the destination buffer at the given index. var bytes_read = copy( - target=dest, - source=self.data, - source_start=self.offset, - source_end=self.size, - target_start=len(dest), + target=dest, source=self.data, source_start=self.offset, source_end=self.size, target_start=len(dest) ) self.offset += bytes_read @@ -332,11 +335,7 @@ struct Buffer( var copy = UnsafePointer[UInt8]().alloc(end - self.offset) memcpy(copy, self.data.offset(self.offset), end - self.offset) - var line = List[Byte]( - unsafe_pointer=copy, - size=end - self.offset, - capacity=end - self.offset, - ) + var line = List[Byte](unsafe_pointer=copy, size=end - self.offset, capacity=end - self.offset) self.offset = end self.last_read = OP_READ @@ -541,8 +540,7 @@ struct LegacyBuffer( fn try_grow_by_reslice(inout self, n: Int) -> (Int, Bool): """Inlineable version of grow for the fast-case where the internal buffer only needs to be resliced. - It returns the index where bytes should be written and whether it succeeded. - """ + It returns the index where bytes should be written and whether it succeeded.""" var buffer_already_used = len(self.buf) if n <= self.buf.capacity - buffer_already_used: diff --git a/gojo/strings/builder.mojo b/gojo/strings/builder.mojo index de1f1ac..3ea8752 100644 --- a/gojo/strings/builder.mojo +++ b/gojo/strings/builder.mojo @@ -2,7 +2,6 @@ import ..io from ..builtins import Byte -@value struct StringBuilder[growth_factor: Float32 = 2]( Stringable, Sized, @@ -24,14 +23,14 @@ struct StringBuilder[growth_factor: Float32 = 2]( builder and appending the strings is not worth the performance gain. Example: - ``` - from strings.builder import StringBuilder - - var sb = StringBuilder() - sb.write_string("Hello ") - sb.write_string("World!") - print(sb) # Hello World! - ``` + ``` + from strings.builder import StringBuilder + + var sb = StringBuilder() + sb.write_string("Hello ") + sb.write_string("World!") + print(sb) # Hello World! + ``` """ var data: DTypePointer[DType.uint8] @@ -45,6 +44,15 @@ struct StringBuilder[growth_factor: Float32 = 2]( self.size = 0 self.capacity = capacity + @always_inline + fn __moveinit__(inout self, owned other: Self): + self.data = other.data + self.size = other.size + self.capacity = other.capacity + other.data = DTypePointer[DType.uint8]() + other.size = 0 + other.capacity = 0 + @always_inline fn __del__(owned self): if self.data: @@ -92,7 +100,7 @@ struct StringBuilder[growth_factor: Float32 = 2]( Resizes the string builder buffer. Args: - capacity: The new capacity of the string builder buffer. + capacity: The new capacity of the string builder buffer. """ var new_data = DTypePointer[DType.uint8]().alloc(capacity) memcpy(new_data, self.data, self.size) @@ -138,7 +146,7 @@ struct StringBuilder[growth_factor: Float32 = 2]( Appends a string to the builder buffer. Args: - src: The string to append. + src: The string to append. """ return self._write(src.as_bytes_slice())