00001
00002
00003 namespace dynamic
00004 {
00005 namespace internal
00006 {
00008
00009 template<typename Impl>
00010 class wrap_cpp_container : public shared_var_impl
00011 {
00012 int m_iterator_count;
00013
00014 protected:
00015 typedef typename Impl::container container;
00016
00017 typedef typename container::iterator iterator;
00018
00019 typedef typename container::reverse_iterator reverse_iterator;
00020
00021 container m_data;
00022
00023 void invalidate_iterators()
00024 {
00025 ++m_iterator_count;
00026 }
00027
00028 public:
00029 wrap_cpp_container()
00030 {
00031 }
00032
00033 wrap_cpp_container(const wrap_cpp_container & other) :
00034 m_data(other.m_data)
00035 {
00036 }
00037
00039 template<typename Iterator>
00040 class wrap_iterator : public shared_var_impl
00041 {
00042 public:
00043 Iterator m_begin, m_it, m_end;
00044
00045 wrap_cpp_container * m_container;
00046
00047 int m_iterator_count;
00048 public:
00049 wrap_iterator(Iterator i,
00050 Iterator begin,
00051 Iterator end,
00052 wrap_cpp_container * c,
00053 int count
00054 ) :
00055 m_it(i),
00056 m_begin(begin),
00057 m_end(end),
00058 m_container(c),
00059 m_iterator_count(count)
00060 {
00061 }
00062
00063 void mark_children(gc::garbage_collector & gc)
00064 {
00065 gc.mark_reachable(m_container);
00066 }
00067
00068 var key()
00069 {
00070 if(m_container->m_iterator_count != m_iterator_count)
00071 throw expired_iterator();
00072
00073 return Impl::key(*m_it);
00074 }
00075
00076 var value()
00077 {
00078 if(m_container->m_iterator_count != m_iterator_count)
00079 throw expired_iterator();
00080
00081 return Impl::value(*m_it);
00082 }
00083
00084 var deref()
00085 {
00086 if(m_container->m_iterator_count != m_iterator_count)
00087 throw expired_iterator();
00088
00089 if(m_it == m_end) throw expired_iterator();
00090 return Impl::deref(*m_it);
00091 }
00092
00093 void op_inc()
00094 {
00095 if(m_container->m_iterator_count != m_iterator_count)
00096 throw expired_iterator();
00097
00098 if( m_it != m_end )
00099 ++m_it;
00100 }
00101
00102 bool as_bool()
00103 {
00104 return m_it != m_end;
00105 }
00106
00107 void op_dec()
00108 {
00109 if(m_container->m_iterator_count != m_iterator_count)
00110 throw expired_iterator();
00111
00112 if( m_it != m_begin )
00113 --m_it;
00114 }
00115
00116 var_cmp_result compare(const var & other)
00117 {
00118 wrap_iterator * other_iterator = dynamic_cast<wrap_iterator*>(other.impl().shared_var());
00119
00120 return other_iterator && m_it == other_iterator->m_it ?
00121 cmp_equal : cmp_not_equal;
00122 }
00123
00124 var clone()
00125 {
00126 return new wrap_iterator(*this);
00127 }
00128
00129 std::string class_name() { return Impl::iterator_class_name(); }
00130 };
00131
00132
00133 void erase(const var & i)
00134 {
00135
00136 wrap_iterator<iterator> * wi = dynamic_cast<wrap_iterator<iterator>*>(i.impl().shared_var());
00137
00138 if(wi)
00139 {
00140 if(wi->m_iterator_count == m_iterator_count)
00141 {
00142 if( wi->m_it != wi->m_end )
00143 {
00144 invalidate_iterators();
00145 m_data.erase(wi->m_it);
00146 }
00147 }
00148 else
00149 {
00150 throw expired_iterator();
00151 }
00152 }
00153 }
00154
00155 var begin()
00156 {
00157 return new wrap_iterator<iterator>(
00158 m_data.begin(),
00159 m_data.begin(),
00160 m_data.end(),
00161 this,
00162 m_iterator_count);
00163 }
00164
00165 var enumerator()
00166 {
00167 return begin();
00168 }
00169
00170 var clone()
00171 {
00172 return new wrap_cpp_container(*this);
00173 }
00174
00175 std::string class_name()
00176 {
00177 return Impl::class_name();
00178 }
00179
00180 var end()
00181 {
00182 return new wrap_iterator<iterator>(
00183 m_data.end(),
00184 m_data.begin(),
00185 m_data.end(),
00186 this,
00187 m_iterator_count);
00188 }
00189
00190 var rbegin()
00191 {
00192 return new wrap_iterator<reverse_iterator>(
00193 m_data.rbegin(),
00194 m_data.rbegin(),
00195 m_data.rend(),
00196 this,
00197 m_iterator_count);
00198 }
00199
00200 var rend()
00201 {
00202 return new wrap_iterator<reverse_iterator>(
00203 m_data.rend(),
00204 m_data.rbegin(),
00205 m_data.rend(),
00206 this,
00207 m_iterator_count);
00208 }
00209
00210 var reverse_enumerator()
00211 {
00212 return rbegin();
00213 }
00214
00215 bool empty()
00216 {
00217 return m_data.empty();
00218 }
00219
00220 bool as_bool()
00221 {
00222 return !empty();
00223 }
00224
00225 void clear()
00226 {
00227 invalidate_iterators();
00228 m_data.clear();
00229 }
00230
00231 var values()
00232 {
00233 return this;
00234 }
00235
00236 int size()
00237 {
00238 return int(m_data.size());
00239 }
00240
00241 void mark_children(gc::garbage_collector & gc)
00242 {
00243 for(iterator i=m_data.begin(); i!=m_data.end(); ++i)
00244 Impl::mark_reachable(*i, gc);
00245 }
00246
00247 var_cmp_index comparison_index()
00248 {
00249 return Impl::comparison_index;
00250 }
00251 };
00252
00253
00255
00256 template<typename Impl>
00257 class wrap_assoc_container : public wrap_cpp_container<Impl>
00258 {
00259 public:
00260 typedef typename wrap_cpp_container<Impl>::iterator iterator;
00261
00262 void set_member(const var & k, const var & v)
00263 {
00264 this->invalidate_iterators();
00265 (this->m_data)[Impl::key(k)] = v;
00266 }
00267
00268 var call(const var & k, const var & v)
00269 {
00270 this->invalidate_iterators();
00271 (this->m_data)[Impl::key(k)] = v;
00272 return this;
00273 }
00274
00275 int max_args()
00276 {
00277 return 2;
00278 }
00279
00280 var get_member(const var & k)
00281 {
00282 iterator i=this->m_data.find( Impl::key(k) );
00283 return i == this->m_data.end() ? var() : Impl::value(*i);
00284 }
00285
00286 void erase(const var & k)
00287 {
00288 this->m_data.erase( Impl::key(k) );
00289 this->invalidate_iterators();
00290 }
00291
00292 bool contains(const var & k)
00293 {
00294 iterator i=this->m_data.find( Impl::key(k) );
00295 return i != this->m_data.end();
00296 }
00297
00298 var values()
00299 {
00301
00302
00303 var v = array();
00304 v.impl().reserve(this->m_data.size());
00305 for(typename Impl::container::iterator i=this->m_data.begin();
00306 i!=this->m_data.end(); ++i)
00307 v.push_back(i->second.get());
00308
00309 return v;
00310 }
00311
00312 void short_output(ostream & ss)
00313 {
00314 ss << "{ ... }";
00315 }
00316
00317 void output(ostream & ss)
00318 {
00319 ss << '{';
00320
00321 bool first=true;
00322 for(iterator i=this->m_data.begin(); i!=this->m_data.end(); ++i)
00323 {
00324 if(first) first=false;
00325 else ss << ',';
00326 Impl::key(*i).impl().short_output(ss);
00327 ss << ':';
00328 Impl::value(*i).impl().short_output(ss);
00329 }
00330
00331 ss << '}';
00332 }
00333
00334 void short_output(wostream & ss)
00335 {
00336 ss << L"{ ... }";
00337 }
00338
00339 void output(wostream & ss)
00340 {
00341 ss << L'{';
00342
00343 bool first=true;
00344 for(iterator i=this->m_data.begin(); i!=this->m_data.end(); ++i)
00345 {
00346 if(first) first=false;
00347 else ss << L',';
00348 Impl::key(*i).impl().short_output(ss);
00349 ss << L':';
00350 Impl::value(*i).impl().short_output(ss);
00351 }
00352
00353 ss << L'}';
00354 }
00355
00356 var clone()
00357 {
00358 return new wrap_assoc_container(*this);
00359 }
00360
00361 var keys()
00362 {
00363 return this;
00364 }
00365
00366 void pickle(pickler & p)
00367 {
00368 p.write_object_type(Impl::comparison_index);
00369 p.write_int(int(this->m_data.size()));
00370 for(iterator i=this->m_data.begin(); i!=this->m_data.end(); ++i)
00371 {
00372 p.write_object(Impl::key(*i));
00373 p.write_object(Impl::value(*i));
00374 }
00375 }
00376
00377 void unpickle(unpickler & p)
00378 {
00379 int size = p.read_int();
00380 for(int i=0; i<size; ++i)
00381 {
00382 var k = p.read_object();
00383 var v = p.read_object();
00384 this->m_data.insert( std::make_pair( Impl::key(k), v) );
00385 }
00386 }
00387
00388 void mixin(const var & other)
00389 {
00390 foreach(i, other)
00391 set_member(i, other[i]);
00392 }
00393
00394 void assign_add(const var & other)
00395 {
00396 mixin(other);
00397 }
00398
00399 var op_add(const var & other)
00400 {
00401 return clone()+=other;
00402 }
00403 };
00404
00405
00407
00408 template<typename Impl>
00409 class wrap_array_container : public wrap_cpp_container<Impl>
00410 {
00411 public:
00412 typedef typename wrap_cpp_container<Impl>::iterator iterator;
00413
00414 void push_back(const var & v)
00415 {
00416 this->invalidate_iterators();
00417 this->m_data.push_back(Impl::to_value(v));
00418 }
00419
00420 var pop_back()
00421 {
00422 if(this->m_data.empty())
00423 return var();
00424 else
00425 {
00426 var result = Impl::back(this->m_data);
00427 Impl::pop_back(this->m_data);
00428 this->invalidate_iterators();
00429 return result;
00430 }
00431 }
00432
00433 var call(const var & a0)
00434 {
00435 this->invalidate_iterators();
00436 this->m_data.push_back(Impl::to_value(a0));
00437 return this;
00438 }
00439
00440 int max_args()
00441 {
00442 return 1;
00443 }
00444
00445 var front()
00446 {
00447 return this->m_data.empty() ? var() : Impl::front(this->m_data);
00448 }
00449
00450 var back()
00451 {
00452 return this->m_data.empty() ? var() : Impl::back(this->m_data);
00453 }
00454
00455 var clone()
00456 {
00457 return new wrap_array_container(*this);
00458 }
00459
00460 var keys()
00461 {
00462 return this->empty() ? var() : dynamic::range(0, this->size()-1);
00463 }
00464
00465 void short_output(ostream & ss)
00466 {
00467 ss << "[ ... ]";
00468 }
00469
00470 void output(ostream & ss)
00471 {
00472 ss << '[';
00473
00474 bool first=true;
00475 for(iterator i=this->m_data.begin(); i!=this->m_data.end(); ++i)
00476 {
00477 if(first) first=false;
00478 else ss << ',';
00479 Impl::value(*i).impl().short_output(ss);
00480 }
00481
00482 ss << ']';
00483 }
00484
00485 void short_output(wostream & ss)
00486 {
00487 ss << L"[ ... ]";
00488 }
00489
00490 void output(wostream & ss)
00491 {
00492 ss << L'[';
00493
00494 bool first=true;
00495 for(iterator i=this->m_data.begin(); i!=this->m_data.end(); ++i)
00496 {
00497 if(first) first=false;
00498 else ss << L',';
00499 Impl::value(*i).impl().short_output(ss);
00500 }
00501
00502 ss << L']';
00503 }
00504
00505 void pickle(pickler & p)
00506 {
00507 p.write_object_type(Impl::comparison_index);
00508 p.write_int(int(this->m_data.size()));
00509 for(iterator i=this->m_data.begin(); i!=this->m_data.end(); ++i)
00510 {
00511 Impl::pickle(p, *i);
00512 }
00513 }
00514
00515 void unpickle(unpickler & p)
00516 {
00517 int size = p.read_int();
00518 for(int i=0; i<size; ++i)
00519 {
00520 this->m_data.push_back( Impl::unpickle(p) );
00521 }
00522 }
00523
00524 var op_add(const var & v)
00525 {
00526 return clone()+=v;
00527 }
00528
00529 void assign_add(const var & v)
00530 {
00531 foreach(i, v) this->push_back(i);
00532 }
00533
00534 var op_mul(const var & v)
00535 {
00536 return clone()*=v;
00537 }
00538
00539 void assign_mul(const var & v)
00540 {
00541 this->invalidate_iterators();
00542 int n=v.as_int();
00543 int s=this->m_data.size();
00544 if(n == 0) this->m_data.clear();
00545 this->reserve(s*n);
00546 for(int i=1; i<n; ++i)
00547 {
00548 iterator it = this->m_data.begin();
00549 for(int j=0; j<s; ++j)
00550 {
00551 this->m_data.push_back(*it++);
00552 }
00553 }
00554 }
00555 };
00556
00557
00559
00560 template<typename Impl>
00561 class wrap_vector_container : public wrap_array_container<Impl>
00562 {
00563 typedef typename Impl::container container;
00564
00565 int get_index(int i2, container & data)
00566 {
00567 return i2>=0 ? i2 : data.size()+i2;
00568 }
00569
00570 public:
00571
00572 void set_member(const var & k, const var & v)
00573 {
00574 int index = get_index(k.as_int(), this->m_data);
00575 if(index < 0) throw not_found(k);
00576
00577 if(unsigned(index) >= this->m_data.size())
00578 {
00579 this->invalidate_iterators();
00580 this->m_data.resize(index+1, Impl::pad_value());
00581 }
00582 (this->m_data)[index] = Impl::to_value(v);
00583 }
00584
00585 void set_member(int k, const var & v)
00586 {
00587 int index = get_index(k, this->m_data);
00588 if(index < 0) throw not_found(k);
00589
00590 if(unsigned(index) >= this->m_data.size())
00591 {
00592 this->invalidate_iterators();
00593 this->m_data.resize(index+1, Impl::pad_value());
00594 }
00595 (this->m_data)[index] = Impl::to_value(v);
00596 }
00597
00598 bool contains(const var & k)
00599 {
00600 int index = get_index(k.as_int(), this->m_data);
00601 return index>=0 && std::size_t(index)<this->m_data.size();
00602 }
00603
00604 void resize(std::size_t new_size)
00605 {
00606 this->invalidate_iterators();
00607 this->m_data.resize(new_size, Impl::pad_value());
00608 }
00609
00610 var get_member(int k)
00611 {
00612 int index = get_index(k, this->m_data);
00613 if(index<0 || unsigned(index) >= this->m_data.size()) return Impl::pad_value();
00614 return Impl::deref((this->m_data)[index]);
00615 }
00616
00617 var get_member(const var & k)
00618 {
00619 int index = get_index(k.as_int(), this->m_data);
00620 if(index<0 || unsigned(index) >= this->m_data.size()) return Impl::pad_value();
00621 return Impl::deref((this->m_data)[index]);
00622 }
00623
00624 void erase(const var & k)
00625 {
00626 std::size_t my_size = this->m_data.size();
00627 std::pair<std::size_t,std::size_t> r;
00628 k.impl().get_range(my_size, r);
00629 if(r.first > my_size) r.first = my_size;
00630 if(r.second > my_size) r.second = my_size;
00631
00632 if(r.first != r.second)
00633 {
00634 this->invalidate_iterators();
00635 this->m_data.erase(this->m_data.begin()+r.first, this->m_data.begin()+r.second);
00636 }
00637 }
00638
00639 void insert(const var & k, const var & value)
00640 {
00641 int index = get_index(k.as_int(), this->m_data);
00642
00643 this->invalidate_iterators();
00644
00645 if(index < 0)
00646 {
00647 this->m_data.insert(this->m_data.begin(), -index, Impl::pad_value());
00648 index=0;
00649 }
00650 else if(unsigned(index) >= this->m_data.size())
00651 {
00652 this->m_data.resize(index, Impl::pad_value());
00653 }
00654
00655 this->m_data.insert(this->m_data.begin()+index, value.size(), Impl::pad_value());
00656
00657
00658
00659
00660 foreach( i, value )
00661 {
00662 this->invalidate_iterators();
00663 this->m_data[index++] = Impl::to_value(i);
00664 }
00665 }
00666
00667 var clone()
00668 {
00669 return new wrap_vector_container(*this);
00670 }
00671
00672 void reserve(std::size_t s)
00673 {
00674 this->invalidate_iterators();
00675 this->m_data.reserve(s);
00676 }
00677
00678 std::size_t capacity()
00679 {
00680 return this->m_data.capacity();
00681 }
00682
00683 void assign_mul(const var & v)
00684 {
00685 this->invalidate_iterators();
00686 int n=v.as_int();
00687 int s=this->m_data.size();
00688 if(n == 0) this->m_data.clear();
00689 reserve(s*n);
00690 for(int i=1; i<n; ++i)
00691 for(int j=0; j<s; ++j)
00692 this->m_data.push_back(this->m_data[j]);
00693 }
00694 };
00695
00696
00698
00699 template<typename Impl>
00700 class wrap_list_container : public wrap_array_container<Impl>
00701 {
00702 public:
00703 void push_front(const var & v)
00704 {
00705 this->m_data.push_front(v);
00706 this->invalidate_iterators();
00707 }
00708
00709 var pop_front()
00710 {
00711 if(this->m_data.empty())
00712 return var();
00713 else
00714 {
00715 var result = this->m_data.front().get();
00716 this->m_data.pop_front();
00717 this->invalidate_iterators();
00718 return result;
00719 }
00720 }
00721
00722 var clone()
00723 {
00724 return new wrap_list_container(*this);
00725 }
00726 };
00727 }
00728 }