/* * 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 \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: \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