lua-users home
lua-l archive

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



It was thus said that the Great Sean Conner <sean@conman.org>  once stated:

It was thus said that the Great tobias@justdreams.de once stated:

I'm designing a library which has a Buffer module that allows to
contain binary data.  Think of it as a string just with less features
:-P

  There was a heated discussion about this back in 2014:

	http://lua-users.org/lists/lua-l/2014-08/msg00819.html

I wrote test code (it's still available) to test that a buffer userdata
would be faster than Lua immutable strings.  Immutable strings were faster,
but like I said, I could have done something wrong.

I don't think there is a 'right' answer, but to all those people who
work with this kind of stuff, what would feel more natural to you?
Also, does Segment( offset, length ) makes more sense than Segment(
length, offset ) ?

  When I work with this kind of data, I either pass it to C for parsing (Lua
5.1), use string.unpack() (Lua 5.3) or LPeg, depending upon the type of
data.  For building data, it's either string concatenation, C (binary
packets under Lua 5.1) or string.pack() (Lua 5.3).

  -spc (Coroutines never did get back to me about my code ... )

I never tested it myself, so thanks for the code!

The main reason why I have a buffer module is not just for mutable network
buffers.  I do have a binary packer/parser that works on Buffer,Segments and
Lua strings alike, however, when you pass it a buffer it can do simple writes
which makes it really convenient:

Pack   = require( "t.Pack" )
Buffer = require( "t.Buffer" )

-- this uses the same identifiers as string.pack
-- `r` is a signed bit-sized integer, `R` is un-signed, `v` is 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' ) }
   , { tail       = '>I5<I4h' }
)

s = 'AbCdEfGhIjKlMnOpQrStVwxy'

-- 'execution' of a packer allows for read or write operations
print( p.bits[3][4]( s ) )
-3
for i,v in pairs( p.bits[3] ) do print( i, v(s) ) end
1       2
2       2
3       -2
4       -3
5       1
6       1
7       3
8       3
-- fails, because s is immutable
p.bits[3][4]( s, 2 )
stdin:1: bad argument #2 to '?' (Can't write value to string type)
stack traceback:
        [C]: in field '?'
        stdin:1: in main chunk
        [C]: in ?

sz = Pack.getSize( p )  -- size in bytes, #p gets the number of elements
b = Buffer( sz )
b:toHex()
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-- buffers are mutable
p.bits[3][4]( b, 2 )
p.bits[6]( b, true )
b:toHex( )
00 00 00 00 00 00 00 00 00 04 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00