# 2021q1 Homework2 (quiz2)
contributed by < `ch1p98` >
## 測驗1
## 測驗3
```cpp=
#include <stdint.h>
void bitcpy(void *_dest, /* Address of the buffer to write to */
size_t _write, /* Bit offset to start writing to */
const void *_src, /* Address of the buffer to read from */
size_t _read, /* Bit offset to start reading from */
size_t count) /* number of bits to be copied */
{
_read = 1;
_write = 3;//for examplification
size_t read_lhs = _read & 7;
size_t read_rhs = 8 - read_lhs;
const uint8_t *source = (const uint8_t *) _src + (_read / 8);
size_t write_lhs = _write & 7;
size_t write_rhs = 8 - write_lhs;
uint8_t *dest = (uint8_t *) _dest + (_write / 8);
static const uint8_t read_mask[] = {
0x00, /* == 0 00000000b */
0x80, /* == 1 10000000b */
0xC0, /* == 2 11000000b */
0xE0, /* == 3 11100000b */
0xF0, /* == 4 11110000b */
0xF8, /* == 5 11111000b */
0xFC, /* == 6 11111100b */
0xFE, /* == 7 11111110b */
0xFF /* == 8 11111111b */
};
```
:::warning
Improve your English writing:
* Grammar is very important because it improves the quality of your writing. Always use the appropriate tense and remember to use punctuation. Punctuation is a great way to make your writing clear and fluent.
:notes: jserv
:::
* Concerning our usage here, zero(s) in read_mask and write_mask elements would be 'sifted out', while one(s) left unchanged.
```cpp
static const uint8_t write_mask[] = {
0xFF, /* == 0 11111111b */
0x7F, /* == 1 01111111b */
0x3F, /* == 2 00111111b */
0x1F, /* == 3 00011111b */
0x0F, /* == 4 00001111b */
0x07, /* == 5 00000111b */
0x03, /* == 6 00000011b */
0x01, /* == 7 00000001b */
0x00 /* == 8 00000000b */
};
```
:::warning
Instead of listing source code, you should address the motivation and considerations behind them.
:notes: jserv
:::
* Declare a pointer, datam to source, which is the data to be read/copied.
* Count is an arbitrary number, but we approach 8 bits at most in a cycle.
* Line 2, 3: the original code is equivalent to what is presented here.
* Line 6 of the following: shift data left by read_lhs; this movement retains (8-read_lhs=read_rhs) bits from LSB, under the motif of source, and then shifted them to MSB side (in data)
* Line 7: if number of bits we are copying (bitsize here) larger than read_rhs, we fill in data byte's unfilled bit(s) with source (which we did increment at line 3 thus it presenting next byte now).
* Line 11:if we don't need as much as a whole byte, mask it so we have correct number of bits needed in data.
```cpp=
while (count > 0) {
uint8_t data = *source;
source++;
size_t bitsize = (count > 8) ? 8 : count;
if (read_lhs > 0) {
data <<= read_lhs;
if (bitsize > read_rhs)
data |= (*source >> read_rhs);
}
if (bitsize < 8)
data &= read_mask[bitsize];
```
* Now we do the writing part: declare original, which contains 8 bits of dest(or, says dest[0]).
* Line 3: if bitsize is larger than write_lhs: well, since write_lhs indicates the writing shift, it means [write_rhs] bit(s) of dest(dest[0]) retained for writing and we will need next byte of dest (or dest[1]).
* Still, line 5~6 is the equivalent of the one-line in original code.
* In line 5, ***original & mask*** prepares the position and ***data >> write_lhs*** retrieved the bits. Then we do OR operation between them and assign the byte to dest (dest[]); the bits before the offset(_write) in original, will be kept in situ.
* Line 7: prepare **original** for the next byte(dest[1]).
* Line 8:OR **original** and 'stuff' for integration.
* stuff: data << write_rhs is equivalent to preserving (write_lhs) bit(s) from LSB of **data** and shifted them to MSB side.
* line 9: if bitsize is not larger than write_rhs, it means we don't need to look at the next byte(dest[1]) anymore. Further, we might need to cut off some bit(if bitsize is less than write_rhs) from those we write earlier.
* Line 11: write_mask[write_lhs + bitsize] serves as LSB-side delimiter and **mask** is a member of read_mask. Here's what it looks like:

:::warning
Generate the editable diagrams via Grapviz.
:notes: jserv
:::
* Line 12: right shift data and apply it to the mask.
* subtract count by how much processed in the cycle. And move on to the next (if needed).
```cpp=
uint8_t original = *dest;
uint8_t mask = read_mask[write_lhs];
if (bitsize > write_rhs) {
/* Cross multiple bytes */
*dest = (original & mask) | (data >> write_lhs);
dest++;
original = *dest & write_mask[bitsize - write_rhs];
*dest = original | (data << write_rhs);
} else {
// Since write_lhs + bitsize is never >= 8, no out-of-bound access.
mask |= write_mask[write_lhs + bitsize];
*dest++ = (original & mask) | (data >> write_lhs);
}
count -= bitsize;
}
}
```