4coder/buffer/history_to_replay.cpp

317 lines
9.7 KiB
C++

/*
* Mr. 4th Dimention - Allen Webster
* Four Tech
*
* public domain -- no warranty is offered or implied; use this code at your own risk
*
* 11.11.2015
*
* Converts code file and saved history from 4coder
* into replay file for the test system.
*
*/
// TOP
#include "shared_test_config.cpp"
#include "4coder_shared.cpp"
#include "4coder_golden_array.cpp"
#define Buffer_Type Buffer
#include "4coder_buffer_abstract.cpp"
#include "shared_test_utils.cpp"
void do_single_edit(Replay *replay, Buffer *buffer, Edit_Step step, char *str, void *scratch, int scratch_size){
{
Edit_Stack *stack;
char *new_data;
Edit_Step inv_step;
int size, new_max, new_size;
stack = &replay->replay;
memzero_4tech(inv_step);
size = 0;
buffer_invert_edit(buffer, step.edit, &inv_step.edit, (char*)scratch, &size, scratch_size);
assert_4tech(stack->count < replay->ed_max);
stack = &replay->replay;
stack->edits[replay->ed_max - (++stack->count)] = inv_step;
new_size = stack->size + size;
if (new_size > replay->str_max){
new_max = (replay->str_max + size) * 2;
new_data = (char*)malloc(new_max);
memcpy_4tech(new_data + new_max - stack->size, stack->strings + replay->str_max - stack->size, stack->size);
free(stack->strings);
stack->strings = new_data;
replay->str_max = new_max;
}
memcpy_4tech(stack->strings + replay->str_max - new_size, scratch, size);
stack->size = new_size;
printf("just wrote: [[ %.*s ]]\n", size, scratch);
}
int start = step.edit.start;
int end = step.edit.end;
int str_start = step.edit.str_start;
int len = step.edit.len;
int shift_amount;
int request_amount;
for (;buffer_replace_range(buffer, start, end, str + str_start, len, &shift_amount,
scratch, scratch_size, &request_amount);){
void *new_data = 0;
if (request_amount > 0) new_data = malloc(request_amount);
void *old_data = buffer_edit_provide_memory(buffer, new_data, request_amount);
if (old_data) free(old_data);
}
}
void do_batch_edit(Replay *replay, Buffer *buffer, Edit_Step step, void *scratch, int scratch_size){
{
Edit_Stack *stack;
Edit_Step inv_step;
stack = &replay->replay;
memzero_4tech(inv_step);
inv_step.first_child = step.inverse_first_child;
inv_step.inverse_first_child = step.first_child;
inv_step.child_count = step.inverse_child_count;
inv_step.inverse_child_count = step.child_count;
assert_4tech(stack->count < replay->ed_max);
stack = &replay->replay;
stack->edits[replay->ed_max - (++stack->count)] = inv_step;
}
char *str;
Buffer_Edit *batch;
int batch_size;
int request_amount;
Buffer_Batch_State state;
str = replay->children.strings;
batch = replay->children.edits + step.first_child;
batch_size = step.child_count;
memzero_4tech(state);
for (;buffer_batch_edit_step(&state, buffer, batch, str, batch_size,
scratch, scratch_size, &request_amount);){
void *new_data = 0;
if (request_amount > 0) new_data = malloc(request_amount);
void *old_data = buffer_edit_provide_memory(buffer, new_data, request_amount);
if (old_data) free(old_data);
}
}
#if 0
int main(int argc, char **argv){
if (argc < 3){
printf("usage: hst_to_rply <history> <target-file> <output>\n");
exit(1);
}
File_Data history_file, code_file;
history_file = get_file(argv[1]);
code_file = get_file(argv[2]);
if (!history_file.data || !code_file.data) exit(1);
History history;
char *curs = history_file.data;
history.undo.count = read_int(&curs);
history.redo.count = read_int(&curs);
history.history.count = read_int(&curs);
history.children.count = read_int(&curs);
history.undo.size = read_int(&curs);
history.redo.size = read_int(&curs);
history.history.size = read_int(&curs);
history.children.size = read_int(&curs);
history.undo.edits = (Edit_Step*)curs;
curs += sizeof(Edit_Step)*history.undo.count;
history.redo.edits = (Edit_Step*)curs;
curs += sizeof(Edit_Step)*history.redo.count;
history.history.edits = (Edit_Step*)curs;
curs += sizeof(Edit_Step)*history.history.count;
history.children.edits = (Buffer_Edit*)curs;
curs += sizeof(Buffer_Edit)*history.children.count;
history.undo.strings = (char*)curs;
curs += history.undo.size;
history.redo.strings = (char*)curs;
curs += history.redo.size;
history.history.strings = (char*)curs;
curs += history.history.size;
history.children.strings = (char*)curs;
curs += history.children.size;
void *scratch;
int scratch_size;
scratch_size = 1 << 20;
scratch = malloc(scratch_size);
Buffer buffer;
Buffer_Init_Type init;
memzero_4tech(buffer);
memzero_4tech(init);
for (init = buffer_begin_init(&buffer, code_file.data, code_file.size);
buffer_init_need_more(&init);){
int page_size = buffer_init_page_size(&init);
page_size = round_up_4tech(page_size, 4 << 10);
void *data = malloc(page_size);
buffer_init_provide_page(&init, data, page_size);
}
buffer_end_init(&init, scratch, scratch_size);
Replay replay;
replay.children = history.children;
replay.ed_max = history.history.count;
replay.replay.edits = (Edit_Step*)malloc(sizeof(Edit_Step)*replay.ed_max);
replay.replay.count = 0;
replay.str_max = history.history. size * 4;
replay.replay.strings = (char*)malloc(replay.str_max);
replay.replay.size = 0;
for (int i = history.history.count - 1; i >= 0; --i){
Edit_Step step = history.history.edits[i];
if (step.child_count == 0){
do_single_edit(&replay, &buffer, step, history.history.strings, scratch, scratch_size);
}
else{
assert(step.special_type == 1);
do_batch_edit(&replay, &buffer, step, scratch, scratch_size);
}
}
assert(history.history.count == replay.replay.count);
int str_start = 0;
for (int i = 0; i < history.history.count; ++i){
replay.replay.edits[i].edit.str_start = str_start;
str_start += replay.replay.edits[i].edit.len;
}
File_Data out_file;
out_file.size = 0;
out_file.size += replay.replay.count*sizeof(Edit_Step) + sizeof(int);
out_file.size += replay.replay.size + sizeof(int);
out_file.size += replay.children.count*sizeof(Buffer_Edit) + sizeof(int);
out_file.size += replay.children.size + sizeof(int);
out_file.data = (char*)malloc(out_file.size);
curs = out_file.data;
curs = write_int(curs, replay.replay.count);
curs = write_int(curs, replay.children.count);
curs = write_int(curs, replay.replay.size);
curs = write_int(curs, replay.children.size);
memcpy(curs, replay.replay.edits, replay.replay.count*sizeof(Edit_Step));
curs += replay.replay.count*sizeof(Edit_Step);
memcpy(curs, replay.children.edits, replay.children.count*sizeof(Buffer_Edit));
curs += replay.children.count*sizeof(Buffer_Edit);
memcpy(curs, replay.replay.strings + replay.str_max - replay.replay.size, replay.replay.size);
curs += replay.replay.size;
memcpy(curs, replay.children.strings, replay.children.size);
curs += replay.children.size;
assert((int)(curs - out_file.data) == out_file.size);
save_file(argv[3], out_file);
return(0);
}
#else
int main(int argc, char **argv){
if (argc < 2){
printf("usage: <replay-file>\n");
exit(1);
}
File_Data file = get_file(argv[1]);
//char *curs = file.data;
Replay replay;
prepare_replay(file, &replay);
#if 0
replay.replay.count = read_int(&curs);
replay.children.count = read_int(&curs);
replay.replay.size = read_int(&curs);
replay.children.size = read_int(&curs);
replay.replay.edits = (Edit_Step*)curs;
curs += sizeof(Edit_Step)*replay.replay.count;
replay.children.edits = (Buffer_Edit*)curs;
curs += sizeof(Buffer_Edit)*replay.children.count;
replay.replay.strings = curs;
curs += replay.replay.size;
replay.children.strings = curs;
curs += replay.children.size;
assert_4tech((int)(curs - file.data) == file.size);
#endif
for (int i = 0; i < replay.replay.count; ++i){
Edit_Step step = replay.replay.edits[i];
if (step.first_child == 0){
if (step.edit.len > 0 && step.edit.str_start >= 0 && step.edit.str_start < replay.replay.size){
printf("replace [%d,%d] with %.*s\n", step.edit.start, step.edit.end,
step.edit.len, replay.replay.strings + step.edit.str_start);
}
else if (step.edit.len > 0){
printf("str_start out of bounds!\n");
}
else{
printf("replace [%d,%d] with ~~empty string~~\n", step.edit.start, step.edit.end);
}
}
else{
printf("batch edit\n");
}
}
printf("string section:\n%.*s\n", replay.replay.size, replay.replay.strings);
}
#endif
// BOTTOM