Mercurial > vim
comparison src/list.c @ 17964:6d4d3bce365d v8.1.1978
patch 8.1.1978: the eval.c file is too big
Commit: https://github.com/vim/vim/commit/1e1d30048e722906a13665bd6c3c24c87eb2fe25
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Sep 4 14:41:14 2019 +0200
patch 8.1.1978: the eval.c file is too big
Problem: The eval.c file is too big.
Solution: Move filter() and map() to list.c.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 04 Sep 2019 14:45:04 +0200 |
parents | 0f7ae8010787 |
children | 684a15da9929 |
comparison
equal
deleted
inserted
replaced
17963:5de9b5831cd4 | 17964:6d4d3bce365d |
---|---|
1545 f_uniq(typval_T *argvars, typval_T *rettv) | 1545 f_uniq(typval_T *argvars, typval_T *rettv) |
1546 { | 1546 { |
1547 do_sort_uniq(argvars, rettv, FALSE); | 1547 do_sort_uniq(argvars, rettv, FALSE); |
1548 } | 1548 } |
1549 | 1549 |
1550 #endif /* defined(FEAT_EVAL) */ | 1550 /* |
1551 * Handle one item for map() and filter(). | |
1552 */ | |
1553 static int | |
1554 filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp) | |
1555 { | |
1556 typval_T rettv; | |
1557 typval_T argv[3]; | |
1558 int retval = FAIL; | |
1559 | |
1560 copy_tv(tv, get_vim_var_tv(VV_VAL)); | |
1561 argv[0] = *get_vim_var_tv(VV_KEY); | |
1562 argv[1] = *get_vim_var_tv(VV_VAL); | |
1563 if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL) | |
1564 goto theend; | |
1565 if (map) | |
1566 { | |
1567 // map(): replace the list item value | |
1568 clear_tv(tv); | |
1569 rettv.v_lock = 0; | |
1570 *tv = rettv; | |
1571 } | |
1572 else | |
1573 { | |
1574 int error = FALSE; | |
1575 | |
1576 // filter(): when expr is zero remove the item | |
1577 *remp = (tv_get_number_chk(&rettv, &error) == 0); | |
1578 clear_tv(&rettv); | |
1579 // On type error, nothing has been removed; return FAIL to stop the | |
1580 // loop. The error message was given by tv_get_number_chk(). | |
1581 if (error) | |
1582 goto theend; | |
1583 } | |
1584 retval = OK; | |
1585 theend: | |
1586 clear_tv(get_vim_var_tv(VV_VAL)); | |
1587 return retval; | |
1588 } | |
1589 | |
1590 /* | |
1591 * Implementation of map() and filter(). | |
1592 */ | |
1593 static void | |
1594 filter_map(typval_T *argvars, typval_T *rettv, int map) | |
1595 { | |
1596 typval_T *expr; | |
1597 listitem_T *li, *nli; | |
1598 list_T *l = NULL; | |
1599 dictitem_T *di; | |
1600 hashtab_T *ht; | |
1601 hashitem_T *hi; | |
1602 dict_T *d = NULL; | |
1603 blob_T *b = NULL; | |
1604 int rem; | |
1605 int todo; | |
1606 char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); | |
1607 char_u *arg_errmsg = (char_u *)(map ? N_("map() argument") | |
1608 : N_("filter() argument")); | |
1609 int save_did_emsg; | |
1610 int idx = 0; | |
1611 | |
1612 if (argvars[0].v_type == VAR_BLOB) | |
1613 { | |
1614 if ((b = argvars[0].vval.v_blob) == NULL) | |
1615 return; | |
1616 } | |
1617 else if (argvars[0].v_type == VAR_LIST) | |
1618 { | |
1619 if ((l = argvars[0].vval.v_list) == NULL | |
1620 || (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE))) | |
1621 return; | |
1622 } | |
1623 else if (argvars[0].v_type == VAR_DICT) | |
1624 { | |
1625 if ((d = argvars[0].vval.v_dict) == NULL | |
1626 || (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE))) | |
1627 return; | |
1628 } | |
1629 else | |
1630 { | |
1631 semsg(_(e_listdictarg), ermsg); | |
1632 return; | |
1633 } | |
1634 | |
1635 expr = &argvars[1]; | |
1636 // On type errors, the preceding call has already displayed an error | |
1637 // message. Avoid a misleading error message for an empty string that | |
1638 // was not passed as argument. | |
1639 if (expr->v_type != VAR_UNKNOWN) | |
1640 { | |
1641 typval_T save_val; | |
1642 typval_T save_key; | |
1643 | |
1644 prepare_vimvar(VV_VAL, &save_val); | |
1645 prepare_vimvar(VV_KEY, &save_key); | |
1646 | |
1647 // We reset "did_emsg" to be able to detect whether an error | |
1648 // occurred during evaluation of the expression. | |
1649 save_did_emsg = did_emsg; | |
1650 did_emsg = FALSE; | |
1651 | |
1652 if (argvars[0].v_type == VAR_DICT) | |
1653 { | |
1654 ht = &d->dv_hashtab; | |
1655 hash_lock(ht); | |
1656 todo = (int)ht->ht_used; | |
1657 for (hi = ht->ht_array; todo > 0; ++hi) | |
1658 { | |
1659 if (!HASHITEM_EMPTY(hi)) | |
1660 { | |
1661 int r; | |
1662 | |
1663 --todo; | |
1664 di = HI2DI(hi); | |
1665 if (map && (var_check_lock(di->di_tv.v_lock, | |
1666 arg_errmsg, TRUE) | |
1667 || var_check_ro(di->di_flags, | |
1668 arg_errmsg, TRUE))) | |
1669 break; | |
1670 set_vim_var_string(VV_KEY, di->di_key, -1); | |
1671 r = filter_map_one(&di->di_tv, expr, map, &rem); | |
1672 clear_tv(get_vim_var_tv(VV_KEY)); | |
1673 if (r == FAIL || did_emsg) | |
1674 break; | |
1675 if (!map && rem) | |
1676 { | |
1677 if (var_check_fixed(di->di_flags, arg_errmsg, TRUE) | |
1678 || var_check_ro(di->di_flags, arg_errmsg, TRUE)) | |
1679 break; | |
1680 dictitem_remove(d, di); | |
1681 } | |
1682 } | |
1683 } | |
1684 hash_unlock(ht); | |
1685 } | |
1686 else if (argvars[0].v_type == VAR_BLOB) | |
1687 { | |
1688 int i; | |
1689 typval_T tv; | |
1690 | |
1691 // set_vim_var_nr() doesn't set the type | |
1692 set_vim_var_type(VV_KEY, VAR_NUMBER); | |
1693 | |
1694 for (i = 0; i < b->bv_ga.ga_len; i++) | |
1695 { | |
1696 tv.v_type = VAR_NUMBER; | |
1697 tv.vval.v_number = blob_get(b, i); | |
1698 set_vim_var_nr(VV_KEY, idx); | |
1699 if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg) | |
1700 break; | |
1701 if (tv.v_type != VAR_NUMBER) | |
1702 { | |
1703 emsg(_(e_invalblob)); | |
1704 break; | |
1705 } | |
1706 tv.v_type = VAR_NUMBER; | |
1707 blob_set(b, i, tv.vval.v_number); | |
1708 if (!map && rem) | |
1709 { | |
1710 char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data; | |
1711 | |
1712 mch_memmove(p + idx, p + i + 1, | |
1713 (size_t)b->bv_ga.ga_len - i - 1); | |
1714 --b->bv_ga.ga_len; | |
1715 --i; | |
1716 } | |
1717 } | |
1718 } | |
1719 else // argvars[0].v_type == VAR_LIST | |
1720 { | |
1721 // set_vim_var_nr() doesn't set the type | |
1722 set_vim_var_type(VV_KEY, VAR_NUMBER); | |
1723 | |
1724 for (li = l->lv_first; li != NULL; li = nli) | |
1725 { | |
1726 if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE)) | |
1727 break; | |
1728 nli = li->li_next; | |
1729 set_vim_var_nr(VV_KEY, idx); | |
1730 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL | |
1731 || did_emsg) | |
1732 break; | |
1733 if (!map && rem) | |
1734 listitem_remove(l, li); | |
1735 ++idx; | |
1736 } | |
1737 } | |
1738 | |
1739 restore_vimvar(VV_KEY, &save_key); | |
1740 restore_vimvar(VV_VAL, &save_val); | |
1741 | |
1742 did_emsg |= save_did_emsg; | |
1743 } | |
1744 | |
1745 copy_tv(&argvars[0], rettv); | |
1746 } | |
1747 | |
1748 /* | |
1749 * "filter()" function | |
1750 */ | |
1751 void | |
1752 f_filter(typval_T *argvars, typval_T *rettv) | |
1753 { | |
1754 filter_map(argvars, rettv, FALSE); | |
1755 } | |
1756 | |
1757 /* | |
1758 * "map()" function | |
1759 */ | |
1760 void | |
1761 f_map(typval_T *argvars, typval_T *rettv) | |
1762 { | |
1763 filter_map(argvars, rettv, TRUE); | |
1764 } | |
1765 | |
1766 #endif // defined(FEAT_EVAL) |