Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,13 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Checkout
uses: actions/checkout@v4

- name: Download zig
run: wget https://ziglang.org/builds/zig-linux-x86_64-0.15.0-dev.75+03123916e.tar.xz

- name: Extract
run: tar -xf zig-linux-x86_64-0.15.0-dev.75+03123916e.tar.xz

- name: Alias
run: alias zig=$PWD/zig-linux-x86_64-0.15.0-dev.75+03123916e/zig

- name: Version
run: $PWD/zig-linux-x86_64-0.15.0-dev.75+03123916e/zig version
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.15.1

- name: Test
run: $PWD/zig-linux-x86_64-0.15.0-dev.75+03123916e/zig build test
run: zig build test
15 changes: 12 additions & 3 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,23 @@ pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

_ = b.addModule("string", .{ .root_source_file = b.path("zig-string.zig") });
_ = b.addModule("string", .{
.root_source_file = b.path("zig-string.zig"),
.target = target,
.optimize = optimize,
});

var main_tests = b.addTest(.{
const test_mod = b.addModule("string-tests", .{
.root_source_file = b.path("zig-string-tests.zig"),
.target = target,
.optimize = optimize,
});

const main_tests = b.addTest(.{
.root_module = test_mod,
});

const run_main_tests = b.addRunArtifact(main_tests);
const test_step = b.step("test", "Run library tests");
test_step.dependOn(&main_tests.step);
test_step.dependOn(&run_main_tests.step);
}
2 changes: 1 addition & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.{
.name = .zig_string,
.version = "0.10.0",
.minimum_zig_version = "0.14.0",
.minimum_zig_version = "0.15.1",
.fingerprint = 0xd2ee692e5a4bdae9,
.paths = .{""},
}
8 changes: 5 additions & 3 deletions zig-string-tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,11 @@ test "String Tests" {
try expectEqual(myStr.size, 0);

// writer
const writer = myStr.writer();
const length = try writer.write("This is a Test!");
var writer = myStr.writer(&.{});
const w = &writer.interface;
const length = try w.write("This is a Test!");
try expectEqual(length, 15);
try w.flush();

// owned
const mySlice = try myStr.toOwned();
Expand Down Expand Up @@ -300,4 +302,4 @@ test "includes Tests" {

try expect(myString.includesLiteral("") == false);
try expect(myString.includesString(needle) == false);
}
}
106 changes: 62 additions & 44 deletions zig-string.zig
Original file line number Diff line number Diff line change
Expand Up @@ -359,15 +359,16 @@ pub const String = struct {

/// Splits the String into slices, based on a delimiter.
pub fn splitAll(self: *const String, delimiters: []const u8) ![][]const u8 {
var splitArr = std.ArrayList([]const u8).init(std.heap.page_allocator);
defer splitArr.deinit();
const allocator = std.heap.page_allocator;
var splitArr: std.ArrayList([]const u8) = .empty;
errdefer splitArr.deinit(allocator);

var i: usize = 0;
while (self.split(delimiters, i)) |slice| : (i += 1) {
try splitArr.append(slice);
try splitArr.append(allocator, slice);
}

return try splitArr.toOwnedSlice();
return try splitArr.toOwnedSlice(allocator);
}

/// Splits the String into a new string, based on delimiters and an index
Expand All @@ -385,22 +386,20 @@ pub const String = struct {
/// Splits the String into a slice of new Strings, based on delimiters.
/// The user of this function is in charge of the memory of the new Strings.
pub fn splitAllToStrings(self: *const String, delimiters: []const u8) ![]String {
var splitArr = std.ArrayList(String).init(std.heap.page_allocator);
defer splitArr.deinit();
const allocator = std.heap.page_allocator;
var splitArr: std.ArrayList(String) = .empty;
errdefer splitArr.deinit(allocator);

var i: usize = 0;
while (try self.splitToString(delimiters, i)) |splitStr| : (i += 1) {
try splitArr.append(splitStr);
try splitArr.append(allocator, splitStr);
}

return try splitArr.toOwnedSlice();
return try splitArr.toOwnedSlice(allocator);
}

/// Splits the String into a slice of Strings by new line (\r\n or \n).
pub fn lines(self: *String) ![]String {
var lineArr = std.ArrayList(String).init(std.heap.page_allocator);
defer lineArr.deinit();

var selfClone = try self.clone();
defer selfClone.deinit();

Expand Down Expand Up @@ -486,45 +485,66 @@ pub const String = struct {
}

// Writer functionality for the String.
pub usingnamespace struct {
pub const Writer = std.io.Writer(*String, Error, appendWrite);

pub fn writer(self: *String) Writer {
return .{ .context = self };
}

fn appendWrite(self: *String, m: []const u8) !usize {
try self.concat(m);
return m.len;
// pub const Writer = std.io.Writer(*String, Error, appendWrite);
pub const Writer = struct {
string: *String,
interface: std.Io.Writer,
err: ?Error = null,

fn drain(w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize {
_ = splat;
const a: *@This() = @alignCast(@fieldParentPtr("interface", w));
const buffered = w.buffered();
if (buffered.len != 0) return w.consume(a.string.appendWrite(buffered) catch |err| {
a.err = err;
return error.WriteFailed;
});
return a.string.appendWrite(data[0]) catch |err| {
a.err = err;
return error.WriteFailed;
};
}
};

// Iterator support
pub usingnamespace struct {
pub const StringIterator = struct {
string: *const String,
index: usize,

pub fn next(it: *StringIterator) ?[]const u8 {
if (it.string.buffer) |buffer| {
if (it.index == it.string.size) return null;
const i = it.index;
it.index += String.getUTF8Size(buffer[i]);
return buffer[i..it.index];
} else {
return null;
}
}
pub fn writer(self: *String, buffer: []u8) Writer {
return .{
.string = self,
.interface = .{
.buffer = buffer,
.vtable = &.{ .drain = Writer.drain },
},
};
}

pub fn iterator(self: *const String) StringIterator {
return StringIterator{
.string = self,
.index = 0,
};
fn appendWrite(self: *String, m: []const u8) !usize {
try self.concat(m);
return m.len;
}

// Iterator support
pub const StringIterator = struct {
string: *const String,
index: usize,

pub fn next(it: *StringIterator) ?[]const u8 {
if (it.string.buffer) |buffer| {
if (it.index == it.string.size) return null;
const i = it.index;
it.index += String.getUTF8Size(buffer[i]);
return buffer[i..it.index];
} else {
return null;
}
}
};

pub fn iterator(self: *const String) StringIterator {
return StringIterator{
.string = self,
.index = 0,
};
}

/// Returns whether or not a character is whitelisted
fn inWhitelist(char: u8, whitelist: []const u8) bool {
var i: usize = 0;
Expand Down Expand Up @@ -609,7 +629,6 @@ pub const String = struct {

/// Checks if the needle String is within the source String
pub fn includesString(self: *String, needle: String) bool {

if (self.size == 0 or needle.size == 0) return false;

if (self.buffer) |buffer| {
Expand All @@ -627,7 +646,6 @@ pub const String = struct {

/// Checks if the needle literal is within the source String
pub fn includesLiteral(self: *String, needle: []const u8) bool {

if (self.size == 0 or needle.len == 0) return false;

if (self.buffer) |buffer| {
Expand Down