I recently had to do something similar.
I managed to achieve this (a lot of use of the board, but ...) by shifting the source bits directly to the LSB position that I wanted to replace, and doing all the bits, including the MSB I wanted to replace, 1.
Then I AND'yielded the bit that I want instead of the bit I want to replace, shifted to the left, the same number that I shifted to the right, OR'ing the result with the original and AND'ed using the XOR'ed replacement mask. (Take a breath, I'll try to explain)
Say I have bytes:
1111 1010 0001 1001
and I want to replace piece 1010 with 0001 in order to produce:
1111 0001 0001 1001.
To achieve this, I performed the following steps:
1) Move right to 8 to produce:
0000 0000 1111 1010
2) OR mask 0xf (1111) to create:
0000 0000 1111 1111
3) And replacing 0001 with 0000 0000 1111 1111 for production:
0000 0000 0000 0001
4) Left shift by 8 to create:
0000 0001 0000 0000
5) Move the mask from LSB and XOR with full bytes
1111 1111 1111 1111
0000 1111 0000 0000
===================
1111 0000 1111 1111
6) And XOR'ed, shifted mask with the original to create:
1111 0000 0001 1001
1111 0000 1111 1111
===================
1111 0000 0001 1001
7) OR that the result of the above with a replacement:
1111 0000 0001 1001
0000 0001 0000 0000
===================
1111 0001 0001 1001 < final result
===================
In java, this leads to a function:
public long overwriteBits(long overwrite, long with, long shift, long mask) { return ((((overwrite >> shift) | mask) & with) << shift) | (overwrite & (~0 ^ (mask << shift))); }
If โoverwriteโ is the source data, โcโ is the bit that you want instead of the bits in the โshiftโ position, and the mask is a series of positive bits with the same replacement length.
To do this, I will call (in sudo):
overwriteBits (1111 1010 00011001, 0001 , 8, 1111)
I want to mention that the above will work to replace bits in any primitive, without the need for byte arrays. e.g. 11 bit replacement as below:
1101001010101101 1111 0101 101 001101
s 1010 1010 101
overwriteBits (1101001010101101 1111 0101 101 001101 , 1010 1010 101, 6 , 11111111111)
1101001010101101 1111 0101 101 001101
110 100 110 110 101 101 1010 101 101 00101
overwriteBits (1789785421l, 1365l, 6, 0x7FF)