Skip to content

Commit bd01ba1

Browse files
committed
Almost done with the strintify process
1 parent f044fd4 commit bd01ba1

File tree

2 files changed

+112
-88
lines changed

2 files changed

+112
-88
lines changed

src/cjlib.c

Lines changed: 105 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* File: cjlib.c
22
************************************************************************
3-
* Copyright (C) 2024 Constantinos Argyriou
3+
* Copyright (C) 2024-2025 Constantinos Argyriou
44
*
55
* This program is free software: you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -28,10 +28,8 @@
2828
#include "cjlib_error.h"
2929
#include "cjlib_dictionary.h"
3030
#include "cjlib_stack.h"
31-
#include "include/cjlib_dictionary.h"
32-
#include "include/cjlib_list.h"
33-
#include "include/cjlib_queue.h"
34-
#include "include/cjlib_stack.h"
31+
#include "cjlib_list.h"
32+
#include "cjlib_queue.h"
3533

3634
#define DOUBLE_QUOTES (0x22) // ASCII representative of "
3735
#define CURLY_BRACKETS_OPEN (0x7B) // ASCII representative of {
@@ -106,12 +104,17 @@ static inline void incomplete_property_str_init(struct incomplete_property_str *
106104
* @return The new state on success, otherwise NULL.
107105
*/
108106
static inline char *incomplete_property_str_expand_state
109-
(const char *state, const char *data)
107+
(const char *state, const char *data, const char *key)
110108
{
111-
char *new_state = (char *) malloc(strlen(state) + strlen(data) + 1);
109+
size_t key_size = (NULL == key)? 0 : strlen(key);
110+
char *new_state = (char *) malloc(strlen(state) + strlen(data) + key_size + 1);
112111
if (NULL == new_state) return NULL;
113-
114-
sprintf(new_state, "%s%s", state, data);
112+
113+
if (NULL == key) {
114+
sprintf(new_state, "%s%s", state, data);
115+
} else {
116+
sprintf(new_state, "%s%s:%s", state, key, data);
117+
}
115118

116119
return new_state;
117120
}
@@ -750,12 +753,11 @@ int cjlib_json_read(struct cjlib_json *restrict dst)
750753
* and produce a string that is in format KEY : DATA,
751754
*
752755
* @param src The data of the field.
753-
* @param key The respective key of the field.
754756
* @return A string representing an entry of the JSON file (Format KEY : DATA,) -> (KEY COLON DATA COMMA) in success,
755757
* otherwise NULL is returned.
756758
*/
757759
static char *simple_key_value_paired_stringtify
758-
(const struct cjlib_json_data *restrict src, const char *restrict key)
760+
(const struct cjlib_json_data *restrict src)
759761
{
760762
const size_t comma_len = 1;
761763
const size_t colon_len = 1;
@@ -768,78 +770,29 @@ static char *simple_key_value_paired_stringtify
768770
switch (src->c_datatype) {
769771
case CJLIB_STRING:
770772
// LEN(KEY) + LEN(:) + LEN(VALUE) + LEN(,) + LEN("\0")
771-
result = (char *) malloc(strlen(key) + strlen(src->c_value.c_str) + comma_len + colon_len + 1);
773+
result = (char *) malloc(strlen(src->c_value.c_str) + comma_len + colon_len + 1);
772774
if (NULL == result) return NULL;
773-
sprintf(result, "%s:%s,", key, src->c_value.c_str);
775+
sprintf(result, "%s,", src->c_value.c_str);
774776
break;
775777
case CJLIB_NUMBER:
776778
digit_num = snprintf(NULL, 0, "%f", src->c_value.c_num);
777-
result = (char *) malloc(strlen(key) + digit_num + comma_len + colon_len + 1);
778-
if (NULL == result) return NULL;
779-
sprintf(result, "%s:%f,", key, src->c_value.c_num);
780-
break;
781-
case CJLIB_BOOLEAN:
782-
if (src->c_value.c_boolean) {
783-
result = (char *) malloc(strlen(key) + boolean_true_len + comma_len + colon_len + 1);
784-
if (NULL == result) return NULL;
785-
sprintf(result, "%s:%s,", key, "true");
786-
} else {
787-
result = (char *) malloc(strlen(key) + boolean_false_len + comma_len + colon_len + 1);
788-
if (NULL == result) return NULL;
789-
sprintf(result, "%s:%s,", key, "false");
790-
}
791-
break;
792-
case CJLIB_NULL:
793-
result = (char *) malloc(strlen(key) + null_len + comma_len + colon_len + 1);
794-
if (NULL == result) return NULL;
795-
sprintf(result, "%s:%s,", key, "null");
796-
break;
797-
default:
798-
break;
799-
}
800-
801-
return result;
802-
}
803-
804-
/**
805-
* Take data from an array as an argument and encode it to the format
806-
* of the JSON like array.
807-
*
808-
* @param src The data of the JSON array.
809-
* @return A string representing the format of JSON array data ( DATA, -> DATA COMMA)
810-
*/
811-
static inline char *array_data_strintify(struct cjlib_json_data *restrict src)
812-
{
813-
const size_t comma_len = 1;
814-
const size_t boolean_true_len = 4;
815-
const size_t boolean_false_len = 5;
816-
const size_t null_len = 4;
817-
size_t digit_num = 0;
818-
819-
char *result = NULL;
820-
switch (src->c_datatype) {
821-
case CJLIB_STRING:
822-
result = strdup(src->c_value.c_str);
823-
break;
824-
case CJLIB_NUMBER:
825-
digit_num = snprintf(NULL, 0, "%f", src->c_value.c_num);
826-
result = (char *) malloc(digit_num + comma_len + 1);
779+
result = (char *) malloc(digit_num + comma_len + colon_len + 1);
827780
if (NULL == result) return NULL;
828781
sprintf(result, "%f,", src->c_value.c_num);
829782
break;
830783
case CJLIB_BOOLEAN:
831784
if (src->c_value.c_boolean) {
832-
result = (char *) malloc(boolean_true_len + comma_len + 1);
785+
result = (char *) malloc(boolean_true_len + comma_len + colon_len + 1);
833786
if (NULL == result) return NULL;
834787
sprintf(result, "%s,", "true");
835788
} else {
836-
result = (char *) malloc(boolean_false_len + comma_len + 1);
789+
result = (char *) malloc(boolean_false_len + comma_len + colon_len + 1);
837790
if (NULL == result) return NULL;
838791
sprintf(result, "%s,", "false");
839792
}
840793
break;
841794
case CJLIB_NULL:
842-
result = (char *) malloc(null_len + comma_len + 1);
795+
result = (char *) malloc(null_len + comma_len + colon_len + 1);
843796
if (NULL == result) return NULL;
844797
sprintf(result, "%s,", "null");
845798
break;
@@ -881,22 +834,51 @@ static inline int switch_incomplete_str_data
881834
return 0;
882835
}
883836

837+
/**
838+
* Convert the provided @src list into a queue.
839+
*
840+
* The queue consists of pointers that point to the objects
841+
* in the list. (NO NEED FOR FREE FOR THOSE OBJECTS NEEDED).
842+
* This is done for optimization purposes (to allocate and free
843+
* two times the same data).
844+
*
845+
* @param dst A pointer to the queue in which the pointers are stored.
846+
* @param src A pointer to the list from which the paointers will be extracted.
847+
* @return 0 on success, otherwise -1.
848+
*/
849+
static int convert_list_to_queue(struct cjlib_queue *restrict dst, const struct cjlib_list *restrict src)
850+
{
851+
struct cjlib_json_data *item;
852+
853+
CJLIB_LIST_FOR_EACH_PTR(item, src, struct cjlib_json_data) {
854+
// Store the pointers of each element in the list into the @dst
855+
if ( -1 == cjlib_queue_enqeue((void *) &item, sizeof(struct cjlib_json_data *), dst)) {
856+
return -1;
857+
}
858+
}
859+
860+
return 0;
861+
}
862+
884863
const char *cjlib_json_object_stringtify(const cjlib_json_object *src)
885864
{
886865
struct incomplete_property_str curr_incomp; // The currently expanding data.
887866
struct cjlib_stack incomplete_st; // The stack of incomplete data.
888867

889868
cjlib_dict_node_t *examine_entry; // The current key:paired entry from the JSON in memory. (contains both the key and data)
890869
struct cjlib_json_data *examine_entry_data; // The data of the examined entry.
891-
870+
871+
char *tmp_state = NULL; // Used to control the memory (see default case in the switch below)
872+
char *tmp_key = NULL; // Used to temporary store the key of the complete JSON object/array.
873+
char *value_str = NULL; // Used to temporary store the strintify data (see default case in the switch below)
874+
892875
// Initiazize the incomplete data.
893876
incomplete_property_str_init(&curr_incomp);
894877
cjlib_stack_init(&incomplete_st);
895878

896-
switch_incomplete_str_data(&curr_incomp, CJLIB_OBJECT, (cjlib_json_object *) src);
879+
if (-1 == switch_incomplete_str_data(&curr_incomp, CJLIB_OBJECT, (cjlib_json_object *) src)) return NULL;
897880

898-
if (-1 == cjlib_dict_postorder(curr_incomp.i_pending_data_q,
899-
curr_incomp.i_data.object)) return NULL;
881+
if (-1 == cjlib_dict_postorder(curr_incomp.i_pending_data_q, curr_incomp.i_data.object)) return NULL;
900882

901883
// Put a dummy entry in the stack to start the process.
902884
if (-1 == cjlib_stack_push((void *) &curr_incomp, sizeof(struct incomplete_property_str),
@@ -906,43 +888,78 @@ const char *cjlib_json_object_stringtify(const cjlib_json_object *src)
906888
if (-1 == cjlib_stack_pop((void *) &curr_incomp, sizeof(struct incomplete_property_str),
907889
&incomplete_st)) return NULL;
908890

891+
tmp_state = curr_incomp.i_state;
892+
if (CJLIB_OBJECT == curr_incomp.i_type) {
893+
curr_incomp.i_state = incomplete_property_str_expand_state(curr_incomp.i_state, value_str, tmp_key);
894+
free(tmp_key);
895+
tmp_key = NULL;
896+
} else {
897+
curr_incomp.i_state = incomplete_property_str_expand_state(curr_incomp.i_state, value_str, NULL);
898+
}
899+
900+
free(value_str);
901+
free(tmp_state);
902+
tmp_state = NULL;
903+
value_str = NULL;
904+
909905
while (!cjlib_queue_is_empty(curr_incomp.i_pending_data_q)) {
910906
// Get the entry to strintify.
911-
cjlib_queue_deqeue((void *) &examine_entry, sizeof(cjlib_dict_node_t *), curr_incomp.i_pending_data_q);
912-
examine_entry_data = CJLIB_DICT_NODE_DATA(examine_entry);
907+
908+
if (CJLIB_OBJECT == curr_incomp.i_type) {
909+
// The queue of an incomplete object consists of NODES of avl binary tree.
910+
cjlib_queue_deqeue((void *) &examine_entry, sizeof(cjlib_dict_node_t *), curr_incomp.i_pending_data_q);
911+
examine_entry_data = CJLIB_DICT_NODE_DATA(examine_entry);
912+
} else {
913+
// The queue of an incomplete array consists of NODES of a linked list.
914+
cjlib_queue_deqeue((void *) &examine_entry_data, sizeof(struct cjlib_json_data), curr_incomp.i_pending_data_q);
915+
}
913916

914917
switch (examine_entry_data->c_datatype) {
915918
case CJLIB_OBJECT:
916919
cjlib_stack_push(&curr_incomp, sizeof(struct incomplete_property_str),
917920
&incomplete_st);
918921

919-
if (-1 == switch_incomplete_str_data(&curr_incomp, CJLIB_OBJECT,
920-
examine_entry)) return NULL;
922+
if (-1 == switch_incomplete_str_data(&curr_incomp, CJLIB_OBJECT, examine_entry)) return NULL;
921923

922-
if (-1 == cjlib_dict_postorder(curr_incomp.i_pending_data_q,
923-
curr_incomp.i_data.object)) return NULL;
924+
if (-1 == cjlib_dict_postorder(curr_incomp.i_pending_data_q, curr_incomp.i_data.object)) return NULL;
924925
break;
925926
case CJLIB_ARRAY:
926-
cjlib_stack_push(&curr_incomp, sizeof(struct incomplete_property_str),
927-
&incomplete_st);
927+
cjlib_stack_push(&curr_incomp, sizeof(struct incomplete_property_str), &incomplete_st);
928928

929-
if (-1 == switch_incomplete_str_data(&curr_incomp, CJLIB_ARRAY,
930-
examine_entry)) return NULL;
929+
if (-1 == switch_incomplete_str_data(&curr_incomp, CJLIB_ARRAY, examine_entry)) return NULL;
931930

932-
// TODO - make something similar to postorder, but for arrays, and store
933-
// the result in the pending queue.
931+
convert_list_to_queue(curr_incomp.i_pending_data_q, curr_incomp.i_data.array);
934932
break;
935933
default:
936-
// TODO - handle the simple case here (the examine data is not object or array)
934+
tmp_state = curr_incomp.i_state;
935+
936+
if (CJLIB_OBJECT == curr_incomp.i_type) {
937+
value_str = simple_key_value_paired_stringtify(CJLIB_DICT_NODE_DATA(examine_entry));
938+
curr_incomp.i_state = incomplete_property_str_expand_state(curr_incomp.i_state, value_str,
939+
CJLIB_DICT_NODE_KEY(examine_entry));
940+
} else {
941+
value_str = simple_key_value_paired_stringtify(examine_entry_data);
942+
curr_incomp.i_state = incomplete_property_str_expand_state(curr_incomp.i_state, value_str, NULL);
943+
}
944+
free(tmp_state);
945+
free(value_str);
946+
tmp_state = NULL;
947+
value_str = NULL;
937948
break;
938949
}
939-
// TODO - write a function to wrap an object with {} and an array with [].
940-
// TODO - after finishing with the nested while, then free the memory of the current incomplete object
941-
// before switching back to the previous incomplete object/array.
942-
}
950+
}
951+
952+
value_str = curr_incomp.i_state; // Save the pointer that points to the state of the complete object/array.
953+
// TODO - wrap the array/object with the correct {} or [].
954+
tmp_key = curr_incomp.i_key;
955+
// Free the pending queue (there are no more incomplete data for the JSON object/array that were examined).
956+
free(curr_incomp.i_pending_data_q);
957+
curr_incomp.i_pending_data_q = NULL;
943958
}
944959

945-
return NULL;
960+
free(curr_incomp.i_key);
961+
// Return the now completed JSON.
962+
return curr_incomp.i_state;
946963
}
947964

948965
int cjlib_json_dump(const struct cjlib_json *restrict src)

src/include/cjlib_list.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@
3131
for (struct cjlib_list_node *node = (LIST_PTR)->l_head, *keep = 0x0; node != NULL; node = node->l_next, keep = 0x0) \
3232
for ((ITEM) = *((TYPE *) node->l_data); keep == 0x0; keep = node)
3333

34+
/**
35+
* For each implementation, but the ITEM is a pointer
36+
*/
37+
#define CJLIB_LIST_FOR_EACH_PTR(ITEM_PTR, LIST_PTR, TYPE) \
38+
for (struct cjlib_list_node *node = (LIST_PTR)->l_head, *keep = 0x0; node != NULL; node = node->l_next, keep = 0x0) \
39+
for ((ITEM_PTR) = ((TYPE *) node->l_data); keep == 0x0; keep = node)
40+
3441
struct cjlib_list_node
3542
{
3643
void *l_data;

0 commit comments

Comments
 (0)