/tags/rel-1-3-28/SWIG/Lib/perl5/std_vector.i

# · Swig · 409 lines · 379 code · 14 blank · 16 comment · 0 complexity · 357c87f39dea77f290388da31d56f51f MD5 · raw file

  1. //
  2. // SWIG typemaps for std::vector types
  3. // Luigi Ballabio
  4. // May 7, 2002
  5. // Chris Seatory
  6. // August 5, 2002
  7. // Igor Bely
  8. // May 16, 2003
  9. //
  10. // Perl implementation
  11. %include <std_common.i>
  12. // ------------------------------------------------------------------------
  13. // std::vector
  14. //
  15. // The aim of all that follows would be to integrate std::vector with
  16. // Perl as much as possible, namely, to allow the user to pass and
  17. // be returned Perl arrays.
  18. // const declarations are used to guess the intent of the function being
  19. // exported; therefore, the following rationale is applied:
  20. //
  21. // -- f(std::vector<T>), f(const std::vector<T>&), f(const std::vector<T>*):
  22. // the parameter being read-only, either a Perl sequence or a
  23. // previously wrapped std::vector<T> can be passed.
  24. // -- f(std::vector<T>&), f(std::vector<T>*):
  25. // the parameter must be modified; therefore, only a wrapped std::vector
  26. // can be passed.
  27. // -- std::vector<T> f():
  28. // the vector is returned by copy; therefore, a Perl sequence of T:s
  29. // is returned which is most easily used in other Perl functions
  30. // -- std::vector<T>& f(), std::vector<T>* f(), const std::vector<T>& f(),
  31. // const std::vector<T>* f():
  32. // the vector is returned by reference; therefore, a wrapped std::vector
  33. // is returned
  34. // ------------------------------------------------------------------------
  35. %{
  36. #include <vector>
  37. #include <algorithm>
  38. #include <stdexcept>
  39. %}
  40. // exported class
  41. namespace std {
  42. template<class T> class vector {
  43. %typemap(in) vector<T> (std::vector<T>* v) {
  44. if (SWIG_ConvertPtr($input,(void **) &v,
  45. $&1_descriptor,1) != -1) {
  46. $1 = *v;
  47. } else if (SvROK($input)) {
  48. AV *av = (AV *)SvRV($input);
  49. if (SvTYPE(av) != SVt_PVAV)
  50. SWIG_croak("Type error in argument $argnum of $symname. "
  51. "Expected an array of " #T);
  52. SV **tv;
  53. I32 len = av_len(av) + 1;
  54. T* obj;
  55. for (int i=0; i<len; i++) {
  56. tv = av_fetch(av, i, 0);
  57. if (SWIG_ConvertPtr(*tv, (void **)&obj,
  58. $descriptor(T *),0) != -1) {
  59. $1.push_back(*obj);
  60. } else {
  61. SWIG_croak("Type error in argument $argnum of "
  62. "$symname. "
  63. "Expected an array of " #T);
  64. }
  65. }
  66. } else {
  67. SWIG_croak("Type error in argument $argnum of $symname. "
  68. "Expected an array of " #T);
  69. }
  70. }
  71. %typemap(in) const vector<T>& (std::vector<T> temp,
  72. std::vector<T>* v),
  73. const vector<T>* (std::vector<T> temp,
  74. std::vector<T>* v) {
  75. if (SWIG_ConvertPtr($input,(void **) &v,
  76. $1_descriptor,1) != -1) {
  77. $1 = v;
  78. } else if (SvROK($input)) {
  79. AV *av = (AV *)SvRV($input);
  80. if (SvTYPE(av) != SVt_PVAV)
  81. SWIG_croak("Type error in argument $argnum of $symname. "
  82. "Expected an array of " #T);
  83. SV **tv;
  84. I32 len = av_len(av) + 1;
  85. T* obj;
  86. for (int i=0; i<len; i++) {
  87. tv = av_fetch(av, i, 0);
  88. if (SWIG_ConvertPtr(*tv, (void **)&obj,
  89. $descriptor(T *),0) != -1) {
  90. temp.push_back(*obj);
  91. } else {
  92. SWIG_croak("Type error in argument $argnum of "
  93. "$symname. "
  94. "Expected an array of " #T);
  95. }
  96. }
  97. $1 = &temp;
  98. } else {
  99. SWIG_croak("Type error in argument $argnum of $symname. "
  100. "Expected an array of " #T);
  101. }
  102. }
  103. %typemap(out) vector<T> {
  104. int len = $1.size();
  105. SV **svs = new SV*[len];
  106. for (unsigned int i=0; i<len; i++) {
  107. T* ptr = new T($1[i]);
  108. svs[i] = sv_newmortal();
  109. SWIG_MakePtr(svs[i], (void*) ptr,
  110. $descriptor(T *), $shadow|$owner);
  111. }
  112. AV *myav = av_make(len, svs);
  113. delete[] svs;
  114. $result = newRV_noinc((SV*) myav);
  115. sv_2mortal($result);
  116. argvi++;
  117. }
  118. %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
  119. {
  120. /* wrapped vector? */
  121. std::vector<T >* v;
  122. if (SWIG_ConvertPtr($input,(void **) &v,
  123. $1_&descriptor,0) != -1) {
  124. $1 = 1;
  125. } else if (SvROK($input)) {
  126. /* native sequence? */
  127. AV *av = (AV *)SvRV($input);
  128. if (SvTYPE(av) == SVt_PVAV) {
  129. SV **tv;
  130. I32 len = av_len(av) + 1;
  131. if (len == 0) {
  132. /* an empty sequence can be of any type */
  133. $1 = 1;
  134. } else {
  135. /* check the first element only */
  136. T* obj;
  137. tv = av_fetch(av, 0, 0);
  138. if (SWIG_ConvertPtr(*tv, (void **)&obj,
  139. $descriptor(T *),0) != -1)
  140. $1 = 1;
  141. else
  142. $1 = 0;
  143. }
  144. }
  145. } else {
  146. $1 = 0;
  147. }
  148. }
  149. }
  150. %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&,
  151. const vector<T>* {
  152. {
  153. /* wrapped vector? */
  154. std::vector<T >* v;
  155. if (SWIG_ConvertPtr($input,(void **) &v,
  156. $1_descriptor,0) != -1) {
  157. $1 = 1;
  158. } else if (SvROK($input)) {
  159. /* native sequence? */
  160. AV *av = (AV *)SvRV($input);
  161. if (SvTYPE(av) == SVt_PVAV) {
  162. SV **tv;
  163. I32 len = av_len(av) + 1;
  164. if (len == 0) {
  165. /* an empty sequence can be of any type */
  166. $1 = 1;
  167. } else {
  168. /* check the first element only */
  169. T* obj;
  170. tv = av_fetch(av, 0, 0);
  171. if (SWIG_ConvertPtr(*tv, (void **)&obj,
  172. $descriptor(T *),0) != -1)
  173. $1 = 1;
  174. else
  175. $1 = 0;
  176. }
  177. }
  178. } else {
  179. $1 = 0;
  180. }
  181. }
  182. }
  183. public:
  184. vector(unsigned int size = 0);
  185. vector(unsigned int size, const T& value);
  186. vector(const vector<T> &);
  187. unsigned int size() const;
  188. bool empty() const;
  189. void clear();
  190. %rename(push) push_back;
  191. void push_back(const T& x);
  192. %extend {
  193. T pop() throw (std::out_of_range) {
  194. if (self->size() == 0)
  195. throw std::out_of_range("pop from empty vector");
  196. T x = self->back();
  197. self->pop_back();
  198. return x;
  199. }
  200. T& get(int i) throw (std::out_of_range) {
  201. int size = int(self->size());
  202. if (i>=0 && i<size)
  203. return (*self)[i];
  204. else
  205. throw std::out_of_range("vector index out of range");
  206. }
  207. void set(int i, const T& x) throw (std::out_of_range) {
  208. int size = int(self->size());
  209. if (i>=0 && i<size)
  210. (*self)[i] = x;
  211. else
  212. throw std::out_of_range("vector index out of range");
  213. }
  214. }
  215. };
  216. // specializations for built-ins
  217. %define specialize_std_vector(T,CHECK_T,TO_T,FROM_T)
  218. template<> class vector<T> {
  219. %typemap(in) vector<T> (std::vector<T>* v) {
  220. if (SWIG_ConvertPtr($input,(void **) &v,
  221. $&1_descriptor,1) != -1){
  222. $1 = *v;
  223. } else if (SvROK($input)) {
  224. AV *av = (AV *)SvRV($input);
  225. if (SvTYPE(av) != SVt_PVAV)
  226. SWIG_croak("Type error in argument $argnum of $symname. "
  227. "Expected an array of " #T);
  228. SV **tv;
  229. I32 len = av_len(av) + 1;
  230. for (int i=0; i<len; i++) {
  231. tv = av_fetch(av, i, 0);
  232. if (CHECK_T(*tv)) {
  233. $1.push_back((T)TO_T(*tv));
  234. } else {
  235. SWIG_croak("Type error in argument $argnum of "
  236. "$symname. "
  237. "Expected an array of " #T);
  238. }
  239. }
  240. } else {
  241. SWIG_croak("Type error in argument $argnum of $symname. "
  242. "Expected an array of " #T);
  243. }
  244. }
  245. %typemap(in) const vector<T>& (std::vector<T> temp,
  246. std::vector<T>* v),
  247. const vector<T>* (std::vector<T> temp,
  248. std::vector<T>* v) {
  249. if (SWIG_ConvertPtr($input,(void **) &v,
  250. $1_descriptor,1) != -1) {
  251. $1 = v;
  252. } else if (SvROK($input)) {
  253. AV *av = (AV *)SvRV($input);
  254. if (SvTYPE(av) != SVt_PVAV)
  255. SWIG_croak("Type error in argument $argnum of $symname. "
  256. "Expected an array of " #T);
  257. SV **tv;
  258. I32 len = av_len(av) + 1;
  259. for (int i=0; i<len; i++) {
  260. tv = av_fetch(av, i, 0);
  261. if (CHECK_T(*tv)) {
  262. temp.push_back((T)TO_T(*tv));
  263. } else {
  264. SWIG_croak("Type error in argument $argnum of "
  265. "$symname. "
  266. "Expected an array of " #T);
  267. }
  268. }
  269. $1 = &temp;
  270. } else {
  271. SWIG_croak("Type error in argument $argnum of $symname. "
  272. "Expected an array of " #T);
  273. }
  274. }
  275. %typemap(out) vector<T> {
  276. size_t len = $1.size();
  277. SV **svs = new SV*[len];
  278. for (size_t i=0; i<len; i++) {
  279. svs[i] = sv_newmortal();
  280. FROM_T(svs[i], $1[i]);
  281. }
  282. AV *myav = av_make(len, svs);
  283. delete[] svs;
  284. $result = newRV_noinc((SV*) myav);
  285. sv_2mortal($result);
  286. argvi++;
  287. }
  288. %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
  289. {
  290. /* wrapped vector? */
  291. std::vector<T >* v;
  292. if (SWIG_ConvertPtr($input,(void **) &v,
  293. $1_&descriptor,0) != -1) {
  294. $1 = 1;
  295. } else if (SvROK($input)) {
  296. /* native sequence? */
  297. AV *av = (AV *)SvRV($input);
  298. if (SvTYPE(av) == SVt_PVAV) {
  299. SV **tv;
  300. I32 len = av_len(av) + 1;
  301. if (len == 0) {
  302. /* an empty sequence can be of any type */
  303. $1 = 1;
  304. } else {
  305. /* check the first element only */
  306. tv = av_fetch(av, 0, 0);
  307. if (CHECK_T(*tv))
  308. $1 = 1;
  309. else
  310. $1 = 0;
  311. }
  312. }
  313. } else {
  314. $1 = 0;
  315. }
  316. }
  317. }
  318. %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&,
  319. const vector<T>* {
  320. {
  321. /* wrapped vector? */
  322. std::vector<T >* v;
  323. if (SWIG_ConvertPtr($input,(void **) &v,
  324. $1_descriptor,0) != -1) {
  325. $1 = 1;
  326. } else if (SvROK($input)) {
  327. /* native sequence? */
  328. AV *av = (AV *)SvRV($input);
  329. if (SvTYPE(av) == SVt_PVAV) {
  330. SV **tv;
  331. I32 len = av_len(av) + 1;
  332. if (len == 0) {
  333. /* an empty sequence can be of any type */
  334. $1 = 1;
  335. } else {
  336. /* check the first element only */
  337. tv = av_fetch(av, 0, 0);
  338. if (CHECK_T(*tv))
  339. $1 = 1;
  340. else
  341. $1 = 0;
  342. }
  343. }
  344. } else {
  345. $1 = 0;
  346. }
  347. }
  348. }
  349. public:
  350. vector(unsigned int size = 0);
  351. vector(unsigned int size, T value);
  352. vector(const vector<T> &);
  353. unsigned int size() const;
  354. bool empty() const;
  355. void clear();
  356. %rename(push) push_back;
  357. void push_back(T x);
  358. %extend {
  359. T pop() throw (std::out_of_range) {
  360. if (self->size() == 0)
  361. throw std::out_of_range("pop from empty vector");
  362. T x = self->back();
  363. self->pop_back();
  364. return x;
  365. }
  366. T get(int i) throw (std::out_of_range) {
  367. int size = int(self->size());
  368. if (i>=0 && i<size)
  369. return (*self)[i];
  370. else
  371. throw std::out_of_range("vector index out of range");
  372. }
  373. void set(int i, T x) throw (std::out_of_range) {
  374. int size = int(self->size());
  375. if (i>=0 && i<size)
  376. (*self)[i] = x;
  377. else
  378. throw std::out_of_range("vector index out of range");
  379. }
  380. }
  381. };
  382. %enddef
  383. specialize_std_vector(bool,SvIOK,SvIVX,sv_setiv);
  384. specialize_std_vector(char,SvIOK,SvIVX,sv_setiv);
  385. specialize_std_vector(int,SvIOK,SvIVX,sv_setiv);
  386. specialize_std_vector(short,SvIOK,SvIVX,sv_setiv);
  387. specialize_std_vector(long,SvIOK,SvIVX,sv_setiv);
  388. specialize_std_vector(unsigned char,SvIOK,SvIVX,sv_setiv);
  389. specialize_std_vector(unsigned int,SvIOK,SvIVX,sv_setiv);
  390. specialize_std_vector(unsigned short,SvIOK,SvIVX,sv_setiv);
  391. specialize_std_vector(unsigned long,SvIOK,SvIVX,sv_setiv);
  392. specialize_std_vector(float,SvNIOK,SwigSvToNumber,sv_setnv);
  393. specialize_std_vector(double,SvNIOK,SwigSvToNumber,sv_setnv);
  394. specialize_std_vector(std::string,SvPOK,SvPVX,SwigSvFromString);
  395. }