Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > pack a three byte int

Reply
Thread Tools

pack a three byte int

 
 
p.lavarre@ieee.org
Guest
Posts: n/a
 
      11-08-2006
Can Python not express the idea of a three-byte int?

For instance, in the working example below, can we somehow collapse the
three calls of struct.pack into one?

>>> import struct
>>>
>>> skip = 0x123456 ; count = 0x80
>>>
>>> cdb = ''
>>> cdb += struct.pack('>B', 0x0
>>> cdb += struct.pack('>I', skip)[-3:]
>>> cdb += struct.pack('>BB', count, 0)
>>>
>>> print ' '.join(['%02X' % ord(xx) for xx in cdb])

08 12 34 56 80 00
>>>


I ask because I'm trying to refactor working code that is concise:

>>> cdb0 = '\x08' '\x12\x34\x56' '\x80' '\0'
>>> print ' '.join(['%02X' % ord(xx) for xx in cdb0])

08 12 34 56 80 00
>>>


Thanks in advance, Pat LaVarre

 
Reply With Quote
 
 
 
 
John Machin
Guest
Posts: n/a
 
      11-08-2006
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> Can Python not express the idea of a three-byte int?


It is a bit hard to determine what that (rhetorical?) question means.
Possible answers:
1. Not as concisely as a one-byte struct code -- as you presumably have
already determined by reading the manual ...
2. No, but when 24-bit machines become as popular as they were in the
1960s, feel free to submit an enhancement request

>
> For instance, in the working example below, can we somehow collapse the
> three calls of struct.pack into one?
>
> >>> import struct
> >>>
> >>> skip = 0x123456 ; count = 0x80
> >>>
> >>> cdb = ''
> >>> cdb += struct.pack('>B', 0x0
> >>> cdb += struct.pack('>I', skip)[-3:]
> >>> cdb += struct.pack('>BB', count, 0)
> >>>
> >>> print ' '.join(['%02X' % ord(xx) for xx in cdb])

> 08 12 34 56 80 00
> >>>


You could try throwing the superfluous bits away before packing instead
of after:

| >>> from struct import pack
| >>> skip = 0x123456; count = 0x80
| >>> hi, lo = divmod(skip, 0x10000)
| >>> cdb = pack(">BBHBB", 0x08, hi, lo, count, 0)
| >>> ' '.join(["%02X" % ord(x) for x in cdb])
| '08 12 34 56 80 00'

but why do you want to do that to concise working code???

 
Reply With Quote
 
 
 
 
Dave Opstad
Guest
Posts: n/a
 
      11-09-2006
In article <(E-Mail Removed) .com>,
(E-Mail Removed) wrote:

> Can Python not express the idea of a three-byte int?
>
> For instance, in the working example below, can we somehow collapse the
> three calls of struct.pack into one?
>
> >>> import struct
> >>>
> >>> skip = 0x123456 ; count = 0x80
> >>>
> >>> cdb = ''
> >>> cdb += struct.pack('>B', 0x0
> >>> cdb += struct.pack('>I', skip)[-3:]
> >>> cdb += struct.pack('>BB', count, 0)


Why not something like this:

skip += struct.pack(">L", skip)[1:]

Dave
 
Reply With Quote
 
Dave Opstad
Guest
Posts: n/a
 
      11-09-2006
Sorry, that should have been:

cdb += struct.pack(">L", skip)[1:]

Dave
 
Reply With Quote
 
John Machin
Guest
Posts: n/a
 
      11-09-2006

Dave Opstad wrote:
> Sorry, that should have been:
>
> cdb += struct.pack(">L", skip)[1:]
>


">L" and ">I" produce exactly the same 4-byte result. The change from
[-3:] to [1:] is a minor cosmetic improvement, but obscures the
underlying ... a bit like putting mascara on a pig. I got the
impression that the OP was interested in more radical improvement.

Cheers,
John

 
Reply With Quote
 
p.lavarre@ieee.org
Guest
Posts: n/a
 
      11-09-2006
> Not as concisely as a one-byte struct code

Help, what do you mean?

> you presumably... read... the manual ...


Did I reread the wrong parts? I see I could define a ctypes.Structure
since 2.5, but that would be neither concise, nor since 2.3.

> when 24-bit machines become ... popular


Indeed the struct's defined recently, ~1980, were contorted to make
them easy to say in C, which makes them easy to say in Python, e.g.:

X28Read10 = 0x28
cdb = struct.pack('>BBIBHB', X28Read10, 0, skip, 0, count, 0)

But when talking the 1960's lingo I find I am actually resorting to
horrors like:

X12Inquiry = 0x12
xxs = [0] * 6
xxs[0] = X12Inquiry
xxs[4] = allocationLength
rq = ''.join([chr(xx) for xx in xxs])

Surely this is wrong? A failure on my part to think in Python?

 
Reply With Quote
 
p.lavarre@ieee.org
Guest
Posts: n/a
 
      11-09-2006
> > > cdb0 = '\x08' '\x01\x23\x45' '\x80' '\0'
> >
> > cdb = ''
> > cdb += struct.pack('>B', 0x0
> > cdb += struct.pack('>I', skip)[-3:]
> > cdb += struct.pack('>BB', count, 0)

>
> The change from [-3:] to [1:] is a minor cosmetic improvement,


Ouch, [1:] works while sizeof I is 4, yes, but that's not what I meant,
more generally.

Something else I tried that doesn't work is:

skip = 0x12345 ; count = 0x80
struct.pack('>8b3b21b8b8b', 0x08, 0, skip, count, 0)

That doesn't work, because in Python struct b means signed char, not
bit; and a struct repeat count adds fields, rather than making a field
wider.

But do you see what I mean? The fields of this struct have 8, 3, 21,
8, and 8 bits. The "skip" field has 21 bits, the "count" field has 8
bits, I'd like to vary both of those.

> why do you want to do that to concise working code???


cdb0 = '\x08' '\x01\x23\x45' '\x80' '\0'
works, but it's not parameterised. Writing out the hex literal always
packs the same x12345 and x80 values into those 21 and 8 bit fields.

I see I can concisely print and eval the big-endian hex:

X08Read6 = 0x08
skip = 0x12345 ; count = 0x80
hex = '%02X' % X08Read6 + ('%06X' % skip) + ('%02X' % count) + '00'
''.join([chr(int(hex[ix:ix+2],0x10)) for ix in range(0,len(hex),2)])

But that's ugly too. Maybe least ugly so far, if I bury the
join-chr-int-for-range-len-2 in a def.

Is there no less ugly way to say pack bits, rather than pack bytes, in
Python?

 
Reply With Quote
 
John Machin
Guest
Posts: n/a
 
      11-09-2006
(E-Mail Removed) wrote:
> > Not as concisely as a one-byte struct code

>
> Help, what do you mean?


Help, what did you mean by the question?

"struct" == "Python struct module"

Struct module has (concise) codes B, H, I, Q for unsigned integers of
lengths 1, 2, 4, 8, but does *not* have a code for 3-byte integers.

>
> > you presumably... read... the manual ...

>
> Did I reread the wrong parts? I see I could define a ctypes.Structure
> since 2.5, but that would be neither concise, nor since 2.3.


Looks like you ignored the first word in the sentence ("Not").

>
> > when 24-bit machines become ... popular

>
> Indeed the struct's defined recently, ~1980, were contorted to make
> them easy to say in C, which makes them easy to say in Python, e.g.:
>
> X28Read10 = 0x28
> cdb = struct.pack('>BBIBHB', X28Read10, 0, skip, 0, count, 0)
>
> But when talking the 1960's lingo I find I am actually resorting to
> horrors like:
>
> X12Inquiry = 0x12
> xxs = [0] * 6
> xxs[0] = X12Inquiry
> xxs[4] = allocationLength
> rq = ''.join([chr(xx) for xx in xxs])
>
> Surely this is wrong? A failure on my part to think in Python?


It looks wrong (and a few other adjectives), irrespective of what
problem it is trying to solve. Looks like little-endian 4-byte integer
followed by 2-byte integer ... what's wrong with struct.pack("<IH",
X12Inquiry, allocationLength) ????

Your original question asked about bigendian 3-byte integers; have you
read the suggested solution that I posted? Does it do what you asked
(one pack call instead of three)????

 
Reply With Quote
 
p.lavarre@ieee.org
Guest
Posts: n/a
 
      11-10-2006
> Help, what did you mean by the question?

How does Python express the idea:

i) Produce the six bytes '\x08' '\x01\x23\x45' '\x80' '\0' at run-time
when given the tuple (0x08, 0x12345, 0x80, 0).

ii) Produce the six bytes '\x12' '\0\0\0' '\x24' '\0' when given the
tuple (0x12, 0, 0x24, 0).

iii) And so on.

So far, everything I write is ugly. Help?

> Looks like you ignored ...


I guess you're asking me to leave the mystery of my question alone long
enough to show more plainly that indeed I am trying to make sense of
every word of every answer.

I guess I should do that in separate replies, cc'ed back into this same
thread. Please stay tuned.

Thanks in advance, Pat LaVarre

 
Reply With Quote
 
p.lavarre@ieee.org
Guest
Posts: n/a
 
      11-10-2006
> "struct" == "Python struct module"
>
> Struct module has (concise) codes B, H, I, Q for unsigned integers of
> lengths 1, 2, 4, 8, but does *not* have a code for 3-byte integers.


I thought that's what the manual meant, but I was unsure, thank you.

> > > 1. Not as concisely as a one-byte struct code

>
> Looks like you ignored the first word in the sentence ("Not").


I agree I have no confident idea of what your English meant.

I guess you're hinting at the solution you think I should find obvious,
without volunteering what that is.

Yes? If so, then:

I guess for you "a one-byte struct code" is a 'B' provided as a "format
character" of the fmt parameter of the struct.pack function.

Yes? if so, then:

You recommend shattering the three byte int:

skip = 0x012345 ; count = 0x80
struct.pack('>6B', 0x08, skip >> 0x10, skip >> 8, skip, count, 0)

Except you know that chokes over:

DeprecationWarning: 'B' format requires 0 <= number <= 255

So actually you recommend:

def lossypack(fmt, *args):
return struct.pack(fmt, *[(arg & 0xFF) for arg in args])
skip = 0x012345 ; count = 0x80
lossypack('>6B', 0x08, skip >> 0x10, skip >> 8, skip, count, 0)

Yes?

> > I guess you're asking me ...
> > to show more plainly that indeed I am trying
> > to make sense of every word of every answer


Am I helping?

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Three Mobile --> Skype on three (Non-three [Symbian - Nokia] handsets) Harry Stottle UK VOIP 0 01-05-2010 08:59 AM
Re: byte + byte -> int Lew Java 6 03-21-2009 02:22 AM
Difference between int i, j; and int i; int j; arun C Programming 8 07-31-2006 05:11 AM
int main(int argc, char *argv[] ) vs int main(int argc, char **argv ) Hal Styli C Programming 14 01-20-2004 10:00 PM
dirty stuff: f(int,int) cast to f(struct{int,int}) Schnoffos C Programming 2 06-27-2003 03:13 AM



Advertisments