https://github.com/J-Kyu/jsmn
Original creator of jsmn: zserge
(※설명과 해석은 어디까지나 글쓴이의 주관적 사고로 부터 나왔습니다※)
<JSMN-jsondump.c>
1.jsondump.c
-앞에서 설명한 simple.c 는 JSON_STRING(이미 정해진)을 parsing하여 출력 값을 보여 주었다 (참고: http://kyu-tag.tistory.com/1)
하지만, jsnondump.c는 직접 stdin으로 부터 받아서 parsing을 통해서 출력하는 코드이다
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "../jsmn.h"
/* Function realloc_it() is a wrapper function for standard realloc()
* with one difference - it frees old memory pointer in case of realloc
* failure. Thus, DO NOT use old data pointer in anyway after call to
* realloc_it(). If your code has some kind of fallback algorithm if
* memory can't be re-allocated - use standard realloc() instead.
*/
static inline void *realloc_it(void *ptrmem, size_t size) { //void 포인터에 size만큼의 ptrmem을 만든다.
void *p = realloc(ptrmem, size);
if (!p) { //만약 p가 메모리 할당이 되지 않는 경우
free (ptrmem); //parameter로 받은 ptrmem의 메모리를 free하고
fprintf(stderr, "realloc(): errno=%d\n", errno); //error를 출력한다
}
return p;
}
//reallo_it() 함수는 원래 realloct함수의 wrapper function이다. 만약 reallocation이 실패하는 경우 오래된 메모리 포이턴를 free해준다
/*
* An example of reading JSON from stdin and printing its content to stdout.
* The output looks like YAML, but I'm not sure if it's really compatible.
*/
static int dump(const char *js, jsmntok_t *t, size_t count, int indent) {
int i, j, k;
if (count == 0) {
return 0;
}
if (t->type == JSMN_PRIMITIVE) {
printf("%.*s", t->end - t->start, js+t->start); //jsmn을 통해 parsing 받은 token의 type이 primitive이면, 해당 token을 출력한다
return 1;
} else if (t->type == JSMN_STRING) {
printf("'%.*s'", t->end - t->start, js+t->start);//jsmn을 통해 parsing 받은 token의 type이 String이면, 해당 token을 출력한다
return 1;
} else if (t->type == JSMN_OBJECT) { //jsmn을 통해 parsing 받은 token의 type이 object이면,
printf("\n"); //다시한번 해당 object를 dump 함수에 넣어서 String과 primitive type을 구분한 뒤
j = 0; //":"를 기준으로 해당 object의 group을 출력한다
for (i = 0; i < t->size; i++) {
for (k = 0; k < indent; k++) printf(" ");
j += dump(js, t+1+j, count-j, indent+1);
printf(": ");
j += dump(js, t+1+j, count-j, indent+1);
printf("\n");
}
return j+1;
} else if (t->type == JSMN_ARRAY) { //jsmn을 통해 parsing 받은 token의 type이 array이면, 해당 token을 다시한번 parsing한다
j = 0;
printf("\n");
for (i = 0; i < t->size; i++) {
for (k = 0; k <indent-1; k++) printf(" "); // 출력 형태를 다듬는다 " "
printf(" - "); //해당 array의 value를 출력할때 앞에 "-"를 부친다
j += dump(js, t+1+j, count-j, indent+1); //parsing한 array를 출력한다
printf("\n");
}
return j+1;
}
return 0;
}
int main() {
int r;
int eof_expected = 0;
char *js = NULL;
size_t jslen = 0;
char buf[BUFSIZ]; //buf라는 char array에 BUFSIZ인 8192의 크기 만큼 들어가 있다
jsmn_parser p;
jsmntok_t *tok;
size_t tokcount = 2;
/* Prepare parser */
jsmn_init(&p);
/* Allocate some tokens as a start */
tok = malloc(sizeof(*tok) * tokcount);
if (tok == NULL) {
fprintf(stderr, "malloc(): errno=%d\n", errno);
return 3;
}
p
for (;;) { //무한루프로 돌리기 때문에 계속해서 string을 받아 r에 저장하여 parsing 한다
/* Read another chunk */
r = fread(buf, 1, sizeof(buf), stdin); //stdin으로 부터 sizeof(buf)만큼의 element를 char형 buf array에 저장한다. return은 읽어준 element의 크기만큼 돌려준다
//sizeof(buf)만큼을 채울 수 없다면, EOF를 통해서 (ctrl+d)를 통해서 fread()를 빠져 나갈수 있다
if (r < 0) {
fprintf(stderr, "fread(): %d, errno=%d\n", r, errno); //fread로 읽었을 때, 오류가 생기면 -1을 출력하여 error를 발한다
return 1;
}
if (r == 0) {
if (eof_expected != 0) {
return 0;
} else {
fprintf(stderr, "fread(): unexpected EOF\n"); //fread로 읽어 올 때, 아무것도 읽어 오지 않으면 0을 반환하는데 parsing할께 없으니 당연히 error를 발하고 프로그램을 종료한다
return 2;
}
}
js = realloc_it(js, jslen + r + 1); //js에 r을 통해서 받은 buf의 array를 넣기 위해 추가로 js에 메모리를 할당해준다
if (js == NULL) {
return 3;
}
strncpy(js + jslen, buf,r); //r을 통해서 stdin으로 부터 받아온 값을 js에 저장한다
jslen = jslen + r;
again:
r = jsmn_parse(&p, js, jslen, tok, tokcount); //저장된 r을 jsmn_parse를 통해서 parsing하고 출력한다
if (r < 0) {
if (r == JSMN_ERROR_NOMEM) { //error를 검사한다
tokcount = tokcount * 2;
tok = realloc_it(tok, sizeof(*tok) * tokcount);
if (tok == NULL) {
return 3;
}
goto again;다 }
} else {
dump(js, tok, p.toknext, 0);
eof_expected = 1;
}
}
return EXIT_SUCCESS;
}
2. jsmn과 jsmndump.c
-jsmndump.c의 기본적인 흐름은 이렇다
1.jsmnsdump.c의 main 함수에서 fread를 통해서 string을 받아 r에 저장을 한다.
2. r에 대해서 요류를 검사한다.
3.문제가 없는 경우 jsmn 함수로 보내서 parsing을 하여 출력한다.....
4.다시 1번을 실행한다
-사용된 jsmn함수
3. 입력 form 및 출력
앞전에 설명한 simple.c에서는 ....
static const char *JSON_STRING ="{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n ""\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"]}";
으로 {}안에 ":"을 기준으로 분리하고 array같은 경우 []으로 구분 지어 주었다
jsmndump.c 에서도 똑같이 { } 안에 parsing될 value를 넣고 ": "으로 구분지어주면 될 것이다
ex)
{name:J-kyu,Age:23,INFO:[Studnet,Computer-Science Major,etc.....]} //를 입력하고 ctrl+D를 누르면 아래와 같이 실행된다
Modified and explained by Kyu
'OSS' 카테고리의 다른 글
[Ubuntu] Package tool&Network status (0) | 2018.05.07 |
---|---|
[Ubuntu]Defaul page (Index.html) modify 1.01 (0) | 2018.04.30 |
[Command]git 기초2 (0) | 2018.04.09 |
[Command]git의 기초1 (0) | 2018.04.07 |
[설명서]MacOS에서 Github사용법 (0) | 2018.04.07 |