source: trunk/libtransmission/json.c @ 7524

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

(trunk libT) avoid some unnecessary memory fragmentation... for composited objects that have a tr_ptrArray, contain the tr_ptrArray directly rather than a pointer to one allocated elsewhere on the heap.

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