Skip to content

Commit c449bb4

Browse files
committed
Updated gitignore file. Fixed parser function prototype arguments. Added include guard to typestack header file. Fixed pointer handling issue, function argument (char**) was incremented instead of argument's (char**) underlying pointer (char*). Fixed StringBuilder, buffer is now written to pointer's pointer instead of to the pointer pointer directly. Fixed number parser's number string length calculation. Added example/testing code to parse the coinbase btc api JSON string. Improved comments.
1 parent c33aab5 commit c449bb4

File tree

7 files changed

+201
-23
lines changed

7 files changed

+201
-23
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
.vs/
33
.vscode/
44

5+
# Ignore build directories
6+
bin/
7+
obj/
8+
59
# Ignore CodeBlocks Project files
610
*.cbp
11+
*.depend
712
*.layout

inc/cJSON.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ cJSON_Result_t cJSON_delGenObj(cJSON_Generic_t GObj);
5757
* @param str String containing the JSON data.
5858
* @return cJSON_Result_t Returns cJSON_Ok by default. Can return one of the following errors: cJSON_DepthOutOfRange_Error, cJSON_Structure_Error, cJSON_InvalidCharacterSequence_Error.
5959
*/
60-
cJSON_Result_t cJSON_parseStr(cJSON_Generic_t *GObjPtr, char *str);
60+
cJSON_Result_t cJSON_parseStr(cJSON_Generic_t *GObjPtr, const char *str);
6161

6262
#pragma endregion
6363

inc/cJSON_Constants.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,19 @@
1010
#include "cJSON_Types.h"
1111

1212
/**
13-
* @brief Contains the highest possible depth that is allowed by the specified depth type (cJSON_depth_t)
13+
* @brief Highest possible depth that is allowed by the specified depth type (cJSON_depth_t)
1414
*
1515
*/
16-
#define CJSON_MAX_DEPTH ((cJSON_depth_t) 0xFFFFFFFFFFFFFFFF)
16+
#define CJSON_MAX_DEPTH ((cJSON_depth_t) 0xFFFFFFFFFFFFFFFF)
17+
18+
/**
19+
* @brief Maximum length of a string containing a number
20+
*
21+
*/
22+
#define CJSON_MAX_NUM_LEN 32u
1723

1824
/**
1925
* @brief Size of the cJSON parser StringBuilder's preBuffer. Max: 255U
2026
*
2127
*/
22-
#define CJSON_PARSE_STRING_PB_SIZE 10U
28+
#define CJSON_PARSE_STRING_PB_SIZE 10U

inc/cJSON_GenericStack.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
*
88
*/
99

10+
#ifndef CJSON_TYPESTACK_DEFINED
11+
#define CJSON_TYPESTACK_DEFINED
1012

1113
#include "cJSON_Types.h"
1214

@@ -115,7 +117,7 @@ typedef enum cJSON_GenericStack_Result
115117
#pragma region Struct Typedefs
116118

117119
/**
118-
* @brief cJSON_GenericStack_t is a struct for a stack used for
120+
* @brief cJSON_GenericStack_t is a struct for a stack used for interations with the JSON data structure.
119121
*
120122
*/
121123
typedef struct cJSON_GenericStack
@@ -206,3 +208,5 @@ bool GS_IsEmpty(cJSON_GenericStack_t *TSptr);
206208
bool GS_IsFull(cJSON_GenericStack_t *TSptr);
207209

208210
#pragma endregion
211+
212+
#endif // CJSON_TYPESTACK_DEFINED

main.c

Lines changed: 159 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,169 @@
11
#include <stdio.h>
22
#include <stdlib.h>
3+
#include <string.h>
34

45
// Include cJSON Library
56
#include "inc/cJSON.h"
67

8+
// - Testing Constant Variables -
9+
10+
// - Testing Function Prototypes -
11+
cJSON_String_t readFileContents(const char* fileName);
12+
void printBtcValue(const char* JSONstr);
13+
714
int main()
815
{
9-
printf("cJSON Library Test Script\n");
16+
printf("cJSON library test script\n\n");
17+
18+
// Get test type
19+
printf(" --- Enter Test Type ---\n");
20+
21+
//printf("\"a\": Parse JSON string\n");
22+
//printf("\"A\": Parse JSON file\n");
23+
printf("\"b\": Bitcoin value from coinbase API's JSON string\n"); //https://api.coinbase.com/v2/prices/spot?currency=USD
24+
//printf("\"B\": Bitcoin value from coinbase API's JSON string (file)\n"); //https://api.coinbase.com/v2/prices/spot?currency=USD
25+
26+
// Get test type
27+
char testType = getchar();
28+
// Discard remaining characters in input
29+
while (getchar() != '\n' && getchar() != EOF);
30+
31+
switch(testType)
32+
{
33+
case 'a':
34+
printf("Test not implemented!\n");
35+
break;
36+
case 'A':
37+
printf("Test not implemented!\n");
38+
break;
39+
case 'b':;
40+
char JSON_BtcStr[100];
41+
42+
// Get string
43+
printf("Enter string from bitcoin API:");
44+
fgets(JSON_BtcStr, 100, stdin);
45+
46+
printBtcValue(JSON_BtcStr);
47+
break;
48+
case 'B':
49+
printf("Test not implemented!\n");
50+
break;
51+
default:
52+
printf("Invalid test type \"%c\"\n", testType);
53+
break;
54+
}
55+
1056
return 0;
1157
}
58+
59+
// - Testing Function Implementations -
60+
cJSON_String_t readFileContents(const char* fileName)
61+
{
62+
FILE *fPtr = fopen(fileName, "r");
63+
if (!fPtr) {
64+
perror("Failed to open file");
65+
return NULL;
66+
}
67+
68+
// Seek to the end of the file to get the file size
69+
fseek(fPtr, 0, SEEK_END);
70+
long fileSize = ftell(fPtr);
71+
rewind(fPtr);
72+
73+
// Allocate memory for the file content plus the null terminator
74+
cJSON_String_t buffer = (cJSON_String_t)malloc((fileSize + 1) * sizeof(char));
75+
if (!buffer) {
76+
perror("Failed to allocate memory");
77+
fclose(fPtr);
78+
return NULL;
79+
}
80+
81+
// Read the file contents into the buffer
82+
size_t bytesRead = fread(buffer, sizeof(char), fileSize, fPtr);
83+
buffer[bytesRead] = '\0'; // Null-terminate the string
84+
85+
// Clean up and return the buffer
86+
fclose(fPtr);
87+
return buffer;
88+
}
89+
90+
void printBtcValue(const char* JSONstr)
91+
{
92+
// Create empty cJSON generic container
93+
cJSON_Generic_t Base_cJSON_Tree = {0};
94+
95+
// Parse string into variable
96+
cJSON_Result_t funcResult = cJSON_parseStr(&Base_cJSON_Tree, JSONstr);
97+
if (funcResult != cJSON_Ok)
98+
{
99+
printf("Parse failed with error code %d!\n", (int)funcResult);
100+
return;
101+
}
102+
103+
printf("\nSuccessfully parsed string!\n");
104+
105+
// Write base cJSON tree to relative cJSON tree
106+
cJSON_Generic_t Rel_cJSON_Tree = Base_cJSON_Tree;
107+
108+
// Temporary dictionary object
109+
cJSON_Dict_t dictObj = {0};
110+
111+
funcResult = cJSON_tryGetDict(Rel_cJSON_Tree, &dictObj);
112+
if (funcResult != cJSON_Ok)
113+
{
114+
printf("Base is not a dictionary!\n");
115+
return;
116+
}
117+
118+
// Get generic object at "data" key
119+
for (int i = 0; i < dictObj.length; i++)
120+
{
121+
if (!strcmp(dictObj.keyData[i], "data"))
122+
{
123+
Rel_cJSON_Tree = dictObj.valueData[i];
124+
break;
125+
}
126+
else if (i == (dictObj.length - 1))
127+
{
128+
printf("Missing \"data\" key in dictionary!\n");
129+
return;
130+
}
131+
}
132+
133+
funcResult = cJSON_tryGetDict(Rel_cJSON_Tree, &dictObj);
134+
if (funcResult != cJSON_Ok)
135+
{
136+
printf("Generic object at \"data\" key is not a dictionary!\n");
137+
return;
138+
}
139+
140+
// Get generic object at "data" -> "amount" key
141+
for (int i = 0; i < dictObj.length; i++)
142+
{
143+
if (!strcmp(dictObj.keyData[i], "amount"))
144+
{
145+
Rel_cJSON_Tree = dictObj.valueData[i];
146+
break;
147+
}
148+
else if (i == (dictObj.length - 1))
149+
{
150+
printf("Missing \"amount\" key in dictionary!\n");
151+
return;
152+
}
153+
}
154+
155+
cJSON_String_t btcStr;
156+
157+
// Try get bitcoin amount string
158+
funcResult = cJSON_tryGetString(Rel_cJSON_Tree, &btcStr);
159+
if (funcResult != cJSON_Ok)
160+
{
161+
printf("Generic object at \"amount\" key is not a string!\n");
162+
return;
163+
}
164+
165+
// Print bitcoin amount
166+
printf("Bicoin value in USD: $%s\n", btcStr);
167+
168+
cJSON_delGenObj(Base_cJSON_Tree);
169+
}

src/cJSON.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* @brief cJSON library c source file.
55
* @version 0.1
66
* @date 2024-08-10
7-
*
7+
*
88
*/
99

1010
#include "../inc/cJSON.h"
@@ -289,7 +289,7 @@ cJSON_Result_t cJSON_parseStr(cJSON_Generic_t *GObjPtr, const char *str)
289289
{
290290
// String is a dictionary key, extract key string to activeKey variable
291291
strBuilderResult = cJSON_Parser_StringBuilder(&str, &activeKey);
292-
292+
293293
pFlags = CJP_DICT_SEPT_POSSIBLE;
294294
}
295295
else if (pFlags & CJP_DICT_VALUE_POSSIBLE)
@@ -480,7 +480,7 @@ cJSON_Result_t cJSON_tryGetDict(cJSON_Generic_t GObj, cJSON_Dict_t *dict)
480480
*dict = AS_DICT(GObj);
481481
return cJSON_Ok;
482482
}
483-
483+
484484
return cJSON_Datatype_Error;
485485
}
486486
cJSON_Result_t cJSON_tryGetList(cJSON_Generic_t GObj, cJSON_List_t *list)
@@ -490,7 +490,7 @@ cJSON_Result_t cJSON_tryGetList(cJSON_Generic_t GObj, cJSON_List_t *list)
490490
*list = AS_LIST(GObj);
491491
return cJSON_Ok;
492492
}
493-
493+
494494
return cJSON_Datatype_Error;
495495
}
496496
cJSON_Result_t cJSON_tryGetString(cJSON_Generic_t GObj, cJSON_String_t *str)
@@ -502,7 +502,7 @@ cJSON_Result_t cJSON_tryGetString(cJSON_Generic_t GObj, cJSON_String_t *str)
502502
strcpy(*str, AS_STRING(GObj));
503503
return cJSON_Ok;
504504
}
505-
505+
506506
return cJSON_Datatype_Error;
507507
}
508508
cJSON_Result_t cJSON_tryGetInt(cJSON_Generic_t GObj, cJSON_Int_t *intVal)
@@ -512,7 +512,7 @@ cJSON_Result_t cJSON_tryGetInt(cJSON_Generic_t GObj, cJSON_Int_t *intVal)
512512
*intVal = AS_INT(GObj);
513513
return cJSON_Ok;
514514
}
515-
515+
516516
return cJSON_Datatype_Error;
517517
}
518518
cJSON_Result_t cJSON_tryGetFloat(cJSON_Generic_t GObj, cJSON_Float_t *floatVal)
@@ -522,7 +522,7 @@ cJSON_Result_t cJSON_tryGetFloat(cJSON_Generic_t GObj, cJSON_Float_t *floatVal)
522522
*floatVal = AS_FLOAT(GObj);
523523
return cJSON_Ok;
524524
}
525-
525+
526526
return cJSON_Datatype_Error;
527527
}
528528
cJSON_Result_t cJSON_tryGetBool(cJSON_Generic_t GObj, cJSON_Bool_t *boolVal)
@@ -532,7 +532,7 @@ cJSON_Result_t cJSON_tryGetBool(cJSON_Generic_t GObj, cJSON_Bool_t *boolVal)
532532
*boolVal = AS_BOOL(GObj);
533533
return cJSON_Ok;
534534
}
535-
535+
536536
return cJSON_Datatype_Error;
537537
}
538538

@@ -548,7 +548,7 @@ cJSON_Result_t cJSON_tryGetDictPtr(cJSON_Generic_t GObj, cJSON_Dict_t **dictPtr)
548548
*dictPtr = AS_DICT_PTR(GObj);
549549
return cJSON_Ok;
550550
}
551-
551+
552552
return cJSON_Datatype_Error;
553553
}
554554
cJSON_Result_t cJSON_tryGetListPtr(cJSON_Generic_t GObj, cJSON_List_t **listPtr)
@@ -558,7 +558,7 @@ cJSON_Result_t cJSON_tryGetListPtr(cJSON_Generic_t GObj, cJSON_List_t **listPtr)
558558
*listPtr = AS_LIST_PTR(GObj);
559559
return cJSON_Ok;
560560
}
561-
561+
562562
return cJSON_Datatype_Error;
563563
}
564564
cJSON_Result_t cJSON_tryGetStringPtr(cJSON_Generic_t GObj, cJSON_String_t *strPtr)
@@ -568,7 +568,7 @@ cJSON_Result_t cJSON_tryGetStringPtr(cJSON_Generic_t GObj, cJSON_String_t *strPt
568568
*strPtr = AS_STRING(GObj);
569569
return cJSON_Ok;
570570
}
571-
571+
572572
return cJSON_Datatype_Error;
573573
}
574574
cJSON_Result_t cJSON_tryGetIntPtr(cJSON_Generic_t GObj, cJSON_Int_t **intValPtr)
@@ -578,7 +578,7 @@ cJSON_Result_t cJSON_tryGetIntPtr(cJSON_Generic_t GObj, cJSON_Int_t **intValPtr)
578578
*intValPtr = AS_INT_PTR(GObj);
579579
return cJSON_Ok;
580580
}
581-
581+
582582
return cJSON_Datatype_Error;
583583
}
584584
cJSON_Result_t cJSON_tryGetFloatPtr(cJSON_Generic_t GObj, cJSON_Float_t **floatValPtr)
@@ -588,7 +588,7 @@ cJSON_Result_t cJSON_tryGetFloatPtr(cJSON_Generic_t GObj, cJSON_Float_t **floatV
588588
*floatValPtr = AS_FLOAT_PTR(GObj);
589589
return cJSON_Ok;
590590
}
591-
591+
592592
return cJSON_Datatype_Error;
593593
}
594594
cJSON_Result_t cJSON_tryGetBoolPtr(cJSON_Generic_t GObj, cJSON_Bool_t **boolValPtr)
@@ -598,7 +598,7 @@ cJSON_Result_t cJSON_tryGetBoolPtr(cJSON_Generic_t GObj, cJSON_Bool_t **boolValP
598598
*boolValPtr = AS_BOOL_PTR(GObj);
599599
return cJSON_Ok;
600600
}
601-
601+
602602
return cJSON_Datatype_Error;
603603
}
604604

0 commit comments

Comments
 (0)