00001 #ifndef AMORPH_IMPLEMENTATION
00002 #define AMORPH_IMPLEMENTATION
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "amorph.h"
00019
00020 #include <basis/array.cpp>
00021 #include <basis/function.h>
00022 #include <basis/guards.h>
00023 #include <basis/packable.h>
00024
00025
00026
00027
00028 #undef static_class_name
00029 #define static_class_name() "amorph"
00030
00031
00032 #undef AMO_ALERT
00033 #ifdef DEBUG_AMORPH
00034 #include <basis/istring.h>
00035 #define AMO_ALERT(a, b, c) continuable_error(a, b, c)
00036 #define CHECK_FIELDS check_fields(func)
00037 #else
00038 #define AMO_ALERT(a1, a2, a3) {}
00039 #define CHECK_FIELDS {}
00040 #endif
00041
00043
00044 template <class contents>
00045 amorph<contents>::amorph(int elements)
00046 : array<contents *>(elements, NIL, array<contents *>::SIMPLE_COPY
00047 | array<contents *>::EXPONE | array<contents *>::FLUSH_INVISIBLE),
00048 _fields_used(0)
00049 {
00050 FUNCDEF("constructor");
00051 set_nil(0, elements - 1);
00052 CHECK_FIELDS;
00053 }
00054
00055 template <class contents>
00056 amorph<contents>::~amorph()
00057 {
00058 FUNCDEF("destructor");
00059 CHECK_FIELDS;
00060 clear_all();
00061 }
00062
00063 template <class contents>
00064 void amorph<contents>::set_nil(int start, int end)
00065 {
00066 for (int i = start; i <= end; i++)
00067 array<contents *>::put(i, (contents *)NIL);
00068 }
00069
00070 template <class contents>
00071 void amorph<contents>::check_fields(const char *where) const
00072 {
00073 FUNCDEF("check_fields");
00074 int counter = 0;
00075 for (int i = 0; i < elements(); i++)
00076 if (array<contents *>::get(i)) counter++;
00077 if (_fields_used != counter)
00078 AMO_ALERT("amorph", isprintf("check_fields for %s", where).s(),
00079 "error in _fields_used count");
00080 }
00081
00082 template <class contents>
00083 void amorph<contents>::reset(int new_maximum)
00084 {
00085 FUNCDEF("reset");
00086 CHECK_FIELDS;
00087 adjust(new_maximum);
00088 clear_all();
00089 }
00090
00091 template <class contents>
00092 void amorph<contents>::clear_all()
00093 {
00094 FUNCDEF("clear_all");
00095 CHECK_FIELDS;
00096 for (int i = 0; i < elements(); i++) clear(i);
00097 }
00098
00099 template <class contents>
00100 outcome amorph<contents>::append(const contents *data)
00101 {
00102 FUNCDEF("append");
00103 CHECK_FIELDS;
00104 adjust(elements() + 1);
00105 return put(elements() - 1, (contents *)data);
00106 }
00107
00108 template <class contents>
00109 const contents *amorph<contents>::get(int field) const
00110 {
00111 FUNCDEF("get");
00112 CHECK_FIELDS;
00113 bounds_return(field, 0, elements() - 1, NIL);
00114 return array<contents *>::observe()[field];
00115 }
00116
00117 template <class contents>
00118 void amorph<contents>::adjust(int new_maximum)
00119 {
00120 FUNCDEF("adjust");
00121 CHECK_FIELDS;
00122 if (new_maximum < 0) return;
00123 int old_max = elements();
00124 if (new_maximum == old_max) return;
00125 if (new_maximum < old_max) {
00126
00127 zap(new_maximum, old_max - 1);
00128
00129 return;
00130 }
00131
00132
00133 int new_fields = new_maximum - old_max;
00134
00135 array<contents *>::insert(old_max, new_fields);
00136 for (int i = old_max; i < new_maximum; i++) {
00137 array<contents *>::put(i, NIL);
00138 }
00139 }
00140
00141 template <class contents>
00142 outcome amorph<contents>::insert(int position, int lines_to_add)
00143 {
00144 FUNCDEF("insert");
00145 CHECK_FIELDS;
00146 bounds_return(position, 0, elements(), common::OUT_OF_RANGE);
00147 outcome outcome = array<contents *>::insert(position, lines_to_add);
00148 if (outcome != common::OKAY) return common::OUT_OF_RANGE;
00149 set_nil(position, position + lines_to_add - 1);
00150 return common::OKAY;
00151 }
00152
00153 template <class contents>
00154 outcome amorph<contents>::zap(int start_index, int end_index)
00155 {
00156 FUNCDEF("zap");
00157 CHECK_FIELDS;
00158 bounds_return(start_index, 0, elements() - 1, common::OUT_OF_RANGE);
00159 bounds_return(end_index, 0, elements() - 1, common::OUT_OF_RANGE);
00160 if (end_index < start_index) return common::OKAY;
00161 for (int i = start_index; i <= end_index; i++) clear(i);
00162 outcome outcome = array<contents *>::zap(start_index, end_index);
00163 return (outcome==common::OKAY? common::OKAY : common::OUT_OF_RANGE);
00164 }
00165
00166 template <class contents>
00167 outcome amorph<contents>::put(int field, const contents *data)
00168 {
00169 FUNCDEF("put");
00170 CHECK_FIELDS;
00171 bounds_return(field, 0, elements() - 1, common::OUT_OF_RANGE);
00172 contents *to_whack = acquire(field);
00173 WHACK(to_whack);
00174 if (data) {
00175 array<contents *>::access()[field] = (contents *)data;
00176 _fields_used++;
00177 }
00178 return common::OKAY;
00179 }
00180
00181 template <class contents>
00182 int amorph<contents>::find_empty(outcome &outcome) const
00183 {
00184 FUNCDEF("find_empty");
00185 CHECK_FIELDS;
00186 if (_fields_used == elements()) { outcome = common::IS_FULL; return 0; }
00187 for (int i = 0; i < elements(); i++)
00188 if (!array<contents *>::get(i)) { outcome = common::OKAY; return i; }
00189 AMO_ALERT("amorph", "empty", "_fields_used is incorrect");
00190 return common::IS_FULL;
00191 }
00192
00193 template <class contents>
00194 const contents *amorph<contents>::next_valid(int &field) const
00195 {
00196 FUNCDEF("next_valid");
00197 CHECK_FIELDS;
00198 bounds_return(field, 0, elements() - 1, NIL);
00199 for (int i = field; i < elements(); i++)
00200 if (array<contents *>::get(i)) {
00201 field = i;
00202 return array<contents *>::get(i);
00203 }
00204 return NIL;
00205 }
00206
00207 template <class contents>
00208 outcome amorph<contents>::clear(int field)
00209 {
00210 FUNCDEF("clear");
00211 CHECK_FIELDS;
00212 return this->put(field, NIL);
00213 }
00214
00215 template <class contents>
00216 contents *amorph<contents>::acquire(int field)
00217 {
00218 FUNCDEF("acquire");
00219 CHECK_FIELDS;
00220 contents *to_return = borrow(field);
00221 if (to_return) {
00222 _fields_used--;
00223 array<contents *>::access()[field] = NIL;
00224 }
00225 return to_return;
00226 }
00227
00228 template <class contents>
00229 int amorph<contents>::find(const contents *to_locate, outcome &outcome)
00230 {
00231 FUNCDEF("find");
00232 CHECK_FIELDS;
00233 if (!_fields_used) { outcome = common::NOT_FOUND; return 0; }
00234 for (int i = 0; i < elements(); i++) {
00235 if (array<contents *>::get(i) == to_locate) {
00236 outcome = common::OKAY;
00237 return i;
00238 }
00239 }
00240 outcome = common::NOT_FOUND;
00241 return 0;
00242 }
00243
00244 template <class contents>
00245 contents *amorph<contents>::borrow(int field)
00246 {
00247 FUNCDEF("borrow");
00248 CHECK_FIELDS;
00249 bounds_return(field, 0, elements() - 1, NIL);
00250 return array<contents *>::access()[field];
00251 }
00252
00253 template <class contents>
00254 void amorph<contents>::swap_contents(amorph<contents> &other)
00255 {
00256 FUNCDEF("swap_contents");
00257 CHECK_FIELDS;
00258 int hold_fields = _fields_used;
00259 _fields_used = other._fields_used;
00260 other._fields_used = hold_fields;
00261 this->array<contents *>::swap_contents(other);
00262 }
00263
00264 template <class contents>
00265 void amorph_pack(byte_array &packed_form, const amorph<contents> &to_pack)
00266 {
00267 basis::attach(packed_form, to_pack.elements());
00268 for (int i = 0; i < to_pack.elements(); i++) {
00269 to_pack.get(i)->pack(packed_form);
00270 }
00271 }
00272
00273 template <class contents>
00274 bool amorph_unpack(byte_array &packed_form, amorph<contents> &to_unpack)
00275 {
00276 to_unpack.reset();
00277 int elem = 0;
00278 if (!basis::detach(packed_form, elem)) return false;
00279 for (int i = 0; i < elem; i++) {
00280 contents *to_add = new contents;
00281 if (!to_add->unpack(packed_form)) { delete to_add; return false; }
00282 to_unpack.append(to_add);
00283 }
00284 return true;
00285 }
00286
00287 template <class contents>
00288 void amorph_assign(amorph<contents> &to_assign,
00289 const amorph<contents> &to_copy)
00290 {
00291 if (&to_assign == &to_copy) return;
00292 to_assign.clear_all();
00293 if (to_assign.elements() != to_copy.elements()) {
00294 to_assign.zap(0, to_assign.elements() - 1);
00295 to_assign.insert(0, to_copy.elements());
00296 }
00297 for (int i = 0; i < to_assign.elements(); i++) {
00298 if (to_copy.get(i)) to_assign.put(i, new contents(*to_copy.get(i)));
00299 else to_assign.put(i, (contents *)NIL);
00300 }
00301 }
00302
00303 #undef static_class_name
00304
00305 #endif
00306