source: trunk/libtransmission/json.c @ 12223

Last change on this file since 12223 was 12223, checked in by jordan, 11 years ago

(trunk) copyediting: remove some unneeded #includes, and annotate some needed ones

  • Property svn:keywords set to Date Rev Author Id
File size: 4.7 KB
Line 
1/*
2 * This file Copyright (C) Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: json.c 12223 2011-03-24 21:49:42Z jordan $
11 */
12
13#include <assert.h>
14#include <ctype.h>
15#include <errno.h> /* EILSEQ, EINVAL */
16
17#include "JSON_parser.h"
18
19#include "transmission.h"
20#include "bencode.h"
21#include "json.h"
22#include "ptrarray.h"
23#include "utils.h"
24
25struct json_benc_data
26{
27    bool        hasContent;
28    tr_benc      * top;
29    tr_ptrArray    stack;
30    char         * key;
31};
32
33static tr_benc*
34getNode( struct json_benc_data * data )
35{
36    tr_benc * parent;
37    tr_benc * node = NULL;
38
39    if( tr_ptrArrayEmpty( &data->stack ) )
40        parent = NULL;
41    else
42        parent = tr_ptrArrayBack( &data->stack );
43
44    if( !parent )
45        node = data->top;
46    else if( tr_bencIsList( parent ) )
47        node = tr_bencListAdd( parent );
48    else if( tr_bencIsDict( parent ) && data->key )
49    {
50        node = tr_bencDictAdd( parent, data->key );
51        tr_free( data->key );
52        data->key = NULL;
53    }
54
55    return node;
56}
57
58static int
59callback( void *             vdata,
60          int                type,
61          const JSON_value * value )
62{
63    struct json_benc_data * data = vdata;
64    tr_benc *               node;
65
66    switch( type )
67    {
68        case JSON_T_ARRAY_BEGIN:
69            data->hasContent = true;
70            node = getNode( data );
71            tr_bencInitList( node, 0 );
72            tr_ptrArrayAppend( &data->stack, node );
73            break;
74
75        case JSON_T_ARRAY_END:
76            tr_ptrArrayPop( &data->stack );
77            break;
78
79        case JSON_T_OBJECT_BEGIN:
80            data->hasContent = true;
81            node = getNode( data );
82            tr_bencInitDict( node, 0 );
83            tr_ptrArrayAppend( &data->stack, node );
84            break;
85
86        case JSON_T_OBJECT_END:
87            tr_ptrArrayPop( &data->stack );
88            break;
89
90        case JSON_T_FLOAT:
91            data->hasContent = true;
92            tr_bencInitReal( getNode( data ), value->vu.float_value );
93            break;
94
95        case JSON_T_NULL:
96            data->hasContent = true;
97            tr_bencInitStr( getNode( data ), "", 0 );
98            break;
99
100        case JSON_T_INTEGER:
101            data->hasContent = true;
102            tr_bencInitInt( getNode( data ), value->vu.integer_value );
103            break;
104
105        case JSON_T_TRUE:
106            data->hasContent = true;
107            tr_bencInitBool( getNode( data ), 1 );
108            break;
109
110        case JSON_T_FALSE:
111            data->hasContent = true;
112            tr_bencInitBool( getNode( data ), 0 );
113            break;
114
115        case JSON_T_STRING:
116            data->hasContent = true;
117            tr_bencInitStr( getNode( data ),
118                            value->vu.str.value,
119                            value->vu.str.length );
120            break;
121
122        case JSON_T_KEY:
123            data->hasContent = true;
124            assert( !data->key );
125            data->key = tr_strdup( value->vu.str.value );
126            break;
127    }
128
129    return 1;
130}
131
132int
133tr_jsonParse( const char     * source,
134              const void     * vbuf,
135              size_t           len,
136              tr_benc        * setme_benc,
137              const uint8_t ** setme_end )
138{
139    int                         line = 1;
140    int                         column = 1;
141    int                         err = 0;
142    const unsigned char       * buf = vbuf;
143    const void                * bufend = buf + len;
144    JSON_config                 config;
145    struct JSON_parser_struct * checker;
146    struct json_benc_data       data;
147
148    init_JSON_config( &config );
149    config.callback = callback;
150    config.callback_ctx = &data;
151    config.depth = -1;
152
153    data.hasContent = false;
154    data.key = NULL;
155    data.top = setme_benc;
156    data.stack = TR_PTR_ARRAY_INIT;
157
158    checker = new_JSON_parser( &config );
159    while( ( buf != bufend ) && JSON_parser_char( checker, *buf ) ) {
160        if( *buf != '\n' )
161            ++column;
162        else {
163            ++line;
164            column = 1;
165        }
166        ++buf;
167    }
168
169    if( buf != bufend ) {
170        if( source )
171            tr_err( "JSON parser failed in %s at line %d, column %d: \"%.16s\"", source, line, column, buf );
172        else
173            tr_err( "JSON parser failed at line %d, column %d: \"%.16s\"", line, column, buf );
174        err = EILSEQ;
175    }
176
177    if( !data.hasContent )
178        err = EINVAL;
179
180    if( setme_end )
181        *setme_end = (const uint8_t*) buf;
182
183    delete_JSON_parser( checker );
184    tr_ptrArrayDestruct( &data.stack, NULL );
185    return err;
186}
187
Note: See TracBrowser for help on using the repository browser.