From 6390977a3efffd4670a7206842f29edfba613077 Mon Sep 17 00:00:00 2001 From: DISTREAT <99132213+DISTREAT@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:23:09 +0100 Subject: [PATCH 1/2] feat!: upgrade to zig 0.15.2 --- README.md | 25 ++++++++++++---- build.zig | 19 +++++++++--- build.zig.zon | 4 +-- src/{zig-csv.zig => root.zig} | 56 +++++++++++++++++------------------ src/tests.zig | 2 +- 5 files changed, 66 insertions(+), 40 deletions(-) rename src/{zig-csv.zig => root.zig} (86%) diff --git a/README.md b/README.md index 780a2bb..da6cb36 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,27 @@ The design of this library is guided by the principles outlined in the [CSV Pars which emphasizes data integrity, fail-fast behavior, and low-level access to parsed data. This design approach ensures the library is compatible with real-world CSV data while avoiding ambiguity in parsing. +## Installation + +First, add the dependency to your `build.zig.zon`: + +```sh +zig fetch --save git+https://github.com/DISTREAT/zig-csv +``` + +Then, add the package to your `build.zig`: + +```zig +const zig_csv = b.dependency("zig_csv", .{}); +exe.root_module.addImport("zig_csv", zig_csv.module("zig_csv")); +``` + ## Usage ```zig const std = @import("std"); -const csv = @import("zig-csv"); -const allocator = std.heap.allocator; +const csv = @import("zig_csv"); +const allocator = std.heap.page_allocator; // Parse CSV data var table = csv.Table.init(allocator, csv.Settings.default()); @@ -33,9 +48,9 @@ try table.parse( ); // Change the color of the dog to "white" -const animal_col = try table.findColumnIndexesByValue(allocator, 0, "animal")[0]; -const dog_row = try table.findRowIndexesByValue(allocator, animal_col, "dog")[0]; -const color_col = try table.findColumnIndexesByValue(allocator, 0, "color")[0]; +const animal_col = (try table.findColumnIndexesByValue(allocator, 0, "animal"))[0]; +const dog_row = (try table.findRowIndexesByValue(allocator, animal_col, "dog"))[0]; +const color_col = (try table.findColumnIndexesByValue(allocator, 0, "color"))[0]; try table.replaceValue(dog_row, color_col, "white"); // Add a new animal diff --git a/build.zig b/build.zig index 5bbd09a..79fbe97 100644 --- a/build.zig +++ b/build.zig @@ -4,13 +4,24 @@ pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const mode = b.standardOptimizeOption(.{}); - const lib = b.addStaticLibrary(.{ - .name = "zig-cvs", - .root_source_file = b.path("src/zig-csv.zig"), + const module_root = b.addModule("zig_csv", .{ + .root_source_file = b.path("src/root.zig"), .optimize = mode, .target = target, }); - const lib_tests = b.addTest(.{ .root_source_file = b.path("src/tests.zig") }); + const lib = b.addLibrary(.{ + .name = "zig_csv", + .linkage = .static, + .root_module = module_root, + }); + const module_tests = b.addModule("tests", .{ + .root_source_file = b.path("src/tests.zig"), + .optimize = mode, + .target = target, + }); + const lib_tests = b.addTest(.{ + .root_module = module_tests, + }); const install_docs = b.addInstallDirectory(.{ .source_dir = lib.getEmittedDocs(), diff --git a/build.zig.zon b/build.zig.zon index f95a794..2abc3e3 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,8 +1,8 @@ .{ .name = .zig_csv, - .version = "1.1.0", + .version = "1.2.0", .fingerprint = 0xb5163165a35b825b, - .minimum_zig_version = "0.14.0", + .minimum_zig_version = "0.15.2", .dependencies = .{}, .paths = .{ "build.zig", diff --git a/src/zig-csv.zig b/src/root.zig similarity index 86% rename from src/zig-csv.zig rename to src/root.zig index 8993f07..8c4c933 100644 --- a/src/zig-csv.zig +++ b/src/root.zig @@ -57,16 +57,16 @@ pub const Table = struct { .settings = settings, .allocator = allocator, .expected_column_count = null, - .data = ArrayList(ArrayList([]const u8)).init(allocator), + .data = .empty, }; } /// Deinitializes the internal arena allocator and parsed data pub fn deinit(self: *Table) void { - for (self.data.items) |row| { - row.deinit(); + for (self.data.items) |*row| { + row.deinit(self.allocator); } - self.data.deinit(); + self.data.deinit(self.allocator); } /// Load and append CSV data to the struct Table @@ -87,12 +87,12 @@ pub const Table = struct { /// /// Returns the number of values parsed in the row. fn parseRow(self: *Table, row: []const u8) TableError!usize { - var values = ArrayList([]const u8).init(self.allocator); + var values: ArrayList([]const u8) = .empty; var columns = std.mem.splitSequence(u8, row, self.settings.delimiter); while (columns.next()) |value| { - try values.append(value); + try values.append(self.allocator, value); } - try self.data.append(values); + try self.data.append(self.allocator, values); return values.items.len; } @@ -127,17 +127,17 @@ pub const Table = struct { /// ``` pub fn findColumnIndexesByValue(self: Table, allocator: Allocator, row_index: usize, searched_value: []const u8) TableError![]usize { if (self.data.items.len < row_index) return TableError.RowNotFound; - var column_indexes = ArrayList(usize).init(allocator); + var column_indexes: ArrayList(usize) = .empty; for (self.data.items[row_index].items, 0..) |column_value, column_index| { if (std.mem.eql(u8, column_value, searched_value)) { - try column_indexes.append(column_index); + try column_indexes.append(allocator, column_index); } } if (column_indexes.items.len <= 0) { - column_indexes.deinit(); + column_indexes.deinit(allocator); return TableError.ValueNotFound; } - return column_indexes.toOwnedSlice(); + return column_indexes.toOwnedSlice(allocator); } /// Returns all row indexes that match a given value in a specific column @@ -160,27 +160,27 @@ pub const Table = struct { /// ``` pub fn findRowIndexesByValue(self: Table, allocator: Allocator, column_index: usize, searched_value: []const u8) TableError![]usize { if (column_index >= self.expected_column_count orelse 0) return TableError.ColumnNotFound; - var row_indexes = ArrayList(usize).init(allocator); + var row_indexes: ArrayList(usize) = .empty; for (self.data.items, 0..) |row, row_index| { if (std.mem.eql(u8, row.items[column_index], searched_value)) { - try row_indexes.append(row_index); + try row_indexes.append(allocator, row_index); } } if (row_indexes.items.len <= 0) { - row_indexes.deinit(); + row_indexes.deinit(allocator); return TableError.ValueNotFound; } - return row_indexes.toOwnedSlice(); + return row_indexes.toOwnedSlice(allocator); } /// Return the column at the provided index as a slice of values pub fn getColumnByIndex(self: Table, allocator: Allocator, column_index: usize) TableError![]const []const u8 { if (column_index > self.expected_column_count orelse 0) return TableError.ColumnNotFound; - var column_values = ArrayList([]const u8).init(allocator); + var column_values: ArrayList([]const u8) = .empty; for (self.data.items) |row| { - try column_values.append(row.items[column_index]); + try column_values.append(allocator, row.items[column_index]); } - return column_values.toOwnedSlice(); + return column_values.toOwnedSlice(allocator); } /// Return the row at the provided index as a slice of values @@ -199,9 +199,9 @@ pub const Table = struct { const target_index = row_index orelse self.data.items.len; if (self.expected_column_count == null) return TableError.NoData; if (target_index > self.data.items.len) return TableError.RowNotFound; - var empty_row = ArrayList([]const u8).init(self.allocator); - for (0..self.expected_column_count orelse unreachable) |_| try empty_row.append(""); - try self.data.insert(target_index, empty_row); + var empty_row: ArrayList([]const u8) = .empty; + for (0..self.expected_column_count orelse unreachable) |_| try empty_row.append(self.allocator, ""); + try self.data.insert(self.allocator, target_index, empty_row); return target_index; } @@ -215,7 +215,7 @@ pub const Table = struct { const target_index = column_index orelse self.expected_column_count orelse return TableError.NoData; if (target_index > self.expected_column_count orelse unreachable) return TableError.ColumnNotFound; for (self.data.items) |*row| { - try row.insert(target_index, ""); + try row.insert(self.allocator, target_index, ""); } self.expected_column_count = (self.expected_column_count orelse unreachable) + 1; return target_index; @@ -247,24 +247,24 @@ pub const Table = struct { /// All prior row indexes will be invalidated. pub fn deleteRowByIndex(self: *Table, row_index: usize) TableError!void { if (row_index >= self.data.items.len) return TableError.RowNotFound; - self.data.items[row_index].deinit(); + self.data.items[row_index].deinit(self.allocator); _ = self.data.orderedRemove(row_index); } /// Returns a slice of bytes containing the CSV data stored in the struct Table. pub fn exportCSV(self: *Table, allocator: Allocator) TableError![]const u8 { - var csv = ArrayList(u8).init(allocator); + var csv: ArrayList(u8) = .empty; for (self.data.items, 0..) |row, row_index| { if (row_index > 0) { - try csv.appendSlice(self.settings.terminator); + try csv.appendSlice(allocator, self.settings.terminator); } for (row.items, 0..) |column, column_index| { if (column_index > 0) { - try csv.appendSlice(self.settings.delimiter); + try csv.appendSlice(allocator, self.settings.delimiter); } - try csv.appendSlice(column); + try csv.appendSlice(allocator, column); } } - return csv.toOwnedSlice(); + return csv.toOwnedSlice(allocator); } }; diff --git a/src/tests.zig b/src/tests.zig index f267b82..e6af172 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -1,7 +1,7 @@ //! Unit and Integration tests for the module scope `src/*.zig` //! [Released under GNU LGPLv3] const std = @import("std"); -const csv = @import("zig-csv.zig"); +const csv = @import("root.zig"); const expect = std.testing.expect; const allocator = std.testing.allocator; From 60705953e8f5beb9e7765bcc37e7d0d8bb73e53a Mon Sep 17 00:00:00 2001 From: DISTREAT <99132213+DISTREAT@users.noreply.github.com> Date: Thu, 15 Jan 2026 23:08:17 +0100 Subject: [PATCH 2/2] ci: update to zig 0.15.2 --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ce1d924..b486171 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@v4 - uses: mlugg/setup-zig@v2 with: - version: 0.14.1 + version: 0.15.2 - run: zig build test lint: runs-on: ubuntu-latest @@ -19,5 +19,5 @@ jobs: - uses: actions/checkout@v4 - uses: mlugg/setup-zig@v2 with: - version: 0.14.1 + version: 0.15.2 - run: zig fmt --check .