full data gathering
parent
dcdec287a1
commit
fb4a86058a
|
@ -985,6 +985,23 @@ buffer_cursor_from_pos(Buffer_Type *buffer, int pos, float *wraps,
|
|||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech Full_Cursor
|
||||
buffer_cursor_from_line_character(Buffer_Type *buffer, int line, int character, float *wraps,
|
||||
float max_width, float font_height, float *advance_data){
|
||||
Full_Cursor result;
|
||||
int line_index;
|
||||
|
||||
line_index = line - 1;
|
||||
if (line_index >= buffer->line_count) line_index = buffer->line_count - 1;
|
||||
if (line_index < 0) line_index = 0;
|
||||
|
||||
result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height);
|
||||
result = buffer_cursor_seek(buffer, seek_line_char(line, character),
|
||||
max_width, font_height, 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, float *advance_data){
|
||||
|
@ -996,8 +1013,8 @@ buffer_cursor_from_unwrapped_xy(Buffer_Type *buffer, float x, float y, int round
|
|||
if (line_index < 0) line_index = 0;
|
||||
|
||||
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, result);
|
||||
result = buffer_cursor_seek(buffer, seek_unwrapped_xy(x, y, round_down),
|
||||
max_width, font_height, advance_data, result);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
@ -1010,8 +1027,8 @@ buffer_cursor_from_wrapped_xy(Buffer_Type *buffer, float x, float y, int round_d
|
|||
|
||||
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, result);
|
||||
result = buffer_cursor_seek(buffer, seek_wrapped_xy(x, y, round_down),
|
||||
max_width, font_height, advance_data, result);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#define external_name "awebster_windows"
|
|
@ -1,67 +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
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#include "4coder_external_name.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
@ -78,6 +80,51 @@ ROUNDPOT32(unsigned int v){
|
|||
#include "4coder_buffer_abstract.cpp"
|
||||
#undef Buffer_Type
|
||||
|
||||
int int_into_str(char *out, int *rem, unsigned int x){
|
||||
char *start = out;
|
||||
int size = *rem;
|
||||
int result;
|
||||
char t;
|
||||
|
||||
if (x == 0 && size > 1){
|
||||
*out = '0';
|
||||
++out;
|
||||
--size;
|
||||
}
|
||||
else{
|
||||
for (;x > 0 && size > 1;--size, ++out){
|
||||
*out = (x%10 + '0');
|
||||
x /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
*rem = size;
|
||||
*out = 0;
|
||||
|
||||
result = (int)(out - start);
|
||||
|
||||
--out;
|
||||
for (; start < out; ++start, --out){
|
||||
t = *out;
|
||||
*out = *start;
|
||||
*start = t;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
int uscore_into_str(char *out, int *rem){
|
||||
int result;
|
||||
result = 0;
|
||||
if (*rem > 1){
|
||||
--*rem;
|
||||
*out++ = '_';
|
||||
*out = 0;
|
||||
result = 1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
|
||||
|
@ -110,6 +157,33 @@ time_int get_time(){
|
|||
return(result);
|
||||
}
|
||||
|
||||
void time_into_str(char *out, int max){
|
||||
SYSTEMTIME systime;
|
||||
int pos;
|
||||
|
||||
GetSystemTime(&systime);
|
||||
pos = uscore_into_str(out, &max);
|
||||
pos += int_into_str(out + pos, &max, systime.wYear);
|
||||
|
||||
pos += uscore_into_str(out + pos, &max);
|
||||
pos += int_into_str(out + pos, &max, systime.wMonth);
|
||||
|
||||
pos += uscore_into_str(out + pos, &max);
|
||||
pos += int_into_str(out + pos, &max, systime.wDay);
|
||||
|
||||
pos += uscore_into_str(out + pos, &max);
|
||||
pos += int_into_str(out + pos, &max, systime.wHour);
|
||||
|
||||
pos += uscore_into_str(out + pos, &max);
|
||||
pos += int_into_str(out + pos, &max, systime.wMinute);
|
||||
|
||||
pos += uscore_into_str(out + pos, &max);
|
||||
pos += int_into_str(out + pos, &max, systime.wSecond);
|
||||
|
||||
pos += uscore_into_str(out + pos, &max);
|
||||
pos += int_into_str(out + pos, &max, systime.wMilliseconds);
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
#include <time.h>
|
||||
|
||||
|
@ -184,36 +258,40 @@ void free_file(File_Data file){
|
|||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "stb_truetype.h"
|
||||
|
||||
float* get_font_data(const char *font_file){
|
||||
float* get_font_data(const char *font_file, float *font_height){
|
||||
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);
|
||||
stbtt_fontinfo font;
|
||||
if (stbtt_InitFont(&font, (unsigned char*)file.data, 0)){
|
||||
float scale;
|
||||
int a,d,g;
|
||||
|
||||
scale = stbtt_ScaleForPixelHeight(&font, 17.f);
|
||||
stbtt_GetFontVMetrics(&font, &a, &d, &g);
|
||||
*font_height = scale*(a - d + g);
|
||||
|
||||
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;
|
||||
data = (float*)malloc(sizeof(float)*256);
|
||||
memset_4tech(data, 0, sizeof(float)*256);
|
||||
|
||||
stbtt_bakedchar *baked_ptr = baked;
|
||||
for (int i = 0; i < 128; ++i, ++baked_ptr){
|
||||
data[i] = baked_ptr->xadvance;
|
||||
}
|
||||
}
|
||||
free(baked);
|
||||
}
|
||||
|
@ -249,6 +327,187 @@ typedef struct Record_Statistics{
|
|||
int count;
|
||||
} Record_Statistics;
|
||||
|
||||
typedef struct Log_Section{
|
||||
int *counter;
|
||||
} Log_Section;
|
||||
|
||||
typedef struct Stats_Log{
|
||||
char *out;
|
||||
int size, max;
|
||||
|
||||
Log_Section *sections;
|
||||
int sec_top, sec_max;
|
||||
|
||||
unsigned int error;
|
||||
} Stats_Log;
|
||||
|
||||
#define log_er_buffer_overflow 0x1
|
||||
#define log_er_stack_overflow 0x2
|
||||
#define log_er_stack_underflow 0x4
|
||||
#define log_er_time_too_large 0x8
|
||||
|
||||
#define logid_begin_section 0
|
||||
#define logid_data_item 1
|
||||
|
||||
#if fast_test
|
||||
#define use_stats_log 1
|
||||
#else
|
||||
#define use_stats_log 0
|
||||
#endif
|
||||
|
||||
void
|
||||
log_write_int(Stats_Log *log, int x){
|
||||
#if use_stats_log
|
||||
if (log->error == 0){
|
||||
if (log->size+4 <= log->max){
|
||||
*(int*)(log->out + log->size) = x;
|
||||
log->size += 4;
|
||||
}
|
||||
else{
|
||||
log->error |= log_er_buffer_overflow;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
log_write_time(Stats_Log *log, time_int x){
|
||||
#if use_stats_log
|
||||
if (log->error == 0){
|
||||
if (x < 0x7FFFFFFF){
|
||||
if (log->size+4 <= log->max){
|
||||
*(int*)(log->out + log->size) = (int)x;
|
||||
log->size += 4;
|
||||
}
|
||||
else{
|
||||
log->error |= log_er_buffer_overflow;
|
||||
}
|
||||
}
|
||||
else{
|
||||
log->error |= log_er_time_too_large;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
log_write_str(Stats_Log *log, char *str, int len){
|
||||
#if use_stats_log
|
||||
int up = (len + 3) & ~3;
|
||||
if (log->error == 0){
|
||||
if (log->size+4+up <= log->max){
|
||||
*(int*)(log->out + log->size) = up;
|
||||
memcpy_4tech(log->out + log->size + 4, str, len);
|
||||
log->size += 4+up;
|
||||
}
|
||||
else{
|
||||
log->error |= log_er_buffer_overflow;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
log_begin_section(Stats_Log *log, char *name, int name_len){
|
||||
#if use_stats_log
|
||||
Log_Section *section;
|
||||
if (log->error == 0){
|
||||
if (log->sec_top < log->sec_max){
|
||||
if (log->sec_top > 0){
|
||||
section = log->sections + log->sec_top - 1;
|
||||
++section->counter;
|
||||
}
|
||||
|
||||
section = log->sections + (log->sec_top++);
|
||||
|
||||
log_write_int(log, logid_begin_section);
|
||||
log_write_str(log, name, name_len);
|
||||
|
||||
section->counter = (int*)(log->out + log->size);
|
||||
log_write_int(log, 0);
|
||||
}
|
||||
else{
|
||||
log->error |= log_er_stack_overflow;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
log_end_section(Stats_Log *log){
|
||||
#if use_stats_log
|
||||
if (log->error == 0){
|
||||
if (log->sec_top > 0){
|
||||
--log->sec_top;
|
||||
}
|
||||
else{
|
||||
log->error |= log_er_stack_underflow;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
log_data_item(Stats_Log *log, char *name, int name_len, time_int t){
|
||||
#if use_stats_log
|
||||
Log_Section *section;
|
||||
if (log->error == 0){
|
||||
if (log->sec_top > 0){
|
||||
section = log->sections + log->sec_top - 1;
|
||||
++section->counter;
|
||||
}
|
||||
|
||||
log_write_int(log, logid_data_item);
|
||||
log_write_str(log, name, name_len);
|
||||
log_write_time(log, t);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
log_finish(Stats_Log *log){
|
||||
#if use_stats_log
|
||||
assert_4tech(sizeof(external_name) < 512);
|
||||
if (log->error == 0){
|
||||
char fname[1024];
|
||||
memcpy_4tech(fname, "out/", 4);
|
||||
memcpy_4tech(fname + 4, external_name, sizeof(external_name)-1);
|
||||
time_into_str(fname + 4 + sizeof(external_name) - 1, 1023 - sizeof(external_name) + 1);
|
||||
|
||||
FILE *log_out = fopen(fname, "wb");
|
||||
if (log_out){
|
||||
fwrite(log->out, 1, log->size, log_out);
|
||||
fclose(log_out);
|
||||
}
|
||||
else{
|
||||
printf("log error: could not open %s\n", fname);
|
||||
}
|
||||
}
|
||||
else{
|
||||
printf("\n");
|
||||
if (log->error & log_er_buffer_overflow)
|
||||
printf("log error: buffer overflow\n");
|
||||
if (log->error & log_er_stack_overflow)
|
||||
printf("log error: stack overflow\n");
|
||||
if (log->error & log_er_stack_underflow)
|
||||
printf("log error: stack underflow\n");
|
||||
printf("there were log error so the log was not saved\n\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define litstr(s) (char*)(s), (sizeof(s)-1)
|
||||
|
||||
void
|
||||
log_time_record(Stats_Log *log, char *name, int name_len, Time_Record record){
|
||||
log_begin_section(log, name, name_len);
|
||||
log_data_item(log, litstr("golden-array"), record.buffer);
|
||||
log_data_item(log, litstr("gap-buffer"), record.gap_buffer);
|
||||
log_data_item(log, litstr("multi-gap-buffer"), record.multi_gap_buffer);
|
||||
log_data_item(log, litstr("rope"), record.rope_buffer);
|
||||
log_end_section(log);
|
||||
}
|
||||
|
||||
Time_Record
|
||||
operator+(const Time_Record &a, const Time_Record &b){
|
||||
Time_Record r;
|
||||
|
@ -259,6 +518,16 @@ operator+(const Time_Record &a, const Time_Record &b){
|
|||
return r;
|
||||
}
|
||||
|
||||
Time_Record&
|
||||
operator/=(Time_Record &r, int x){
|
||||
r.buffer /= x;
|
||||
r.gap_buffer /= x;
|
||||
r.multi_gap_buffer /= x;
|
||||
r.rope_buffer /= x;
|
||||
|
||||
return(r);
|
||||
}
|
||||
|
||||
#define minify(a,b) if ((a)>(b)) (a) = (b)
|
||||
#define maxify(a,b) if ((a)<(b)) (a) = (b)
|
||||
|
||||
|
@ -286,10 +555,7 @@ get_record_statistics(Record_Statistics *stats_out, Time_Record *records, int co
|
|||
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.expected /= count;
|
||||
|
||||
*stats_out = stats;
|
||||
}
|
||||
|
@ -350,38 +616,82 @@ typedef struct Buffer_Set{
|
|||
#include "4coder_test_abstract.cpp"
|
||||
#undef Buffer_Type
|
||||
|
||||
#define print_name() printf("%s:\n", __FUNCTION__)
|
||||
void
|
||||
log_sample_set(Stats_Log *log, char *name, int name_len, Record_Statistics *stats,
|
||||
Time_Record *samples, int sample_count){
|
||||
log_begin_section(log, name, name_len);
|
||||
|
||||
log_data_item(log, litstr("sample-count"), sample_count);
|
||||
log_time_record(log, litstr("max"), stats->max);
|
||||
log_time_record(log, litstr("min"), stats->min);
|
||||
log_time_record(log, litstr("average"), stats->expected);
|
||||
|
||||
for (int i = 0; i < sample_count; ++i){
|
||||
log_time_record(log, litstr("item"), samples[i]);
|
||||
}
|
||||
|
||||
log_end_section(log);
|
||||
}
|
||||
|
||||
typedef struct Sample_Machine{
|
||||
time_int tstart, tend;
|
||||
Time_Record *samples;
|
||||
int count;
|
||||
} Sample_Machine;
|
||||
|
||||
Sample_Machine
|
||||
begin_machine(int count, void **data, int *max){
|
||||
Sample_Machine result;
|
||||
|
||||
result.count = count;
|
||||
result.samples = (Time_Record*)*data;
|
||||
*data = result.samples + count;
|
||||
assert_4tech(count*sizeof(*result.samples) < *max);
|
||||
*max -= count*sizeof(*result.samples);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
initialization_test(Buffer_Set *set, File_Data file, int test_repitions,
|
||||
end_machine(Sample_Machine *machine, Record_Statistics *stats_out, char *func_name){
|
||||
if (!test_is_silenced) printf("%s\n", func_name);
|
||||
print_statistics(machine->samples, machine->count, stats_out);
|
||||
if (!test_is_silenced) printf("\n");
|
||||
test_is_silenced = 0;
|
||||
}
|
||||
|
||||
void start(Sample_Machine *machine){
|
||||
machine->tstart = get_time();
|
||||
}
|
||||
|
||||
time_int stop(Sample_Machine *machine){
|
||||
machine->tend = get_time();
|
||||
return machine->tend - machine->tstart;
|
||||
}
|
||||
|
||||
void
|
||||
initialization_test(Stats_Log *log, 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);
|
||||
Sample_Machine machine;
|
||||
machine = begin_machine(test_repitions, &scratch, &scratch_size);
|
||||
|
||||
for (int i = 0; i < test_repitions; ++i){
|
||||
tstart = get_time();
|
||||
start(&machine);
|
||||
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;
|
||||
machine.samples[i].buffer = stop(&machine);
|
||||
|
||||
start(&machine);
|
||||
init_buffer(&set->gap_buffer, file, scratch, scratch_size);
|
||||
machine.samples[i].gap_buffer = stop(&machine);
|
||||
|
||||
start(&machine);
|
||||
init_buffer(&set->multi_gap_buffer, file, scratch, scratch_size);
|
||||
machine.samples[i].multi_gap_buffer = stop(&machine);
|
||||
|
||||
start(&machine);
|
||||
init_buffer(&set->rope_buffer, file, scratch, scratch_size);
|
||||
machine.samples[i].rope_buffer = stop(&machine);
|
||||
|
||||
if (i+1 != test_repitions){
|
||||
free(set->buffer.data);
|
||||
free(set->gap_buffer.data);
|
||||
|
@ -394,42 +704,33 @@ initialization_test(Buffer_Set *set, File_Data file, int test_repitions,
|
|||
}
|
||||
}
|
||||
|
||||
if (!test_is_silenced) print_name();
|
||||
print_statistics(init_time, test_repitions, stats_out);
|
||||
if (!test_is_silenced) printf("\n");
|
||||
test_is_silenced = 0;
|
||||
end_machine(&machine, stats_out, __FUNCTION__);
|
||||
|
||||
log_sample_set(log, litstr("initialization"), stats_out, machine.samples, machine.count);
|
||||
}
|
||||
|
||||
void
|
||||
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;
|
||||
assert_4tech(test_repitions*sizeof(*measure_time) < scratch_size);
|
||||
scratch_size -= test_repitions*sizeof(*measure_time);
|
||||
measure_starts_widths_test(Stats_Log *log, Buffer_Set *set, int test_repitions, void *scratch,
|
||||
int scratch_size, Record_Statistics *stats_out, float *font_widths){
|
||||
Sample_Machine machine;
|
||||
machine = begin_machine(test_repitions, &scratch, &scratch_size);
|
||||
|
||||
for (int i = 0; i < test_repitions; ++i){
|
||||
tstart = get_time();
|
||||
start(&machine);
|
||||
measure_starts_widths(&set->buffer, font_widths);
|
||||
tend = get_time();
|
||||
measure_time[i].buffer = tend - tstart;
|
||||
machine.samples[i].buffer = stop(&machine);
|
||||
|
||||
tstart = get_time();
|
||||
start(&machine);
|
||||
measure_starts_widths(&set->gap_buffer, font_widths);
|
||||
tend = get_time();
|
||||
measure_time[i].gap_buffer = tend - tstart;
|
||||
|
||||
tstart = get_time();
|
||||
machine.samples[i].gap_buffer = stop(&machine);
|
||||
|
||||
start(&machine);
|
||||
measure_starts_widths(&set->multi_gap_buffer, font_widths);
|
||||
tend = get_time();
|
||||
measure_time[i].multi_gap_buffer = tend - tstart;
|
||||
machine.samples[i].multi_gap_buffer = stop(&machine);
|
||||
|
||||
tstart = get_time();
|
||||
start(&machine);
|
||||
measure_starts_widths(&set->rope_buffer, font_widths);
|
||||
tend = get_time();
|
||||
measure_time[i].rope_buffer = tend - tstart;
|
||||
machine.samples[i].rope_buffer = stop(&machine);
|
||||
|
||||
if (i+1 != test_repitions){
|
||||
free(set->buffer.line_starts);
|
||||
|
@ -444,14 +745,15 @@ measure_starts_widths_test(Buffer_Set *set, int test_repitions,
|
|||
}
|
||||
}
|
||||
|
||||
if (!test_is_silenced) print_name();
|
||||
print_statistics(measure_time, test_repitions, stats_out);
|
||||
if (!test_is_silenced) printf("\n");
|
||||
test_is_silenced = 0;
|
||||
end_machine(&machine, stats_out, __FUNCTION__);
|
||||
|
||||
log_sample_set(log, litstr("measure_starts_widths"), stats_out, machine.samples, machine.count);
|
||||
}
|
||||
|
||||
int
|
||||
page_compare(char *page_1, char *page_2, int page_size){
|
||||
page_compare(void *page_1_, void *page_2_, int page_size){
|
||||
char *page_1 = (char*)page_1_;
|
||||
char *page_2 = (char*)page_2_;
|
||||
int result = 1;
|
||||
for (int i = 0; i < page_size; ++i){
|
||||
hard_assert_4tech(page_1[i] == page_2[i]);
|
||||
|
@ -459,6 +761,173 @@ page_compare(char *page_1, char *page_2, int page_size){
|
|||
return result;
|
||||
}
|
||||
|
||||
float*
|
||||
measure_wraps_test(Stats_Log *log, Buffer_Set *buffers, int test_repitions, void *scratch,
|
||||
int scratch_size, Record_Statistics *stats_out, float font_height, float max_width){
|
||||
Sample_Machine machine;
|
||||
machine = begin_machine(test_repitions, &scratch, &scratch_size);
|
||||
|
||||
float *wrap_ys, *wrap_ys2;
|
||||
wrap_ys = (float*)malloc(sizeof(float)*buffers->buffer.line_count);
|
||||
wrap_ys2 = (float*)malloc(sizeof(float)*buffers->buffer.line_count);
|
||||
|
||||
for (int i = 0; i < test_repitions; ++i){
|
||||
start(&machine);
|
||||
buffer_measure_wrap_y(&buffers->buffer, wrap_ys, font_height, max_width);
|
||||
machine.samples[i].buffer = stop(&machine);
|
||||
|
||||
start(&machine);
|
||||
buffer_measure_wrap_y(&buffers->gap_buffer, wrap_ys2, font_height, max_width);
|
||||
machine.samples[i].gap_buffer = stop(&machine);
|
||||
if (i == 0)
|
||||
page_compare((char*)wrap_ys, (char*)wrap_ys2, sizeof(float)*buffers->buffer.line_count);
|
||||
|
||||
start(&machine);
|
||||
buffer_measure_wrap_y(&buffers->multi_gap_buffer, wrap_ys2, font_height, max_width);
|
||||
machine.samples[i].multi_gap_buffer = stop(&machine);
|
||||
if (i == 0)
|
||||
page_compare((char*)wrap_ys, (char*)wrap_ys2, sizeof(float)*buffers->buffer.line_count);
|
||||
|
||||
start(&machine);
|
||||
buffer_measure_wrap_y(&buffers->rope_buffer, wrap_ys2, font_height, max_width);
|
||||
machine.samples[i].rope_buffer = stop(&machine);
|
||||
if (i == 0)
|
||||
page_compare((char*)wrap_ys, (char*)wrap_ys2, sizeof(float)*buffers->buffer.line_count);
|
||||
}
|
||||
|
||||
free(wrap_ys2);
|
||||
|
||||
end_machine(&machine, stats_out, __FUNCTION__);
|
||||
|
||||
log_sample_set(log, litstr("measure-wrap-ys"), stats_out, machine.samples, machine.count);
|
||||
|
||||
return wrap_ys;
|
||||
}
|
||||
|
||||
int
|
||||
cursor_eq(Full_Cursor c1, Full_Cursor c2){
|
||||
int result = 0;
|
||||
if (c1.pos == c2.pos && c1.line == c2.line && c1.character == c2.character &&
|
||||
c1.wrapped_x == c2.wrapped_x && c1.wrapped_y == c2.wrapped_y &&
|
||||
c1.unwrapped_x == c2.unwrapped_x && c1.unwrapped_y == c2.unwrapped_y){
|
||||
result = 1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
full_cursor_test(Stats_Log *log, Buffer_Set *buffers, int pos,
|
||||
float *wrap_ys, float *advance_data, float font_height, float max_width,
|
||||
int test_repitions, void *scratch, int scratch_size, Record_Statistics *stats_out){
|
||||
Sample_Machine machine;
|
||||
machine = begin_machine(test_repitions, &scratch, &scratch_size);
|
||||
|
||||
Full_Cursor cursor, cursor2;
|
||||
|
||||
for (int i = 0; i < test_repitions; ++i){
|
||||
start(&machine);
|
||||
cursor = buffer_cursor_from_pos(&buffers->buffer, pos, wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].buffer = stop(&machine);
|
||||
|
||||
start(&machine);
|
||||
cursor2 = buffer_cursor_from_pos(&buffers->gap_buffer, pos, wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].gap_buffer = stop(&machine);
|
||||
if (i == 0) assert_4tech(cursor_eq(cursor, cursor2));
|
||||
|
||||
start(&machine);
|
||||
cursor2 = buffer_cursor_from_pos(&buffers->multi_gap_buffer, pos, wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].multi_gap_buffer = stop(&machine);
|
||||
if (i == 0) assert_4tech(cursor_eq(cursor, cursor2));
|
||||
|
||||
start(&machine);
|
||||
cursor2 = buffer_cursor_from_pos(&buffers->rope_buffer, pos, wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].rope_buffer = stop(&machine);
|
||||
if (i == 0) assert_4tech(cursor_eq(cursor, cursor2));
|
||||
}
|
||||
|
||||
end_machine(&machine, stats_out, __FUNCTION__);
|
||||
|
||||
log_sample_set(log, litstr("full-cursor-seek"), stats_out, machine.samples, machine.count);
|
||||
}
|
||||
|
||||
void
|
||||
full_cursor_line_test(Stats_Log *log, Buffer_Set *buffers, int line, int character,
|
||||
float *wrap_ys, float *advance_data, float font_height, float max_width,
|
||||
int test_repitions, void *scratch, int scratch_size, Record_Statistics *stats_out){
|
||||
Sample_Machine machine;
|
||||
machine = begin_machine(test_repitions, &scratch, &scratch_size);
|
||||
|
||||
Full_Cursor cursor, cursor2;
|
||||
|
||||
for (int i = 0; i < test_repitions; ++i){
|
||||
start(&machine);
|
||||
cursor = buffer_cursor_from_line_character(&buffers->buffer, line, character,
|
||||
wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].buffer = stop(&machine);
|
||||
|
||||
start(&machine);
|
||||
cursor2 = buffer_cursor_from_line_character(&buffers->gap_buffer, line, character,
|
||||
wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].gap_buffer = stop(&machine);
|
||||
if (i == 0) assert_4tech(cursor_eq(cursor, cursor2));
|
||||
|
||||
start(&machine);
|
||||
cursor2 = buffer_cursor_from_line_character(&buffers->multi_gap_buffer, line, character,
|
||||
wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].multi_gap_buffer = stop(&machine);
|
||||
if (i == 0) assert_4tech(cursor_eq(cursor, cursor2));
|
||||
|
||||
start(&machine);
|
||||
cursor2 = buffer_cursor_from_line_character(&buffers->rope_buffer, line, character,
|
||||
wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].rope_buffer = stop(&machine);
|
||||
if (i == 0) assert_4tech(cursor_eq(cursor, cursor2));
|
||||
}
|
||||
|
||||
end_machine(&machine, stats_out, __FUNCTION__);
|
||||
|
||||
log_sample_set(log, litstr("full-cursor-seek"), stats_out, machine.samples, machine.count);
|
||||
}
|
||||
|
||||
void
|
||||
full_cursor_xy_test(Stats_Log *log, Buffer_Set *buffers, float x, float y, int round_down,
|
||||
float *wrap_ys, float *advance_data, float font_height, float max_width,
|
||||
int test_repitions, void *scratch, int scratch_size, Record_Statistics *stats_out){
|
||||
Sample_Machine machine;
|
||||
machine = begin_machine(test_repitions, &scratch, &scratch_size);
|
||||
|
||||
Full_Cursor cursor, cursor2;
|
||||
|
||||
for (int i = 0; i < test_repitions; ++i){
|
||||
start(&machine);
|
||||
cursor = buffer_cursor_from_unwrapped_xy(&buffers->buffer, x, y, round_down,
|
||||
wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].buffer = stop(&machine);
|
||||
|
||||
start(&machine);
|
||||
cursor2 = buffer_cursor_from_unwrapped_xy(&buffers->gap_buffer, x, y, round_down,
|
||||
wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].gap_buffer = stop(&machine);
|
||||
if (i == 0) assert_4tech(cursor_eq(cursor, cursor2));
|
||||
|
||||
start(&machine);
|
||||
cursor2 = buffer_cursor_from_unwrapped_xy(&buffers->multi_gap_buffer, x, y, round_down,
|
||||
wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].multi_gap_buffer = stop(&machine);
|
||||
if (i == 0) assert_4tech(cursor_eq(cursor, cursor2));
|
||||
|
||||
start(&machine);
|
||||
cursor2 = buffer_cursor_from_unwrapped_xy(&buffers->rope_buffer, x, y, round_down,
|
||||
wrap_ys, max_width, font_height, advance_data);
|
||||
machine.samples[i].rope_buffer = stop(&machine);
|
||||
if (i == 0) assert_4tech(cursor_eq(cursor, cursor2));
|
||||
}
|
||||
|
||||
end_machine(&machine, stats_out, __FUNCTION__);
|
||||
|
||||
log_sample_set(log, litstr("full-cursor-seek"), stats_out, machine.samples, machine.count);
|
||||
}
|
||||
|
||||
void
|
||||
stream_check_test(Buffer_Set *buffers, void *scratch, int scratch_size){
|
||||
int i, page_size, size;
|
||||
|
@ -514,39 +983,161 @@ stream_check_test(Buffer_Set *buffers, void *scratch, int scratch_size){
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
measure_check_test(Buffer_Set *buffers){
|
||||
int count;
|
||||
count = buffers->buffer.line_count;
|
||||
assert_4tech(count == buffers->buffer.widths_count);
|
||||
|
||||
assert_4tech(count == buffers->gap_buffer.line_count);
|
||||
assert_4tech(count == buffers->multi_gap_buffer.line_count);
|
||||
assert_4tech(count == buffers->rope_buffer.line_count);
|
||||
|
||||
assert_4tech(count == buffers->gap_buffer.widths_count);
|
||||
assert_4tech(count == buffers->multi_gap_buffer.widths_count);
|
||||
assert_4tech(count == buffers->rope_buffer.widths_count);
|
||||
|
||||
page_compare(buffers->buffer.line_starts, buffers->gap_buffer.line_starts, sizeof(int)*count);
|
||||
page_compare(buffers->buffer.line_starts, buffers->multi_gap_buffer.line_starts, sizeof(int)*count);
|
||||
page_compare(buffers->buffer.line_starts, buffers->rope_buffer.line_starts, sizeof(int)*count);
|
||||
|
||||
page_compare(buffers->buffer.line_widths, buffers->gap_buffer.line_widths, sizeof(float)*count);
|
||||
page_compare(buffers->buffer.line_widths, buffers->multi_gap_buffer.line_widths, sizeof(float)*count);
|
||||
page_compare(buffers->buffer.line_widths, buffers->rope_buffer.line_widths, sizeof(float)*count);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
Buffer_Set buffers;
|
||||
File_Data file;
|
||||
float *widths_data;
|
||||
float *wrap_ys;
|
||||
float font_height;
|
||||
float max_width;
|
||||
|
||||
void *scratch;
|
||||
int scratch_size;
|
||||
|
||||
Stats_Log log;
|
||||
|
||||
if (argc < 2){
|
||||
printf("usage: buffer_test <filename>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
setup();
|
||||
|
||||
log.max = 1 << 20;
|
||||
log.size = 0;
|
||||
log.out = (char*)malloc(log.max);
|
||||
|
||||
log.sec_max = 32;
|
||||
log.sec_top = 0;
|
||||
log.sections = (Log_Section*)malloc(sizeof(Log_Section)*log.sec_max);
|
||||
|
||||
log.error = 0;
|
||||
|
||||
scratch_size = 1 << 20;
|
||||
scratch = malloc(scratch_size);
|
||||
|
||||
file = get_file(argv[1]);
|
||||
widths_data = get_font_data("LiberationSans-Regular.ttf");
|
||||
widths_data = get_font_data("LiberationSans-Regular.ttf", &font_height);
|
||||
max_width = 500.f;
|
||||
|
||||
Record_Statistics init_rec, starts_widths_rec;
|
||||
log_begin_section(&log, litstr("which-test"));
|
||||
{
|
||||
log_write_str(&log, argv[1], (int)strlen(argv[1]));
|
||||
log_write_int(&log, file.size);
|
||||
}
|
||||
log_end_section(&log);
|
||||
|
||||
initialization_test(&buffers, file, 100, scratch, scratch_size, &init_rec);
|
||||
stream_check_test(&buffers, scratch, scratch_size);
|
||||
log_begin_section(&log, litstr("file-open"));
|
||||
{
|
||||
Record_Statistics init_rec, starts_widths_rec, wraps_rec;
|
||||
|
||||
measure_starts_widths_test(&buffers, 100, scratch, scratch_size, &starts_widths_rec, widths_data);
|
||||
initialization_test(&log, &buffers, file, 25, scratch, scratch_size, &init_rec);
|
||||
stream_check_test(&buffers, scratch, scratch_size);
|
||||
|
||||
Time_Record expected_file_open;
|
||||
expected_file_open = init_rec.expected + starts_widths_rec.expected;
|
||||
measure_starts_widths_test(&log, &buffers, 25, scratch, scratch_size, &starts_widths_rec, widths_data);
|
||||
measure_check_test(&buffers);
|
||||
|
||||
wrap_ys = measure_wraps_test(&log, &buffers, 25, scratch, scratch_size, &wraps_rec, font_height, max_width);
|
||||
|
||||
printf("average file open:\n");
|
||||
print_record(expected_file_open);
|
||||
Time_Record expected_file_open;
|
||||
expected_file_open = init_rec.expected + starts_widths_rec.expected + wraps_rec.expected;
|
||||
|
||||
printf("average file open:\n");
|
||||
print_record(expected_file_open);
|
||||
printf("\n");
|
||||
log_time_record(&log, litstr("average"), expected_file_open);
|
||||
}
|
||||
log_end_section(&log);
|
||||
|
||||
log_begin_section(&log, litstr("cursor-seek"));
|
||||
{
|
||||
Record_Statistics full_cursor;
|
||||
Time_Record full_cursor_average;
|
||||
|
||||
log_begin_section(&log, litstr("to-pos"));
|
||||
{
|
||||
memzero_4tech(full_cursor_average);
|
||||
for (int i = 0; i < 5; ++i){
|
||||
silence_test();
|
||||
int pos = (file.size*i) / 5;
|
||||
full_cursor_test(&log, &buffers, pos,
|
||||
wrap_ys, widths_data, font_height, max_width,
|
||||
5, scratch, scratch_size, &full_cursor);
|
||||
full_cursor_average = full_cursor_average + full_cursor.expected;
|
||||
}
|
||||
full_cursor_average /= 5;
|
||||
printf("average cursor from position:\n");
|
||||
print_record(full_cursor_average);
|
||||
printf("\n");
|
||||
log_time_record(&log, litstr("average"), full_cursor_average);
|
||||
}
|
||||
log_end_section(&log);
|
||||
|
||||
log_begin_section(&log, litstr("to-line-character"));
|
||||
{
|
||||
memzero_4tech(full_cursor_average);
|
||||
for (int i = 0; i < 5; ++i){
|
||||
silence_test();
|
||||
int line = (buffers.buffer.line_count*i) / 5;
|
||||
full_cursor_line_test(&log, &buffers, line, 20,
|
||||
wrap_ys, widths_data, font_height, max_width,
|
||||
5, scratch, scratch_size, &full_cursor);
|
||||
full_cursor_average = full_cursor_average + full_cursor.expected;
|
||||
}
|
||||
full_cursor_average /= 5;
|
||||
printf("average cursor from line & character:\n");
|
||||
print_record(full_cursor_average);
|
||||
printf("\n");
|
||||
log_time_record(&log, litstr("average"), full_cursor_average);
|
||||
}
|
||||
log_end_section(&log);
|
||||
|
||||
log_begin_section(&log, litstr("to-unwrapped-x-y"));
|
||||
{
|
||||
memzero_4tech(full_cursor_average);
|
||||
for (int i = 0; i < 5; ++i){
|
||||
silence_test();
|
||||
float y = font_height * (buffers.buffer.line_count*i) / 4.f;
|
||||
full_cursor_xy_test(&log, &buffers, y, 37.f, 0,
|
||||
wrap_ys, widths_data, font_height, max_width,
|
||||
5, scratch, scratch_size, &full_cursor);
|
||||
full_cursor_average = full_cursor_average + full_cursor.expected;
|
||||
}
|
||||
full_cursor_average /= 5;
|
||||
printf("average cursor from line & character:\n");
|
||||
print_record(full_cursor_average);
|
||||
printf("\n");
|
||||
log_time_record(&log, litstr("average"), full_cursor_average);
|
||||
}
|
||||
log_end_section(&log);
|
||||
|
||||
}
|
||||
log_end_section(&log);
|
||||
|
||||
log_finish(&log);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue