util/dbuffer.lua
branch0.11
changeset 11193 0ff148362a3d
parent 11160 a8ef69f7fc35
child 11194 88ce53df44a9
--- a/util/dbuffer.lua	Fri Oct 16 13:38:04 2020 +0100
+++ b/util/dbuffer.lua	Wed Oct 28 14:21:09 2020 +0000
@@ -1,5 +1,6 @@
 local queue = require "util.queue";
 
+local s_byte, s_sub = string.byte, string.sub;
 local dbuffer_methods = {};
 local dynamic_buffer_mt = { __index = dbuffer_methods };
 
@@ -101,7 +102,11 @@
 	return true;
 end
 
-function dbuffer_methods:sub(i, j)
+-- Normalize i, j into absolute offsets within the
+-- front chunk (accounting for front_consumed), and
+-- ensure there is enough data in the first chunk
+-- to cover any subsequent :sub() or :byte() operation
+function dbuffer_methods:_prep_sub(i, j)
 	if j == nil then
 		j = -1;
 	end
@@ -118,18 +123,35 @@
 		j = self._length;
 	end
 	if i > j then
-		return "";
+		return nil;
 	end
 
 	self:collapse(j);
 
-	return self.items:peek():sub(self.front_consumed+1):sub(i, j);
+	if self.front_consumed > 0 then
+		i = i + self.front_consumed;
+		j = j + self.front_consumed;
+	end
+
+	return i, j;
+end
+
+function dbuffer_methods:sub(i, j)
+	i, j = self:_prep_sub(i, j);
+	if not i then
+		return "";
+	end
+	return s_sub(self.items:peek(), i, j);
 end
 
 function dbuffer_methods:byte(i, j)
 	i = i or 1;
 	j = j or i;
-	return string.byte(self:sub(i, j), 1, -1);
+	i, j = self:_prep_sub(i, j);
+	if not i then
+		return;
+	end
+	return s_byte(self.items:peek(), i, j);
 end
 
 function dbuffer_methods:length()