forked from rjpcomputing/luaforwindows
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathread.lua
More file actions
executable file
·130 lines (110 loc) · 2.94 KB
/
read.lua
File metadata and controls
executable file
·130 lines (110 loc) · 2.94 KB
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
-- read formats
-- return a value if applicable, which will be packed
-- otherwise return nil
-- Copyright © 2008 Ben "ToxicFrog" Kelly; see COPYING
-- load operations common to both read and write, and set __index so that
-- requests for, say, read.seekto will succeed
local name = (...):gsub('%.[^%.]+$', '')
local struct = require (name)
local common = require (name..".common")
local read = setmetatable({}, { __index = common })
local fp = require (name..".fp")
-- boolean
-- true if any bit is 1, false otherwise
function read.b(fd, w)
return read.u(fd, w) ~= 0
end
-- counted string
-- a string immediately prefaced with its length as a uint
function read.c(fd, w)
w = read.u(fd, w)
return read.s(fd, w)
end
-- float
-- this is callout to the floating-point read/write module, if installed
function read.f(fd, w)
if not fp.r[w] then
error("struct.unpack: illegal floating point width")
end
return fp.r[w](read.s(fd,w))
end
-- signed int of w bytes
function read.i(fd, w)
local i = read.u(fd, w)
if i >= 2^(w*8 - 1) then
return i - 2^(w*8)
end
return i
end
-- bitmask of w bytes
-- we need to read and unpack it as a string, not an unsigned, because otherwise
-- we're limited to 52 bits
function read.m(fd, w)
local buf = read.s(fd, w)
local mask = {}
local sof = (read.is_bigendian and w or 1)
local eof = (read.is_bigendian and 1 or w)
local dir = (read.is_bigendian and -1 or 1)
for i=sof,eof,dir do
local byte = buf:sub(i,i):byte()
local bits = struct.explode(byte)
for i=1,8 do
mask[#mask+1] = bits[i] or false
end
end
return mask
end
-- fixed point bit aligned
-- w is in the form d.f, where d is the number of bits in the integer part
-- and f the number of bits in the fractional part
function read.P(fd, dp, fp)
if (dp+fp) % 8 ~= 0 then
error "total width of fixed point value must be byte multiple"
end
return read.u(fd, (dp+fp)/8)/(2^fp)
end
-- fixed point byte aligned
function read.p(fd, dp, fp)
return read.P(fd, dp*8, fp*8)
end
-- string
-- reads exactly w bytes of data and returns them verbatim
function read.s(fd, w)
return fd:read(w or 0)
end
-- unsigned int
function read.u(fd, w)
local u = 0
local s = read.s(fd, w)
-- the "is_bigendian" setting is provided by struct.common
local sof = (read.is_bigendian and 1 or w)
local eof = (read.is_bigendian and w or 1)
local dir = (read.is_bigendian and 1 or -1)
for i=sof,eof,dir do
u = u * 2^8 + s:sub(i,i):byte()
end
return u
end
-- skip/pad
-- reads w bytes and discards them
function read.x(fd, w)
fd:read(w)
return nil
end
-- null-terminated string
-- if w is omitted, reads up to and including the first nul, and returns everything
-- except that nul
-- otherwise, reads exactly w bytes and returns everything up to the first nul
function read.z(fd, w)
if w then
return read.s(fd, w):match('^%Z*')
end
local buf = ""
local c = read.s(fd, 1)
while #c > 0 and c ~= string.char(0) do
buf = buf..c
c = read.s(fd, 1)
end
return buf
end
return read