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 */
7678struct 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+
91119int 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}
0 commit comments