diff --git a/comment.c b/comment.c
index 49c8bda..4b3b3fa 100644
--- a/comment.c
+++ b/comment.c
@@ -194,61 +194,3 @@ void comment_repository_delete(CommentRepository* repository, uint16_t first, ui
}
}
}
-
-#if 0
-// [todo] move to comment/load
-// Load comments from file.
-bool comment_repository_load(CommentRepository* repository, const char* filename) {
- assert(filename != NULL);
- assert(repository != NULL);
-
- bool ret = false;
-
- json_t* root;
- json_error_t err;
- json_t* value;
- int index = 0;
- root = json_load_file(filename, 0, &err);
- if(!root) {
- ERROR_MSG("Failed to parse %s:%d:%d: %s", filename, err.line, err.column, err.text);
- } else {
- if(!json_is_array(root)) {
- ERROR_MSG("Array expected.");
- } else for (index = 0, ret = true; ret && (index < json_array_size(root)) && (value = json_array_get(root, index)); index++) {
- ret = false;
- if(!json_is_object(value)) {
- ERROR_MSG("Expected object.");
- } else {
- int num;
- // logical
- json_t *tmp = json_object_get(value, "logical");
- if(!json_validate_int(tmp, &num)) {
- ERROR_MSG("Invalid or missing logical address.");
- } else if((num < 0) || (num > 0xffff)) {
- ERROR_MSG("Logical address out of range.");
- } else {
- uint16_t logical = (uint16_t)num;
- // page
- tmp = json_object_get(value, "page");
- if(!json_validate_int(tmp, &num)) {
- ERROR_MSG("Invalid or missing page.");
- } else {
- // text (same format as section/label description)
- char* text = json_load_description(value, "text");
- if(text == NULL) {
- ERROR_MSG("Invalid or missing text.");
- } else if((num < 0) || (num > 0xff)) {
- ERROR_MSG("Page value out of range.");
- } else if(comment_repository_add(repository, logical, (uint8_t)num, text)) {
- ret = true;
- }
- free(text);
- }
- }
- }
- }
- json_decref(root);
- }
- return ret;
-}
-#endif
\ No newline at end of file
diff --git a/comment.h b/comment.h
index 1087f52..1cb7be5 100644
--- a/comment.h
+++ b/comment.h
@@ -95,10 +95,17 @@ bool comment_repository_get(CommentRepository* repository, int index, Comment *o
void comment_repository_delete(CommentRepository* repository, uint16_t first, uint16_t end, uint8_t page);
/// Load comments from file.
+/// \param [in, out] repository Comment repository.
/// \param [in] filename Input filename.
-/// \param [out] repository Comment repository.
/// \return true if the comments contained in the file was succesfully added to the repository.
/// \return false if an error occured.
bool comment_repository_load(CommentRepository* repository, const char* filename);
+/// Save comments to file.
+/// \param [in] repository Comment repository.
+/// \param [in] filename Output filename.
+/// \return true if the comments were succesfully saved.
+/// \return false if an error occured.
+bool comment_repository_save(CommentRepository* repository, const char* filename);
+
#endif // ETRIPATOR_COMMENT_H
\ No newline at end of file
diff --git a/comment/load.c b/comment/load.c
new file mode 100644
index 0000000..710332a
--- /dev/null
+++ b/comment/load.c
@@ -0,0 +1,94 @@
+/*
+¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸
+¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯
+
+ __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__
+ \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_
+ _> ___/ ¯>__> <<__// __ _/ |> > _/> ¯ \\__> <<__// /\ // __ _/
+ _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_
+|:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::|
+|¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯|
+|__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _|
+ \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/
+
+¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸
+¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯
+
+ This file is part of Etripator,
+ copyright (c) 2009--2023 Vincent Cruz.
+
+ Etripator is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Etripator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Etripator. If not, see .
+
+¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸
+¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯
+*/
+#include
+#include "../message.h"
+#include "../jsonhelpers.h"
+#include "../comment.h"
+
+// Load comments from file.
+bool comment_repository_load(CommentRepository* repository, const char* filename) {
+ assert(filename != NULL);
+ assert(repository != NULL);
+
+ bool ret = false;
+
+ json_t* root;
+ json_error_t err;
+ json_t* value;
+ int index = 0;
+ root = json_load_file(filename, 0, &err);
+ if(!root) {
+ ERROR_MSG("Failed to parse %s:%d:%d: %s", filename, err.line, err.column, err.text);
+ } else {
+ if(!json_is_array(root)) {
+ ERROR_MSG("Array expected.");
+ } else for (index = 0, ret = true; ret && (index < json_array_size(root)) && (value = json_array_get(root, index)); index++) {
+ ret = false;
+ if(!json_is_object(value)) {
+ ERROR_MSG("Expected object.");
+ } else {
+ int num;
+ // logical
+ json_t *tmp = json_object_get(value, "logical");
+ if(!json_validate_int(tmp, &num)) {
+ ERROR_MSG("Invalid or missing logical address.");
+ } else if((num < 0) || (num > 0xffff)) {
+ ERROR_MSG("Logical address out of range.");
+ } else {
+ uint16_t logical = (uint16_t)num;
+ // page
+ tmp = json_object_get(value, "page");
+ if(!json_validate_int(tmp, &num)) {
+ ERROR_MSG("Invalid or missing page.");
+ } else {
+ // text (same format as section/label description)
+ char* text = json_load_description (value, "text");
+ if(text == NULL) {
+ ERROR_MSG("Invalid or missing text.");
+ } else if((num < 0) || (num > 0xFF)) {
+ ERROR_MSG("Page value out of range.");
+ } else if(comment_repository_add(repository, logical, (uint8_t)num, text)) {
+ ret = true;
+ }
+ free(text);
+ }
+ }
+ }
+ }
+ json_decref(root);
+ }
+ return ret;
+}
diff --git a/comment/save.c b/comment/save.c
new file mode 100644
index 0000000..4b63db0
--- /dev/null
+++ b/comment/save.c
@@ -0,0 +1,91 @@
+/*
+¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸
+¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯
+
+ __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__
+ \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_
+ _> ___/ ¯>__> <<__// __ _/ |> > _/> ¯ \\__> <<__// /\ // __ _/
+ _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_
+|:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::|
+|¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯|
+|__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _|
+ \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/
+
+¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸
+¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯
+
+ This file is part of Etripator,
+ copyright (c) 2009--2023 Vincent Cruz.
+
+ Etripator is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Etripator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Etripator. If not, see .
+
+¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸
+¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯
+*/
+#include
+#include
+
+#include "../message.h"
+#include "../jsonhelpers.h"
+#include "../comment.h"
+
+// Save comments to file.
+bool comment_repository_save(CommentRepository* repository, const char* filename) {
+ assert(filename != NULL);
+ assert(repository != NULL);
+
+ bool ret = false;
+
+ int i, count = comment_repository_size(repository);
+ FILE *stream = fopen(filename, "wb");
+ if(stream == NULL) {
+ ERROR_MSG("Failed to open %s: %s", filename, strerror(errno));
+ } else {
+ fprintf(stream, "[\n");
+ for(i=0; i