PageRenderTime 54ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Lib/d/std_vector.i

#
Swig | 591 lines | 486 code | 88 blank | 17 comment | 0 complexity | db4d32ef8f493efdef696cbc5f266391 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1. /* -----------------------------------------------------------------------------
  2. * std_vector.i
  3. *
  4. * SWIG typemaps for std::vector<T>, D implementation.
  5. *
  6. * The D wrapper is made to loosely resemble a tango.util.container.more.Vector
  7. * and to provide built-in array-like access.
  8. *
  9. * If T does define an operator==, then use the SWIG_STD_VECTOR_ENHANCED
  10. * macro to obtain enhanced functionality (none yet), for example:
  11. *
  12. * SWIG_STD_VECTOR_ENHANCED(SomeNamespace::Klass)
  13. * %template(VectKlass) std::vector<SomeNamespace::Klass>;
  14. *
  15. * Warning: heavy macro usage in this file. Use swig -E to get a sane view on
  16. * the real file contents!
  17. * ----------------------------------------------------------------------------- */
  18. // Warning: Use the typemaps here in the expectation that the macros they are in will change name.
  19. %include <std_common.i>
  20. // MACRO for use within the std::vector class body
  21. %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CONST_REFERENCE, CTYPE...)
  22. #if (SWIG_D_VERSION == 1)
  23. %typemap(dimports) std::vector< CTYPE > "static import tango.core.Exception;"
  24. %typemap(dcode) std::vector< CTYPE > %{
  25. public this($typemap(dtype, CTYPE)[] values) {
  26. this();
  27. append(values);
  28. }
  29. alias push_back add;
  30. alias push_back push;
  31. alias push_back opCatAssign;
  32. alias size length;
  33. alias opSlice slice;
  34. public $typemap(dtype, CTYPE) opIndexAssign($typemap(dtype, CTYPE) value, size_t index) {
  35. if (index >= size()) {
  36. throw new tango.core.Exception.NoSuchElementException("Tried to assign to element out of vector bounds.");
  37. }
  38. setElement(index, value);
  39. return value;
  40. }
  41. public $typemap(dtype, CTYPE) opIndex(size_t index) {
  42. if (index >= size()) {
  43. throw new tango.core.Exception.NoSuchElementException("Tried to read from element out of vector bounds.");
  44. }
  45. return getElement(index);
  46. }
  47. public void append($typemap(dtype, CTYPE)[] value...) {
  48. foreach (v; value) {
  49. add(v);
  50. }
  51. }
  52. public $typemap(dtype, CTYPE)[] opSlice() {
  53. $typemap(dtype, CTYPE)[] array = new $typemap(dtype, CTYPE)[size()];
  54. foreach (i, ref value; array) {
  55. value = getElement(i);
  56. }
  57. return array;
  58. }
  59. public int opApply(int delegate(ref $typemap(dtype, CTYPE) value) dg) {
  60. int result;
  61. size_t currentSize = size();
  62. for (size_t i = 0; i < currentSize; ++i) {
  63. auto value = getElement(i);
  64. result = dg(value);
  65. setElement(i, value);
  66. }
  67. return result;
  68. }
  69. public int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) {
  70. int result;
  71. size_t currentSize = size();
  72. for (size_t i = 0; i < currentSize; ++i) {
  73. auto value = getElement(i);
  74. // Workaround for http://d.puremagic.com/issues/show_bug.cgi?id=2443.
  75. auto index = i;
  76. result = dg(index, value);
  77. setElement(i, value);
  78. }
  79. return result;
  80. }
  81. public void capacity(size_t value) {
  82. if (value < size()) {
  83. throw new tango.core.Exception.IllegalArgumentException("Tried to make the capacity of a vector smaller than its size.");
  84. }
  85. reserve(value);
  86. }
  87. %}
  88. public:
  89. typedef size_t size_type;
  90. typedef CTYPE value_type;
  91. typedef CONST_REFERENCE const_reference;
  92. void clear();
  93. void push_back(CTYPE const& x);
  94. size_type size() const;
  95. size_type capacity() const;
  96. void reserve(size_type n) throw (std::length_error);
  97. vector();
  98. vector(const vector &other);
  99. %extend {
  100. vector(size_type capacity) throw (std::length_error) {
  101. std::vector< CTYPE >* pv = 0;
  102. pv = new std::vector< CTYPE >();
  103. // Might throw std::length_error.
  104. pv->reserve(capacity);
  105. return pv;
  106. }
  107. size_type unused() const {
  108. return $self->capacity() - $self->size();
  109. }
  110. const_reference remove() throw (std::out_of_range) {
  111. if ($self->empty()) {
  112. throw std::out_of_range("Tried to remove last element from empty vector.");
  113. }
  114. std::vector< CTYPE >::const_reference value = $self->back();
  115. $self->pop_back();
  116. return value;
  117. }
  118. const_reference remove(size_type index) throw (std::out_of_range) {
  119. if (index >= $self->size()) {
  120. throw std::out_of_range("Tried to remove element with invalid index.");
  121. }
  122. std::vector< CTYPE >::iterator it = $self->begin() + index;
  123. std::vector< CTYPE >::const_reference value = *it;
  124. $self->erase(it);
  125. return value;
  126. }
  127. }
  128. // Wrappers for setting/getting items with the possibly thrown exception
  129. // specified (important for SWIG wrapper generation).
  130. %extend {
  131. const_reference getElement(size_type index) throw (std::out_of_range) {
  132. if ((index < 0) || ($self->size() <= index)) {
  133. throw std::out_of_range("Tried to get value of element with invalid index.");
  134. }
  135. return (*$self)[index];
  136. }
  137. }
  138. // Use CTYPE const& instead of const_reference to work around SWIG code
  139. // generation issue when using const pointers as vector elements (like
  140. // std::vector< const int* >).
  141. %extend {
  142. void setElement(size_type index, CTYPE const& val) throw (std::out_of_range) {
  143. if ((index < 0) || ($self->size() <= index)) {
  144. throw std::out_of_range("Tried to set value of element with invalid index.");
  145. }
  146. (*$self)[index] = val;
  147. }
  148. }
  149. %dmethodmodifiers std::vector::getElement "private"
  150. %dmethodmodifiers std::vector::setElement "private"
  151. %dmethodmodifiers std::vector::reserve "private"
  152. #else
  153. %typemap(dimports) std::vector< CTYPE > %{
  154. static import std.algorithm;
  155. static import std.exception;
  156. static import std.range;
  157. static import std.traits;
  158. %}
  159. %typemap(dcode) std::vector< CTYPE > %{
  160. alias size_t KeyType;
  161. alias $typemap(dtype, CTYPE) ValueType;
  162. this(ValueType[] values...) {
  163. this();
  164. reserve(values.length);
  165. foreach (e; values) {
  166. this ~= e;
  167. }
  168. }
  169. struct Range {
  170. private $typemap(dtype, std::vector< CTYPE >) _outer;
  171. private size_t _a, _b;
  172. this($typemap(dtype, std::vector< CTYPE >) data, size_t a, size_t b) {
  173. _outer = data;
  174. _a = a;
  175. _b = b;
  176. }
  177. @property bool empty() const {
  178. assert((cast($typemap(dtype, std::vector< CTYPE >))_outer).length >= _b);
  179. return _a >= _b;
  180. }
  181. @property Range save() {
  182. return this;
  183. }
  184. @property ValueType front() {
  185. std.exception.enforce(!empty);
  186. return _outer[_a];
  187. }
  188. @property void front(ValueType value) {
  189. std.exception.enforce(!empty);
  190. _outer[_a] = std.algorithm.move(value);
  191. }
  192. void popFront() {
  193. std.exception.enforce(!empty);
  194. ++_a;
  195. }
  196. void opIndexAssign(ValueType value, size_t i) {
  197. i += _a;
  198. std.exception.enforce(i < _b && _b <= _outer.length);
  199. _outer[i] = value;
  200. }
  201. void opIndexOpAssign(string op)(ValueType value, size_t i) {
  202. std.exception.enforce(_outer && _a + i < _b && _b <= _outer.length);
  203. auto element = _outer[i];
  204. mixin("element "~op~"= value;");
  205. _outer[i] = element;
  206. }
  207. }
  208. // TODO: dup?
  209. Range opSlice() {
  210. return Range(this, 0, length);
  211. }
  212. Range opSlice(size_t a, size_t b) {
  213. std.exception.enforce(a <= b && b <= length);
  214. return Range(this, a, b);
  215. }
  216. size_t opDollar() const {
  217. return length;
  218. }
  219. @property ValueType front() {
  220. std.exception.enforce(!empty);
  221. return getElement(0);
  222. }
  223. @property void front(ValueType value) {
  224. std.exception.enforce(!empty);
  225. setElement(0, value);
  226. }
  227. @property ValueType back() {
  228. std.exception.enforce(!empty);
  229. return getElement(length - 1);
  230. }
  231. @property void back(ValueType value) {
  232. std.exception.enforce(!empty);
  233. setElement(length - 1, value);
  234. }
  235. ValueType opIndex(size_t i) {
  236. return getElement(i);
  237. }
  238. void opIndexAssign(ValueType value, size_t i) {
  239. setElement(i, value);
  240. }
  241. void opIndexOpAssign(string op)(ValueType value, size_t i) {
  242. auto element = this[i];
  243. mixin("element "~op~"= value;");
  244. this[i] = element;
  245. }
  246. ValueType[] opBinary(string op, Stuff)(Stuff stuff) if (op == "~") {
  247. ValueType[] result;
  248. result ~= this[];
  249. assert(result.length == length);
  250. result ~= stuff[];
  251. return result;
  252. }
  253. void opOpAssign(string op, Stuff)(Stuff stuff) if (op == "~") {
  254. static if (is(typeof(insertBack(stuff)))) {
  255. insertBack(stuff);
  256. } else if (is(typeof(insertBack(stuff[])))) {
  257. insertBack(stuff[]);
  258. } else {
  259. static assert(false, "Cannot append " ~ Stuff.stringof ~ " to " ~ typeof(this).stringof);
  260. }
  261. }
  262. alias size length;
  263. alias remove removeAny;
  264. alias removeAny stableRemoveAny;
  265. size_t insertBack(Stuff)(Stuff stuff)
  266. if (std.traits.isImplicitlyConvertible!(Stuff, ValueType)){
  267. push_back(stuff);
  268. return 1;
  269. }
  270. size_t insertBack(Stuff)(Stuff stuff)
  271. if (std.range.isInputRange!Stuff &&
  272. std.traits.isImplicitlyConvertible!(std.range.ElementType!Stuff, ValueType)) {
  273. size_t itemCount;
  274. foreach(item; stuff) {
  275. insertBack(item);
  276. ++itemCount;
  277. }
  278. return itemCount;
  279. }
  280. alias insertBack insert;
  281. alias pop_back removeBack;
  282. alias pop_back stableRemoveBack;
  283. size_t insertBefore(Stuff)(Range r, Stuff stuff)
  284. if (std.traits.isImplicitlyConvertible!(Stuff, ValueType)) {
  285. std.exception.enforce(r._outer.swigCPtr == swigCPtr && r._a < length);
  286. insertAt(r._a, stuff);
  287. return 1;
  288. }
  289. size_t insertBefore(Stuff)(Range r, Stuff stuff)
  290. if (std.range.isInputRange!Stuff && std.traits.isImplicitlyConvertible!(ElementType!Stuff, ValueType)) {
  291. std.exception.enforce(r._outer.swigCPtr == swigCPtr && r._a <= length);
  292. size_t insertCount;
  293. foreach(i, item; stuff) {
  294. insertAt(r._a + i, item);
  295. ++insertCount;
  296. }
  297. return insertCount;
  298. }
  299. size_t insertAfter(Stuff)(Range r, Stuff stuff) {
  300. // TODO: optimize
  301. immutable offset = r._a + r.length;
  302. std.exception.enforce(offset <= length);
  303. auto result = insertBack(stuff);
  304. std.algorithm.bringToFront(this[offset .. length - result],
  305. this[length - result .. length]);
  306. return result;
  307. }
  308. size_t replace(Stuff)(Range r, Stuff stuff)
  309. if (std.range.isInputRange!Stuff &&
  310. std.traits.isImplicitlyConvertible!(ElementType!Stuff, ValueType)) {
  311. immutable offset = r._a;
  312. std.exception.enforce(offset <= length);
  313. size_t result;
  314. for (; !stuff.empty; stuff.popFront()) {
  315. if (r.empty) {
  316. // append the rest
  317. return result + insertBack(stuff);
  318. }
  319. r.front = stuff.front;
  320. r.popFront();
  321. ++result;
  322. }
  323. // Remove remaining stuff in r
  324. remove(r);
  325. return result;
  326. }
  327. size_t replace(Stuff)(Range r, Stuff stuff)
  328. if (std.traits.isImplicitlyConvertible!(Stuff, ValueType))
  329. {
  330. if (r.empty)
  331. {
  332. insertBefore(r, stuff);
  333. }
  334. else
  335. {
  336. r.front = stuff;
  337. r.popFront();
  338. remove(r);
  339. }
  340. return 1;
  341. }
  342. Range linearRemove(Range r) {
  343. std.exception.enforce(r._a <= r._b && r._b <= length);
  344. immutable tailLength = length - r._b;
  345. linearRemove(r._a, r._b);
  346. return this[length - tailLength .. length];
  347. }
  348. alias remove stableLinearRemove;
  349. int opApply(int delegate(ref $typemap(dtype, CTYPE) value) dg) {
  350. int result;
  351. size_t currentSize = size();
  352. for (size_t i = 0; i < currentSize; ++i) {
  353. auto value = getElement(i);
  354. result = dg(value);
  355. setElement(i, value);
  356. }
  357. return result;
  358. }
  359. int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) {
  360. int result;
  361. size_t currentSize = size();
  362. for (size_t i = 0; i < currentSize; ++i) {
  363. auto value = getElement(i);
  364. // Workaround for http://d.puremagic.com/issues/show_bug.cgi?id=2443.
  365. auto index = i;
  366. result = dg(index, value);
  367. setElement(i, value);
  368. }
  369. return result;
  370. }
  371. %}
  372. public:
  373. typedef size_t size_type;
  374. typedef CTYPE value_type;
  375. typedef CONST_REFERENCE const_reference;
  376. bool empty() const;
  377. void clear();
  378. void push_back(CTYPE const& x);
  379. void pop_back();
  380. size_type size() const;
  381. size_type capacity() const;
  382. void reserve(size_type n) throw (std::length_error);
  383. vector();
  384. vector(const vector &other);
  385. %extend {
  386. vector(size_type capacity) throw (std::length_error) {
  387. std::vector< CTYPE >* pv = 0;
  388. pv = new std::vector< CTYPE >();
  389. // Might throw std::length_error.
  390. pv->reserve(capacity);
  391. return pv;
  392. }
  393. const_reference remove() throw (std::out_of_range) {
  394. if ($self->empty()) {
  395. throw std::out_of_range("Tried to remove last element from empty vector.");
  396. }
  397. std::vector< CTYPE >::const_reference value = $self->back();
  398. $self->pop_back();
  399. return value;
  400. }
  401. const_reference remove(size_type index) throw (std::out_of_range) {
  402. if (index >= $self->size()) {
  403. throw std::out_of_range("Tried to remove element with invalid index.");
  404. }
  405. std::vector< CTYPE >::iterator it = $self->begin() + index;
  406. std::vector< CTYPE >::const_reference value = *it;
  407. $self->erase(it);
  408. return value;
  409. }
  410. void removeBack(size_type how_many) throw (std::out_of_range) {
  411. std::vector< CTYPE >::iterator end = $self->end();
  412. std::vector< CTYPE >::iterator start = end - how_many;
  413. $self->erase(start, end);
  414. }
  415. void linearRemove(size_type start_index, size_type end_index) throw (std::out_of_range) {
  416. std::vector< CTYPE >::iterator start = $self->begin() + start_index;
  417. std::vector< CTYPE >::iterator end = $self->begin() + end_index;
  418. $self->erase(start, end);
  419. }
  420. void insertAt(size_type index, CTYPE const& x) throw (std::out_of_range) {
  421. std::vector< CTYPE >::iterator it = $self->begin() + index;
  422. $self->insert(it, x);
  423. }
  424. }
  425. // Wrappers for setting/getting items with the possibly thrown exception
  426. // specified (important for SWIG wrapper generation).
  427. %extend {
  428. const_reference getElement(size_type index) throw (std::out_of_range) {
  429. if ((index < 0) || ($self->size() <= index)) {
  430. throw std::out_of_range("Tried to get value of element with invalid index.");
  431. }
  432. return (*$self)[index];
  433. }
  434. }
  435. // Use CTYPE const& instead of const_reference to work around SWIG code
  436. // generation issue when using const pointers as vector elements (like
  437. // std::vector< const int* >).
  438. %extend {
  439. void setElement(size_type index, CTYPE const& val) throw (std::out_of_range) {
  440. if ((index < 0) || ($self->size() <= index)) {
  441. throw std::out_of_range("Tried to set value of element with invalid index.");
  442. }
  443. (*$self)[index] = val;
  444. }
  445. }
  446. %dmethodmodifiers std::vector::getElement "private"
  447. %dmethodmodifiers std::vector::setElement "private"
  448. #endif
  449. %enddef
  450. // Extra methods added to the collection class if operator== is defined for the class being wrapped
  451. // The class will then implement IList<>, which adds extra functionality
  452. %define SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CTYPE...)
  453. %extend {
  454. }
  455. %enddef
  456. // For vararg handling in macros, from swigmacros.swg
  457. #define %arg(X...) X
  458. // Macros for std::vector class specializations/enhancements
  459. %define SWIG_STD_VECTOR_ENHANCED(CTYPE...)
  460. namespace std {
  461. template<> class vector<CTYPE > {
  462. SWIG_STD_VECTOR_MINIMUM_INTERNAL(%arg(CTYPE const&), %arg(CTYPE))
  463. SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CTYPE)
  464. };
  465. }
  466. %enddef
  467. %{
  468. #include <vector>
  469. #include <stdexcept>
  470. %}
  471. namespace std {
  472. // primary (unspecialized) class template for std::vector
  473. // does not require operator== to be defined
  474. template<class T> class vector {
  475. SWIG_STD_VECTOR_MINIMUM_INTERNAL(T const&, T)
  476. };
  477. // specializations for pointers
  478. template<class T> class vector<T *> {
  479. SWIG_STD_VECTOR_MINIMUM_INTERNAL(T *const&, T *)
  480. SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(T *)
  481. };
  482. // bool is a bit different in the C++ standard - const_reference in particular
  483. template<> class vector<bool> {
  484. SWIG_STD_VECTOR_MINIMUM_INTERNAL(bool, bool)
  485. SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(bool)
  486. };
  487. }
  488. // template specializations for std::vector
  489. // these provide extra collections methods as operator== is defined
  490. SWIG_STD_VECTOR_ENHANCED(char)
  491. SWIG_STD_VECTOR_ENHANCED(signed char)
  492. SWIG_STD_VECTOR_ENHANCED(unsigned char)
  493. SWIG_STD_VECTOR_ENHANCED(short)
  494. SWIG_STD_VECTOR_ENHANCED(unsigned short)
  495. SWIG_STD_VECTOR_ENHANCED(int)
  496. SWIG_STD_VECTOR_ENHANCED(unsigned int)
  497. SWIG_STD_VECTOR_ENHANCED(long)
  498. SWIG_STD_VECTOR_ENHANCED(unsigned long)
  499. SWIG_STD_VECTOR_ENHANCED(long long)
  500. SWIG_STD_VECTOR_ENHANCED(unsigned long long)
  501. SWIG_STD_VECTOR_ENHANCED(float)
  502. SWIG_STD_VECTOR_ENHANCED(double)
  503. SWIG_STD_VECTOR_ENHANCED(std::string) // also requires a %include <std_string.i>