00001
00010 #ifndef BS_TABLE_2D_H_
00011 #define BS_TABLE_2D_H_
00012
00013 #include "seq_vector.h"
00014
00015 namespace blue_sky
00016 {
00017 namespace table
00018 {
00019
00020 template <typename strategy_t> class data_group;
00021 template <typename strategy_t> class data_row;
00022 template <typename strategy_t> class table_2d;
00023 template <typename strategy_t> class data_row_push_back;
00024
00025 template <typename strategy_t>
00026 class data_row
00027 {
00028 public:
00029 typedef typename strategy_t::item_t item_t;
00030 typedef typename strategy_t::item_array_t item_array_t;
00031
00032 typedef data_row <strategy_t> this_t;
00033
00034 private:
00035 friend class data_group <strategy_t>;
00036
00037 data_row (item_t *data_ptr, int columns_count)
00038 : data_ptr (data_ptr)
00039 , columns_count (columns_count)
00040 {
00041 }
00042
00043 public:
00044
00045 data_row ()
00046 : data_ptr (0)
00047 , columns_count (0)
00048 {
00049 }
00050
00051 data_row (const this_t &row)
00052 {
00053 *this = row;
00054 }
00055 data_row &operator= (const this_t &row)
00056 {
00057 if (this != &row)
00058 {
00059 data_ptr = row.data_ptr;
00060 columns_count = row.columns_count;
00061 }
00062 return *this;
00063 }
00064
00065 inline item_t &operator[] (int column_index)
00066 {
00067 BS_ASSERT (column_index < columns_count);
00068 BS_ASSERT (column_index >= 0);
00069 BS_ASSERT (data_ptr);
00070 #ifdef _DEBUG
00071 static item_t dummy = 0.0;
00072
00073 if (column_index >= 0 && column_index < columns_count && data_ptr)
00074 return data_ptr[column_index];
00075
00076 throw bs_exception ("data_row", "out of range");
00077 return dummy;
00078 #else
00079 return data_ptr[column_index];
00080 #endif
00081 }
00082 inline const item_t &operator[] (int column_index) const
00083 {
00084 BS_ASSERT (column_index < columns_count);
00085 BS_ASSERT (column_index >= 0);
00086 BS_ASSERT (data_ptr);
00087 #ifdef _DEBUG
00088 static item_t dummy = 0.0;
00089
00090 if (column_index >= 0 && column_index < columns_count && data_ptr)
00091 return data_ptr[column_index];
00092
00093 throw bs_exception ("data_row", "out of range");
00094 return dummy;
00095 #else
00096 return data_ptr[column_index];
00097 #endif
00098 }
00099
00100 private:
00101
00102 item_t *data_ptr;
00103 int columns_count;
00104
00105 };
00106
00107 template <typename strategy_t>
00108 class data_group
00109 {
00110 public:
00111 typedef typename strategy_t::item_t item_t;
00112 typedef typename strategy_t::item_array_t item_array_t;
00113
00114 typedef data_group<strategy_t> this_t;
00115 typedef data_row<strategy_t> data_row_t;
00116
00117 private:
00118
00119 friend class table_2d <strategy_t>;
00120
00121 public:
00122 data_group (item_t *data_ptr = 0, int rows_count = 0, int columns_count = 0)
00123 : data_ptr (data_ptr)
00124 , rows_count (rows_count)
00125 , columns_count (columns_count)
00126 {
00127 row_size = columns_count;
00128 }
00129
00130 inline void set_rows_count (int count)
00131 {
00132 rows_count = count;
00133 }
00134 inline void set_data_ptr (item_t *ptr)
00135 {
00136 data_ptr = ptr;
00137 }
00138
00139 public:
00140
00141 data_group (const this_t & group)
00142 {
00143 *this = group;
00144 }
00145 this_t &operator= (const this_t &group)
00146 {
00147 if (this != &group)
00148 {
00149 data_ptr = group.data_ptr;
00150 rows_count = group.rows_count;
00151 columns_count = group.columns_count;
00152 row_size = group.row_size;
00153 }
00154
00155 return *this;
00156 }
00157
00158 inline data_row_t get_row (int row_index) const
00159 {
00160 #ifdef _DEBUG
00161 if (row_index >= 0 && row_index < rows_count)
00162 return data_row_t (data_ptr + row_index * row_size, columns_count);
00163
00164 throw bs_exception ("data_row", "out of range");
00165 #else
00166 return data_row_t (data_ptr + row_index * row_size, columns_count);
00167 #endif
00168 }
00169
00170 inline int get_rows_count () const
00171 {
00172 return rows_count;
00173 }
00174 inline int get_columns_count () const
00175 {
00176 return columns_count;
00177 }
00178
00179 inline void set_columns_count (int count)
00180 {
00181 columns_count = count;
00182 row_size = columns_count;
00183 }
00184
00185 private:
00186
00187 item_t *data_ptr;
00188 int rows_count;
00189 int columns_count;
00190 int row_size;
00191
00192 };
00193
00194 template <typename strategy_t>
00195 class data_row_push_back
00196 {
00197 public:
00198 typedef typename strategy_t::item_t item_t;
00199 typedef typename strategy_t::item_array_t item_array_t;
00200
00201 typedef data_row_push_back <strategy_t> this_t;
00202
00203 private:
00204 friend class table_2d <strategy_t>;
00205
00206 data_row_push_back (item_t *data_ptr, int columns_count)
00207 : data_ptr (data_ptr)
00208 , columns_count (columns_count)
00209 {
00210
00211 }
00212
00213 public:
00214
00215 this_t &push_back (int column_index, item_t value)
00216 {
00217 BS_ASSERT (data_ptr);
00218 BS_ASSERT (column_index < columns_count);
00219 BS_ASSERT (column_index >= 0);
00220
00221 if (column_index >= 0 && column_index < columns_count)
00222 data_ptr[column_index] = value;
00223
00224 return *this;
00225 }
00226
00227 private:
00228
00229
00230 item_t *data_ptr;
00231 int columns_count;
00232
00233 };
00234
00235 template <typename strategy_t>
00236 class table_2d
00237 {
00238 public:
00239
00240 typedef typename strategy_t::item_t item_t;
00241 typedef typename strategy_t::item_array_t item_array_t;
00242
00243 typedef typename strategy_t::item_t index_t;
00244
00245 typedef data_group <strategy_t> data_group_t;
00246 typedef data_row_push_back <strategy_t> data_row_push_back_t;
00247
00248 table_2d (int group_count)
00249 : rows_count (0)
00250 {
00251 for (int i = 0; i < group_count; ++i)
00252 {
00253 group_list.push_back (data_group_t (0, 0, 0));
00254 }
00255 }
00256
00257 inline void init_dependent (int dependent_rows_count)
00258 {
00259 BS_ASSERT (dependent_rows_count);
00260
00261 int column_count = 0;
00262 for (int i = 1, cnt = (int)group_list.size (); i < cnt; i++)
00263 {
00264 column_count += group_list[i].get_columns_count ();
00265 }
00266
00267 BS_ASSERT (column_count);
00268 BS_ASSERT (data.size ());
00269
00270 if (data.empty ())
00271 {
00272
00273 BS_ASSERT (false);
00274 throw bs_exception ("", "data is empty");
00275 }
00276
00277 data_t new_data;
00278 new_data.resize (data.size () + column_count * dependent_rows_count);
00279
00280 memset (&new_data[0], 0, sizeof (typename data_t::value_type) * new_data.size ());
00281 memcpy (&new_data[0], &data[0], sizeof (typename data_t::value_type) * data.size ());
00282
00283 data.swap (new_data);
00284 item_t *data_ptr = &data[0];
00285
00286 int rows_count_ = rows_count;
00287 for (int i = 0, cnt = (int)group_list.size (); i < cnt; i++)
00288 {
00289 data_group_t &group = group_list[i];
00290
00291 group.set_rows_count (rows_count_);
00292 group.set_data_ptr (data_ptr);
00293
00294 data_ptr += (rows_count_ * group.get_columns_count ());
00295 rows_count_ = dependent_rows_count;
00296 }
00297
00298 #ifdef _DEBUG
00299 item_t *last_data = &data[0] + data.size ();
00300 BS_ASSERT (data_ptr == last_data);
00301 #endif
00302 }
00303 inline void clear ()
00304 {
00305 data.clear ();
00306
00307 for (int i = 0, cnt = (int)group_list.size (); i < cnt; i++)
00308 {
00309 data_group_t &group = group_list[i];
00310
00311 group.set_rows_count (0);
00312 group.set_data_ptr (0);
00313 }
00314 }
00315
00316 inline data_group_t &get_data_group (int group_index)
00317 {
00318 BS_ASSERT (group_index < (int)group_list.size ());
00319 BS_ASSERT (group_index >= 0);
00320 #ifdef _DEBUG
00321 static data_group_t dummy(0, 0, 0);
00322
00323 if (group_index >= 0 && group_index < (int)group_list.size ())
00324 return group_list[group_index];
00325
00326 throw bs_exception ("data_row", "out of range");
00327 #else
00328 return group_list[group_index];
00329 #endif
00330 }
00331 inline const data_group_t &get_data_group (int group_index) const
00332 {
00333 BS_ASSERT (group_index < (int)group_list.size ());
00334 BS_ASSERT (group_index >= 0);
00335 #ifdef _DEBUG
00336 static data_group_t dummy(0, 0, 0);
00337
00338 if (group_index >= 0 && group_index < (int)group_list.size ())
00339 return group_list[group_index];
00340
00341 throw bs_exception ("data_row", "out of range");
00342 #else
00343 return group_list[group_index];
00344 #endif
00345 }
00346 inline data_group_t get_initial_group ()
00347 {
00348 data_group_t group (group_list[0]);
00349 item_t *data_ptr = &data[0];
00350
00351 group.set_rows_count (rows_count);
00352 group.set_data_ptr (data_ptr);
00353
00354 return group;
00355 }
00356
00357 inline int get_groups_count () const
00358 {
00359 return (int)group_list.size ();
00360 }
00361
00362 inline int get_data_rows_count () const
00363 {
00364 return (int)rows_count;
00365 }
00366
00367 inline data_row_push_back_t add_row ()
00368 {
00369 BS_ASSERT (group_list.size ());
00370
00371 rows_count += 1;
00372 data.resize (rows_count * group_list[0].get_columns_count ());
00373
00374 return data_row_push_back_t (&data[0] + data.size () - group_list[0].get_columns_count (), group_list[0].get_columns_count ());
00375 }
00376
00377 private:
00378
00379 typedef item_array_t data_t;
00380 typedef seq_vector <data_group_t> group_list_t;
00381
00382 data_t data;
00383 group_list_t group_list;
00384 index_t rows_count;
00385 };
00386
00387
00388 }
00389 }
00390
00391
00392 #endif // #ifndef BS_TABLE_2D_H_