blob: 3038b22f933b8d1db25cec160b1d7c34f28b346d [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaarda861d62016-07-17 15:46:27 +02002 *
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/*
Bram Moolenaar08c308a2019-09-04 17:48:15 +020011 * list.c: List support and container (List, Dict, Blob) functions.
Bram Moolenaarda861d62016-07-17 15:46:27 +020012 */
13
14#include "vim.h"
15
16#if defined(FEAT_EVAL) || defined(PROTO)
17
Bram Moolenaar08c308a2019-09-04 17:48:15 +020018static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob");
19
Bram Moolenaarda861d62016-07-17 15:46:27 +020020/* List heads for garbage collection. */
21static list_T *first_list = NULL; /* list of all lists */
22
23/*
24 * Add a watcher to a list.
25 */
26 void
27list_add_watch(list_T *l, listwatch_T *lw)
28{
29 lw->lw_next = l->lv_watch;
30 l->lv_watch = lw;
31}
32
33/*
34 * Remove a watcher from a list.
35 * No warning when it isn't found...
36 */
37 void
38list_rem_watch(list_T *l, listwatch_T *lwrem)
39{
40 listwatch_T *lw, **lwp;
41
42 lwp = &l->lv_watch;
43 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
44 {
45 if (lw == lwrem)
46 {
47 *lwp = lw->lw_next;
48 break;
49 }
50 lwp = &lw->lw_next;
51 }
52}
53
54/*
55 * Just before removing an item from a list: advance watchers to the next
56 * item.
57 */
Bram Moolenaar5843f5f2019-08-20 20:13:45 +020058 static void
Bram Moolenaarda861d62016-07-17 15:46:27 +020059list_fix_watch(list_T *l, listitem_T *item)
60{
61 listwatch_T *lw;
62
63 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
64 if (lw->lw_item == item)
65 lw->lw_item = item->li_next;
66}
67
68/*
69 * Allocate an empty header for a list.
70 * Caller should take care of the reference count.
71 */
72 list_T *
73list_alloc(void)
74{
75 list_T *l;
76
Bram Moolenaarc799fe22019-05-28 23:08:19 +020077 l = ALLOC_CLEAR_ONE(list_T);
Bram Moolenaarda861d62016-07-17 15:46:27 +020078 if (l != NULL)
79 {
80 /* Prepend the list to the list of lists for garbage collection. */
81 if (first_list != NULL)
82 first_list->lv_used_prev = l;
83 l->lv_used_prev = NULL;
84 l->lv_used_next = first_list;
85 first_list = l;
86 }
87 return l;
88}
89
90/*
Bram Moolenaarf49cc602018-11-11 15:21:05 +010091 * list_alloc() with an ID for alloc_fail().
92 */
93 list_T *
94list_alloc_id(alloc_id_T id UNUSED)
95{
96#ifdef FEAT_EVAL
Bram Moolenaar51e14382019-05-25 20:21:28 +020097 if (alloc_fail_id == id && alloc_does_fail(sizeof(list_T)))
Bram Moolenaarf49cc602018-11-11 15:21:05 +010098 return NULL;
99#endif
100 return (list_alloc());
101}
102
103/*
Bram Moolenaarda861d62016-07-17 15:46:27 +0200104 * Allocate an empty list for a return value, with reference count set.
105 * Returns OK or FAIL.
106 */
107 int
108rettv_list_alloc(typval_T *rettv)
109{
110 list_T *l = list_alloc();
111
112 if (l == NULL)
113 return FAIL;
114
Bram Moolenaarda861d62016-07-17 15:46:27 +0200115 rettv->v_lock = 0;
Bram Moolenaar45cf6e92017-04-30 20:25:19 +0200116 rettv_list_set(rettv, l);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200117 return OK;
118}
119
120/*
Bram Moolenaar162b7142018-12-21 15:17:36 +0100121 * Same as rettv_list_alloc() but uses an allocation id for testing.
122 */
123 int
124rettv_list_alloc_id(typval_T *rettv, alloc_id_T id UNUSED)
125{
126#ifdef FEAT_EVAL
Bram Moolenaar51e14382019-05-25 20:21:28 +0200127 if (alloc_fail_id == id && alloc_does_fail(sizeof(list_T)))
Bram Moolenaar162b7142018-12-21 15:17:36 +0100128 return FAIL;
129#endif
130 return rettv_list_alloc(rettv);
131}
132
133
134/*
Bram Moolenaare809a4e2019-07-04 17:35:05 +0200135 * Set a list as the return value. Increments the reference count.
Bram Moolenaar45cf6e92017-04-30 20:25:19 +0200136 */
137 void
138rettv_list_set(typval_T *rettv, list_T *l)
139{
140 rettv->v_type = VAR_LIST;
141 rettv->vval.v_list = l;
142 if (l != NULL)
143 ++l->lv_refcount;
144}
145
146/*
Bram Moolenaarda861d62016-07-17 15:46:27 +0200147 * Unreference a list: decrement the reference count and free it when it
148 * becomes zero.
149 */
150 void
151list_unref(list_T *l)
152{
153 if (l != NULL && --l->lv_refcount <= 0)
154 list_free(l);
155}
156
157/*
158 * Free a list, including all non-container items it points to.
159 * Ignores the reference count.
160 */
161 static void
162list_free_contents(list_T *l)
163{
164 listitem_T *item;
165
166 for (item = l->lv_first; item != NULL; item = l->lv_first)
167 {
168 /* Remove the item before deleting it. */
169 l->lv_first = item->li_next;
170 clear_tv(&item->li_tv);
171 vim_free(item);
172 }
173}
174
175/*
176 * Go through the list of lists and free items without the copyID.
177 * But don't free a list that has a watcher (used in a for loop), these
178 * are not referenced anywhere.
179 */
180 int
181list_free_nonref(int copyID)
182{
183 list_T *ll;
184 int did_free = FALSE;
185
186 for (ll = first_list; ll != NULL; ll = ll->lv_used_next)
187 if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
188 && ll->lv_watch == NULL)
189 {
190 /* Free the List and ordinary items it contains, but don't recurse
191 * into Lists and Dictionaries, they will be in the list of dicts
192 * or list of lists. */
193 list_free_contents(ll);
194 did_free = TRUE;
195 }
196 return did_free;
197}
198
199 static void
200list_free_list(list_T *l)
201{
202 /* Remove the list from the list of lists for garbage collection. */
203 if (l->lv_used_prev == NULL)
204 first_list = l->lv_used_next;
205 else
206 l->lv_used_prev->lv_used_next = l->lv_used_next;
207 if (l->lv_used_next != NULL)
208 l->lv_used_next->lv_used_prev = l->lv_used_prev;
209
210 vim_free(l);
211}
212
213 void
214list_free_items(int copyID)
215{
216 list_T *ll, *ll_next;
217
218 for (ll = first_list; ll != NULL; ll = ll_next)
219 {
220 ll_next = ll->lv_used_next;
221 if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
222 && ll->lv_watch == NULL)
223 {
224 /* Free the List and ordinary items it contains, but don't recurse
225 * into Lists and Dictionaries, they will be in the list of dicts
226 * or list of lists. */
227 list_free_list(ll);
228 }
229 }
230}
231
232 void
233list_free(list_T *l)
234{
235 if (!in_free_unref_items)
236 {
237 list_free_contents(l);
238 list_free_list(l);
239 }
240}
241
242/*
243 * Allocate a list item.
244 * It is not initialized, don't forget to set v_lock.
245 */
246 listitem_T *
247listitem_alloc(void)
248{
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200249 return ALLOC_ONE(listitem_T);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200250}
251
252/*
253 * Free a list item. Also clears the value. Does not notify watchers.
254 */
255 void
256listitem_free(listitem_T *item)
257{
258 clear_tv(&item->li_tv);
259 vim_free(item);
260}
261
262/*
263 * Remove a list item from a List and free it. Also clears the value.
264 */
265 void
266listitem_remove(list_T *l, listitem_T *item)
267{
268 vimlist_remove(l, item, item);
269 listitem_free(item);
270}
271
272/*
273 * Get the number of items in a list.
274 */
275 long
276list_len(list_T *l)
277{
278 if (l == NULL)
279 return 0L;
280 return l->lv_len;
281}
282
283/*
284 * Return TRUE when two lists have exactly the same values.
285 */
286 int
287list_equal(
288 list_T *l1,
289 list_T *l2,
290 int ic, /* ignore case for strings */
291 int recursive) /* TRUE when used recursively */
292{
293 listitem_T *item1, *item2;
294
295 if (l1 == NULL || l2 == NULL)
296 return FALSE;
297 if (l1 == l2)
298 return TRUE;
299 if (list_len(l1) != list_len(l2))
300 return FALSE;
301
302 for (item1 = l1->lv_first, item2 = l2->lv_first;
303 item1 != NULL && item2 != NULL;
304 item1 = item1->li_next, item2 = item2->li_next)
305 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive))
306 return FALSE;
307 return item1 == NULL && item2 == NULL;
308}
309
310/*
311 * Locate item with index "n" in list "l" and return it.
312 * A negative index is counted from the end; -1 is the last item.
313 * Returns NULL when "n" is out of range.
314 */
315 listitem_T *
316list_find(list_T *l, long n)
317{
318 listitem_T *item;
319 long idx;
320
321 if (l == NULL)
322 return NULL;
323
324 /* Negative index is relative to the end. */
325 if (n < 0)
326 n = l->lv_len + n;
327
328 /* Check for index out of range. */
329 if (n < 0 || n >= l->lv_len)
330 return NULL;
331
332 /* When there is a cached index may start search from there. */
333 if (l->lv_idx_item != NULL)
334 {
335 if (n < l->lv_idx / 2)
336 {
337 /* closest to the start of the list */
338 item = l->lv_first;
339 idx = 0;
340 }
341 else if (n > (l->lv_idx + l->lv_len) / 2)
342 {
343 /* closest to the end of the list */
344 item = l->lv_last;
345 idx = l->lv_len - 1;
346 }
347 else
348 {
349 /* closest to the cached index */
350 item = l->lv_idx_item;
351 idx = l->lv_idx;
352 }
353 }
354 else
355 {
356 if (n < l->lv_len / 2)
357 {
358 /* closest to the start of the list */
359 item = l->lv_first;
360 idx = 0;
361 }
362 else
363 {
364 /* closest to the end of the list */
365 item = l->lv_last;
366 idx = l->lv_len - 1;
367 }
368 }
369
370 while (n > idx)
371 {
372 /* search forward */
373 item = item->li_next;
374 ++idx;
375 }
376 while (n < idx)
377 {
378 /* search backward */
379 item = item->li_prev;
380 --idx;
381 }
382
383 /* cache the used index */
384 l->lv_idx = idx;
385 l->lv_idx_item = item;
386
387 return item;
388}
389
390/*
391 * Get list item "l[idx]" as a number.
392 */
393 long
394list_find_nr(
395 list_T *l,
396 long idx,
397 int *errorp) /* set to TRUE when something wrong */
398{
399 listitem_T *li;
400
401 li = list_find(l, idx);
402 if (li == NULL)
403 {
404 if (errorp != NULL)
405 *errorp = TRUE;
406 return -1L;
407 }
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100408 return (long)tv_get_number_chk(&li->li_tv, errorp);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200409}
410
411/*
412 * Get list item "l[idx - 1]" as a string. Returns NULL for failure.
413 */
414 char_u *
415list_find_str(list_T *l, long idx)
416{
417 listitem_T *li;
418
419 li = list_find(l, idx - 1);
420 if (li == NULL)
421 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100422 semsg(_(e_listidx), idx);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200423 return NULL;
424 }
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100425 return tv_get_string(&li->li_tv);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200426}
427
428/*
429 * Locate "item" list "l" and return its index.
430 * Returns -1 when "item" is not in the list.
431 */
432 long
433list_idx_of_item(list_T *l, listitem_T *item)
434{
435 long idx = 0;
436 listitem_T *li;
437
438 if (l == NULL)
439 return -1;
440 idx = 0;
441 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
442 ++idx;
443 if (li == NULL)
444 return -1;
445 return idx;
446}
447
448/*
449 * Append item "item" to the end of list "l".
450 */
451 void
452list_append(list_T *l, listitem_T *item)
453{
454 if (l->lv_last == NULL)
455 {
456 /* empty list */
457 l->lv_first = item;
458 l->lv_last = item;
459 item->li_prev = NULL;
460 }
461 else
462 {
463 l->lv_last->li_next = item;
464 item->li_prev = l->lv_last;
465 l->lv_last = item;
466 }
467 ++l->lv_len;
468 item->li_next = NULL;
469}
470
471/*
472 * Append typval_T "tv" to the end of list "l".
473 * Return FAIL when out of memory.
474 */
475 int
476list_append_tv(list_T *l, typval_T *tv)
477{
478 listitem_T *li = listitem_alloc();
479
480 if (li == NULL)
481 return FAIL;
482 copy_tv(tv, &li->li_tv);
483 list_append(l, li);
484 return OK;
485}
486
487/*
488 * Add a dictionary to a list. Used by getqflist().
489 * Return FAIL when out of memory.
490 */
491 int
492list_append_dict(list_T *list, dict_T *dict)
493{
494 listitem_T *li = listitem_alloc();
495
496 if (li == NULL)
497 return FAIL;
498 li->li_tv.v_type = VAR_DICT;
499 li->li_tv.v_lock = 0;
500 li->li_tv.vval.v_dict = dict;
501 list_append(list, li);
502 ++dict->dv_refcount;
503 return OK;
504}
505
506/*
Bram Moolenaar4f505882018-02-10 21:06:32 +0100507 * Append list2 to list1.
508 * Return FAIL when out of memory.
509 */
510 int
Bram Moolenaar6f8d2ac2018-07-25 19:49:45 +0200511list_append_list(list_T *list1, list_T *list2)
Bram Moolenaar4f505882018-02-10 21:06:32 +0100512{
513 listitem_T *li = listitem_alloc();
514
515 if (li == NULL)
516 return FAIL;
517 li->li_tv.v_type = VAR_LIST;
518 li->li_tv.v_lock = 0;
519 li->li_tv.vval.v_list = list2;
520 list_append(list1, li);
521 ++list2->lv_refcount;
522 return OK;
523}
524
525/*
Bram Moolenaarda861d62016-07-17 15:46:27 +0200526 * Make a copy of "str" and append it as an item to list "l".
527 * When "len" >= 0 use "str[len]".
528 * Returns FAIL when out of memory.
529 */
530 int
531list_append_string(list_T *l, char_u *str, int len)
532{
533 listitem_T *li = listitem_alloc();
534
535 if (li == NULL)
536 return FAIL;
537 list_append(l, li);
538 li->li_tv.v_type = VAR_STRING;
539 li->li_tv.v_lock = 0;
540 if (str == NULL)
541 li->li_tv.vval.v_string = NULL;
542 else if ((li->li_tv.vval.v_string = (len >= 0 ? vim_strnsave(str, len)
543 : vim_strsave(str))) == NULL)
544 return FAIL;
545 return OK;
546}
547
548/*
549 * Append "n" to list "l".
550 * Returns FAIL when out of memory.
551 */
552 int
553list_append_number(list_T *l, varnumber_T n)
554{
555 listitem_T *li;
556
557 li = listitem_alloc();
558 if (li == NULL)
559 return FAIL;
560 li->li_tv.v_type = VAR_NUMBER;
561 li->li_tv.v_lock = 0;
562 li->li_tv.vval.v_number = n;
563 list_append(l, li);
564 return OK;
565}
566
567/*
568 * Insert typval_T "tv" in list "l" before "item".
569 * If "item" is NULL append at the end.
570 * Return FAIL when out of memory.
571 */
572 int
573list_insert_tv(list_T *l, typval_T *tv, listitem_T *item)
574{
575 listitem_T *ni = listitem_alloc();
576
577 if (ni == NULL)
578 return FAIL;
579 copy_tv(tv, &ni->li_tv);
580 list_insert(l, ni, item);
581 return OK;
582}
583
584 void
585list_insert(list_T *l, listitem_T *ni, listitem_T *item)
586{
587 if (item == NULL)
588 /* Append new item at end of list. */
589 list_append(l, ni);
590 else
591 {
592 /* Insert new item before existing item. */
593 ni->li_prev = item->li_prev;
594 ni->li_next = item;
595 if (item->li_prev == NULL)
596 {
597 l->lv_first = ni;
598 ++l->lv_idx;
599 }
600 else
601 {
602 item->li_prev->li_next = ni;
603 l->lv_idx_item = NULL;
604 }
605 item->li_prev = ni;
606 ++l->lv_len;
607 }
608}
609
610/*
611 * Extend "l1" with "l2".
612 * If "bef" is NULL append at the end, otherwise insert before this item.
613 * Returns FAIL when out of memory.
614 */
615 int
616list_extend(list_T *l1, list_T *l2, listitem_T *bef)
617{
618 listitem_T *item;
619 int todo = l2->lv_len;
620
621 /* We also quit the loop when we have inserted the original item count of
622 * the list, avoid a hang when we extend a list with itself. */
623 for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next)
624 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
625 return FAIL;
626 return OK;
627}
628
629/*
630 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
631 * Return FAIL when out of memory.
632 */
633 int
634list_concat(list_T *l1, list_T *l2, typval_T *tv)
635{
636 list_T *l;
637
638 if (l1 == NULL || l2 == NULL)
639 return FAIL;
640
641 /* make a copy of the first list. */
642 l = list_copy(l1, FALSE, 0);
643 if (l == NULL)
644 return FAIL;
645 tv->v_type = VAR_LIST;
646 tv->vval.v_list = l;
647
648 /* append all items from the second list */
649 return list_extend(l, l2, NULL);
650}
651
652/*
653 * Make a copy of list "orig". Shallow if "deep" is FALSE.
654 * The refcount of the new list is set to 1.
655 * See item_copy() for "copyID".
656 * Returns NULL when out of memory.
657 */
658 list_T *
659list_copy(list_T *orig, int deep, int copyID)
660{
661 list_T *copy;
662 listitem_T *item;
663 listitem_T *ni;
664
665 if (orig == NULL)
666 return NULL;
667
668 copy = list_alloc();
669 if (copy != NULL)
670 {
671 if (copyID != 0)
672 {
673 /* Do this before adding the items, because one of the items may
674 * refer back to this list. */
675 orig->lv_copyID = copyID;
676 orig->lv_copylist = copy;
677 }
678 for (item = orig->lv_first; item != NULL && !got_int;
679 item = item->li_next)
680 {
681 ni = listitem_alloc();
682 if (ni == NULL)
683 break;
684 if (deep)
685 {
686 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
687 {
688 vim_free(ni);
689 break;
690 }
691 }
692 else
693 copy_tv(&item->li_tv, &ni->li_tv);
694 list_append(copy, ni);
695 }
696 ++copy->lv_refcount;
697 if (item != NULL)
698 {
699 list_unref(copy);
700 copy = NULL;
701 }
702 }
703
704 return copy;
705}
706
707/*
708 * Remove items "item" to "item2" from list "l".
709 * Does not free the listitem or the value!
710 * This used to be called list_remove, but that conflicts with a Sun header
711 * file.
712 */
713 void
714vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2)
715{
716 listitem_T *ip;
717
718 /* notify watchers */
719 for (ip = item; ip != NULL; ip = ip->li_next)
720 {
721 --l->lv_len;
722 list_fix_watch(l, ip);
723 if (ip == item2)
724 break;
725 }
726
727 if (item2->li_next == NULL)
728 l->lv_last = item->li_prev;
729 else
730 item2->li_next->li_prev = item->li_prev;
731 if (item->li_prev == NULL)
732 l->lv_first = item2->li_next;
733 else
734 item->li_prev->li_next = item2->li_next;
735 l->lv_idx_item = NULL;
736}
737
738/*
739 * Return an allocated string with the string representation of a list.
740 * May return NULL.
741 */
742 char_u *
743list2string(typval_T *tv, int copyID, int restore_copyID)
744{
745 garray_T ga;
746
747 if (tv->vval.v_list == NULL)
748 return NULL;
749 ga_init2(&ga, (int)sizeof(char), 80);
750 ga_append(&ga, '[');
751 if (list_join(&ga, tv->vval.v_list, (char_u *)", ",
752 FALSE, restore_copyID, copyID) == FAIL)
753 {
754 vim_free(ga.ga_data);
755 return NULL;
756 }
757 ga_append(&ga, ']');
758 ga_append(&ga, NUL);
759 return (char_u *)ga.ga_data;
760}
761
762typedef struct join_S {
763 char_u *s;
764 char_u *tofree;
765} join_T;
766
767 static int
768list_join_inner(
769 garray_T *gap, /* to store the result in */
770 list_T *l,
771 char_u *sep,
772 int echo_style,
773 int restore_copyID,
774 int copyID,
775 garray_T *join_gap) /* to keep each list item string */
776{
777 int i;
778 join_T *p;
779 int len;
780 int sumlen = 0;
781 int first = TRUE;
782 char_u *tofree;
783 char_u numbuf[NUMBUFLEN];
784 listitem_T *item;
785 char_u *s;
786
787 /* Stringify each item in the list. */
788 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
789 {
790 s = echo_string_core(&item->li_tv, &tofree, numbuf, copyID,
Bram Moolenaar35422f42017-08-05 16:33:56 +0200791 echo_style, restore_copyID, !echo_style);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200792 if (s == NULL)
793 return FAIL;
794
795 len = (int)STRLEN(s);
796 sumlen += len;
797
798 (void)ga_grow(join_gap, 1);
799 p = ((join_T *)join_gap->ga_data) + (join_gap->ga_len++);
800 if (tofree != NULL || s != numbuf)
801 {
802 p->s = s;
803 p->tofree = tofree;
804 }
805 else
806 {
807 p->s = vim_strnsave(s, len);
808 p->tofree = p->s;
809 }
810
811 line_breakcheck();
812 if (did_echo_string_emsg) /* recursion error, bail out */
813 break;
814 }
815
816 /* Allocate result buffer with its total size, avoid re-allocation and
817 * multiple copy operations. Add 2 for a tailing ']' and NUL. */
818 if (join_gap->ga_len >= 2)
819 sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1);
820 if (ga_grow(gap, sumlen + 2) == FAIL)
821 return FAIL;
822
823 for (i = 0; i < join_gap->ga_len && !got_int; ++i)
824 {
825 if (first)
826 first = FALSE;
827 else
828 ga_concat(gap, sep);
829 p = ((join_T *)join_gap->ga_data) + i;
830
831 if (p->s != NULL)
832 ga_concat(gap, p->s);
833 line_breakcheck();
834 }
835
836 return OK;
837}
838
839/*
840 * Join list "l" into a string in "*gap", using separator "sep".
841 * When "echo_style" is TRUE use String as echoed, otherwise as inside a List.
842 * Return FAIL or OK.
843 */
844 int
845list_join(
846 garray_T *gap,
847 list_T *l,
848 char_u *sep,
849 int echo_style,
850 int restore_copyID,
851 int copyID)
852{
853 garray_T join_ga;
854 int retval;
855 join_T *p;
856 int i;
857
858 if (l->lv_len < 1)
859 return OK; /* nothing to do */
860 ga_init2(&join_ga, (int)sizeof(join_T), l->lv_len);
861 retval = list_join_inner(gap, l, sep, echo_style, restore_copyID,
862 copyID, &join_ga);
863
864 /* Dispose each item in join_ga. */
865 if (join_ga.ga_data != NULL)
866 {
867 p = (join_T *)join_ga.ga_data;
868 for (i = 0; i < join_ga.ga_len; ++i)
869 {
870 vim_free(p->tofree);
871 ++p;
872 }
873 ga_clear(&join_ga);
874 }
875
876 return retval;
877}
878
879/*
Bram Moolenaar9f9fe372019-07-27 23:12:12 +0200880 * "join()" function
881 */
882 void
883f_join(typval_T *argvars, typval_T *rettv)
884{
885 garray_T ga;
886 char_u *sep;
887
888 if (argvars[0].v_type != VAR_LIST)
889 {
890 emsg(_(e_listreq));
891 return;
892 }
893 if (argvars[0].vval.v_list == NULL)
894 return;
895 if (argvars[1].v_type == VAR_UNKNOWN)
896 sep = (char_u *)" ";
897 else
898 sep = tv_get_string_chk(&argvars[1]);
899
900 rettv->v_type = VAR_STRING;
901
902 if (sep != NULL)
903 {
904 ga_init2(&ga, (int)sizeof(char), 80);
905 list_join(&ga, argvars[0].vval.v_list, sep, TRUE, FALSE, 0);
906 ga_append(&ga, NUL);
907 rettv->vval.v_string = (char_u *)ga.ga_data;
908 }
909 else
910 rettv->vval.v_string = NULL;
911}
912
913/*
Bram Moolenaarda861d62016-07-17 15:46:27 +0200914 * Allocate a variable for a List and fill it from "*arg".
915 * Return OK or FAIL.
916 */
917 int
918get_list_tv(char_u **arg, typval_T *rettv, int evaluate)
919{
920 list_T *l = NULL;
921 typval_T tv;
922 listitem_T *item;
923
924 if (evaluate)
925 {
926 l = list_alloc();
927 if (l == NULL)
928 return FAIL;
929 }
930
931 *arg = skipwhite(*arg + 1);
932 while (**arg != ']' && **arg != NUL)
933 {
934 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
935 goto failret;
936 if (evaluate)
937 {
938 item = listitem_alloc();
939 if (item != NULL)
940 {
941 item->li_tv = tv;
942 item->li_tv.v_lock = 0;
943 list_append(l, item);
944 }
945 else
946 clear_tv(&tv);
947 }
948
949 if (**arg == ']')
950 break;
951 if (**arg != ',')
952 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100953 semsg(_("E696: Missing comma in List: %s"), *arg);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200954 goto failret;
955 }
956 *arg = skipwhite(*arg + 1);
957 }
958
959 if (**arg != ']')
960 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100961 semsg(_("E697: Missing end of List ']': %s"), *arg);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200962failret:
963 if (evaluate)
964 list_free(l);
965 return FAIL;
966 }
967
968 *arg = skipwhite(*arg + 1);
969 if (evaluate)
Bram Moolenaar45cf6e92017-04-30 20:25:19 +0200970 rettv_list_set(rettv, l);
Bram Moolenaarda861d62016-07-17 15:46:27 +0200971
972 return OK;
973}
974
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200975/*
Bram Moolenaarcaa55b62017-01-10 13:51:09 +0100976 * Write "list" of strings to file "fd".
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200977 */
978 int
979write_list(FILE *fd, list_T *list, int binary)
980{
981 listitem_T *li;
982 int c;
983 int ret = OK;
984 char_u *s;
985
986 for (li = list->lv_first; li != NULL; li = li->li_next)
987 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100988 for (s = tv_get_string(&li->li_tv); *s != NUL; ++s)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200989 {
990 if (*s == '\n')
991 c = putc(NUL, fd);
992 else
993 c = putc(*s, fd);
994 if (c == EOF)
995 {
996 ret = FAIL;
997 break;
998 }
999 }
1000 if (!binary || li->li_next != NULL)
1001 if (putc('\n', fd) == EOF)
1002 {
1003 ret = FAIL;
1004 break;
1005 }
1006 if (ret == FAIL)
1007 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001008 emsg(_(e_write));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02001009 break;
1010 }
1011 }
1012 return ret;
1013}
1014
Bram Moolenaardf48fb42016-07-22 21:50:18 +02001015/*
1016 * Initialize a static list with 10 items.
1017 */
1018 void
1019init_static_list(staticList10_T *sl)
1020{
1021 list_T *l = &sl->sl_list;
1022 int i;
1023
1024 memset(sl, 0, sizeof(staticList10_T));
1025 l->lv_first = &sl->sl_items[0];
1026 l->lv_last = &sl->sl_items[9];
1027 l->lv_refcount = DO_NOT_FREE_CNT;
1028 l->lv_lock = VAR_FIXED;
1029 sl->sl_list.lv_len = 10;
1030
1031 for (i = 0; i < 10; ++i)
1032 {
1033 listitem_T *li = &sl->sl_items[i];
1034
1035 if (i == 0)
1036 li->li_prev = NULL;
1037 else
1038 li->li_prev = li - 1;
1039 if (i == 9)
1040 li->li_next = NULL;
1041 else
1042 li->li_next = li + 1;
1043 }
1044}
1045
Bram Moolenaar9f9fe372019-07-27 23:12:12 +02001046/*
1047 * "list2str()" function
1048 */
1049 void
1050f_list2str(typval_T *argvars, typval_T *rettv)
1051{
1052 list_T *l;
1053 listitem_T *li;
1054 garray_T ga;
1055 int utf8 = FALSE;
1056
1057 rettv->v_type = VAR_STRING;
1058 rettv->vval.v_string = NULL;
1059 if (argvars[0].v_type != VAR_LIST)
1060 {
1061 emsg(_(e_invarg));
1062 return;
1063 }
1064
1065 l = argvars[0].vval.v_list;
1066 if (l == NULL)
1067 return; // empty list results in empty string
1068
1069 if (argvars[1].v_type != VAR_UNKNOWN)
1070 utf8 = (int)tv_get_number_chk(&argvars[1], NULL);
1071
1072 ga_init2(&ga, 1, 80);
1073 if (has_mbyte || utf8)
1074 {
1075 char_u buf[MB_MAXBYTES + 1];
1076 int (*char2bytes)(int, char_u *);
1077
1078 if (utf8 || enc_utf8)
1079 char2bytes = utf_char2bytes;
1080 else
1081 char2bytes = mb_char2bytes;
1082
1083 for (li = l->lv_first; li != NULL; li = li->li_next)
1084 {
1085 buf[(*char2bytes)(tv_get_number(&li->li_tv), buf)] = NUL;
1086 ga_concat(&ga, buf);
1087 }
1088 ga_append(&ga, NUL);
1089 }
1090 else if (ga_grow(&ga, list_len(l) + 1) == OK)
1091 {
1092 for (li = l->lv_first; li != NULL; li = li->li_next)
1093 ga_append(&ga, tv_get_number(&li->li_tv));
1094 ga_append(&ga, NUL);
1095 }
1096
1097 rettv->v_type = VAR_STRING;
1098 rettv->vval.v_string = ga.ga_data;
1099}
1100
1101 void
1102list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg)
1103{
1104 list_T *l;
1105 listitem_T *item, *item2;
1106 listitem_T *li;
1107 int error = FALSE;
1108 int idx;
1109
1110 if ((l = argvars[0].vval.v_list) == NULL
1111 || var_check_lock(l->lv_lock, arg_errmsg, TRUE))
1112 return;
1113
1114 idx = (long)tv_get_number_chk(&argvars[1], &error);
1115 if (error)
1116 ; // type error: do nothing, errmsg already given
1117 else if ((item = list_find(l, idx)) == NULL)
1118 semsg(_(e_listidx), idx);
1119 else
1120 {
1121 if (argvars[2].v_type == VAR_UNKNOWN)
1122 {
1123 /* Remove one item, return its value. */
1124 vimlist_remove(l, item, item);
1125 *rettv = item->li_tv;
1126 vim_free(item);
1127 }
1128 else
1129 {
1130 // Remove range of items, return list with values.
1131 int end = (long)tv_get_number_chk(&argvars[2], &error);
1132
1133 if (error)
1134 ; // type error: do nothing
1135 else if ((item2 = list_find(l, end)) == NULL)
1136 semsg(_(e_listidx), end);
1137 else
1138 {
1139 int cnt = 0;
1140
1141 for (li = item; li != NULL; li = li->li_next)
1142 {
1143 ++cnt;
1144 if (li == item2)
1145 break;
1146 }
1147 if (li == NULL) /* didn't find "item2" after "item" */
1148 emsg(_(e_invrange));
1149 else
1150 {
1151 vimlist_remove(l, item, item2);
1152 if (rettv_list_alloc(rettv) == OK)
1153 {
1154 l = rettv->vval.v_list;
1155 l->lv_first = item;
1156 l->lv_last = item2;
1157 item->li_prev = NULL;
1158 item2->li_next = NULL;
1159 l->lv_len = cnt;
1160 }
1161 }
1162 }
1163 }
1164 }
1165}
1166
1167static int item_compare(const void *s1, const void *s2);
1168static int item_compare2(const void *s1, const void *s2);
1169
1170/* struct used in the array that's given to qsort() */
1171typedef struct
1172{
1173 listitem_T *item;
1174 int idx;
1175} sortItem_T;
1176
1177/* struct storing information about current sort */
1178typedef struct
1179{
1180 int item_compare_ic;
1181 int item_compare_numeric;
1182 int item_compare_numbers;
1183#ifdef FEAT_FLOAT
1184 int item_compare_float;
1185#endif
1186 char_u *item_compare_func;
1187 partial_T *item_compare_partial;
1188 dict_T *item_compare_selfdict;
1189 int item_compare_func_err;
1190 int item_compare_keep_zero;
1191} sortinfo_T;
1192static sortinfo_T *sortinfo = NULL;
1193#define ITEM_COMPARE_FAIL 999
1194
1195/*
1196 * Compare functions for f_sort() and f_uniq() below.
1197 */
1198 static int
1199item_compare(const void *s1, const void *s2)
1200{
1201 sortItem_T *si1, *si2;
1202 typval_T *tv1, *tv2;
1203 char_u *p1, *p2;
1204 char_u *tofree1 = NULL, *tofree2 = NULL;
1205 int res;
1206 char_u numbuf1[NUMBUFLEN];
1207 char_u numbuf2[NUMBUFLEN];
1208
1209 si1 = (sortItem_T *)s1;
1210 si2 = (sortItem_T *)s2;
1211 tv1 = &si1->item->li_tv;
1212 tv2 = &si2->item->li_tv;
1213
1214 if (sortinfo->item_compare_numbers)
1215 {
1216 varnumber_T v1 = tv_get_number(tv1);
1217 varnumber_T v2 = tv_get_number(tv2);
1218
1219 return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
1220 }
1221
1222#ifdef FEAT_FLOAT
1223 if (sortinfo->item_compare_float)
1224 {
1225 float_T v1 = tv_get_float(tv1);
1226 float_T v2 = tv_get_float(tv2);
1227
1228 return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
1229 }
1230#endif
1231
1232 /* tv2string() puts quotes around a string and allocates memory. Don't do
1233 * that for string variables. Use a single quote when comparing with a
1234 * non-string to do what the docs promise. */
1235 if (tv1->v_type == VAR_STRING)
1236 {
1237 if (tv2->v_type != VAR_STRING || sortinfo->item_compare_numeric)
1238 p1 = (char_u *)"'";
1239 else
1240 p1 = tv1->vval.v_string;
1241 }
1242 else
1243 p1 = tv2string(tv1, &tofree1, numbuf1, 0);
1244 if (tv2->v_type == VAR_STRING)
1245 {
1246 if (tv1->v_type != VAR_STRING || sortinfo->item_compare_numeric)
1247 p2 = (char_u *)"'";
1248 else
1249 p2 = tv2->vval.v_string;
1250 }
1251 else
1252 p2 = tv2string(tv2, &tofree2, numbuf2, 0);
1253 if (p1 == NULL)
1254 p1 = (char_u *)"";
1255 if (p2 == NULL)
1256 p2 = (char_u *)"";
1257 if (!sortinfo->item_compare_numeric)
1258 {
1259 if (sortinfo->item_compare_ic)
1260 res = STRICMP(p1, p2);
1261 else
1262 res = STRCMP(p1, p2);
1263 }
1264 else
1265 {
1266 double n1, n2;
1267 n1 = strtod((char *)p1, (char **)&p1);
1268 n2 = strtod((char *)p2, (char **)&p2);
1269 res = n1 == n2 ? 0 : n1 > n2 ? 1 : -1;
1270 }
1271
1272 /* When the result would be zero, compare the item indexes. Makes the
1273 * sort stable. */
1274 if (res == 0 && !sortinfo->item_compare_keep_zero)
1275 res = si1->idx > si2->idx ? 1 : -1;
1276
1277 vim_free(tofree1);
1278 vim_free(tofree2);
1279 return res;
1280}
1281
1282 static int
1283item_compare2(const void *s1, const void *s2)
1284{
1285 sortItem_T *si1, *si2;
1286 int res;
1287 typval_T rettv;
1288 typval_T argv[3];
Bram Moolenaar9f9fe372019-07-27 23:12:12 +02001289 char_u *func_name;
1290 partial_T *partial = sortinfo->item_compare_partial;
Bram Moolenaarc6538bc2019-08-03 18:17:11 +02001291 funcexe_T funcexe;
Bram Moolenaar9f9fe372019-07-27 23:12:12 +02001292
1293 /* shortcut after failure in previous call; compare all items equal */
1294 if (sortinfo->item_compare_func_err)
1295 return 0;
1296
1297 si1 = (sortItem_T *)s1;
1298 si2 = (sortItem_T *)s2;
1299
1300 if (partial == NULL)
1301 func_name = sortinfo->item_compare_func;
1302 else
1303 func_name = partial_name(partial);
1304
1305 /* Copy the values. This is needed to be able to set v_lock to VAR_FIXED
1306 * in the copy without changing the original list items. */
1307 copy_tv(&si1->item->li_tv, &argv[0]);
1308 copy_tv(&si2->item->li_tv, &argv[1]);
1309
1310 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaarc6538bc2019-08-03 18:17:11 +02001311 vim_memset(&funcexe, 0, sizeof(funcexe));
1312 funcexe.evaluate = TRUE;
1313 funcexe.partial = partial;
1314 funcexe.selfdict = sortinfo->item_compare_selfdict;
1315 res = call_func(func_name, -1, &rettv, 2, argv, &funcexe);
Bram Moolenaar9f9fe372019-07-27 23:12:12 +02001316 clear_tv(&argv[0]);
1317 clear_tv(&argv[1]);
1318
1319 if (res == FAIL)
1320 res = ITEM_COMPARE_FAIL;
1321 else
1322 res = (int)tv_get_number_chk(&rettv, &sortinfo->item_compare_func_err);
1323 if (sortinfo->item_compare_func_err)
1324 res = ITEM_COMPARE_FAIL; /* return value has wrong type */
1325 clear_tv(&rettv);
1326
1327 /* When the result would be zero, compare the pointers themselves. Makes
1328 * the sort stable. */
1329 if (res == 0 && !sortinfo->item_compare_keep_zero)
1330 res = si1->idx > si2->idx ? 1 : -1;
1331
1332 return res;
1333}
1334
1335/*
1336 * "sort()" or "uniq()" function
1337 */
1338 static void
1339do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
1340{
1341 list_T *l;
1342 listitem_T *li;
1343 sortItem_T *ptrs;
1344 sortinfo_T *old_sortinfo;
1345 sortinfo_T info;
1346 long len;
1347 long i;
1348
1349 /* Pointer to current info struct used in compare function. Save and
1350 * restore the current one for nested calls. */
1351 old_sortinfo = sortinfo;
1352 sortinfo = &info;
1353
1354 if (argvars[0].v_type != VAR_LIST)
1355 semsg(_(e_listarg), sort ? "sort()" : "uniq()");
1356 else
1357 {
1358 l = argvars[0].vval.v_list;
1359 if (l == NULL || var_check_lock(l->lv_lock,
1360 (char_u *)(sort ? N_("sort() argument") : N_("uniq() argument")),
1361 TRUE))
1362 goto theend;
1363 rettv_list_set(rettv, l);
1364
1365 len = list_len(l);
1366 if (len <= 1)
1367 goto theend; /* short list sorts pretty quickly */
1368
1369 info.item_compare_ic = FALSE;
1370 info.item_compare_numeric = FALSE;
1371 info.item_compare_numbers = FALSE;
1372#ifdef FEAT_FLOAT
1373 info.item_compare_float = FALSE;
1374#endif
1375 info.item_compare_func = NULL;
1376 info.item_compare_partial = NULL;
1377 info.item_compare_selfdict = NULL;
1378 if (argvars[1].v_type != VAR_UNKNOWN)
1379 {
1380 /* optional second argument: {func} */
1381 if (argvars[1].v_type == VAR_FUNC)
1382 info.item_compare_func = argvars[1].vval.v_string;
1383 else if (argvars[1].v_type == VAR_PARTIAL)
1384 info.item_compare_partial = argvars[1].vval.v_partial;
1385 else
1386 {
1387 int error = FALSE;
1388
1389 i = (long)tv_get_number_chk(&argvars[1], &error);
1390 if (error)
1391 goto theend; /* type error; errmsg already given */
1392 if (i == 1)
1393 info.item_compare_ic = TRUE;
1394 else if (argvars[1].v_type != VAR_NUMBER)
1395 info.item_compare_func = tv_get_string(&argvars[1]);
1396 else if (i != 0)
1397 {
1398 emsg(_(e_invarg));
1399 goto theend;
1400 }
1401 if (info.item_compare_func != NULL)
1402 {
1403 if (*info.item_compare_func == NUL)
1404 {
1405 /* empty string means default sort */
1406 info.item_compare_func = NULL;
1407 }
1408 else if (STRCMP(info.item_compare_func, "n") == 0)
1409 {
1410 info.item_compare_func = NULL;
1411 info.item_compare_numeric = TRUE;
1412 }
1413 else if (STRCMP(info.item_compare_func, "N") == 0)
1414 {
1415 info.item_compare_func = NULL;
1416 info.item_compare_numbers = TRUE;
1417 }
1418#ifdef FEAT_FLOAT
1419 else if (STRCMP(info.item_compare_func, "f") == 0)
1420 {
1421 info.item_compare_func = NULL;
1422 info.item_compare_float = TRUE;
1423 }
1424#endif
1425 else if (STRCMP(info.item_compare_func, "i") == 0)
1426 {
1427 info.item_compare_func = NULL;
1428 info.item_compare_ic = TRUE;
1429 }
1430 }
1431 }
1432
1433 if (argvars[2].v_type != VAR_UNKNOWN)
1434 {
1435 /* optional third argument: {dict} */
1436 if (argvars[2].v_type != VAR_DICT)
1437 {
1438 emsg(_(e_dictreq));
1439 goto theend;
1440 }
1441 info.item_compare_selfdict = argvars[2].vval.v_dict;
1442 }
1443 }
1444
1445 /* Make an array with each entry pointing to an item in the List. */
1446 ptrs = ALLOC_MULT(sortItem_T, len);
1447 if (ptrs == NULL)
1448 goto theend;
1449
1450 i = 0;
1451 if (sort)
1452 {
1453 /* sort(): ptrs will be the list to sort */
1454 for (li = l->lv_first; li != NULL; li = li->li_next)
1455 {
1456 ptrs[i].item = li;
1457 ptrs[i].idx = i;
1458 ++i;
1459 }
1460
1461 info.item_compare_func_err = FALSE;
1462 info.item_compare_keep_zero = FALSE;
1463 /* test the compare function */
1464 if ((info.item_compare_func != NULL
1465 || info.item_compare_partial != NULL)
1466 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
1467 == ITEM_COMPARE_FAIL)
1468 emsg(_("E702: Sort compare function failed"));
1469 else
1470 {
1471 /* Sort the array with item pointers. */
1472 qsort((void *)ptrs, (size_t)len, sizeof(sortItem_T),
1473 info.item_compare_func == NULL
1474 && info.item_compare_partial == NULL
1475 ? item_compare : item_compare2);
1476
1477 if (!info.item_compare_func_err)
1478 {
1479 /* Clear the List and append the items in sorted order. */
1480 l->lv_first = l->lv_last = l->lv_idx_item = NULL;
1481 l->lv_len = 0;
1482 for (i = 0; i < len; ++i)
1483 list_append(l, ptrs[i].item);
1484 }
1485 }
1486 }
1487 else
1488 {
1489 int (*item_compare_func_ptr)(const void *, const void *);
1490
1491 /* f_uniq(): ptrs will be a stack of items to remove */
1492 info.item_compare_func_err = FALSE;
1493 info.item_compare_keep_zero = TRUE;
1494 item_compare_func_ptr = info.item_compare_func != NULL
1495 || info.item_compare_partial != NULL
1496 ? item_compare2 : item_compare;
1497
1498 for (li = l->lv_first; li != NULL && li->li_next != NULL;
1499 li = li->li_next)
1500 {
1501 if (item_compare_func_ptr((void *)&li, (void *)&li->li_next)
1502 == 0)
1503 ptrs[i++].item = li;
1504 if (info.item_compare_func_err)
1505 {
1506 emsg(_("E882: Uniq compare function failed"));
1507 break;
1508 }
1509 }
1510
1511 if (!info.item_compare_func_err)
1512 {
1513 while (--i >= 0)
1514 {
1515 li = ptrs[i].item->li_next;
1516 ptrs[i].item->li_next = li->li_next;
1517 if (li->li_next != NULL)
1518 li->li_next->li_prev = ptrs[i].item;
1519 else
1520 l->lv_last = ptrs[i].item;
1521 list_fix_watch(l, li);
1522 listitem_free(li);
1523 l->lv_len--;
1524 }
1525 }
1526 }
1527
1528 vim_free(ptrs);
1529 }
1530theend:
1531 sortinfo = old_sortinfo;
1532}
1533
1534/*
1535 * "sort({list})" function
1536 */
1537 void
1538f_sort(typval_T *argvars, typval_T *rettv)
1539{
1540 do_sort_uniq(argvars, rettv, TRUE);
1541}
1542
1543/*
1544 * "uniq({list})" function
1545 */
1546 void
1547f_uniq(typval_T *argvars, typval_T *rettv)
1548{
1549 do_sort_uniq(argvars, rettv, FALSE);
1550}
1551
Bram Moolenaar1e1d3002019-09-04 14:41:14 +02001552/*
1553 * Handle one item for map() and filter().
1554 */
1555 static int
1556filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
1557{
1558 typval_T rettv;
1559 typval_T argv[3];
1560 int retval = FAIL;
1561
1562 copy_tv(tv, get_vim_var_tv(VV_VAL));
1563 argv[0] = *get_vim_var_tv(VV_KEY);
1564 argv[1] = *get_vim_var_tv(VV_VAL);
1565 if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL)
1566 goto theend;
1567 if (map)
1568 {
1569 // map(): replace the list item value
1570 clear_tv(tv);
1571 rettv.v_lock = 0;
1572 *tv = rettv;
1573 }
1574 else
1575 {
1576 int error = FALSE;
1577
1578 // filter(): when expr is zero remove the item
1579 *remp = (tv_get_number_chk(&rettv, &error) == 0);
1580 clear_tv(&rettv);
1581 // On type error, nothing has been removed; return FAIL to stop the
1582 // loop. The error message was given by tv_get_number_chk().
1583 if (error)
1584 goto theend;
1585 }
1586 retval = OK;
1587theend:
1588 clear_tv(get_vim_var_tv(VV_VAL));
1589 return retval;
1590}
1591
1592/*
1593 * Implementation of map() and filter().
1594 */
1595 static void
1596filter_map(typval_T *argvars, typval_T *rettv, int map)
1597{
1598 typval_T *expr;
1599 listitem_T *li, *nli;
1600 list_T *l = NULL;
1601 dictitem_T *di;
1602 hashtab_T *ht;
1603 hashitem_T *hi;
1604 dict_T *d = NULL;
1605 blob_T *b = NULL;
1606 int rem;
1607 int todo;
1608 char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
1609 char_u *arg_errmsg = (char_u *)(map ? N_("map() argument")
1610 : N_("filter() argument"));
1611 int save_did_emsg;
1612 int idx = 0;
1613
1614 if (argvars[0].v_type == VAR_BLOB)
1615 {
1616 if ((b = argvars[0].vval.v_blob) == NULL)
1617 return;
1618 }
1619 else if (argvars[0].v_type == VAR_LIST)
1620 {
1621 if ((l = argvars[0].vval.v_list) == NULL
1622 || (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE)))
1623 return;
1624 }
1625 else if (argvars[0].v_type == VAR_DICT)
1626 {
1627 if ((d = argvars[0].vval.v_dict) == NULL
1628 || (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE)))
1629 return;
1630 }
1631 else
1632 {
1633 semsg(_(e_listdictarg), ermsg);
1634 return;
1635 }
1636
1637 expr = &argvars[1];
1638 // On type errors, the preceding call has already displayed an error
1639 // message. Avoid a misleading error message for an empty string that
1640 // was not passed as argument.
1641 if (expr->v_type != VAR_UNKNOWN)
1642 {
1643 typval_T save_val;
1644 typval_T save_key;
1645
1646 prepare_vimvar(VV_VAL, &save_val);
1647 prepare_vimvar(VV_KEY, &save_key);
1648
1649 // We reset "did_emsg" to be able to detect whether an error
1650 // occurred during evaluation of the expression.
1651 save_did_emsg = did_emsg;
1652 did_emsg = FALSE;
1653
1654 if (argvars[0].v_type == VAR_DICT)
1655 {
1656 ht = &d->dv_hashtab;
1657 hash_lock(ht);
1658 todo = (int)ht->ht_used;
1659 for (hi = ht->ht_array; todo > 0; ++hi)
1660 {
1661 if (!HASHITEM_EMPTY(hi))
1662 {
1663 int r;
1664
1665 --todo;
1666 di = HI2DI(hi);
1667 if (map && (var_check_lock(di->di_tv.v_lock,
1668 arg_errmsg, TRUE)
1669 || var_check_ro(di->di_flags,
1670 arg_errmsg, TRUE)))
1671 break;
1672 set_vim_var_string(VV_KEY, di->di_key, -1);
1673 r = filter_map_one(&di->di_tv, expr, map, &rem);
1674 clear_tv(get_vim_var_tv(VV_KEY));
1675 if (r == FAIL || did_emsg)
1676 break;
1677 if (!map && rem)
1678 {
1679 if (var_check_fixed(di->di_flags, arg_errmsg, TRUE)
1680 || var_check_ro(di->di_flags, arg_errmsg, TRUE))
1681 break;
1682 dictitem_remove(d, di);
1683 }
1684 }
1685 }
1686 hash_unlock(ht);
1687 }
1688 else if (argvars[0].v_type == VAR_BLOB)
1689 {
1690 int i;
1691 typval_T tv;
1692
1693 // set_vim_var_nr() doesn't set the type
1694 set_vim_var_type(VV_KEY, VAR_NUMBER);
1695
1696 for (i = 0; i < b->bv_ga.ga_len; i++)
1697 {
1698 tv.v_type = VAR_NUMBER;
1699 tv.vval.v_number = blob_get(b, i);
1700 set_vim_var_nr(VV_KEY, idx);
1701 if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg)
1702 break;
1703 if (tv.v_type != VAR_NUMBER)
1704 {
1705 emsg(_(e_invalblob));
1706 break;
1707 }
1708 tv.v_type = VAR_NUMBER;
1709 blob_set(b, i, tv.vval.v_number);
1710 if (!map && rem)
1711 {
1712 char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
1713
1714 mch_memmove(p + idx, p + i + 1,
1715 (size_t)b->bv_ga.ga_len - i - 1);
1716 --b->bv_ga.ga_len;
1717 --i;
1718 }
1719 }
1720 }
1721 else // argvars[0].v_type == VAR_LIST
1722 {
1723 // set_vim_var_nr() doesn't set the type
1724 set_vim_var_type(VV_KEY, VAR_NUMBER);
1725
1726 for (li = l->lv_first; li != NULL; li = nli)
1727 {
1728 if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
1729 break;
1730 nli = li->li_next;
1731 set_vim_var_nr(VV_KEY, idx);
1732 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
1733 || did_emsg)
1734 break;
1735 if (!map && rem)
1736 listitem_remove(l, li);
1737 ++idx;
1738 }
1739 }
1740
1741 restore_vimvar(VV_KEY, &save_key);
1742 restore_vimvar(VV_VAL, &save_val);
1743
1744 did_emsg |= save_did_emsg;
1745 }
1746
1747 copy_tv(&argvars[0], rettv);
1748}
1749
1750/*
1751 * "filter()" function
1752 */
1753 void
1754f_filter(typval_T *argvars, typval_T *rettv)
1755{
1756 filter_map(argvars, rettv, FALSE);
1757}
1758
1759/*
1760 * "map()" function
1761 */
1762 void
1763f_map(typval_T *argvars, typval_T *rettv)
1764{
1765 filter_map(argvars, rettv, TRUE);
1766}
1767
Bram Moolenaar08c308a2019-09-04 17:48:15 +02001768/*
1769 * "add(list, item)" function
1770 */
1771 void
1772f_add(typval_T *argvars, typval_T *rettv)
1773{
1774 list_T *l;
1775 blob_T *b;
1776
1777 rettv->vval.v_number = 1; /* Default: Failed */
1778 if (argvars[0].v_type == VAR_LIST)
1779 {
1780 if ((l = argvars[0].vval.v_list) != NULL
1781 && !var_check_lock(l->lv_lock,
1782 (char_u *)N_("add() argument"), TRUE)
1783 && list_append_tv(l, &argvars[1]) == OK)
1784 copy_tv(&argvars[0], rettv);
1785 }
1786 else if (argvars[0].v_type == VAR_BLOB)
1787 {
1788 if ((b = argvars[0].vval.v_blob) != NULL
1789 && !var_check_lock(b->bv_lock,
1790 (char_u *)N_("add() argument"), TRUE))
1791 {
1792 int error = FALSE;
1793 varnumber_T n = tv_get_number_chk(&argvars[1], &error);
1794
1795 if (!error)
1796 {
1797 ga_append(&b->bv_ga, (int)n);
1798 copy_tv(&argvars[0], rettv);
1799 }
1800 }
1801 }
1802 else
1803 emsg(_(e_listblobreq));
1804}
1805
1806/*
1807 * "count()" function
1808 */
1809 void
1810f_count(typval_T *argvars, typval_T *rettv)
1811{
1812 long n = 0;
1813 int ic = FALSE;
1814 int error = FALSE;
1815
1816 if (argvars[2].v_type != VAR_UNKNOWN)
1817 ic = (int)tv_get_number_chk(&argvars[2], &error);
1818
1819 if (argvars[0].v_type == VAR_STRING)
1820 {
1821 char_u *expr = tv_get_string_chk(&argvars[1]);
1822 char_u *p = argvars[0].vval.v_string;
1823 char_u *next;
1824
1825 if (!error && expr != NULL && *expr != NUL && p != NULL)
1826 {
1827 if (ic)
1828 {
1829 size_t len = STRLEN(expr);
1830
1831 while (*p != NUL)
1832 {
1833 if (MB_STRNICMP(p, expr, len) == 0)
1834 {
1835 ++n;
1836 p += len;
1837 }
1838 else
1839 MB_PTR_ADV(p);
1840 }
1841 }
1842 else
1843 while ((next = (char_u *)strstr((char *)p, (char *)expr))
1844 != NULL)
1845 {
1846 ++n;
1847 p = next + STRLEN(expr);
1848 }
1849 }
1850
1851 }
1852 else if (argvars[0].v_type == VAR_LIST)
1853 {
1854 listitem_T *li;
1855 list_T *l;
1856 long idx;
1857
1858 if ((l = argvars[0].vval.v_list) != NULL)
1859 {
1860 li = l->lv_first;
1861 if (argvars[2].v_type != VAR_UNKNOWN)
1862 {
1863 if (argvars[3].v_type != VAR_UNKNOWN)
1864 {
1865 idx = (long)tv_get_number_chk(&argvars[3], &error);
1866 if (!error)
1867 {
1868 li = list_find(l, idx);
1869 if (li == NULL)
1870 semsg(_(e_listidx), idx);
1871 }
1872 }
1873 if (error)
1874 li = NULL;
1875 }
1876
1877 for ( ; li != NULL; li = li->li_next)
1878 if (tv_equal(&li->li_tv, &argvars[1], ic, FALSE))
1879 ++n;
1880 }
1881 }
1882 else if (argvars[0].v_type == VAR_DICT)
1883 {
1884 int todo;
1885 dict_T *d;
1886 hashitem_T *hi;
1887
1888 if ((d = argvars[0].vval.v_dict) != NULL)
1889 {
1890 if (argvars[2].v_type != VAR_UNKNOWN)
1891 {
1892 if (argvars[3].v_type != VAR_UNKNOWN)
1893 emsg(_(e_invarg));
1894 }
1895
1896 todo = error ? 0 : (int)d->dv_hashtab.ht_used;
1897 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
1898 {
1899 if (!HASHITEM_EMPTY(hi))
1900 {
1901 --todo;
1902 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE))
1903 ++n;
1904 }
1905 }
1906 }
1907 }
1908 else
1909 semsg(_(e_listdictarg), "count()");
1910 rettv->vval.v_number = n;
1911}
1912
1913/*
1914 * "extend(list, list [, idx])" function
1915 * "extend(dict, dict [, action])" function
1916 */
1917 void
1918f_extend(typval_T *argvars, typval_T *rettv)
1919{
1920 char_u *arg_errmsg = (char_u *)N_("extend() argument");
1921
1922 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
1923 {
1924 list_T *l1, *l2;
1925 listitem_T *item;
1926 long before;
1927 int error = FALSE;
1928
1929 l1 = argvars[0].vval.v_list;
1930 l2 = argvars[1].vval.v_list;
1931 if (l1 != NULL && !var_check_lock(l1->lv_lock, arg_errmsg, TRUE)
1932 && l2 != NULL)
1933 {
1934 if (argvars[2].v_type != VAR_UNKNOWN)
1935 {
1936 before = (long)tv_get_number_chk(&argvars[2], &error);
1937 if (error)
1938 return; /* type error; errmsg already given */
1939
1940 if (before == l1->lv_len)
1941 item = NULL;
1942 else
1943 {
1944 item = list_find(l1, before);
1945 if (item == NULL)
1946 {
1947 semsg(_(e_listidx), before);
1948 return;
1949 }
1950 }
1951 }
1952 else
1953 item = NULL;
1954 list_extend(l1, l2, item);
1955
1956 copy_tv(&argvars[0], rettv);
1957 }
1958 }
1959 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
1960 {
1961 dict_T *d1, *d2;
1962 char_u *action;
1963 int i;
1964
1965 d1 = argvars[0].vval.v_dict;
1966 d2 = argvars[1].vval.v_dict;
1967 if (d1 != NULL && !var_check_lock(d1->dv_lock, arg_errmsg, TRUE)
1968 && d2 != NULL)
1969 {
1970 /* Check the third argument. */
1971 if (argvars[2].v_type != VAR_UNKNOWN)
1972 {
1973 static char *(av[]) = {"keep", "force", "error"};
1974
1975 action = tv_get_string_chk(&argvars[2]);
1976 if (action == NULL)
1977 return; /* type error; errmsg already given */
1978 for (i = 0; i < 3; ++i)
1979 if (STRCMP(action, av[i]) == 0)
1980 break;
1981 if (i == 3)
1982 {
1983 semsg(_(e_invarg2), action);
1984 return;
1985 }
1986 }
1987 else
1988 action = (char_u *)"force";
1989
1990 dict_extend(d1, d2, action);
1991
1992 copy_tv(&argvars[0], rettv);
1993 }
1994 }
1995 else
1996 semsg(_(e_listdictarg), "extend()");
1997}
1998
1999/*
2000 * "insert()" function
2001 */
2002 void
2003f_insert(typval_T *argvars, typval_T *rettv)
2004{
2005 long before = 0;
2006 listitem_T *item;
2007 list_T *l;
2008 int error = FALSE;
2009
2010 if (argvars[0].v_type == VAR_BLOB)
2011 {
2012 int val, len;
2013 char_u *p;
2014
2015 len = blob_len(argvars[0].vval.v_blob);
2016 if (argvars[2].v_type != VAR_UNKNOWN)
2017 {
2018 before = (long)tv_get_number_chk(&argvars[2], &error);
2019 if (error)
2020 return; // type error; errmsg already given
2021 if (before < 0 || before > len)
2022 {
2023 semsg(_(e_invarg2), tv_get_string(&argvars[2]));
2024 return;
2025 }
2026 }
2027 val = tv_get_number_chk(&argvars[1], &error);
2028 if (error)
2029 return;
2030 if (val < 0 || val > 255)
2031 {
2032 semsg(_(e_invarg2), tv_get_string(&argvars[1]));
2033 return;
2034 }
2035
2036 if (ga_grow(&argvars[0].vval.v_blob->bv_ga, 1) == FAIL)
2037 return;
2038 p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
2039 mch_memmove(p + before + 1, p + before, (size_t)len - before);
2040 *(p + before) = val;
2041 ++argvars[0].vval.v_blob->bv_ga.ga_len;
2042
2043 copy_tv(&argvars[0], rettv);
2044 }
2045 else if (argvars[0].v_type != VAR_LIST)
2046 semsg(_(e_listblobarg), "insert()");
2047 else if ((l = argvars[0].vval.v_list) != NULL
2048 && !var_check_lock(l->lv_lock,
2049 (char_u *)N_("insert() argument"), TRUE))
2050 {
2051 if (argvars[2].v_type != VAR_UNKNOWN)
2052 before = (long)tv_get_number_chk(&argvars[2], &error);
2053 if (error)
2054 return; /* type error; errmsg already given */
2055
2056 if (before == l->lv_len)
2057 item = NULL;
2058 else
2059 {
2060 item = list_find(l, before);
2061 if (item == NULL)
2062 {
2063 semsg(_(e_listidx), before);
2064 l = NULL;
2065 }
2066 }
2067 if (l != NULL)
2068 {
2069 list_insert_tv(l, &argvars[1], item);
2070 copy_tv(&argvars[0], rettv);
2071 }
2072 }
2073}
2074
2075/*
2076 * "remove()" function
2077 */
2078 void
2079f_remove(typval_T *argvars, typval_T *rettv)
2080{
2081 char_u *arg_errmsg = (char_u *)N_("remove() argument");
2082
2083 if (argvars[0].v_type == VAR_DICT)
2084 dict_remove(argvars, rettv, arg_errmsg);
2085 else if (argvars[0].v_type == VAR_BLOB)
2086 blob_remove(argvars, rettv);
2087 else if (argvars[0].v_type == VAR_LIST)
2088 list_remove(argvars, rettv, arg_errmsg);
2089 else
2090 semsg(_(e_listdictblobarg), "remove()");
2091}
2092
2093/*
2094 * "reverse({list})" function
2095 */
2096 void
2097f_reverse(typval_T *argvars, typval_T *rettv)
2098{
2099 list_T *l;
2100 listitem_T *li, *ni;
2101
2102 if (argvars[0].v_type == VAR_BLOB)
2103 {
2104 blob_T *b = argvars[0].vval.v_blob;
2105 int i, len = blob_len(b);
2106
2107 for (i = 0; i < len / 2; i++)
2108 {
2109 int tmp = blob_get(b, i);
2110
2111 blob_set(b, i, blob_get(b, len - i - 1));
2112 blob_set(b, len - i - 1, tmp);
2113 }
2114 rettv_blob_set(rettv, b);
2115 return;
2116 }
2117
2118 if (argvars[0].v_type != VAR_LIST)
2119 semsg(_(e_listblobarg), "reverse()");
2120 else if ((l = argvars[0].vval.v_list) != NULL
2121 && !var_check_lock(l->lv_lock,
2122 (char_u *)N_("reverse() argument"), TRUE))
2123 {
2124 li = l->lv_last;
2125 l->lv_first = l->lv_last = NULL;
2126 l->lv_len = 0;
2127 while (li != NULL)
2128 {
2129 ni = li->li_prev;
2130 list_append(l, li);
2131 li = ni;
2132 }
2133 rettv_list_set(rettv, l);
2134 l->lv_idx = l->lv_len - l->lv_idx - 1;
2135 }
2136}
2137
Bram Moolenaar1e1d3002019-09-04 14:41:14 +02002138#endif // defined(FEAT_EVAL)