Changeset 13672


Ignore:
Timestamp:
Dec 15, 2012, 12:01:59 AM (9 years ago)
Author:
jordan
Message:

(trunk, libT) faster JSON parsing for tr_variant. This mostly helps the Qt client, which makes heavy use of the JSON-based RPC calls.

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/daemon/remote.c

    r13667 r13672  
    564564                isNum = false;
    565565        if (isNum || isList)
    566             tr_rpc_parse_list_str (tr_variantDictAdd (args, "ids"), id, strlen (id));
     566            tr_rpc_parse_list_str (tr_variantDictAdd (args, "ids", 3), id, strlen (id));
    567567        else
    568568            tr_variantDictAddStr (args, "ids", id); /* it's a torrent sha hash */
  • trunk/libtransmission/makemeta.c

    r13667 r13672  
    337337        {
    338338            tr_variant * d = tr_variantListAddDict (list, 2);
    339             tr_variant * length = tr_variantDictAdd (d, "length");
    340             tr_variant * pathVal = tr_variantDictAdd (d, "path");
     339            tr_variant * length = tr_variantDictAdd (d, "length", 6);
     340            tr_variant * pathVal = tr_variantDictAdd (d, "path", 4);
    341341            getFileInfo (builder->top, &builder->files[i], length, pathVal);
    342342        }
  • trunk/libtransmission/resume.c

    r13667 r13672  
    6767#define KEY_PROGRESS_BITFIELD  "bitfield"
    6868#define KEY_PROGRESS_BLOCKS    "blocks"
     69#define KEY_PROGRESS_BLOCKS_STRLEN 6
    6970#define KEY_PROGRESS_HAVE      "have"
    7071
     
    481482    /* add the blocks bitfield */
    482483    bitfieldToBenc (&tor->completion.blockBitfield,
    483                     tr_variantDictAdd (prog, KEY_PROGRESS_BLOCKS));
     484                    tr_variantDictAdd (prog, KEY_PROGRESS_BLOCKS, KEY_PROGRESS_BLOCKS_STRLEN));
    484485}
    485486
  • trunk/libtransmission/rpcimpl.c

    r13667 r13672  
    631631        tr_variantDictAddInt (d, key, tr_torrentGetPeerLimit (tor));
    632632    else if (tr_streq (key, keylen, "peers"))
    633         addPeers (tor, tr_variantDictAdd (d, key));
     633        addPeers (tor, tr_variantDictAdd (d, key, keylen));
    634634    else if (tr_streq (key, keylen, "peersConnected"))
    635635        tr_variantDictAddInt (d, key, st->peersConnected);
     
    13331333        tr_variantListAddStr (&fields, "name");
    13341334        tr_variantListAddStr (&fields, "hashString");
    1335         addInfo (tor, tr_variantDictAdd (data->args_out, "torrent-added"), &fields);
     1335        addInfo (tor, tr_variantDictAdd (data->args_out, "torrent-added", 13), &fields);
    13361336        notify (data->session, TR_RPC_TORRENT_ADDED, tor);
    13371337        tr_variantFree (&fields);
     
    19711971            int       isArg = strcmp (key, "method") && strcmp (key, "tag");
    19721972            tr_variant * parent = isArg ? args : ⊤
    1973             tr_rpc_parse_list_str (tr_variantDictAdd (parent, key),
     1973            tr_rpc_parse_list_str (tr_variantDictAdd (parent, key, delim-pch),
    19741974                                  delim + 1,
    19751975                                  next ? (size_t)(
  • trunk/libtransmission/variant-json.c

    r13669 r13672  
    4444  bool has_content;
    4545  tr_variant * top;
    46   char * key;
     46  const char * key;
     47  size_t keylen;
     48  struct evbuffer * keybuf;
     49  struct evbuffer * strbuf;
    4750  const char * source;
    4851  tr_ptrArray stack;
     
    7073  else if (tr_variantIsDict (parent) && (data->key!=NULL))
    7174    {
    72       node = tr_variantDictAdd (parent, data->key);
    73       tr_free (data->key);
     75      node = tr_variantDictAdd (parent, data->key, data->keylen);
     76
    7477      data->key = NULL;
     78      data->keylen = 0;
    7579    }
    7680
     
    168172
    169173static char*
    170 extract_string (jsonsl_t jsn, struct jsonsl_state_st * state, size_t * len)
    171 {
    172   const char * in_begin;
    173   const char * in_end;
    174   const char * in_it;
    175   size_t out_buflen;
    176   char * out_buf;
    177   char * out_it;
    178 
    179   in_begin = jsn->base + state->pos_begin;
    180   if (*in_begin == '"')
    181     in_begin++;
    182   in_end = jsn->base + state->pos_cur;
    183 
    184   out_buflen = (in_end-in_begin)*3 + 1;
    185   out_buf = tr_new0 (char, out_buflen);
    186   out_it = out_buf;
    187 
    188   for (in_it=in_begin; in_it!=in_end;)
     174extract_escaped_string (const char * in, size_t in_len, size_t * len, struct evbuffer * buf)
     175{
     176  const char * const in_end = in + in_len;
     177
     178  evbuffer_drain (buf, evbuffer_get_length (buf));
     179
     180  while (in < in_end)
    189181    {
    190182      bool unescaped = false;
    191183
    192       if (*in_it=='\\' && in_end-in_it>=2)
    193         {
    194           switch (in_it[1])
     184      if (*in=='\\' && in_end-in>=2)
     185        {
     186          switch (in[1])
    195187            {
    196               case 'b' : *out_it++ = '\b'; in_it+=2; unescaped = true; break;
    197               case 'f' : *out_it++ = '\f'; in_it+=2; unescaped = true; break;
    198               case 'n' : *out_it++ = '\n'; in_it+=2; unescaped = true; break;
    199               case 'r' : *out_it++ = '\r'; in_it+=2; unescaped = true; break;
    200               case 't' : *out_it++ = '\t'; in_it+=2; unescaped = true; break;
    201               case '/' : *out_it++ = '/' ; in_it+=2; unescaped = true; break;
    202               case '"' : *out_it++ = '"' ; in_it+=2; unescaped = true; break;
    203               case '\\': *out_it++ = '\\'; in_it+=2; unescaped = true; break;
     188              case 'b' : evbuffer_add (buf, "\b", 1); in+=2; unescaped = true; break;
     189              case 'f' : evbuffer_add (buf, "\f", 1); in+=2; unescaped = true; break;
     190              case 'n' : evbuffer_add (buf, "\n", 1); in+=2; unescaped = true; break;
     191              case 'r' : evbuffer_add (buf, "\r", 1); in+=2; unescaped = true; break;
     192              case 't' : evbuffer_add (buf, "\t", 1); in+=2; unescaped = true; break;
     193              case '/' : evbuffer_add (buf, "/" , 1); in+=2; unescaped = true; break;
     194              case '"' : evbuffer_add (buf, "\"" , 1); in+=2; unescaped = true; break;
     195              case '\\': evbuffer_add (buf, "\\", 1); in+=2; unescaped = true; break;
    204196              case 'u':
    205197                {
    206                   if (in_end - in_it >= 6)
     198                  if (in_end - in >= 6)
    207199                    {
    208200                      unsigned int val = 0;
    209                       if (decode_hex_string (in_it, &val))
     201
     202                      if (decode_hex_string (in, &val))
    210203                        {
    211204                          UTF32 str32_buf[2] = { val, 0 };
     
    215208                          UTF8 * str8_walk = str8_buf;
    216209                          UTF8 * str8_end = str8_buf + 8;
    217 
     210   
    218211                          if (ConvertUTF32toUTF8 (&str32_walk, str32_end, &str8_walk, str8_end, 0) == 0)
    219212                            {
    220213                              const size_t len = str8_walk - str8_buf;
    221                               memcpy (out_it, str8_buf, len);
    222                               out_it += len;
     214                              evbuffer_add (buf, str8_buf, len);
    223215                              unescaped = true;
    224216                            }
    225 
    226                           in_it += 6;
     217   
     218                          in += 6;
    227219                          break;
    228220                        }
     
    233225
    234226      if (!unescaped)
    235         *out_it++ = *in_it++;
    236     }
    237 
    238   if (len != NULL)
    239     *len = out_it - out_buf;
    240 
    241   return out_buf;
     227        {
     228          evbuffer_add (buf, in, 1);
     229          ++in;
     230        }
     231    }
     232
     233  *len = evbuffer_get_length (buf);
     234  return (char*) evbuffer_pullup (buf, -1);
     235}
     236
     237static const char*
     238extract_string (jsonsl_t jsn, struct jsonsl_state_st * state, size_t * len, struct evbuffer * buf)
     239{
     240  const char * ret;
     241  const char * in_begin;
     242  const char * in_end;
     243  size_t in_len;
     244
     245  /* figure out where the string is */
     246  in_begin = jsn->base + state->pos_begin;
     247  if (*in_begin == '"')
     248    in_begin++;
     249  in_end = jsn->base + state->pos_cur;
     250  in_len = in_end - in_begin;
     251
     252  if (memchr (in_begin, '\\', in_len) == NULL)
     253    {
     254      /* it's not escaped */
     255      ret = in_begin;
     256      *len = in_len;
     257    }
     258  else
     259    {
     260      ret = extract_escaped_string (in_begin, in_len, len, buf);
     261    }
     262
     263  return ret;
    242264}
    243265
     
    252274  if (state->type == JSONSL_T_STRING)
    253275    {
    254       size_t len = 0;
    255       char * str = extract_string (jsn, state, &len);
     276      size_t len;
     277      const char * str = extract_string (jsn, state, &len, data->strbuf);
    256278      tr_variantInitStr (get_node (jsn), str, len);
    257279      data->has_content = true;
    258       tr_free (str);
    259280    }
    260281  else if (state->type == JSONSL_T_HKEY)
    261282    {
    262       char * str = extract_string (jsn, state, NULL);
    263283      data->has_content = true;
    264       data->key = str;
     284      data->key = extract_string (jsn, state, &data->keylen, data->keybuf);
    265285    }
    266286  else if ((state->type == JSONSL_T_LIST) || (state->type == JSONSL_T_OBJECT))
     
    320340  data.stack = TR_PTR_ARRAY_INIT;
    321341  data.source = source;
     342  data.keybuf = evbuffer_new ();
     343  data.strbuf = evbuffer_new ();
    322344
    323345  /* parse it */
     
    334356  /* cleanup */
    335357  error = data.error;
     358  evbuffer_free (data.keybuf);
     359  evbuffer_free (data.strbuf);
    336360  tr_ptrArrayDestruct (&data.stack, NULL);
    337361  jsonsl_destroy (jsn);
  • trunk/libtransmission/variant.c

    r13669 r13672  
    8989  if (tr_variantIsDict (dict))
    9090    {
    91       size_t i;
     91      const tr_variant * walk;
     92      const tr_variant * const begin = dict->val.l.vals;
     93      const tr_variant * const end = begin + dict->val.l.count;
    9294      const size_t len = strlen (key);
    9395
    94       for (i=0; (i+1) < dict->val.l.count; i += 2)
    95         {
    96           const tr_variant * child = dict->val.l.vals + i;
    97           if ((child->type == TR_VARIANT_TYPE_STR)
    98               && (child->val.s.len == len)
    99               && !memcmp (getStr (child), key, len))
    100             return i;
    101         }
     96      for (walk=begin; walk!=end; walk+=2)
     97      {
     98        assert (walk->type == TR_VARIANT_TYPE_STR);
     99
     100        if ((walk->val.s.len==len) && !memcmp (getStr(walk), key, len))
     101          return walk - begin;
     102      }
    102103    }
    103104
     
    528529tr_variant *
    529530tr_variantDictAdd (tr_variant  * dict,
    530                    const char  * key)
     531                   const char  * key,
     532                   int           keylen)
    531533{
    532534  tr_variant * child_key;
     
    538540
    539541  child_key = dict->val.l.vals + dict->val.l.count++;
    540   tr_variantInitStr (child_key, key, -1);
     542  tr_variantInitStr (child_key, key, keylen);
    541543
    542544  child_val = dict->val.l.vals + dict->val.l.count++;
     
    562564  /* if it doesn't exist, create it */
    563565  if (child == NULL)
    564     child = tr_variantDictAdd (dict, key);
     566    child = tr_variantDictAdd (dict, key, -1);
    565567
    566568  return child;
     
    615617  /* if it doesn't exist, create it */
    616618  if (child == NULL)
    617     child = tr_variantDictAdd (dict, key);
     619    child = tr_variantDictAdd (dict, key, -1);
    618620
    619621  return child;
     
    645647                       size_t       reserve_count)
    646648{
    647   tr_variant * child = tr_variantDictAdd (dict, key);
     649  tr_variant * child = tr_variantDictAdd (dict, key, -1);
    648650  tr_variantInitList (child, reserve_count);
    649651  return child;
     
    655657                       size_t       reserve_count)
    656658{
    657   tr_variant * child = tr_variantDictAdd (dict, key);
     659  tr_variant * child = tr_variantDictAdd (dict, key, -1);
    658660  tr_variantInitDict (child, reserve_count);
    659661  return child;
  • trunk/libtransmission/variant.h

    r13667 r13672  
    321321
    322322tr_variant * tr_variantDictAdd         (tr_variant       * dict,
    323                                         const char       * key);
     323                                        const char       * key,
     324                                        int                keylen);
    324325
    325326tr_variant * tr_variantDictAddReal     (tr_variant       * dict,
Note: See TracChangeset for help on using the changeset viewer.