# 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; } } ```