1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * dict.c: Dictionary support 12 */ 13 14 #include "vim.h" 15 16 #if defined(FEAT_EVAL) || defined(PROTO) 17 18 // List head for garbage collection. Although there can be a reference loop 19 // from partial to dict to partial, we don't need to keep track of the partial, 20 // since it will get freed when the dict is unused and gets freed. 21 static dict_T *first_dict = NULL; 22 23 /* 24 * Allocate an empty header for a dictionary. 25 */ 26 dict_T * 27 dict_alloc(void) 28 { 29 dict_T *d; 30 31 d = ALLOC_CLEAR_ONE(dict_T); 32 if (d != NULL) 33 { 34 // Add the dict to the list of dicts for garbage collection. 35 if (first_dict != NULL) 36 first_dict->dv_used_prev = d; 37 d->dv_used_next = first_dict; 38 d->dv_used_prev = NULL; 39 first_dict = d; 40 41 hash_init(&d->dv_hashtab); 42 d->dv_lock = 0; 43 d->dv_scope = 0; 44 d->dv_refcount = 0; 45 d->dv_copyID = 0; 46 } 47 return d; 48 } 49 50 /* 51 * dict_alloc() with an ID for alloc_fail(). 52 */ 53 dict_T * 54 dict_alloc_id(alloc_id_T id UNUSED) 55 { 56 #ifdef FEAT_EVAL 57 if (alloc_fail_id == id && alloc_does_fail(sizeof(list_T))) 58 return NULL; 59 #endif 60 return (dict_alloc()); 61 } 62 63 dict_T * 64 dict_alloc_lock(int lock) 65 { 66 dict_T *d = dict_alloc(); 67 68 if (d != NULL) 69 d->dv_lock = lock; 70 return d; 71 } 72 73 /* 74 * Allocate an empty dict for a return value. 75 * Returns OK or FAIL. 76 */ 77 int 78 rettv_dict_alloc(typval_T *rettv) 79 { 80 dict_T *d = dict_alloc_lock(0); 81 82 if (d == NULL) 83 return FAIL; 84 85 rettv_dict_set(rettv, d); 86 return OK; 87 } 88 89 /* 90 * Set a dictionary as the return value 91 */ 92 void 93 rettv_dict_set(typval_T *rettv, dict_T *d) 94 { 95 rettv->v_type = VAR_DICT; 96 rettv->vval.v_dict = d; 97 if (d != NULL) 98 ++d->dv_refcount; 99 } 100 101 /* 102 * Free a Dictionary, including all non-container items it contains. 103 * Ignores the reference count. 104 */ 105 void 106 dict_free_contents(dict_T *d) 107 { 108 hashtab_free_contents(&d->dv_hashtab); 109 } 110 111 /* 112 * Clear hashtab "ht" and dict items it contains. 113 */ 114 void 115 hashtab_free_contents(hashtab_T *ht) 116 { 117 int todo; 118 hashitem_T *hi; 119 dictitem_T *di; 120 121 // Lock the hashtab, we don't want it to resize while freeing items. 122 hash_lock(ht); 123 todo = (int)ht->ht_used; 124 for (hi = ht->ht_array; todo > 0; ++hi) 125 { 126 if (!HASHITEM_EMPTY(hi)) 127 { 128 // Remove the item before deleting it, just in case there is 129 // something recursive causing trouble. 130 di = HI2DI(hi); 131 hash_remove(ht, hi); 132 dictitem_free(di); 133 --todo; 134 } 135 } 136 137 // The hashtab is still locked, it has to be re-initialized anyway. 138 hash_clear(ht); 139 } 140 141 static void 142 dict_free_dict(dict_T *d) 143 { 144 // Remove the dict from the list of dicts for garbage collection. 145 if (d->dv_used_prev == NULL) 146 first_dict = d->dv_used_next; 147 else 148 d->dv_used_prev->dv_used_next = d->dv_used_next; 149 if (d->dv_used_next != NULL) 150 d->dv_used_next->dv_used_prev = d->dv_used_prev; 151 vim_free(d); 152 } 153 154 static void 155 dict_free(dict_T *d) 156 { 157 if (!in_free_unref_items) 158 { 159 dict_free_contents(d); 160 dict_free_dict(d); 161 } 162 } 163 164 /* 165 * Unreference a Dictionary: decrement the reference count and free it when it 166 * becomes zero. 167 */ 168 void 169 dict_unref(dict_T *d) 170 { 171 if (d != NULL && --d->dv_refcount <= 0) 172 dict_free(d); 173 } 174 175 /* 176 * Go through the list of dicts and free items without the copyID. 177 * Returns TRUE if something was freed. 178 */ 179 int 180 dict_free_nonref(int copyID) 181 { 182 dict_T *dd; 183 int did_free = FALSE; 184 185 for (dd = first_dict; dd != NULL; dd = dd->dv_used_next) 186 if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) 187 { 188 // Free the Dictionary and ordinary items it contains, but don't 189 // recurse into Lists and Dictionaries, they will be in the list 190 // of dicts or list of lists. 191 dict_free_contents(dd); 192 did_free = TRUE; 193 } 194 return did_free; 195 } 196 197 void 198 dict_free_items(int copyID) 199 { 200 dict_T *dd, *dd_next; 201 202 for (dd = first_dict; dd != NULL; dd = dd_next) 203 { 204 dd_next = dd->dv_used_next; 205 if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) 206 dict_free_dict(dd); 207 } 208 } 209 210 /* 211 * Allocate a Dictionary item. 212 * The "key" is copied to the new item. 213 * Note that the type and value of the item "di_tv" still needs to be 214 * initialized! 215 * Returns NULL when out of memory. 216 */ 217 dictitem_T * 218 dictitem_alloc(char_u *key) 219 { 220 dictitem_T *di; 221 222 di = alloc(offsetof(dictitem_T, di_key) + STRLEN(key) + 1); 223 if (di != NULL) 224 { 225 STRCPY(di->di_key, key); 226 di->di_flags = DI_FLAGS_ALLOC; 227 di->di_tv.v_lock = 0; 228 } 229 return di; 230 } 231 232 /* 233 * Make a copy of a Dictionary item. 234 */ 235 static dictitem_T * 236 dictitem_copy(dictitem_T *org) 237 { 238 dictitem_T *di; 239 240 di = alloc(offsetof(dictitem_T, di_key) + STRLEN(org->di_key) + 1); 241 if (di != NULL) 242 { 243 STRCPY(di->di_key, org->di_key); 244 di->di_flags = DI_FLAGS_ALLOC; 245 copy_tv(&org->di_tv, &di->di_tv); 246 } 247 return di; 248 } 249 250 /* 251 * Remove item "item" from Dictionary "dict" and free it. 252 */ 253 void 254 dictitem_remove(dict_T *dict, dictitem_T *item) 255 { 256 hashitem_T *hi; 257 258 hi = hash_find(&dict->dv_hashtab, item->di_key); 259 if (HASHITEM_EMPTY(hi)) 260 internal_error("dictitem_remove()"); 261 else 262 hash_remove(&dict->dv_hashtab, hi); 263 dictitem_free(item); 264 } 265 266 /* 267 * Free a dict item. Also clears the value. 268 */ 269 void 270 dictitem_free(dictitem_T *item) 271 { 272 clear_tv(&item->di_tv); 273 if (item->di_flags & DI_FLAGS_ALLOC) 274 vim_free(item); 275 } 276 277 /* 278 * Make a copy of dict "d". Shallow if "deep" is FALSE. 279 * The refcount of the new dict is set to 1. 280 * See item_copy() for "copyID". 281 * Returns NULL when out of memory. 282 */ 283 dict_T * 284 dict_copy(dict_T *orig, int deep, int copyID) 285 { 286 dict_T *copy; 287 dictitem_T *di; 288 int todo; 289 hashitem_T *hi; 290 291 if (orig == NULL) 292 return NULL; 293 294 copy = dict_alloc(); 295 if (copy != NULL) 296 { 297 if (copyID != 0) 298 { 299 orig->dv_copyID = copyID; 300 orig->dv_copydict = copy; 301 } 302 todo = (int)orig->dv_hashtab.ht_used; 303 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) 304 { 305 if (!HASHITEM_EMPTY(hi)) 306 { 307 --todo; 308 309 di = dictitem_alloc(hi->hi_key); 310 if (di == NULL) 311 break; 312 if (deep) 313 { 314 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep, 315 copyID) == FAIL) 316 { 317 vim_free(di); 318 break; 319 } 320 } 321 else 322 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv); 323 if (dict_add(copy, di) == FAIL) 324 { 325 dictitem_free(di); 326 break; 327 } 328 } 329 } 330 331 ++copy->dv_refcount; 332 if (todo > 0) 333 { 334 dict_unref(copy); 335 copy = NULL; 336 } 337 } 338 339 return copy; 340 } 341 342 /* 343 * Add item "item" to Dictionary "d". 344 * Returns FAIL when out of memory and when key already exists. 345 */ 346 int 347 dict_add(dict_T *d, dictitem_T *item) 348 { 349 return hash_add(&d->dv_hashtab, item->di_key); 350 } 351 352 /* 353 * Add a number or special entry to dictionary "d". 354 * Returns FAIL when out of memory and when key already exists. 355 */ 356 static int 357 dict_add_number_special(dict_T *d, char *key, varnumber_T nr, vartype_T vartype) 358 { 359 dictitem_T *item; 360 361 item = dictitem_alloc((char_u *)key); 362 if (item == NULL) 363 return FAIL; 364 item->di_tv.v_type = vartype; 365 item->di_tv.vval.v_number = nr; 366 if (dict_add(d, item) == FAIL) 367 { 368 dictitem_free(item); 369 return FAIL; 370 } 371 return OK; 372 } 373 374 /* 375 * Add a number entry to dictionary "d". 376 * Returns FAIL when out of memory and when key already exists. 377 */ 378 int 379 dict_add_number(dict_T *d, char *key, varnumber_T nr) 380 { 381 return dict_add_number_special(d, key, nr, VAR_NUMBER); 382 } 383 384 /* 385 * Add a special entry to dictionary "d". 386 * Returns FAIL when out of memory and when key already exists. 387 */ 388 int 389 dict_add_bool(dict_T *d, char *key, varnumber_T nr) 390 { 391 return dict_add_number_special(d, key, nr, VAR_BOOL); 392 } 393 394 /* 395 * Add a string entry to dictionary "d". 396 * Returns FAIL when out of memory and when key already exists. 397 */ 398 int 399 dict_add_string(dict_T *d, char *key, char_u *str) 400 { 401 return dict_add_string_len(d, key, str, -1); 402 } 403 404 /* 405 * Add a string entry to dictionary "d". 406 * "str" will be copied to allocated memory. 407 * When "len" is -1 use the whole string, otherwise only this many bytes. 408 * Returns FAIL when out of memory and when key already exists. 409 */ 410 int 411 dict_add_string_len(dict_T *d, char *key, char_u *str, int len) 412 { 413 dictitem_T *item; 414 char_u *val = NULL; 415 416 item = dictitem_alloc((char_u *)key); 417 if (item == NULL) 418 return FAIL; 419 item->di_tv.v_type = VAR_STRING; 420 if (str != NULL) 421 { 422 if (len == -1) 423 val = vim_strsave(str); 424 else 425 val = vim_strnsave(str, len); 426 } 427 item->di_tv.vval.v_string = val; 428 if (dict_add(d, item) == FAIL) 429 { 430 dictitem_free(item); 431 return FAIL; 432 } 433 return OK; 434 } 435 436 /* 437 * Add a list entry to dictionary "d". 438 * Returns FAIL when out of memory and when key already exists. 439 */ 440 int 441 dict_add_list(dict_T *d, char *key, list_T *list) 442 { 443 dictitem_T *item; 444 445 item = dictitem_alloc((char_u *)key); 446 if (item == NULL) 447 return FAIL; 448 item->di_tv.v_type = VAR_LIST; 449 item->di_tv.vval.v_list = list; 450 ++list->lv_refcount; 451 if (dict_add(d, item) == FAIL) 452 { 453 dictitem_free(item); 454 return FAIL; 455 } 456 return OK; 457 } 458 459 /* 460 * Add a typval_T entry to dictionary "d". 461 * Returns FAIL when out of memory and when key already exists. 462 */ 463 int 464 dict_add_tv(dict_T *d, char *key, typval_T *tv) 465 { 466 dictitem_T *item; 467 468 item = dictitem_alloc((char_u *)key); 469 if (item == NULL) 470 return FAIL; 471 copy_tv(tv, &item->di_tv); 472 if (dict_add(d, item) == FAIL) 473 { 474 dictitem_free(item); 475 return FAIL; 476 } 477 return OK; 478 } 479 480 /* 481 * Add a callback to dictionary "d". 482 * Returns FAIL when out of memory and when key already exists. 483 */ 484 int 485 dict_add_callback(dict_T *d, char *key, callback_T *cb) 486 { 487 dictitem_T *item; 488 489 item = dictitem_alloc((char_u *)key); 490 if (item == NULL) 491 return FAIL; 492 put_callback(cb, &item->di_tv); 493 if (dict_add(d, item) == FAIL) 494 { 495 dictitem_free(item); 496 return FAIL; 497 } 498 return OK; 499 } 500 501 /* 502 * Initializes "iter" for iterating over dictionary items with 503 * dict_iterate_next(). 504 * If "var" is not a Dict or an empty Dict then there will be nothing to 505 * iterate over, no error is given. 506 * NOTE: The dictionary must not change until iterating is finished! 507 */ 508 void 509 dict_iterate_start(typval_T *var, dict_iterator_T *iter) 510 { 511 if (var->v_type != VAR_DICT || var->vval.v_dict == NULL) 512 iter->dit_todo = 0; 513 else 514 { 515 dict_T *d = var->vval.v_dict; 516 517 iter->dit_todo = d->dv_hashtab.ht_used; 518 iter->dit_hi = d->dv_hashtab.ht_array; 519 } 520 } 521 522 /* 523 * Iterate over the items referred to by "iter". It should be initialized with 524 * dict_iterate_start(). 525 * Returns a pointer to the key. 526 * "*tv_result" is set to point to the value for that key. 527 * If there are no more items, NULL is returned. 528 */ 529 char_u * 530 dict_iterate_next(dict_iterator_T *iter, typval_T **tv_result) 531 { 532 dictitem_T *di; 533 char_u *result; 534 535 if (iter->dit_todo == 0) 536 return NULL; 537 538 while (HASHITEM_EMPTY(iter->dit_hi)) 539 ++iter->dit_hi; 540 541 di = HI2DI(iter->dit_hi); 542 result = di->di_key; 543 *tv_result = &di->di_tv; 544 545 --iter->dit_todo; 546 ++iter->dit_hi; 547 return result; 548 } 549 550 /* 551 * Add a dict entry to dictionary "d". 552 * Returns FAIL when out of memory and when key already exists. 553 */ 554 int 555 dict_add_dict(dict_T *d, char *key, dict_T *dict) 556 { 557 dictitem_T *item; 558 559 item = dictitem_alloc((char_u *)key); 560 if (item == NULL) 561 return FAIL; 562 item->di_tv.v_type = VAR_DICT; 563 item->di_tv.vval.v_dict = dict; 564 ++dict->dv_refcount; 565 if (dict_add(d, item) == FAIL) 566 { 567 dictitem_free(item); 568 return FAIL; 569 } 570 return OK; 571 } 572 573 /* 574 * Get the number of items in a Dictionary. 575 */ 576 long 577 dict_len(dict_T *d) 578 { 579 if (d == NULL) 580 return 0L; 581 return (long)d->dv_hashtab.ht_used; 582 } 583 584 /* 585 * Find item "key[len]" in Dictionary "d". 586 * If "len" is negative use strlen(key). 587 * Returns NULL when not found. 588 */ 589 dictitem_T * 590 dict_find(dict_T *d, char_u *key, int len) 591 { 592 #define AKEYLEN 200 593 char_u buf[AKEYLEN]; 594 char_u *akey; 595 char_u *tofree = NULL; 596 hashitem_T *hi; 597 598 if (d == NULL) 599 return NULL; 600 if (len < 0) 601 akey = key; 602 else if (len >= AKEYLEN) 603 { 604 tofree = akey = vim_strnsave(key, len); 605 if (akey == NULL) 606 return NULL; 607 } 608 else 609 { 610 // Avoid a malloc/free by using buf[]. 611 vim_strncpy(buf, key, len); 612 akey = buf; 613 } 614 615 hi = hash_find(&d->dv_hashtab, akey); 616 vim_free(tofree); 617 if (HASHITEM_EMPTY(hi)) 618 return NULL; 619 return HI2DI(hi); 620 } 621 622 /* 623 * Get a typval_T item from a dictionary and copy it into "rettv". 624 * Returns FAIL if the entry doesn't exist or out of memory. 625 */ 626 int 627 dict_get_tv(dict_T *d, char_u *key, typval_T *rettv) 628 { 629 dictitem_T *di; 630 631 di = dict_find(d, key, -1); 632 if (di == NULL) 633 return FAIL; 634 copy_tv(&di->di_tv, rettv); 635 return OK; 636 } 637 638 /* 639 * Get a string item from a dictionary. 640 * When "save" is TRUE allocate memory for it. 641 * When FALSE a shared buffer is used, can only be used once! 642 * Returns NULL if the entry doesn't exist or out of memory. 643 */ 644 char_u * 645 dict_get_string(dict_T *d, char_u *key, int save) 646 { 647 dictitem_T *di; 648 char_u *s; 649 650 di = dict_find(d, key, -1); 651 if (di == NULL) 652 return NULL; 653 s = tv_get_string(&di->di_tv); 654 if (save && s != NULL) 655 s = vim_strsave(s); 656 return s; 657 } 658 659 /* 660 * Get a number item from a dictionary. 661 * Returns 0 if the entry doesn't exist. 662 */ 663 varnumber_T 664 dict_get_number(dict_T *d, char_u *key) 665 { 666 return dict_get_number_def(d, key, 0); 667 } 668 669 /* 670 * Get a number item from a dictionary. 671 * Returns "def" if the entry doesn't exist. 672 */ 673 varnumber_T 674 dict_get_number_def(dict_T *d, char_u *key, int def) 675 { 676 dictitem_T *di; 677 678 di = dict_find(d, key, -1); 679 if (di == NULL) 680 return def; 681 return tv_get_number(&di->di_tv); 682 } 683 684 /* 685 * Get a number item from a dictionary. 686 * Returns 0 if the entry doesn't exist. 687 * Give an error if the entry is not a number. 688 */ 689 varnumber_T 690 dict_get_number_check(dict_T *d, char_u *key) 691 { 692 dictitem_T *di; 693 694 di = dict_find(d, key, -1); 695 if (di == NULL) 696 return 0; 697 if (di->di_tv.v_type != VAR_NUMBER) 698 { 699 semsg(_(e_invarg2), tv_get_string(&di->di_tv)); 700 return 0; 701 } 702 return tv_get_number(&di->di_tv); 703 } 704 705 /* 706 * Return an allocated string with the string representation of a Dictionary. 707 * May return NULL. 708 */ 709 char_u * 710 dict2string(typval_T *tv, int copyID, int restore_copyID) 711 { 712 garray_T ga; 713 int first = TRUE; 714 char_u *tofree; 715 char_u numbuf[NUMBUFLEN]; 716 hashitem_T *hi; 717 char_u *s; 718 dict_T *d; 719 int todo; 720 721 if ((d = tv->vval.v_dict) == NULL) 722 return NULL; 723 ga_init2(&ga, (int)sizeof(char), 80); 724 ga_append(&ga, '{'); 725 726 todo = (int)d->dv_hashtab.ht_used; 727 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) 728 { 729 if (!HASHITEM_EMPTY(hi)) 730 { 731 --todo; 732 733 if (first) 734 first = FALSE; 735 else 736 ga_concat(&ga, (char_u *)", "); 737 738 tofree = string_quote(hi->hi_key, FALSE); 739 if (tofree != NULL) 740 { 741 ga_concat(&ga, tofree); 742 vim_free(tofree); 743 } 744 ga_concat(&ga, (char_u *)": "); 745 s = echo_string_core(&HI2DI(hi)->di_tv, &tofree, numbuf, copyID, 746 FALSE, restore_copyID, TRUE); 747 if (s != NULL) 748 ga_concat(&ga, s); 749 vim_free(tofree); 750 if (s == NULL || did_echo_string_emsg) 751 break; 752 line_breakcheck(); 753 754 } 755 } 756 if (todo > 0) 757 { 758 vim_free(ga.ga_data); 759 return NULL; 760 } 761 762 ga_append(&ga, '}'); 763 ga_append(&ga, NUL); 764 return (char_u *)ga.ga_data; 765 } 766 767 /* 768 * Get the key for #{key: val} into "tv" and advance "arg". 769 * Return FAIL when there is no valid key. 770 */ 771 static int 772 get_literal_key(char_u **arg, typval_T *tv) 773 { 774 char_u *p; 775 776 if (!ASCII_ISALNUM(**arg) && **arg != '_' && **arg != '-') 777 return FAIL; 778 779 for (p = *arg; ASCII_ISALNUM(*p) || *p == '_' || *p == '-'; ++p) 780 ; 781 tv->v_type = VAR_STRING; 782 tv->vval.v_string = vim_strnsave(*arg, (int)(p - *arg)); 783 784 *arg = skipwhite(p); 785 return OK; 786 } 787 788 /* 789 * Allocate a variable for a Dictionary and fill it from "*arg". 790 * "literal" is TRUE for #{key: val} 791 * Return OK or FAIL. Returns NOTDONE for {expr}. 792 */ 793 int 794 eval_dict(char_u **arg, typval_T *rettv, int flags, int literal) 795 { 796 int evaluate = flags & EVAL_EVALUATE; 797 dict_T *d = NULL; 798 typval_T tvkey; 799 typval_T tv; 800 char_u *key = NULL; 801 dictitem_T *item; 802 char_u *start = skipwhite(*arg + 1); 803 char_u buf[NUMBUFLEN]; 804 int vim9script = current_sctx.sc_version == SCRIPT_VERSION_VIM9; 805 806 /* 807 * First check if it's not a curly-braces thing: {expr}. 808 * Must do this without evaluating, otherwise a function may be called 809 * twice. Unfortunately this means we need to call eval1() twice for the 810 * first item. 811 * But {} is an empty Dictionary. 812 */ 813 if (!vim9script && *start != '}') 814 { 815 if (eval1(&start, &tv, 0) == FAIL) // recursive! 816 return FAIL; 817 if (*start == '}') 818 return NOTDONE; 819 } 820 821 if (evaluate) 822 { 823 d = dict_alloc(); 824 if (d == NULL) 825 return FAIL; 826 } 827 tvkey.v_type = VAR_UNKNOWN; 828 tv.v_type = VAR_UNKNOWN; 829 830 *arg = skipwhite(*arg + 1); 831 while (**arg != '}' && **arg != NUL) 832 { 833 if ((literal 834 ? get_literal_key(arg, &tvkey) 835 : eval1(arg, &tvkey, flags)) == FAIL) // recursive! 836 goto failret; 837 838 if (**arg != ':') 839 { 840 if (evaluate) 841 semsg(_(e_missing_dict_colon), *arg); 842 clear_tv(&tvkey); 843 goto failret; 844 } 845 if (evaluate) 846 { 847 key = tv_get_string_buf_chk(&tvkey, buf); 848 if (key == NULL) 849 { 850 // "key" is NULL when tv_get_string_buf_chk() gave an errmsg 851 clear_tv(&tvkey); 852 goto failret; 853 } 854 } 855 856 *arg = skipwhite(*arg + 1); 857 if (eval1(arg, &tv, flags) == FAIL) // recursive! 858 { 859 if (evaluate) 860 clear_tv(&tvkey); 861 goto failret; 862 } 863 if (evaluate) 864 { 865 item = dict_find(d, key, -1); 866 if (item != NULL) 867 { 868 if (evaluate) 869 semsg(_(e_duplicate_key), key); 870 clear_tv(&tvkey); 871 clear_tv(&tv); 872 goto failret; 873 } 874 item = dictitem_alloc(key); 875 if (item != NULL) 876 { 877 item->di_tv = tv; 878 item->di_tv.v_lock = 0; 879 if (dict_add(d, item) == FAIL) 880 dictitem_free(item); 881 } 882 } 883 clear_tv(&tvkey); 884 885 if (**arg == '}') 886 break; 887 if (**arg != ',') 888 { 889 if (evaluate) 890 semsg(_(e_missing_dict_comma), *arg); 891 goto failret; 892 } 893 *arg = skipwhite(*arg + 1); 894 } 895 896 if (**arg != '}') 897 { 898 if (evaluate) 899 semsg(_(e_missing_dict_end), *arg); 900 failret: 901 if (d != NULL) 902 dict_free(d); 903 return FAIL; 904 } 905 906 *arg = skipwhite(*arg + 1); 907 if (evaluate) 908 rettv_dict_set(rettv, d); 909 910 return OK; 911 } 912 913 /* 914 * Go over all entries in "d2" and add them to "d1". 915 * When "action" is "error" then a duplicate key is an error. 916 * When "action" is "force" then a duplicate key is overwritten. 917 * Otherwise duplicate keys are ignored ("action" is "keep"). 918 */ 919 void 920 dict_extend(dict_T *d1, dict_T *d2, char_u *action) 921 { 922 dictitem_T *di1; 923 hashitem_T *hi2; 924 int todo; 925 char_u *arg_errmsg = (char_u *)N_("extend() argument"); 926 927 todo = (int)d2->dv_hashtab.ht_used; 928 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2) 929 { 930 if (!HASHITEM_EMPTY(hi2)) 931 { 932 --todo; 933 di1 = dict_find(d1, hi2->hi_key, -1); 934 if (d1->dv_scope != 0) 935 { 936 // Disallow replacing a builtin function in l: and g:. 937 // Check the key to be valid when adding to any scope. 938 if (d1->dv_scope == VAR_DEF_SCOPE 939 && HI2DI(hi2)->di_tv.v_type == VAR_FUNC 940 && var_check_func_name(hi2->hi_key, di1 == NULL)) 941 break; 942 if (!valid_varname(hi2->hi_key)) 943 break; 944 } 945 if (di1 == NULL) 946 { 947 di1 = dictitem_copy(HI2DI(hi2)); 948 if (di1 != NULL && dict_add(d1, di1) == FAIL) 949 dictitem_free(di1); 950 } 951 else if (*action == 'e') 952 { 953 semsg(_("E737: Key already exists: %s"), hi2->hi_key); 954 break; 955 } 956 else if (*action == 'f' && HI2DI(hi2) != di1) 957 { 958 if (var_check_lock(di1->di_tv.v_lock, arg_errmsg, TRUE) 959 || var_check_ro(di1->di_flags, arg_errmsg, TRUE)) 960 break; 961 clear_tv(&di1->di_tv); 962 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv); 963 } 964 } 965 } 966 } 967 968 /* 969 * Return the dictitem that an entry in a hashtable points to. 970 */ 971 dictitem_T * 972 dict_lookup(hashitem_T *hi) 973 { 974 return HI2DI(hi); 975 } 976 977 /* 978 * Return TRUE when two dictionaries have exactly the same key/values. 979 */ 980 int 981 dict_equal( 982 dict_T *d1, 983 dict_T *d2, 984 int ic, // ignore case for strings 985 int recursive) // TRUE when used recursively 986 { 987 hashitem_T *hi; 988 dictitem_T *item2; 989 int todo; 990 991 if (d1 == d2) 992 return TRUE; 993 if (dict_len(d1) != dict_len(d2)) 994 return FALSE; 995 if (dict_len(d1) == 0) 996 // empty and NULL dicts are considered equal 997 return TRUE; 998 if (d1 == NULL || d2 == NULL) 999 return FALSE; 1000 1001 todo = (int)d1->dv_hashtab.ht_used; 1002 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi) 1003 { 1004 if (!HASHITEM_EMPTY(hi)) 1005 { 1006 item2 = dict_find(d2, hi->hi_key, -1); 1007 if (item2 == NULL) 1008 return FALSE; 1009 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic, recursive)) 1010 return FALSE; 1011 --todo; 1012 } 1013 } 1014 return TRUE; 1015 } 1016 1017 /* 1018 * Turn a dict into a list: 1019 * "what" == 0: list of keys 1020 * "what" == 1: list of values 1021 * "what" == 2: list of items 1022 */ 1023 static void 1024 dict_list(typval_T *argvars, typval_T *rettv, int what) 1025 { 1026 list_T *l2; 1027 dictitem_T *di; 1028 hashitem_T *hi; 1029 listitem_T *li; 1030 listitem_T *li2; 1031 dict_T *d; 1032 int todo; 1033 1034 if (argvars[0].v_type != VAR_DICT) 1035 { 1036 emsg(_(e_dictreq)); 1037 return; 1038 } 1039 if ((d = argvars[0].vval.v_dict) == NULL) 1040 return; 1041 1042 if (rettv_list_alloc(rettv) == FAIL) 1043 return; 1044 1045 todo = (int)d->dv_hashtab.ht_used; 1046 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) 1047 { 1048 if (!HASHITEM_EMPTY(hi)) 1049 { 1050 --todo; 1051 di = HI2DI(hi); 1052 1053 li = listitem_alloc(); 1054 if (li == NULL) 1055 break; 1056 list_append(rettv->vval.v_list, li); 1057 1058 if (what == 0) 1059 { 1060 // keys() 1061 li->li_tv.v_type = VAR_STRING; 1062 li->li_tv.v_lock = 0; 1063 li->li_tv.vval.v_string = vim_strsave(di->di_key); 1064 } 1065 else if (what == 1) 1066 { 1067 // values() 1068 copy_tv(&di->di_tv, &li->li_tv); 1069 } 1070 else 1071 { 1072 // items() 1073 l2 = list_alloc(); 1074 li->li_tv.v_type = VAR_LIST; 1075 li->li_tv.v_lock = 0; 1076 li->li_tv.vval.v_list = l2; 1077 if (l2 == NULL) 1078 break; 1079 ++l2->lv_refcount; 1080 1081 li2 = listitem_alloc(); 1082 if (li2 == NULL) 1083 break; 1084 list_append(l2, li2); 1085 li2->li_tv.v_type = VAR_STRING; 1086 li2->li_tv.v_lock = 0; 1087 li2->li_tv.vval.v_string = vim_strsave(di->di_key); 1088 1089 li2 = listitem_alloc(); 1090 if (li2 == NULL) 1091 break; 1092 list_append(l2, li2); 1093 copy_tv(&di->di_tv, &li2->li_tv); 1094 } 1095 } 1096 } 1097 } 1098 1099 /* 1100 * "items(dict)" function 1101 */ 1102 void 1103 f_items(typval_T *argvars, typval_T *rettv) 1104 { 1105 dict_list(argvars, rettv, 2); 1106 } 1107 1108 /* 1109 * "keys()" function 1110 */ 1111 void 1112 f_keys(typval_T *argvars, typval_T *rettv) 1113 { 1114 dict_list(argvars, rettv, 0); 1115 } 1116 1117 /* 1118 * "values(dict)" function 1119 */ 1120 void 1121 f_values(typval_T *argvars, typval_T *rettv) 1122 { 1123 dict_list(argvars, rettv, 1); 1124 } 1125 1126 /* 1127 * Make each item in the dict readonly (not the value of the item). 1128 */ 1129 void 1130 dict_set_items_ro(dict_T *di) 1131 { 1132 int todo = (int)di->dv_hashtab.ht_used; 1133 hashitem_T *hi; 1134 1135 // Set readonly 1136 for (hi = di->dv_hashtab.ht_array; todo > 0 ; ++hi) 1137 { 1138 if (HASHITEM_EMPTY(hi)) 1139 continue; 1140 --todo; 1141 HI2DI(hi)->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX; 1142 } 1143 } 1144 1145 /* 1146 * "has_key()" function 1147 */ 1148 void 1149 f_has_key(typval_T *argvars, typval_T *rettv) 1150 { 1151 if (argvars[0].v_type != VAR_DICT) 1152 { 1153 emsg(_(e_dictreq)); 1154 return; 1155 } 1156 if (argvars[0].vval.v_dict == NULL) 1157 return; 1158 1159 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict, 1160 tv_get_string(&argvars[1]), -1) != NULL; 1161 } 1162 1163 /* 1164 * "remove({dict})" function 1165 */ 1166 void 1167 dict_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg) 1168 { 1169 dict_T *d; 1170 char_u *key; 1171 dictitem_T *di; 1172 1173 if (argvars[2].v_type != VAR_UNKNOWN) 1174 semsg(_(e_toomanyarg), "remove()"); 1175 else if ((d = argvars[0].vval.v_dict) != NULL 1176 && !var_check_lock(d->dv_lock, arg_errmsg, TRUE)) 1177 { 1178 key = tv_get_string_chk(&argvars[1]); 1179 if (key != NULL) 1180 { 1181 di = dict_find(d, key, -1); 1182 if (di == NULL) 1183 semsg(_(e_dictkey), key); 1184 else if (!var_check_fixed(di->di_flags, arg_errmsg, TRUE) 1185 && !var_check_ro(di->di_flags, arg_errmsg, TRUE)) 1186 { 1187 *rettv = di->di_tv; 1188 init_tv(&di->di_tv); 1189 dictitem_remove(d, di); 1190 } 1191 } 1192 } 1193 } 1194 1195 #endif // defined(FEAT_EVAL) 1196