1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "HidUtils.h"
17 #include <stdint.h>
18 #include <algorithm>
19
20 namespace HidUtil {
21
copyBits(const void * src,void * dst,size_t dst_size,unsigned int src_bit_offset,unsigned int dst_bit_offset,unsigned int bit_count)22 void copyBits(const void *src, void *dst, size_t dst_size,
23 unsigned int src_bit_offset, unsigned int dst_bit_offset,
24 unsigned int bit_count) {
25 const uint8_t *p_src;
26 uint8_t *p_dst;
27 uint8_t dst_mask;
28 unsigned int bits_rem;
29 unsigned int bit_block_count;
30
31 // Do nothing if copying past the end of the destination buffer.
32 if ((static_cast<size_t>(dst_bit_offset) > (8 * dst_size)) ||
33 (static_cast<size_t>(bit_count) > (8 * dst_size)) ||
34 (static_cast<size_t>(dst_bit_offset + bit_count) > (8 * dst_size))) {
35 return;
36 }
37
38 // Copy bits from source to destination buffer.
39 p_src = static_cast<const uint8_t*>(src) + (src_bit_offset / 8);
40 src_bit_offset = src_bit_offset % 8;
41 p_dst = static_cast<uint8_t*>(dst) + (dst_bit_offset / 8);
42 dst_bit_offset = dst_bit_offset % 8;
43 bits_rem = bit_count;
44 while (bits_rem > 0) {
45 // Determine the size of the next block of bits to copy. The block must
46 // not cross a source or desintation byte boundary.
47 bit_block_count = std::min(bits_rem, 8 - src_bit_offset);
48 bit_block_count = std::min(bit_block_count, 8 - dst_bit_offset);
49
50 // Determine the destination bit block mask.
51 dst_mask = ((1 << bit_block_count) - 1) << dst_bit_offset;
52
53 // Copy the block of bits.
54 *p_dst = (*p_dst & ~dst_mask) |
55 (((*p_src >> src_bit_offset) << dst_bit_offset) & dst_mask);
56
57 // Advance past the block of copied bits in the source.
58 src_bit_offset += bit_block_count;
59 p_src += src_bit_offset / 8;
60 src_bit_offset = src_bit_offset % 8;
61
62 // Advance past the block of copied bits in the destination.
63 dst_bit_offset += bit_block_count;
64 p_dst += dst_bit_offset / 8;
65 dst_bit_offset = dst_bit_offset % 8;
66
67 // Decrement the number of bits remaining.
68 bits_rem -= bit_block_count;
69 }
70 }
71
72 } // namespace HidUtil
73