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를 누르면 아래와 같이 실행된다






Original coded by zserge

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

+ Recent posts