started ropes
parent
60dab2731c
commit
cab1801465
16
4ed.cpp
16
4ed.cpp
|
@ -678,7 +678,7 @@ COMMAND_DECL(interactive_new){
|
|||
}
|
||||
|
||||
internal File_View*
|
||||
app_open_file(App_Vars *vars, General_Memory *general, Panel *panel,
|
||||
app_open_file(App_Vars *vars, Mem_Options *mem, Panel *panel,
|
||||
Working_Set *working_set, String *string, Style *style,
|
||||
Live_Views *live_set, Command_Data *command_data){
|
||||
File_View *result = 0;
|
||||
|
@ -690,7 +690,7 @@ app_open_file(App_Vars *vars, General_Memory *general, Panel *panel,
|
|||
Get_File_Result file = working_set_get_available_file(working_set);
|
||||
if (file.file){
|
||||
file_get_dummy(file.file);
|
||||
created_file = file_create(general, file.file, (u8*)string->str, style->font);
|
||||
created_file = file_create(mem, file.file, (u8*)string->str, style->font);
|
||||
table_add(&working_set->table, file.file->source_path, file.index);
|
||||
if (created_file){
|
||||
target_file = file.file;
|
||||
|
@ -725,7 +725,7 @@ app_open_file(App_Vars *vars, General_Memory *general, Panel *panel,
|
|||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 0
|
||||
if (created_file && target_file->tokens_exist)
|
||||
file_first_lex_parallel(general, target_file);
|
||||
file_first_lex_parallel(&mem->general, target_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -762,7 +762,7 @@ COMMAND_DECL(interactive_open){
|
|||
|
||||
if (filename){
|
||||
String string = make_string(filename, filename_len);
|
||||
if (app_open_file(vars, &mem->general, panel, working_set,
|
||||
if (app_open_file(vars, mem, panel, working_set,
|
||||
&string, style, live_set, command)) made_file = 1;
|
||||
}
|
||||
|
||||
|
@ -794,7 +794,7 @@ COMMAND_DECL(reopen){
|
|||
USE_VARS(vars);
|
||||
|
||||
Editing_File temp_file;
|
||||
if (file_create(&mem->general, &temp_file, (u8*)make_c_str(file->source_path), style->font)){
|
||||
if (file_create(mem, &temp_file, (u8*)make_c_str(file->source_path), style->font)){
|
||||
file_close(&mem->general, file);
|
||||
*file = temp_file;
|
||||
file->source_path.str = file->source_path_;
|
||||
|
@ -1566,7 +1566,7 @@ COMMAND_DECL(build){
|
|||
}
|
||||
|
||||
if (file){
|
||||
file_create_super_locked(&mem->general, file, (u8*)buffer_name, style->font);
|
||||
file_create_super_locked(mem, file, (u8*)buffer_name, style->font);
|
||||
table_add(&working_set->table, file->live_name, index);
|
||||
|
||||
View *new_view = live_set_alloc_view(live_set, mem);
|
||||
|
@ -3042,7 +3042,7 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
|||
case DACT_OPEN:
|
||||
{
|
||||
command_data.view = (View*)
|
||||
app_open_file(vars, general,panel, working_set, string, style, live_set, &command_data);
|
||||
app_open_file(vars, mem, panel, working_set, string, style, live_set, &command_data);
|
||||
}break;
|
||||
|
||||
case DACT_SAVE_AS:
|
||||
|
@ -3070,7 +3070,7 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
|||
case DACT_NEW:
|
||||
{
|
||||
Get_File_Result file = working_set_get_available_file(working_set);
|
||||
file_create_empty(general, file.file, (u8*)string->str, style->font);
|
||||
file_create_empty(mem, file.file, (u8*)string->str, style->font);
|
||||
table_add(&working_set->table, file.file->source_path, file.index);
|
||||
|
||||
View *new_view = live_set_alloc_view(live_set, mem);
|
||||
|
|
|
@ -17,9 +17,12 @@
|
|||
#elif BUFFER_EXPERIMENT_SCALPEL == 1
|
||||
#include "buffer/4coder_gap_buffer.cpp"
|
||||
#define Buffer_Type Gap_Buffer
|
||||
#else
|
||||
#elif BUFFER_EXPERIMENT_SCALPEL == 2
|
||||
#include "buffer/4coder_multi_gap_buffer.cpp"
|
||||
#define Buffer_Type Multi_Gap_Buffer
|
||||
#else
|
||||
#include "buffer/4coder_rope_buffer.cpp"
|
||||
#define Buffer_Type Rope_Buffer
|
||||
#endif
|
||||
|
||||
#include "buffer/4coder_buffer_abstract.cpp"
|
||||
|
@ -1388,9 +1391,10 @@ alloc_for_buffer(void *context, int *size){
|
|||
}
|
||||
|
||||
internal void
|
||||
file_create_from_string(General_Memory *general, Editing_File *file, u8 *filename, Font *font, String val, b32 super_locked = 0){
|
||||
file_create_from_string(Mem_Options *mem, Editing_File *file, u8 *filename, Font *font, String val, b32 super_locked = 0){
|
||||
*file = {};
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
General_Memory *general = &mem->general;
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
||||
Buffer_Init_Type init = buffer_begin_init(&file->buffer, val.str, val.size);
|
||||
for (; buffer_init_need_more(&init); ){
|
||||
i32 page_size = buffer_init_page_size(&init);
|
||||
|
@ -1399,7 +1403,11 @@ file_create_from_string(General_Memory *general, Editing_File *file, u8 *filenam
|
|||
void *data = general_memory_allocate(general, page_size, BUBBLE_BUFFER);
|
||||
buffer_init_provide_page(&init, data, page_size);
|
||||
}
|
||||
i32 init_success = buffer_end_init(&init);
|
||||
|
||||
Partition *part = &mem->part;
|
||||
i32 scratch_size = partition_remaining(part);
|
||||
Assert(scratch_size > 0);
|
||||
i32 init_success = buffer_end_init(&init, part->base + part->pos, scratch_size);
|
||||
Assert(init_success);
|
||||
#endif
|
||||
|
||||
|
@ -1444,14 +1452,14 @@ file_create_from_string(General_Memory *general, Editing_File *file, u8 *filenam
|
|||
}
|
||||
|
||||
internal bool32
|
||||
file_create(General_Memory *general, Editing_File *file, u8 *filename, Font *font){
|
||||
file_create(Mem_Options *mem, Editing_File *file, u8 *filename, Font *font){
|
||||
bool32 result = 0;
|
||||
|
||||
File_Data raw_file = system_load_file(filename);
|
||||
if (raw_file.data){
|
||||
result = 1;
|
||||
String val = make_string((char*)raw_file.data, raw_file.size);
|
||||
file_create_from_string(general, file, filename, font, val);
|
||||
file_create_from_string(mem, file, filename, font, val);
|
||||
system_free_file(raw_file);
|
||||
}
|
||||
|
||||
|
@ -1459,18 +1467,18 @@ file_create(General_Memory *general, Editing_File *file, u8 *filename, Font *fon
|
|||
}
|
||||
|
||||
internal b32
|
||||
file_create_empty(General_Memory *general, Editing_File *file, u8 *filename, Font *font){
|
||||
file_create_empty(Mem_Options *mem, Editing_File *file, u8 *filename, Font *font){
|
||||
b32 result = 1;
|
||||
String empty_str = {};
|
||||
file_create_from_string(general, file, filename, font, empty_str);
|
||||
file_create_from_string(mem, file, filename, font, empty_str);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
file_create_super_locked(General_Memory *general, Editing_File *file, u8 *filename, Font *font){
|
||||
file_create_super_locked(Mem_Options *mem, Editing_File *file, u8 *filename, Font *font){
|
||||
b32 result = 1;
|
||||
String empty_str = {};
|
||||
file_create_from_string(general, file, filename, font, empty_str, 1);
|
||||
file_create_from_string(mem, file, filename, font, empty_str, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1800,7 +1808,7 @@ struct Edit_Spec{
|
|||
Edit_Step step;
|
||||
};
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
internal Edit_Step*
|
||||
file_post_undo(General_Memory *general, Editing_File *file,
|
||||
Edit_Step step, bool32 do_merge, bool32 can_merge){
|
||||
|
@ -1876,7 +1884,7 @@ undo_stack_pop(Edit_Stack *stack){
|
|||
}
|
||||
}
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
internal void
|
||||
file_post_redo(General_Memory *general, Editing_File *file, Edit_Step step){
|
||||
Edit_Stack *redo = &file->undo.redo;
|
||||
|
@ -1937,7 +1945,7 @@ file_unpost_history_block(Editing_File *file){
|
|||
file->undo.history_head_block = old_head->prev_block;
|
||||
}
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
internal Edit_Step*
|
||||
file_post_history(General_Memory *general, Editing_File *file,
|
||||
Edit_Step step, bool32 do_merge, bool32 can_merge){
|
||||
|
@ -2284,7 +2292,7 @@ internal void
|
|||
file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str,
|
||||
History_Mode history_mode){
|
||||
if (!file->undo.undo.edits) return;
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
General_Memory *general = &mem->general;
|
||||
|
||||
#if FRED_SLOW
|
||||
|
@ -2531,7 +2539,7 @@ file_do_single_edit(Mem_Options *mem, Editing_File *file,
|
|||
file_relex_parallel(mem, file, start, end, shift_amount);
|
||||
#endif
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
Temp_Memory cursor_temp = begin_temp_memory(&mem->part);
|
||||
i32 cursor_max = layout->panel_max_count * 2;
|
||||
Cursor_With_Index *cursors = push_array(&mem->part, Cursor_With_Index, cursor_max);
|
||||
|
@ -2573,7 +2581,7 @@ internal void
|
|||
view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
||||
Editing_Layout *layout, Edit_Spec spec, History_Mode history_mode){
|
||||
if (view->locked) return;
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
Assert(file);
|
||||
ProfileMomentFunction();
|
||||
|
||||
|
@ -2952,7 +2960,7 @@ file_compute_whitespace_edit(Mem_Options *mem, Editing_File *file, i32 cursor_po
|
|||
Buffer_Edit *edits, char *str_base, i32 str_size,
|
||||
Buffer_Edit *inverse_array, char *inv_str, i32 inv_max,
|
||||
i32 edit_count){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
General_Memory *general = &mem->general;
|
||||
|
||||
i32 inv_str_pos = 0;
|
||||
|
@ -2986,7 +2994,7 @@ file_compute_whitespace_edit(Mem_Options *mem, Editing_File *file, i32 cursor_po
|
|||
|
||||
internal void
|
||||
view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
Editing_File *file = view->file;
|
||||
Assert(file && !file->is_dummy);
|
||||
Partition *part = &mem->part;
|
||||
|
|
12
4ed_math.cpp
12
4ed_math.cpp
|
@ -83,6 +83,18 @@ DIVCEIL32(i32 n, i32 d) {
|
|||
inline real32
|
||||
FRACPART32(real32 x) { return x - (i32)x; }
|
||||
|
||||
inline u32
|
||||
ROUNDPOT32(u32 v){
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rectangles
|
||||
*/
|
||||
|
|
|
@ -78,7 +78,7 @@ buffer_init_provide_page(Gap_Buffer_Init *init, void *page, int page_size){
|
|||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_end_init(Gap_Buffer_Init *init){
|
||||
buffer_end_init(Gap_Buffer_Init *init, void *scratch, int scratch_size){
|
||||
Gap_Buffer *buffer;
|
||||
int osize1, size1, size2, size;
|
||||
int result;
|
||||
|
@ -292,7 +292,8 @@ buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len,
|
|||
|
||||
// NOTE(allen): This could should be optimized for Gap_Buffer
|
||||
internal_4tech int
|
||||
buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count, int *request_amount){
|
||||
buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edit *sorted_edits,
|
||||
char *strings, int edit_count, int *request_amount){
|
||||
Buffer_Edit *edit;
|
||||
int i, result;
|
||||
int shift_total, shift_amount;
|
||||
|
|
|
@ -76,7 +76,7 @@ buffer_init_provide_page(Buffer_Init *init, void *page, int page_size){
|
|||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_end_init(Buffer_Init *init){
|
||||
buffer_end_init(Buffer_Init *init, void *scratch, int scratch_size){
|
||||
Buffer *buffer;
|
||||
int result;
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ buffer_begin_init(Multi_Gap_Buffer *buffer, char *data, int size){
|
|||
return(init);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
inline_4tech int
|
||||
buffer_init_need_more(Multi_Gap_Buffer_Init *init){
|
||||
int result;
|
||||
result = 1;
|
||||
|
@ -88,7 +88,7 @@ buffer_init_need_more(Multi_Gap_Buffer_Init *init){
|
|||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
inline_4tech int
|
||||
buffer_init_page_size(Multi_Gap_Buffer_Init *init){
|
||||
Multi_Gap_Buffer *buffer;
|
||||
int result;
|
||||
|
@ -115,7 +115,7 @@ buffer_init_provide_page(Multi_Gap_Buffer_Init *init, void *page, int page_size)
|
|||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_end_init(Multi_Gap_Buffer_Init *init){
|
||||
buffer_end_init(Multi_Gap_Buffer_Init *init, void *scratch, int scratch_size){
|
||||
Multi_Gap_Buffer *buffer;
|
||||
Fixed_Width_Gap_Buffer *gap;
|
||||
int result;
|
||||
|
@ -419,16 +419,16 @@ buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, in
|
|||
gap = gaps + gap_start;
|
||||
if (buffer->edit_stage == 1){
|
||||
if (gap_start < gap_end && gap_start+1 < buffer->chunk_count){
|
||||
supplanted_gaps = gap_end - gap_start + 1;
|
||||
supplanted_gaps = gap_end - gap_start - 1;
|
||||
if (buffer->chunk_max - buffer->chunk_alloced >= supplanted_gaps){
|
||||
++gap;
|
||||
memcpy_4tech(gaps + buffer->chunk_alloced, gap, sizeof(*gaps)*supplanted_gaps);
|
||||
memmove_4tech(gap, gaps + gap_end, sizeof(*gaps)*(buffer->chunk_alloced - gap_start - 1));
|
||||
buffer->chunk_count -= (gap_end - gap_start + 1);
|
||||
buffer->chunk_count -= (gap_end - gap_start - 1);
|
||||
|
||||
local_end = end - gap->start_pos;
|
||||
|
||||
if (gap->size1 >= local_end){
|
||||
if (local_end >= gap->size1){
|
||||
gap->size2 -= (local_end - gap->size1);
|
||||
gap->size1 = 0;
|
||||
}
|
||||
|
@ -436,6 +436,7 @@ buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, in
|
|||
memmove_4tech(gap->data, gap->data + local_end, gap->size1 - local_end);
|
||||
gap->size1 -= local_end;
|
||||
}
|
||||
gap->gap_size = fixed_width_buffer_size - gap->size2 - gap->size1;
|
||||
|
||||
--gap;
|
||||
}
|
||||
|
@ -449,10 +450,11 @@ buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, in
|
|||
buffer->edit_stage = 2;
|
||||
}
|
||||
|
||||
shift_amount = (len - (end - start));
|
||||
start -= gap->start_pos;
|
||||
end -= gap->start_pos;
|
||||
assert_4tech(start >= 0 && end >= 0);
|
||||
if (end > gap->size1 + gap->size2) end = gap->size1 + gap->size2;
|
||||
shift_amount = (len - (end - start));
|
||||
|
||||
if (shift_amount + gap->size1 + gap->size2 <= fixed_width_buffer_size){
|
||||
data = gap->data;
|
||||
|
@ -514,44 +516,37 @@ buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, in
|
|||
gap->size1 = start;
|
||||
}
|
||||
|
||||
if (gap->size1 > fixed_width_buffer_half_size){
|
||||
move_size = gap->size1 - fixed_width_buffer_half_size;
|
||||
memmove_4tech(data + gap->size1 + gap->gap_size - move_size, data + end, move_size);
|
||||
gap->size1 -= move_size + (end - start);
|
||||
gap->size2 += move_size;
|
||||
}
|
||||
else if (gap->size2 > fixed_width_buffer_half_size){
|
||||
move_size = gap->size2 - fixed_width_buffer_half_size;
|
||||
memmove_4tech(data + gap->size1, data + gap->size1 + gap->gap_size, move_size);
|
||||
gap->size1 += move_size;
|
||||
gap->size2 -= move_size + (end - start);
|
||||
}
|
||||
|
||||
dgap = gap + required_empty_buffers;
|
||||
dpos = gap->size1 + gap->gap_size;
|
||||
memcpy_4tech(dgap->data + dpos, data + dpos, gap->size2);
|
||||
dgap->size2 = gap->size2;
|
||||
gap->size2 = 0;
|
||||
|
||||
middle_size = div_ceil_4tech(len, (required_empty_buffers * 2));
|
||||
|
||||
head_size = middle_size;
|
||||
tail_size = middle_size;
|
||||
|
||||
if (head_size + gap->size1 + 256 > fixed_width_buffer_size){
|
||||
head_size = fixed_width_buffer_size - gap->size1 - 256;
|
||||
if (head_size < 0) head_size = 0;
|
||||
}
|
||||
|
||||
if (tail_size + dgap->size2 + 256 > fixed_width_buffer_size){
|
||||
tail_size = fixed_width_buffer_size - dgap->size2 - 256;
|
||||
if (tail_size < 0) tail_size = 0;
|
||||
}
|
||||
tail_size = fixed_width_buffer_half_size - dgap->size2;
|
||||
if (tail_size < 0) tail_size = 0;
|
||||
|
||||
if (required_empty_buffers-1 > 0)
|
||||
middle_size = div_ceil_4tech(len - head_size - tail_size, (required_empty_buffers-1)*2);
|
||||
else
|
||||
if (tail_size < len){
|
||||
middle_size = div_ceil_4tech(len - tail_size, (required_empty_buffers * 2));
|
||||
|
||||
head_size = middle_size;
|
||||
|
||||
if (head_size + gap->size1 + 256 > fixed_width_buffer_size){
|
||||
head_size = fixed_width_buffer_size - gap->size1 - 256;
|
||||
if (head_size < 0) head_size = 0;
|
||||
}
|
||||
|
||||
if (required_empty_buffers-1 > 0){
|
||||
middle_size = div_ceil_4tech(len - head_size - tail_size, (required_empty_buffers-1)*2);
|
||||
}
|
||||
else{
|
||||
middle_size = 0;
|
||||
assert_4tech(head_size + tail_size >= len);
|
||||
}
|
||||
}
|
||||
else{
|
||||
middle_size = 0;
|
||||
head_size = 0;
|
||||
}
|
||||
|
||||
mem_pos = 0;
|
||||
if (head_size > len - mem_pos) head_size = len - mem_pos;
|
||||
|
@ -578,7 +573,6 @@ buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, in
|
|||
|
||||
gap->gap_size = fixed_width_buffer_size - (gap->size1 + gap->size2);
|
||||
local_start_pos += gap->size1 + gap->size2;
|
||||
++gap;
|
||||
}
|
||||
|
||||
if (tail_size > len - mem_pos) tail_size = len - mem_pos;
|
||||
|
@ -588,6 +582,8 @@ buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, in
|
|||
memcpy_4tech(gap->data, str + mem_pos, tail_size);
|
||||
mem_pos += tail_size;
|
||||
assert_4tech(mem_pos == len);
|
||||
debug_4tech(local_start_pos += gap->size1 + gap->size2);
|
||||
assert_4tech(local_start_pos == buffer->size);
|
||||
|
||||
buffer->chunk_count += required_empty_buffers;
|
||||
|
||||
|
@ -618,34 +614,6 @@ mugab_replace_range_end:
|
|||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech void*
|
||||
buffer_edit_provide_memory(Multi_Gap_Buffer *buffer, void *new_data, int size){
|
||||
void *result;
|
||||
Fixed_Width_Gap_Buffer *gap;
|
||||
|
||||
if (buffer->grow_gaps){
|
||||
assert_4tech(size >= buffer->chunk_max*sizeof(*buffer->gaps));
|
||||
|
||||
result = buffer->gaps;
|
||||
memcpy_4tech(new_data, buffer->gaps, buffer->chunk_alloced*sizeof(*buffer->gaps));
|
||||
buffer->gaps = (Fixed_Width_Gap_Buffer*)new_data;
|
||||
buffer->chunk_max = size / sizeof(*buffer->gaps);
|
||||
buffer->grow_gaps = 0;
|
||||
}
|
||||
|
||||
else{
|
||||
assert_4tech(buffer->chunk_max > buffer->chunk_alloced);
|
||||
assert_4tech(size >= fixed_width_buffer_size);
|
||||
|
||||
gap = &buffer->gaps[buffer->chunk_alloced++];
|
||||
*gap = {};
|
||||
gap->data = (char*)new_data;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_mugab_check(Multi_Gap_Buffer *buffer){
|
||||
Fixed_Width_Gap_Buffer *gap;
|
||||
|
@ -674,6 +642,61 @@ buffer_mugab_check(Multi_Gap_Buffer *buffer){
|
|||
return(result);
|
||||
}
|
||||
|
||||
// NOTE(allen): This could should be optimized for Multi_Gap_Buffer
|
||||
internal_4tech int
|
||||
buffer_batch_edit_step(Buffer_Batch_State *state, Multi_Gap_Buffer *buffer, Buffer_Edit *sorted_edits,
|
||||
char *strings, int edit_count, int *request_amount){
|
||||
Buffer_Edit *edit;
|
||||
int i, result;
|
||||
int shift_total, shift_amount;
|
||||
|
||||
result = 0;
|
||||
shift_total = state->shift_total;
|
||||
i = state->i;
|
||||
|
||||
edit = sorted_edits + i;
|
||||
for (; i < edit_count; ++i, ++edit){
|
||||
result = buffer_replace_range(buffer, edit->start + shift_total, edit->end + shift_total,
|
||||
strings + edit->str_start, edit->len, &shift_amount, request_amount);
|
||||
if (result) break;
|
||||
buffer_mugab_check(buffer);
|
||||
shift_total += shift_amount;
|
||||
}
|
||||
|
||||
state->shift_total = shift_total;
|
||||
state->i = i;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech void*
|
||||
buffer_edit_provide_memory(Multi_Gap_Buffer *buffer, void *new_data, int size){
|
||||
void *result;
|
||||
Fixed_Width_Gap_Buffer *gap;
|
||||
|
||||
if (buffer->grow_gaps){
|
||||
assert_4tech(size >= buffer->chunk_max*sizeof(*buffer->gaps));
|
||||
|
||||
result = buffer->gaps;
|
||||
memcpy_4tech(new_data, buffer->gaps, buffer->chunk_alloced*sizeof(*buffer->gaps));
|
||||
buffer->gaps = (Fixed_Width_Gap_Buffer*)new_data;
|
||||
buffer->chunk_max = size / sizeof(*buffer->gaps);
|
||||
buffer->grow_gaps = 0;
|
||||
}
|
||||
|
||||
else{
|
||||
assert_4tech(buffer->chunk_max > buffer->chunk_alloced);
|
||||
assert_4tech(size >= fixed_width_buffer_size);
|
||||
|
||||
gap = &buffer->gaps[buffer->chunk_alloced++];
|
||||
*gap = {};
|
||||
gap->data = (char*)new_data;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
* Four Tech
|
||||
*
|
||||
* public domain -- no warranty is offered or implied; use this code at your own risk
|
||||
*
|
||||
* 03.11.2015
|
||||
*
|
||||
* Buffer data object
|
||||
* type - Rope
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
typedef struct Rope_Node{
|
||||
int left, right, parent;
|
||||
int left_total, total;
|
||||
int str_start;
|
||||
} Rope_Node;
|
||||
|
||||
typedef struct Rope_String{
|
||||
int next_free;
|
||||
} Rope_String;
|
||||
|
||||
#define rope_string_full_size 256
|
||||
#define rope_string_width (rope_string_full_size-sizeof(Rope_String))
|
||||
|
||||
typedef struct Rope_Buffer{
|
||||
void *data;
|
||||
int free_rope_string;
|
||||
int string_count;
|
||||
|
||||
Rope_Node *nodes;
|
||||
int free_rope_node;
|
||||
int node_count;
|
||||
|
||||
float *line_widths;
|
||||
int *line_starts;
|
||||
int line_count;
|
||||
int widths_count;
|
||||
int line_max;
|
||||
int widths_max;
|
||||
} Rope_Buffer;
|
||||
|
||||
inline_4tech int
|
||||
buffer_good(Rope_Buffer *buffer){
|
||||
int good;
|
||||
good = (buffer->data != 0);
|
||||
return(good);
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
buffer_size(Rope_Buffer *buffer){
|
||||
int size;
|
||||
size = buffer->nodes->left_total;
|
||||
return(size);
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
Rope_Buffer *buffer;
|
||||
char *data;
|
||||
int size;
|
||||
|
||||
int rope_string_count;
|
||||
int node_count;
|
||||
} Rope_Buffer_Init;
|
||||
|
||||
internal_4tech Rope_Buffer_Init
|
||||
buffer_begin_init(Rope_Buffer *buffer, char *data, int size){
|
||||
Rope_Buffer_Init init;
|
||||
|
||||
init.buffer = buffer;
|
||||
init.data = data;
|
||||
init.size = size;
|
||||
|
||||
init.node_count = div_ceil_4tech(size, rope_string_width);
|
||||
|
||||
if (init.node_count < 4){
|
||||
init.node_count = 7;
|
||||
init.rope_string_count = 4;
|
||||
}
|
||||
else{
|
||||
init.rope_string_count = round_pot_4tech(init.node_count);
|
||||
init.node_count = init.rope_string_count*2 - 1;
|
||||
}
|
||||
|
||||
return(init);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_init_need_more(Rope_Buffer_Init *init){
|
||||
Rope_Buffer *buffer;
|
||||
int result;
|
||||
buffer = init->buffer;
|
||||
result = 1;
|
||||
if (buffer->data != 0 && buffer->nodes != 0)
|
||||
result = 0;
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
buffer_init_page_size(Rope_Buffer_Init *init){
|
||||
Rope_Buffer *buffer;
|
||||
int result;
|
||||
buffer = init->buffer;
|
||||
if (buffer->data) result = init->node_count*sizeof(Rope_Node);
|
||||
else result = init->rope_string_count*rope_string_full_size;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_init_provide_page(Rope_Buffer_Init *init, void *page, int page_size){
|
||||
Rope_Buffer *buffer;
|
||||
buffer = init->buffer;
|
||||
|
||||
if (buffer->data){
|
||||
assert_4tech(buffer->nodes == 0);
|
||||
assert_4tech(page_size >= init->node_count*sizeof(Rope_Node));
|
||||
buffer->nodes = (Rope_Node*)page;
|
||||
init->node_count = page_size / sizeof(Rope_Node);
|
||||
}
|
||||
else{
|
||||
assert_4tech(page_size >= init->rope_string_count*rope_string_full_size);
|
||||
buffer->data = page;
|
||||
init->rope_string_count = page_size / rope_string_full_size;
|
||||
}
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_alloc_rope_string(Rope_Buffer *buffer, int *result){
|
||||
Rope_String *rope_string;
|
||||
int success;
|
||||
|
||||
success = 0;
|
||||
if (buffer->free_rope_string >= 0){
|
||||
success = 1;
|
||||
*result = buffer->free_rope_string;
|
||||
rope_string = (Rope_String*)((char*)buffer->data + *result);
|
||||
buffer->free_rope_string = rope_string->next_free;
|
||||
*result += sizeof(Rope_String);
|
||||
}
|
||||
|
||||
return(success);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_free_rope_string(Rope_Buffer *buffer, int str_start){
|
||||
Rope_String *rope_string;
|
||||
|
||||
str_start -= sizeof(Rope_String);
|
||||
rope_string = (Rope_String*)((char*)buffer->data + str_start);
|
||||
rope_string->next_free = buffer->free_rope_string;
|
||||
buffer->free_rope_string = str_start;
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_alloc_rope_node(Rope_Buffer *buffer, int *result){
|
||||
Rope_Node *node;
|
||||
int success;
|
||||
|
||||
success = 0;
|
||||
if (buffer->free_rope_node > 0){
|
||||
success = 1;
|
||||
*result = buffer->free_rope_node;
|
||||
node = buffer->nodes + *result;
|
||||
buffer->free_rope_node = node->parent;
|
||||
}
|
||||
|
||||
return(success);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_free_rope_node(Rope_Buffer *buffer, int node_index){
|
||||
Rope_Node *node;
|
||||
|
||||
node = buffer->nodes + node_index;
|
||||
node->parent = buffer->free_rope_node;
|
||||
buffer->free_rope_node = node_index;
|
||||
}
|
||||
|
||||
typedef struct Rope_Construct_Stage{
|
||||
int parent_index;
|
||||
int is_right_side;
|
||||
int weight;
|
||||
} Rope_Construct_Stage;
|
||||
|
||||
inline_4tech Rope_Construct_Stage
|
||||
buffer_construct_stage(int parent, int right, int weight){
|
||||
Rope_Construct_Stage result;
|
||||
result.parent_index = parent;
|
||||
result.is_right_side = right;
|
||||
result.weight = weight;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_end_init(Rope_Buffer_Init *init, void *scratch, int scratch_size){
|
||||
Rope_Construct_Stage *stack, *stage;
|
||||
Rope_Buffer *buffer;
|
||||
Rope_String *rope_string;
|
||||
Rope_Node *node;
|
||||
char *src, *dest;
|
||||
int node_index;
|
||||
int i, top, stack_max, is_right_side;
|
||||
int read_pos, read_end;
|
||||
int result;
|
||||
int count;
|
||||
|
||||
src = init->data;
|
||||
read_pos = 0;
|
||||
read_end = init->size;
|
||||
|
||||
result = 0;
|
||||
buffer = init->buffer;
|
||||
if (buffer->nodes && buffer->data){
|
||||
// NOTE(allen): initialize free lists
|
||||
buffer->string_count = init->rope_string_count;
|
||||
buffer->free_rope_string = 0;
|
||||
|
||||
rope_string = (Rope_String*)buffer->data;
|
||||
count = init->rope_string_count;
|
||||
for (i = 0; i < count-1; ++i){
|
||||
rope_string->next_free = rope_string_full_size*(i+1);
|
||||
rope_string = (Rope_String*)((char*)rope_string + rope_string_full_size);
|
||||
}
|
||||
rope_string->next_free = -1;
|
||||
|
||||
buffer->node_count = init->node_count;
|
||||
buffer->free_rope_node = 1;
|
||||
|
||||
node = buffer->nodes + 1;
|
||||
count = init->node_count;
|
||||
for (i = 1; i < count; ++i, ++node){
|
||||
node->parent = i+1;
|
||||
}
|
||||
node->parent = 0;
|
||||
|
||||
result = 1;
|
||||
|
||||
// NOTE(allen): initialize tree
|
||||
node = buffer->nodes;
|
||||
node->parent = 0;
|
||||
node->total = init->size;
|
||||
node->left_total = init->size;
|
||||
|
||||
stack = (Rope_Construct_Stage*)scratch;
|
||||
stack_max = scratch_size / sizeof(Rope_Construct_Stage);
|
||||
top = 0;
|
||||
|
||||
stack[top++] = buffer_construct_stage(0, 0, init->size);
|
||||
for (;top > 0;){
|
||||
stage = stack + (--top);
|
||||
|
||||
if (buffer_alloc_rope_node(buffer, &node_index)){
|
||||
node = buffer->nodes + node_index;
|
||||
node->parent = stage->parent_index;
|
||||
node->total = stage->weight;
|
||||
is_right_side = stage->is_right_side;
|
||||
if (stage->weight > rope_string_width){
|
||||
node->left_total = stage->weight / 2;
|
||||
assert_4tech(top < stack_max);
|
||||
stack[top++] = buffer_construct_stage(node_index, 1, node->total - node->left_total);
|
||||
assert_4tech(top < stack_max);
|
||||
stack[top++] = buffer_construct_stage(node_index, 0, node->left_total);
|
||||
}
|
||||
else{
|
||||
node->left_total = 0;
|
||||
node->left = 0;
|
||||
node->right = 0;
|
||||
if (buffer_alloc_rope_string(buffer, &node->str_start)){
|
||||
dest = (char*)buffer->data + node->str_start;
|
||||
assert_4tech(read_pos < read_end);
|
||||
memcpy_4tech(dest, src + read_pos, node->total);
|
||||
read_pos += node->total;
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
node = buffer->nodes + node->parent;
|
||||
if (is_right_side) node->right = node_index;
|
||||
else node->left = node_index;
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_4tech(!result || read_pos == read_end);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
@ -66,6 +66,10 @@ lroundup_(int x, int granularity){
|
|||
#define round_up_4tech(x,g) lroundup_(x,g)
|
||||
#endif
|
||||
|
||||
#ifndef round_pot_4tech
|
||||
#define round_pot_4tech ROUNDPOT32
|
||||
#endif
|
||||
|
||||
inline_4tech float
|
||||
measure_character(void *advance_data, int stride, char character){
|
||||
char *advances;
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
#define FPS 30
|
||||
#define FRAME_TIME (1000000 / FPS)
|
||||
|
||||
#define BUFFER_EXPERIMENT_SCALPEL 1
|
||||
#define BUFFER_EXPERIMENT_SCALPEL 3
|
||||
|
||||
#include "4ed_meta.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue