mirror of
https://github.com/transmission/transmission
synced 2025-03-06 03:28:33 +00:00
(rpc) make our generated JSON more human-readable.
This commit is contained in:
parent
7b209acc1b
commit
90e151cd4d
2 changed files with 76 additions and 28 deletions
|
@ -1,3 +1,4 @@
|
|||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include "transmission.h"
|
||||
#include "bencode.h"
|
||||
|
@ -150,6 +151,10 @@ testString( const char * str, int isGood )
|
|||
check( err );
|
||||
} else {
|
||||
check( !err );
|
||||
#if 0
|
||||
fprintf( stderr, "in: [%s]\n", str );
|
||||
fprintf( stderr, "out:\n%s", tr_bencSaveAsJSON(&val,NULL) );
|
||||
#endif
|
||||
check( end == (const uint8_t*)str + len );
|
||||
saved = tr_bencSave( &val, &savedLen );
|
||||
check( !strcmp( saved, str ) );
|
||||
|
@ -219,6 +224,8 @@ testParse( void )
|
|||
return err;
|
||||
if(( err = testString( "d4:spaml1:a1:bee", TRUE )))
|
||||
return err;
|
||||
if(( err = testString( "d5:greenli1ei2ei3ee4:spamd1:ai123e3:keyi214eee", TRUE )))
|
||||
return err;
|
||||
if(( err = testString( "d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee", TRUE )))
|
||||
return err;
|
||||
if(( err = testString( "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e", TRUE )))
|
||||
|
@ -271,6 +278,16 @@ testParse( void )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
stripWhitespace( char * in )
|
||||
{
|
||||
char * out;
|
||||
for( out=in; *in; ++in )
|
||||
if( !isspace( *in ) )
|
||||
*out++ = *in;
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
testJSONSnippet( const char * benc_str, const char * expected )
|
||||
{
|
||||
|
@ -278,9 +295,11 @@ testJSONSnippet( const char * benc_str, const char * expected )
|
|||
char * serialized;
|
||||
tr_bencLoad( benc_str, strlen( benc_str ), &top, NULL );
|
||||
serialized = tr_bencSaveAsJSON( &top, NULL );
|
||||
stripWhitespace( serialized );
|
||||
#if 0
|
||||
fprintf( stderr, " expected: [%s]\n", expected );
|
||||
fprintf( stderr, " got: [%s]\n", serialized );
|
||||
fprintf( stderr, "benc: %s\n", benc_str );
|
||||
fprintf( stderr, "json: %s\n", serialized );
|
||||
fprintf( stderr, "want: %s\n", expected );
|
||||
#endif
|
||||
check( !strcmp( serialized, expected ) );
|
||||
tr_free( serialized );
|
||||
|
@ -301,22 +320,22 @@ testJSON( void )
|
|||
return val;
|
||||
|
||||
benc_str = "d5:helloi1e5:worldi2ee";
|
||||
expected = "{ \"hello\": 1, \"world\": 2 }";
|
||||
expected = "{\"hello\":1,\"world\":2}";
|
||||
if(( val = testJSONSnippet( benc_str, expected )))
|
||||
return val;
|
||||
|
||||
benc_str = "d5:helloi1e5:worldi2e3:fooli1ei2ei3ee";
|
||||
expected = "{ \"foo\": [ 1, 2, 3 ], \"hello\": 1, \"world\": 2 }";
|
||||
expected = "{\"foo\":[1,2,3],\"hello\":1,\"world\":2}";
|
||||
if(( val = testJSONSnippet( benc_str, expected )))
|
||||
return val;
|
||||
|
||||
benc_str = "d5:helloi1e5:worldi2e3:fooli1ei2ei3ed1:ai0eee";
|
||||
expected = "{ \"foo\": [ 1, 2, 3, { \"a\": 0 } ], \"hello\": 1, \"world\": 2 }";
|
||||
expected = "{\"foo\":[1,2,3,{\"a\":0}],\"hello\":1,\"world\":2}";
|
||||
if(( val = testJSONSnippet( benc_str, expected )))
|
||||
return val;
|
||||
|
||||
benc_str = "d4:argsd6:statuslee6:result7:successe";
|
||||
expected = "{ \"args\": { \"status\": [ ] }, \"result\": \"success\" }";
|
||||
benc_str = "d4:argsd6:statusle7:status2lee6:result7:successe";
|
||||
expected = "{\"args\":{\"status\":[],\"status2\":[]},\"result\":\"success\"}";
|
||||
if(( val = testJSONSnippet( benc_str, expected )))
|
||||
return val;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h> /* isdigit, isprint */
|
||||
#include <ctype.h> /* isdigit, isprint, isspace */
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
@ -1023,6 +1023,13 @@ struct jsonWalk
|
|||
struct evbuffer * out;
|
||||
};
|
||||
|
||||
static void
|
||||
jsonIndent( struct jsonWalk * data )
|
||||
{
|
||||
const int width = tr_list_size( data->parents ) * 4;
|
||||
evbuffer_add_printf( data->out, "\n%*.*s", width, width, " " );
|
||||
}
|
||||
|
||||
static void
|
||||
jsonChildFunc( struct jsonWalk * data )
|
||||
{
|
||||
|
@ -1036,14 +1043,17 @@ jsonChildFunc( struct jsonWalk * data )
|
|||
const int i = parentState->childIndex++;
|
||||
if( ! ( i % 2 ) )
|
||||
evbuffer_add_printf( data->out, ": " );
|
||||
else
|
||||
else {
|
||||
evbuffer_add_printf( data->out, ", " );
|
||||
jsonIndent( data );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_LIST: {
|
||||
++parentState->childIndex;
|
||||
evbuffer_add_printf( data->out, ", " );
|
||||
jsonIndent( data );
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1085,14 +1095,14 @@ jsonStringFunc( const tr_benc * val, void * vdata )
|
|||
for( it=val->val.s.s, end=it+val->val.s.i; it!=end; ++it )
|
||||
{
|
||||
switch( *it ) {
|
||||
case '"' : evbuffer_add_printf( data->out, "\\\"" ); break;
|
||||
case '/' : evbuffer_add_printf( data->out, "\\/" ); break;
|
||||
case '\b': evbuffer_add_printf( data->out, "\\b" ); break;
|
||||
case '\f': evbuffer_add_printf( data->out, "\\f" ); break;
|
||||
case '\n': evbuffer_add_printf( data->out, "\\n" ); break;
|
||||
case '\r': evbuffer_add_printf( data->out, "\\n" ); break;
|
||||
case '\t': evbuffer_add_printf( data->out, "\\n" ); break;
|
||||
case '\\': evbuffer_add_printf( data->out, "\\\\" ); break;
|
||||
case '"' :
|
||||
case '/' :
|
||||
case '\b':
|
||||
case '\f':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case '\\': evbuffer_add_printf( data->out, "\\%c", *it ); break;
|
||||
default: {
|
||||
if( isascii( *it ) )
|
||||
evbuffer_add_printf( data->out, "%c", *it );
|
||||
|
@ -1110,29 +1120,46 @@ jsonDictBeginFunc( const tr_benc * val, void * vdata )
|
|||
{
|
||||
struct jsonWalk * data = vdata;
|
||||
jsonPushParent( data, val );
|
||||
evbuffer_add_printf( data->out, "{ " );
|
||||
if( !val->val.l.count )
|
||||
evbuffer_add_printf( data->out, " " );
|
||||
evbuffer_add_printf( data->out, "{" );
|
||||
if( val->val.l.count )
|
||||
jsonIndent( data );
|
||||
}
|
||||
static void
|
||||
jsonListBeginFunc( const tr_benc * val, void * vdata )
|
||||
{
|
||||
const int nChildren = tr_bencListSize( val );
|
||||
struct jsonWalk * data = vdata;
|
||||
jsonPushParent( data, val );
|
||||
evbuffer_add_printf( data->out, "[ " );
|
||||
if( !val->val.l.count )
|
||||
evbuffer_add_printf( data->out, " " );
|
||||
evbuffer_add_printf( data->out, "[" );
|
||||
if( nChildren )
|
||||
jsonIndent( data );
|
||||
}
|
||||
static void
|
||||
jsonContainerEndFunc( const tr_benc * val, void * vdata )
|
||||
{
|
||||
size_t i;
|
||||
struct jsonWalk * data = vdata;
|
||||
EVBUFFER_LENGTH( data->out ) -= 2;
|
||||
if( tr_bencIsDict( val ) )
|
||||
evbuffer_add_printf( data->out, " }" );
|
||||
else /* list */
|
||||
evbuffer_add_printf( data->out, " ]" );
|
||||
char * str;
|
||||
int emptyContainer = FALSE;
|
||||
|
||||
/* trim out the trailing comma, if any */
|
||||
str = (char*) EVBUFFER_DATA( data->out );
|
||||
for( i=EVBUFFER_LENGTH( data->out )-1; i>0; --i ) {
|
||||
if( isspace( str[i] ) ) continue;
|
||||
if( str[i]==',' )
|
||||
EVBUFFER_LENGTH( data->out ) = i;
|
||||
if( str[i]=='{' || str[i]=='[' )
|
||||
emptyContainer = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
jsonPopParent( data );
|
||||
if( !emptyContainer )
|
||||
jsonIndent( data );
|
||||
if( tr_bencIsDict( val ) )
|
||||
evbuffer_add_printf( data->out, "}" );
|
||||
else /* list */
|
||||
evbuffer_add_printf( data->out, "]" );
|
||||
jsonChildFunc( data );
|
||||
}
|
||||
char*
|
||||
|
@ -1153,6 +1180,8 @@ tr_bencSaveAsJSON( const tr_benc * top, int * len )
|
|||
|
||||
bencWalk( top, &walkFuncs, &data );
|
||||
|
||||
if( EVBUFFER_LENGTH( data.out ) )
|
||||
evbuffer_add_printf( data.out, "\n" );
|
||||
if( len != NULL )
|
||||
*len = EVBUFFER_LENGTH( data.out );
|
||||
ret = tr_strndup( (char*) EVBUFFER_DATA( data.out ), EVBUFFER_LENGTH( data.out ) );
|
||||
|
|
Loading…
Add table
Reference in a new issue