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