Skip to content

Commit ba91dc4

Browse files
committed
Finish strintifying process
1 parent 39225b0 commit ba91dc4

File tree

3 files changed

+82
-25
lines changed

3 files changed

+82
-25
lines changed

src/cjlib.c

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct incomplete_property_str
7575
{
7676
char *i_key; // The key of the current incomplete element.
7777
char *i_state; // How much of the JSON stringtifying process is done for the incomplete data.
78+
bool set_comma; // Determines whether to set commad when completing an object/array.
7879
enum cjlib_json_datatypes i_type; // The type of the incompelte object (object or array)
7980
struct cjlib_queue *i_pending_data_q; // The data that must be stored in the incomplete object (but not expanded yet).
8081
union {
@@ -631,6 +632,9 @@ int cjlib_json_read(struct cjlib_json *restrict dst)
631632
p_value = parse_property_value((const struct cjlib_json *) dst, p_name);
632633
if (NULL == p_value) goto read_err;
633634

635+
// If the current data is only a 'comma', nothing else, then ignore it.
636+
if (!strcmp(p_value, ",")) goto read_cleanup;
637+
634638
if (BUILDING_OBJECT(compl_indicator)) {
635639
if (!strcmp(ROOT_PROPERTY_NAME, p_name) &&
636640
!strcmp(ROOT_PROPERTY_NAME, curr_incomplete_data.i_name)) goto read_cleanup;
@@ -759,15 +763,19 @@ int cjlib_json_read(struct cjlib_json *restrict dst)
759763
* Otherwise NULL.
760764
*/
761765
static inline char *wrap_complete_entry(const char *entry_state, char opening_symbol,
762-
char closing_symbol)
766+
char closing_symbol, bool set_comma)
763767
{
764-
size_t additional_size = 2; // The size of {} or [].
768+
size_t additional_size = 3; // The size of {} or [] + comma.
765769
size_t wrapped_size = strlen(entry_state) + additional_size;
766770

767771
char *wrapped_state = (char *) malloc(wrapped_size + 1);
768772
if (NULL == wrapped_state) return NULL;
769773

770-
(void) sprintf(wrapped_state, "%c%s%c", opening_symbol, entry_state, closing_symbol);
774+
if (set_comma) {
775+
(void) sprintf(wrapped_state, "%c%s%c,", opening_symbol, entry_state, closing_symbol);
776+
} else {
777+
(void) sprintf(wrapped_state, "%c%s%c", opening_symbol, entry_state, closing_symbol);
778+
}
771779

772780
return wrapped_state;
773781
}
@@ -777,11 +785,12 @@ static inline char *wrap_complete_entry(const char *entry_state, char opening_sy
777785
* and produce a string that is in format KEY : DATA,
778786
*
779787
* @param src The data of the field.
788+
* @param set_comma Determines whether to insert a comma or not.
780789
* @return A string representing an entry of the JSON file (Format KEY : DATA,) -> (KEY COLON DATA COMMA) in success,
781790
* otherwise NULL is returned.
782791
*/
783792
static char *simple_key_value_paired_stringtify
784-
(const struct cjlib_json_data *restrict src)
793+
(const struct cjlib_json_data *restrict src, bool set_comma)
785794
{
786795
const size_t comma_len = 1;
787796
const size_t colon_len = 1;
@@ -797,29 +806,53 @@ static char *simple_key_value_paired_stringtify
797806
// LEN(KEY) + LEN(:) + LEN(VALUE) + LEN(,) + LEN("\0")
798807
result = (char *) malloc(strlen(src->c_value.c_str) + comma_len + colon_len + double_quotes_len + 1);
799808
if (NULL == result) return NULL;
800-
(void) sprintf(result, "\"%s\",", src->c_value.c_str);
809+
if (set_comma) {
810+
(void) sprintf(result, "\"%s\",", src->c_value.c_str);
811+
} else {
812+
(void) sprintf(result, "\"%s\"", src->c_value.c_str);
813+
}
801814
break;
802815
case CJLIB_NUMBER:
803816
digit_num = snprintf(NULL, 0, "%f", src->c_value.c_num);
804817
result = (char *) malloc(digit_num + comma_len + colon_len + 1);
805818
if (NULL == result) return NULL;
806-
(void) sprintf(result, "%f,", src->c_value.c_num);
819+
820+
if (set_comma) {
821+
(void) sprintf(result, "%f,", src->c_value.c_num);
822+
} else {
823+
(void) sprintf(result, "%f", src->c_value.c_num);
824+
}
807825
break;
808826
case CJLIB_BOOLEAN:
809827
if (src->c_value.c_boolean) {
810828
result = (char *) malloc(boolean_true_len + comma_len + colon_len + 1);
811829
if (NULL == result) return NULL;
812-
(void) sprintf(result, "%s,", "true");
830+
831+
if (set_comma) {
832+
(void) sprintf(result, "%s,", "true");
833+
} else {
834+
(void) sprintf(result, "%s", "true");
835+
}
813836
} else {
814837
result = (char *) malloc(boolean_false_len + comma_len + colon_len + 1);
815838
if (NULL == result) return NULL;
816-
(void) sprintf(result, "%s,", "false");
839+
840+
if (set_comma) {
841+
(void) sprintf(result, "%s,", "false");
842+
} else {
843+
(void) sprintf(result, "%s", "false");
844+
}
817845
}
818846
break;
819847
case CJLIB_NULL:
820848
result = (char *) malloc(null_len + comma_len + colon_len + 1);
821849
if (NULL == result) return NULL;
822-
(void) sprintf(result, "%s,", "null");
850+
851+
if (set_comma) {
852+
(void) sprintf(result, "%s,", "null");
853+
} else {
854+
(void) sprintf(result, "%s", "null");
855+
}
823856
break;
824857
default:
825858
break;
@@ -853,6 +886,7 @@ static inline int switch_from_incomplete_obj_str_data
853886
struct cjlib_json_data *examine_entry_data = CJLIB_DICT_NODE_DATA(entry);
854887
*dst = (struct incomplete_property_str) {
855888
.i_key = key_wrapped,
889+
.set_comma = true,
856890
.i_type = type,
857891
.i_state = strdup(""),
858892
.i_pending_data_q = (struct cjlib_queue *) malloc(sizeof(struct cjlib_queue))
@@ -884,6 +918,7 @@ struct cjlib_json_data *entry_data, const char *key)
884918
struct cjlib_json_data *examine_entry_data = entry_data;
885919
*dst = (struct incomplete_property_str) {
886920
.i_key = key_wrapped,
921+
.set_comma = true,
887922
.i_type = type,
888923
.i_state = strdup(""),
889924
.i_pending_data_q = (struct cjlib_queue *) malloc(sizeof(struct cjlib_queue))
@@ -924,12 +959,8 @@ static inline int convert_list_to_queue(struct cjlib_queue *restrict dst, const
924959
return 0;
925960
}
926961

927-
928962
const char *cjlib_json_object_stringtify(const cjlib_json_object *src)
929963
{
930-
/**
931-
* TODO - 1. Why some fields don't appear in the stringtifying version? (look type field in the JSON).
932-
*/
933964
struct incomplete_property_str curr_incomp; // The currently expanding data.
934965
struct cjlib_stack incomplete_st; // The stack of incomplete data.
935966

@@ -940,6 +971,8 @@ const char *cjlib_json_object_stringtify(const cjlib_json_object *src)
940971
char *tmp_key = NULL; // Used to temporary store the key of the complete JSON object/array.
941972
char *value_str = NULL; // Used to temporary store the strintify data (see default case in the switch below)
942973

974+
bool set_comma_tmp = true; // Helper, to maintain the information about whether to put comma or not on completion (see incomplete_str & on switch below.)
975+
943976
char opening_symbol_obj = CURLY_BRACKETS_OPEN;
944977
char opening_symbol_arr = SQUARE_BRACKETS_OPEN;
945978
char closing_symbol_obj = CURLY_BRACKETS_CLOSE;
@@ -972,16 +1005,16 @@ const char *cjlib_json_object_stringtify(const cjlib_json_object *src)
9721005
tmp_state = curr_incomp.i_state;
9731006
if (CJLIB_OBJECT == curr_incomp.i_type) {
9741007
curr_incomp.i_state = incomplete_property_str_expand_state(curr_incomp.i_state, value_str, tmp_key);
975-
free(tmp_key);
976-
tmp_key = NULL;
9771008
} else {
9781009
curr_incomp.i_state = incomplete_property_str_expand_state(curr_incomp.i_state, value_str, NULL);
9791010
}
9801011

1012+
free(tmp_key);
9811013
free(value_str);
9821014
free(tmp_state);
9831015
tmp_state = NULL;
9841016
value_str = NULL;
1017+
tmp_key = NULL;
9851018
}
9861019

9871020
while (!cjlib_queue_is_empty(curr_incomp.i_pending_data_q)) {
@@ -997,59 +1030,81 @@ const char *cjlib_json_object_stringtify(const cjlib_json_object *src)
9971030

9981031
switch (examine_entry_data->c_datatype) {
9991032
case CJLIB_OBJECT:
1033+
if (cjlib_queue_is_empty(curr_incomp.i_pending_data_q)) set_comma_tmp = false;
1034+
10001035
cjlib_stack_push(&curr_incomp, sizeof(struct incomplete_property_str),
10011036
&incomplete_st);
10021037

1003-
if (CJLIB_ARRAY == curr_incomp.i_type) examine_entry = examine_entry_data->c_value.c_obj;
1038+
if (CJLIB_ARRAY == curr_incomp.i_type) examine_entry = examine_entry_data->c_value.c_obj;
10041039
if (-1 == switch_from_incomplete_obj_str_data(&curr_incomp, CJLIB_OBJECT, examine_entry)) return NULL;
1040+
1041+
curr_incomp.set_comma = set_comma_tmp;
10051042

10061043
if (-1 == cjlib_dict_preorder(curr_incomp.i_pending_data_q, curr_incomp.i_data.object)) return NULL;
10071044
break;
10081045
case CJLIB_ARRAY:
1046+
if (cjlib_queue_is_empty(curr_incomp.i_pending_data_q)) set_comma_tmp = false;
10091047
cjlib_stack_push(&curr_incomp, sizeof(struct incomplete_property_str), &incomplete_st);
10101048

10111049
if (-1 == switch_from_incomplete_arr_str_data(&curr_incomp, CJLIB_ARRAY, examine_entry_data,
10121050
CJLIB_DICT_NODE_KEY(examine_entry))) return NULL;
10131051

1052+
curr_incomp.set_comma = set_comma_tmp;
10141053
convert_list_to_queue(curr_incomp.i_pending_data_q, curr_incomp.i_data.array);
10151054
break;
10161055
default:
10171056
tmp_state = curr_incomp.i_state;
10181057

10191058
if (CJLIB_OBJECT == curr_incomp.i_type) {
1020-
value_str = simple_key_value_paired_stringtify(CJLIB_DICT_NODE_DATA(examine_entry));
1021-
tmp_key = wrap_complete_entry(CJLIB_DICT_NODE_KEY(examine_entry),opening_symbol_str, closing_symbol_str);
1059+
if (cjlib_queue_is_empty(curr_incomp.i_pending_data_q)) {
1060+
value_str = simple_key_value_paired_stringtify(CJLIB_DICT_NODE_DATA(examine_entry), false);
1061+
} else {
1062+
value_str = simple_key_value_paired_stringtify(CJLIB_DICT_NODE_DATA(examine_entry), true);
1063+
}
1064+
1065+
tmp_key = wrap_complete_entry(CJLIB_DICT_NODE_KEY(examine_entry),opening_symbol_str, closing_symbol_str, false);
10221066
curr_incomp.i_state = incomplete_property_str_expand_state(curr_incomp.i_state, value_str,
10231067
tmp_key);
10241068

10251069
free(tmp_key);
10261070
tmp_key = NULL;
10271071
} else {
1028-
value_str = simple_key_value_paired_stringtify(examine_entry_data);
1072+
if (cjlib_queue_is_empty(curr_incomp.i_pending_data_q)) {
1073+
value_str = simple_key_value_paired_stringtify(examine_entry_data, false);
1074+
} else {
1075+
value_str = simple_key_value_paired_stringtify(examine_entry_data, true);
1076+
}
1077+
10291078
curr_incomp.i_state = incomplete_property_str_expand_state(curr_incomp.i_state, value_str, NULL);
10301079
}
10311080
free(tmp_state);
10321081
free(value_str);
10331082
tmp_state = NULL;
10341083
value_str = NULL;
10351084
break;
1036-
}
1085+
}
1086+
1087+
set_comma_tmp = true;
10371088
}
10381089

10391090
opening_symbol = (CJLIB_OBJECT == curr_incomp.i_type)? opening_symbol_obj : opening_symbol_arr;
10401091
closing_symbol = (CJLIB_OBJECT == curr_incomp.i_type)? closing_symbol_obj : closing_symbol_arr;
10411092

10421093
if (CJLIB_OBJECT == curr_incomp.i_type || CJLIB_ARRAY == curr_incomp.i_type) {
10431094
tmp_state = curr_incomp.i_state;
1044-
curr_incomp.i_state = wrap_complete_entry(curr_incomp.i_state, opening_symbol, closing_symbol);
1095+
1096+
if (cjlib_stack_is_empty(&incomplete_st) || !curr_incomp.set_comma) {
1097+
curr_incomp.i_state = wrap_complete_entry(curr_incomp.i_state, opening_symbol, closing_symbol, false);
1098+
} else {
1099+
curr_incomp.i_state = wrap_complete_entry(curr_incomp.i_state, opening_symbol, closing_symbol, true);
1100+
}
10451101

10461102
free(tmp_state);
10471103
if (NULL == curr_incomp.i_state) return NULL;
10481104
}
10491105

10501106
value_str = curr_incomp.i_state;
10511107

1052-
// TODO - wrap the array/object with the correct {} or [].
10531108
tmp_key = curr_incomp.i_key;
10541109
// Free the pending queue (there are no more incomplete data for the JSON object/array that were examined).
10551110
free(curr_incomp.i_pending_data_q);

src/cjlib_dictionary.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* File: cjlib_dictionary.c
77
*
88
************************************************************************
9-
* Copyright (C) 2024 Constantinos Argyriou
9+
* Copyright (C) 2024-2025 Constantinos Argyriou
1010
*
1111
* This program is free software: you can redistribute it and/or modify
1212
* it under the terms of the GNU General Public License as published by
@@ -135,7 +135,9 @@ int cjlib_dict_preorder(struct cjlib_queue *restrict dst, const struct avl_bs_tr
135135
root = root->avl_left;
136136
}
137137

138-
} while(!cjlib_stack_is_empty(&pre_order_traversal_st));
138+
if (cjlib_stack_is_empty(&pre_order_traversal_st) && NULL == root) break;
139+
140+
} while(true);
139141

140142
(void) memcpy(dst, &pre_order_data_q, sizeof(struct cjlib_stack));
141143

tests/src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ int main(void)
8686
(void) printf("%s\n", dst.c_value.c_str);*/
8787

8888

89-
cjlib_json_stringtify(&json_file);
89+
free((void *) cjlib_json_stringtify(&json_file));
9090

9191
// // Close the json file.
9292
cjlib_json_close(&json_file);

0 commit comments

Comments
 (0)