Skip to content

Commit cef0a4f

Browse files
committed
Add support for lua.gsub()
1 parent 951e44a commit cef0a4f

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ you.
8686
| API | Support |
8787
|-----------------------------|---------------------------------------|
8888
| Lua C API (`lua_*`) | 🎉 100% coverage<sup>†</sup> (92/92) |
89-
| Auxilary Library (`luaL_*`) | 52% coverage (26/48) |
89+
| Auxilary Library (`luaL_*`) | 54% coverage (27/48) |
9090
| LuaJIT Extensions | *No plans to implement.* |
9191

9292
*†: Coroutine yield/resume is not yet part of the public `zig-luajit` Zig API, see [#6][ISSUE-6].*
@@ -248,7 +248,7 @@ The `zig-luajit` project has not yet reached the 1.0 release, the API is subject
248248
| `luaL_error` | ☑️📢 `lua.raiseErrorFormat()` |
249249
| `luaL_getmetafield` ||
250250
| `luaL_getmetatable` ||
251-
| `luaL_gsub` ||
251+
| `luaL_gsub` | ☑️ `lua.gsub()` |
252252
| `luaL_loadbuffer` ||
253253
| `luaL_loadfile` ||
254254
| `luaL_loadstring` ||

src/lual_api.zig

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,6 @@ pub fn getMetaField(lua: *Lua, obj: i32, e: [:0]const u8) i32;
106106
/// Stack Behavior: `[-0, +1, -]`
107107
pub fn getMetatable(lua: *Lua, name: [*:0]const u8) void;
108108

109-
/// Creates a copy of string s by replacing any occurrence of the string p with the string r.
110-
/// Pushes the resulting string on the stack and returns it.
111-
///
112-
/// From: `const char *luaL_gsub(lua_State *L, const char *s, const char *p, const char *r);`
113-
/// Refer to: https://www.lua.org/manual/5.1/manual.html#luaL_gsub
114-
/// Stack Behavior: `[-0, +1, m]`
115-
pub fn gSub(lua: *Lua, s: []const u8, p: []const u8, r: []const u8) []const u8;
116-
117109
/// Loads a buffer as a Lua chunk using lua_load to load the chunk in the buffer pointed to by buff with size sz.
118110
/// Returns the same results as lua_load. The name parameter is used for debug information and error messages.
119111
///

src/root.zig

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,6 +2253,34 @@ pub const Lua = opaque {
22532253
@ptrCast(functions.ptr),
22542254
);
22552255
}
2256+
2257+
/// Performs a `[g]lobal [sub]stitution` of content in the given `string` replacing all occurrences of the substring
2258+
/// `pattern` with the content `replacement`.
2259+
///
2260+
/// Pushes the resulting string on the stack and returns it.
2261+
///
2262+
/// From: `const char *luaL_gsub(lua_State *L, const char *s, const char *p, const char *r);`
2263+
/// Refer to: https://www.lua.org/manual/5.1/manual.html#luaL_gsub
2264+
/// Stack Behavior: `[-0, +1, m]`
2265+
pub fn gsub(lua: *Lua, string: [:0]const u8, pattern: [:0]const u8, replacement: [:0]const u8) [:0]const u8 {
2266+
assert(pattern.len > 0); // gsub(string, "", replacement) causes an infinite loop -- avoid using the empty string as a pattern.
2267+
2268+
const str: ?[*:0]const u8 = c.luaL_gsub(asState(lua), @ptrCast(string.ptr), @ptrCast(pattern.ptr), @ptrCast(replacement.ptr));
2269+
if (str) |s| {
2270+
const len = std.mem.indexOfSentinel(u8, 0, s);
2271+
return s[0..len :0];
2272+
} else {
2273+
lua.raiseErrorFormat(
2274+
"gsub('%s', '%s', '%s') returned null instead of the replaced string.",
2275+
.{
2276+
string.ptr,
2277+
pattern.ptr,
2278+
replacement.ptr,
2279+
},
2280+
);
2281+
unreachable;
2282+
}
2283+
}
22562284
};
22572285

22582286
test "Lua can be initialized with an allocator" {
@@ -4225,3 +4253,19 @@ test "suspend and resume coroutines" {
42254253
// TODO: This does not return the expected behavior - I do not think yield and resume work as expected.
42264254
// try std.testing.expectEqual(20, try thread.toIntegerStrict(-1));
42274255
}
4256+
4257+
test "gsub" {
4258+
const lua = try Lua.init(std.testing.allocator);
4259+
defer lua.deinit();
4260+
4261+
const string = "ABBA";
4262+
const pattern = "B";
4263+
const replacement = "C";
4264+
const expected = "ACCA";
4265+
4266+
const actual = lua.gsub(string, pattern, replacement);
4267+
4268+
try std.testing.expectEqual(1, lua.getTop());
4269+
try std.testing.expectEqualStrings(expected, try lua.toLString(-1));
4270+
try std.testing.expectEqualStrings(expected, actual);
4271+
}

0 commit comments

Comments
 (0)