Changeset 13687
- Timestamp:
- Dec 24, 2012, 10:38:41 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/variant-benc.c
r13683 r13687 12 12 13 13 #include <assert.h> 14 #include <ctype.h> /* isdigit 14 #include <ctype.h> /* isdigit() */ 15 15 #include <errno.h> 16 #include <stdlib.h> /* strtoul (), strtod (), realloc (), qsort (), mkstemp () */ 17 #include <string.h> /* strlen (), memchr () */ 18 19 #include <locale.h> /* setlocale () */ 16 #include <stdlib.h> /* strtoul(), strtod(), realloc(), qsort(), mkstemp() */ 17 #include <string.h> /* strlen(), memchr() */ 20 18 21 19 #include <event2/buffer.h> … … 26 24 #include "transmission.h" 27 25 #include "ptrarray.h" 28 #include "utils.h" /* tr_s trlcpy() */26 #include "utils.h" /* tr_snprintf() */ 29 27 #include "variant.h" 30 28 #include "variant-common.h" 31 29 32 30 /*** 33 **** tr_variantParse 34 **** tr_variantLoad 31 **** tr_variantParse() 32 **** tr_variantLoad() 35 33 ***/ 36 34 … … 118 116 } 119 117 120 static int 121 makeroom (tr_variant * container, size_t count) 122 { 123 const size_t needed = container->val.l.count + count; 124 125 assert (tr_variantIsContainer (container)); 126 127 if (needed > container->val.l.alloc) 118 static tr_variant* 119 get_node (tr_ptrArray * stack, tr_quark * key, tr_variant * top, int * err) 120 { 121 tr_variant * node = NULL; 122 123 if (tr_ptrArrayEmpty (stack)) 128 124 { 129 size_t n; 130 void * tmp; 131 132 /* scale the alloc size in powers-of-2 */ 133 n = container->val.l.alloc ? container->val.l.alloc : 8; 134 while (n < needed) 135 n *= 2u; 136 137 tmp = realloc (container->val.l.vals, n * sizeof (tr_variant)); 138 if (tmp == NULL) 139 return 1; 140 141 container->val.l.alloc = n; 142 container->val.l.vals = tmp; 125 node = top; 143 126 } 144 145 return 0; 146 } 147 148 static inline bool 149 isReadyForDictKey (tr_ptrArray * parentStack) 150 { 151 tr_variant * parent = tr_ptrArrayBack (parentStack); 152 153 return (parent != NULL) 154 && (tr_variantIsDict(parent)) 155 && ((parent->val.l.count%2)==0); 156 } 157 158 static tr_variant* 159 getNode (tr_variant * top, 160 tr_ptrArray * parentStack, 161 int type) 162 { 163 tr_variant * parent; 164 165 assert (top); 166 assert (parentStack); 167 168 if (tr_ptrArrayEmpty (parentStack)) 169 return top; 170 171 parent = tr_ptrArrayBack (parentStack); 172 assert (parent); 173 174 /* dictionary keys must be strings */ 175 if ((parent->type == TR_VARIANT_TYPE_DICT) 176 && (type != TR_VARIANT_TYPE_STR) 177 && (! (parent->val.l.count % 2))) 178 return NULL; 179 180 makeroom (parent, 1); 181 return parent->val.l.vals + parent->val.l.count++; 127 else 128 { 129 tr_variant * parent = tr_ptrArrayBack (stack); 130 131 if (tr_variantIsList (parent)) 132 { 133 node = tr_variantListAdd (parent); 134 } 135 else if (*key && tr_variantIsDict (parent)) 136 { 137 node = tr_variantDictAdd (parent, *key); 138 *key = 0; 139 } 140 else 141 { 142 *err = EILSEQ; 143 } 144 } 145 146 return node; 182 147 } 183 148 … … 187 152 * attack via maliciously-crafted bencoded data. (#667) 188 153 */ 189 staticint190 tr_variantParse Impl(const void * buf_in,154 int 155 tr_variantParseBenc (const void * buf_in, 191 156 const void * bufend_in, 192 157 tr_variant * top, 193 tr_ptrArray * parentStack,194 158 const char ** setme_end) 195 159 { 196 int err ;160 int err = 0; 197 161 const uint8_t * buf = buf_in; 198 162 const uint8_t * bufend = bufend_in; 163 tr_ptrArray stack = TR_PTR_ARRAY_INIT; 164 tr_quark key = 0; 199 165 200 166 tr_variantInit (top, 0); … … 203 169 { 204 170 if (buf > bufend) /* no more text to parse... */ 205 return 1; 171 err = EILSEQ; 172 173 if (err) 174 break; 206 175 207 176 if (*buf == 'i') /* int */ … … 209 178 int64_t val; 210 179 const uint8_t * end; 211 tr_variant * node;180 tr_variant * v; 212 181 213 182 if ((err = tr_bencParseInt (buf, bufend, &end, &val))) 214 return err; 215 216 node = getNode (top, parentStack, TR_VARIANT_TYPE_INT); 217 if (!node) 218 return EILSEQ; 219 220 tr_variantInitInt (node, val); 183 break; 221 184 buf = end; 222 185 223 if ( tr_ptrArrayEmpty (parentStack))224 break;186 if ((v = get_node (&stack, &key, top, &err))) 187 tr_variantInitInt (v, val); 225 188 } 226 189 else if (*buf == 'l') /* list */ 227 190 { 228 tr_variant * node = getNode (top, parentStack, TR_VARIANT_TYPE_LIST); 229 if (!node) 230 return EILSEQ; 231 232 tr_variantInit (node, TR_VARIANT_TYPE_LIST); 233 tr_ptrArrayAppend (parentStack, node); 191 tr_variant * v; 192 234 193 ++buf; 194 195 if ((v = get_node (&stack, &key, top, &err))) 196 { 197 tr_variantInitList (v, 0); 198 tr_ptrArrayAppend (&stack, v); 199 } 235 200 } 236 201 else if (*buf == 'd') /* dict */ 237 202 { 238 tr_variant * node = getNode (top, parentStack, TR_VARIANT_TYPE_DICT); 239 if (!node) 240 return EILSEQ; 241 242 tr_variantInit (node, TR_VARIANT_TYPE_DICT); 243 tr_ptrArrayAppend (parentStack, node); 203 tr_variant * v; 204 244 205 ++buf; 206 207 if ((v = get_node (&stack, &key, top, &err))) 208 { 209 tr_variantInitDict (v, 0); 210 tr_ptrArrayAppend (&stack, v); 211 } 245 212 } 246 213 else if (*buf == 'e') /* end of list or dict */ 247 214 { 248 tr_variant * node;249 215 ++buf; 250 if (tr_ptrArrayEmpty (parentStack)) 251 return EILSEQ; 252 253 node = tr_ptrArrayBack (parentStack); 254 if (tr_variantIsDict (node) && (node->val.l.count % 2)) 216 217 if (tr_ptrArrayEmpty (&stack) || (key != 0)) 255 218 { 256 /* odd # of children in dict */ 257 tr_variantFree (&node->val.l.vals[--node->val.l.count]); 258 return EILSEQ; 219 err = EILSEQ; 220 break; 259 221 } 260 261 tr_ptrArrayPop (parentStack); 262 if (tr_ptrArrayEmpty (parentStack)) 263 break; 222 else 223 { 224 tr_ptrArrayPop (&stack); 225 if (tr_ptrArrayEmpty (&stack)) 226 break; 227 } 264 228 } 265 229 else if (isdigit (*buf)) /* string? */ 266 230 { 231 tr_variant * v; 267 232 const uint8_t * end; 268 233 const uint8_t * str; 269 234 size_t str_len; 270 tr_variant * node;271 const bool is_key = isReadyForDictKey (parentStack);272 235 273 236 if ((err = tr_bencParseStr (buf, bufend, &end, &str, &str_len))) 274 return err; 275 276 node = getNode (top, parentStack, TR_VARIANT_TYPE_STR); 277 if (!node) 278 return EILSEQ; 279 280 if (is_key) 281 tr_variantInitQuark (node, tr_quark_new (str, str_len)); 282 else 283 tr_variantInitStr (node, str, str_len); 284 237 break; 285 238 buf = end; 286 239 287 if (tr_ptrArrayEmpty (parentStack)) 288 break; 240 if (!key && !tr_ptrArrayEmpty(&stack) && tr_variantIsDict(tr_ptrArrayBack(&stack))) 241 key = tr_quark_new (str, str_len); 242 else if ((v = get_node (&stack, &key, top, &err))) 243 tr_variantInitStr (v, str, str_len); 289 244 } 290 245 else /* invalid bencoded text... march past it */ … … 292 247 ++buf; 293 248 } 249 250 if (tr_ptrArrayEmpty (&stack)) 251 break; 294 252 } 295 253 296 err = !tr_variantIsSomething (top) || !tr_ptrArrayEmpty (parentStack); 254 if (!err) 255 err = !top->type || !tr_ptrArrayEmpty(&stack); 297 256 298 257 if (!err && setme_end) 299 258 *setme_end = (const char*) buf; 300 259 301 return err; 302 } 303 304 305 int 306 tr_variantParseBenc (const void * buf, 307 const void * end, 308 tr_variant * top, 309 const char ** setme_end) 310 { 311 int err; 312 tr_ptrArray parentStack = TR_PTR_ARRAY_INIT; 313 314 top->type = 0; /* set to `uninitialized' */ 315 err = tr_variantParseImpl (buf, end, top, &parentStack, setme_end); 316 if (err) 317 tr_variantFree (top); 318 319 tr_ptrArrayDestruct (&parentStack, NULL); 260 tr_ptrArrayDestruct (&stack, NULL); 320 261 return err; 321 262 } … … 343 284 saveRealFunc (const tr_variant * val, void * evbuf) 344 285 { 286 int len; 345 287 char buf[128]; 346 char locale[128]; 347 size_t len; 348 349 /* always use a '.' decimal point s.t. locale-hopping doesn't bite us */ 350 tr_strlcpy (locale, setlocale (LC_NUMERIC, NULL), sizeof (locale)); 351 setlocale (LC_NUMERIC, "POSIX"); 352 tr_snprintf (buf, sizeof (buf), "%f", val->val.d); 353 setlocale (LC_NUMERIC, locale); 354 355 len = strlen (buf); 356 evbuffer_add_printf (evbuf, "%lu:", (unsigned long)len); 288 289 len = tr_snprintf (buf, sizeof (buf), "%f", val->val.d); 290 evbuffer_add_printf (evbuf, "%d:", len); 357 291 evbuffer_add (evbuf, buf, len); 358 292 } -
trunk/libtransmission/variant-common.h
r13667 r13687 41 41 void tr_variantToBufBenc (const tr_variant * top, struct evbuffer * buf); 42 42 43 bool tr_variantIsSomething (const tr_variant * v);44 45 bool tr_variantIsContainer (const tr_variant * v);46 47 43 void tr_variantInit (tr_variant * v, char type); 48 44 -
trunk/libtransmission/variant-json.c
r13683 r13687 17 17 #include <string.h> 18 18 #include <errno.h> /* EILSEQ, EINVAL */ 19 20 #include <locale.h> /* setlocale() */21 19 22 20 #include <event2/buffer.h> /* evbuffer_add() */ … … 390 388 jsonIndent (struct jsonWalk * data) 391 389 { 390 static char buf[1024] = { '\0' }; 391 if (!*buf) 392 { 393 memset (buf, ' ', sizeof(buf)); 394 buf[0] = '\n'; 395 } 396 392 397 if (data->doIndent) 393 { 394 char buf[1024]; 395 const int width = tr_list_size (data->parents) * 4; 396 397 buf[0] = '\n'; 398 memset (buf+1, ' ', width); 399 evbuffer_add (data->out, buf, 1+width); 400 } 398 evbuffer_add (data->out, buf, tr_list_size(data->parents)*4 + 1); 401 399 } 402 400 … … 456 454 pstate->childIndex = 0; 457 455 pstate->childCount = v->val.l.count; 456 if (tr_variantIsDict (v)) 457 pstate->childCount *= 2; 458 458 459 tr_list_prepend (&data->parents, pstate); 459 460 } … … 621 622 tr_variantToBufJson (const tr_variant * top, struct evbuffer * buf, bool lean) 622 623 { 623 char lc_numeric[128];624 624 struct jsonWalk data; 625 625 … … 628 628 data.parents = NULL; 629 629 630 /* json requires a '.' decimal point regardless of locale */631 tr_strlcpy (lc_numeric, setlocale (LC_NUMERIC, NULL), sizeof (lc_numeric));632 setlocale (LC_NUMERIC, "POSIX");633 630 tr_variantWalk (top, &walk_funcs, &data, true); 634 setlocale (LC_NUMERIC, lc_numeric);635 631 636 632 if (evbuffer_get_length (buf)) -
trunk/libtransmission/variant.c
r13683 r13687 13 13 #include <assert.h> 14 14 #include <errno.h> 15 #include <stdio.h> /* rename 16 #include <stdlib.h> /* strtoul (), strtod (), realloc (), qsort (), mkstemp() */15 #include <stdio.h> /* rename() */ 16 #include <stdlib.h> /* strtoul(), strtod(), realloc(), qsort(), mkstemp() */ 17 17 #include <string.h> 18 18 19 #ifdef WIN32 /* tr_mkstemp 19 #ifdef WIN32 /* tr_mkstemp() */ 20 20 #include <fcntl.h> 21 21 #define _S_IREAD 256 … … 23 23 #endif 24 24 25 #include <locale.h> /* setlocale 26 #include <unistd.h> /* write (), unlink() */25 #include <locale.h> /* setlocale() */ 26 #include <unistd.h> /* write(), unlink() */ 27 27 28 28 #include <event2/buffer.h> … … 31 31 #include "transmission.h" 32 32 #include "ConvertUTF.h" 33 #include "fdlimit.h" /* tr_close_file 33 #include "fdlimit.h" /* tr_close_file() */ 34 34 #include "platform.h" /* TR_PATH_MAX */ 35 #include "utils.h" /* tr_new (), tr_free() */35 #include "utils.h" /* tr_new(), tr_free() */ 36 36 #include "variant.h" 37 37 #include "variant-common.h" … … 41 41 **/ 42 42 43 bool43 static bool 44 44 tr_variantIsContainer (const tr_variant * v) 45 45 { … … 47 47 } 48 48 49 bool49 static bool 50 50 tr_variantIsSomething (const tr_variant * v) 51 51 { … … 60 60 tr_variantInit (tr_variant * v, char type) 61 61 { 62 memset (v, 0, sizeof (*v));63 62 v->type = type; 63 memset (&v->val, 0, sizeof(v->val)); 64 64 } 65 65 … … 67 67 **** 68 68 ***/ 69 70 /*71 zzz72 73 typedef enum74 {75 TR_STRING_TYPE_KEY,76 TR_STRING_TYPE_HEAP,77 TR_STRING_TYPE_BUF78 }79 tr_string_type;80 81 struct tr_variant_string82 {83 tr_key key;84 tr_string_type type;85 size_t len;86 union { char buf[8]; char * ptr; } str;87 };88 */89 69 90 70 static const struct tr_variant_string STRING_INIT = … … 123 103 124 104 static void 125 tr_variant_string_set_quark (struct tr_variant_string * str, const tr_quark quark) 105 tr_variant_string_set_quark (struct tr_variant_string * str, 106 const tr_quark quark) 126 107 { 127 108 tr_variant_string_clear (str); … … 133 114 134 115 static void 135 tr_variant_string_set_string (struct tr_variant_string * str, const char * bytes, int len) 116 tr_variant_string_set_string (struct tr_variant_string * str, 117 const char * bytes, 118 int len) 136 119 { 137 120 tr_quark quark; … … 189 172 const tr_variant * const end = begin + dict->val.l.count; 190 173 191 for (walk=begin; walk!=end; walk+=2) 192 { 193 assert (walk->type == TR_VARIANT_TYPE_STR); 194 assert (walk->val.s.type == TR_STRING_TYPE_QUARK); 195 196 if (walk->val.s.quark == key) 174 for (walk=begin; walk!=end; ++walk) 175 if (walk->key == key) 197 176 return walk - begin; 198 }199 177 } 200 178 … … 207 185 const int i = dictIndexOf (dict, key); 208 186 209 return i < 0 ? NULL : &dict->val.l.vals[i + 1];187 return i < 0 ? NULL : dict->val.l.vals+i; 210 188 } 211 189 … … 226 204 227 205 tr_variant* 228 tr_variantListChild (tr_variant * v al,229 size_t i)206 tr_variantListChild (tr_variant * v, 207 size_t i) 230 208 { 231 209 tr_variant * ret = NULL; 232 210 233 if (tr_variantIsList (v al) && (i < val->val.l.count))234 ret = v al->val.l.vals + i;211 if (tr_variantIsList (v) && (i < v->val.l.count)) 212 ret = v->val.l.vals + i; 235 213 236 214 return ret; 237 215 } 238 216 239 int 217 bool 240 218 tr_variantListRemove (tr_variant * list, size_t i) 241 219 { 220 bool removed = false; 221 242 222 if (tr_variantIsList (list) && (i < list->val.l.count)) 243 223 { 224 removed = true; 244 225 tr_variantFree (&list->val.l.vals[i]); 245 226 tr_removeElementFromArray (list->val.l.vals, i, 246 227 sizeof (tr_variant), 247 228 list->val.l.count--); 248 return 1; 249 } 250 251 return 0; 252 } 253 254 static void 255 tr_variant_warning (const char * err) 256 { 257 fprintf (stderr, "warning: %s\n", err); 258 } 259 260 bool 261 tr_variantGetInt (const tr_variant * val, 229 } 230 231 return removed; 232 } 233 234 bool 235 tr_variantGetInt (const tr_variant * v, 262 236 int64_t * setme) 263 237 { 264 238 bool success = false; 265 239 266 if (!success && ((success = tr_variantIsInt (v al))))240 if (!success && ((success = tr_variantIsInt (v)))) 267 241 if (setme) 268 *setme = val->val.i; 269 270 if (!success && ((success = tr_variantIsBool (val)))) 271 { 272 tr_variant_warning ("reading bool as an int"); 273 if (setme) 274 *setme = val->val.b ? 1 : 0; 275 } 242 *setme = v->val.i; 243 244 if (!success && ((success = tr_variantIsBool (v)))) 245 if (setme) 246 *setme = v->val.b ? 1 : 0; 276 247 277 248 return success; … … 279 250 280 251 bool 281 tr_variantGetStr (const tr_variant * v al,252 tr_variantGetStr (const tr_variant * v, 282 253 const char ** setme, 283 254 size_t * len) 284 255 { 285 const bool success = tr_variantIsString (v al);256 const bool success = tr_variantIsString (v); 286 257 287 258 if (success) 288 *setme = getStr (v al);259 *setme = getStr (v); 289 260 290 261 if (len != NULL) 291 *len = success ? v al->val.s.len : 0;262 *len = success ? v->val.s.len : 0; 292 263 293 264 return success; … … 295 266 296 267 bool 297 tr_variantGetRaw (const tr_variant * v al,268 tr_variantGetRaw (const tr_variant * v, 298 269 const uint8_t ** setme_raw, 299 270 size_t * setme_len) 300 271 { 301 const bool success = tr_variantIsString (v al);272 const bool success = tr_variantIsString (v); 302 273 303 274 if (success) 304 275 { 305 *setme_raw = (uint8_t*) getStr (v al);306 *setme_len = v al->val.s.len;276 *setme_raw = (uint8_t*) getStr (v); 277 *setme_len = v->val.s.len; 307 278 } 308 279 … … 311 282 312 283 bool 313 tr_variantGetBool (const tr_variant * v al, bool * setme)284 tr_variantGetBool (const tr_variant * v, bool * setme) 314 285 { 315 286 const char * str; 316 287 bool success = false; 317 288 318 if ((success = tr_variantIsBool (v al)))319 *setme = v al->val.b;320 321 if (!success && tr_variantIsInt (v al))322 if ((success = (v al->val.i==0 || val->val.i==1)))323 *setme = v al->val.i!=0;324 325 if (!success && tr_variantGetStr (v al, &str, NULL))289 if ((success = tr_variantIsBool (v))) 290 *setme = v->val.b; 291 292 if (!success && tr_variantIsInt (v)) 293 if ((success = (v->val.i==0 || v->val.i==1))) 294 *setme = v->val.i!=0; 295 296 if (!success && tr_variantGetStr (v, &str, NULL)) 326 297 if ((success = (!strcmp (str,"true") || !strcmp (str,"false")))) 327 298 *setme = !strcmp (str,"true"); … … 331 302 332 303 bool 333 tr_variantGetReal (const tr_variant * v al, double * setme)304 tr_variantGetReal (const tr_variant * v, double * setme) 334 305 { 335 306 bool success = false; 336 307 337 if (!success && ((success = tr_variantIsReal (v al))))338 *setme = v al->val.d;339 340 if (!success && ((success = tr_variantIsInt (v al))))341 *setme = v al->val.i;342 343 if (!success && tr_variantIsString (v al))308 if (!success && ((success = tr_variantIsReal (v)))) 309 *setme = v->val.d; 310 311 if (!success && ((success = tr_variantIsInt (v)))) 312 *setme = v->val.i; 313 314 if (!success && tr_variantIsString (v)) 344 315 { 345 316 char * endptr; … … 350 321 tr_strlcpy (locale, setlocale (LC_NUMERIC, NULL), sizeof (locale)); 351 322 setlocale (LC_NUMERIC, "POSIX"); 352 d = strtod (getStr (v al), &endptr);323 d = strtod (getStr (v), &endptr); 353 324 setlocale (LC_NUMERIC, locale); 354 325 355 if ((success = (getStr (v al) != endptr) && !*endptr))326 if ((success = (getStr (v) != endptr) && !*endptr)) 356 327 *setme = d; 357 328 } … … 402 373 tr_variant ** setme) 403 374 { 404 return tr_variantDictFindType (dict, 405 key, 406 TR_VARIANT_TYPE_LIST, 407 setme); 375 return tr_variantDictFindType (dict, key, TR_VARIANT_TYPE_LIST, setme); 408 376 } 409 377 … … 413 381 tr_variant ** setme) 414 382 { 415 return tr_variantDictFindType (dict, 416 key, 417 TR_VARIANT_TYPE_DICT, 418 setme); 383 return tr_variantDictFindType (dict, key, TR_VARIANT_TYPE_DICT, setme); 419 384 } 420 385 … … 455 420 456 421 void 457 tr_variantInitBool (tr_variant * variant, bool value) 458 { 459 tr_variantInit (variant, TR_VARIANT_TYPE_BOOL); 460 variant->val.b = value != 0; 461 } 462 463 void 464 tr_variantInitReal (tr_variant * b, double value) 465 { 466 tr_variantInit (b, TR_VARIANT_TYPE_REAL); 467 b->val.d = value; 468 } 469 470 void 471 tr_variantInitInt (tr_variant * variant, int64_t value) 472 { 473 tr_variantInit (variant, TR_VARIANT_TYPE_INT); 474 variant->val.i = value; 475 } 476 477 int 478 tr_variantInitList (tr_variant * variant, size_t reserve_count) 479 { 480 tr_variantInit (variant, TR_VARIANT_TYPE_LIST); 481 return tr_variantListReserve (variant, reserve_count); 482 } 483 484 static int 485 containerReserve (tr_variant * container, size_t count) 486 { 487 const size_t needed = container->val.l.count + count; 488 489 assert (tr_variantIsContainer (container)); 490 491 if (needed > container->val.l.alloc) 492 { 493 size_t n; 494 void * tmp; 495 422 tr_variantInitBool (tr_variant * v, bool value) 423 { 424 tr_variantInit (v, TR_VARIANT_TYPE_BOOL); 425 v->val.b = value != 0; 426 } 427 428 void 429 tr_variantInitReal (tr_variant * v, double value) 430 { 431 tr_variantInit (v, TR_VARIANT_TYPE_REAL); 432 v->val.d = value; 433 } 434 435 void 436 tr_variantInitInt (tr_variant * v, int64_t value) 437 { 438 tr_variantInit (v, TR_VARIANT_TYPE_INT); 439 v->val.i = value; 440 } 441 442 void 443 tr_variantInitList (tr_variant * v, size_t reserve_count) 444 { 445 tr_variantInit (v, TR_VARIANT_TYPE_LIST); 446 tr_variantListReserve (v, reserve_count); 447 } 448 449 static void 450 containerReserve (tr_variant * v, size_t count) 451 { 452 const size_t needed = v->val.l.count + count; 453 454 assert (tr_variantIsContainer (v)); 455 456 if (needed > v->val.l.alloc) 457 { 496 458 /* scale the alloc size in powers-of-2 */ 497 n = container->val.l.alloc ? container->val.l.alloc : 8;459 size_t n = v->val.l.alloc ? v->val.l.alloc : 8; 498 460 while (n < needed) 499 461 n *= 2u; 500 462 501 tmp = tr_renew (tr_variant, container->val.l.vals, n); 502 if (tmp == NULL) 503 return 1; 504 505 container->val.l.alloc = n; 506 container->val.l.vals = tmp; 507 } 508 509 return 0; 510 } 511 512 int 463 v->val.l.vals = tr_renew (tr_variant, v->val.l.vals, n); 464 v->val.l.alloc = n; 465 } 466 } 467 468 void 513 469 tr_variantListReserve (tr_variant * list, size_t count) 514 470 { 515 471 assert (tr_variantIsList (list)); 516 returncontainerReserve (list, count);517 } 518 519 int 520 tr_variantInitDict (tr_variant * v ariant, size_t reserve_count)521 { 522 tr_variantInit (v ariant, TR_VARIANT_TYPE_DICT);523 return tr_variantDictReserve (variant, reserve_count);524 } 525 526 int 472 containerReserve (list, count); 473 } 474 475 void 476 tr_variantInitDict (tr_variant * v, size_t reserve_count) 477 { 478 tr_variantInit (v, TR_VARIANT_TYPE_DICT); 479 tr_variantDictReserve (v, reserve_count); 480 } 481 482 void 527 483 tr_variantDictReserve (tr_variant * dict, 528 484 size_t reserve_count) 529 485 { 530 486 assert (tr_variantIsDict (dict)); 531 return containerReserve (dict, reserve_count * 2);487 containerReserve (dict, reserve_count); 532 488 } 533 489 … … 541 497 containerReserve (list, 1); 542 498 child = &list->val.l.vals[list->val.l.count++]; 499 child->key = 0; 543 500 tr_variantInit (child, TR_VARIANT_TYPE_INT); 544 501 … … 623 580 const tr_quark key) 624 581 { 625 tr_variant * child_key; 626 tr_variant * child_val; 582 tr_variant * val; 627 583 628 584 assert (tr_variantIsDict (dict)); 629 585 630 containerReserve (dict, 2); 631 632 child_key = dict->val.l.vals + dict->val.l.count++; 633 tr_variantInitQuark (child_key, key); 634 635 child_val = dict->val.l.vals + dict->val.l.count++; 636 tr_variantInit (child_val, TR_VARIANT_TYPE_INT); 637 return child_val; 586 containerReserve (dict, 1); 587 588 val = dict->val.l.vals + dict->val.l.count++; 589 tr_variantInit (val, TR_VARIANT_TYPE_INT); 590 val->key = key; 591 return val; 638 592 } 639 593 … … 675 629 676 630 tr_variant* 677 tr_variantDictAddBool (tr_variant * dict, const tr_quark key, bool val) 631 tr_variantDictAddBool (tr_variant * dict, 632 const tr_quark key, 633 bool val) 678 634 { 679 635 tr_variant * child = dictFindOrAdd (dict, key, TR_VARIANT_TYPE_BOOL); … … 683 639 684 640 tr_variant* 685 tr_variantDictAddReal (tr_variant * dict, const tr_quark key, double val) 641 tr_variantDictAddReal (tr_variant * dict, 642 const tr_quark key, 643 double val) 686 644 { 687 645 tr_variant * child = dictFindOrAdd (dict, key, TR_VARIANT_TYPE_REAL); … … 691 649 692 650 tr_variant* 693 tr_variantDictAddQuark (tr_variant * dict, const tr_quark key, const tr_quark val) 651 tr_variantDictAddQuark (tr_variant * dict, 652 const tr_quark key, 653 const tr_quark val) 694 654 { 695 655 tr_variant * child = dictFindOrAdd (dict, key, TR_VARIANT_TYPE_STR); … … 699 659 700 660 tr_variant* 701 tr_variantDictAddStr (tr_variant * dict, const tr_quark key, const char * val) 661 tr_variantDictAddStr (tr_variant * dict, 662 const tr_quark key, 663 const char * val) 702 664 { 703 665 tr_variant * child = dictFindOrAdd (dict, key, TR_VARIANT_TYPE_STR); … … 737 699 } 738 700 739 int 701 bool 740 702 tr_variantDictRemove (tr_variant * dict, 741 703 const tr_quark key) 742 704 { 705 bool removed = false; 743 706 const int i = dictIndexOf (dict, key); 744 707 745 708 if (i >= 0) 746 709 { 747 const int n = dict->val.l.count; 710 const int last = dict->val.l.count - 1; 711 748 712 tr_variantFree (&dict->val.l.vals[i]); 749 tr_variantFree (&dict->val.l.vals[i + 1]); 750 if (i + 2 < n)751 {752 dict->val.l.vals[i] = dict->val.l.vals[n - 2]; 753 dict->val.l.vals[i + 1] = dict->val.l.vals[n - 1];754 } 755 dict->val.l.count -= 2;756 } 757 758 return i >= 0; /* return true if found */713 714 if (i != last) 715 dict->val.l.vals[i] = dict->val.l.vals[last]; 716 717 --dict->val.l.count; 718 719 removed = true; 720 } 721 722 return removed; 759 723 } 760 724 … … 765 729 struct KeyIndex 766 730 { 767 const char * key;768 int index;731 const char * keystr; 732 tr_variant * val; 769 733 }; 770 734 … … 775 739 const struct KeyIndex * b = vb; 776 740 777 return strcmp (a->key , b->key);741 return strcmp (a->keystr, b->keystr); 778 742 } 779 743 780 744 struct SaveNode 781 745 { 782 const tr_variant * val; 783 int valIsVisited; 784 int childCount; 785 int childIndex; 786 int * children; 746 const tr_variant * v; 747 tr_variant sorted; 748 size_t childIndex; 749 bool isVisited; 787 750 }; 788 751 789 752 static void 790 nodeInitDict (struct SaveNode * node, 791 const tr_variant * val, 792 bool sort_dicts) 793 { 794 const int n = val->val.l.count; 795 const int nKeys = n / 2; 796 797 assert (tr_variantIsDict (val)); 798 799 node->val = val; 800 node->children = tr_new0 (int, n); 801 802 if (sort_dicts) 803 { 804 int i, j; 805 struct KeyIndex * indices = tr_new (struct KeyIndex, nKeys); 806 807 for (i=j=0; i<n; i+=2, ++j) 753 nodeConstruct (struct SaveNode * node, 754 const tr_variant * v, 755 bool sort_dicts) 756 { 757 node->isVisited = false; 758 node->childIndex = 0; 759 760 if (sort_dicts && tr_variantIsDict(v)) 761 { 762 /* make node->sorted a sorted version of this dictionary */ 763 764 size_t i; 765 const size_t n = v->val.l.count; 766 struct KeyIndex * tmp = tr_new (struct KeyIndex, n); 767 768 for (i=0; i<n; i++) 808 769 { 809 indices[j].key = getStr (&val->val.l.vals[i]);810 indices[j].index = i;770 tmp[i].val = v->val.l.vals+i; 771 tmp[i].keystr = tr_quark_get_string (tmp[i].val->key, NULL); 811 772 } 812 773 813 qsort ( indices, j, sizeof (struct KeyIndex), compareKeyIndex);814 815 for (i=0; i<j; ++i)816 {817 const int index = indices[i].index;818 node->children[node->childCount++] = index;819 node->children[node->childCount++] = index + 1; 820 }821 822 tr_free (indices);774 qsort (tmp, n, sizeof (struct KeyIndex), compareKeyIndex); 775 776 tr_variantInitDict (&node->sorted, n); 777 for (i=0; i<n; ++i) 778 node->sorted.val.l.vals[i] = *tmp[i].val; 779 node->sorted.val.l.count = n; 780 781 tr_free (tmp); 782 783 node->v = &node->sorted; 823 784 } 824 785 else 825 786 { 826 int i; 827 828 for (i=0; i<n; ++i) 829 node->children[node->childCount++] = i; 830 } 831 832 assert (node->childCount == n); 787 node->v = v; 788 } 833 789 } 834 790 835 791 static void 836 nodeInitList (struct SaveNode * node, 837 const tr_variant * val) 838 { 839 int i; 840 int n; 841 842 assert (tr_variantIsList (val)); 843 844 n = val->val.l.count; 845 node->val = val; 846 node->childCount = n; 847 node->children = tr_new0 (int, n); 848 for (i=0; i<n; ++i) /* a list's children don't need to be reordered */ 849 node->children[i] = i; 850 } 851 852 static void 853 nodeInitLeaf (struct SaveNode * node, 854 const tr_variant * variant) 855 { 856 assert (!tr_variantIsContainer (variant)); 857 858 node->val = variant; 859 } 860 861 static void 862 nodeInit (struct SaveNode * node, 863 const tr_variant * variant, 864 bool sort_dicts) 865 { 866 static const struct SaveNode INIT_NODE = { NULL, 0, 0, 0, NULL }; 867 868 *node = INIT_NODE; 869 870 if (tr_variantIsList (variant)) 871 nodeInitList (node, variant); 872 else if (tr_variantIsDict (variant)) 873 nodeInitDict (node, variant, sort_dicts); 874 else 875 nodeInitLeaf (node, variant); 792 nodeDestruct (struct SaveNode * node) 793 { 794 if (node->v == &node->sorted) 795 tr_free (node->sorted.val.l.vals); 876 796 } 877 797 … … 882 802 */ 883 803 void 884 tr_variantWalk (const tr_variant * top,804 tr_variantWalk (const tr_variant * v, 885 805 const struct VariantWalkFuncs * walkFuncs, 886 806 void * user_data, … … 889 809 int stackSize = 0; 890 810 int stackAlloc = 64; 811 char lc_numeric[128]; 891 812 struct SaveNode * stack = tr_new (struct SaveNode, stackAlloc); 892 813 893 nodeInit (&stack[stackSize++], top, sort_dicts); 814 /* always use a '.' decimal point s.t. locale-hopping doesn't bite us */ 815 tr_strlcpy (lc_numeric, setlocale (LC_NUMERIC, NULL), sizeof (lc_numeric)); 816 setlocale (LC_NUMERIC, "POSIX"); 817 818 nodeConstruct (&stack[stackSize++], v, sort_dicts); 894 819 895 820 while (stackSize > 0) 896 821 { 897 822 struct SaveNode * node = &stack[stackSize-1]; 898 const tr_variant * v al;899 900 if (!node-> valIsVisited)823 const tr_variant * v; 824 825 if (!node->isVisited) 901 826 { 902 val = node->val;903 node->valIsVisited = true;827 v = node->v; 828 node->isVisited = true; 904 829 } 905 else if ( node->childIndex < node->childCount)830 else if (tr_variantIsContainer(node->v) && (node->childIndex < node->v->val.l.count)) 906 831 { 907 const int index = node->children[node->childIndex++]; 908 val = node->val->val.l.vals + index; 832 const int index = node->childIndex++; 833 v = node->v->val.l.vals + index; 834 835 if (tr_variantIsDict (node->v)) 836 { 837 tr_variant tmp; 838 tr_variantInitQuark (&tmp, v->key); 839 walkFuncs->stringFunc (&tmp, user_data); 840 } 909 841 } 910 842 else /* done with this node */ 911 843 { 912 if (tr_variantIsContainer (node->val))913 walkFuncs->containerEndFunc (node->val, user_data);914 915 tr_free (node->children);916 844 if (tr_variantIsContainer (node->v)) 845 walkFuncs->containerEndFunc (node->v, user_data); 846 --stackSize; 847 nodeDestruct (node); 848 continue; 917 849 } 918 850 919 if (v al) switch (val->type)851 if (v) switch (v->type) 920 852 { 921 853 case TR_VARIANT_TYPE_INT: 922 walkFuncs->intFunc (v al, user_data);854 walkFuncs->intFunc (v, user_data); 923 855 break; 924 856 925 857 case TR_VARIANT_TYPE_BOOL: 926 walkFuncs->boolFunc (v al, user_data);858 walkFuncs->boolFunc (v, user_data); 927 859 break; 928 860 929 861 case TR_VARIANT_TYPE_REAL: 930 walkFuncs->realFunc (v al, user_data);862 walkFuncs->realFunc (v, user_data); 931 863 break; 932 864 933 865 case TR_VARIANT_TYPE_STR: 934 walkFuncs->stringFunc (v al, user_data);866 walkFuncs->stringFunc (v, user_data); 935 867 break; 936 868 937 869 case TR_VARIANT_TYPE_LIST: 938 if (v al == node->val)870 if (v == node->v) 939 871 { 940 walkFuncs->listBeginFunc (v al, user_data);872 walkFuncs->listBeginFunc (v, user_data); 941 873 } 942 874 else … … 947 879 stack = tr_renew (struct SaveNode, stack, stackAlloc); 948 880 } 949 node Init (&stack[stackSize++], val, sort_dicts);881 nodeConstruct (&stack[stackSize++], v, sort_dicts); 950 882 } 951 883 break; 952 884 953 885 case TR_VARIANT_TYPE_DICT: 954 if (v al == node->val)886 if (v == node->v) 955 887 { 956 walkFuncs->dictBeginFunc (v al, user_data);888 walkFuncs->dictBeginFunc (v, user_data); 957 889 } 958 890 else … … 963 895 stack = tr_renew (struct SaveNode, stack, stackAlloc); 964 896 } 965 node Init (&stack[stackSize++], val, sort_dicts);897 nodeConstruct (&stack[stackSize++], v, sort_dicts); 966 898 } 967 899 break; … … 973 905 } 974 906 } 907 908 /* restore the locale... */ 909 setlocale (LC_NUMERIC, lc_numeric); 975 910 976 911 tr_free (stack); … … 1067 1002 tr_variantDictSize (const tr_variant * dict) 1068 1003 { 1069 size_t count = 0; 1070 1071 if (tr_variantIsDict (dict)) 1072 count = dict->val.l.count / 2; 1073 1074 return count; 1004 return tr_variantIsDict (dict) ? dict->val.l.count : 0; 1075 1005 } 1076 1006 … … 1085 1015 assert (tr_variantIsDict (dict)); 1086 1016 1087 if (tr_variantIsDict (dict) && (n*2)+1 <= dict->val.l.count) 1088 { 1089 tr_variant * k = dict->val.l.vals + (n*2); 1090 tr_variant * v = dict->val.l.vals + (n*2) + 1; 1091 if ((k->val.s.type == TR_STRING_TYPE_QUARK) && tr_variantIsSomething (v)) 1092 { 1093 *key = k->val.s.quark; 1094 *val = v; 1095 success = true; 1096 } 1017 if (tr_variantIsDict (dict) && (n<dict->val.l.count)) 1018 { 1019 *key = dict->val.l.vals[n].key; 1020 *val = dict->val.l.vals+n; 1021 success = true; 1097 1022 } 1098 1023 … … 1176 1101 1177 1102 struct evbuffer * 1178 tr_variantToBuf (const tr_variant * top, tr_variant_fmt fmt)1179 { 1180 struct evbuffer * buf = evbuffer_new 1103 tr_variantToBuf (const tr_variant * v, tr_variant_fmt fmt) 1104 { 1105 struct evbuffer * buf = evbuffer_new(); 1181 1106 1182 1107 evbuffer_expand (buf, 4096); /* alloc a little memory to start off with */ … … 1185 1110 { 1186 1111 case TR_VARIANT_FMT_BENC: 1187 tr_variantToBufBenc ( top, buf);1112 tr_variantToBufBenc (v, buf); 1188 1113 break; 1189 1114 1190 1115 case TR_VARIANT_FMT_JSON: 1191 tr_variantToBufJson ( top, buf, false);1116 tr_variantToBufJson (v, buf, false); 1192 1117 break; 1193 1118 1194 1119 case TR_VARIANT_FMT_JSON_LEAN: 1195 tr_variantToBufJson ( top, buf, true);1120 tr_variantToBufJson (v, buf, true); 1196 1121 break; 1197 1122 } … … 1201 1126 1202 1127 char* 1203 tr_variantToStr (const tr_variant * top, tr_variant_fmt fmt, int * len)1204 { 1205 struct evbuffer * buf = tr_variantToBuf ( top, fmt);1128 tr_variantToStr (const tr_variant * v, tr_variant_fmt fmt, int * len) 1129 { 1130 struct evbuffer * buf = tr_variantToBuf (v, fmt); 1206 1131 const size_t n = evbuffer_get_length (buf); 1207 1132 char * ret = evbuffer_free_to_str (buf); … … 1211 1136 } 1212 1137 1213 /* portability wrapper for mkstemp 1138 /* portability wrapper for mkstemp(). */ 1214 1139 static int 1215 1140 tr_mkstemp (char * template) … … 1226 1151 1227 1152 int 1228 tr_variantToFile (const tr_variant * top,1153 tr_variantToFile (const tr_variant * v, 1229 1154 tr_variant_fmt fmt, 1230 1155 const char * filename) … … 1236 1161 1237 1162 /* follow symlinks to find the "real" file, to make sure the temporary 1238 * we build with tr_mkstemp 1163 * we build with tr_mkstemp() is created on the right partition */ 1239 1164 if (tr_realpath (filename, buf) != NULL) 1240 1165 filename = buf; … … 1250 1175 /* save the variant to a temporary file */ 1251 1176 { 1252 struct evbuffer * buf = tr_variantToBuf ( top, fmt);1177 struct evbuffer * buf = tr_variantToBuf (v, fmt); 1253 1178 const char * walk = (const char *) evbuffer_pullup (buf, -1); 1254 1179 nleft = evbuffer_get_length (buf); -
trunk/libtransmission/variant.h
r13685 r13687 75 75 char type; 76 76 77 tr_quark key; 78 77 79 union 78 80 { … … 87 89 struct 88 90 { 89 s truct tr_variant * vals; /* nodes */90 size_t alloc; /* nodes allocated */91 s ize_t count; /* nodes used */91 size_t alloc; 92 size_t count; 93 struct tr_variant * vals; 92 94 } l; 93 95 } … … 276 278 } 277 279 278 inttr_variantInitList (tr_variant * list,279 size_t reserve_count); 280 281 inttr_variantListReserve (tr_variant * list,280 void tr_variantInitList (tr_variant * list, 281 size_t reserve_count); 282 283 void tr_variantListReserve (tr_variant * list, 282 284 size_t reserve_count); 283 285 … … 312 314 size_t pos); 313 315 314 inttr_variantListRemove (tr_variant * list,316 bool tr_variantListRemove (tr_variant * list, 315 317 size_t pos); 316 318 … … 328 330 } 329 331 330 inttr_variantInitDict (tr_variant * initme,331 size_t reserve_count); 332 333 inttr_variantDictReserve (tr_variant * dict,334 size_t reserve_count); 335 336 inttr_variantDictRemove (tr_variant * dict,332 void tr_variantInitDict (tr_variant * initme, 333 size_t reserve_count); 334 335 void tr_variantDictReserve (tr_variant * dict, 336 size_t reserve_count); 337 338 bool tr_variantDictRemove (tr_variant * dict, 337 339 const tr_quark key); 338 340 -
trunk/qt/my-valgrind.sh
r13667 r13687 1 1 #/bin/sh 2 valgrind --tool=cachegrind ./transmission-qt 2 valgrind --tool=cachegrind ./transmission-qt 2>&1 | tee runlog 3 #valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=48 --log-file=x-valgrind --show-reachable=no ./transmission-qt 2>&1 | tee runlog
Note: See TracChangeset
for help on using the changeset viewer.