00001
00014 #ifndef FLEXGRID_HPP
00015 #define FLEXGRID_HPP
00016
00017 #include <deque>
00018 #include <stdexcept>
00019 #include <iterator>
00020
00021 #include <sys/types.h>
00022
00023 namespace jafar {
00024 namespace lgl {
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 template<typename value_t>
00049 class sdeque
00050 {
00051 public:
00052 typedef std::deque<value_t> deque_t;
00053 typedef typename deque_t::iterator iterator;
00054 typedef typename deque_t::const_iterator const_iterator;
00055
00056 sdeque(): m_ibegin(0), m_iend(0) {}
00057
00058 sdeque(sdeque const & orig)
00059 : m_ibegin(orig.m_ibegin), m_iend(orig.m_iend), m_deque(orig.m_deque) {}
00060
00061 value_t & at(ssize_t ii)
00062 { return m_deque.at(static_cast<size_t>(ii - m_ibegin)); }
00063
00064 value_t const & at(ssize_t ii) const
00065 { return m_deque.at(static_cast<size_t>(ii - m_ibegin)); }
00066
00067 void resize_begin(ssize_t ibegin, value_t const & value) {
00068 if (ibegin > m_iend)
00069 throw std::out_of_range("estar::sdeque::resize_begin() range error");
00070 ssize_t delta(m_ibegin - ibegin);
00071 m_ibegin = ibegin;
00072 if (0 < delta)
00073 m_deque.insert(m_deque.begin(), static_cast<size_t>(delta), value);
00074 else if (0 > delta)
00075 m_deque.erase(m_deque.begin(),
00076 m_deque.begin() + static_cast<size_t>(-delta));
00077
00078 }
00079
00080 void resize_begin(ssize_t ibegin) { resize_begin(ibegin, value_t()); }
00081
00082 void resize_end(ssize_t iend, value_t const & value) {
00083 if (iend < m_ibegin)
00084 throw std::out_of_range("estar::sdeque::resize_end() range error");
00085 m_iend = iend;
00086 m_deque.resize(static_cast<size_t>(m_iend - m_ibegin), value);
00087 }
00088
00089 void resize_end(ssize_t iend) { resize_end(iend, value_t()); }
00090
00094 void resize(ssize_t ibegin, ssize_t iend, value_t const & value) {
00095 resize_begin(ibegin, value);
00096 resize_end(iend, value);
00097 }
00098
00099 void resize(ssize_t ibegin, ssize_t iend)
00100 { resize(ibegin, iend, value_t()); }
00101
00102 ssize_t ibegin() const { return m_ibegin; }
00103
00104 ssize_t iend() const { return m_iend; }
00105
00106 deque_t const & get() const { return m_deque; }
00107
00108 iterator begin() { return m_deque.begin(); }
00109
00110 const_iterator begin() const { return m_deque.begin(); }
00111
00112 iterator end() { return m_deque.end(); }
00113
00114 const_iterator end() const { return m_deque.end(); }
00115
00116 protected:
00117 ssize_t m_ibegin, m_iend;
00118 deque_t m_deque;
00119 };
00120
00121
00122
00123
00124
00125
00126
00127 template<typename value_t>
00128 class flexgrid_traits
00129 {
00130 public:
00131 typedef sdeque<value_t> line_t;
00132 typedef typename line_t::iterator cell_iterator;
00133 typedef typename line_t::const_iterator const_cell_iterator;
00134
00135 typedef sdeque<line_t> grid_t;
00136 typedef typename grid_t::iterator line_iterator;
00137 typedef typename grid_t::const_iterator const_line_iterator;
00138 };
00139
00140
00141
00142
00143
00144
00145
00146 template<typename blah>
00147 struct flexgrid_iterator_traits {
00148 typedef flexgrid_traits<blah> traits;
00149 typedef blah value_t;
00150 typedef value_t * pointer_t;
00151 typedef value_t & reference_t;
00152 typedef typename traits::grid_t & grid_ref_t;
00153 typedef typename traits::line_t & line_ref_t;
00154 };
00155
00156
00157 template<typename blah>
00158 struct flexgrid_const_iterator_traits {
00159 typedef flexgrid_traits<blah> traits;
00160 typedef blah value_t;
00161 typedef value_t const * pointer_t;
00162 typedef value_t const & reference_t;
00163 typedef typename traits::grid_t const & grid_ref_t;
00164 typedef typename traits::line_t const & line_ref_t;
00165 };
00166
00167
00168 template<typename value_t, typename traits>
00169 class base_flexgrid_iterator
00170 {
00171 public:
00172
00173 typedef base_flexgrid_iterator<value_t, traits> self;
00174
00175
00176 typedef std::bidirectional_iterator_tag iterator_category;
00177 typedef typename traits::value_t value_type;
00178 typedef typename std::ptrdiff_t difference_type;
00179 typedef typename traits::pointer_t pointer;
00180 typedef typename traits::reference_t reference;
00181
00182
00183 typedef typename traits::grid_ref_t grid_ref_t;
00184 typedef typename traits::line_ref_t line_ref_t;
00185
00186
00187 base_flexgrid_iterator(grid_ref_t grid, line_ref_t line,
00188 ssize_t ix, ssize_t iy)
00189 : m_grid(grid), m_line(line), m_ix(ix), m_iy(iy) {}
00190
00191 base_flexgrid_iterator(base_flexgrid_iterator const & orig)
00192 : m_grid(orig.m_grid), m_line(orig.m_line),
00193 m_ix(orig.m_ix), m_iy(orig.m_iy) {}
00194
00195 bool at_end() const
00196 { return (m_ix >= xend()) || (m_iy >= yend()); }
00197
00198 bool at_begin() const
00199 { return (m_ix <= xbegin()) && (m_iy <= ybegin()); }
00200
00201 reference operator*() const
00202 { return m_grid.at(m_iy).at(m_ix); }
00203
00204 pointer operator->() const
00205 { return &(m_grid.at(m_iy).at(m_ix)); }
00206
00207 self & operator++() {
00208 increment();
00209 return *this;
00210 }
00211
00212 self operator++(int) {
00213 self tmp(*this);
00214 increment();
00215 return tmp;
00216 }
00217
00218 self & operator--() {
00219 decrement();
00220 return *this;
00221 }
00222
00223 self operator--(int) {
00224 self tmp(*this);
00225 decrement();
00226 return tmp;
00227 }
00228
00229 template<typename other_t>
00230 bool operator==(other_t const & other) const {
00231 if (&m_grid != &other.m_grid)
00232 return false;
00233 if (at_end() && other.at_end())
00234 return true;
00235 if (at_begin() && other.at_begin())
00236 return true;
00237 return (m_ix == other.m_ix) && (m_iy == other.m_iy);
00238 }
00239
00240 template<typename other_t>
00241 bool operator!=(other_t const & other) const
00242 { return ! (*this == other); }
00243
00245 grid_ref_t m_grid;
00246 line_ref_t m_line;
00247 ssize_t m_ix, m_iy;
00248
00249 ssize_t xend() const { return m_line.iend(); }
00250 ssize_t xbegin() const { return m_line.ibegin(); }
00251 ssize_t yend() const { return m_grid.iend(); }
00252 ssize_t ybegin() const { return m_grid.ibegin(); }
00253
00254 void increment() {
00255 if (at_end())
00256 return;
00257 if (at_begin()) {
00258 m_ix = xbegin() + 1;
00259 m_iy = ybegin();
00260 return;
00261 }
00262 ++m_ix;
00263 if (m_ix >= xend()) {
00264 ++m_iy;
00265 if (m_iy >= yend())
00266 return;
00267 m_ix = xbegin();
00268 }
00269 }
00270
00271 void decrement() {
00272 if (at_begin())
00273 return;
00274 if (at_end()) {
00275 m_ix = xend() - 1;
00276 m_iy = yend() - 1;
00277 return;
00278 }
00279 --m_ix;
00280 if (m_ix < xbegin()) {
00281 --m_iy;
00282 if (m_iy < ybegin())
00283 return;
00284 m_ix = xend() - 1;
00285 }
00286 }
00287 };
00288
00289
00290 template<typename value_t>
00291 class flexgrid_iterator
00292 : public base_flexgrid_iterator<value_t, flexgrid_iterator_traits<value_t> >
00293 {
00294 public:
00295 typedef base_flexgrid_iterator<value_t, flexgrid_iterator_traits<value_t> > base;
00296
00297 typedef typename base::grid_ref_t grid_ref_t;
00298 typedef typename base::line_ref_t line_ref_t;
00299
00300 flexgrid_iterator(grid_ref_t grid, line_ref_t line, ssize_t ix, ssize_t iy)
00301 : base(grid, line, ix, iy) {}
00302
00303 flexgrid_iterator(flexgrid_iterator const & orig)
00304 : base(orig) {}
00305 };
00306
00307
00308 template<typename value_t>
00309 class const_flexgrid_iterator
00310 : public base_flexgrid_iterator<value_t, flexgrid_const_iterator_traits<value_t> >
00311 {
00312 public:
00313 typedef
00314 base_flexgrid_iterator<value_t, flexgrid_const_iterator_traits<value_t> > base;
00315
00316 typedef typename base::grid_ref_t grid_ref_t;
00317 typedef typename base::line_ref_t line_ref_t;
00318
00319 const_flexgrid_iterator(grid_ref_t grid, line_ref_t line,
00320 ssize_t ix, ssize_t iy)
00321 : base(grid, line, ix, iy) {}
00322
00323 const_flexgrid_iterator(const_flexgrid_iterator const & orig)
00324 : base(orig) {}
00325
00326 const_flexgrid_iterator(flexgrid_iterator<value_t> const & orig)
00327 : base(reinterpret_cast<base const &>(orig)) {}
00328 };
00329
00330
00331
00332
00333
00334
00335 template<typename value_t>
00336 class FlexGrid
00337 {
00338 public:
00339 typedef flexgrid_traits<value_t> traits;
00340 typedef typename traits::line_t line_t;
00341 typedef typename traits::cell_iterator cell_iterator;
00342 typedef typename traits::const_cell_iterator const_cell_iterator;
00343 typedef typename traits::grid_t grid_t;
00344 typedef typename traits::line_iterator line_iterator;
00345 typedef typename traits::const_line_iterator const_line_iterator;
00346 typedef flexgrid_iterator<value_t> iterator;
00347 typedef const_flexgrid_iterator<value_t> const_iterator;
00348
00349 bool set(ssize_t ix, ssize_t iy, value_t const & value) {
00350 if (!valid(ix,iy)) {
00351 return false;
00352 }
00353
00354 m_grid.at(iy).at(ix) = value;
00355
00356 return true;
00357
00358 }
00359
00360 value_t & at(ssize_t ix, ssize_t iy) { return m_grid.at(iy).at(ix); }
00361
00362 value_t const & at(ssize_t ix, ssize_t iy) const
00363 { return m_grid.at(iy).at(ix); }
00364
00365 value_t get(ssize_t ix, ssize_t iy) {
00366 return m_grid.at(iy).at(ix);
00367 }
00368
00369 void resize_xbegin(ssize_t xbegin, value_t const & value) {
00370 for (line_iterator ii(m_grid.begin()); ii != m_grid.end(); ++ii)
00371 ii->resize_begin(xbegin, value);
00372 m_default.resize_begin(xbegin);
00373 }
00374
00375 void resize_xbegin(ssize_t xbegin) { resize_xbegin(xbegin, value_t()); }
00376
00377 void resize_xend(ssize_t xend, value_t const & value) {
00378 for (line_iterator ii(m_grid.begin()); ii != m_grid.end(); ++ii)
00379 ii->resize_end(xend, value);
00380 m_default.resize_end(xend);
00381 }
00382
00383 void resize_xend(ssize_t xend) { resize_xend(xend, value_t()); }
00384
00385 void resize_x(ssize_t xbegin, ssize_t xend, value_t const & value) {
00386 if (xbegin < m_default.ibegin())
00387 resize_xbegin(xbegin, value);
00388 if (xend > m_default.iend())
00389 resize_xend(xend, value);
00390 }
00391
00392 void resize_x(ssize_t xbegin, ssize_t xend) {
00393 if (xbegin < m_default.ibegin())
00394 resize_xbegin(xbegin);
00395 if (xend > m_default.iend())
00396 resize_xend(xend);
00397 }
00398
00401 void resize_ybegin(ssize_t ybegin, value_t const & value) {
00402 if (ybegin > m_grid.ibegin())
00403 m_grid.resize_begin(ybegin, m_default);
00404 else if (ybegin < m_grid.ibegin()) {
00405 line_t vline(m_default);
00406 fill(vline.begin(), vline.end(), value);
00407 m_grid.resize_begin(ybegin, vline);
00408 }
00409
00410 }
00411
00412 void resize_ybegin(ssize_t ybegin)
00413 { m_grid.resize_begin(ybegin, m_default); }
00414
00417 void resize_yend(ssize_t yend, value_t const & value) {
00418 if (yend < m_grid.iend())
00419 m_grid.resize_end(yend, m_default);
00420 else if (yend > m_grid.iend()) {
00421 line_t vline(m_default);
00422 fill(vline.begin(), vline.end(), value);
00423 m_grid.resize_end(yend, vline);
00424 }
00425
00426 }
00427
00428 void resize_yend(ssize_t yend)
00429 { m_grid.resize_end(yend, m_default); }
00430
00431 void resize_y(ssize_t ybegin, ssize_t yend, value_t const & value) {
00432 if (ybegin < m_grid.ibegin())
00433 resize_ybegin(ybegin, value);
00434 if (yend > m_grid.iend())
00435 resize_yend(yend, value);
00436 }
00437
00438 void resize_y(ssize_t ybegin, ssize_t yend) {
00439 if (ybegin < m_grid.ibegin())
00440 resize_ybegin(ybegin);
00441 if (yend > m_grid.iend())
00442 resize_yend(yend);
00443 }
00444
00447 void resize(ssize_t xbegin, ssize_t xend,
00448 ssize_t ybegin, ssize_t yend,
00449 value_t const & value) {
00450 if (xbegin < m_default.ibegin())
00451 resize_xbegin(xbegin, value);
00452 if (xend > m_default.iend())
00453 resize_xend(xend, value);
00454 if (ybegin < m_grid.ibegin())
00455 resize_ybegin(ybegin, value);
00456 if (yend > m_grid.iend())
00457 resize_yend(yend, value);
00458 }
00459
00462 void resize(ssize_t xbegin, ssize_t xend,
00463 ssize_t ybegin, ssize_t yend) {
00464 if (xbegin < m_default.ibegin())
00465 resize_xbegin(xbegin);
00466 if (xend > m_default.iend())
00467 resize_xend(xend);
00468 if (ybegin < m_grid.ibegin())
00469 resize_ybegin(ybegin);
00470 if (yend > m_grid.iend())
00471 resize_yend(yend);
00472 }
00473
00474 ssize_t xbegin() const { return m_default.ibegin(); }
00475
00476 ssize_t xend() const { return m_default.iend(); }
00477
00478 ssize_t ybegin() const { return m_grid.ibegin(); }
00479
00480 ssize_t yend() const { return m_grid.iend(); }
00481
00482 ssize_t x_size() const {
00483 return (xend()-xbegin());
00484 }
00485
00486 ssize_t y_size() const {
00487 return (yend()-ybegin());
00488 }
00489
00490 ssize_t size() const {
00491 return (x_size()*y_size());
00492 }
00493
00496 value_t & smart_at(ssize_t ix, ssize_t iy) {
00497 if (ix < m_default.ibegin())
00498 resize_xbegin(ix);
00499 else if (ix >= m_default.iend())
00500 resize_xend(ix + 1);
00501 if (iy < m_grid.ibegin())
00502 resize_ybegin(iy);
00503 else if (iy >= m_grid.iend())
00504 resize_yend(iy + 1);
00505 return m_grid.at(iy).at(ix);
00506 }
00507
00508 line_iterator line_begin() { return m_grid.begin(); }
00509
00510 const_line_iterator line_begin() const { return m_grid.begin(); }
00511
00512 line_iterator line_end() { return m_grid.end(); }
00513
00514 const_line_iterator line_end() const { return m_grid.end(); }
00515
00516 iterator begin() {
00517 return iterator(m_grid, m_default, m_default.ibegin(), m_grid.ibegin());
00518 }
00519
00520 const_iterator begin() const {
00521 return const_iterator(m_grid, m_default,
00522 m_default.ibegin(), m_grid.ibegin());
00523 }
00524
00525 iterator end()
00526 { return iterator(m_grid, m_default, m_default.iend(), m_grid.iend()); }
00527
00528 const_iterator end() const {
00529 return const_iterator(m_grid, m_default,
00530 m_default.iend(), m_grid.iend());
00531 }
00532
00533 bool valid(ssize_t ix, ssize_t iy) const {
00534 return (ix >= m_default.ibegin())
00535 && (ix < m_default.iend())
00536 && (iy >= m_grid.ibegin())
00537 && (iy < m_grid.iend());
00538 }
00539
00540 bool valid_range(ssize_t xbegin, ssize_t xend,
00541 ssize_t ybegin, ssize_t yend) const {
00542 return (xbegin >= m_default.ibegin())
00543 && (xend <= m_default.iend())
00544 && (ybegin >= m_grid.ibegin())
00545 && (yend <= m_grid.iend());
00546 }
00547
00548 bool valid_bbox(ssize_t x0, ssize_t y0, ssize_t x1, ssize_t y1) const {
00549 return (x0 >= m_default.ibegin())
00550 && (x1 < m_default.iend())
00551 && (y0 >= m_grid.ibegin())
00552 && (y1 < m_grid.iend());
00553 }
00554
00555 void clear()
00556 {
00557
00558 m_grid.resize(0,0);
00559 m_default.resize(0,0);
00560 }
00561
00562 protected:
00563 friend class flexgrid_iterator<value_t>;
00564
00565 grid_t m_grid;
00566 line_t m_default;
00567 };
00568 }
00569 }
00570
00571 #endif