void fixed_gap_arena_insert(FixedGapArena *arena, memi offset, const ch8 *data, memi size) { // TODO: In case we can take ownership of data, we can just wrap it with gap buffers and be done. // TODO: In case we cannot take ownership of data, but the data is persistent, we can wrap it with copy-on-write gap buffers. // TODO: Remove the checks. if (size == 0) { return; } hale_assert(offset <= arena->size); hale_assert_debug(vector_count(arena->buffers)); Buf *it0 = find_buf_GTE(arena, &offset, vector_begin(&arena->buffers), vector_end(&arena->buffers)); // Move these to tests. hale_assert_requirement(it0); // hale_assert(buf_length(it) != 0); hale_assert(buf_length(it0) >= offset); if (buf_available(it0) >= size) { buf_insert(it0, offset, data, size); } else { insert_non_crit_branch(arena, offset, data, size, it0); } arena->size += size; }
static void cmdline_mode_key_pressed(struct editor *editor, struct tb_event *ev) { char ch; struct cmdline_mode *mode = (struct cmdline_mode*) editor->mode; switch (ev->key) { case TB_KEY_ESC: case TB_KEY_CTRL_C: buf_clear(editor->status); editor_pop_mode(editor); return; // FIXME(ibadawi): termbox doesn't support shift + arrow keys. // vim uses <S-Left>, <S-Right> for moving cursor to prev/next WORD. case TB_KEY_ARROW_LEFT: editor->status_cursor = max(editor->status_cursor - 1, 1); return; case TB_KEY_ARROW_RIGHT: editor->status_cursor = min(editor->status_cursor + 1, editor->status->len); return; case TB_KEY_CTRL_B: case TB_KEY_HOME: editor->status_cursor = 1; return; case TB_KEY_CTRL_E: case TB_KEY_END: editor->status_cursor = editor->status->len; return; case TB_KEY_BACKSPACE2: buf_delete(editor->status, --editor->status_cursor, 1); if (editor->status->len == 0) { editor_pop_mode(editor); return; } else if (mode->char_cb) { char *command = xstrdup(editor->status->buf + 1); mode->char_cb(editor, command); free(command); } return; case TB_KEY_ENTER: { char *command = xstrdup(editor->status->buf + 1); editor_pop_mode(editor); mode->done_cb(editor, command); free(command); return; } case TB_KEY_SPACE: ch = ' '; break; default: ch = (char) ev->ch; } char s[2] = {ch, '\0'}; buf_insert(editor->status, s, editor->status_cursor++); if (mode->char_cb) { char *command = xstrdup(editor->status->buf + 1); mode->char_cb(editor, command); free(command); } }
void STDCALL gesave_finish( void ) { buf bt; pbuf pb = gesave; uint size = buf_len( pb ) - gesaveoff; if ( size <= 187 ) *( pubyte )(( pubyte )buf_ptr( gesave ) + gesaveoff + 5 ) = ( ubyte )size; else { buf_init( &bt ); gesave = &bt; if ( size < 16800 ) { size++; gesave_bwdi( size ); } else if ( size < 0xFFF0 ) { gesave_addubyte( 0xFE ); size += 2; gesave_addushort( size ); } else { gesave_addubyte( 0xFF ); size += 4; gesave_adduint( size ); } // Write the size // We have already had one byte, so -1 buf_insert( pb, gesaveoff + 5, ( pubyte )&size /*any*/, buf_len( gesave ) - 1 ); mem_copy( buf_ptr( pb ) + gesaveoff + 5, buf_ptr( gesave ), buf_len( gesave )); buf_delete( &bt ); gesave = pb; } }
void STDCALL gesave_finish( pvmEngine pThis ) { buf bt; pbuf pb = pThis->gesave; uint size = buf_len( pThis, pb ) - pThis->gesaveoff; if ( size <= 187 ) *( pubyte )(( pubyte )buf_ptr( pThis, pThis->gesave ) + pThis->gesaveoff + 5 ) = ( ubyte )size; else { buf_init( pThis, &bt ); pThis->gesave = &bt; if ( size < 16800 ) { size++; gesave_bwd( pThis, size ); } else if ( size < 0xFFF0 ) { gesave_addubyte( pThis, 0xFE ); size += 2; gesave_addushort( pThis, size ); } else { gesave_addubyte( pThis, 0xFF ); size += 4; gesave_adduint( pThis, size ); } // Write the size // We have already had one byte, so -1 buf_insert( pThis, pb, pThis->gesaveoff + 5, ( pubyte )&size /*any*/, buf_len( pThis, pThis->gesave ) - 1 ); mem_copy( pThis, buf_ptr( pThis, pb ) + pThis->gesaveoff + 5, buf_ptr( pThis, pThis->gesave ), buf_len( pThis, pThis->gesave )); buf_delete( pThis, &bt ); pThis->gesave = pb; } }
void buf_append(struct buf *buf, char *s) { buf_insert(buf, s, buf->len); }
hale_internal void insert_non_crit_branch(FixedGapArena *arena, memi offset, const ch8 *data, memi size, Buf *it0) { requirement_check_buf(it0); Buf *it1 = NULL; // TODO: Merge the `it` with next and previous buffers. // [...**] // ^^----suffix----vv // [..+++] [+++++] [+++**] // ^^^ ^^^^^ ^^^ // +++ +++++ +++** // p0 p1 p2 ^-sx // http://cpp.sh/9yp22 // Copy to first (possible split) memi p0 = hale_minimum(buf_capacity - offset, size); // Copy to new buffers (full) memi p1 = (size-p0) & ~buf_align_mask; // Copy to last (partial) memi p2 = (size-p0) & buf_align_mask; // same as (data_size - r.p1 - r.p0); // Split size (won't underflow, as offset must be within the block (or == buf_length)) memi sx = buf_length(it0) - offset; hale_assert(p0 + p1 + p2 == size); // TODO: Check if we can put part of `p1`, `p2` into sx. // - `p1` probably makes no sense to be merged with sx, as it's already calculated to be full. memi n = 0; // if (p0 && sx) { n += 1; } n += p0 && sx; // if (p1) { n += p1 >> buf_capacity_shift; } n += p1 >> buf_align_shift; // if (p2) { n += 1; } n += !!p2; if (n) { it1 = allocate_buffers(arena, buf_index(arena, it0) + 1, n); // TODO: This wouldn't be needed if allocate_buffers wouldn't // invalidate the pointers. (deque?) it0 = it1 - 1; } if (p0) { if (sx) { hale_assert_requirement(n != 0) buf_move_suffix(it0, offset, it0 + n); // same as `it1 + n - 1` } buf_insert(it0, offset, data, p0); // `data` and `size` is used in `p1` and `p2`, // so we update he right away. data += p0; size -= p0; } if (p1) { hale_assert_debug(it1); while (size != p2) { // TODO: buf_set buf_insert(it1, 0, data, buf_capacity); data += buf_capacity; size -= buf_capacity; ++it1; } } if (p2) { hale_assert_requirement(it1); hale_assert_requirement(p2 == size); // TODO: buf_set buf_insert(it1, 0, data, p2); } }