/usr/share/lua/5.1/pl/stringio.lua is in lua-penlight 1.2.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156  | --- Reading and writing strings using file-like objects. <br>
--
--    f = stringio.open(text)
--    l1 = f:read()  -- read first line
--    n,m = f:read ('*n','*n') -- read two numbers
--    for line in f:lines() do print(line) end -- iterate over all lines
--    f = stringio.create()
--    f:write('hello')
--    f:write('dolly')
--    assert(f:value(),'hellodolly')
--
-- See  @{03-strings.md.File_style_I_O_on_Strings|the Guide}.
-- @module pl.stringio
local unpack = rawget(_G,'unpack') or rawget(table,'unpack')
local getmetatable,tostring,unpack,tonumber = getmetatable,tostring,unpack,tonumber
local concat,append = table.concat,table.insert
local stringio = {}
-- Writer class
local SW = {}
SW.__index = SW
local function xwrite(self,...)
    local args = {...} --arguments may not be nil!
    for i = 1, #args do
        append(self.tbl,args[i])
    end
end
function SW:write(arg1,arg2,...)
    if arg2 then
        xwrite(self,arg1,arg2,...)
    else
        append(self.tbl,arg1)
    end
end
function SW:writef(fmt,...)
    self:write(fmt:format(...))
end
function SW:value()
    return concat(self.tbl)
end
function SW:__tostring()
    return self:value()
end
function SW:close() -- for compatibility only
end
function SW:seek()
end
-- Reader class
local SR = {}
SR.__index = SR
function SR:_read(fmt)
    local i,str = self.i,self.str
    local sz = #str
    if i > sz then return nil end
    local res
    if fmt == '*l' or fmt == '*L' then
        local idx = str:find('\n',i) or (sz+1)
        res = str:sub(i,fmt == '*l' and idx-1 or idx)
        self.i = idx+1
    elseif fmt == '*a' then
        res = str:sub(i)
        self.i = sz
    elseif fmt == '*n' then
        local _,i2,i2,idx
        _,idx = str:find ('%s*%d+',i)
        _,i2 = str:find ('^%.%d+',idx+1)
        if i2 then idx = i2 end
        _,i2 = str:find ('^[eE][%+%-]*%d+',idx+1)
        if i2 then idx = i2 end
        local val = str:sub(i,idx)
        res = tonumber(val)
        self.i = idx+1
    elseif type(fmt) == 'number' then
        res = str:sub(i,i+fmt-1)
        self.i = i + fmt
    else
        error("bad read format",2)
    end
    return res
end
function SR:read(...)
    if select('#',...) == 0 then
        return self:_read('*l')
    else
        local res, fmts = {},{...}
        for i = 1, #fmts do
            res[i] = self:_read(fmts[i])
        end
        return unpack(res)
    end
end
function SR:seek(whence,offset)
    local base
    whence = whence or 'cur'
    offset = offset or 0
    if whence == 'set' then
        base = 1
    elseif whence == 'cur' then
        base = self.i
    elseif whence == 'end' then
        base = #self.str
    end
    self.i = base + offset
    return self.i
end
function SR:lines(...)
    local n, args = select('#',...)
    if n > 0 then
        args = {...}
    end
    return function()
        if n == 0 then
            return self:_read '*l'
        else
            return self:read(unpack(args))
        end
    end
end
function SR:close() -- for compatibility only
end
--- create a file-like object which can be used to construct a string.
-- The resulting object has an extra <code>value()</code> method for
-- retrieving the string value.
-- @usage f = create(); f:write('hello, dolly\n'); print(f:value())
function stringio.create()
    return setmetatable({tbl={}},SW)
end
--- create a file-like object for reading from a given string.
-- @param s The input string.
function stringio.open(s)
    return setmetatable({str=s,i=1},SR)
end
function stringio.lines(s,...)
    return stringio.open(s):lines(...)
end
return stringio
 |