comparison src/if_py_both.h @ 5608:ec02e1474bc2 v7.4.151

updated for version 7.4.151 Problem: Python: slices with steps are not supported. Solution: Support slices in Python vim.List. (ZyX)
author Bram Moolenaar <bram@vim.org>
date Tue, 14 Jan 2014 16:36:51 +0100
parents 2ca470c6096e
children 2ace11abcfb5
comparison
equal deleted inserted replaced
5607:98a642716acc 5608:ec02e1474bc2
34 static const char *vim_special_path = "_vim_path_"; 34 static const char *vim_special_path = "_vim_path_";
35 35
36 #define PyErr_SET_STRING(exc, str) PyErr_SetString(exc, _(str)) 36 #define PyErr_SET_STRING(exc, str) PyErr_SetString(exc, _(str))
37 #define PyErr_SetVim(str) PyErr_SetString(VimError, str) 37 #define PyErr_SetVim(str) PyErr_SetString(VimError, str)
38 #define PyErr_SET_VIM(str) PyErr_SET_STRING(VimError, str) 38 #define PyErr_SET_VIM(str) PyErr_SET_STRING(VimError, str)
39 #define PyErr_FORMAT(exc, str, tail) PyErr_Format(exc, _(str), tail) 39 #define PyErr_FORMAT(exc, str, arg) PyErr_Format(exc, _(str), arg)
40 #define PyErr_VIM_FORMAT(str, tail) PyErr_FORMAT(VimError, str, tail) 40 #define PyErr_FORMAT2(exc, str, arg1, arg2) PyErr_Format(exc, _(str), arg1,arg2)
41 #define PyErr_VIM_FORMAT(str, arg) PyErr_FORMAT(VimError, str, arg)
41 42
42 #define Py_TYPE_NAME(obj) (obj->ob_type->tp_name == NULL \ 43 #define Py_TYPE_NAME(obj) (obj->ob_type->tp_name == NULL \
43 ? "(NULL)" \ 44 ? "(NULL)" \
44 : obj->ob_type->tp_name) 45 : obj->ob_type->tp_name)
45 46
2106 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""}, 2107 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
2107 { NULL, NULL, 0, NULL} 2108 { NULL, NULL, 0, NULL}
2108 }; 2109 };
2109 2110
2110 static PyTypeObject ListType; 2111 static PyTypeObject ListType;
2111 static PySequenceMethods ListAsSeq;
2112 static PyMappingMethods ListAsMapping;
2113 2112
2114 typedef struct 2113 typedef struct
2115 { 2114 {
2116 PyObject_HEAD 2115 PyObject_HEAD
2117 list_T *list; 2116 list_T *list;
2251 { 2250 {
2252 return ((PyInt) (self->list->lv_len)); 2251 return ((PyInt) (self->list->lv_len));
2253 } 2252 }
2254 2253
2255 static PyObject * 2254 static PyObject *
2256 ListItem(ListObject *self, Py_ssize_t index) 2255 ListIndex(ListObject *self, Py_ssize_t index)
2257 { 2256 {
2258 listitem_T *li; 2257 listitem_T *li;
2259 2258
2260 if (index >= ListLength(self)) 2259 if (index >= ListLength(self))
2261 { 2260 {
2271 return NULL; 2270 return NULL;
2272 } 2271 }
2273 return ConvertToPyObject(&li->li_tv); 2272 return ConvertToPyObject(&li->li_tv);
2274 } 2273 }
2275 2274
2276 #define PROC_RANGE \ 2275 static PyObject *
2277 if (last < 0) {\ 2276 ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t step,
2278 if (last < -size) \ 2277 Py_ssize_t slicelen)
2279 last = 0; \
2280 else \
2281 last += size; \
2282 } \
2283 if (first < 0) \
2284 first = 0; \
2285 if (first > size) \
2286 first = size; \
2287 if (last > size) \
2288 last = size;
2289
2290 static PyObject *
2291 ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last)
2292 { 2278 {
2293 PyInt i; 2279 PyInt i;
2294 PyInt size = ListLength(self);
2295 PyInt n;
2296 PyObject *list; 2280 PyObject *list;
2297 int reversed = 0; 2281
2298 2282 if (step == 0)
2299 PROC_RANGE 2283 {
2300 if (first >= last) 2284 PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero"));
2301 first = last; 2285 return NULL;
2302 2286 }
2303 n = last-first; 2287
2304 list = PyList_New(n); 2288 list = PyList_New(slicelen);
2305 if (list == NULL) 2289 if (list == NULL)
2306 return NULL; 2290 return NULL;
2307 2291
2308 for (i = 0; i < n; ++i) 2292 for (i = 0; i < slicelen; ++i)
2309 { 2293 {
2310 PyObject *item = ListItem(self, first + i); 2294 PyObject *item;
2295
2296 item = ListIndex(self, first + i*step);
2311 if (item == NULL) 2297 if (item == NULL)
2312 { 2298 {
2313 Py_DECREF(list); 2299 Py_DECREF(list);
2314 return NULL; 2300 return NULL;
2315 } 2301 }
2316 2302
2317 PyList_SET_ITEM(list, ((reversed)?(n-i-1):(i)), item); 2303 PyList_SET_ITEM(list, i, item);
2318 } 2304 }
2319 2305
2320 return list; 2306 return list;
2321 } 2307 }
2322 2308
2323 typedef struct 2309 static PyObject *
2324 { 2310 ListItem(ListObject *self, PyObject* idx)
2325 listwatch_T lw; 2311 {
2326 list_T *list; 2312 #if PY_MAJOR_VERSION < 3
2327 } listiterinfo_T; 2313 if (PyInt_Check(idx))
2314 {
2315 long _idx = PyInt_AsLong(idx);
2316 return ListIndex(self, _idx);
2317 }
2318 else
2319 #endif
2320 if (PyLong_Check(idx))
2321 {
2322 long _idx = PyLong_AsLong(idx);
2323 return ListIndex(self, _idx);
2324 }
2325 else if (PySlice_Check(idx))
2326 {
2327 Py_ssize_t start, stop, step, slicelen;
2328
2329 if (PySlice_GetIndicesEx(idx, ListLength(self),
2330 &start, &stop, &step, &slicelen) < 0)
2331 return NULL;
2332 return ListSlice(self, start, step, slicelen);
2333 }
2334 else
2335 {
2336 RAISE_INVALID_INDEX_TYPE(idx);
2337 return NULL;
2338 }
2339 }
2328 2340
2329 static void 2341 static void
2330 ListIterDestruct(listiterinfo_T *lii) 2342 list_restore(Py_ssize_t numadded, Py_ssize_t numreplaced, Py_ssize_t slicelen,
2331 { 2343 list_T *l, listitem_T **lis, listitem_T *lastaddedli)
2332 list_rem_watch(lii->list, &lii->lw); 2344 {
2333 PyMem_Free(lii); 2345 while (numreplaced--)
2334 } 2346 {
2335 2347 list_insert(l, lis[numreplaced], lis[slicelen + numreplaced]);
2336 static PyObject * 2348 listitem_remove(l, lis[slicelen + numreplaced]);
2337 ListIterNext(listiterinfo_T **lii) 2349 }
2338 { 2350 while (numadded--)
2339 PyObject *ret; 2351 {
2340 2352 listitem_T *next;
2341 if (!((*lii)->lw.lw_item)) 2353
2342 return NULL; 2354 next = lastaddedli->li_prev;
2343 2355 listitem_remove(l, lastaddedli);
2344 if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv)))) 2356 lastaddedli = next;
2345 return NULL; 2357 }
2346 2358 }
2347 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next; 2359
2348 2360 static int
2349 return ret; 2361 ListAssSlice(ListObject *self, Py_ssize_t first,
2350 } 2362 Py_ssize_t step, Py_ssize_t slicelen, PyObject *obj)
2351 2363 {
2352 static PyObject * 2364 PyObject *iterator;
2353 ListIter(ListObject *self) 2365 PyObject *item;
2354 { 2366 listitem_T *li;
2355 listiterinfo_T *lii; 2367 listitem_T *lastaddedli = NULL;
2368 listitem_T *next;
2369 typval_T v;
2356 list_T *l = self->list; 2370 list_T *l = self->list;
2357 2371 PyInt i;
2358 if (!(lii = PyMem_New(listiterinfo_T, 1))) 2372 PyInt j;
2359 { 2373 PyInt numreplaced = 0;
2360 PyErr_NoMemory(); 2374 PyInt numadded = 0;
2361 return NULL; 2375 PyInt size;
2362 } 2376 listitem_T **lis;
2363 2377
2364 list_add_watch(l, &lii->lw); 2378 size = ListLength(self);
2365 lii->lw.lw_item = l->lv_first; 2379
2366 lii->list = l; 2380 if (l->lv_lock)
2367 2381 {
2368 return IterNew(lii, 2382 RAISE_LOCKED_LIST;
2369 (destructorfun) ListIterDestruct, (nextfun) ListIterNext, 2383 return -1;
2370 NULL, NULL); 2384 }
2385
2386 if (step == 0)
2387 {
2388 PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero"));
2389 return -1;
2390 }
2391
2392 if (step != 1 && slicelen == 0)
2393 {
2394 /* Nothing to do. Only error out if obj has some items. */
2395 int ret = 0;
2396
2397 if (obj == NULL)
2398 return 0;
2399
2400 if (!(iterator = PyObject_GetIter(obj)))
2401 return -1;
2402
2403 if ((item = PyIter_Next(iterator)))
2404 {
2405 PyErr_FORMAT(PyExc_ValueError,
2406 N_("attempt to assign sequence of size greater then %d "
2407 "to extended slice"), 0);
2408 Py_DECREF(item);
2409 ret = -1;
2410 }
2411 Py_DECREF(iterator);
2412 return ret;
2413 }
2414
2415 if (obj != NULL)
2416 /* XXX May allocate zero bytes. */
2417 if (!(lis = PyMem_New(listitem_T *, slicelen * 2)))
2418 {
2419 PyErr_NoMemory();
2420 return -1;
2421 }
2422
2423 if (first == size)
2424 li = NULL;
2425 else
2426 {
2427 li = list_find(l, (long) first);
2428 if (li == NULL)
2429 {
2430 PyErr_VIM_FORMAT(N_("internal error: no vim list item %d"),
2431 (int)first);
2432 if (obj != NULL)
2433 PyMem_Free(lis);
2434 return -1;
2435 }
2436 i = slicelen;
2437 while (i-- && li != NULL)
2438 {
2439 j = step;
2440 next = li;
2441 if (step > 0)
2442 while (next != NULL && ((next = next->li_next) != NULL) && --j);
2443 else
2444 while (next != NULL && ((next = next->li_prev) != NULL) && ++j);
2445
2446 if (obj == NULL)
2447 listitem_remove(l, li);
2448 else
2449 lis[slicelen - i - 1] = li;
2450
2451 li = next;
2452 }
2453 if (li == NULL && i != -1)
2454 {
2455 PyErr_SET_VIM(N_("internal error: not enough list items"));
2456 if (obj != NULL)
2457 PyMem_Free(lis);
2458 return -1;
2459 }
2460 }
2461
2462 if (obj == NULL)
2463 return 0;
2464
2465 if (!(iterator = PyObject_GetIter(obj)))
2466 {
2467 PyMem_Free(lis);
2468 return -1;
2469 }
2470
2471 i = 0;
2472 while ((item = PyIter_Next(iterator)))
2473 {
2474 if (ConvertFromPyObject(item, &v) == -1)
2475 {
2476 Py_DECREF(iterator);
2477 Py_DECREF(item);
2478 PyMem_Free(lis);
2479 return -1;
2480 }
2481 Py_DECREF(item);
2482 if (list_insert_tv(l, &v, numreplaced < slicelen
2483 ? lis[numreplaced]
2484 : li) == FAIL)
2485 {
2486 clear_tv(&v);
2487 PyErr_SET_VIM(N_("internal error: failed to add item to list"));
2488 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2489 PyMem_Free(lis);
2490 return -1;
2491 }
2492 if (numreplaced < slicelen)
2493 {
2494 lis[slicelen + numreplaced] = lis[numreplaced]->li_prev;
2495 list_remove(l, lis[numreplaced], lis[numreplaced]);
2496 numreplaced++;
2497 }
2498 else
2499 {
2500 if (li)
2501 lastaddedli = li->li_prev;
2502 else
2503 lastaddedli = l->lv_last;
2504 numadded++;
2505 }
2506 clear_tv(&v);
2507 if (step != 1 && i >= slicelen)
2508 {
2509 Py_DECREF(iterator);
2510 PyErr_FORMAT(PyExc_ValueError,
2511 N_("attempt to assign sequence of size greater then %d "
2512 "to extended slice"), slicelen);
2513 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2514 PyMem_Free(lis);
2515 return -1;
2516 }
2517 ++i;
2518 }
2519 Py_DECREF(iterator);
2520
2521 if (step != 1 && i != slicelen)
2522 {
2523 PyErr_FORMAT2(PyExc_ValueError,
2524 N_("attempt to assign sequence of size %d to extended slice "
2525 "of size %d"), i, slicelen);
2526 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2527 PyMem_Free(lis);
2528 return -1;
2529 }
2530
2531 if (PyErr_Occurred())
2532 {
2533 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2534 PyMem_Free(lis);
2535 return -1;
2536 }
2537
2538 for (i = 0; i < numreplaced; i++)
2539 listitem_free(lis[i]);
2540 if (step == 1)
2541 for (i = numreplaced; i < slicelen; i++)
2542 listitem_remove(l, lis[i]);
2543
2544 PyMem_Free(lis);
2545
2546 return 0;
2371 } 2547 }
2372 2548
2373 static int 2549 static int
2374 ListAssItem(ListObject *self, Py_ssize_t index, PyObject *obj) 2550 ListAssIndex(ListObject *self, Py_ssize_t index, PyObject *obj)
2375 { 2551 {
2376 typval_T tv; 2552 typval_T tv;
2377 list_T *l = self->list; 2553 list_T *l = self->list;
2378 listitem_T *li; 2554 listitem_T *li;
2379 Py_ssize_t length = ListLength(self); 2555 Py_ssize_t length = ListLength(self);
2418 clear_tv(&tv); 2594 clear_tv(&tv);
2419 } 2595 }
2420 return 0; 2596 return 0;
2421 } 2597 }
2422 2598
2423 static int 2599 static Py_ssize_t
2424 ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj) 2600 ListAssItem(ListObject *self, PyObject *idx, PyObject *obj)
2425 { 2601 {
2426 PyInt size = ListLength(self); 2602 #if PY_MAJOR_VERSION < 3
2427 PyObject *iterator; 2603 if (PyInt_Check(idx))
2428 PyObject *item; 2604 {
2429 listitem_T *li; 2605 long _idx = PyInt_AsLong(idx);
2430 listitem_T *next; 2606 return ListAssIndex(self, _idx, obj);
2431 typval_T v; 2607 }
2432 list_T *l = self->list;
2433 PyInt i;
2434
2435 if (l->lv_lock)
2436 {
2437 RAISE_LOCKED_LIST;
2438 return -1;
2439 }
2440
2441 PROC_RANGE
2442
2443 if (first == size)
2444 li = NULL;
2445 else 2608 else
2446 { 2609 #endif
2447 li = list_find(l, (long) first); 2610 if (PyLong_Check(idx))
2448 if (li == NULL) 2611 {
2449 { 2612 long _idx = PyLong_AsLong(idx);
2450 PyErr_VIM_FORMAT(N_("internal error: no vim list item %d"), 2613 return ListAssIndex(self, _idx, obj);
2451 (int)first); 2614 }
2452 return -1; 2615 else if (PySlice_Check(idx))
2453 } 2616 {
2454 if (last > first) 2617 Py_ssize_t start, stop, step, slicelen;
2455 { 2618
2456 i = last - first; 2619 if (PySlice_GetIndicesEx(idx, ListLength(self),
2457 while (i-- && li != NULL) 2620 &start, &stop, &step, &slicelen) < 0)
2458 { 2621 return -1;
2459 next = li->li_next; 2622 return ListAssSlice(self, start, step, slicelen,
2460 listitem_remove(l, li); 2623 obj);
2461 li = next; 2624 }
2462 } 2625 else
2463 } 2626 {
2464 } 2627 RAISE_INVALID_INDEX_TYPE(idx);
2465 2628 return -1;
2466 if (obj == NULL) 2629 }
2467 return 0;
2468
2469 if (!(iterator = PyObject_GetIter(obj)))
2470 return -1;
2471
2472 while ((item = PyIter_Next(iterator)))
2473 {
2474 if (ConvertFromPyObject(item, &v) == -1)
2475 {
2476 Py_DECREF(iterator);
2477 Py_DECREF(item);
2478 return -1;
2479 }
2480 Py_DECREF(item);
2481 if (list_insert_tv(l, &v, li) == FAIL)
2482 {
2483 clear_tv(&v);
2484 PyErr_SET_VIM(N_("internal error: failed to add item to list"));
2485 return -1;
2486 }
2487 clear_tv(&v);
2488 }
2489 Py_DECREF(iterator);
2490
2491 if (PyErr_Occurred())
2492 return -1;
2493
2494 return 0;
2495 } 2630 }
2496 2631
2497 static PyObject * 2632 static PyObject *
2498 ListConcatInPlace(ListObject *self, PyObject *obj) 2633 ListConcatInPlace(ListObject *self, PyObject *obj)
2499 { 2634 {
2516 } 2651 }
2517 Py_DECREF(lookup_dict); 2652 Py_DECREF(lookup_dict);
2518 2653
2519 Py_INCREF(self); 2654 Py_INCREF(self);
2520 return (PyObject *)(self); 2655 return (PyObject *)(self);
2656 }
2657
2658 typedef struct
2659 {
2660 listwatch_T lw;
2661 list_T *list;
2662 } listiterinfo_T;
2663
2664 static void
2665 ListIterDestruct(listiterinfo_T *lii)
2666 {
2667 list_rem_watch(lii->list, &lii->lw);
2668 PyMem_Free(lii);
2669 }
2670
2671 static PyObject *
2672 ListIterNext(listiterinfo_T **lii)
2673 {
2674 PyObject *ret;
2675
2676 if (!((*lii)->lw.lw_item))
2677 return NULL;
2678
2679 if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
2680 return NULL;
2681
2682 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
2683
2684 return ret;
2685 }
2686
2687 static PyObject *
2688 ListIter(ListObject *self)
2689 {
2690 listiterinfo_T *lii;
2691 list_T *l = self->list;
2692
2693 if (!(lii = PyMem_New(listiterinfo_T, 1)))
2694 {
2695 PyErr_NoMemory();
2696 return NULL;
2697 }
2698
2699 list_add_watch(l, &lii->lw);
2700 lii->lw.lw_item = l->lv_first;
2701 lii->list = l;
2702
2703 return IterNew(lii,
2704 (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
2705 NULL, NULL);
2521 } 2706 }
2522 2707
2523 static char *ListAttrs[] = { 2708 static char *ListAttrs[] = {
2524 "locked", 2709 "locked",
2525 NULL 2710 NULL
2564 { 2749 {
2565 PyErr_FORMAT(PyExc_AttributeError, N_("cannot set attribute %s"), name); 2750 PyErr_FORMAT(PyExc_AttributeError, N_("cannot set attribute %s"), name);
2566 return -1; 2751 return -1;
2567 } 2752 }
2568 } 2753 }
2754
2755 static PySequenceMethods ListAsSeq = {
2756 (lenfunc) ListLength, /* sq_length, len(x) */
2757 (binaryfunc) 0, /* RangeConcat, sq_concat, x+y */
2758 0, /* RangeRepeat, sq_repeat, x*n */
2759 (PyIntArgFunc) ListIndex, /* sq_item, x[i] */
2760 0, /* was_sq_slice, x[i:j] */
2761 (PyIntObjArgProc) ListAssIndex, /* sq_as_item, x[i]=v */
2762 0, /* was_sq_ass_slice, x[i:j]=v */
2763 0, /* sq_contains */
2764 (binaryfunc) ListConcatInPlace,/* sq_inplace_concat */
2765 0, /* sq_inplace_repeat */
2766 };
2767
2768 static PyMappingMethods ListAsMapping = {
2769 /* mp_length */ (lenfunc) ListLength,
2770 /* mp_subscript */ (binaryfunc) ListItem,
2771 /* mp_ass_subscript */ (objobjargproc) ListAssItem,
2772 };
2569 2773
2570 static struct PyMethodDef ListMethods[] = { 2774 static struct PyMethodDef ListMethods[] = {
2571 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""}, 2775 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
2572 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""}, 2776 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
2573 { NULL, NULL, 0, NULL} 2777 { NULL, NULL, 0, NULL}