MCPcopy Create free account
hub / github.com/ElementsProject/elements / copyBitsHelper

Function copyBitsHelper

src/simplicity/frame.c:189–254  ·  view source on GitHub ↗

Given a write frame and a read frame, copy 'n' cells from after the read frame's cursor to after the write frame's cursor, * Cells in within the write frame beyond 'n' cells after the write frame's cursor may also be overwritten. * * Precondition: '*dst' is a valid write frame for 'n' more cells; * '*src' is a valid read frame for 'n' more cells; * '0 < n'; */

Source from the content-addressed store, hash-verified

187 * '0 < n';
188 */
189static void copyBitsHelper(const frameItem* dst, const frameItem *src, size_t n) {
190 /* Pointers to the UWORDs of the read and write frame that contain the frame's cursor. */
191 UWORD* src_ptr = src->edge - 1 - src->offset / UWORD_BIT;
192 UWORD* dst_ptr = dst->edge + (dst->offset - 1) / UWORD_BIT;
193 /* The specific bit within those UWORDs that is immediately in front of their respective cursors.
194 * That bit is specifically '1 << (src_shift - 1)' for the read frame,
195 * and '1 << (dst_shift - 1)' for the write frame, unless 'dst_shift == 0', in which case it is '1 << (UWORD_BIT - 1)'.
196 */
197 size_t src_shift = UWORD_BIT - (src->offset % UWORD_BIT);
198 size_t dst_shift = dst->offset % UWORD_BIT;
199 if (dst_shift) {
200 /* The write frame's current UWORD is partially filled.
201 * Fill the rest of it without overwriting the existing data.
202 */
203 *dst_ptr = LSBclear(*dst_ptr, dst_shift);
204
205 if (src_shift < dst_shift) {
206 /* The read frame's current UWORD doesn't have enough data to entirely fill the rest of the write frame's current UWORD.
207 * Fill as much as we can and move src_ptr to the read frame's next UWORD.
208 */
209 *dst_ptr |= (UWORD)(LSBkeep(*src_ptr, src_shift) << (dst_shift - src_shift));
210 if (n <= src_shift) return;
211 n -= src_shift;
212 dst_shift -= src_shift;
213 src_ptr--;
214 src_shift = UWORD_BIT;
215 }
216
217 /* Fill the rest of the write frame's current UWORD and move dst_ptr to the write frame's next UWORD. */
218 *dst_ptr |= LSBkeep((UWORD)(*src_ptr >> (src_shift - dst_shift)), dst_shift);
219 if (n <= dst_shift) return;
220 n -= dst_shift;
221 src_shift -= dst_shift;
222 dst_ptr--;
223 }
224 /* The next cell in the write frame to be filled begins at the boundary of a UWORD. */
225
226 /* :TODO: Use static analysis to limit the total amount of copied memory. */
227 if (0 == src_shift % UWORD_BIT) {
228 /* The next cell in the read frame to be filled also begins at the boundary of a UWORD.
229 * We can use 'memcpy' to copy data in bulk.
230 */
231 size_t m = ROUND_UWORD(n);
232 /* If we went through the previous 'if (dst_shift)' block then 'src_shift == 0' and we need to decrement src_ptr.
233 * If we did not go through the previous 'if (dst_shift)' block then 'src_shift == UWORD_BIT'
234 * and we do not need to decrement src_ptr.
235 * We have folded this conditional decrement into the equation applied to 'src_ptr' below.
236 */
237 memcpy(dst_ptr - (m - 1), src_ptr - (m - src_shift / UWORD_BIT), m * sizeof(UWORD));
238 } else {
239 while(1) {
240 /* Fill the write frame's UWORD by copying the LSBs of the read frame's current UWORD
241 * to the MSBs of the write frame's current UWORD,
242 * and copy the MSBs of the read frame's next UWORD to the LSBs of the write frame's current UWORD.
243 * Then move both the src_ptr and dst_ptr to their next UWORDs.
244 */
245 *dst_ptr = (UWORD)(LSBkeep(*src_ptr, src_shift) << (UWORD_BIT - src_shift));
246 if (n <= src_shift) return;

Callers 1

simplicity_copyBitsFunction · 0.85

Calls 2

LSBclearFunction · 0.85
LSBkeepFunction · 0.85

Tested by

no test coverage detected