bug fixes
This commit is contained in:
parent
813e878a9b
commit
774c8daaff
|
@ -17,7 +17,6 @@
|
||||||
#define Buffer_Stringify_Type cat_4tech(Buffer_Type, _Stringify_Loop)
|
#define Buffer_Stringify_Type cat_4tech(Buffer_Type, _Stringify_Loop)
|
||||||
#define Buffer_Backify_Type cat_4tech(Buffer_Type, _Backify_Loop)
|
#define Buffer_Backify_Type cat_4tech(Buffer_Type, _Backify_Loop)
|
||||||
|
|
||||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
|
||||||
inline_4tech void
|
inline_4tech void
|
||||||
buffer_stringify(Buffer_Type *buffer, int start, int end, char *out){
|
buffer_stringify(Buffer_Type *buffer, int start, int end, char *out){
|
||||||
for (Buffer_Stringify_Type loop = buffer_stringify_loop(buffer, start, end);
|
for (Buffer_Stringify_Type loop = buffer_stringify_loop(buffer, start, end);
|
||||||
|
@ -70,9 +69,7 @@ buffer_count_newlines(Buffer_Type *buffer, int start, int end){
|
||||||
|
|
||||||
return(count);
|
return(count);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
buffer_seek_whitespace_down(Buffer_Type *buffer, int pos){
|
buffer_seek_whitespace_down(Buffer_Type *buffer, int pos){
|
||||||
Buffer_Stringify_Type loop;
|
Buffer_Stringify_Type loop;
|
||||||
|
@ -477,14 +474,14 @@ buffer_rfind_string(Buffer_Type *buffer, int start_pos, char *str, int len, char
|
||||||
buffer_rfind_string_end:
|
buffer_rfind_string_end:
|
||||||
return(pos);
|
return(pos);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
#ifndef NON_ABSTRACT_4TECH
|
||||||
typedef struct Buffer_Measure_Starts{
|
typedef struct Buffer_Measure_Starts{
|
||||||
int i;
|
int i;
|
||||||
int count;
|
int count;
|
||||||
int start;
|
int start;
|
||||||
} Buffer_Measure_Starts;
|
} Buffer_Measure_Starts;
|
||||||
|
#endif
|
||||||
|
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
||||||
|
@ -525,6 +522,10 @@ buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == size){
|
if (i == size){
|
||||||
|
if (count == max){
|
||||||
|
result = 1;
|
||||||
|
goto buffer_measure_starts_end;
|
||||||
|
}
|
||||||
starts[count++] = start;
|
starts[count++] = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,7 +717,6 @@ buffer_get_line_index(Buffer_Type *buffer, int pos){
|
||||||
result = buffer_get_line_index_range(buffer, pos, 0, buffer->line_count);
|
result = buffer_get_line_index_range(buffer, pos, 0, buffer->line_count);
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NON_ABSTRACT_4TECH
|
#ifndef NON_ABSTRACT_4TECH
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
|
@ -852,10 +852,8 @@ cursor_seek_step_end:
|
||||||
state->prev_cursor = prev_cursor;
|
state->prev_cursor = prev_cursor;
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
|
||||||
internal_4tech Full_Cursor
|
internal_4tech Full_Cursor
|
||||||
buffer_cursor_seek(Buffer_Type *buffer, Buffer_Seek seek, float max_width, float font_height,
|
buffer_cursor_seek(Buffer_Type *buffer, Buffer_Seek seek, float max_width, float font_height,
|
||||||
void *advance_data, int stride, Full_Cursor cursor){
|
void *advance_data, int stride, Full_Cursor cursor){
|
||||||
|
@ -941,9 +939,7 @@ buffer_cursor_from_wrapped_xy(Buffer_Type *buffer, float x, float y, int round_d
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
|
||||||
internal_4tech void
|
internal_4tech void
|
||||||
buffer_invert_edit_shift(Buffer_Type *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings,
|
buffer_invert_edit_shift(Buffer_Type *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings,
|
||||||
int *str_pos, int max, int shift_amount){
|
int *str_pos, int max, int shift_amount){
|
||||||
|
@ -968,11 +964,13 @@ buffer_invert_edit(Buffer_Type *buffer, Buffer_Edit edit, Buffer_Edit *inverse,
|
||||||
buffer_invert_edit_shift(buffer, edit, inverse, strings, str_pos, max, 0);
|
buffer_invert_edit_shift(buffer, edit, inverse, strings, str_pos, max, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NON_ABSTRACT_4TECH
|
||||||
typedef struct Buffer_Invert_Batch{
|
typedef struct Buffer_Invert_Batch{
|
||||||
int i;
|
int i;
|
||||||
int shift_amount;
|
int shift_amount;
|
||||||
int len;
|
int len;
|
||||||
} Buffer_Invert_Batch;
|
} Buffer_Invert_Batch;
|
||||||
|
#endif
|
||||||
|
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
buffer_invert_batch(Buffer_Invert_Batch *state, Buffer_Type *buffer, Buffer_Edit *edits, int count,
|
buffer_invert_batch(Buffer_Invert_Batch *state, Buffer_Type *buffer, Buffer_Edit *edits, int count,
|
||||||
|
@ -1005,26 +1003,7 @@ buffer_invert_batch(Buffer_Invert_Batch *state, Buffer_Type *buffer, Buffer_Edit
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
|
||||||
internal_4tech void
|
|
||||||
buffer_batch_edit(Buffer_Type *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count){
|
|
||||||
Buffer_Batch_State state;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
debug_4tech(int result);
|
|
||||||
|
|
||||||
state.i = 0;
|
|
||||||
state.shift_total = 0;
|
|
||||||
|
|
||||||
debug_4tech(result =)
|
|
||||||
buffer_batch_edit_step(&state, buffer, sorted_edits, strings, edit_count, &r);
|
|
||||||
assert_4tech(result == 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
|
||||||
internal_4tech void
|
internal_4tech void
|
||||||
buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *items, int max, int *count,
|
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 port_x, float port_y, float scroll_x, float scroll_y, int wrapped,
|
||||||
|
@ -1148,7 +1127,6 @@ buffer_get_render_data_end:
|
||||||
assert_4tech(item_i <= max);
|
assert_4tech(item_i <= max);
|
||||||
*count = item_i;
|
*count = item_i;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NON_ABSTRACT_4TECH
|
#ifndef NON_ABSTRACT_4TECH
|
||||||
#define NON_ABSTRACT_4TECH 1
|
#define NON_ABSTRACT_4TECH 1
|
||||||
|
|
|
@ -245,7 +245,8 @@ buffer_backify_next(Gap_Buffer_Backify_Loop *loop){
|
||||||
}
|
}
|
||||||
|
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount, int *request_amount){
|
buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount,
|
||||||
|
void *scratch, int scratch_memory, int *request_amount){
|
||||||
char *data;
|
char *data;
|
||||||
int result;
|
int result;
|
||||||
int size;
|
int size;
|
||||||
|
|
|
@ -161,7 +161,8 @@ buffer_backify_next(Buffer_Backify_Loop *loop){
|
||||||
}
|
}
|
||||||
|
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int *shift_amount, int *request_amount){
|
buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int *shift_amount,
|
||||||
|
void *scratch, int scratch_size, int *request_amount){
|
||||||
char *data;
|
char *data;
|
||||||
int result;
|
int result;
|
||||||
int size;
|
int size;
|
||||||
|
|
|
@ -22,8 +22,8 @@ typedef struct Fixed_Width_Gap_Buffer{
|
||||||
int start_pos;
|
int start_pos;
|
||||||
} Fixed_Width_Gap_Buffer;
|
} Fixed_Width_Gap_Buffer;
|
||||||
|
|
||||||
#define fixed_width_buffer_size Kbytes(8)
|
#define fixed_width_buffer_size (8 << 10)
|
||||||
#define fixed_width_buffer_half_size Kbytes(4)
|
#define fixed_width_buffer_half_size (4 << 10)
|
||||||
|
|
||||||
typedef struct Multi_Gap_Buffer{
|
typedef struct Multi_Gap_Buffer{
|
||||||
Fixed_Width_Gap_Buffer *gaps;
|
Fixed_Width_Gap_Buffer *gaps;
|
||||||
|
@ -142,6 +142,7 @@ buffer_end_init(Multi_Gap_Buffer_Init *init, void *scratch, int scratch_size){
|
||||||
start_pos = 0;
|
start_pos = 0;
|
||||||
|
|
||||||
for (i = 0; i < count; ++i, ++gap, pos += size){
|
for (i = 0; i < count; ++i, ++gap, pos += size){
|
||||||
|
assert_4tech(size == fixed_width_buffer_half_size);
|
||||||
if (pos + size > total_size) size = total_size - pos;
|
if (pos + size > total_size) size = total_size - pos;
|
||||||
|
|
||||||
if (gap->data){
|
if (gap->data){
|
||||||
|
@ -225,7 +226,7 @@ buffer_stringify_loop(Multi_Gap_Buffer *buffer, int start, int end){
|
||||||
result.absolute_pos = start;
|
result.absolute_pos = start;
|
||||||
|
|
||||||
result.chunk_i = buffer_find_chunk(buffer, start);
|
result.chunk_i = buffer_find_chunk(buffer, start);
|
||||||
result.chunk_end = buffer_find_chunk(buffer, end-1);
|
result.chunk_end = buffer_find_chunk(buffer, end);
|
||||||
|
|
||||||
gap = result.gaps + result.chunk_end;
|
gap = result.gaps + result.chunk_end;
|
||||||
end -= gap->start_pos;
|
end -= gap->start_pos;
|
||||||
|
@ -312,7 +313,7 @@ buffer_backify_loop(Multi_Gap_Buffer *buffer, int start, int end){
|
||||||
result.buffer = buffer;
|
result.buffer = buffer;
|
||||||
result.gaps = buffer->gaps;
|
result.gaps = buffer->gaps;
|
||||||
|
|
||||||
result.chunk_i = buffer_find_chunk(buffer, start-1);
|
result.chunk_i = buffer_find_chunk(buffer, start);
|
||||||
result.chunk_end = buffer_find_chunk(buffer, end);
|
result.chunk_end = buffer_find_chunk(buffer, end);
|
||||||
|
|
||||||
gap = result.gaps + result.chunk_end;
|
gap = result.gaps + result.chunk_end;
|
||||||
|
@ -379,7 +380,8 @@ buffer_backify_next(Multi_Gap_Buffer_Backify_Loop *loop){
|
||||||
}
|
}
|
||||||
|
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount_out, int *request_amount){
|
buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount_out,
|
||||||
|
void *scratch, int scratch_size, int *request_amount){
|
||||||
Fixed_Width_Gap_Buffer *gaps, *gap, *dgap;
|
Fixed_Width_Gap_Buffer *gaps, *gap, *dgap;
|
||||||
char *data;
|
char *data;
|
||||||
int move_size;
|
int move_size;
|
||||||
|
|
|
@ -80,7 +80,7 @@ buffer_begin_init(Rope_Buffer *buffer, char *data, int size){
|
||||||
|
|
||||||
init.buffer = buffer;
|
init.buffer = buffer;
|
||||||
init.data = data;
|
init.data = data;
|
||||||
init.size = size;
|
init.size = eol_in_place_convert_in(data, size);
|
||||||
|
|
||||||
init.node_count = div_ceil_4tech(size, rope_string_width);
|
init.node_count = div_ceil_4tech(size, rope_string_width);
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ buffer_begin_init(Rope_Buffer *buffer, char *data, int size){
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
init.rope_string_count = round_pot_4tech(init.node_count);
|
init.rope_string_count = round_pot_4tech(init.node_count);
|
||||||
init.node_count = init.rope_string_count*2 - 1;
|
init.node_count = init.rope_string_count*2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(init);
|
return(init);
|
||||||
|
|
|
@ -189,7 +189,7 @@ make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height)
|
||||||
hint.pos = starts[line_index];
|
hint.pos = starts[line_index];
|
||||||
hint.line = line_index + 1;
|
hint.line = line_index + 1;
|
||||||
hint.character = 1;
|
hint.character = 1;
|
||||||
hint.unwrapped_y = (f32)(line_index * font_height);
|
hint.unwrapped_y = (float)(line_index * font_height);
|
||||||
hint.unwrapped_x = 0;
|
hint.unwrapped_x = 0;
|
||||||
hint.wrapped_y = wrap_ys[line_index];
|
hint.wrapped_y = wrap_ys[line_index];
|
||||||
hint.wrapped_x = 0;
|
hint.wrapped_x = 0;
|
||||||
|
@ -350,9 +350,10 @@ internal_4tech int
|
||||||
eol_convert_in(char *dest, char *src, int size){
|
eol_convert_in(char *dest, char *src, int size){
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (i = 0, j = 0; i < size; ++i, ++j){
|
for (i = 0, j = 0; i < size; ++i){
|
||||||
if (src[i] == '\r' && i+1 < size && src[i+1] == '\n') ++i;
|
if (src[i] != '\r'){
|
||||||
dest[j] = src[i];
|
dest[j++] = src[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(j);
|
return(j);
|
||||||
|
@ -360,16 +361,15 @@ eol_convert_in(char *dest, char *src, int size){
|
||||||
|
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
eol_in_place_convert_in(char *data, int size){
|
eol_in_place_convert_in(char *data, int size){
|
||||||
int i;
|
int i, j;
|
||||||
|
|
||||||
for (i = 0; i < size; ++i){
|
for (i = 0, j = 0; i < size; ++i){
|
||||||
if (data[i] == '\r' && i+1 < size && data[i+1] == '\n'){
|
if (data[i] != '\r'){
|
||||||
memmove_4tech(data + i, data + i + 1, size - i);
|
data[j++] = data[i];
|
||||||
size -= 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(size);
|
return(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
|
|
|
@ -0,0 +1,531 @@
|
||||||
|
/*
|
||||||
|
* Mr. 4th Dimention - Allen Webster
|
||||||
|
* Four Tech
|
||||||
|
*
|
||||||
|
* public domain -- no warranty is offered or implied; use this code at your own risk
|
||||||
|
*
|
||||||
|
* 06.11.2015
|
||||||
|
*
|
||||||
|
* Buffer experiment testing layer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TOP
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define inline_4tech inline
|
||||||
|
|
||||||
|
inline_4tech int
|
||||||
|
CEIL32(float x){
|
||||||
|
int extra;
|
||||||
|
extra = ((x!=(int)(x) && x>0)?1:0);
|
||||||
|
extra += (int)(x);
|
||||||
|
return(extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech int
|
||||||
|
DIVCEIL32(int n, int d) {
|
||||||
|
int q = (n/d);
|
||||||
|
q += (q*d < n);
|
||||||
|
return(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech unsigned int
|
||||||
|
ROUNDPOT32(unsigned int v){
|
||||||
|
v--;
|
||||||
|
v |= v >> 1;
|
||||||
|
v |= v >> 2;
|
||||||
|
v |= v >> 4;
|
||||||
|
v |= v >> 8;
|
||||||
|
v |= v >> 16;
|
||||||
|
v++;
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef fast_test
|
||||||
|
#define debug_4tech(x)
|
||||||
|
#define assert_4tech(x)
|
||||||
|
#endif
|
||||||
|
#define hard_assert_4tech(x) assert(x)
|
||||||
|
|
||||||
|
#include "4coder_shared.cpp"
|
||||||
|
#include "4coder_golden_array.cpp"
|
||||||
|
#include "4coder_gap_buffer.cpp"
|
||||||
|
#include "4coder_multi_gap_buffer.cpp"
|
||||||
|
#include "4coder_rope_buffer.cpp"
|
||||||
|
|
||||||
|
#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
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
typedef unsigned long long time_int;
|
||||||
|
|
||||||
|
unsigned long long win32_counts_per_second_4tech;
|
||||||
|
|
||||||
|
int time_init(unsigned long long *resolution){
|
||||||
|
int result;
|
||||||
|
LARGE_INTEGER time;
|
||||||
|
result = 0;
|
||||||
|
if (QueryPerformanceFrequency(&time)){
|
||||||
|
win32_counts_per_second_4tech = (unsigned long long)(time.QuadPart);
|
||||||
|
result = 1;
|
||||||
|
*resolution = win32_counts_per_second_4tech;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
time_int get_time(){
|
||||||
|
LARGE_INTEGER time;
|
||||||
|
time_int result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
if (QueryPerformanceCounter(&time)){
|
||||||
|
result = (time_int)(time.QuadPart);
|
||||||
|
result = result * 1000000 / win32_counts_per_second_4tech;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error Timer not supported by this platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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 File_Data{
|
||||||
|
char *data;
|
||||||
|
int size;
|
||||||
|
} File_Data;
|
||||||
|
|
||||||
|
File_Data get_file(char *filename){
|
||||||
|
FILE *file;
|
||||||
|
File_Data result;
|
||||||
|
|
||||||
|
file = fopen(filename, "rb");
|
||||||
|
if (!file){
|
||||||
|
printf("error: could not find file %s\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
result.size = ftell(file);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (result.size == 0){
|
||||||
|
printf("error: file %s was empty\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.data = (char*)malloc(result.size);
|
||||||
|
fread(result.data, result.size, 1, file);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_file(File_Data file){
|
||||||
|
free(file.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct Time_Record{
|
||||||
|
time_int buffer;
|
||||||
|
time_int gap_buffer;
|
||||||
|
time_int multi_gap_buffer;
|
||||||
|
time_int rope_buffer;
|
||||||
|
} Time_Record;
|
||||||
|
|
||||||
|
typedef struct Record_Statistics{
|
||||||
|
Time_Record max, min;
|
||||||
|
Time_Record expected;
|
||||||
|
int count;
|
||||||
|
} Record_Statistics;
|
||||||
|
|
||||||
|
Time_Record
|
||||||
|
operator+(const Time_Record &a, const Time_Record &b){
|
||||||
|
Time_Record r;
|
||||||
|
r.buffer = a.buffer + b.buffer;
|
||||||
|
r.gap_buffer = a.gap_buffer + b.gap_buffer;
|
||||||
|
r.multi_gap_buffer = a.multi_gap_buffer + b.multi_gap_buffer;
|
||||||
|
r.rope_buffer = a.rope_buffer + b.rope_buffer;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define minify(a,b) if ((a)>(b)) (a) = (b)
|
||||||
|
#define maxify(a,b) if ((a)<(b)) (a) = (b)
|
||||||
|
|
||||||
|
void
|
||||||
|
get_record_statistics(Record_Statistics *stats_out, Time_Record *records, int count){
|
||||||
|
Record_Statistics stats;
|
||||||
|
stats.max = records[0];
|
||||||
|
stats.min = records[0];
|
||||||
|
stats.expected = records[0];
|
||||||
|
stats.count = count;
|
||||||
|
|
||||||
|
Time_Record *record = records + 1;
|
||||||
|
|
||||||
|
for (int i = 1; i < count; ++i, ++record){
|
||||||
|
stats.expected = stats.expected + *record;
|
||||||
|
|
||||||
|
minify(stats.min.buffer, record->buffer);
|
||||||
|
minify(stats.min.gap_buffer, record->gap_buffer);
|
||||||
|
minify(stats.min.multi_gap_buffer, record->multi_gap_buffer);
|
||||||
|
minify(stats.min.rope_buffer, record->rope_buffer);
|
||||||
|
|
||||||
|
maxify(stats.max.buffer, record->buffer);
|
||||||
|
maxify(stats.max.gap_buffer, record->gap_buffer);
|
||||||
|
maxify(stats.max.multi_gap_buffer, record->multi_gap_buffer);
|
||||||
|
maxify(stats.max.rope_buffer, record->rope_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
stats.expected.buffer /= count;
|
||||||
|
stats.expected.gap_buffer /= count;
|
||||||
|
stats.expected.multi_gap_buffer /= count;
|
||||||
|
stats.expected.rope_buffer /= count;
|
||||||
|
|
||||||
|
*stats_out = stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_is_silenced;
|
||||||
|
|
||||||
|
void
|
||||||
|
silence_test(){
|
||||||
|
test_is_silenced = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_record(Time_Record record){
|
||||||
|
printf("%-16s - %25lluus\n%-16s - %25lluus\n%-16s - %25lluus\n%-16s - %25lluus\n",
|
||||||
|
"Golden Array", record.buffer,
|
||||||
|
"Gap Buffer", record.gap_buffer,
|
||||||
|
"Multi-Gap Buffer", record.multi_gap_buffer,
|
||||||
|
"Rope", record.rope_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_statistics(Time_Record *records, int count, Record_Statistics *stats_out){
|
||||||
|
Record_Statistics stats;
|
||||||
|
get_record_statistics(&stats, records, count);
|
||||||
|
if (!test_is_silenced){
|
||||||
|
printf("samples: %d\n", count);
|
||||||
|
printf("---averages---\n");
|
||||||
|
print_record(stats.expected);
|
||||||
|
printf("---max---\n");
|
||||||
|
print_record(stats.max);
|
||||||
|
printf("---min---\n");
|
||||||
|
print_record(stats.min);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats_out) *stats_out = stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct Buffer_Set{
|
||||||
|
Buffer buffer;
|
||||||
|
Gap_Buffer gap_buffer;
|
||||||
|
Multi_Gap_Buffer multi_gap_buffer;
|
||||||
|
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 print_name() printf("%s:\n", __FUNCTION__)
|
||||||
|
|
||||||
|
void
|
||||||
|
initialization_test(Buffer_Set *set, File_Data file, int test_repitions,
|
||||||
|
void *scratch, int scratch_size, Record_Statistics *stats_out){
|
||||||
|
time_int tstart, tend;
|
||||||
|
Time_Record *init_time = (Time_Record*)scratch;
|
||||||
|
scratch = init_time + test_repitions;
|
||||||
|
assert_4tech(test_repitions*sizeof(*init_time) < scratch_size);
|
||||||
|
scratch_size -= test_repitions*sizeof(*init_time);
|
||||||
|
|
||||||
|
for (int i = 0; i < test_repitions; ++i){
|
||||||
|
tstart = get_time();
|
||||||
|
init_buffer<Buffer_Init>(&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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
tend = get_time();
|
||||||
|
init_time[i].rope_buffer = tend - tstart;
|
||||||
|
|
||||||
|
if (i+1 != test_repitions){
|
||||||
|
free(set->buffer.data);
|
||||||
|
free(set->gap_buffer.data);
|
||||||
|
for (int j = 0; j < set->multi_gap_buffer.chunk_alloced; ++j){
|
||||||
|
free(set->multi_gap_buffer.gaps[j].data);
|
||||||
|
}
|
||||||
|
free(set->multi_gap_buffer.gaps);
|
||||||
|
free(set->rope_buffer.data);
|
||||||
|
free(set->rope_buffer.nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!test_is_silenced) print_name();
|
||||||
|
print_statistics(init_time, test_repitions, stats_out);
|
||||||
|
if (!test_is_silenced) printf("\n");
|
||||||
|
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){
|
||||||
|
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_starts(&set->buffer);
|
||||||
|
tend = get_time();
|
||||||
|
measure_time[i].buffer = tend - tstart;
|
||||||
|
|
||||||
|
tstart = get_time();
|
||||||
|
measure_starts(&set->gap_buffer);
|
||||||
|
tend = get_time();
|
||||||
|
measure_time[i].gap_buffer = tend - tstart;
|
||||||
|
|
||||||
|
tstart = get_time();
|
||||||
|
measure_starts(&set->multi_gap_buffer);
|
||||||
|
tend = get_time();
|
||||||
|
measure_time[i].multi_gap_buffer = tend - tstart;
|
||||||
|
|
||||||
|
tstart = get_time();
|
||||||
|
measure_starts(&set->rope_buffer);
|
||||||
|
tend = get_time();
|
||||||
|
measure_time[i].rope_buffer = tend - tstart;
|
||||||
|
|
||||||
|
if (i+1 != test_repitions){
|
||||||
|
free(set->buffer.line_starts);
|
||||||
|
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);
|
||||||
|
free(set->rope_buffer.line_widths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!test_is_silenced) print_name();
|
||||||
|
print_statistics(measure_time, test_repitions, stats_out);
|
||||||
|
if (!test_is_silenced) printf("\n");
|
||||||
|
test_is_silenced = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
page_compare(char *page_1, char *page_2, int page_size){
|
||||||
|
int result = 1;
|
||||||
|
for (int i = 0; i < page_size; ++i){
|
||||||
|
hard_assert_4tech(page_1[i] == page_2[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stream_check_test(Buffer_Set *buffers, void *scratch, int scratch_size){
|
||||||
|
int i, page_size, size;
|
||||||
|
|
||||||
|
size = buffer_size(&buffers->buffer);
|
||||||
|
{
|
||||||
|
int size2;
|
||||||
|
size2 = buffer_size(&buffers->gap_buffer);
|
||||||
|
hard_assert_4tech(size == size2);
|
||||||
|
size2 = buffer_size(&buffers->multi_gap_buffer);
|
||||||
|
hard_assert_4tech(size == size2);
|
||||||
|
size2 = buffer_size(&buffers->rope_buffer);
|
||||||
|
hard_assert_4tech(size == size2);
|
||||||
|
}
|
||||||
|
|
||||||
|
page_size = 1 << 10;
|
||||||
|
|
||||||
|
char *page_1 = (char*)scratch;
|
||||||
|
char *page_2 = page_1 + page_size;
|
||||||
|
scratch_size -= page_size*2;
|
||||||
|
hard_assert_4tech(scratch_size > 0);
|
||||||
|
|
||||||
|
for (i = 0; i < size; i += page_size){
|
||||||
|
int end = i + page_size;
|
||||||
|
if (end > size) end = size;
|
||||||
|
|
||||||
|
buffer_stringify(&buffers->buffer, i, end, page_1);
|
||||||
|
|
||||||
|
buffer_stringify(&buffers->gap_buffer, i, end, page_2);
|
||||||
|
page_compare(page_1, page_2, page_size);
|
||||||
|
|
||||||
|
buffer_stringify(&buffers->multi_gap_buffer, i, end, page_2);
|
||||||
|
page_compare(page_1, page_2, page_size);
|
||||||
|
|
||||||
|
buffer_stringify(&buffers->rope_buffer, i, end, page_2);
|
||||||
|
page_compare(page_1, page_2, page_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
Buffer_Set buffers;
|
||||||
|
File_Data file;
|
||||||
|
|
||||||
|
void *scratch;
|
||||||
|
int scratch_size;
|
||||||
|
|
||||||
|
setup();
|
||||||
|
|
||||||
|
scratch_size = 1 << 20;
|
||||||
|
scratch = malloc(scratch_size);
|
||||||
|
|
||||||
|
file = get_file("test_file_1.cpp");
|
||||||
|
|
||||||
|
Record_Statistics init_rec, starts_rec, 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);
|
||||||
|
|
||||||
|
Time_Record expected_file_open;
|
||||||
|
expected_file_open = init_rec.expected + starts_rec.expected + widths_rec.expected;
|
||||||
|
|
||||||
|
printf("average file open:\n");
|
||||||
|
print_record(expected_file_open);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOTTOM
|
||||||
|
|
Loading…
Reference in New Issue