Skip to content

Commit

Permalink
add new builder
Browse files Browse the repository at this point in the history
  • Loading branch information
thatstoasty committed May 28, 2024
1 parent 2d71da6 commit aa2c2e5
Show file tree
Hide file tree
Showing 14 changed files with 171 additions and 186 deletions.
1 change: 0 additions & 1 deletion gojo/bufio/bufio.mojo
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from math import max
from ..io import traits as io
from ..builtins import copy, panic
from ..builtins.bytes import Byte, index_byte
Expand Down
6 changes: 1 addition & 5 deletions gojo/builtins/bytes.mojo
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
from .list import equals


alias Byte = Int8
alias Byte = UInt8


fn has_prefix(bytes: List[Byte], prefix: List[Byte]) -> Bool:
Expand Down Expand Up @@ -44,7 +41,6 @@ fn index_byte(bytes: List[Byte], delim: Byte) -> Int:
Returns:
The index of the first occurrence of the byte delim.
"""
var i = 0
for i in range(len(bytes)):
if bytes[i] == delim:
return i
Expand Down
133 changes: 0 additions & 133 deletions gojo/builtins/list.mojo

This file was deleted.

2 changes: 1 addition & 1 deletion gojo/bytes/reader.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ struct Reader(
"""Reads and returns a single byte from the internal buffer. Implements the [io.ByteReader] Interface."""
self.prev_rune = -1
if self.index >= len(self.buffer):
return Int8(0), Error(io.EOF)
return UInt8(0), Error(io.EOF)

var byte = self.buffer[int(self.index)]
self.index += 1
Expand Down
20 changes: 10 additions & 10 deletions gojo/fmt/fmt.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,15 @@ fn sprintf(formatting: String, *args: Args) -> String:
for i in range(len(args)):
var argument = args[i]
if argument.isa[String]():
text = format_string(text, argument.get[String]()[])
text = format_string(text, argument[String])
elif argument.isa[List[Byte]]():
text = format_bytes(text, argument.get[List[Byte]]()[])
text = format_bytes(text, argument[List[Byte]])
elif argument.isa[Int]():
text = format_integer(text, argument.get[Int]()[])
text = format_integer(text, argument[Int])
elif argument.isa[Float64]():
text = format_float(text, argument.get[Float64]()[])
text = format_float(text, argument[Float64])
elif argument.isa[Bool]():
text = format_boolean(text, argument.get[Bool]()[])
text = format_boolean(text, argument[Bool])

return text

Expand Down Expand Up @@ -204,15 +204,15 @@ fn printf(formatting: String, *args: Args) raises:
for i in range(len(args)):
var argument = args[i]
if argument.isa[String]():
text = format_string(text, argument.get[String]()[])
text = format_string(text, argument[String])
elif argument.isa[List[Byte]]():
text = format_bytes(text, argument.get[List[Byte]]()[])
text = format_bytes(text, argument[List[Byte]])
elif argument.isa[Int]():
text = format_integer(text, argument.get[Int]()[])
text = format_integer(text, argument[Int])
elif argument.isa[Float64]():
text = format_float(text, argument.get[Float64]()[])
text = format_float(text, argument[Float64])
elif argument.isa[Bool]():
text = format_boolean(text, argument.get[Bool]()[])
text = format_boolean(text, argument[Bool])
else:
raise Error("Unknown for argument #" + String(i))

Expand Down
5 changes: 5 additions & 0 deletions gojo/io/__init__.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,8 @@ from .traits import (
EOF,
)
from .io import write_string, read_at_least, read_full, read_all, BUFFER_SIZE


alias i1 = __mlir_type.i1
alias i1_1 = __mlir_attr.`1: i1`
alias i1_0 = __mlir_attr.`0: i1`
4 changes: 1 addition & 3 deletions gojo/io/io.mojo
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from collections.optional import Optional
from ..builtins import cap, copy, Byte, Error, panic
from ..builtins import cap, copy, Byte, panic
from .traits import ERR_UNEXPECTED_EOF


alias BUFFER_SIZE = 4096


Expand Down Expand Up @@ -419,7 +418,6 @@ fn read_all[R: Reader](inout reader: R) -> (List[Byte], Error):
Returns:
The data read."""
var dest = List[Byte](capacity=BUFFER_SIZE)
var index: Int = 0
var at_eof: Bool = False

while True:
Expand Down
2 changes: 1 addition & 1 deletion gojo/io/traits.mojo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections.optional import Optional
from ..builtins import Byte, Error
from ..builtins import Byte

alias Rune = Int32

Expand Down
2 changes: 1 addition & 1 deletion gojo/net/net.mojo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from memory._arc import Arc
from memory.arc import Arc
import ..io
from ..builtins import Byte
from .socket import Socket
Expand Down
2 changes: 1 addition & 1 deletion gojo/net/socket.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ struct Socket(FileDescriptorBase):
src: The data to send.
max_attempts: The maximum number of attempts to send the data.
"""
var header_pointer = Pointer[Int8](src.data.address).bitcast[UInt8]()
var header_pointer = src.unsafe_ptr()
var total_bytes_sent = 0
var attempts = 0

Expand Down
97 changes: 92 additions & 5 deletions gojo/strings/builder.mojo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Adapted from https://github.com/maniartech/mojo-strings/blob/master/strings/builder.mojo
# Modified to use List[Int8] instead of List[String]
# Modified to use List[Byte] instead of List[String]

import ..io
from ..builtins import Byte
Expand Down Expand Up @@ -48,7 +48,7 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite
copy.append(0)
return String(copy)

fn get_bytes(self) -> List[Int8]:
fn get_bytes(self) -> List[Byte]:
"""
Returns a deepcopy of the byte array of the string builder.
Expand All @@ -57,7 +57,7 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite
"""
return List[Byte](self._vector)

fn get_null_terminated_bytes(self) -> List[Int8]:
fn get_null_terminated_bytes(self) -> List[Byte]:
"""
Returns a deepcopy of the byte array of the string builder with a null terminator.
Expand All @@ -80,7 +80,7 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite
self._vector.extend(src)
return len(src), Error()

fn write_byte(inout self, byte: Int8) -> (Int, Error):
fn write_byte(inout self, byte: Byte) -> (Int, Error):
"""
Appends a byte array to the builder buffer.
Expand Down Expand Up @@ -122,7 +122,7 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite
"""
return self._vector[index]

fn __setitem__(inout self, index: Int, value: Int8):
fn __setitem__(inout self, index: Int, value: Byte):
"""
Sets the string at the given index.
Expand All @@ -131,3 +131,90 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite
value: The value to set.
"""
self._vector[index] = value


@value
struct NewStringBuilder(Stringable, Sized):
"""
A string builder class that allows for efficient string management and concatenation.
This class is useful when you need to build a string by appending multiple strings
together. It is around 20x faster than using the `+` operator to concatenate
strings because it avoids the overhead of creating and destroying many
intermediate strings and performs memcopy operations.
The result is a more efficient when building larger string concatenations. It
is generally not recommended to use this class for small concatenations such as
a few strings like `a + b + c + d` because the overhead of creating the string
builder and appending the strings is not worth the performance gain.
Example:
```
from strings.builder import StringBuilder
var sb = StringBuilder()
sb.write_string("mojo")
sb.write_string("jojo")
print(sb) # mojojojo
```
"""

var _vector: DTypePointer[DType.uint8]
var _size: Int

@always_inline
fn __init__(inout self, *, size: Int = 4096):
self._vector = DTypePointer[DType.uint8]().alloc(size)
self._size = 0

@always_inline
fn __str__(self) -> String:
"""
Converts the string builder to a string.
Returns:
The string representation of the string builder. Returns an empty
string if the string builder is empty.
"""
var copy = DTypePointer[DType.uint8]().alloc(self._size + 1)
memcpy(copy, self._vector, self._size)
copy[self._size] = 0
return StringRef(copy, self._size + 1)

@always_inline
fn __del__(owned self):
if self._vector:
self._vector.free()

@always_inline
fn write(inout self, src: Span[Byte]) -> (Int, Error):
"""
Appends a byte Span to the builder buffer.
Args:
src: The byte array to append.
"""
for i in range(len(src)):
self._vector[i] = src._data[i]
self._size += 1

return len(src), Error()

@always_inline
fn write_string(inout self, src: String) -> (Int, Error):
"""
Appends a string to the builder buffer.
Args:
src: The string to append.
"""
return self.write(src.as_bytes_slice())

@always_inline
fn __len__(self) -> Int:
"""
Returns the length of the string builder.
Returns:
The length of the string builder.
"""
return self._size
Loading

0 comments on commit aa2c2e5

Please sign in to comment.