diff options
Diffstat (limited to 'src/save.c')
| -rw-r--r-- | src/save.c | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/src/save.c b/src/save.c new file mode 100644 index 0000000..82ca623 --- /dev/null +++ b/src/save.c @@ -0,0 +1,380 @@ +/* +* BSD 2-Clause “Simplified” License +* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com +* All rights reserved. +*/ + +search_result *create_empty_search_result(); +void* destroy_search_result_thread(void *arg); + +static void write_json_file(char *buffer, s32 length, search_result *search_result) +{ + array matches = search_result->matches; + + cJSON *result = cJSON_CreateObject(); + if (cJSON_AddStringToObject(result, "search_directory", + search_result->directory_to_search) == NULL) + return; + + if (cJSON_AddStringToObject(result, "filter", + search_result->file_filter) == NULL) + return; + + if (cJSON_AddStringToObject(result, "search_query", + search_result->text_to_find) == NULL) + return; + + if (cJSON_AddNumberToObject(result, "duration_us", + search_result->find_duration_us) == NULL) + return; + + if (cJSON_AddNumberToObject(result, "show_error", + search_result->show_error_message) == NULL) + return; + + if (cJSON_AddNumberToObject(result, "file_match_found", + search_result->found_file_matches) == NULL) + return; + + if (cJSON_AddNumberToObject(result, "files_searched", + search_result->files_searched) == NULL) + return; + + if (cJSON_AddNumberToObject(result, "files_matched", + search_result->files_matched) == NULL) + return; + + if (cJSON_AddNumberToObject(result, "query_match_found", + search_result->match_found) == NULL) + return; + + if (cJSON_AddNumberToObject(result, "recursive_search", + search_result->is_recursive) == NULL) + return; + + cJSON *match_list = cJSON_AddArrayToObject(result, "match_list"); + + if (!match_list) return; + + for (s32 i = 0; i < matches.length; i++) + { + file_match* m = array_at(&matches, i); + + cJSON *item = cJSON_CreateObject(); + + if (cJSON_AddStringToObject(item, "path", + m->file.path) == NULL) + return; + + if (cJSON_AddStringToObject(item, "matched_filter", + m->file.matched_filter) == NULL) + return; + + if (cJSON_AddNumberToObject(item, "word_offset", + m->word_match_offset) == NULL) + return; + + if (cJSON_AddNumberToObject(item, "word_length", + m->word_match_length) == NULL) + return; + + if (cJSON_AddNumberToObject(item, "file_error", + m->file_error) == NULL) + return; + + if (cJSON_AddNumberToObject(item, "line_nr", + m->line_nr) == NULL) + return; + + if (cJSON_AddNumberToObject(item, "file_size", + m->file_size) == NULL) + return; + + if (m->line_info) + { + if (cJSON_AddStringToObject(item, "line_info", + m->line_info) == NULL) + return; + } + else + { + if (cJSON_AddNumberToObject(item, "line_info", 0) == NULL) + return; + } + + cJSON_AddItemToArray(match_list, item); + } + + cJSON_PrintPreallocated(result, buffer, length, true); + cJSON_Delete(result); +} + +static void *export_result_d(void *arg) +{ + search_result *search_result = arg; + + array matches = search_result->files; + + char path_buf[MAX_INPUT_LENGTH]; + path_buf[0] = 0; + + char start_path[MAX_INPUT_LENGTH]; + snprintf(start_path, MAX_INPUT_LENGTH, "%s%s", binary_path, ""); + + char default_save_file_extension[50]; + string_copyn(default_save_file_extension, "json", 50); + + if (!search_result->is_command_line_search) + { + struct open_dialog_args *args = mem_alloc(sizeof(struct open_dialog_args)); + args->buffer = path_buf; + args->type = SAVE_FILE; + args->file_filter = SEARCH_RESULT_FILE_EXTENSION; + args->start_path = start_path; + args->default_save_file_extension = default_save_file_extension; + + platform_open_file_dialog_block(args); + } + else + { + string_copyn(path_buf, search_result->export_path, MAX_INPUT_LENGTH); + } + + char tmp_dir_buffer[MAX_INPUT_LENGTH]; + get_directory_from_path(tmp_dir_buffer, path_buf); + + char tmp_name_buffer[MAX_INPUT_LENGTH]; + get_name_from_path(tmp_name_buffer, path_buf); + + if (string_equals(path_buf, "")) return 0; + if (string_equals(tmp_name_buffer, "")) return 0; + if (!platform_directory_exists(tmp_dir_buffer)) return 0; + + s32 size = matches.length * (MAX_INPUT_LENGTH*10); + char *buffer = mem_alloc(size); + memset(buffer, 0, size); + + char *file_extension = get_file_extension(path_buf); + if (string_equals(file_extension, ".json") || string_equals(file_extension, "")) + { + write_json_file(buffer, size, search_result); + } + + if (string_equals(file_extension, "")) + { + string_appendn(path_buf, ".json", MAX_INPUT_LENGTH); + } + + platform_write_file_content(path_buf, "w", buffer, size); + + return 0; +} + +bool export_results(search_result *search_result) +{ + thread thr; + thr.valid = false; + + while (!thr.valid) + thr = thread_start(export_result_d, search_result); + + if (!search_result->is_command_line_search) + thread_detach(&thr); + else + thread_join(&thr); + + return true; +} + +static bool read_json_file(char *buffer, s32 size, search_result *search_result) +{ + cJSON *result = cJSON_Parse(buffer); + if (!result) return false; + + cJSON *search_directory = cJSON_GetObjectItemCaseSensitive(result, "search_directory"); + string_copyn(textbox_path.buffer, search_directory->valuestring, MAX_INPUT_LENGTH); + string_copyn(search_result->directory_to_search, search_directory->valuestring, MAX_INPUT_LENGTH); + + cJSON *filter = cJSON_GetObjectItemCaseSensitive(result, "filter"); + string_copyn(textbox_file_filter.buffer, filter->valuestring, MAX_INPUT_LENGTH); + string_copyn(search_result->file_filter, filter->valuestring, MAX_INPUT_LENGTH); + + cJSON *search_query = cJSON_GetObjectItemCaseSensitive(result, "search_query"); + string_copyn(textbox_search_text.buffer, search_query->valuestring, MAX_INPUT_LENGTH); + string_copyn(search_result->text_to_find, search_query->valuestring, MAX_INPUT_LENGTH); + + cJSON *duration_us = cJSON_GetObjectItemCaseSensitive(result, "duration_us"); + search_result->find_duration_us = duration_us->valueint; + + cJSON *show_error = cJSON_GetObjectItemCaseSensitive(result, "show_error"); + search_result->show_error_message = show_error->valueint; + + cJSON *file_match_found = cJSON_GetObjectItemCaseSensitive(result, "file_match_found"); + search_result->found_file_matches = file_match_found->valueint; + + cJSON *files_searched = cJSON_GetObjectItemCaseSensitive(result, "files_searched"); + search_result->files_searched = files_searched->valueint; + + cJSON *files_matched = cJSON_GetObjectItemCaseSensitive(result, "files_matched"); + search_result->files_matched = files_matched->valueint; + + cJSON *query_match_found = cJSON_GetObjectItemCaseSensitive(result, "query_match_found"); + search_result->match_found = query_match_found->valueint; + + cJSON *recursive = cJSON_GetObjectItemCaseSensitive(result, "recursive_search"); + search_result->is_recursive = recursive->valueint; + checkbox_recursive.state = search_result->is_recursive; + + search_result->search_result_source_dir_len = strlen(search_result->directory_to_search); + + cJSON *file_list = cJSON_GetObjectItem(result, "match_list"); + cJSON *file; + cJSON_ArrayForEach(file, file_list) + { + file_match new_match; + + //// + cJSON *path = cJSON_GetObjectItem(file, "path"); + new_match.file.path = memory_bucket_reserve(&search_result->mem_bucket, strlen(path->valuestring)+1); + string_copyn(new_match.file.path, path->valuestring, strlen(path->valuestring)+1); + + //// + cJSON *matched_filter = cJSON_GetObjectItem(file, "matched_filter"); + new_match.file.matched_filter = memory_bucket_reserve(&search_result->mem_bucket, strlen(matched_filter->valuestring)+1); + string_copyn(new_match.file.matched_filter, matched_filter->valuestring, strlen(matched_filter->valuestring)+1); + + //// + cJSON *word_offset = cJSON_GetObjectItem(file, "word_offset"); + new_match.word_match_offset = word_offset->valueint; + + //// + cJSON *word_length = cJSON_GetObjectItem(file, "word_length"); + new_match.word_match_length = word_length->valueint; + + //// + cJSON *file_error = cJSON_GetObjectItem(file, "file_error"); + new_match.file_error = file_error->valueint; + + //// + cJSON *line_nr = cJSON_GetObjectItem(file, "line_nr"); + new_match.line_nr = line_nr->valueint; + + //// + cJSON *file_size = cJSON_GetObjectItem(file, "file_size"); + new_match.file_size = file_size->valueint; + + //// + cJSON *line_info = cJSON_GetObjectItem(file, "line_info"); + if (cJSON_IsString(line_info)) + { + new_match.line_info = memory_bucket_reserve(&search_result->mem_bucket, strlen(line_info->valuestring)+1); + string_copyn(new_match.line_info, line_info->valuestring, strlen(line_info->valuestring)+1); + search_result->match_found = true; + } + else + { + new_match.line_info = 0; + } + + // calculate highlight offsets + if (new_match.line_info) + { + new_match.word_match_offset_x = + calculate_text_width_upto(font_mini, new_match.line_info, new_match.word_match_offset); + + new_match.word_match_width = + calculate_text_width_from_upto(font_mini, new_match.line_info, new_match.word_match_offset, new_match.word_match_offset + new_match.word_match_length); + } + + array_push(&search_result->matches, &new_match); + } + + return true; +} + +void import_results_from_file(char *path_buf) +{ + char *file_extension = get_file_extension(path_buf); + if (!string_equals(file_extension, ".json") && !string_equals(file_extension, ".xml") && !string_equals(file_extension, ".yaml")) + { + platform_show_message(main_window, localize("invalid_search_result_file"), localize("error_importing_results")); + return; + } + + scroll_y = 0; + file_content content = platform_read_file_content(path_buf, "r"); + + if (!content.content || content.file_error) + { + platform_destroy_file_content(&content); + return; + } + + search_result *new_result = create_empty_search_result(); + search_result *old_result = current_search_result; + current_search_result = new_result; + + thread cleanup_thread = thread_start(destroy_search_result_thread, old_result); + thread_detach(&cleanup_thread); + + if (string_equals(file_extension, ".json")) + { + bool result = read_json_file(content.content, content.content_length, new_result); + if (!result) goto failed_to_load_file; + } + else + { + goto failed_to_load_file; + } + + new_result->walking_file_system = false; + new_result->done_finding_matches = true; + new_result->done_finding_files = true; + + snprintf(global_status_bar.result_status_text, MAX_INPUT_LENGTH, localize("files_matches_comparison"), current_search_result->matches.length, current_search_result->files_searched, current_search_result->find_duration_us/1000.0); + + array_destroy(&new_result->files); + platform_destroy_file_content(&content); + return; + + failed_to_load_file: + platform_show_message(main_window, localize("invalid_search_result_file"), localize("error_importing_results")); + platform_destroy_file_content(&content); +} + +static void* import_results_d(void *arg) +{ + char path_buf[MAX_INPUT_LENGTH]; + path_buf[0] = 0; + + char start_path[MAX_INPUT_LENGTH]; + snprintf(start_path, MAX_INPUT_LENGTH, "%s%s", binary_path, ""); + + char default_save_file_extension[50]; + string_copyn(default_save_file_extension, "json", 50); + + struct open_dialog_args *args = mem_alloc(sizeof(struct open_dialog_args)); + args->buffer = path_buf; + args->type = OPEN_FILE; + args->file_filter = SEARCH_RESULT_FILE_EXTENSION; + args->start_path = start_path; + args->default_save_file_extension = default_save_file_extension; + + platform_open_file_dialog_block(args); + + if (string_equals(path_buf, "")) return 0; + if (!platform_file_exists(path_buf)) return 0; + + import_results_from_file(path_buf); + return 0; +} + +void import_results() +{ + thread thr; + thr.valid = false; + + while (!thr.valid) + thr = thread_start(import_results_d, 0); + thread_detach(&thr); +}
\ No newline at end of file |
