317 lines
9.7 KiB
C++
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
|
|
|