diff --git a/buffer/4coder_buffer_abstract.cpp b/buffer/4coder_buffer_abstract.cpp index b6bca77c..38d6d0dd 100644 --- a/buffer/4coder_buffer_abstract.cpp +++ b/buffer/4coder_buffer_abstract.cpp @@ -17,7 +17,6 @@ #define Buffer_Stringify_Type cat_4tech(Buffer_Type, _Stringify_Loop) #define Buffer_Backify_Type cat_4tech(Buffer_Type, _Backify_Loop) -#if BUFFER_EXPERIMENT_SCALPEL <= 3 inline_4tech void buffer_stringify(Buffer_Type *buffer, int start, int end, char *out){ 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); } -#endif -#if BUFFER_EXPERIMENT_SCALPEL <= 3 internal_4tech int buffer_seek_whitespace_down(Buffer_Type *buffer, int pos){ 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: return(pos); } -#endif -#if BUFFER_EXPERIMENT_SCALPEL <= 3 +#ifndef NON_ABSTRACT_4TECH typedef struct Buffer_Measure_Starts{ int i; int count; int start; } Buffer_Measure_Starts; +#endif internal_4tech int 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 (count == max){ + result = 1; + goto buffer_measure_starts_end; + } 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); return(result); } -#endif #ifndef NON_ABSTRACT_4TECH internal_4tech int @@ -852,10 +852,8 @@ cursor_seek_step_end: state->prev_cursor = prev_cursor; return(result); } - #endif -#if BUFFER_EXPERIMENT_SCALPEL <= 3 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){ @@ -941,9 +939,7 @@ buffer_cursor_from_wrapped_xy(Buffer_Type *buffer, float x, float y, int round_d return(result); } -#endif -#if BUFFER_EXPERIMENT_SCALPEL <= 3 internal_4tech void buffer_invert_edit_shift(Buffer_Type *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings, 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); } +#ifndef NON_ABSTRACT_4TECH typedef struct Buffer_Invert_Batch{ int i; int shift_amount; int len; } Buffer_Invert_Batch; +#endif internal_4tech int 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); } -#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 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, @@ -1148,7 +1127,6 @@ buffer_get_render_data_end: assert_4tech(item_i <= max); *count = item_i; } -#endif #ifndef NON_ABSTRACT_4TECH #define NON_ABSTRACT_4TECH 1 diff --git a/buffer/4coder_gap_buffer.cpp b/buffer/4coder_gap_buffer.cpp index ec838ce9..1154a569 100644 --- a/buffer/4coder_gap_buffer.cpp +++ b/buffer/4coder_gap_buffer.cpp @@ -245,7 +245,8 @@ buffer_backify_next(Gap_Buffer_Backify_Loop *loop){ } 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; int result; int size; diff --git a/buffer/4coder_golden_array.cpp b/buffer/4coder_golden_array.cpp index d351fec3..32019cb5 100644 --- a/buffer/4coder_golden_array.cpp +++ b/buffer/4coder_golden_array.cpp @@ -161,7 +161,8 @@ buffer_backify_next(Buffer_Backify_Loop *loop){ } 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; int result; int size; diff --git a/buffer/4coder_multi_gap_buffer.cpp b/buffer/4coder_multi_gap_buffer.cpp index 4c62eeaf..6c73401a 100644 --- a/buffer/4coder_multi_gap_buffer.cpp +++ b/buffer/4coder_multi_gap_buffer.cpp @@ -22,8 +22,8 @@ typedef struct Fixed_Width_Gap_Buffer{ int start_pos; } Fixed_Width_Gap_Buffer; -#define fixed_width_buffer_size Kbytes(8) -#define fixed_width_buffer_half_size Kbytes(4) +#define fixed_width_buffer_size (8 << 10) +#define fixed_width_buffer_half_size (4 << 10) typedef struct Multi_Gap_Buffer{ 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; 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 (gap->data){ @@ -225,7 +226,7 @@ buffer_stringify_loop(Multi_Gap_Buffer *buffer, int start, int end){ result.absolute_pos = 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; end -= gap->start_pos; @@ -312,7 +313,7 @@ buffer_backify_loop(Multi_Gap_Buffer *buffer, int start, int end){ result.buffer = buffer; 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); gap = result.gaps + result.chunk_end; @@ -379,7 +380,8 @@ buffer_backify_next(Multi_Gap_Buffer_Backify_Loop *loop){ } 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; char *data; int move_size; diff --git a/buffer/4coder_rope_buffer.cpp b/buffer/4coder_rope_buffer.cpp index 7660177a..2b686157 100644 --- a/buffer/4coder_rope_buffer.cpp +++ b/buffer/4coder_rope_buffer.cpp @@ -80,7 +80,7 @@ buffer_begin_init(Rope_Buffer *buffer, char *data, int size){ init.buffer = buffer; 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); @@ -90,7 +90,7 @@ buffer_begin_init(Rope_Buffer *buffer, char *data, int size){ } else{ 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); diff --git a/buffer/4coder_shared.cpp b/buffer/4coder_shared.cpp index e4fca991..4f308e50 100644 --- a/buffer/4coder_shared.cpp +++ b/buffer/4coder_shared.cpp @@ -189,7 +189,7 @@ make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height) hint.pos = starts[line_index]; hint.line = line_index + 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.wrapped_y = wrap_ys[line_index]; hint.wrapped_x = 0; @@ -350,9 +350,10 @@ internal_4tech int eol_convert_in(char *dest, char *src, int size){ int i, j; - for (i = 0, j = 0; i < size; ++i, ++j){ - if (src[i] == '\r' && i+1 < size && src[i+1] == '\n') ++i; - dest[j] = src[i]; + for (i = 0, j = 0; i < size; ++i){ + if (src[i] != '\r'){ + dest[j++] = src[i]; + } } return(j); @@ -360,16 +361,15 @@ eol_convert_in(char *dest, char *src, int size){ internal_4tech int eol_in_place_convert_in(char *data, int size){ - int i; + int i, j; - for (i = 0; i < size; ++i){ - if (data[i] == '\r' && i+1 < size && data[i+1] == '\n'){ - memmove_4tech(data + i, data + i + 1, size - i); - size -= 1; + for (i = 0, j = 0; i < size; ++i){ + if (data[i] != '\r'){ + data[j++] = data[i]; } } - return(size); + return(j); } internal_4tech int diff --git a/buffer/4coder_test_main.cpp b/buffer/4coder_test_main.cpp new file mode 100644 index 00000000..3f7789ca --- /dev/null +++ b/buffer/4coder_test_main.cpp @@ -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 +#include +#include +#include + +#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 + +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 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(&set->buffer, file, scratch, scratch_size); + tend = get_time(); + init_time[i].buffer = tend - tstart; + + tstart = get_time(); + init_buffer(&set->gap_buffer, file, scratch, scratch_size); + tend = get_time(); + init_time[i].gap_buffer = tend - tstart; + + tstart = get_time(); + 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(&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 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 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 +