source: trunk/libtransmission/json.c @ 9979

Last change on this file since 9979 was 9979, checked in by charles, 12 years ago

(trunk libT) fix some #include statements

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