# HG changeset patch # User Matthew Wild # Date 1624970894 -3600 # Node ID 11e0a0a08da3b3db6e3500eec12b0621208d862f # Parent 1b17b967838e24806180f5a6cd087f98b81cb47c util.dbuffer: Add read_until() method diff -r 1b17b967838e -r 11e0a0a08da3 spec/util_dbuffer_spec.lua --- a/spec/util_dbuffer_spec.lua Thu May 27 13:09:18 2021 +0200 +++ b/spec/util_dbuffer_spec.lua Tue Jun 29 13:48:14 2021 +0100 @@ -36,6 +36,50 @@ end); end); + describe(":read_until", function () + it("works", function () + local b = dbuffer.new(); + b:write("hello\n"); + b:write("world"); + b:write("\n"); + b:write("\n\n"); + b:write("stuff"); + b:write("more\nand more"); + + assert.equal(nil, b:read_until(".")); + assert.equal(nil, b:read_until("%")); + assert.equal("hello\n", b:read_until("\n")); + assert.equal("world\n", b:read_until("\n")); + assert.equal("\n", b:read_until("\n")); + assert.equal("\n", b:read_until("\n")); + assert.equal("stu", b:read(3)); + assert.equal("ffmore\n", b:read_until("\n")); + assert.equal(nil, b:read_until("\n")); + assert.equal("and more", b:read_chunk()); + end); + + it("works with multi-character sequences", function () + local b = dbuffer.new(); + b:write("hello\r\n"); + b:write("world"); + b:write("\r\n"); + b:write("\r\n\r\n"); + b:write("stuff"); + b:write("more\r\nand more"); + + assert.equal(nil, b:read_until(".")); + assert.equal(nil, b:read_until("%")); + assert.equal("hello\r\n", b:read_until("\r\n")); + assert.equal("world\r\n", b:read_until("\r\n")); + assert.equal("\r\n", b:read_until("\r\n")); + assert.equal("\r\n", b:read_until("\r\n")); + assert.equal("stu", b:read(3)); + assert.equal("ffmore\r\n", b:read_until("\r\n")); + assert.equal(nil, b:read_until("\r\n")); + assert.equal("and more", b:read_chunk()); + end); + end); + describe(":discard", function () local b = dbuffer.new(); it("works", function () diff -r 1b17b967838e -r 11e0a0a08da3 util/dbuffer.lua --- a/util/dbuffer.lua Thu May 27 13:09:18 2021 +0200 +++ b/util/dbuffer.lua Tue Jun 29 13:48:14 2021 +0100 @@ -76,6 +76,20 @@ return table.concat(chunks); end +-- Read to, and including, the specified character sequence (return nil if not found) +function dbuffer_methods:read_until(char) + local buffer_pos = 0; + for i, chunk in self.items:items() do + local start = 1 + self.front_consumed; + local char_pos = chunk:find(char, start, true); + if char_pos then + return self:read(buffer_pos + (char_pos - start) + #char); + end + buffer_pos = buffer_pos + #chunk; + end + return nil; +end + function dbuffer_methods:discard(requested_bytes) if requested_bytes > self._length then return nil;