aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ttt.jai417
1 files changed, 187 insertions, 230 deletions
diff --git a/ttt.jai b/ttt.jai
index 2dac60b..42c68d7 100644
--- a/ttt.jai
+++ b/ttt.jai
@@ -14,14 +14,15 @@
// this program. If not, see <https://www.gnu.org/licenses/>.
// Compilation commands:
-// - release : jai ttt.jai -import_dir . -x64 -release
-// - debug : jai ttt.jai -import_dir . -x64
+// - release : jai ttt.jai -import_dir . -quiet -x64 -release
+// - debug : jai ttt.jai -import_dir . -quiet -x64
#import "Basic"()(MEMORY_DEBUGGER=true);
#import "System";
#import "Math";
#import "POSIX";
#import "File";
+#import "File_Utilities";
#import "String";
#import "curses";
@@ -155,17 +156,6 @@ void show_processing() {
refresh();
}
-// Checks if file is exists and is accessible.
-// Returns true when the file exists and is accessible.
-bool is_file_accessible(const char *path) {
- assert(path != NULL);
- FILE *file = fopen(path, "r+");
- bool is_file_accessible = file != NULL;
- if (is_file_accessible) {
- fclose(file);
- }
- return is_file_accessible;
-}
*/
// Returns true if string to_compare is equal to any of the other passed strings, false otherwise.
@@ -237,19 +227,13 @@ is_empty_string :: (str: string) -> bool {
}
return true;
}
-/*
-// Uses strchr to replace all instances of find by replace.
-// Returns string.
-replace_char :: (str: string, char find, char replace) -> string { // TODO Use modules/String/module.jai:replace_chars
- // TODO replace_chars :: (s: string, chars: string, replacement: u8) {
- char *idx = string;
- while((idx = strchr(idx, find)) != NULL) {
- *idx = replace;
- idx++;
- }
- return string;
-}
+replace_char :: (str: string, find: u8, replace: u8) -> string {
+ assert(false, "Use modules/String/module.jai:replace_chars");
+ // TODO Use modules/String/module.jai:replace_chars
+ return "";
+}
+/*
// Prints, on row y and column x, the time using 5 characters centered on space.
// Returns the result of a call to mvprintw.
int mvprintw_time(int y, int x, intmax_t time, int space) {
@@ -606,52 +590,73 @@ void add_task_time(database_st *db, task_st *task, int day, int64_t time) {
task->times[day] = add_int64(task->times[day], time);
db->total_times[day] = add_int64(db->total_times[day], time);
}
+*/
// Resets database to the initial state and deallocates all memory taken by tasks.
-void reset_database(database_st *db) {
- assert(db != NULL);
+reset_database :: (db: *Database) {
+ assert(db != null);
- free(db->tasks);
- memset(db, 0, SIZEOF_DATABASE_ST);
- db->active_task = -1;
- db->selected_task = -1;
+ free(db.tasks.data);
+ <<db = .{};
}
// Stores data from database into binary file.
// Returns success.
-bool store_database(const database_st *db, const char *path) {
- assert(db != NULL);
- assert(path != NULL);
+// bool store_database(const database_st *db, const char *path) {
+// assert(db != NULL);
+// assert(path != NULL);
+//
+// Open file.
+// FILE *file = fopen(path, "wb");
+// if (file == NULL) {
+// print_error("Failed to open file '%s' while storing database: %s.", path, strerror(errno));
+// return false;
+// }
+//
+// fwrite(DB_FILE_SIGN, SIZEOF_CHAR, DB_FILE_SIGN_LENGTH, file);
+// fwrite(db, SIZEOF_DATABASE_ST, 1, file);
+// fwrite(db->tasks, SIZEOF_TASK_ST, db->count, file);
+//
+// fclose(file);
+// return true;
+// }
+
+// Stores data from database into binary file.
+// Returns success.
+store_database :: (db: *Database, path: string) -> success: bool {
+ assert(db != null, "Parameter 'db' is null.");
+ assert(xx path, "Parameter 'path' is empty.");
// Open file.
- FILE *file = fopen(path, "wb");
- if (file == NULL) {
- print_error("Failed to open file '%s' while storing database: %s.", path, strerror(errno));
+ file, open_success := file_open(path, for_writing = true); // log_errors: bool = true
+ if open_success == false {
+ print_error("Failed to open file '%' while storing database: ERROR_FROM_LOG", path); // TODO Get error from logger ?!
return false;
}
+ defer file_close(*file);
- fwrite(DB_FILE_SIGN, SIZEOF_CHAR, DB_FILE_SIGN_LENGTH, file);
- fwrite(db, SIZEOF_DATABASE_ST, 1, file);
- fwrite(db->tasks, SIZEOF_TASK_ST, db->count, file);
-
- fclose(file);
+ file_write(*file, DB_FILE_SIGN_STR);
+ file_write(*file, db, size_of(Database));
+ file_write(*file, db.tasks.data, size_of(Task)*db.tasks.count);
+
return true;
}
// Loads data from binary file into database.
// Returns success.
+/*
bool load_database(database_st *db, const char *path) {
assert(db != NULL);
assert(path != NULL);
- // Open file.
+ Open file.
FILE *file = fopen(path, "rb");
if (file == NULL) {
print_error("Failed to open file '%s' while loading database: %s.", path, strerror(errno));
return false;
}
- // Validate file signature.
+ Validate file signature.
char file_signature[DB_FILE_SIGN_LENGTH];
fread(&file_signature, SIZEOF_CHAR, DB_FILE_SIGN_LENGTH, file);
if (strncmp(file_signature, DB_FILE_SIGN, DB_FILE_SIGN_LENGTH) != 0) {
@@ -660,10 +665,10 @@ bool load_database(database_st *db, const char *path) {
return false;
}
- // Read database structure.
+ Read database structure.
fread(db, SIZEOF_DATABASE_ST, 1, file);
- // Reserve database capacity for tasks.
+ Reserve database capacity for tasks.
size_t capacity_bytes = db->capacity * SIZEOF_TASK_ST;
db->tasks = malloc(capacity_bytes);
if (db->tasks == NULL && capacity_bytes > 0) {
@@ -671,46 +676,110 @@ bool load_database(database_st *db, const char *path) {
return false;
}
- // Read database tasks.
+ Read database tasks.
fread(db->tasks, SIZEOF_TASK_ST, db->count, file);
- // Make sure we are reading all the file.
+ Make sure we are reading all the file.
assert(fgetc(file) == EOF);
fclose(file);
return true;
-}
+}*/
-// Exports data into CSV file.
+// Loads data from binary file into database.
// Returns success.
-bool export_to_csv(const database_st *db, const char *path) {
- assert(db != NULL);
- assert(path != NULL);
+load_database :: (db: *Database, path: string) -> success: bool {
+ assert(db != null, "Parameter 'db' is null.");
+ assert(xx path, "Parameter 'path' is empty.");
- FILE *file = fopen(path, "w");
- if (file == NULL) {
- print_error("Failed to open file '%s' while exporting to CSV: %s.", path, strerror(errno));
+ // Open file.
+ file, open_success := file_open(path); // log_errors: bool = true
+ if open_success == false {
+ print_error("Failed to open file '%' while loading database: ERROR_FROM_LOG", path); // TODO Get error from logger ?!
return false;
}
+ defer file_close(*file);
- fprintf(file, "%s,%s,%s,%s,%s,%s,%s,%s\n",
- "task", "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"
- );
+ // Validate file signature.
+ file_signature: [DB_FILE_SIGN_STR.count] u8;
+ read_success := file_read(file, *file_signature, DB_FILE_SIGN_STR.count);
+ if read_success == false print_error("Failed to read file signature from '%'.", path);
+ if cast(string)file_signature != DB_FILE_SIGN_STR {
+ print_error("Invalid file signature.");
+ file_close(*file);
+ return false;
+ }
- char name[TASK_NAME_BYTES];
- for (size_t idx = 0; idx < db->count; idx++) {
- task_st *task = &db->tasks[idx];
- memcpy(name, task->name, TASK_NAME_BYTES);
- replace_char(name, ',', ' ');
- fprintf(file, "%s,%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 "\n",
- name, task->times[0], task->times[1], task->times[2], task->times[3], task->times[4], task->times[5], task->times[6]
- );
+ // Read database structure.
+ read_success = file_read(file, db, size_of(Database));
+ db.tasks.data = null; // Discard invalid pointer read into 'data'.
+ //if read_success == false print_error("Failed to read database info from '%'.", path); TODO
+
+ //file_open :: (name: string, for_writing := false, keep_existing_content := false, log_errors := true) -> File, bool
+ //file_read :: (f: File, vdata: *void, bytes_to_read: s64) -> (success: bool, total_read: s64)
+
+
+ // Reserve database capacity for tasks. HACK
+ value := db.tasks.count;
+ d: [..] Task;
+ db.tasks = d;
+// array_reserve(*db.tasks, value);
+// db.tasks.count = value;
+
+// size_t capacity_bytes = db->capacity * SIZEOF_TASK_ST;
+// db->tasks = malloc(capacity_bytes);
+// if (db->tasks == NULL && capacity_bytes > 0) {
+// print_error("Failed to allocate memory while loading database: %s.", strerror(errno));
+// return false;
+// }
+//
+ // Read database tasks. HACK
+ for 0..value-1 {
+ task: Task;
+ file_read(file, *task, size_of(Task));
+ array_add(*db.tasks, task);
}
+// file_read(file, db.tasks.data, size_of(Task)*db.tasks.count);
+
+ // Make sure we are reading all the file.
+ buffer: [1] u8;
+ success, bytes := file_read(file, *buffer, 1);
+ assert(bytes == 0);
+
+ print("done importing CSV with a bunch of hacks\n");
- fclose(file);
return true;
}
-*/
+
+// Exports data into CSV file.
+// Returns success.
+export_to_csv :: (db: *Database, path: string) -> success: bool {
+ assert(db != null, "Parameter 'db' is null.");
+ assert(xx path, "Parameter 'path' is empty.");
+ // TODO Make sure (IN ALL PROCEDURES) we're not receiving an empty path.
+
+
+ builder: String_Builder;
+ defer reset(*builder);
+
+ CSV_HEADER :: string.[ "task", "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ];
+ print_to_builder(*builder, "%\n", join(..CSV_HEADER, separator = ","));
+
+ buffer: [Task.name.count] u8;
+ name: string = xx buffer;
+ for db.tasks {
+ memcpy(name.data, it.name.data, name.count);
+ replace_chars(name, ",", #char " ");
+ print_to_builder(*builder, "%,%,%,%,%,%,%,%\n",
+ name, it.times[0], it.times[1], it.times[2],
+ it.times[3], it.times[4], it.times[5], it.times[6]);
+ }
+
+ write_entire_file(path, *builder);
+
+ return true;
+}
+
// Imports CSV file into database.
// Returns success.
import_from_csv :: (db: *Database, path: string) -> bool {
@@ -831,7 +900,7 @@ import_from_csv :: (db: *Database, path: string) -> bool {
print("temp: %\n", context.temporary_storage.total_bytes_occupied >> 20);
reset_temporary_storage();
- return false;
+ return true;
}
/*
// Appends task to the end of the CSV file.
@@ -1295,6 +1364,9 @@ bool read_enter_confirmation(int row, int style, const char *message) {
main :: () {
+ database: Database;
+ archive: Database;
+
defer report_memory_leaks(); // TODO DEBUG
defer free_memory();
@@ -1308,158 +1380,43 @@ main :: () {
home_path, success_path := get_absolute_path(home_dir); // Returns temporary memory. TODO LEAK
if success_path == false {
print_error("Failed to find home directory '%'.", home_dir);
- return;
+ exit(1);
}
app_directory = join(home_path, "/", APP_FOLDER_NAME);
db_file_path = join(app_directory, "/", DB_FILE_NAME);
ar_file_path = join(app_directory, "/", AR_FILE_NAME);
- }
-
-
- db: Database;
- {
- import_from_csv(*db, ar_file_path);
-
- for db.tasks print_task(it);
-
- print_task :: (task: Task) {
- for task.times print("% |", it);
- print(" %\n", cast(string)task.name);
- }
- return;
-
- // Stores data from database into binary file.
- // Returns success.
- store_database :: (db: Database, path: string) -> success: bool {
- //assert(db != null, "Parameter 'db' is null.");
- assert(xx path, "Parameter 'path' is empty.");
-
- // Open file.
- file, open_success := file_open(path, for_writing = true); // log_errors: bool = true
- if open_success == false {
- print_error("Failed to open file '%' while storing database: ERROR_FROM_LOG", path); // TODO Get error from logger ?!
- return false;
- }
- defer file_close(*file);
-
- file_write(*file, DB_FILE_SIGN_STR);
- file_write(*file, *db, size_of(Database));
- //fwrite(DB_FILE_SIGN, SIZEOF_CHAR, DB_FILE_SIGN_LENGTH, file);
- //fwrite(db, SIZEOF_DATABASE_ST, 1, file);
- //fwrite(db->tasks, SIZEOF_TASK_ST, db->count, file);
+ make_directory_if_it_does_not_exist(app_directory, recursive = true);
+ }
- return true;
- }
-
- // Loads data from binary file into database.
- // Returns success.
- load_database :: (db: *Database, path: string) -> success: bool {
- assert(db != null, "Parameter 'db' is null.");
- assert(xx path, "Parameter 'path' is empty.");
-
- // Open file.
- file, open_success := file_open(path); // log_errors: bool = true
- if open_success == false {
- print_error("Failed to open file '%' while loading database: ERROR_FROM_LOG", path); // TODO Get error from logger ?!
- return false;
- }
- defer file_close(*file);
-
- // Validate file signature.
- file_signature: [DB_FILE_SIGN_STR.count] u8;
- read_success := file_read(file, *file_signature, DB_FILE_SIGN_STR.count);
- if read_success == false print_error("Failed to read file signature from '%'.", path);
- if cast(string)file_signature != DB_FILE_SIGN_STR {
- print_error("Invalid file signature.");
- file_close(*file);
- return false;
- }
-
- // Read database structure.
-
- read_success = file_read(file, db, size_of(Database));
- //if read_success == false print_error("Failed to read database info from '%'.", path);
-
-
- //file_open :: (name: string, for_writing := false, keep_existing_content := false, log_errors := true) -> File, bool
- //file_read :: (f: File, vdata: *void, bytes_to_read: s64) -> (success: bool, total_read: s64)
-
- return true;
- }
-
-
- // Loads data from binary file into database.
- // Returns success.
- /*
- load_database :: (
+ { // Initialize database and archive files if needed.
-
- bool load_database(database_st *db, const char *path) {
- assert(db != NULL);
- assert(path != NULL);
-
- // Open file.
- FILE *file = fopen(path, "rb");
- if (file == NULL) {
- print_error("Failed to open file '%s' while loading database: %s.", path, strerror(errno));
- return false;
- }
-
- // Validate file signature.
- char file_signature[DB_FILE_SIGN_LENGTH];
- fread(&file_signature, SIZEOF_CHAR, DB_FILE_SIGN_LENGTH, file);
- if (strncmp(file_signature, DB_FILE_SIGN, DB_FILE_SIGN_LENGTH) != 0) {
- print_error("Invalid file signature.");
- fclose(file);
- return false;
+ if (file_exists(db_file_path) == false) {
+ if (store_database(*database, db_file_path) == false) {
+ print_error("Failed to initialize database.");
+ exit(1);
}
-
- // Read database structure.
- fread(db, SIZEOF_DATABASE_ST, 1, file);
-
- // Reserve database capacity for tasks.
- size_t capacity_bytes = db->capacity * SIZEOF_TASK_ST;
- db->tasks = malloc(capacity_bytes);
- if (db->tasks == NULL && capacity_bytes > 0) {
- print_error("Failed to allocate memory while loading database: %s.", strerror(errno));
- return false;
- }
-
- // Read database tasks.
- fread(db->tasks, SIZEOF_TASK_ST, db->count, file);
-
- // Make sure we are reading all the file.
- assert(fgetc(file) == EOF);
-
- fclose(file);
- return true;
}
- */
- }
-
- return; // TODO DEBUG
-
- /*
- db = &database;
- reset_database(&database);
- reset_database(&archive);
- if (is_file_accessible(db_file_path) == false) {
- if (store_database(&database, db_file_path) == false) {
- print_error("Failed to initialize database.");
- return;
+ if (file_exists(ar_file_path) == false) {
+ if (export_to_csv(*archive, ar_file_path) == false) {
+ print_error("Failed to initialize archive.");
+ exit(1);
+ }
}
- }
- if (is_file_accessible(ar_file_path) == false) {
- if (export_to_csv(&archive, ar_file_path) == false) {
- print_error("Failed to initialize archive.");
- return;
- }
+
+// import_from_csv(*db, ar_file_path);
+//
+// for db.tasks print_task(it);
+//
+// print_task :: (task: Task) {
+// for task.times print("% |", it);
+// print(" %\n", cast(string)task.name);
+// }
+// return;
}
- */
args := get_command_line_arguments();
defer array_reset(*args);
@@ -1531,19 +1488,19 @@ main :: () {
return;
}
// TODO Implement
-// if (load_database(&database, db_file_path) == false) {
-// print_error("Failed to load database.");
-// return;
-// }
-// if (import_from_csv(&database, args[it]) == false) {
-// print_error("Failed to import CSV file.");
-// return;
-// }
-// if (store_database(&database, db_file_path) == false) {
-// print_error("Failed to store database.");
-// return;
-// }
-// reset_database(&database);
+ if (load_database(*database, db_file_path) == false) {
+ print_error("Failed to load database.");
+ return;
+ }
+ if (import_from_csv(*database, args[it]) == false) {
+ print_error("Failed to import CSV file.");
+ return;
+ }
+ if (store_database(*database, db_file_path) == false) {
+ print_error("Failed to store database.");
+ return;
+ }
+ reset_database(*database);
is_exit_requested = true;
continue;
}
@@ -1555,15 +1512,15 @@ main :: () {
return;
}
// TODO Implement
-// if (load_database(&database, db_file_path) == false) {
-// print_error("Failed to load database.");
-// return;
-// }
-// if (export_to_csv(&database, args[it]) == false) {
-// print_error("Failed to export CSV file.");
-// return;
-// }
-// reset_database(&database);
+ if (load_database(*database, db_file_path) == false) {
+ print_error("Failed to load database.");
+ return;
+ }
+ if (export_to_csv(*database, args[it]) == false) {
+ print_error("Failed to export CSV file.");
+ return;
+ }
+ reset_database(*database);
is_exit_requested = true;
continue;
}