This is an automated email from the ASF dual-hosted git repository. kasjer pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 4ab74a6915cf5c79bf6092263b75fb4a8b450c68 Author: Jerzy Kasenberg <[email protected]> AuthorDate: Thu Jun 25 15:09:24 2026 +0200 util: Add bit_set Simple API to work with bit set. Signed-off-by: Jerzy Kasenberg <[email protected]> --- hw/util/bit_set/include/bit_set/bit_set.h | 130 ++++++++++++++++++++++++++++++ hw/util/bit_set/pkg.yml | 24 ++++++ hw/util/bit_set/src/bit_set.c | 112 +++++++++++++++++++++++++ 3 files changed, 266 insertions(+) diff --git a/hw/util/bit_set/include/bit_set/bit_set.h b/hw/util/bit_set/include/bit_set/bit_set.h new file mode 100644 index 000000000..2f343c871 --- /dev/null +++ b/hw/util/bit_set/include/bit_set/bit_set.h @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _UTIL_BIT_SET_H_ +#define _UTIL_BIT_SET_H_ + +#include <stdint.h> +#include <stdlib.h> +#include <os/endian.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Set bit from other bit set + * + * @param bit_set - pointer to first byte of a bit set + * @param start_bit - first bit to set + * @param bit_count - number of bits to set + * @param src_bits - source bits (starting from bit 0) + */ +void bit_set_set_bits(void *bit_set, int start_bit, int bit_count, const void *src_bits); + +/** + * Get bits from bit set + * + * @param bit_set - pointer to first byte of a bit set + * @param start_bit - first bit to extract + * @param bit_count - number of bits to extract + * @param dst_bits - buffer for extracted bits (little endian buffer) + */ +void bit_set_get_bits(const void *bit_set, int start_bit, int bit_count, void *dst_bits); + +/** + * Get single bit value from bit set in little endian order + * + * @param bit_set - pointer to first byte of a bit set + * @param bit_num - bit to get + * @return value of bit_num bit + */ +uint32_t bit_set_get_bit(const void *bit_set, int bit_num); + +/** + * Set bit in bit set + * + * @param bit_set - pointer to first byte of a bit set + * @param bit_num - bit to set value + * @param val - 0 or 1 value to set + */ +void bit_set_set_bit(void *bit_set, int bit_num, uint32_t val); + +/** + * Set bit in bit set + * + * @param bit_set - pointer to first byte of a bit set + * @param bit_num - bit to set value + * @return bit value after flip + */ +uint32_t bit_set_flip_bit(void *bit_set, int bit_num); + +/** + * Reverse bytes in bit set + * This can be useful if original buffer contains bytes in bit endian order + * + * @param bit_set - bit set to revers order + * @param bit_count - number of bits in bit set + */ +static inline void +bit_set_reverse(void *bit_set, int bit_count) +{ + swap_in_place(bit_set, ((bit_count + 7) >> 3)); +} + +/** + * Get 32 bit value from bit set starting from given bit + * This function is wrapper to ease extraction of bit fields + * + * @param bit_set - pointer to first byte of a bit set + * @param start_bit - first bit to extract + * @param bit_count - number of bits to extract + * @return 32 bit value in host order + */ +static inline uint32_t +bit_set_get_uint32(const void *bit_set, int start_bit, int bit_count) +{ + uint32_t val = 0; + + bit_set_get_bits(bit_set, start_bit, bit_count, &val); + + return le32toh(val); +} + +/** + * Set number of bit in bit set from host order integer value + * + * @param bit_set - pointer to first byte of a bit set + * @param start_bit - first bit to set + * @param bit_count - number of bits to set + * @param val - host order val to set in bit field + */ +static inline void +bit_set_set_uint32(void *bit_set, int start_bit, int bit_count, uint32_t val) +{ + val = htole32(val); + + bit_set_set_bits(bit_set, start_bit, bit_count, &val); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/util/bit_set/pkg.yml b/hw/util/bit_set/pkg.yml new file mode 100644 index 000000000..f2d960e8c --- /dev/null +++ b/hw/util/bit_set/pkg.yml @@ -0,0 +1,24 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: util/bit_set +pkg.description: Bit manipulation package +pkg.author: "Apache Mynewt <[email protected]>" +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: diff --git a/hw/util/bit_set/src/bit_set.c b/hw/util/bit_set/src/bit_set.c new file mode 100644 index 000000000..91e10c0bb --- /dev/null +++ b/hw/util/bit_set/src/bit_set.c @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANYÄ„ + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <stdint.h> +#include <bit_set/bit_set.h> +#include <os/endian.h> +#include <os/os.h> + +void +bit_set_set_bits(void *bit_set, int start_bit, int bit_count, const void *src_bits) +{ + const uint8_t *src_bytes = (uint8_t *)src_bits; + uint32_t bits = *src_bytes++; + int start_byte = start_bit >> 3; + + uint8_t *bytes = start_byte + (uint8_t *)bit_set; + start_bit -= start_byte << 3; + int src_bit_offset = start_bit; + + while (bit_count > 0) { + int n = min(bit_count, 8); + uint8_t mask = ((1 << n) - 1) << start_bit; + uint8_t b = (*bytes & ~mask) | ((bits << start_bit) & mask); + *bytes++ = b; + bit_count -= 8 - start_bit; + bits >>= 8 - start_bit; + start_bit = 0; + bits |= (*src_bytes++) << src_bit_offset; + } +} + +void +bit_set_get_bits(const void *bit_set, int start_bit, int bit_count, void *dst_bits) +{ + uint8_t *dst_bytes = (uint8_t *)dst_bits; + int start_byte = start_bit >> 3; + const uint8_t *bytes = start_byte + (const uint8_t *)bit_set; + start_bit -= start_byte << 3; + uint32_t bits = 0; + uint32_t dst_bit_offset = 0; + int dst_bit_count = 0; + + while (dst_bit_count > 0 || bit_count > 0) { + if (bit_count) { + int n = min(bit_count, 8 - start_bit); + bits |= ((*bytes++) >> start_bit) << dst_bit_offset; + if (start_bit) { + dst_bit_offset = 8 - start_bit; + start_bit = 0; + } + dst_bit_count += n; + bit_count -= n; + } + if (bit_count <= 0 || dst_bit_count >= 8) { + if (dst_bit_count < 8) { + uint8_t mask = (1 << dst_bit_count) - 1; + bits &= (1 << dst_bit_count) - 1; + *dst_bytes = (*dst_bytes & ~mask) | (bits & mask); + } else { + *dst_bytes++ = (uint8_t)bits; + } + dst_bit_count -= 8; + bits >>= 8; + } + } +} + +uint32_t +bit_set_get_bit(const void *bit_set, int bit_num) +{ + uint8_t b; + + bit_set_get_bits(bit_set, bit_num, 1, &b); + + return b; +} + +void +bit_set_set_bit(void *bit_set, int bit_num, uint32_t val) +{ + uint8_t b = val & 1; + + bit_set_set_bits(bit_set, bit_num, 1, &b); +} + +uint32_t +bit_set_flip_bit(void *bit_set, int bit_num) +{ + uint8_t b; + + bit_set_get_bits(bit_set, bit_num, 1, &b); + b ^= 1; + bit_set_set_bits(bit_set, bit_num, 1, &b); + + return b; +}
