---
# System prepended metadata

title: 2021q1 Homework2 (quiz2)

---

# 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:
 ![](https://i.imgur.com/XQFs2i7.jpg =200x200)
:::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;
    }
}

```