source: trunk/libtransmission/json.c @ 6584

Last change on this file since 6584 was 6584, checked in by charles, 13 years ago

roll back the last two diffs (r6582 and r6583) in favor of a simpler/cleaner/better fix

  • Property svn:keywords set to Date Rev Author Id
File size: 3.7 KB
Line 
1/*
2 * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
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 6584 2008-08-18 03:44:09Z charles $
11 */
12
13#include <assert.h>
14#include <ctype.h>
15#include <string.h>
16#include <stdio.h> /* printf */
17
18#include <event.h> /* evbuffer */
19
20#include "JSON_parser.h"
21
22#include "transmission.h"
23#include "bencode.h"
24#include "json.h"
25#include "ptrarray.h"
26#include "utils.h"
27
28struct json_benc_data
29{
30    tr_benc * top;
31    tr_ptrArray * stack;
32    char * key;
33};
34
35static tr_benc*
36getNode( struct json_benc_data * data )
37{
38    tr_benc * parent;
39    tr_benc * node = NULL;
40
41    if( tr_ptrArrayEmpty( data->stack ) )
42        parent = NULL;
43     else
44        parent = tr_ptrArrayBack( data->stack );
45
46    if( !parent )
47        node = data->top;
48    else if( tr_bencIsList( parent ) )
49        node = tr_bencListAdd( parent );
50    else if( tr_bencIsDict( parent ) && data->key ) {
51        node = tr_bencDictAdd( parent, data->key );
52        tr_free( data->key );
53        data->key = NULL;
54    }
55
56    return node;
57}
58
59static int
60callback( void * vdata, int type, const JSON_value * value )
61{
62    struct json_benc_data * data = vdata;
63    tr_benc * node;
64
65    switch( type )
66    {
67        case JSON_T_ARRAY_BEGIN:
68            node = getNode( data );
69            tr_bencInitList( node, 0 );
70            tr_ptrArrayAppend( data->stack, node ); 
71            break;
72
73        case JSON_T_ARRAY_END:
74            tr_ptrArrayPop( data->stack );
75            break;
76
77        case JSON_T_OBJECT_BEGIN:
78            node = getNode( data );
79            tr_bencInitDict( node, 0 );
80            tr_ptrArrayAppend( data->stack, node ); 
81            break;
82
83        case JSON_T_OBJECT_END:
84            tr_ptrArrayPop( data->stack );
85            break;
86
87        case JSON_T_FLOAT: {
88            char buf[128];
89            tr_snprintf( buf, sizeof( buf ), "%f", (double)value->vu.float_value );
90            tr_bencInitStrDup( getNode( data ), buf );
91            break;
92        }
93
94        case JSON_T_NULL:
95            break;
96
97        case JSON_T_INTEGER:
98            tr_bencInitInt( getNode( data ), value->vu.integer_value );
99            break;
100
101        case JSON_T_TRUE:
102            tr_bencInitInt( getNode( data ), 1 );
103            break;
104
105        case JSON_T_FALSE:
106            tr_bencInitInt( getNode( data ), 0 );
107            break;
108
109        case JSON_T_STRING:
110            tr_bencInitStrDup( getNode( data ), value->vu.str.value );
111            break;
112
113        case JSON_T_KEY:
114            assert( !data->key );
115            data->key = tr_strdup( value->vu.str.value );
116            break;
117    }
118
119    return 1;
120}
121
122int
123tr_jsonParse( const void      * vbuf,
124              size_t            len,
125              tr_benc         * setme_benc,
126              const uint8_t  ** setme_end )
127{
128    int err = 0;
129    const unsigned char * buf = vbuf;
130    const void * bufend = buf + len;
131    struct JSON_config_struct config;
132    struct JSON_parser_struct * checker;
133    struct json_benc_data data;
134
135    init_JSON_config( &config );
136    config.callback = callback;
137    config.callback_ctx = &data;
138    config.depth = -1;
139
140    data.key = NULL;
141    data.top = setme_benc;
142    data.stack = tr_ptrArrayNew( );
143
144    checker = new_JSON_parser( &config );
145    while( ( buf != bufend ) && JSON_parser_char( checker, *buf ) )
146        ++buf;
147    if( buf != bufend )
148        err = TR_ERROR;
149
150    if( setme_end )
151        *setme_end = (const uint8_t*) buf;
152
153    delete_JSON_parser( checker );
154    tr_ptrArrayFree( data.stack, NULL );
155    return err;
156}
Note: See TracBrowser for help on using the repository browser.