started ropes

master
Allen Webster 2015-11-03 18:57:04 -05:00
parent 60dab2731c
commit cab1801465
9 changed files with 444 additions and 96 deletions

16
4ed.cpp
View File

@ -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);

View File

@ -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;

View File

@ -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
*/

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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"