Changeset 13614


Ignore:
Timestamp:
Nov 11, 2012, 4:26:56 AM (9 years ago)
Author:
jordan
Message:

(trunk libT) #5131: replace JSON_parser with jsonsl to resolve licensing issue.

Location:
trunk/libtransmission
Files:
2 added
2 deleted
1 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/Makefile.am

    r13567 r13614  
    3535    inout.c \
    3636    json.c \
    37     JSON_parser.c \
    3837    list.c \
    3938    magnet.c \
     
    8584    history.h \
    8685    inout.h \
     86    jsonsl.c \
     87    jsonsl.h \
    8788    json.h \
    88     JSON_parser.h \
    8989    libtransmission-test.h \
    9090    list.h \
  • trunk/libtransmission/json.c

    r13612 r13614  
    1717#include <errno.h> /* EILSEQ, EINVAL */
    1818
    19 #include "JSON_parser.h"
     19#include <event2/util.h> /* evutil_strtoll() */
     20
     21#define JSONSL_STATE_USER_FIELDS /* no fields */
     22#include "jsonsl.h"
     23#include "jsonsl.c"
    2024
    2125#include "transmission.h"
     26#include "ConvertUTF.h"
    2227#include "bencode.h"
    2328#include "json.h"
     
    2530#include "utils.h"
    2631
    27 struct json_benc_data
    28 {
    29     bool        hasContent;
    30     tr_benc      * top;
    31     tr_ptrArray    stack;
    32     char         * key;
     32/* arbitrary value... this is much deeper than our code goes */
     33#define MAX_DEPTH 64
     34
     35struct json_wrapper_data
     36{
     37  int error;
     38  bool has_content;
     39  tr_benc * top;
     40  char * key;
     41  const char * source;
     42  tr_ptrArray stack;
    3343};
    3444
    3545static tr_benc*
    36 getNode( 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     {
    52         node = tr_bencDictAdd( parent, data->key );
    53         tr_free( data->key );
    54         data->key = NULL;
    55     }
    56 
    57     return node;
     46get_node (struct jsonsl_st * jsn)
     47{
     48  tr_benc * parent;
     49  tr_benc * node = NULL;
     50  struct json_wrapper_data * data = jsn->data;
     51
     52  parent = tr_ptrArrayEmpty (&data->stack)
     53         ? NULL
     54         : tr_ptrArrayBack (&data->stack);
     55
     56  if (!parent)
     57    {
     58      node = data->top;
     59    }
     60  else if (tr_bencIsList (parent))
     61    {
     62      node = tr_bencListAdd (parent);
     63    }
     64  else if (tr_bencIsDict (parent) && (data->key!=NULL))
     65    {
     66      node = tr_bencDictAdd (parent, data->key);
     67      tr_free (data->key);
     68      data->key = NULL;
     69    }
     70
     71  return node;
     72}
     73
     74
     75static void
     76error_handler (jsonsl_t                  jsn,
     77               jsonsl_error_t            error,
     78               struct jsonsl_state_st  * state   UNUSED,
     79               const jsonsl_char_t     * buf)
     80{
     81  struct json_wrapper_data * data = jsn->data;
     82
     83  if (data->source)
     84    {
     85      tr_err ("JSON parse failed in %s at pos %zu: %s -- remaining text \"%.16s\"",
     86              data->source,
     87              jsn->pos,
     88              jsonsl_strerror(error),
     89              buf);
     90    }
     91  else
     92    {
     93      tr_err ("JSON parse failed at pos %zu: %s -- remaining text \"%.16s\"",
     94              jsn->pos,
     95              jsonsl_strerror(error),
     96              buf);
     97    }
     98
     99  data->error = EILSEQ;
    58100}
    59101
    60102static int
    61 callback( void *             vdata,
    62           int                type,
    63           const JSON_value * value )
    64 {
    65     struct json_benc_data * data = vdata;
    66     tr_benc *               node;
    67 
    68     switch( type )
    69     {
    70         case JSON_T_ARRAY_BEGIN:
    71             data->hasContent = true;
    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             data->hasContent = true;
    83             node = getNode( data );
    84             tr_bencInitDict( node, 0 );
    85             tr_ptrArrayAppend( &data->stack, node );
    86             break;
    87 
    88         case JSON_T_OBJECT_END:
    89             tr_ptrArrayPop( &data->stack );
    90             break;
    91 
    92         case JSON_T_FLOAT:
    93             data->hasContent = true;
    94             tr_bencInitReal( getNode( data ), value->vu.float_value );
    95             break;
    96 
    97         case JSON_T_NULL:
    98             data->hasContent = true;
    99             tr_bencInitStr( getNode( data ), "", 0 );
    100             break;
    101 
    102         case JSON_T_INTEGER:
    103             data->hasContent = true;
    104             tr_bencInitInt( getNode( data ), value->vu.integer_value );
    105             break;
    106 
    107         case JSON_T_TRUE:
    108             data->hasContent = true;
    109             tr_bencInitBool( getNode( data ), 1 );
    110             break;
    111 
    112         case JSON_T_FALSE:
    113             data->hasContent = true;
    114             tr_bencInitBool( getNode( data ), 0 );
    115             break;
    116 
    117         case JSON_T_STRING:
    118             data->hasContent = true;
    119             tr_bencInitStr( getNode( data ),
    120                             value->vu.str.value,
    121                             value->vu.str.length );
    122             break;
    123 
    124         case JSON_T_KEY:
    125             data->hasContent = true;
    126             assert( !data->key );
    127             data->key = tr_strndup( value->vu.str.value, value->vu.str.length );
    128             break;
    129     }
    130 
    131     return 1;
     103error_callback (jsonsl_t                  jsn,
     104                jsonsl_error_t            error,
     105                struct jsonsl_state_st  * state,
     106                jsonsl_char_t           * at)
     107{
     108  error_handler (jsn, error, state, at);
     109  return 0; /* bail */
     110}
     111
     112static void
     113action_callback_PUSH (jsonsl_t                  jsn,
     114                      jsonsl_action_t           action  UNUSED,
     115                      struct jsonsl_state_st  * state,
     116                      const jsonsl_char_t     * buf     UNUSED)
     117{
     118  tr_benc * node;
     119  struct json_wrapper_data * data = jsn->data;
     120
     121  switch (state->type)
     122    {
     123      case JSONSL_T_LIST:
     124        data->has_content = true;
     125        node = get_node (jsn);
     126        tr_bencInitList (node, 0);
     127        tr_ptrArrayAppend (&data->stack, node);
     128        break;
     129
     130      case JSONSL_T_OBJECT:
     131        data->has_content = true;
     132        node = get_node (jsn);
     133        tr_bencInitDict (node, 0);
     134        tr_ptrArrayAppend (&data->stack, node);
     135        break;
     136
     137      default:
     138        /* nothing else interesting on push */
     139        break;
     140    }
     141}
     142
     143static char*
     144extract_string (jsonsl_t jsn, struct jsonsl_state_st * state, size_t * len)
     145{
     146  const char * in_begin;
     147  const char * in_end;
     148  const char * in_it;
     149  size_t out_buflen;
     150  char * out_buf;
     151  char * out_it;
     152
     153  in_begin = jsn->base + state->pos_begin;
     154  if (*in_begin == '"')
     155    in_begin++;
     156  in_end = jsn->base + state->pos_cur;
     157
     158  out_buflen = (in_end-in_begin)*3 + 1;
     159  out_buf = tr_new0 (char, out_buflen);
     160  out_it = out_buf;
     161
     162  for (in_it=in_begin; in_it!=in_end; )
     163    {
     164      bool unescaped = false;
     165
     166      if (*in_it=='\\' && in_end-in_it>=2)
     167        {
     168          switch (in_it[1])
     169            {
     170              case 'b' : *out_it++ = '\b'; in_it+=2; unescaped = true; break;
     171              case 'f' : *out_it++ = '\f'; in_it+=2; unescaped = true; break;
     172              case 'n' : *out_it++ = '\n'; in_it+=2; unescaped = true; break;
     173              case 'r' : *out_it++ = '\r'; in_it+=2; unescaped = true; break;
     174              case 't' : *out_it++ = '\t'; in_it+=2; unescaped = true; break;
     175              case '"' : *out_it++ = '"' ; in_it+=2; unescaped = true; break;
     176              case '\\': *out_it++ = '\\'; in_it+=2; unescaped = true; break;
     177              case 'u':
     178                {
     179                  if (in_end - in_it >= 6)
     180                    {
     181                      unsigned int val = 0;
     182                      if (sscanf (in_it+2, "%4x", &val) == 1)
     183                        {
     184                          UTF32 str32_buf[2] = { val, 0 };
     185                          const UTF32 * str32_walk = str32_buf;
     186                          const UTF32 * str32_end = str32_buf + 1;
     187                          UTF8 str8_buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
     188                          UTF8 * str8_walk = str8_buf;
     189                          UTF8 * str8_end = str8_buf + 8;
     190
     191                          if (ConvertUTF32toUTF8 (&str32_walk, str32_end, &str8_walk, str8_end, 0) == 0)
     192                            {
     193                              const size_t len = str8_walk - str8_buf;
     194                              memcpy (out_it, str8_buf, len);
     195                              out_it += len;
     196                              unescaped = true;
     197                            }
     198
     199                          in_it += 6;
     200                          break;
     201                        }
     202                    }
     203                }
     204            }
     205        }
     206
     207      if (!unescaped)
     208        *out_it++ = *in_it++;
     209    }
     210
     211  if (len != NULL)
     212    *len = out_it - out_buf;
     213
     214  return out_buf;
     215}
     216
     217static void
     218action_callback_POP (jsonsl_t                  jsn,
     219                     jsonsl_action_t           action  UNUSED,
     220                     struct jsonsl_state_st  * state,
     221                     const jsonsl_char_t     * buf     UNUSED)
     222{
     223  struct json_wrapper_data * data = jsn->data;
     224
     225  if (state->type == JSONSL_T_STRING)
     226    {
     227      size_t len = 0;
     228      char * str = extract_string (jsn, state, &len);
     229      tr_bencInitStr (get_node (jsn), str, len);
     230      data->has_content = true;
     231      tr_free (str);
     232    }
     233  else if (state->type == JSONSL_T_HKEY)
     234    {
     235      char * str = extract_string (jsn, state, NULL);
     236      data->has_content = true;
     237      data->key = str;
     238    }
     239  else if ((state->type == JSONSL_T_LIST) || (state->type == JSONSL_T_OBJECT))
     240    {
     241      tr_ptrArrayPop (&data->stack);
     242    }
     243  else if (state->type == JSONSL_T_SPECIAL)
     244    {
     245      if (state->special_flags & JSONSL_SPECIALf_NUMNOINT)
     246        {
     247          const char * begin = jsn->base + state->pos_begin;
     248          data->has_content = true;
     249          tr_bencInitReal (get_node (jsn), strtod (begin, NULL));
     250        }
     251      else if (state->special_flags & JSONSL_SPECIALf_NUMERIC)
     252        {
     253          const char * begin = jsn->base + state->pos_begin;
     254          data->has_content = true;
     255          tr_bencInitInt (get_node (jsn), evutil_strtoll (begin, NULL, 10));
     256        }
     257      else if (state->special_flags & JSONSL_SPECIALf_BOOLEAN)
     258        {
     259          const bool b = (state->special_flags & JSONSL_SPECIALf_TRUE) != 0;
     260          data->has_content = true;
     261          tr_bencInitBool (get_node (jsn), b);
     262        }
     263      else if (state->special_flags & JSONSL_SPECIALf_NULL)
     264        {
     265          data->has_content = true;
     266          tr_bencInitStr (get_node (jsn), "", 0 );
     267        }
     268    }
    132269}
    133270
    134271int
    135 tr_jsonParse( const char     * source,
     272tr_jsonParse (const char     * source,
    136273              const void     * vbuf,
    137274              size_t           len,
    138275              tr_benc        * setme_benc,
    139               const uint8_t ** setme_end )
    140 {
    141     int                         line = 1;
    142     int                         column = 1;
    143     int                         err = 0;
    144     const unsigned char       * buf = vbuf;
    145     const void                * bufend = buf + len;
    146     JSON_config                 config;
    147     struct JSON_parser_struct * checker;
    148     struct json_benc_data       data;
    149 
    150     init_JSON_config( &config );
    151     config.callback = callback;
    152     config.callback_ctx = &data;
    153     config.depth = -1;
    154 
    155     data.hasContent = false;
    156     data.key = NULL;
    157     data.top = setme_benc;
    158     data.stack = TR_PTR_ARRAY_INIT;
    159 
    160     checker = new_JSON_parser( &config );
    161     while( ( buf != bufend ) && JSON_parser_char( checker, *buf ) ) {
    162         if( *buf != '\n' )
    163             ++column;
    164         else {
    165             ++line;
    166             column = 1;
    167         }
    168         ++buf;
    169     }
    170 
    171     if( buf != bufend ) {
    172         if( source )
    173             tr_err( "JSON parser failed in %s at line %d, column %d: \"%.16s\"", source, line, column, buf );
    174         else
    175             tr_err( "JSON parser failed at line %d, column %d: \"%.16s\"", line, column, buf );
    176         err = EILSEQ;
    177     }
    178 
    179     if( !data.hasContent )
    180         err = EINVAL;
    181 
    182     if( setme_end )
    183         *setme_end = (const uint8_t*) buf;
    184 
    185     delete_JSON_parser( checker );
    186     tr_ptrArrayDestruct( &data.stack, NULL );
    187     return err;
    188 }
    189 
     276              const uint8_t ** setme_end)
     277{
     278  int error;
     279  jsonsl_t jsn;
     280  struct json_wrapper_data data;
     281
     282  jsn = jsonsl_new (MAX_DEPTH);
     283  jsn->action_callback_PUSH = action_callback_PUSH;
     284  jsn->action_callback_POP = action_callback_POP;
     285  jsn->error_callback = error_callback;
     286  jsn->data = &data;
     287  jsonsl_enable_all_callbacks (jsn);
     288
     289  data.error = 0;
     290  data.has_content = false;
     291  data.key = NULL;
     292  data.top = setme_benc;
     293  data.stack = TR_PTR_ARRAY_INIT;
     294  data.source = source;
     295
     296  /* parse it */
     297  jsonsl_feed (jsn, vbuf, len);
     298
     299  /* EINVAL if there was no content */
     300  if (!data.error && !data.has_content)
     301    data.error = EINVAL;
     302
     303  /* maybe set the end ptr */
     304  if (setme_end)
     305    *setme_end = ((const uint8_t*)vbuf) + jsn->pos;
     306
     307  /* cleanup */
     308  error = data.error;
     309  tr_ptrArrayDestruct( &data.stack, NULL );
     310  jsonsl_destroy (jsn);
     311  return error;
     312}
Note: See TracChangeset for help on using the changeset viewer.