[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: [PROPOSAL 5.4] alternate way of format/pack/unpack (in the string library)
- From: tobias@...
- Date: Fri, 26 May 2017 22:50:36 +0200
Quoting 云风 <cloudwu@gmail.com>:
发自我的 iPhone
在 2017年5月26日,下午11:32,François Perrad <francois.perrad@gadz.org> 写道:
pack/unpack are introduced only since Lua 5.3, so, I think they
could be deprecated in Lua 5.4.
string.pack/unpack are the best feature introduced by lua 5.3
(IMHO), and I don't think any jit technology can do better.
Minilanguage is the key for high cohesion , that is why people
prefer printf than iostream.
Hi there,
as part of a library I'm working on I have developed a different type of
pack/unpack mechanism which basically does some pre-compilation of sort but
most importatntly allows for much more expressive way of writing this stuff.
I think this makes a compelling case for Luiz' argument of putting things
into separate libraries.
Please not this is from lua-t which is under heavy development. So it's a
very moving target. Also C-strings pascal strings and alignmentare not yet
handled :-)
https://github.com/tobbik/lua-t
Example:
Pack = require't.Pack'
i = Pack('>I6') -- Single packer instance
i
t.Pack.UInt6B: 0xd73f1e8
p = Pack('>I3<i2bB>I5<I4h') -- Packer sequence instance
p
t.Pack.Sequence[7]: 0xd73eb08
b = 'aBcDeüHiJkLmNoPö'
#p -- Packer behaves like a table
7
p[3] -- Access to single packers
t.Pack.Field[5](Int1L): 0xd74b238 -- Filed with offset of 5 bytes from
-- start, 1 byte long
p[3](b) -- Reading from a string is done by __call
-61
x = p(b) -- create a table with results
for i=1,#p do print(p[i], x[i] ) end
t.Pack.Field[0](UInt3B): 0xd749868 6373987
t.Pack.Field[3](Int2L): 0xd749048 25924
t.Pack.Field[5](Int1L): 0xd7491b8 -61
t.Pack.Field[6](UInt1L): 0xd7492e8 188
t.Pack.Field[7](UInt5B): 0xd748bc8 311004130124
t.Pack.Field[12](UInt4L): 0xd748d68 1349471853
t.Pack.Field[16](Int2L): 0xd748648 -18749
There are some more convieniences, you can have named fields, you can have
nested structures, arrays of packers and you can have bit sized resolution
(using 'r' and 'R' as format strings or 'v' for single bit boolean):
p = Pack(
{ threeUInt = '>I3' }
, { twoIntegs = '<i2' }
, { twoBytes = Pack(
{ signedByte = 'b' }
, { unsignByte = 'B' }
) }
, { bits = Pack( 'r4','R7',Pack( 'r3', 8
),'r15','v','v','R1','R1','r1','r1' ) }
, { fiveSInt = '>I5' }
, { fourSInt = '<I4' }
, { signShort = 'h' }
)
p.bits[3][4]
t.Pack.Field[9](SBit3:0): 0xd73f5b8 -- signed bit, 3 bits wide, 9 byte offset
Additionally, if you use a t.Buffer instance, provided in the same library,
you can write to a partial section of it without recreating strings over and
over again (think crude but mutable strings):
Buffer = require't.Buffer'
b = Buffer( string.rep( string.char( 0xFF ), 25 ) )
b
T.Buffer[25]: 0xd72d1b8
b:toHex()
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
p.bits[2](b,0) -- overwriting the bits in 'R7' with 0
b:toHex()
FF FF FF FF FF FF FF F0 1F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF