lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



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