diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2016-02-02 04:21:27 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2016-02-02 04:21:27 +0000 |
commit | c68b788ce091800ab12ad6a37681d0c1ee275ca0 (patch) | |
tree | 87fcb51f0e9ba2b6bdf98e732ae097238b116ba2 /include/sg_unaligned.h | |
parent | 572d431816271830cc321c2c7b596236e5708ea0 (diff) | |
download | sg3_utils-c68b788ce091800ab12ad6a37681d0c1ee275ca0.tar.gz |
sg_unaligned.h: gets for variable length unsigned integers; sg_inq: version descriptor list to 20160125
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@658 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'include/sg_unaligned.h')
-rw-r--r-- | include/sg_unaligned.h | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/include/sg_unaligned.h b/include/sg_unaligned.h index f2aafd3b..e40e359b 100644 --- a/include/sg_unaligned.h +++ b/include/sg_unaligned.h @@ -2,7 +2,7 @@ #define SG_UNALIGNED_H /* - * Copyright (c) 2014-2015 Douglas Gilbert. + * Copyright (c) 2014-2016 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. @@ -16,10 +16,10 @@ extern "C" { /* Borrowed from the Linux kernel, via mhvtl */ -/* In the first section below, functions that copy unsigned integers in - * a computer's native format, to and from an unaligned big endian sequence - * of bytes. Big endian byte format "on the wire" is the default used by - * SCSI standards (www.t10.org). */ +/* In the first section below, functions that copy unsigned integers in a + * computer's native format, to and from an unaligned big endian sequence of + * bytes. Big endian byte format "on the wire" is the default used by SCSI + * standards (www.t10.org). Big endian is also the network byte order. */ static inline uint16_t __get_unaligned_be16(const uint8_t *p) { @@ -95,6 +95,23 @@ static inline uint64_t sg_get_unaligned_be64(const void *p) return __get_unaligned_be64((const uint8_t *)p); } +/* Returns 0 if 'num_bytes' is less than or equal to 0 or greater than + * 8 (i.e. sizeof(uint64_t)). Else returns result in uint64_t which is + * an 8 bytes unsigned integer. */ +static inline uint64_t sg_get_unaligned_be(int num_bytes, const void *p) +{ + if ((num_bytes <= 0) || (num_bytes > (int)sizeof(uint64_t))) + return 0; + else { + const uint8_t * xp = (const uint8_t *)p; + uint64_t res = *xp; + + for (++xp; num_bytes > 1; ++xp, --num_bytes) + res = (res << 8) | *xp; + return res; + } +} + static inline void sg_put_unaligned_be16(uint16_t val, void *p) { __put_unaligned_be16(val, (uint8_t *)p); @@ -156,12 +173,6 @@ static inline void sg_nz_put_unaligned_be64(uint64_t val, void *p) /* Below are the little endian equivalents of the big endian functions * above. Little endian is used by ATA, networking and PCI. - * This section could take advantage of the - * 'uint32_t htonl(uint32_t hostlong)' [and the complementary ntohl()] - * family of functions but that would introduce a dependency on the - * <arpa/inet.h> header. Also they don't address moving to and from - * an unaligned sequence of bytes. The latter would still need to be - * done. */ static inline uint16_t __get_unaligned_le16(const uint8_t *p) @@ -226,6 +237,23 @@ static inline uint64_t sg_get_unaligned_le64(const void *p) return __get_unaligned_le64((const uint8_t *)p); } +/* Returns 0 if 'num_bytes' is less than or equal to 0 or greater than + * 8 (i.e. sizeof(uint64_t)). Else returns result in uint64_t which is + * an 8 bytes unsigned integer. */ +static inline uint64_t sg_get_unaligned_le(int num_bytes, const void *p) +{ + if ((num_bytes <= 0) || (num_bytes > (int)sizeof(uint64_t))) + return 0; + else { + const uint8_t * xp = (const uint8_t *)p + (num_bytes - 1); + uint64_t res = *xp; + + for (--xp; num_bytes > 1; --xp, --num_bytes) + res = (res << 8) | *xp; + return res; + } +} + static inline void sg_put_unaligned_le16(uint16_t val, void *p) { __put_unaligned_le16(val, (uint8_t *)p); |