Skip to content

Commit f044fd4

Browse files
committed
Figure out how to encode the JSON in memory to a string version
1 parent e01216a commit f044fd4

File tree

3 files changed

+172
-34
lines changed

3 files changed

+172
-34
lines changed

include/cjlib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
typedef double cjlib_json_num;
3636
typedef bool cjlib_json_bool;
37-
typedef char * cjlib_json_path;
37+
typedef char *cjlib_json_path;
3838

3939
typedef FILE *cjlib_json_fd;
4040
typedef cjlib_dict_t cjlib_json_object;

src/cjlib.c

Lines changed: 169 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
#include "cjlib_dictionary.h"
3030
#include "cjlib_stack.h"
3131
#include "include/cjlib_dictionary.h"
32+
#include "include/cjlib_list.h"
3233
#include "include/cjlib_queue.h"
34+
#include "include/cjlib_stack.h"
3335

3436
#define DOUBLE_QUOTES (0x22) // ASCII representative of "
3537
#define CURLY_BRACKETS_OPEN (0x7B) // ASCII representative of {
@@ -75,19 +77,45 @@ struct incomplete_property
7577
*/
7678
struct incomplete_property_str
7779
{
78-
char *i_state; // How much of the object/array is complete.
79-
union
80-
{
81-
cjlib_json_object *object;
82-
cjlib_json_array *array;
80+
char *i_key; // The key of the current incomplete element.
81+
char *i_state; // How much of the JSON stringtifying process is done for the incomplete data.
82+
enum cjlib_json_datatypes i_type; // The type of the incompelte object (object or array)
83+
struct cjlib_queue *i_pending_data_q; // The data that must be stored in the incomplete object (but not expanded yet).
84+
union {
85+
cjlib_json_object *object; // The incomplete data is an object.
86+
cjlib_json_array *array; // The incompelte data is an array.
8387
} i_data;
8488
};
8589

86-
static void incomplete_property_init(struct incomplete_property *src)
90+
static inline void incomplete_property_init(struct incomplete_property *src)
8791
{
8892
(void) memset(src, 0x0, sizeof(struct incomplete_property));
8993
}
9094

95+
static inline void incomplete_property_str_init(struct incomplete_property_str *src)
96+
{
97+
(void) memset(src, 0x0, sizeof(struct incomplete_property_str));
98+
}
99+
100+
/**
101+
* Recieve the current active state of an object and expanded using
102+
* by storing the @data on the end of the @state.
103+
*
104+
* @param state The state of the incomplete data untill now.
105+
* @param data The data to add to the state.
106+
* @return The new state on success, otherwise NULL.
107+
*/
108+
static inline char *incomplete_property_str_expand_state
109+
(const char *state, const char *data)
110+
{
111+
char *new_state = (char *) malloc(strlen(state) + strlen(data) + 1);
112+
if (NULL == new_state) return NULL;
113+
114+
sprintf(new_state, "%s%s", state, data);
115+
116+
return new_state;
117+
}
118+
91119
int cjlib_json_object_set
92120
(cjlib_json_object *src, const char *restrict key,
93121
struct cjlib_json_data *restrict value, enum cjlib_json_datatypes datatype)
@@ -726,7 +754,8 @@ int cjlib_json_read(struct cjlib_json *restrict dst)
726754
* @return A string representing an entry of the JSON file (Format KEY : DATA,) -> (KEY COLON DATA COMMA) in success,
727755
* otherwise NULL is returned.
728756
*/
729-
static char *key_value_paired_stringtify(const struct cjlib_json_data *restrict src, const char *restrict key)
757+
static char *simple_key_value_paired_stringtify
758+
(const struct cjlib_json_data *restrict src, const char *restrict key)
730759
{
731760
const size_t comma_len = 1;
732761
const size_t colon_len = 1;
@@ -735,7 +764,7 @@ static char *key_value_paired_stringtify(const struct cjlib_json_data *restrict
735764
const size_t null_len = 4;
736765
size_t digit_num = 0;
737766

738-
char *result;
767+
char *result = NULL;
739768
switch (src->c_datatype) {
740769
case CJLIB_STRING:
741770
// LEN(KEY) + LEN(:) + LEN(VALUE) + LEN(,) + LEN("\0")
@@ -765,44 +794,153 @@ static char *key_value_paired_stringtify(const struct cjlib_json_data *restrict
765794
if (NULL == result) return NULL;
766795
sprintf(result, "%s:%s,", key, "null");
767796
break;
768-
case CJLIB_ARRAY:
769-
break;
770797
default:
771798
break;
772799
}
773800

774801
return result;
775802
}
776803

777-
const char *cjlib_json_object_stringtify(const cjlib_json_object *src)
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)
778812
{
779-
struct cjlib_queue object_data_q; // The queue where all nodes are stored.
780-
struct cjlib_queue pending_objects_q; // The queue where the object to be expanded are stored.
781-
782-
cjlib_dict_node_t *field; // The current key:paired field from the JSON in memory. (contains both the key and data)
783-
struct cjlib_json_data *field_data; // The data of the current field.
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;
784818

785-
// Initialize the queue.
786-
cjlib_queue_init(&object_data_q);
787-
cjlib_queue_init(&pending_objects_q);
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);
827+
if (NULL == result) return NULL;
828+
sprintf(result, "%f,", src->c_value.c_num);
829+
break;
830+
case CJLIB_BOOLEAN:
831+
if (src->c_value.c_boolean) {
832+
result = (char *) malloc(boolean_true_len + comma_len + 1);
833+
if (NULL == result) return NULL;
834+
sprintf(result, "%s,", "true");
835+
} else {
836+
result = (char *) malloc(boolean_false_len + comma_len + 1);
837+
if (NULL == result) return NULL;
838+
sprintf(result, "%s,", "false");
839+
}
840+
break;
841+
case CJLIB_NULL:
842+
result = (char *) malloc(null_len + comma_len + 1);
843+
if (NULL == result) return NULL;
844+
sprintf(result, "%s,", "null");
845+
break;
846+
default:
847+
break;
848+
}
849+
850+
return result;
851+
}
788852

789-
// Returns Queue<cjlib_dict_node *>
790-
if (-1 == cjlib_dict_postorder(&object_data_q, src)) return NULL;
853+
/**
854+
* Switches to another incompelete object,i.e., when a nested array or object is
855+
* detected.
856+
*
857+
* @param dst A pointer that points to the location to store the switched data.
858+
* @param type The type of the new data.
859+
* @param entry The incomplete object/array.
860+
* @param entry_key The key of the key:pair combination for the incomplete object/array.
861+
*/
862+
static inline int switch_incomplete_str_data
863+
(struct incomplete_property_str *restrict dst, enum cjlib_json_datatypes type,
864+
cjlib_json_object *entry)
865+
{
866+
struct cjlib_json_data *examine_entry_data = CJLIB_DICT_NODE_DATA(entry);
867+
*dst = (struct incomplete_property_str) {
868+
.i_key = strdup(CJLIB_DICT_NODE_KEY(entry)),
869+
.i_type = type,
870+
.i_state = strdup(""),
871+
.i_pending_data_q = (struct cjlib_queue *) malloc(sizeof(struct cjlib_queue))
872+
};
791873

792-
do {
793-
cjlib_queue_deqeue((void *) &field, sizeof(cjlib_dict_node_t *), &object_data_q);
874+
if (NULL == dst->i_pending_data_q) return -1;
794875

795-
// obtain the data
796-
field_data = (struct cjlib_json_data *) CJLIB_DICT_NODE_DATA(field);
876+
cjlib_queue_init(dst->i_pending_data_q);
797877

798-
if (field_data->c_datatype == CJLIB_STRING) {
799-
char *result = key_value_paired_stringtify(field_data, CJLIB_DICT_NODE_KEY(field));
800-
(void) printf("%s\n", result); // TODO - REMOVE THIS
878+
if (CJLIB_OBJECT == type) dst->i_data.object = entry;
879+
else dst->i_data.array = examine_entry_data->c_value.c_arr;
801880

802-
free(result);
803-
}
804-
} while(!cjlib_queue_is_empty(&object_data_q));
881+
return 0;
882+
}
805883

884+
const char *cjlib_json_object_stringtify(const cjlib_json_object *src)
885+
{
886+
struct incomplete_property_str curr_incomp; // The currently expanding data.
887+
struct cjlib_stack incomplete_st; // The stack of incomplete data.
888+
889+
cjlib_dict_node_t *examine_entry; // The current key:paired entry from the JSON in memory. (contains both the key and data)
890+
struct cjlib_json_data *examine_entry_data; // The data of the examined entry.
891+
892+
// Initiazize the incomplete data.
893+
incomplete_property_str_init(&curr_incomp);
894+
cjlib_stack_init(&incomplete_st);
895+
896+
switch_incomplete_str_data(&curr_incomp, CJLIB_OBJECT, (cjlib_json_object *) src);
897+
898+
if (-1 == cjlib_dict_postorder(curr_incomp.i_pending_data_q,
899+
curr_incomp.i_data.object)) return NULL;
900+
901+
// Put a dummy entry in the stack to start the process.
902+
if (-1 == cjlib_stack_push((void *) &curr_incomp, sizeof(struct incomplete_property_str),
903+
&incomplete_st)) return NULL;
904+
905+
while (!cjlib_stack_is_empty(&incomplete_st)) {
906+
if (-1 == cjlib_stack_pop((void *) &curr_incomp, sizeof(struct incomplete_property_str),
907+
&incomplete_st)) return NULL;
908+
909+
while (!cjlib_queue_is_empty(curr_incomp.i_pending_data_q)) {
910+
// 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);
913+
914+
switch (examine_entry_data->c_datatype) {
915+
case CJLIB_OBJECT:
916+
cjlib_stack_push(&curr_incomp, sizeof(struct incomplete_property_str),
917+
&incomplete_st);
918+
919+
if (-1 == switch_incomplete_str_data(&curr_incomp, CJLIB_OBJECT,
920+
examine_entry)) return NULL;
921+
922+
if (-1 == cjlib_dict_postorder(curr_incomp.i_pending_data_q,
923+
curr_incomp.i_data.object)) return NULL;
924+
break;
925+
case CJLIB_ARRAY:
926+
cjlib_stack_push(&curr_incomp, sizeof(struct incomplete_property_str),
927+
&incomplete_st);
928+
929+
if (-1 == switch_incomplete_str_data(&curr_incomp, CJLIB_ARRAY,
930+
examine_entry)) return NULL;
931+
932+
// TODO - make something similar to postorder, but for arrays, and store
933+
// the result in the pending queue.
934+
break;
935+
default:
936+
// TODO - handle the simple case here (the examine data is not object or array)
937+
break;
938+
}
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+
}
943+
}
806944

807945
return NULL;
808946
}

src/include/cjlib_dictionary.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
struct cjlib_json_data;
3030

3131
// Requires a pointer and accesses the key of a node.
32-
#define CJLIB_DICT_NODE_KEY(NODE_PTR) NODE_PTR->avl_key
32+
#define CJLIB_DICT_NODE_KEY(NODE_PTR) (NODE_PTR)->avl_key
3333

3434
// Requires a pointer and accesses the data of a node.
35-
#define CJLIB_DICT_NODE_DATA(NODE_PTR) NODE_PTR->avl_data
35+
#define CJLIB_DICT_NODE_DATA(NODE_PTR) (NODE_PTR)->avl_data
3636

3737
/**
3838
* AVL Binary search tree node.

0 commit comments

Comments
 (0)