blob: 92965ee54d56490d3ac7c9b5e410e79db4be7cff (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
-- Basic shim for LuaJIT's stringbuffer.
-- Note this does not implement the full API.
-- This is intentionally internal-only. If we want to expose it, we should
-- reimplement this a userdata and ship it as `string.buffer`
-- (minus the FFI stuff) for Lua 5.1.
local M = {}
local has_strbuffer, strbuffer = pcall(require, 'string.buffer')
if has_strbuffer then
M.new = strbuffer.new
-- Lua 5.1 does not have __len metamethod so we need to provide a len()
-- function to use instead.
--- @param buf vim._stringbuffer
--- @return integer
function M.len(buf)
return #buf
end
return M
end
--- @class vim._stringbuffer
--- @field private buf string[]
--- @field package len integer absolute length of the `buf`
--- @field package skip_ptr integer
local StrBuffer = {}
StrBuffer.__index = StrBuffer
--- @return string
function StrBuffer:tostring()
if #self.buf > 1 then
self.buf = { table.concat(self.buf) }
end
-- assert(self.len == #(self.buf[1] or ''), 'len mismatch')
if self.skip_ptr > 0 then
if self.buf[1] then
self.buf[1] = self.buf[1]:sub(self.skip_ptr + 1)
self.len = self.len - self.skip_ptr
end
self.skip_ptr = 0
end
-- assert(self.len == #(self.buf[1] or ''), 'len mismatch')
return self.buf[1] or ''
end
StrBuffer.__tostring = StrBuffer.tostring
--- @private
--- Efficiently peak at the first `n` characters of the buffer.
--- @param n integer
--- @return string
function StrBuffer:_peak(n)
local skip, buf1 = self.skip_ptr, self.buf[1]
if buf1 and (n + skip) < #buf1 then
return buf1:sub(skip + 1, skip + n)
end
return self:tostring():sub(1, n)
end
--- @param chunk string
function StrBuffer:put(chunk)
local s = tostring(chunk)
self.buf[#self.buf + 1] = s
self.len = self.len + #s
return self
end
--- @param str string
function StrBuffer:set(str)
return self:reset():put(str)
end
--- @param n integer
--- @return string
function StrBuffer:get(n)
local r = self:_peak(n)
self:skip(n)
return r
end
--- @param n integer
function StrBuffer:skip(n)
self.skip_ptr = math.min(self.len, self.skip_ptr + n)
return self
end
function StrBuffer:reset()
self.buf = {}
self.skip_ptr = 0
self.len = 0
return self
end
function M.new()
return setmetatable({}, StrBuffer):reset()
end
--- @param buf vim._stringbuffer
function M.len(buf)
return buf.len - buf.skip_ptr
end
return M
|