diff --git a/4ed.cpp b/4ed.cpp index 9a8015f0..89b4e5a3 100644 --- a/4ed.cpp +++ b/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); diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 2eca2df5..f8039c96 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -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; diff --git a/4ed_math.cpp b/4ed_math.cpp index 59c5af0e..a1eddb7a 100644 --- a/4ed_math.cpp +++ b/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 */ diff --git a/buffer/4coder_gap_buffer.cpp b/buffer/4coder_gap_buffer.cpp index 654399c5..2c2da69f 100644 --- a/buffer/4coder_gap_buffer.cpp +++ b/buffer/4coder_gap_buffer.cpp @@ -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; diff --git a/buffer/4coder_golden_array.cpp b/buffer/4coder_golden_array.cpp index 2e7592eb..645a4a5b 100644 --- a/buffer/4coder_golden_array.cpp +++ b/buffer/4coder_golden_array.cpp @@ -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; diff --git a/buffer/4coder_multi_gap_buffer.cpp b/buffer/4coder_multi_gap_buffer.cpp index 25ad00d1..225f2c61 100644 --- a/buffer/4coder_multi_gap_buffer.cpp +++ b/buffer/4coder_multi_gap_buffer.cpp @@ -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 diff --git a/buffer/4coder_rope_buffer.cpp b/buffer/4coder_rope_buffer.cpp new file mode 100644 index 00000000..2729c8a3 --- /dev/null +++ b/buffer/4coder_rope_buffer.cpp @@ -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 + + diff --git a/buffer/4coder_shared.cpp b/buffer/4coder_shared.cpp index bb8e0019..8605b17a 100644 --- a/buffer/4coder_shared.cpp +++ b/buffer/4coder_shared.cpp @@ -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; diff --git a/win32_4ed.cpp b/win32_4ed.cpp index 2eb405d6..df08cf5f 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -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"