basic file open optimizations
parent
774c8daaff
commit
dcdec287a1
|
@ -42,8 +42,8 @@ struct Font{
|
|||
String name;
|
||||
bool32 loaded;
|
||||
|
||||
Glyph_Data glyphs[128];
|
||||
stbtt_bakedchar chardata[128];
|
||||
Glyph_Data glyphs[256];
|
||||
stbtt_bakedchar chardata[256];
|
||||
i32 height, ascent, descent, line_skip;
|
||||
i32 advance;
|
||||
u32 tex;
|
||||
|
|
|
@ -27,6 +27,16 @@ buffer_stringify(Buffer_Type *buffer, int start, int end, char *out){
|
|||
}
|
||||
}
|
||||
|
||||
inline_4tech void
|
||||
buffer_backify(Buffer_Type *buffer, int start, int end, char *out){
|
||||
for (Buffer_Backify_Type loop = buffer_backify_loop(buffer, end, start);
|
||||
buffer_backify_good(&loop);
|
||||
buffer_backify_next(&loop)){
|
||||
memcpy_4tech(out, loop.data, loop.size);
|
||||
out += loop.size;
|
||||
}
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_convert_out(Buffer_Type *buffer, char *dest, int max){
|
||||
Buffer_Stringify_Type loop;
|
||||
|
@ -480,9 +490,11 @@ typedef struct Buffer_Measure_Starts{
|
|||
int i;
|
||||
int count;
|
||||
int start;
|
||||
float width;
|
||||
} Buffer_Measure_Starts;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
internal_4tech int
|
||||
buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
||||
Buffer_Stringify_Type loop;
|
||||
|
@ -497,7 +509,7 @@ buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
|||
starts = buffer->line_starts;
|
||||
max = buffer->line_max;
|
||||
|
||||
result = 0;
|
||||
result = 1;
|
||||
|
||||
i = state->i;
|
||||
count = state->count;
|
||||
|
@ -510,10 +522,7 @@ buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
|||
data = loop.data - loop.absolute_pos;
|
||||
for (; i < end; ++i){
|
||||
if (data[i] == '\n'){
|
||||
if (count == max){
|
||||
result = 1;
|
||||
goto buffer_measure_starts_end;
|
||||
}
|
||||
if (count == max) goto buffer_measure_starts_end;
|
||||
|
||||
starts[count++] = start;
|
||||
start = i + 1;
|
||||
|
@ -521,13 +530,11 @@ buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
|||
}
|
||||
}
|
||||
|
||||
if (i == size){
|
||||
if (count == max){
|
||||
result = 1;
|
||||
goto buffer_measure_starts_end;
|
||||
}
|
||||
starts[count++] = start;
|
||||
}
|
||||
assert_4tech(i == size);
|
||||
|
||||
if (count == max) goto buffer_measure_starts_end;
|
||||
starts[count++] = start;
|
||||
result = 0;
|
||||
|
||||
buffer_measure_starts_end:
|
||||
state->i = i;
|
||||
|
@ -536,6 +543,75 @@ buffer_measure_starts_end:
|
|||
|
||||
return(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
internal_4tech int
|
||||
buffer_measure_starts_widths(Buffer_Measure_Starts *state, Buffer_Type *buffer,
|
||||
float *advance_data){
|
||||
Buffer_Stringify_Type loop;
|
||||
int *start_ptr, *start_end;
|
||||
float *width_ptr;
|
||||
debug_4tech(int widths_max);
|
||||
debug_4tech(int max);
|
||||
char *data;
|
||||
int size, end;
|
||||
float width;
|
||||
int start, i;
|
||||
int result;
|
||||
char ch;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
|
||||
debug_4tech(max = buffer->line_max);
|
||||
debug_4tech(widths_max = buffer->widths_max);
|
||||
assert_4tech(max == widths_max);
|
||||
|
||||
result = 1;
|
||||
|
||||
i = state->i;
|
||||
start = state->start;
|
||||
width = state->width;
|
||||
|
||||
start_ptr = buffer->line_starts + state->count;
|
||||
width_ptr = buffer->line_widths + state->count;
|
||||
start_end = buffer->line_starts + buffer->line_max;
|
||||
|
||||
for (loop = buffer_stringify_loop(buffer, i, size);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; i < end; ++i){
|
||||
ch = data[i];
|
||||
if (ch == '\n'){
|
||||
if (start_ptr == start_end) goto buffer_measure_starts_widths_end;
|
||||
|
||||
*width_ptr++ = width;
|
||||
*start_ptr++ = start;
|
||||
start = i + 1;
|
||||
width = 0;
|
||||
}
|
||||
else{
|
||||
width += measure_character(advance_data, ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_4tech(i == size);
|
||||
|
||||
if (start_ptr == start_end) goto buffer_measure_starts_widths_end;
|
||||
*start_ptr++ = start;
|
||||
*width_ptr++ = 0;
|
||||
result = 0;
|
||||
|
||||
buffer_measure_starts_widths_end:
|
||||
state->i = i;
|
||||
state->count = (int)(start_ptr - buffer->line_starts);
|
||||
state->start = start;
|
||||
state->width = width;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_remeasure_starts(Buffer_Type *buffer, int line_start, int line_end, int line_shift, int text_shift){
|
||||
|
@ -600,7 +676,7 @@ buffer_remeasure_starts_end:
|
|||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_remeasure_widths(Buffer_Type *buffer, void *advance_data, int stride,
|
||||
buffer_remeasure_widths(Buffer_Type *buffer, float *advance_data,
|
||||
int line_start, int line_end, int line_shift){
|
||||
Buffer_Stringify_Type loop;
|
||||
int *starts;
|
||||
|
@ -652,17 +728,19 @@ buffer_remeasure_widths(Buffer_Type *buffer, void *advance_data, int stride,
|
|||
width = 0;
|
||||
}
|
||||
else{
|
||||
width += measure_character(advance_data, stride, ch);
|
||||
width += measure_character(advance_data, ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
inline_4tech void
|
||||
buffer_measure_widths(Buffer_Type *buffer, void *advance_data, int stride){
|
||||
buffer_measure_widths(Buffer_Type *buffer, void *advance_data){
|
||||
assert_4tech(buffer->line_count >= 1);
|
||||
buffer_remeasure_widths(buffer, advance_data, stride, 0, buffer->line_count-1, 0);
|
||||
buffer_remeasure_widths(buffer, advance_data, 0, buffer->line_count-1, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
internal_4tech void
|
||||
buffer_measure_wrap_y(Buffer_Type *buffer, float *wraps,
|
||||
|
@ -748,8 +826,8 @@ typedef struct Seek_State{
|
|||
} Seek_State;
|
||||
|
||||
internal_4tech int
|
||||
cursor_seek_step(Seek_State *state, Buffer_Seek seek, int xy_seek, float max_width, float font_height,
|
||||
char *advances, int stride, int size, char ch){
|
||||
cursor_seek_step(Seek_State *state, Buffer_Seek seek, int xy_seek, float max_width,
|
||||
float font_height, float *advances, int size, char ch){
|
||||
Full_Cursor cursor, prev_cursor;
|
||||
float ch_width;
|
||||
int result;
|
||||
|
@ -772,8 +850,8 @@ cursor_seek_step(Seek_State *state, Buffer_Seek seek, int xy_seek, float max_wid
|
|||
|
||||
default:
|
||||
++cursor.character;
|
||||
if (ch == '\r') ch_width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * 'r');
|
||||
else ch_width = *(float*)(advances + stride * ch);
|
||||
if (ch == '\r') ch_width = *(float*)(advances + '\\') + *(float*)(advances + 'r');
|
||||
else ch_width = *(float*)(advances + ch);
|
||||
|
||||
if (cursor.wrapped_x + ch_width >= max_width){
|
||||
cursor.wrapped_y += font_height;
|
||||
|
@ -855,8 +933,8 @@ cursor_seek_step_end:
|
|||
#endif
|
||||
|
||||
internal_4tech Full_Cursor
|
||||
buffer_cursor_seek(Buffer_Type *buffer, Buffer_Seek seek, float max_width, float font_height,
|
||||
void *advance_data, int stride, Full_Cursor cursor){
|
||||
buffer_cursor_seek(Buffer_Type *buffer, Buffer_Seek seek, float max_width,
|
||||
float font_height, float *advance_data, Full_Cursor cursor){
|
||||
Buffer_Stringify_Type loop;
|
||||
char *data;
|
||||
int size, end;
|
||||
|
@ -864,11 +942,9 @@ buffer_cursor_seek(Buffer_Type *buffer, Buffer_Seek seek, float max_width, float
|
|||
int result;
|
||||
|
||||
Seek_State state;
|
||||
char *advances;
|
||||
int xy_seek;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
advances = (char*)advance_data;
|
||||
xy_seek = (seek.type == buffer_seek_wrapped_xy || seek.type == buffer_seek_unwrapped_xy);
|
||||
state.cursor = cursor;
|
||||
|
||||
|
@ -880,14 +956,14 @@ buffer_cursor_seek(Buffer_Type *buffer, Buffer_Seek seek, float max_width, float
|
|||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; i < end; ++i){
|
||||
result = cursor_seek_step(&state, seek, xy_seek, max_width, font_height,
|
||||
advances, stride, size, data[i]);
|
||||
result = cursor_seek_step(&state, seek, xy_seek, max_width,
|
||||
font_height, advance_data, size, data[i]);
|
||||
if (!result) goto buffer_cursor_seek_end;
|
||||
}
|
||||
}
|
||||
if (result){
|
||||
result = cursor_seek_step(&state, seek, xy_seek, max_width, font_height,
|
||||
advances, stride, size, 0);
|
||||
result = cursor_seek_step(&state, seek, xy_seek, max_width,
|
||||
font_height, advance_data, size, 0);
|
||||
assert_4tech(result == 0);
|
||||
}
|
||||
|
||||
|
@ -897,21 +973,21 @@ buffer_cursor_seek_end:
|
|||
|
||||
internal_4tech Full_Cursor
|
||||
buffer_cursor_from_pos(Buffer_Type *buffer, int pos, float *wraps,
|
||||
float max_width, float font_height, void *advance_data, int stride){
|
||||
float max_width, float font_height, float *advance_data){
|
||||
Full_Cursor result;
|
||||
int line_index;
|
||||
|
||||
line_index = buffer_get_line_index_range(buffer, pos, 0, buffer->line_count);
|
||||
result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height);
|
||||
result = buffer_cursor_seek(buffer, seek_pos(pos), max_width, font_height,
|
||||
advance_data, stride, result);
|
||||
advance_data, result);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech Full_Cursor
|
||||
buffer_cursor_from_unwrapped_xy(Buffer_Type *buffer, float x, float y, int round_down, float *wraps,
|
||||
float max_width, float font_height, void *advance_data, int stride){
|
||||
float max_width, float font_height, float *advance_data){
|
||||
Full_Cursor result;
|
||||
int line_index;
|
||||
|
||||
|
@ -921,21 +997,21 @@ buffer_cursor_from_unwrapped_xy(Buffer_Type *buffer, float x, float y, int round
|
|||
|
||||
result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height);
|
||||
result = buffer_cursor_seek(buffer, seek_unwrapped_xy(x, y, round_down), max_width, font_height,
|
||||
advance_data, stride, result);
|
||||
advance_data, result);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech Full_Cursor
|
||||
buffer_cursor_from_wrapped_xy(Buffer_Type *buffer, float x, float y, int round_down, float *wraps,
|
||||
float max_width, float font_height, void *advance_data, int stride){
|
||||
float max_width, float font_height, float *advance_data){
|
||||
Full_Cursor result;
|
||||
int line_index;
|
||||
|
||||
line_index = buffer_get_line_index_from_wrapped_y(wraps, y, font_height, 0, buffer->line_count);
|
||||
result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height);
|
||||
result = buffer_cursor_seek(buffer, seek_wrapped_xy(x, y, round_down), max_width, font_height,
|
||||
advance_data, stride, result);
|
||||
advance_data, result);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
@ -1007,7 +1083,7 @@ buffer_invert_batch(Buffer_Invert_Batch *state, Buffer_Type *buffer, Buffer_Edit
|
|||
internal_4tech void
|
||||
buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *items, int max, int *count,
|
||||
float port_x, float port_y, float scroll_x, float scroll_y, int wrapped,
|
||||
float width, float height, void *advance_data, int stride, float font_height){
|
||||
float width, float height, float *advance_data, float font_height){
|
||||
Buffer_Stringify_Type loop;
|
||||
Full_Cursor start_cursor;
|
||||
Buffer_Render_Item *item;
|
||||
|
@ -1025,12 +1101,12 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it
|
|||
shift_y = port_y - scroll_y;
|
||||
if (wrapped){
|
||||
start_cursor = buffer_cursor_from_wrapped_xy(buffer, 0, scroll_y, 0, wraps,
|
||||
width, font_height, advance_data, stride);
|
||||
width, font_height, advance_data);
|
||||
shift_y += start_cursor.wrapped_y;
|
||||
}
|
||||
else{
|
||||
start_cursor = buffer_cursor_from_unwrapped_xy(buffer, 0, scroll_y, 0, wraps,
|
||||
width, font_height, advance_data, stride);
|
||||
width, font_height, advance_data);
|
||||
shift_y += start_cursor.unwrapped_y;
|
||||
}
|
||||
|
||||
|
@ -1048,7 +1124,7 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it
|
|||
|
||||
for (i = loop.absolute_pos; i < end; ++i){
|
||||
ch = data[i];
|
||||
ch_width = measure_character(advance_data, stride, ch);
|
||||
ch_width = measure_character(advance_data, ch);
|
||||
|
||||
if (ch_width + x > width + shift_x && wrapped){
|
||||
x = shift_x;
|
||||
|
@ -1058,7 +1134,7 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it
|
|||
|
||||
switch (ch){
|
||||
case '\n':
|
||||
write_render_item_inline(item, i, ' ', x, y, advance_data, stride, font_height);
|
||||
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
|
||||
|
@ -1067,35 +1143,35 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it
|
|||
break;
|
||||
|
||||
case 0:
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, stride, font_height);
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, stride, font_height);
|
||||
ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, stride, font_height);
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, stride, font_height);
|
||||
ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, stride, font_height);
|
||||
ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
|
||||
write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, stride, font_height);
|
||||
write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
@ -1116,7 +1192,7 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it
|
|||
buffer_get_render_data_end:
|
||||
if (y <= height + shift_y || item == items){
|
||||
ch = 0;
|
||||
ch_width = measure_character(advance_data, stride, ' ');
|
||||
ch_width = measure_character(advance_data, ' ');
|
||||
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
|
|
|
@ -692,7 +692,7 @@ buffer_edit_provide_memory(Multi_Gap_Buffer *buffer, void *new_data, int size){
|
|||
assert_4tech(size >= fixed_width_buffer_size);
|
||||
|
||||
gap = &buffer->gaps[buffer->chunk_alloced++];
|
||||
*gap = {};
|
||||
memzero_4tech(*gap);
|
||||
gap->data = (char*)new_data;
|
||||
result = 0;
|
||||
}
|
||||
|
|
|
@ -402,7 +402,7 @@ buffer_end_init(Rope_Buffer_Init *init, void *scratch, int scratch_size){
|
|||
result = 1;
|
||||
|
||||
node = buffer->nodes;
|
||||
*node = {};
|
||||
memzero_4tech(*node);
|
||||
node->weight = init->size;
|
||||
node->left_weight = init->size;
|
||||
|
||||
|
@ -988,12 +988,14 @@ buffer_split_end:
|
|||
internal_4tech int
|
||||
buffer_build_tree_floating(Rope_Buffer *buffer, char *str, int len, int *out,
|
||||
void *scratch, int scratch_size, int *request_amount){
|
||||
Rope_Node *super_root_node;
|
||||
int result;
|
||||
int super_root;
|
||||
|
||||
result = 0;
|
||||
if (buffer_alloc_rope_node(buffer, &super_root)){
|
||||
buffer->nodes[super_root] = {};
|
||||
super_root_node = buffer->nodes + super_root;
|
||||
memset_4tech(super_root_node, 0, sizeof(*super_root_node));
|
||||
if (buffer_build_tree(buffer, str, len, super_root, scratch, scratch_size, request_amount)){
|
||||
*out = buffer->nodes[super_root].left;
|
||||
buffer_free_rope_node(buffer, super_root);
|
||||
|
@ -1124,7 +1126,7 @@ buffer_replace_range(Rope_Buffer *buffer, int start, int end, char *str, int len
|
|||
nodes->left = state.middle;
|
||||
nodes->weight = nodes->left_weight = nodes[state.middle].weight;
|
||||
|
||||
state = {};
|
||||
memset_4tech(&state, 0, sizeof(state));
|
||||
|
||||
buffer_rope_check(buffer, scratch, scratch_size);
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#define memset_4tech memset
|
||||
#endif
|
||||
|
||||
#ifndef memzero_4tech
|
||||
#define memzero_4tech(x) ((x) = {})
|
||||
#endif
|
||||
|
||||
#ifndef memcpy_4tech
|
||||
#define memcpy_4tech memcpy
|
||||
#endif
|
||||
|
@ -70,21 +74,7 @@ lroundup_(int x, int granularity){
|
|||
#define round_pot_4tech ROUNDPOT32
|
||||
#endif
|
||||
|
||||
inline_4tech float
|
||||
measure_character(void *advance_data, int stride, char character){
|
||||
char *advances;
|
||||
float width;
|
||||
|
||||
advances = (char*)advance_data;
|
||||
switch (character){
|
||||
case 0: width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * '0'); break;
|
||||
case '\n': width = 0; break;
|
||||
case '\r': width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * '\r'); break;
|
||||
default: width = *(float*)(advances + stride * character);
|
||||
}
|
||||
|
||||
return(width);
|
||||
}
|
||||
#define measure_character(a,c) ((a)[c])
|
||||
|
||||
typedef struct Buffer_Edit{
|
||||
int str_start, len;
|
||||
|
@ -176,9 +166,9 @@ write_render_item(Buffer_Render_Item *item, int index, int glyphid,
|
|||
|
||||
inline_4tech float
|
||||
write_render_item_inline(Buffer_Render_Item *item, int index, int glyphid,
|
||||
float x, float y, void *advance_data, int stride, float h){
|
||||
float x, float y, float *advance_data, float h){
|
||||
float ch_width;
|
||||
ch_width = measure_character(advance_data, stride, (char)glyphid);
|
||||
ch_width = measure_character(advance_data, (char)glyphid);
|
||||
write_render_item(item, index, glyphid, x, y, ch_width, h);
|
||||
return(ch_width);
|
||||
}
|
||||
|
@ -348,12 +338,27 @@ buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, int count,
|
|||
|
||||
internal_4tech int
|
||||
eol_convert_in(char *dest, char *src, int size){
|
||||
int i, j;
|
||||
int i, j, k;
|
||||
|
||||
i = 0;
|
||||
k = 0;
|
||||
j = 0;
|
||||
|
||||
for (i = 0, j = 0; i < size; ++i){
|
||||
if (src[i] != '\r'){
|
||||
dest[j++] = src[i];
|
||||
for (; j < size && src[j] != '\r'; ++j);
|
||||
memcpy_4tech(dest, src, j);
|
||||
|
||||
if (j < size){
|
||||
k = 1;
|
||||
++j;
|
||||
for (i = j; i < size; ++i){
|
||||
if (src[i] == '\r'){
|
||||
memcpy_4tech(dest + j - k, src + j, i - j);
|
||||
++k;
|
||||
j = i+1;
|
||||
}
|
||||
}
|
||||
memcpy_4tech(dest + j - k, src + j, i - j);
|
||||
j = i - k;
|
||||
}
|
||||
|
||||
return(j);
|
||||
|
@ -361,12 +366,26 @@ eol_convert_in(char *dest, char *src, int size){
|
|||
|
||||
internal_4tech int
|
||||
eol_in_place_convert_in(char *data, int size){
|
||||
int i, j;
|
||||
int i, j, k;
|
||||
|
||||
i = 0;
|
||||
k = 0;
|
||||
j = 0;
|
||||
|
||||
for (i = 0, j = 0; i < size; ++i){
|
||||
if (data[i] != '\r'){
|
||||
data[j++] = data[i];
|
||||
for (; j < size && data[j] != '\r'; ++j);
|
||||
|
||||
if (j < size){
|
||||
k = 1;
|
||||
++j;
|
||||
for (i = j; i < size; ++i){
|
||||
if (data[i] == '\r'){
|
||||
memmove_4tech(data + j - k, data + j, i - j);
|
||||
++k;
|
||||
j = i+1;
|
||||
}
|
||||
}
|
||||
memmove_4tech(data + j - k, data + j, i - j);
|
||||
j = i - k;
|
||||
}
|
||||
|
||||
return(j);
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
* Four Tech
|
||||
*
|
||||
* public domain -- no warranty is offered or implied; use this code at your own risk
|
||||
*
|
||||
* 08.11.2015
|
||||
*
|
||||
* Buffer experiment testing layer, abstract portion
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#define Buffer_Init_Type cat_4tech(Buffer_Type, _Init)
|
||||
#define Buffer_Stringify_Type cat_4tech(Buffer_Type, _Stringify_Loop)
|
||||
#define Buffer_Backify_Type cat_4tech(Buffer_Type, _Backify_Loop)
|
||||
|
||||
void
|
||||
init_buffer(Buffer_Type *buffer, File_Data file, void *scratch, int scratch_size){
|
||||
memzero_4tech(*buffer);
|
||||
Buffer_Init_Type init;
|
||||
for (init = buffer_begin_init(buffer, file.data, file.size);
|
||||
buffer_init_need_more(&init);){
|
||||
int page_size = buffer_init_page_size(&init);
|
||||
void *page = malloc(page_size);
|
||||
buffer_init_provide_page(&init, page, page_size);
|
||||
}
|
||||
debug_4tech(int result =)
|
||||
buffer_end_init(&init, scratch, scratch_size);
|
||||
assert_4tech(result);
|
||||
}
|
||||
|
||||
void
|
||||
measure_starts_widths(Buffer_Type *buffer, float *font_widths){
|
||||
int max = 1 << 10;
|
||||
buffer->line_starts = (int*)malloc(max*sizeof(int));
|
||||
buffer->line_max = max;
|
||||
buffer->line_widths = (float*)malloc(max*sizeof(float));
|
||||
buffer->widths_max = max;
|
||||
|
||||
Buffer_Measure_Starts state;
|
||||
memzero_4tech(state);
|
||||
for (;buffer_measure_starts_widths(&state, buffer, font_widths);){
|
||||
int max = buffer->line_max;
|
||||
int count = state.count;
|
||||
int target = count + 1;
|
||||
|
||||
max = target*2;
|
||||
int *new_lines = (int*)malloc(max*sizeof(int));
|
||||
memcpy_4tech(new_lines, buffer->line_starts, count*sizeof(int));
|
||||
free(buffer->line_starts);
|
||||
buffer->line_starts = new_lines;
|
||||
buffer->line_max = max;
|
||||
|
||||
float *new_widths = (float*)malloc(max*sizeof(float));
|
||||
memcpy_4tech(new_widths, buffer->line_widths, count*sizeof(int));
|
||||
free(buffer->line_widths);
|
||||
buffer->line_widths = new_widths;
|
||||
buffer->widths_max = max;
|
||||
}
|
||||
buffer->line_count = state.count;
|
||||
buffer->widths_count = state.count;
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -52,6 +52,10 @@ ROUNDPOT32(unsigned int v){
|
|||
#endif
|
||||
#define hard_assert_4tech(x) assert(x)
|
||||
|
||||
#ifdef __linux__
|
||||
#define memzero_4tech(x) memset_4tech(&(x), 0, sizeof(x))
|
||||
#endif
|
||||
|
||||
#include "4coder_shared.cpp"
|
||||
#include "4coder_golden_array.cpp"
|
||||
#include "4coder_gap_buffer.cpp"
|
||||
|
@ -60,25 +64,21 @@ ROUNDPOT32(unsigned int v){
|
|||
|
||||
#define Buffer_Type Buffer
|
||||
#include "4coder_buffer_abstract.cpp"
|
||||
|
||||
#undef Buffer_Type
|
||||
|
||||
#define Buffer_Type Gap_Buffer
|
||||
#include "4coder_buffer_abstract.cpp"
|
||||
|
||||
#undef Buffer_Type
|
||||
|
||||
#define Buffer_Type Multi_Gap_Buffer
|
||||
#include "4coder_buffer_abstract.cpp"
|
||||
|
||||
#undef Buffer_Type
|
||||
|
||||
#define Buffer_Type Rope_Buffer
|
||||
#include "4coder_buffer_abstract.cpp"
|
||||
|
||||
#undef Buffer_Type
|
||||
#undef Buffer_Init_Type
|
||||
#undef Buffer_Stringify_Type
|
||||
#undef Buffer_Backify_Type
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
|
||||
typedef unsigned long long time_int;
|
||||
|
@ -110,28 +110,47 @@ time_int get_time(){
|
|||
return(result);
|
||||
}
|
||||
|
||||
#else
|
||||
#error Timer not supported by this platform
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
#include <time.h>
|
||||
|
||||
void setup(){
|
||||
unsigned long long resolution;
|
||||
if (!time_init(&resolution)){
|
||||
printf("error: could not initialize timer");
|
||||
exit(1);
|
||||
typedef unsigned long long time_int;
|
||||
|
||||
int time_init(unsigned long long *resolution){
|
||||
int result;
|
||||
struct timespec res;
|
||||
result = 0;
|
||||
|
||||
if (!clock_getres(CLOCK_MONOTONIC, &res)){
|
||||
result = 1;
|
||||
if (res.tv_sec > 0 || res.tv_nsec == 0) *resolution = 0;
|
||||
else *resolution = (unsigned long long)(1000000/res.tv_nsec);
|
||||
}
|
||||
|
||||
if (resolution < 1000000)
|
||||
printf("warning: timer is not actually at high enough resolution for good measurements!\n");
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
time_int get_time(){
|
||||
time_int result;
|
||||
struct timespec time;
|
||||
|
||||
result = 0;
|
||||
if (!clock_gettime(CLOCK_MONOTONIC, &time)){
|
||||
result = (time.tv_sec * 1000000) + (time.tv_nsec / 1000);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
#else
|
||||
#error Timer not supported on this platform
|
||||
#endif
|
||||
|
||||
typedef struct File_Data{
|
||||
char *data;
|
||||
int size;
|
||||
} File_Data;
|
||||
|
||||
File_Data get_file(char *filename){
|
||||
File_Data get_file(const char *filename){
|
||||
FILE *file;
|
||||
File_Data result;
|
||||
|
||||
|
@ -162,6 +181,61 @@ void free_file(File_Data file){
|
|||
free(file.data);
|
||||
}
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "stb_truetype.h"
|
||||
|
||||
float* get_font_data(const char *font_file){
|
||||
float *data = 0;
|
||||
stbtt_bakedchar *baked;
|
||||
File_Data file = get_file(font_file);
|
||||
int stride, offset;
|
||||
|
||||
if (file.data){
|
||||
int size = sizeof(*baked)*256;
|
||||
baked = (stbtt_bakedchar*)malloc(size);
|
||||
memset_4tech(baked, 0, sizeof(*baked)*256);
|
||||
|
||||
offset = (int)((char*)&baked->xadvance - (char*)baked);
|
||||
stride = sizeof(*baked);
|
||||
|
||||
int w, h;
|
||||
w = 10*256;
|
||||
h = 25;
|
||||
unsigned char *pixels = (unsigned char*)malloc(w * h);
|
||||
stbtt_BakeFontBitmap((unsigned char*)file.data, 0, 17.f, pixels, w, h, 0, 128, baked);
|
||||
free(pixels);
|
||||
free_file(file);
|
||||
|
||||
data = (float*)malloc(sizeof(float)*256);
|
||||
memset_4tech(data, 0, sizeof(float)*256);
|
||||
|
||||
char *pos = (char*)baked;
|
||||
pos += offset;
|
||||
for (int i = 0; i < 128; ++i){
|
||||
data[i] = *(float*)pos;
|
||||
pos += stride;
|
||||
}
|
||||
free(baked);
|
||||
}
|
||||
else{
|
||||
printf("error: cannot continue without font\n");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void setup(){
|
||||
unsigned long long resolution;
|
||||
if (!time_init(&resolution)){
|
||||
printf("error: could not initialize timer");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (resolution < 1000000)
|
||||
printf("warning: timer is not actually at high enough resolution for good measurements!\n");
|
||||
|
||||
}
|
||||
|
||||
typedef struct Time_Record{
|
||||
time_int buffer;
|
||||
time_int gap_buffer;
|
||||
|
@ -260,20 +334,21 @@ typedef struct Buffer_Set{
|
|||
Rope_Buffer rope_buffer;
|
||||
} Buffer_Set;
|
||||
|
||||
template<typename Buffer_Init_Type, typename Buffer_Type> void
|
||||
init_buffer(Buffer_Type *buffer, File_Data file, void *scratch, int scratch_size){
|
||||
*buffer = {};
|
||||
Buffer_Init_Type init;
|
||||
for (init = buffer_begin_init(buffer, file.data, file.size);
|
||||
buffer_init_need_more(&init);){
|
||||
int page_size = buffer_init_page_size(&init);
|
||||
void *page = malloc(page_size);
|
||||
buffer_init_provide_page(&init, page, page_size);
|
||||
}
|
||||
debug_4tech(int result =)
|
||||
buffer_end_init(&init, scratch, scratch_size);
|
||||
assert_4tech(result);
|
||||
}
|
||||
#define Buffer_Type Buffer
|
||||
#include "4coder_test_abstract.cpp"
|
||||
#undef Buffer_Type
|
||||
|
||||
#define Buffer_Type Gap_Buffer
|
||||
#include "4coder_test_abstract.cpp"
|
||||
#undef Buffer_Type
|
||||
|
||||
#define Buffer_Type Multi_Gap_Buffer
|
||||
#include "4coder_test_abstract.cpp"
|
||||
#undef Buffer_Type
|
||||
|
||||
#define Buffer_Type Rope_Buffer
|
||||
#include "4coder_test_abstract.cpp"
|
||||
#undef Buffer_Type
|
||||
|
||||
#define print_name() printf("%s:\n", __FUNCTION__)
|
||||
|
||||
|
@ -288,22 +363,22 @@ initialization_test(Buffer_Set *set, File_Data file, int test_repitions,
|
|||
|
||||
for (int i = 0; i < test_repitions; ++i){
|
||||
tstart = get_time();
|
||||
init_buffer<Buffer_Init>(&set->buffer, file, scratch, scratch_size);
|
||||
init_buffer(&set->buffer, file, scratch, scratch_size);
|
||||
tend = get_time();
|
||||
init_time[i].buffer = tend - tstart;
|
||||
|
||||
tstart = get_time();
|
||||
init_buffer<Gap_Buffer_Init>(&set->gap_buffer, file, scratch, scratch_size);
|
||||
init_buffer(&set->gap_buffer, file, scratch, scratch_size);
|
||||
tend = get_time();
|
||||
init_time[i].gap_buffer = tend - tstart;
|
||||
|
||||
tstart = get_time();
|
||||
init_buffer<Multi_Gap_Buffer_Init>(&set->multi_gap_buffer, file, scratch, scratch_size);
|
||||
init_buffer(&set->multi_gap_buffer, file, scratch, scratch_size);
|
||||
tend = get_time();
|
||||
init_time[i].multi_gap_buffer = tend - tstart;
|
||||
|
||||
tstart = get_time();
|
||||
init_buffer<Rope_Buffer_Init>(&set->rope_buffer, file, scratch, scratch_size);
|
||||
init_buffer(&set->rope_buffer, file, scratch, scratch_size);
|
||||
tend = get_time();
|
||||
init_time[i].rope_buffer = tend - tstart;
|
||||
|
||||
|
@ -325,31 +400,10 @@ initialization_test(Buffer_Set *set, File_Data file, int test_repitions,
|
|||
test_is_silenced = 0;
|
||||
}
|
||||
|
||||
template<typename Buffer_Type> void
|
||||
measure_starts(Buffer_Type *buffer){
|
||||
int max = 1 << 10;
|
||||
buffer->line_starts = (int*)malloc(max*sizeof(int));
|
||||
buffer->line_max = max;
|
||||
|
||||
Buffer_Measure_Starts state = {};
|
||||
for (;buffer_measure_starts(&state, buffer);){
|
||||
int max = buffer->line_max;
|
||||
int count = state.count;
|
||||
int target = count + 1;
|
||||
|
||||
max = target*2;
|
||||
int *new_lines = (int*)malloc(max*sizeof(int));
|
||||
memcpy_4tech(new_lines, buffer->line_starts, count*sizeof(int));
|
||||
free(buffer->line_starts);
|
||||
buffer->line_starts = new_lines;
|
||||
buffer->line_max = max;
|
||||
}
|
||||
buffer->line_count = state.count;
|
||||
}
|
||||
|
||||
void
|
||||
measure_starts_test(Buffer_Set *set, int test_repitions,
|
||||
void *scratch, int scratch_size, Record_Statistics *stats_out){
|
||||
measure_starts_widths_test(Buffer_Set *set, int test_repitions,
|
||||
void *scratch, int scratch_size, Record_Statistics *stats_out,
|
||||
float *font_widths){
|
||||
time_int tstart, tend;
|
||||
Time_Record *measure_time = (Time_Record*)scratch;
|
||||
scratch = measure_time + test_repitions;
|
||||
|
@ -358,22 +412,22 @@ measure_starts_test(Buffer_Set *set, int test_repitions,
|
|||
|
||||
for (int i = 0; i < test_repitions; ++i){
|
||||
tstart = get_time();
|
||||
measure_starts(&set->buffer);
|
||||
measure_starts_widths(&set->buffer, font_widths);
|
||||
tend = get_time();
|
||||
measure_time[i].buffer = tend - tstart;
|
||||
|
||||
tstart = get_time();
|
||||
measure_starts(&set->gap_buffer);
|
||||
measure_starts_widths(&set->gap_buffer, font_widths);
|
||||
tend = get_time();
|
||||
measure_time[i].gap_buffer = tend - tstart;
|
||||
|
||||
tstart = get_time();
|
||||
measure_starts(&set->multi_gap_buffer);
|
||||
measure_starts_widths(&set->multi_gap_buffer, font_widths);
|
||||
tend = get_time();
|
||||
measure_time[i].multi_gap_buffer = tend - tstart;
|
||||
|
||||
tstart = get_time();
|
||||
measure_starts(&set->rope_buffer);
|
||||
measure_starts_widths(&set->rope_buffer, font_widths);
|
||||
tend = get_time();
|
||||
measure_time[i].rope_buffer = tend - tstart;
|
||||
|
||||
|
@ -382,59 +436,7 @@ measure_starts_test(Buffer_Set *set, int test_repitions,
|
|||
free(set->gap_buffer.line_starts);
|
||||
free(set->multi_gap_buffer.line_starts);
|
||||
free(set->rope_buffer.line_starts);
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_is_silenced) print_name();
|
||||
print_statistics(measure_time, test_repitions, stats_out);
|
||||
if (!test_is_silenced) printf("\n");
|
||||
test_is_silenced = 0;
|
||||
}
|
||||
|
||||
template<typename Buffer_Type> void
|
||||
measure_widths(Buffer_Type *buffer){
|
||||
int new_max = round_up_4tech(buffer->line_count, 1 << 10);
|
||||
if (new_max < (1 << 10)) new_max = 1 << 10;
|
||||
|
||||
buffer->line_widths = (float*)malloc(new_max*sizeof(float));
|
||||
buffer->widths_max = new_max;
|
||||
buffer->widths_count = 0;
|
||||
|
||||
float glyph_width = 8.f;
|
||||
buffer_measure_widths(buffer, &glyph_width, 0);
|
||||
}
|
||||
|
||||
void
|
||||
measure_widths_test(Buffer_Set *set, int test_repitions,
|
||||
void *scratch, int scratch_size, Record_Statistics *stats_out){
|
||||
time_int tstart, tend;
|
||||
Time_Record *measure_time = (Time_Record*)scratch;
|
||||
scratch = measure_time + test_repitions;
|
||||
assert_4tech(test_repitions*sizeof(*measure_time) < scratch_size);
|
||||
scratch_size -= test_repitions*sizeof(*measure_time);
|
||||
|
||||
for (int i = 0; i < test_repitions; ++i){
|
||||
tstart = get_time();
|
||||
measure_widths(&set->buffer);
|
||||
tend = get_time();
|
||||
measure_time[i].buffer = tend - tstart;
|
||||
|
||||
tstart = get_time();
|
||||
measure_widths(&set->gap_buffer);
|
||||
tend = get_time();
|
||||
measure_time[i].gap_buffer = tend - tstart;
|
||||
|
||||
tstart = get_time();
|
||||
measure_widths(&set->multi_gap_buffer);
|
||||
tend = get_time();
|
||||
measure_time[i].multi_gap_buffer = tend - tstart;
|
||||
|
||||
tstart = get_time();
|
||||
measure_widths(&set->rope_buffer);
|
||||
tend = get_time();
|
||||
measure_time[i].rope_buffer = tend - tstart;
|
||||
|
||||
if (i+1 != test_repitions){
|
||||
|
||||
free(set->buffer.line_widths);
|
||||
free(set->gap_buffer.line_widths);
|
||||
free(set->multi_gap_buffer.line_widths);
|
||||
|
@ -494,32 +496,54 @@ stream_check_test(Buffer_Set *buffers, void *scratch, int scratch_size){
|
|||
buffer_stringify(&buffers->rope_buffer, i, end, page_2);
|
||||
page_compare(page_1, page_2, page_size);
|
||||
}
|
||||
|
||||
for (i = size-1; i > 0; i -= page_size){
|
||||
int end = i - page_size;
|
||||
if (end < 0) end = 0;
|
||||
|
||||
buffer_backify(&buffers->buffer, i, end, page_1);
|
||||
|
||||
buffer_backify(&buffers->gap_buffer, i, end, page_2);
|
||||
page_compare(page_1, page_2, page_size);
|
||||
|
||||
buffer_backify(&buffers->multi_gap_buffer, i, end, page_2);
|
||||
page_compare(page_1, page_2, page_size);
|
||||
|
||||
buffer_backify(&buffers->rope_buffer, i, end, page_2);
|
||||
page_compare(page_1, page_2, page_size);
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
int main(int argc, char **argv){
|
||||
Buffer_Set buffers;
|
||||
File_Data file;
|
||||
float *widths_data;
|
||||
|
||||
void *scratch;
|
||||
int scratch_size;
|
||||
|
||||
if (argc < 2){
|
||||
printf("usage: buffer_test <filename>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
setup();
|
||||
|
||||
scratch_size = 1 << 20;
|
||||
scratch = malloc(scratch_size);
|
||||
|
||||
file = get_file("test_file_1.cpp");
|
||||
file = get_file(argv[1]);
|
||||
widths_data = get_font_data("LiberationSans-Regular.ttf");
|
||||
|
||||
Record_Statistics init_rec, starts_rec, widths_rec;
|
||||
Record_Statistics init_rec, starts_widths_rec;
|
||||
|
||||
initialization_test(&buffers, file, 100, scratch, scratch_size, &init_rec);
|
||||
stream_check_test(&buffers, scratch, scratch_size);
|
||||
|
||||
measure_starts_test(&buffers, 100, scratch, scratch_size, &starts_rec);
|
||||
measure_widths_test(&buffers, 100, scratch, scratch_size, &widths_rec);
|
||||
measure_starts_widths_test(&buffers, 100, scratch, scratch_size, &starts_widths_rec, widths_data);
|
||||
|
||||
Time_Record expected_file_open;
|
||||
expected_file_open = init_rec.expected + starts_rec.expected + widths_rec.expected;
|
||||
expected_file_open = init_rec.expected + starts_widths_rec.expected;
|
||||
|
||||
printf("average file open:\n");
|
||||
print_record(expected_file_open);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue