123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- -- 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
|