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