amorph.cpp

Go to the documentation of this file.
00001 #ifndef AMORPH_IMPLEMENTATION
00002 #define AMORPH_IMPLEMENTATION
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : amorph                                                            *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 1989-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
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 //#define DEBUG_AMORPH
00026   // uncomment to enable more testing, as well as complaints on errors.
00027 
00028 #undef static_class_name
00029 #define static_class_name() "amorph"
00030   // used in bounds_halt macro.
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;  // bad input here.
00123   int old_max = elements();
00124   if (new_maximum == old_max) return;  // nothing to do.
00125   if (new_maximum < old_max) {
00126     // removes the elements beyond the new size of the amorph.
00127     zap(new_maximum, old_max - 1);
00128     // we're done tuning it.
00129     return;
00130   }
00131 
00132   // we get to here if we need more space than we used to.
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 

Generated on Wed Nov 19 04:28:47 2008 for HOOPLE Libraries by  doxygen 1.5.1