pythonic malloc

K

kjockey

I have some simple UDP code that does:
s.sendto("\xf0\x00\x02\x00rachel\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",addr)

This is OK, except that I'd like to change the text in the middle ("rachel",
which is the hostname FWIW), and the NUL padding needs to go out to make
the length 25 bytes (so the padding depends on the length of the name).

So I could do something like:
retpacket = "\xf0\x00\x02\x00"+socket.gethostname()
while len(retpacket) < 26:
retpacket += "\x00"
s.sendto(retpacket, addr)

But that feels "wrong". And Python in a Nutshell says its a bad idea -
"anti-idiom".

Can anyone show me the true path?

Brad
 
K

Karl Scalet

kjockey said:
I have some simple UDP code that does:
s.sendto("\xf0\x00\x02\x00rachel\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",addr)

This is OK, except that I'd like to change the text in the middle ("rachel",
which is the hostname FWIW), and the NUL padding needs to go out to make
the length 25 bytes (so the padding depends on the length of the name).

So I could do something like:
retpacket = "\xf0\x00\x02\x00"+socket.gethostname()
while len(retpacket) < 26:

shouldn't that be 25?
retpacket += "\x00"
s.sendto(retpacket, addr)

But that feels "wrong". And Python in a Nutshell says its a bad idea -
"anti-idiom".

Can anyone show me the true path?

No idea, if it's the true path:

hn = socket.gethostname()
retpacket = '\xf0\x00\x02\x00%s%s' % (hn, (25-4-len(hn))*chr(0))
s.sendto(retpacket, addr)

Karl
 
B

Brad Hards

Karl said:
shouldn't that be 25? Yes.


No idea, if it's the true path:

hn = socket.gethostname()
retpacket = '\xf0\x00\x02\x00%s%s' % (hn, (25-4-len(hn))*chr(0))
s.sendto(retpacket, addr)
Probably better for efficiency, but not much for readability....

Anyone else?
 
B

Bengt Richter

Well, adding the same character one by one is about as ugly as
sum = 14
while sum <25:
sum += 1
(Of course, if the original 14 units are also the same, as in integers,
sum += 25-sum
is not much better ;-)

But for small strings, I don't think it should be a big deal to do something like

retpacket = "\xf0\x00\x02\x00"+socket.gethostname()
retpacket += '\x00'*(25-len(retpacket))

Probably better for efficiency, but not much for readability....

Anyone else?

another alternative (untested!):

fmt = '\xf0\x00\x02\x00%s'+21*'\x00' # or write it out ;-)
...
retpacket = (fmt%socket.gethostname())[:25]
s.sendto(retpacket, addr)

Regards,
Bengt Richter
 
E

eichin

I was going to suggest struct.pack:
'\xf0\x00\x02\x00rachel\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

but it is, umm, "kind of perlish" - note also that the "21s" is
basically "string of up to 21 chars, pad with NUL if we run out" which
is probably what you wanted, but is saying it another way.

Another approach is the overpad and truncate:

msglen = 25
header = struct.pack("<HH", 0xf0, 2)
msg = header + "rachel" + "\0" * msglen
s.sendto(msg[0:msglen], addr)

ie. you know there will never be more than 25 bytes of pad (really,
more than 21, but "eww, literal numbers" presumably in your real code
you have some name attached to either the field length (which is
sufficient) in stead of the message length I've used here.)
 
B

Brad Hards

'\xf0\x00\x02\x00rachel\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

but it is, umm, "kind of perlish" - note also that the "21s" is
basically "string of up to 21 chars, pad with NUL if we run out" which
is probably what you wanted, but is saying it another way.
This is nice, because it also deals with the case where the hostname would
otherwise overflow. It also matches my mental model - this isn't really a
string, its really a fixed length binary structure. Note that I don't
really know what it is - I'm trying to figure out a proprietary network
protocol.

Now I just have a question about portability. Will this break on a
big-endian box? That is, does:
struct.pack("<HH", 0xf0, 0x02)
produce:
'\x00\xf0\x00\x02'?

Would I be better off using "BBBB 21s" or "L 21s" as the format?

Brad
 
E

eichin

Now I just have a question about portability. Will this break on a
big-endian box? That is, does:

read struct.__doc__, it explains about endianness in detail (in
particular, that's what the "<" at the beginning is all about.)
 
B

Brad Hards

read struct.__doc__, it explains about endianness in detail (in
particular, that's what the "<" at the beginning is all about.)
Thankyou for your patience. Now that you mention it, I do remember reading
about that in the past, but I guess I'm more rusty than I thought.

Brad
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top