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)