Synopsis - Cross-Reference
File: /src/Synopsis/Python/Object.hh1// 2// Copyright (C) 2004 Stefan Seefeld 3// All rights reserved. 4// Licensed to the public under the terms of the GNU LGPL (>= 2), 5// see the file COPYING for details. 6// 7 8#ifndef _Synopsis_Python_Object_hh 9#define _Synopsis_Python_Object_hh 10 11#include <Python.h> 12#include <string> 13#include <stdexcept> 14#include <iostream> 15 16#if PY_VERSION_HEX >= 0x02030000 17# define PYTHON_HAS_BOOL 1 18#else 19# define PYTHON_HAS_BOOL 0 20#endif 21 22#if PY_VERSION_HEX < 0x02050000 23typedef int Py_ssize_t; 24#endif 25 26namespace Synopsis 27{ 28namespace Python 29{ 30 31class List; 32class Tuple; 33class Dict; 34class Module; 35class Interpreter; 36 37//. Object provides basic 38//. functionality to access the underlaying 39//. python object, to be used in subclasses and 40//. generic accessors such as (python) lists and tuples 41class Object 42{ 43 friend class List; 44 friend class Tuple; 45 friend class Dict; 46 friend class Module; 47 friend class Interpreter; 48public: 49 struct TypeError : std::invalid_argument 50 { 51 TypeError(const std::string &msg = "") : std::invalid_argument(msg) {} 52 }; 53 54 struct AttributeError : std::invalid_argument 55 { 56 AttributeError(const std::string &msg = "") : std::invalid_argument(msg) {} 57 }; 58 59 struct KeyError : std::invalid_argument 60 { 61 KeyError(const std::string &msg = "") : std::invalid_argument(msg) {} 62 }; 63 64 struct ImportError : std::invalid_argument 65 { 66 ImportError(const std::string &msg = "") : std::invalid_argument(msg) {} 67 }; 68 69 Object() : my_impl(Py_None) { Py_INCREF(Py_None);} 70 Object(PyObject *); 71 Object(const Object &o) : my_impl(o.my_impl) { Py_INCREF(my_impl);} 72 Object(const std::string &value) : my_impl(PyString_FromString(value.c_str())) {} 73 Object(const char *value) : my_impl(PyString_FromString(value)) {} 74 Object(char value) : my_impl(PyString_FromStringAndSize(&value, 1)) {} 75 Object(double value) : my_impl(PyFloat_FromDouble(value)) {} 76 Object(int value) : my_impl(PyInt_FromLong(value)) {} 77 Object(unsigned int value) : my_impl(PyInt_FromLong(value)) {} 78 Object(long value) : my_impl(PyInt_FromLong(value)) {} 79 Object(bool value) : my_impl(PyInt_FromLong(value)) {} 80 virtual ~Object() { Py_DECREF(my_impl);} 81 Object &operator = (const Object &o); 82 83 int hash() const { return PyObject_Hash(my_impl);} 84 operator bool () const 85 { 86 int retn = PyObject_IsTrue(my_impl); 87 if (retn == -1) check_exception(); 88 return retn == 1; 89 } 90 Object type() const { return PyObject_Type(my_impl);} 91 Object repr() const { return PyObject_Repr(my_impl);} 92 Object str() const { return PyObject_Str(my_impl);} 93 int cmp(Object o) const; 94 Object boolean() const { return PyObject_IsTrue(my_impl);} 95 bool is_instance(Object) const; 96 void assert_type(const char *module, 97 const char *type) const 98 throw(TypeError); 99 100 //. callable interface 101 Object operator () (); 102 Object operator () (Tuple); 103 Object operator () (Tuple, Dict); 104 105 Object get(Object) const; 106 107 //. try to downcast to T, throw on failure 108 template <typename T> 109 static T narrow(Object) throw(TypeError); 110 //. more relaxed form of downcast, return None on failure 111 template <typename T> 112 static T try_narrow(Object); 113 static Object import(const std::string &name); 114 115 Object attr(const std::string &) const; 116 bool set_attr(const std::string &, Object); 117 PyObject *ref() { Py_INCREF(my_impl); return my_impl;} 118 int ref_count() const { return my_impl->ob_refcnt;} 119private: 120 //. check for an exception and if set translate into 121 //. a C++ exception that is thrown 122 void check_exception() const; 123 124 PyObject *my_impl; 125}; 126 127inline bool operator == (Object o1, Object o2) { return !o1.cmp(o2);} 128inline bool operator < (Object o1, Object o2) { return o1.cmp(o2) < 0;} 129inline bool operator > (Object o1, Object o2) { return o1.cmp(o2)> 0;} 130 131class Tuple : public Object 132{ 133public: 134 Tuple() : Object(PyTuple_New(0)) {} 135 explicit Tuple(PyObject *); 136 size_t size() const { return PyTuple_GET_SIZE(my_impl);} 137 bool empty() const { return !size();} 138 Tuple(Object); 139 Tuple(Object, Object); 140 Tuple(Object, Object, Object); 141 Tuple(Object, Object, Object, Object); 142 Tuple(Object, Object, Object, Object, Object); 143 Tuple(Object, Object, Object, Object, Object, Object); 144 Tuple(Object, Object, Object, Object, Object, Object, Object); 145 Tuple(Object, Object, Object, Object, Object, Object, Object, Object); 146 Tuple(Object, Object, Object, Object, Object, Object, Object, Object, Object); 147 Object get(size_t i) const; 148}; 149 150class List : public Object 151{ 152public: 153 class iterator; 154 class reverse_iterator; 155 156 List(size_t i = 0) : Object(PyList_New(i)) {} 157 List(Object) throw(TypeError); 158 template <typename I> 159 List(I begin, I end); 160 Tuple tuple() const { return Tuple(PyList_AsTuple(my_impl));} 161 size_t size() const { return PyList_GET_SIZE(my_impl);} 162 bool empty() const { return !size();} 163 void set(int i, Object o); 164 Object get(int i) const; 165 void append(Object o) { PyList_Append(my_impl, o.my_impl);} 166 void insert(int i, Object o) { PyList_Insert(my_impl, i, o.my_impl);} 167 void extend(List l); 168 void del(int i) { PySequence_DelItem(my_impl, i);} 169 170 iterator begin() const; 171 iterator end() const; 172 iterator erase(iterator); 173 174 reverse_iterator rbegin() const; 175 reverse_iterator rend() const; 176 177 List get_slice(int low, int high) const; 178 List copy() const { return get_slice(0, -1);} 179 bool sort() { return PyList_Sort(my_impl) == 0;} 180 bool reverse() { return PyList_Reverse(my_impl) == 0;} 181private: 182 PyObject *impl() { return my_impl;} // extend friendship 183}; 184 185class List::iterator 186{ 187 friend class List; 188public: 189 iterator(const iterator &i) 190 : my_list(i.my_list), my_pos(i.my_pos), my_current(i.my_current) {} 191 iterator &operator = (const iterator &); 192 193 bool operator == (iterator i); 194 bool operator != (iterator i) { return !operator==(i);} 195 196 const Object &operator *() { return my_current;} 197 const Object *operator ->() { return &(operator *());} 198 iterator operator ++(int) { incr(); return *this;} 199 iterator operator ++() { iterator tmp = *this; incr(); return tmp;} 200 iterator operator +(int i); 201 iterator operator --(int) { decr(); return *this;} 202 iterator operator --() { iterator tmp = *this; decr(); return tmp;} 203 iterator operator -(int i); 204 205private: 206 iterator(List l, int i) : my_list(l), my_pos(i) 207 { if (my_pos >= 0) my_current = my_list.get(my_pos);} 208 void incr(); 209 void decr(); 210 211 List my_list; 212 Py_ssize_t my_pos; 213 214 Object my_current; 215}; 216 217class List::reverse_iterator 218{ 219 friend class List; 220public: 221 reverse_iterator(const reverse_iterator &i) 222 : my_list(i.my_list), my_pos(i.my_pos), my_current(i.my_current) {} 223 reverse_iterator &operator = (const reverse_iterator &); 224 225 bool operator == (reverse_iterator i); 226 bool operator != (reverse_iterator i) { return !operator==(i);} 227 228 const Object &operator *() { return my_current;} 229 const Object *operator ->() { return &(operator *());} 230 reverse_iterator operator ++(int) { incr(); return *this;} 231 reverse_iterator operator ++() { reverse_iterator tmp = *this; incr(); return tmp;} 232 reverse_iterator operator +(int i); 233 reverse_iterator operator --(int) { decr(); return *this;} 234 reverse_iterator operator --() { reverse_iterator tmp = *this; decr(); return tmp;} 235 reverse_iterator operator -(int i); 236 237private: 238 reverse_iterator(List l, int i) : my_list(l), my_pos(i) 239 { if (my_pos >= 0) my_current = my_list.get(my_pos);} 240 void incr(); 241 void decr(); 242 243 List my_list; 244 Py_ssize_t my_pos; 245 246 Object my_current; 247}; 248 249class Dict : public Object 250{ 251public: 252 class iterator; 253 friend class iterator; 254 255 Dict() : Object(PyDict_New()) {} 256 Dict(Object o) throw(TypeError) : Object(o) 257 { if (!PyDict_Check(o.my_impl)) throw TypeError("object not a dict");} 258 void set(Object k, Object v); 259 Object get(Object k, Object d = Object()) const; 260 bool has_key(Object k) const; 261 bool del(Object k); 262 263 iterator begin() const; 264 iterator end() const; 265 266 void clear() { PyDict_Clear(my_impl);} 267 Dict copy() const { return Object(PyDict_Copy(my_impl));} 268 bool update(Dict d) { return PyDict_Update(my_impl, d.my_impl) == 0;} 269 270 List keys() const { return List(Object(PyDict_Keys(my_impl)));} 271 List values() const { return List(Object(PyDict_Values(my_impl)));} 272 List items() const { return List(Object(PyDict_Items(my_impl)));} 273 274private: 275 PyObject *impl() { return my_impl;} // extend friendship 276}; 277 278class Dict::iterator 279{ 280 friend class Dict; 281public: 282 iterator(const iterator &i) : my_dict(i.my_dict), my_pos(i.my_pos) {} 283 iterator &operator = (const iterator &); 284 285 bool operator == (iterator i); 286 bool operator != (iterator i) { return !operator==(i);} 287 288 const Tuple &operator *() { return my_current;} 289 const Tuple *operator ->() { return &(operator *());} 290 iterator operator ++(int) { incr(); return *this;} 291 iterator operator ++() { iterator tmp = *this; incr(); return tmp;} 292 293private: 294 iterator(Dict, int); 295 void incr(); 296 297 Dict my_dict; 298 Py_ssize_t my_pos; 299 300 Tuple my_current; 301}; 302 303inline Object::Object(PyObject *o) 304 : my_impl(o) 305{ 306 if (!my_impl) 307 { 308 check_exception(); 309 my_impl = Py_None; 310 Py_INCREF(Py_None); 311 } 312} 313 314inline Object &Object::operator = (const Object &o) 315{ 316 if (my_impl != o.my_impl) 317 { 318 Py_DECREF(my_impl); 319 my_impl = o.my_impl; 320 Py_INCREF(my_impl); 321 } 322 return *this; 323} 324 325inline int Object::cmp(Object o) const 326{ 327 int result = PyObject_Compare(my_impl, o.my_impl); 328 check_exception(); 329 return result; 330} 331 332inline bool Object::is_instance(Object o) const 333{ 334 return PyObject_IsInstance(my_impl, o.my_impl) == 1; 335} 336 337inline void Object::assert_type(const char *module_name, 338 const char *type_name) const 339 throw(TypeError) 340{ 341 Object module = Object::import(module_name); 342 if (!is_instance(module.attr(type_name))) 343 { 344 std::string msg = "object not a "; 345 msg += module_name; 346 msg += "."; 347 msg += type_name; 348 msg += " (was "; 349 Object type = attr("__class__").repr(); 350 msg += PyString_AS_STRING(type.my_impl); 351 msg += ")"; 352 throw TypeError(msg); 353 } 354} 355 356inline Object Object::import(const std::string &name) 357{ 358 PyObject *retn = PyImport_ImportModule(const_cast<char *>(name.c_str())); 359 if (!retn) throw ImportError(name); 360 else return Object(retn); 361} 362 363inline Object Object::attr(const std::string &name) const 364{ 365 PyObject *retn = PyObject_GetAttrString(my_impl, const_cast<char *>(name.c_str())); 366 if (!retn) throw AttributeError(name.c_str()); 367 else return Object(retn); 368} 369 370inline bool Object::set_attr(const std::string &name, Object value) 371{ 372 int retn = PyObject_SetAttrString(my_impl, 373 const_cast<char *>(name.c_str()), 374 value.ref()); 375 return retn != -1; 376} 377 378inline Object Object::get(Object k) const 379{ 380 PyObject *retn = PyObject_GetItem(my_impl, k.my_impl); 381 if (!retn) check_exception(); 382 Py_INCREF(retn); 383 return Object(retn); 384} 385 386 387template <typename T> 388inline T Object::narrow(Object o) throw(Object::TypeError) 389{ 390 T retn(o.my_impl); 391 Py_INCREF(o.my_impl); 392 return retn; 393} 394 395template <typename T> 396inline T Object::try_narrow(Object o) 397{ 398 try 399 { 400 T retn(o.my_impl); 401 Py_INCREF(o.my_impl); 402 return retn; 403 } 404 catch (const TypeError &) { return T();} 405} 406 407template <> 408inline char Object::narrow(Object o) throw(Object::TypeError) 409{ 410 if (!PyString_Check(o.my_impl) || PyString_GET_SIZE(o.my_impl) != 1) 411 throw TypeError("object not a character"); 412 char *value; 413 Py_ssize_t length; 414 PyString_AsStringAndSize(o.my_impl, &value, &length); 415 return value[0]; 416} 417 418template <> 419inline const char *Object::narrow(Object o) throw(Object::TypeError) 420{ 421 if (!PyString_Check(o.my_impl)) throw TypeError("object not a string"); 422 return PyString_AS_STRING(o.my_impl); 423} 424 425template <> 426inline std::string Object::narrow(Object o) throw(Object::TypeError) 427{ 428 if (!PyString_Check(o.my_impl)) throw TypeError("object not a string"); 429 return PyString_AS_STRING(o.my_impl); 430} 431 432template <> 433inline double Object::narrow(Object o) throw(Object::TypeError) 434{ 435 if (!PyFloat_Check(o.my_impl)) throw TypeError("object not a float"); 436 return PyFloat_AsDouble(o.my_impl); 437} 438 439template <> 440inline long Object::narrow(Object o) throw(Object::TypeError) 441{ 442 if (!PyInt_Check(o.my_impl)) throw TypeError("object not an integer"); 443 return PyInt_AsLong(o.my_impl); 444} 445 446template <> 447inline bool Object::narrow(Object o) throw(Object::TypeError) 448{ 449#if 0 //PYTHON_HAS_BOOL 450 if (!PyBool_Check(o.my_impl)) throw TypeError("object not a boolean"); 451#else 452 if (!PyInt_Check(o.my_impl)) throw TypeError("object not an integer"); 453#endif 454 return PyInt_AsLong(o.my_impl); 455} 456 457inline void Object::check_exception() const 458{ 459 PyObject *exc = PyErr_Occurred(); 460 if (!exc) return; 461 PyObject *type, *value, *trace; 462 // PyErr_Print(); 463 PyErr_Fetch(&type, &value, &trace); 464 Object t(type), v(value), tr(trace); // to release the reference at end of scope 465 std::cerr << trace << ' ' << Object::narrow<std::string>(tr.str()) << std::endl; 466 if (exc == PyExc_KeyError) 467 throw KeyError(Object::narrow<std::string>(v.str())); 468 else if (exc == PyExc_TypeError) 469 throw TypeError(Object::narrow<std::string>(v.str())); 470 else if (exc == PyExc_AttributeError) 471 throw AttributeError(); 472 throw std::runtime_error(PyString_AsString(value)); 473} 474 475inline std::ostream &operator << (std::ostream &os, const Object &o) 476{ 477 return os << Object::narrow<std::string>(o.str()); 478} 479 480inline Object Object::operator () () 481{ 482 return PyObject_CallObject(my_impl, 0); 483} 484 485inline Object Object::operator () (Tuple args) 486{ 487 return PyObject_Call(my_impl, args.my_impl, 0); 488} 489 490inline Object Object::operator () (Tuple args, Dict kwds) 491{ 492 return PyObject_Call(my_impl, args.my_impl, kwds.my_impl); 493} 494 495inline Tuple::Tuple(PyObject *o) 496 : Object(o) 497{ 498 if (!PyTuple_Check(o)) throw TypeError("object not a tuple"); 499} 500 501inline Tuple::Tuple(Object o) 502 : Object(PyTuple_New(1)) 503{ 504 PyTuple_SET_ITEM(my_impl, 0, o.my_impl); 505 Py_INCREF(o.my_impl); 506} 507 508inline Tuple::Tuple(Object o1, Object o2) 509 : Object(PyTuple_New(2)) 510{ 511 PyTuple_SET_ITEM(my_impl, 0, o1.my_impl); 512 Py_INCREF(o1.my_impl); 513 PyTuple_SET_ITEM(my_impl, 1, o2.my_impl); 514 Py_INCREF(o2.my_impl); 515} 516 517inline Tuple::Tuple(Object o1, Object o2, Object o3) 518 : Object(PyTuple_New(3)) 519{ 520 PyTuple_SET_ITEM(my_impl, 0, o1.my_impl); 521 Py_INCREF(o1.my_impl); 522 PyTuple_SET_ITEM(my_impl, 1, o2.my_impl); 523 Py_INCREF(o2.my_impl); 524 PyTuple_SET_ITEM(my_impl, 2, o3.my_impl); 525 Py_INCREF(o3.my_impl); 526} 527 528inline Tuple::Tuple(Object o1, Object o2, Object o3, 529 Object o4) 530 : Object(PyTuple_New(4)) 531{ 532 PyTuple_SET_ITEM(my_impl, 0, o1.my_impl); 533 Py_INCREF(o1.my_impl); 534 PyTuple_SET_ITEM(my_impl, 1, o2.my_impl); 535 Py_INCREF(o2.my_impl); 536 PyTuple_SET_ITEM(my_impl, 2, o3.my_impl); 537 Py_INCREF(o3.my_impl); 538 PyTuple_SET_ITEM(my_impl, 3, o4.my_impl); 539 Py_INCREF(o4.my_impl); 540} 541 542inline Tuple::Tuple(Object o1, Object o2, Object o3, 543 Object o4, Object o5) 544 : Object(PyTuple_New(5)) 545{ 546 PyTuple_SET_ITEM(my_impl, 0, o1.my_impl); 547 Py_INCREF(o1.my_impl); 548 PyTuple_SET_ITEM(my_impl, 1, o2.my_impl); 549 Py_INCREF(o2.my_impl); 550 PyTuple_SET_ITEM(my_impl, 2, o3.my_impl); 551 Py_INCREF(o3.my_impl); 552 PyTuple_SET_ITEM(my_impl, 3, o4.my_impl); 553 Py_INCREF(o4.my_impl); 554 PyTuple_SET_ITEM(my_impl, 4, o5.my_impl); 555 Py_INCREF(o5.my_impl); 556} 557 558inline Tuple::Tuple(Object o1, Object o2, Object o3, 559 Object o4, Object o5, Object o6) 560 : Object(PyTuple_New(6)) 561{ 562 PyTuple_SET_ITEM(my_impl, 0, o1.my_impl); 563 Py_INCREF(o1.my_impl); 564 PyTuple_SET_ITEM(my_impl, 1, o2.my_impl); 565 Py_INCREF(o2.my_impl); 566 PyTuple_SET_ITEM(my_impl, 2, o3.my_impl); 567 Py_INCREF(o3.my_impl); 568 PyTuple_SET_ITEM(my_impl, 3, o4.my_impl); 569 Py_INCREF(o4.my_impl); 570 PyTuple_SET_ITEM(my_impl, 4, o5.my_impl); 571 Py_INCREF(o5.my_impl); 572 PyTuple_SET_ITEM(my_impl, 5, o6.my_impl); 573 Py_INCREF(o6.my_impl); 574} 575 576inline Tuple::Tuple(Object o1, Object o2, Object o3, 577 Object o4, Object o5, Object o6, 578 Object o7) 579 : Object(PyTuple_New(7)) 580{ 581 PyTuple_SET_ITEM(my_impl, 0, o1.my_impl); 582 Py_INCREF(o1.my_impl); 583 PyTuple_SET_ITEM(my_impl, 1, o2.my_impl); 584 Py_INCREF(o2.my_impl); 585 PyTuple_SET_ITEM(my_impl, 2, o3.my_impl); 586 Py_INCREF(o3.my_impl); 587 PyTuple_SET_ITEM(my_impl, 3, o4.my_impl); 588 Py_INCREF(o4.my_impl); 589 PyTuple_SET_ITEM(my_impl, 4, o5.my_impl); 590 Py_INCREF(o5.my_impl); 591 PyTuple_SET_ITEM(my_impl, 5, o6.my_impl); 592 Py_INCREF(o6.my_impl); 593 PyTuple_SET_ITEM(my_impl, 6, o7.my_impl); 594 Py_INCREF(o7.my_impl); 595} 596 597inline Tuple::Tuple(Object o1, Object o2, Object o3, 598 Object o4, Object o5, Object o6, 599 Object o7, Object o8) 600 : Object(PyTuple_New(8)) 601{ 602 PyTuple_SET_ITEM(my_impl, 0, o1.my_impl); 603 Py_INCREF(o1.my_impl); 604 PyTuple_SET_ITEM(my_impl, 1, o2.my_impl); 605 Py_INCREF(o2.my_impl); 606 PyTuple_SET_ITEM(my_impl, 2, o3.my_impl); 607 Py_INCREF(o3.my_impl); 608 PyTuple_SET_ITEM(my_impl, 3, o4.my_impl); 609 Py_INCREF(o4.my_impl); 610 PyTuple_SET_ITEM(my_impl, 4, o5.my_impl); 611 Py_INCREF(o5.my_impl); 612 PyTuple_SET_ITEM(my_impl, 5, o6.my_impl); 613 Py_INCREF(o6.my_impl); 614 PyTuple_SET_ITEM(my_impl, 6, o7.my_impl); 615 Py_INCREF(o7.my_impl); 616 PyTuple_SET_ITEM(my_impl, 7, o8.my_impl); 617 Py_INCREF(o8.my_impl); 618} 619 620inline Tuple::Tuple(Object o1, Object o2, Object o3, 621 Object o4, Object o5, Object o6, 622 Object o7, Object o8, Object o9) 623 : Object(PyTuple_New(9)) 624{ 625 PyTuple_SET_ITEM(my_impl, 0, o1.my_impl); 626 Py_INCREF(o1.my_impl); 627 PyTuple_SET_ITEM(my_impl, 1, o2.my_impl); 628 Py_INCREF(o2.my_impl); 629 PyTuple_SET_ITEM(my_impl, 2, o3.my_impl); 630 Py_INCREF(o3.my_impl); 631 PyTuple_SET_ITEM(my_impl, 3, o4.my_impl); 632 Py_INCREF(o4.my_impl); 633 PyTuple_SET_ITEM(my_impl, 4, o5.my_impl); 634 Py_INCREF(o5.my_impl); 635 PyTuple_SET_ITEM(my_impl, 5, o6.my_impl); 636 Py_INCREF(o6.my_impl); 637 PyTuple_SET_ITEM(my_impl, 6, o7.my_impl); 638 Py_INCREF(o7.my_impl); 639 PyTuple_SET_ITEM(my_impl, 7, o8.my_impl); 640 Py_INCREF(o8.my_impl); 641 PyTuple_SET_ITEM(my_impl, 8, o9.my_impl); 642 Py_INCREF(o9.my_impl); 643} 644 645inline Object Tuple::get(size_t i) const 646{ 647 PyObject *retn = PyTuple_GetItem(my_impl, i); 648 if (!retn) check_exception(); 649 Py_INCREF(retn); 650 return Object(retn); 651} 652 653 654inline List::List(Object o) throw(TypeError) 655 : Object(o) 656{ 657 if (PyTuple_Check(o.my_impl)) // copy elements into new list 658 { 659 Py_DECREF(my_impl); 660 my_impl = PyList_New(PyTuple_Size(o.my_impl)); 661 for (int i = 0; i != PyList_Size(my_impl); ++i) 662 { 663 PyObject *item = PyTuple_GetItem(o.my_impl, i); 664 Py_INCREF(item); 665 PyList_SetItem(my_impl, i, item); 666 } 667 } 668 else if (!PyList_Check(o.my_impl)) throw TypeError("object not a list"); 669} 670 671template <typename I> 672List::List(I begin, I end) 673 : Object(PyList_New(0)) 674{ 675 for (I i = begin; i != end; ++i) append(*i); 676} 677 678inline void List::set(int i, Object o) 679{ 680 Py_INCREF(o.my_impl); 681 PyList_SetItem(my_impl, i, o.my_impl); 682} 683 684inline Object List::get(int i) const 685{ 686 PyObject *retn = PyList_GetItem(my_impl, i); 687 if (!retn) check_exception(); 688 Py_INCREF(retn); 689 return Object(retn); 690} 691 692inline void List::extend(List l) 693{ 694 for (List::iterator i = l.begin(); i != l.end(); ++i) 695 append(*i); 696} 697 698inline List::iterator List::begin() const 699{ 700 return iterator(*this, size() ? 0 : -1); 701} 702 703inline List::iterator List::end() const 704{ 705 return iterator(*this, -1); 706} 707 708inline List::iterator List::erase(List::iterator i) 709{ 710 if (i.my_pos >= 0) del(i.my_pos); 711 if (i.my_pos >= size()) // if the erased element was the last... 712 --i.my_pos; // ... decrement the iterator by one 713 return i; 714} 715 716inline List::reverse_iterator List::rbegin() const 717{ 718 return reverse_iterator(*this, size() - 1); 719} 720 721inline List::reverse_iterator List::rend() const 722{ 723 return reverse_iterator(*this, -1); 724} 725 726inline List List::get_slice(int low, int high) const 727{ 728 return List(PyList_GetSlice(my_impl, low, high)); 729} 730 731inline List::iterator &List::iterator::operator = (const List::iterator &i) 732{ 733 my_list = i.my_list; 734 my_pos = i.my_pos; 735 my_current = i.my_current; 736 return *this; 737} 738 739inline bool List::iterator::operator == (List::iterator i) 740{ 741 return i.my_list.impl() == my_list.impl() && i.my_pos == my_pos; 742} 743 744inline List::iterator List::iterator::operator + (int i) 745{ 746 if (my_pos != -1) my_pos += i; 747 748 if (my_pos < my_list.size()) 749 my_current = my_list.get(my_pos); 750 else 751 my_pos = -1; 752 return *this; 753} 754 755inline List::iterator List::iterator::operator - (int i) 756{ 757 my_pos = my_pos == -1 ? my_list.size() - i : my_pos - i; 758 759 if (my_pos > -1) 760 my_current = my_list.get(my_pos); 761 else 762 my_pos = -1; 763 return *this; 764} 765 766inline void List::iterator::incr() 767{ 768 operator + (1); 769} 770 771inline void List::iterator::decr() 772{ 773 operator - (1); 774} 775 776inline bool List::reverse_iterator::operator == (List::reverse_iterator i) 777{ 778 return i.my_list.impl() == my_list.impl() && i.my_pos == my_pos; 779} 780 781inline List::reverse_iterator List::reverse_iterator::operator + (int i) 782{ 783 my_pos = my_pos == -1 ? my_list.size() - i : my_pos - i; 784 785 if (my_pos > -1) 786 my_current = my_list.get(my_pos); 787 else 788 my_pos = -1; 789 return *this; 790} 791 792inline List::reverse_iterator List::reverse_iterator::operator - (int i) 793{ 794 my_pos += i; 795 796 if (my_pos < my_list.size()) 797 my_current = my_list.get(my_pos); 798 else 799 my_pos = -1; 800 return *this; 801} 802 803inline void List::reverse_iterator::incr() 804{ 805 operator + (1); 806} 807 808inline void List::reverse_iterator::decr() 809{ 810 operator - (1); 811} 812 813inline void Dict::set(Object k, Object v) 814{ 815 PyObject_SetItem(my_impl, k.my_impl, v.my_impl); 816} 817 818inline Object Dict::get(Object k, Object d) const 819{ 820 PyObject *retn = PyDict_GetItem(my_impl, k.my_impl); 821 if (retn) Py_INCREF(retn); 822 return retn ? Object(retn) : d; 823} 824 825inline bool Dict::has_key(Object k) const 826{ 827 return PyObject_GetItem(my_impl, k.my_impl) != 0; 828} 829 830inline bool Dict::del(Object k) 831{ 832 return PyObject_DelItem(my_impl, k.my_impl) == 0; 833} 834 835inline Dict::iterator Dict::begin() const 836{ 837 return iterator(*this, 0); 838} 839 840inline Dict::iterator Dict::end() const 841{ 842 return iterator(*this, -1); 843} 844 845inline Dict::iterator::iterator(Dict dict, int pos) 846 : my_dict(dict), my_pos(pos) 847{ 848 if (pos != -1) incr(); 849} 850 851inline Dict::iterator &Dict::iterator::operator = (const Dict::iterator &i) 852{ 853 my_dict = i.my_dict; 854 my_pos = i.my_pos; 855 my_current = i.my_current; 856 return *this; 857} 858 859inline void Dict::iterator::incr() 860{ 861 PyObject *key = 0, *value = 0; 862 bool valid = PyDict_Next(my_dict.impl(), &my_pos, &key, &value); 863 if (!valid) my_pos = -1; 864 else 865 { 866 Py_INCREF(key); 867 Py_INCREF(value); 868 my_current = Tuple(key, value); 869 } 870} 871 872inline bool Dict::iterator::operator == (Dict::iterator i) 873{ 874 return i.my_dict.impl() == my_dict.impl() && i.my_pos == my_pos; 875} 876 877} 878} 879 880#endif