On 02/11/2013 05:56 PM, John Ferlan wrote:
On 02/11/2013 07:07 PM, Eric Blake wrote:
> We have several cases where we need to read endian-dependent
> data regardless of host endianness; rather than open-coding
> these call sites, it will be nicer to funnel things through
> a macro.
>
> The virendian.h file can be expanded to add writer functions,
> and/or 16-bit access patterns, if needed. Also, if we need
> to turn things into a function to avoid multiple evaluations
> of buf, that can be done later. But for now, a macro worked.
>
> +# define virReadBufInt32LE(buf) \
> + ((uint32_t)(uint8_t)((buf)[0]) | \
> + ((uint32_t)(uint8_t)((buf)[1]) << 8) | \
> + ((uint32_t)(uint8_t)((buf)[2]) << 16) | \
> + ((uint32_t)(uint8_t)((buf)[3]) << 24))
> +
> +#endif /* __VIR_ENDIAN_H__ */
Looking at byteswap.h.in I'm reminded of what I've seen in a previous job where
we had lots of byteswapping to do. The macros will "isolate" each byte to move,
eg:
#define bswap_32(x) ((((x) & 0x000000FF) << 24) | \
(((x) & 0x0000FF00) << 8) | \
(((x) & 0x00FF0000) >> 8) | \
(((x) & 0xFF000000) >> 24))
Not sure if it's necessary in this case, but figured I'd ask.
In the byteswap case, you are going from an int to an int; so you do
have to mask out bytes on each part of the expression. But this
function is going from a char[] to an int, so we are already starting
with bytes. You will also notice that my code does a double cast: first
to uint8_t (to guarantee that the byte is not sign-extended) then to
uint{32,64}_t (to widen to the correct size of the resulting
expression); the first cast is the same as masking with 0xff.
ACK
Thanks for reviewing; and I have now pushed the series.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library
http://libvirt.org