00001 #ifndef AMORPH_CLASS
00002 #define AMORPH_CLASS
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "object_packers.h"
00019
00020 #include <basis/astring.h>
00021 #include <basis/functions.h>
00022 #include <basis/contracts.h>
00023 #include <basis/guards.h>
00024
00026
00055 namespace structures {
00056
00057 template <class contents>
00058 class amorph : private basis::array<contents *>
00059 {
00060 public:
00061 amorph(int elements = 0);
00063
00064 ~amorph();
00065
00066 int elements() const { return this->length(); }
00068
00069 int valid_fields() const { return _fields_used; }
00071
00073 void adjust(int new_max);
00075
00079 void reset(int new_maximum = 0);
00081
00082 basis::outcome put(int field, const contents *data);
00084
00090 basis::outcome append(const contents *data);
00092
00095 basis::outcome operator += (const contents *data) { return append(data); }
00097
00099
00101 const contents *get(int field) const;
00103
00105 contents *borrow(int field);
00106
00108 const contents *operator [] (int field) const { return get(field); }
00110 contents *operator [] (int field) { return borrow(field); }
00111
00112 contents *acquire(int field);
00114
00121 basis::outcome clear(int field);
00123
00127 void clear_all();
00129
00130 basis::outcome zap(int start, int end);
00132
00140 basis::outcome insert(int position, int lines_to_add);
00142
00146 int find_empty(basis::outcome &o) const;
00148
00150 const contents *next_valid(int &field) const;
00152
00156 int find(const contents *to_locate, basis::outcome &o);
00158
00163 void swap_contents(amorph<contents> &other);
00165
00168 private:
00169 int _fields_used;
00170
00171 void check_fields(const char *where) const;
00173
00175 void set_nil(int start, int end);
00176
00180
00181
00182
00183 amorph(const amorph &to_copy) {}
00184 amorph &operator = (const amorph &to_copy) { return *this; }
00186 };
00187
00189
00190
00191
00192
00193
00195
00197
00198 template <class contents>
00199 void amorph_assign(amorph<contents> &to_assign,
00200 const amorph<contents> &to_copy);
00201
00203
00205
00211 template <class contents>
00212 void amorph_pack(basis::byte_array &packed_form, const amorph<contents> &to_pack);
00213
00215 template <class contents>
00216 bool amorph_unpack(basis::byte_array &packed_form, amorph<contents> &to_unpack);
00217
00219 template <class contents>
00220 int amorph_packed_size(const amorph<contents> &to_pack);
00221
00222
00223
00224
00225
00226
00227 #undef static_class_name
00228 #define static_class_name() "amorph"
00229
00230
00231 #undef AMO_ALERT
00232 #ifdef DEBUG_AMORPH
00233 #include <basis/astring.h>
00234 #define AMO_ALERT(a, b, c) basis::throw_error(basis::astring(a), basis::astring(func), basis::astring(b) + " -- " + c)
00235 #define CHECK_FIELDS check_fields(func)
00236 #else
00237 #define AMO_ALERT(a1, a2, a3) {}
00238 #define CHECK_FIELDS { if (!func) {} }
00239 #endif
00240
00242
00243 template <class contents>
00244 amorph<contents>::amorph(int elements)
00245 : basis::array<contents *>(elements, NIL, basis::array<contents *>::SIMPLE_COPY
00246 | basis::array<contents *>::EXPONE | basis::array<contents *>::FLUSH_INVISIBLE),
00247 _fields_used(0)
00248 {
00249 FUNCDEF("constructor");
00250 set_nil(0, elements - 1);
00251 CHECK_FIELDS;
00252 }
00253
00254 template <class contents>
00255 amorph<contents>::~amorph()
00256 {
00257 FUNCDEF("destructor");
00258 CHECK_FIELDS;
00259 clear_all();
00260 }
00261
00262 template <class contents>
00263 void amorph<contents>::set_nil(int start, int end)
00264 {
00265 for (int i = start; i <= end; i++)
00266 basis::array<contents *>::put(i, (contents *)NIL);
00267 }
00268
00269 template <class contents>
00270 void amorph<contents>::check_fields(const char *where) const
00271 {
00272 FUNCDEF("check_fields");
00273 int counter = 0;
00274 for (int i = 0; i < elements(); i++)
00275 if (basis::array<contents *>::get(i)) counter++;
00276 if (_fields_used != counter) {
00277 AMO_ALERT("amorph", basis::a_sprintf("check_fields for %s", where),
00278 "error in _fields_used count");
00279 }
00280 }
00281
00282 template <class contents>
00283 void amorph<contents>::reset(int new_maximum)
00284 {
00285 FUNCDEF("reset");
00286 CHECK_FIELDS;
00287 adjust(new_maximum);
00288 clear_all();
00289 }
00290
00291 template <class contents>
00292 void amorph<contents>::clear_all()
00293 {
00294 FUNCDEF("clear_all");
00295 CHECK_FIELDS;
00296 for (int i = 0; i < elements(); i++) clear(i);
00297 }
00298
00299 template <class contents>
00300 basis::outcome amorph<contents>::append(const contents *data)
00301 {
00302 FUNCDEF("append");
00303 CHECK_FIELDS;
00304 adjust(elements() + 1);
00305 return put(elements() - 1, (contents *)data);
00306 }
00307
00308 template <class contents>
00309 const contents *amorph<contents>::get(int field) const
00310 {
00311 FUNCDEF("get");
00312 CHECK_FIELDS;
00313 bounds_return(field, 0, elements() - 1, NIL);
00314 return basis::array<contents *>::observe()[field];
00315 }
00316
00317 template <class contents>
00318 void amorph<contents>::adjust(int new_maximum)
00319 {
00320 FUNCDEF("adjust");
00321 CHECK_FIELDS;
00322 if (new_maximum < 0) return;
00323 int old_max = elements();
00324 if (new_maximum == old_max) return;
00325 if (new_maximum < old_max) {
00326
00327 zap(new_maximum, old_max - 1);
00328
00329 return;
00330 }
00331
00332
00333 int new_fields = new_maximum - old_max;
00334
00335 basis::array<contents *>::insert(old_max, new_fields);
00336 for (int i = old_max; i < new_maximum; i++) {
00337 basis::array<contents *>::put(i, NIL);
00338 }
00339 }
00340
00341 template <class contents>
00342 basis::outcome amorph<contents>::insert(int position, int lines_to_add)
00343 {
00344 FUNCDEF("insert");
00345 CHECK_FIELDS;
00346 bounds_return(position, 0, elements(), basis::common::OUT_OF_RANGE);
00347 basis::outcome o = basis::array<contents *>::insert(position, lines_to_add);
00348 if (o != basis::common::OKAY) return basis::common::OUT_OF_RANGE;
00349 set_nil(position, position + lines_to_add - 1);
00350 return basis::common::OKAY;
00351 }
00352
00353 template <class contents>
00354 basis::outcome amorph<contents>::zap(int start_index, int end_index)
00355 {
00356 FUNCDEF("zap");
00357 CHECK_FIELDS;
00358 bounds_return(start_index, 0, elements() - 1, basis::common::OUT_OF_RANGE);
00359 bounds_return(end_index, 0, elements() - 1, basis::common::OUT_OF_RANGE);
00360 if (end_index < start_index) return basis::common::OKAY;
00361 for (int i = start_index; i <= end_index; i++) clear(i);
00362 basis::outcome o = basis::array<contents *>::zap(start_index, end_index);
00363 return (o == basis::common::OKAY? basis::common::OKAY : basis::common::OUT_OF_RANGE);
00364 }
00365
00366 template <class contents>
00367 basis::outcome amorph<contents>::put(int field, const contents *data)
00368 {
00369 FUNCDEF("put");
00370 CHECK_FIELDS;
00371 bounds_return(field, 0, elements() - 1, basis::common::OUT_OF_RANGE);
00372 contents *to_whack = acquire(field);
00373 WHACK(to_whack);
00374 if (data) {
00375 basis::array<contents *>::access()[field] = (contents *)data;
00376 _fields_used++;
00377 }
00378 return basis::common::OKAY;
00379 }
00380
00381 template <class contents>
00382 int amorph<contents>::find_empty(basis::outcome &o) const
00383 {
00384 FUNCDEF("find_empty");
00385 CHECK_FIELDS;
00386 if (_fields_used == elements()) { o = basis::common::IS_FULL; return 0; }
00387 for (int i = 0; i < elements(); i++)
00388 if (!basis::array<contents *>::get(i)) { o = basis::common::OKAY; return i; }
00389 AMO_ALERT("amorph", "empty", "_fields_used is incorrect");
00390 return basis::common::IS_FULL;
00391 }
00392
00393 template <class contents>
00394 const contents *amorph<contents>::next_valid(int &field) const
00395 {
00396 FUNCDEF("next_valid");
00397 CHECK_FIELDS;
00398 bounds_return(field, 0, elements() - 1, NIL);
00399 for (int i = field; i < elements(); i++)
00400 if (basis::array<contents *>::get(i)) {
00401 field = i;
00402 return basis::array<contents *>::get(i);
00403 }
00404 return NIL;
00405 }
00406
00407 template <class contents>
00408 basis::outcome amorph<contents>::clear(int field)
00409 {
00410 FUNCDEF("clear");
00411 CHECK_FIELDS;
00412 return this->put(field, NIL);
00413 }
00414
00415 template <class contents>
00416 contents *amorph<contents>::acquire(int field)
00417 {
00418 FUNCDEF("acquire");
00419 CHECK_FIELDS;
00420 contents *to_return = borrow(field);
00421 if (to_return) {
00422 _fields_used--;
00423 basis::array<contents *>::access()[field] = NIL;
00424 }
00425 return to_return;
00426 }
00427
00428 template <class contents>
00429 int amorph<contents>::find(const contents *to_locate, basis::outcome &o)
00430 {
00431 FUNCDEF("find");
00432 CHECK_FIELDS;
00433 if (!_fields_used) { o = basis::common::NOT_FOUND; return 0; }
00434 for (int i = 0; i < elements(); i++) {
00435 if (basis::array<contents *>::get(i) == to_locate) {
00436 o = basis::common::OKAY;
00437 return i;
00438 }
00439 }
00440 o = basis::common::NOT_FOUND;
00441 return 0;
00442 }
00443
00444 template <class contents>
00445 contents *amorph<contents>::borrow(int field)
00446 {
00447 FUNCDEF("borrow");
00448 CHECK_FIELDS;
00449 bounds_return(field, 0, elements() - 1, NIL);
00450 return basis::array<contents *>::access()[field];
00451 }
00452
00453 template <class contents>
00454 void amorph<contents>::swap_contents(amorph<contents> &other)
00455 {
00456 FUNCDEF("swap_contents");
00457 CHECK_FIELDS;
00458 int hold_fields = _fields_used;
00459 _fields_used = other._fields_used;
00460 other._fields_used = hold_fields;
00461 this->basis::array<contents *>::swap_contents(other);
00462 }
00463
00464 template <class contents>
00465 int amorph_packed_size(const amorph<contents> &to_pack)
00466 {
00467 int parts_size = 0;
00468 for (int i = 0; i < to_pack.elements(); i++) {
00469 const contents *current = to_pack.get(i);
00470 if (current) parts_size += current->packed_size();
00471 }
00472 return PACKED_SIZE_INT32 + parts_size;
00473 }
00474
00475 template <class contents>
00476 void amorph_pack(basis::byte_array &packed_form, const amorph<contents> &to_pack)
00477 {
00478 structures::attach(packed_form, to_pack.elements());
00479 for (int i = 0; i < to_pack.elements(); i++) {
00480 const contents *current = to_pack.get(i);
00481 if (current) current->pack(packed_form);
00482 }
00483 }
00484
00485 template <class contents>
00486 bool amorph_unpack(basis::byte_array &packed_form, amorph<contents> &to_unpack)
00487 {
00488 to_unpack.reset();
00489 int elem = 0;
00490 if (!structures::detach(packed_form, elem)) return false;
00491 for (int i = 0; i < elem; i++) {
00492 contents *to_add = new contents;
00493 if (!to_add->unpack(packed_form)) { delete to_add; return false; }
00494 to_unpack.append(to_add);
00495 }
00496 return true;
00497 }
00498
00499 template <class contents>
00500 void amorph_assign(amorph<contents> &to_assign,
00501 const amorph<contents> &to_copy)
00502 {
00503 if (&to_assign == &to_copy) return;
00504 to_assign.clear_all();
00505 if (to_assign.elements() != to_copy.elements()) {
00506 to_assign.zap(0, to_assign.elements() - 1);
00507 to_assign.insert(0, to_copy.elements());
00508 }
00509 for (int i = 0; i < to_assign.elements(); i++) {
00510 if (to_copy.get(i)) to_assign.put(i, new contents(*to_copy.get(i)));
00511 else to_assign.put(i, (contents *)NIL);
00512 }
00513 }
00514
00515 #undef static_class_name
00516
00517 }
00518
00519 #endif
00520