oqlinline.h

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 //#define DEST_TRACE
00026 
00027 struct gbLink {
00028   oqmlAtom *at;
00029   oqmlAtomList *atlist;
00030 
00031   gbLink *prev, *next;
00032 
00033   inline gbLink(oqmlAtom *_at) {at = _at; atlist = 0;prev=next=0;}
00034   inline gbLink(oqmlAtomList *_atlist) {atlist = _atlist; at = 0;prev=next=0;}
00035 };
00036 
00037 //#define GB_TRACE
00038 
00039 #ifdef GB_TRACE
00040 extern int GB_COUNT;
00041 extern int BR_CND;
00042 extern void break_now();
00043 #endif
00044 
00045 inline gbLink *oqmlGarbManager::add_realize(gbLink *link)
00046 {
00047   if (last) {
00048     last->next = link;
00049     link->prev = last;
00050     last = link;
00051   }
00052   else
00053     first = last = link;
00054 
00055   count++;
00056 #ifdef GB_TRACE
00057   printf("creating %s link=%p ptr=%p [%d]\n",
00058          link->at ? "atom" : "list",
00059          link,
00060          link->at ? (void *)link->at : (void *)link->atlist,
00061          GB_COUNT);
00062   if (BR_CND && GB_COUNT == BR_CND)
00063     break_now();
00064   GB_COUNT++;
00065 #endif
00066   return link;
00067 }
00068 
00069 inline gbLink *oqmlGarbManager::add(oqmlAtom *at)
00070 {
00071   gbLink *link = new gbLink(at);
00072   return add_realize(link);
00073 }
00074 
00075 inline gbLink *oqmlGarbManager::add(oqmlAtomList *atlist)
00076 {
00077   gbLink *link = new gbLink(atlist);
00078   return add_realize(link);
00079 }
00080 
00081 inline void oqmlGarbManager::add(char *s)
00082 {
00083   str_list.insertObject(s);
00084 }
00085 
00086 extern void break_now();
00087 
00088 inline void oqmlGarbManager::remove(gbLink *link)
00089 {
00090   if (!link)
00091     return;
00092 
00093   if (!garbaging) {
00094 
00095     std::list<gbContext *>::iterator begin = ctx_l.begin();
00096     std::list<gbContext *>::iterator end = ctx_l.end();
00097     while (begin != end) {
00098       if ((*begin)->link == link)
00099         (*begin)->link = link->next;    
00100       ++begin;
00101     }
00102 
00103     if (link->prev)
00104       link->prev->next = link->next;
00105     if (link->next)
00106       link->next->prev = link->prev;
00107 
00108     if (last == link)
00109       last = link->prev;
00110     if (first == link)
00111       first = link->next;
00112 
00113     count--;
00114 #ifdef GB_TRACE
00115     printf("removing %s link %p\n",
00116            link->at ? "atom" : "list",
00117            link->at ? (void *)link->at : (void *)link->atlist);
00118 #endif
00119     delete link;
00120   }
00121 #ifdef GB_TRACE
00122   else
00123     printf("NOT removing %s link %p\n",
00124            link->at ? "atom" : "list",
00125            link->at ? (void *)link->at : (void *)link->atlist);
00126 #endif
00127 }
00128 
00129 inline oqmlAtom::oqmlAtom()
00130 {
00131   type.comp = oqml_False;
00132   next = 0;
00133   refcnt = 0;
00134   recurs = oqml_False;
00135   link = oqmlGarbManager::add(this);
00136   string = (char *)0;
00137 #ifdef DEST_TRACE
00138   printf("new atom %p\n", this);
00139 #endif
00140 }
00141 
00142 inline oqmlAtom_oid::oqmlAtom_oid(const Oid &_oid, Class *_class) :
00143      oqmlAtom()
00144 {
00145   type.type = oqmlATOM_OID;
00146   type.cls = _class;
00147   oid = _oid;
00148 }
00149 
00150 inline oqmlAtom_obj::oqmlAtom_obj(Object *_o, pointer_int_t _idx,
00151                                   const Class *_class) : oqmlAtom()
00152 {
00153   type.type = oqmlATOM_OBJ;
00154   type.cls = (Class *)_class;
00155   o = _o;
00156   idx = _idx;
00157   //printf("oqmlAtom_obj(%p, %p, %d)\n", this, o, idx);
00158 }
00159 
00160 inline oqmlAtom_bool::oqmlAtom_bool(oqmlBool _b) : oqmlAtom()
00161 {
00162   type.type = oqmlATOM_BOOL;
00163   type.cls = 0;
00164   b = _b;
00165 }
00166 
00167 inline oqmlAtom_nil::oqmlAtom_nil() : oqmlAtom()
00168 {
00169   type.type = oqmlATOM_NIL;
00170   type.cls = 0;
00171 }
00172 
00173 inline oqmlAtom_null::oqmlAtom_null() : oqmlAtom()
00174 {
00175   type.type = oqmlATOM_NULL;
00176   type.cls = 0;
00177 }
00178 
00179 inline oqmlAtom_int::oqmlAtom_int(eyedblib::int64 _i) : oqmlAtom()
00180 {
00181   type.type = oqmlATOM_INT;
00182   type.cls = 0;
00183   i = _i;
00184 }
00185 
00186 inline oqmlAtom_char::oqmlAtom_char(char _c) : oqmlAtom()
00187 {
00188   type.type = oqmlATOM_CHAR;
00189   type.cls = 0;
00190   c = _c;
00191 }
00192 
00193 inline oqmlAtom_string::oqmlAtom_string(const char *s) : oqmlAtom()
00194 {
00195   type.type = oqmlATOM_STRING;
00196   type.cls = 0;
00197   type.comp = oqml_True;
00198 
00199   shstr = new oqmlSharedString(s);
00200 }
00201 
00202 inline
00203 oqmlSharedString::oqmlSharedString(const char *_s)
00204 {
00205   refcnt = 1;
00206   s = strdup(_s);
00207   len = -1;
00208 }
00209 
00210 inline void
00211 oqmlSharedString::set(const char *_s)
00212 {
00213   free(s);
00214   s = strdup(_s);
00215   len = -1;
00216 }
00217 
00218 inline int
00219 oqmlSharedString::getLen() const
00220 {
00221   return len >= 0 ? len : (const_cast<oqmlSharedString *>(this)->len = strlen(s));
00222 }
00223 
00224 inline
00225 oqmlSharedString::~oqmlSharedString()
00226 {
00227   free(s);
00228 }
00229 
00230 inline int
00231 oqmlAtom_string::getLen() const
00232 {
00233   return shstr->getLen();
00234 }
00235 
00236 inline oqmlAtom_string::oqmlAtom_string(oqmlSharedString *_shstr) :
00237  oqmlAtom()
00238 {
00239   type.type = oqmlATOM_STRING;
00240   type.cls = 0;
00241   type.comp = oqml_True;
00242 
00243   shstr = _shstr;
00244   shstr->refcnt++;
00245 }
00246 
00247 inline oqmlAtom_struct::oqmlAtom_struct()
00248 {
00249   attr = 0;
00250   attr_cnt = 0;
00251 }
00252 
00253 inline oqmlAtom_struct::oqmlAtom_struct(oqml_StructAttr *_attr,
00254                                         int _attr_cnt)
00255 {
00256   type.type = oqmlATOM_STRUCT;
00257   type.cls = 0;
00258   type.comp = oqml_False;
00259   attr_cnt = _attr_cnt;
00260   attr = _attr;
00261 }
00262 
00263 inline oqmlAtom_ident::oqmlAtom_ident(const char *ident,
00264                                       oqmlSymbolEntry *_entry) : oqmlAtom()
00265 {
00266   entry = _entry;
00267   if (entry) entry->addEntry(this);
00268   type.type = oqmlATOM_IDENT;
00269   type.cls = 0;
00270   type.comp = oqml_False;
00271 
00272   shstr = new oqmlSharedString(ident);
00273 }
00274 
00275 inline oqmlAtom_ident::oqmlAtom_ident(oqmlSharedString *_shstr,
00276                                       oqmlSymbolEntry *_entry) : oqmlAtom()
00277 {
00278   entry = _entry;
00279   if (entry) entry->addEntry(this);
00280   type.type = oqmlATOM_IDENT;
00281   type.cls = 0;
00282   type.comp = oqml_False;
00283 
00284   shstr = _shstr;
00285   shstr->refcnt++;
00286 }
00287 
00288 inline void oqmlAtom_ident::releaseEntry()
00289 {
00290   entry = 0;
00291 }
00292 
00293 inline oqmlAtom_double::oqmlAtom_double(double _d) : oqmlAtom()
00294 {
00295   type.type = oqmlATOM_DOUBLE;
00296   type.cls = 0;
00297   d = _d;
00298 }
00299 
00300 inline oqmlAtom_node::oqmlAtom_node(oqmlNode *_node) : oqmlAtom()
00301 {
00302   node = _node;
00303   type.type = oqmlATOM_NODE;
00304   type.cls = 0;
00305   evaluated = oqml_False;
00306 //  list = 0;
00307 }
00308 
00309 inline oqmlAtom *oqmlAtom_node::copy()
00310 {
00311   return new oqmlAtom_node(node);
00312 }
00313 
00314 inline oqmlAtom_select::oqmlAtom_select(oqmlNode *_node, oqmlNode *_node_orig) : oqmlAtom()
00315 {
00316   node = _node;
00317   node_orig = _node_orig;
00318   type.type = oqmlATOM_SELECT;
00319   type.cls = 0;
00320   evaluated = oqml_False;
00321   indexed = oqml_False;
00322   collatom = 0;
00323   list = 0;
00324   cpcnt = 0;
00325   for (int i = 0; i < OQML_MAX_CPS; i++)
00326     cplists[i] = 0;
00327 }
00328 
00329 inline oqmlAtom *oqmlAtom_select::copy()
00330 {
00331   return new oqmlAtom_select(node, node_orig);
00332 }
00333 
00334 inline oqmlAtom_coll::oqmlAtom_coll(oqmlAtomList *_list) : oqmlAtom()
00335 {
00336 #ifdef DEST_TRACE
00337   printf("new coll %p\n", this);
00338 #endif
00339   list = _list;
00340 }
00341 
00342 inline oqmlAtom_list::oqmlAtom_list(oqmlAtomList *_list) : oqmlAtom_coll(_list)
00343 {
00344   type.type = oqmlATOM_LIST;
00345   type.cls = 0;
00346 }
00347 
00348 inline oqmlAtom_set::oqmlAtom_set(oqmlAtomList *_list,
00349                                   oqmlBool _suppressDoubles) :
00350   oqmlAtom_coll(_list)
00351 {
00352   type.type = oqmlATOM_SET;
00353   type.cls = 0;
00354   if (_suppressDoubles)
00355     suppressDoubles();
00356 }
00357 
00358 inline oqmlAtom_bag::oqmlAtom_bag(oqmlAtomList *_list) : oqmlAtom_coll(_list)
00359 {
00360   type.type = oqmlATOM_BAG;
00361   type.cls = 0;
00362 }
00363 
00364 inline oqmlAtom_array::oqmlAtom_array(oqmlAtomList *_list) : oqmlAtom_coll(_list)
00365 {
00366   type.type = oqmlATOM_ARRAY;
00367   type.cls = 0;
00368 }
00369 
00370 inline oqmlAtom *oqmlAtom_oid::copy()
00371 {
00372   return new oqmlAtom_oid(oid, type.cls);
00373 }
00374 
00375 inline oqmlAtom *oqmlAtom_obj::copy()
00376 {
00377   //printf("copy obj %p %p %d\n", this, o, idx);
00378   //return new oqmlAtom_obj(o, idx);
00379   return oqmlObjectManager::registerObject(o);
00380 }
00381 
00382 inline Object *oqmlAtom_obj::getObject()
00383 {
00384   return o;
00385 }
00386 
00387 inline oqmlAtom *oqmlAtom_bool::copy()
00388 {
00389   return new oqmlAtom_bool(b);
00390 }
00391 
00392 inline oqmlAtom *oqmlAtom_nil::copy()
00393 {
00394   return new oqmlAtom_nil;
00395 }
00396 
00397 inline oqmlAtom *oqmlAtom_null::copy()
00398 {
00399   return new oqmlAtom_null;
00400 }
00401 
00402 inline oqmlAtom *oqmlAtom_int::copy()
00403 {
00404   return new oqmlAtom_int(i);
00405 }
00406 
00407 inline oqmlAtom *oqmlAtom_char::copy()
00408 {
00409   return new oqmlAtom_char(c);
00410 }
00411 
00412 #define SHARE
00413 
00414 inline oqmlAtom *oqmlAtom_string::copy()
00415 {
00416 #ifdef SHARE
00417   // 7/04/99: adding True to share the copied string
00418   return new oqmlAtom_string(shstr);
00419 #else
00420   return new oqmlAtom_string(s);
00421 #endif
00422 }
00423 
00424 inline oqmlAtom *oqmlAtom_ident::copy()
00425 {
00426 #ifdef SHARE
00427   // 7/04/99: adding True to share the copied string
00428   return new oqmlAtom_ident(shstr, entry);
00429 #else
00430   return new oqmlAtom_ident(ident, entry);
00431 #endif
00432 }
00433 
00434 inline oqmlAtom *oqmlAtom_double::copy()
00435 {
00436   return new oqmlAtom_double(d);
00437 }
00438 
00439 inline oqmlAtom *oqmlAtom_list::copy()
00440 {
00441   return new oqmlAtom_list(list);
00442 }
00443 
00444 inline oqmlAtom *oqmlAtom_set::copy()
00445 {
00446   return new oqmlAtom_set(list, oqml_False);
00447 }
00448 
00449 inline oqmlAtom *oqmlAtom_bag::copy()
00450 {
00451   return new oqmlAtom_bag(list);
00452 }
00453 
00454 inline oqmlAtom *oqmlAtom_array::copy()
00455 {
00456   return new oqmlAtom_array(list);
00457 }
00458 
00459 inline oqmlAtom *oqmlAtom_struct::copy()
00460 {
00461   return new oqmlAtom_struct(attr, attr_cnt);
00462 }
00463 
00464 #define __CMP__(n, o, op) \
00465   if (op == oqmlEQUAL) \
00466     return OQMLBOOL((n) == (o)); \
00467   if (op == oqmlINF) \
00468     return OQMLBOOL((n) < (o)); \
00469   if (op == oqmlINFEQ) \
00470     return OQMLBOOL((n) <= (o)); \
00471   if (op == oqmlSUP) \
00472     return OQMLBOOL((n) > (o)); \
00473   if (op == oqmlSUPEQ) \
00474     return OQMLBOOL((n) >= (o)); \
00475   if (op == oqmlDIFF) \
00476     return OQMLBOOL((n) != (o)); \
00477   return oqml_False
00478 
00479 inline oqmlBool oqmlAtom_null::compare(unsigned char *data, int len_data, Bool isnull, oqmlTYPE op) const
00480 {
00481   int n1 = (isnull ? 0 : 1);
00482 
00483   __CMP__(0, n1, op);
00484 }
00485 
00486 inline oqmlBool oqmlAtom_nil::compare(unsigned char *data, int len_data, Bool isnull, oqmlTYPE op) const
00487 {
00488   return oqml_False;
00489 }
00490 
00491 inline oqmlBool oqmlAtom_bool::compare(unsigned char *data, int len_data, Bool isnull, oqmlTYPE op) const
00492 {
00493   if (isnull)
00494     {
00495       if (op == oqmlDIFF)
00496         return oqml_True;
00497       return oqml_False;
00498     }
00499 
00500   if (len_data != sizeof(oqmlBool))
00501     return oqml_False;
00502 
00503   int n1 = (int)(*(oqmlBool *)data);
00504   int n = (int)b;
00505 
00506   __CMP__(n, n1, op);
00507 }
00508 
00509 inline oqmlBool oqmlAtom_oid::compare(unsigned char *data, int len_data, Bool isnull, oqmlTYPE op) const
00510 {
00511   if (len_data < sizeof(Oid))
00512     return oqml_False;
00513 
00514   Oid noid;
00515   memcpy(&noid, data, sizeof(Oid));
00516 
00517   eyedbsm::Oid::NX nnx = noid.getNX();
00518   eyedbsm::Oid::NX nx =  oid.getNX();
00519   __CMP__(nnx, nx, op);
00520 }
00521 
00522 inline oqmlBool oqmlAtom_obj::compare(unsigned char *data, int len_data, Bool isnull, oqmlTYPE op) const
00523 {
00524   if (len_data < sizeof(Object *))
00525     return oqml_False;
00526 
00527   Object *no;
00528   memcpy(&no, data, sizeof(Object *));
00529 
00530   __CMP__(no, o, op);
00531 }
00532 
00533 inline oqmlBool oqmlAtom_int::compare(unsigned char *data, int len_data,
00534                                       Bool isnull, oqmlTYPE op) const
00535 {
00536   if (isnull)
00537     {
00538       if (op == oqmlDIFF)
00539         return oqml_True;
00540       return oqml_False;
00541     }
00542 
00543   if (len_data == sizeof(eyedblib::int32)+1)
00544     {
00545       eyedblib::int32 ni;
00546       memcpy(&ni, data, sizeof(ni));
00547       __CMP__(ni, i, op);
00548     }
00549 
00550   if (len_data == sizeof(eyedblib::int16))
00551     {
00552       eyedblib::int16 ni;
00553       memcpy(&ni, data, sizeof(ni));
00554       __CMP__(ni, i, op);
00555     }
00556 
00557   if (len_data == sizeof(eyedblib::int32))
00558     {
00559       eyedblib::int32 ni;
00560       memcpy(&ni, data, sizeof(ni));
00561       __CMP__(ni, i, op);
00562     }
00563 
00564   if (len_data == sizeof(eyedblib::int64))
00565     {
00566       eyedblib::int64 ni;
00567       memcpy(&ni, data, sizeof(ni));
00568       __CMP__(ni, i, op);
00569     }
00570 
00571   if (op == oqmlDIFF)
00572     return oqml_True;
00573   return oqml_False;
00574 }
00575 
00576 inline oqmlBool oqmlAtom_char::compare(unsigned char *data, int len_data, Bool isnull, oqmlTYPE op) const
00577 {
00578   if (isnull)
00579     {
00580       if (op == oqmlDIFF)
00581         return oqml_True;
00582       return oqml_False;
00583     }
00584 
00585   if (len_data < sizeof(char))
00586     return oqml_False;
00587 
00588   char nc = data[0];
00589   __CMP__(nc, c, op);
00590 }
00591 
00592 inline oqmlBool oqmlAtom_string::compare(unsigned char *data, int len_data, Bool isnull, oqmlTYPE op) const
00593 {
00594   if (isnull)
00595     {
00596       if (op == oqmlDIFF)
00597         return oqml_True;
00598       return oqml_False;
00599     }
00600 
00601   int cmp;
00602   if (len_data)
00603     cmp = strcmp((char *)data, shstr->s);
00604   else if (data)
00605     cmp = !*shstr->s;
00606   else
00607     cmp = !shstr->s;
00608 
00609   __CMP__(cmp, 0, op);
00610 }
00611 
00612 inline oqmlBool oqmlAtom_ident::compare(unsigned char *data, int len_data, Bool isnull, oqmlTYPE op) const
00613 {
00614   if (isnull)
00615     {
00616       if (op == oqmlDIFF)
00617         return oqml_True;
00618       return oqml_False;
00619     }
00620 
00621   if (len_data < strlen(shstr->s))
00622     return oqml_False;
00623 
00624   int cmp = strcmp((char *)data, shstr->s);
00625   __CMP__(cmp, 0, op);
00626 }
00627 
00628 inline oqmlBool oqmlAtom_double::compare(unsigned char *data, int len_data, Bool isnull, oqmlTYPE op) const
00629 {
00630   if (isnull)
00631     {
00632       if (op == oqmlDIFF)
00633         return oqml_True;
00634       return oqml_False;
00635     }
00636 
00637   if (len_data < sizeof(double))
00638     return oqml_False;
00639 
00640   double nd;
00641   memcpy(&nd, data, sizeof(double));
00642 
00643   if (op == oqmlEQUAL)
00644     {
00645       double delta = nd - d;
00646       if (delta < 0.)
00647         delta = -delta;
00648       return OQMLBOOL(delta < .0001);
00649     }
00650   else
00651     __CMP__(nd, d, op);
00652 }
00653 
00654 inline void oqmlAtom::print(FILE *fd)
00655 {
00656   (void)makeString(fd);
00657 }
00658 
00659 inline char *oqmlAtom::getString() const
00660 {
00661   return makeString(0);
00662 }
00663 
00664 inline oqmlBool oqmlAtom::compare(unsigned char *, int, Bool, oqmlTYPE) const
00665 {
00666   return oqml_False;
00667 }
00668 
00669 #include <assert.h>
00670 
00671 inline oqmlAtom::~oqmlAtom()
00672 {
00673 #ifdef DEST_TRACE
00674   printf("deleting atom %p refcnt=%d\n", this, refcnt);
00675 #endif
00676   assert(!refcnt);
00677   if (refcnt)
00678     return;
00679   refcnt = 32000;
00680   oqmlGarbManager::remove(link);
00681   free(string);
00682 }
00683 
00684 inline void oqmlAtom_string::set(const char *s)
00685 {
00686   shstr->set(s);
00687 }
00688 
00689 inline oqmlAtom_string::~oqmlAtom_string()
00690 {
00691   if (!--shstr->refcnt)
00692     delete shstr;
00693 }
00694 
00695 inline oqmlAtom_ident::~oqmlAtom_ident()
00696 {
00697   if (!--shstr->refcnt)
00698     delete shstr;
00699 }
00700 
00701 inline oqmlAtom_obj::~oqmlAtom_obj()
00702 {
00703   //printf("oqmlAtom_obj::~oqmlAtom_obj(%p, %p, %u)\n", this, o, idx);
00704   oqmlStatus *s = oqmlObjectManager::unregisterObject(0, o);
00705 #if 0
00706   if (s) {
00707     fprintf(stderr, "~oqmlAtom_obj error: %s\n", s->msg);
00708     abort();
00709   }
00710 #endif
00711   o = 0;
00712 }
00713 
00714 inline oqmlAtom_node::~oqmlAtom_node()
00715 {
00716 }
00717 
00718 inline oqmlAtom_select::~oqmlAtom_select()
00719 {
00720 }
00721 
00722 inline oqmlAtom_struct::~oqmlAtom_struct()
00723 {
00724 }
00725 
00726 inline oqmlBool oqmlAtomType::cmp(const oqmlAtomType &at, Bool autocast)
00727 {
00728   /*
00729   if (type == oqmlATOM_OBJ || at.type == oqmlATOM_OBJ)
00730     return oqml_False;
00731   */
00732   if (type == oqmlATOM_OBJ && at.type == oqmlATOM_OBJ) {
00733     if (cls == 0)
00734       return (oqmlBool)(at.cls == 0);
00735     if (at.cls == 0)
00736       return (oqmlBool)(cls == 0);
00737     return (oqmlBool)cls->compare(at.cls);
00738   }
00739 
00740   if (autocast)
00741     {
00742       if ((type == oqmlATOM_DOUBLE && at.type == oqmlATOM_INT) ||
00743           (at.type == oqmlATOM_DOUBLE && type == oqmlATOM_INT))
00744         return oqml_True;
00745     }
00746 
00747   return OQMLBOOL(type == at.type && comp == at.comp);
00748 }
00749 
00750 inline oqmlAtomList::oqmlAtomList()
00751 {
00752   cnt = 0;
00753   first = last = 0;
00754   link = oqmlGarbManager::add(this);
00755   refcnt = 0;
00756   recurs = oqml_False;
00757   string = (char *)0;
00758 }
00759 
00760 inline oqmlAtomList::oqmlAtomList(oqmlAtomList *alist)
00761 {
00762   cnt = 0;
00763   first = last = 0;
00764 
00765   refcnt = 0;
00766   recurs = oqml_False;
00767   string = (char *)0;
00768 
00769   link = oqmlGarbManager::add(this);
00770 
00771   if (!alist)
00772     return;
00773 
00774   oqmlAtom *a = alist->first;
00775   while (a)
00776     {
00777       oqmlAtom *next = a->next;
00778       append(a->copy());
00779       a = next;
00780     }
00781 }
00782 
00783 inline oqmlAtomList::oqmlAtomList(oqmlAtom *a)
00784 {
00785   cnt = (a ? 1 : 0);
00786   first = last = a;
00787   refcnt = 0;
00788   recurs = oqml_False;
00789   string = (char *)0;
00790   link = oqmlGarbManager::add(this);
00791 
00792   if (!a)
00793     return;
00794 
00795   a->next = 0;
00796 }
00797 
00798 inline oqmlAtomList::~oqmlAtomList()
00799 {
00800 #ifdef DEST_TRACE
00801   printf("deleting list %p refcnt=%d\n", this, refcnt);
00802 #endif
00803   assert(!refcnt);
00804   if (refcnt)
00805     return;
00806 
00807   oqmlAtom *a = first;
00808   while (a) {
00809     oqmlAtom *next = a->next;
00810     //printf("a->refcnt %d %s\n", a->refcnt, a->getString());
00811     if (!a->refcnt)
00812       delete a;
00813     a = next;
00814   }
00815 
00816   cnt = 0;
00817   oqmlGarbManager::remove(link);
00818 #ifdef DEST_TRACE
00819   printf("end of deleting list %p\n", this);
00820 #endif
00821   refcnt = 64000;
00822   free(string);
00823 }
00824 
00825 inline int oqmlAtomList::getFlattenCount() const
00826 {
00827   int count = 0;
00828 
00829   oqmlAtom *a = first;
00830   while (a)
00831     {
00832       if (a->type.type == oqmlATOM_LIST)
00833         count += ((oqmlAtom_list *)a)->list->getFlattenCount() + 2;
00834       else
00835         count++;
00836       a = a->next;
00837     }
00838 
00839   return count;
00840 }
00841 
00842 inline void oqmlAtomList::print(FILE *fd)
00843 {
00844   oqmlAtom *a = first;
00845 
00846   fprintf(fd, "(");
00847   while (a)
00848     {
00849       a->print(fd);
00850       a = a->next;
00851       if (a)
00852         fprintf(fd, ", ");
00853     }
00854   fprintf(fd, ")");
00855 }
00856 
00857 inline char *oqmlAtomList::getString() const
00858 {
00859   oqmlAtom *a = first;
00860   int sz = 1;
00861   char *b = (char *)malloc(sz);
00862   b[0] = 0;
00863 
00864   while (a)
00865     {
00866       char *d = a->getString();
00867       sz += strlen(d) + 2;
00868       b = (char *)realloc(b, sz);
00869       if (a != first)
00870         strcat(b, ", ");
00871       strcat(b, d);
00872       a = a->next;
00873     }
00874 
00875   delete string;
00876   ((oqmlAtomList *)this)->string = b;
00877   return b;
00878 }
00879 
00880 inline bool detect_cycle(oqmlAtom *a1, oqmlAtom *a2)
00881 {
00882   while (a1) {
00883     while (a2) {
00884       bool r = false;
00885 
00886       if (a1 == a2)
00887         r = true;
00888       else if (a1->as_coll() && a2->as_coll())
00889         r = detect_cycle(a1->as_coll()->list->first, a2->as_coll()->list->first);
00890       else if (a1->as_coll())
00891         r = detect_cycle(a1->as_coll()->list->first, a2);
00892 
00893       else if (a2->as_coll())
00894         r = detect_cycle(a1, a2->as_coll()->list->first);
00895 
00896       if (r)
00897         return true;
00898       a2 = a2->next;
00899     }
00900     a1 = a1->next;
00901   }
00902 
00903   return false;
00904 }
00905 
00906 inline bool oqmlAtomList::append(oqmlAtom *a, bool incref, bool _detect_cycle)
00907 {
00908   a->next = 0;
00909 
00910   if (_detect_cycle && detect_cycle(first, a))
00911     return true;
00912 
00913   if (last) {
00914     last->next = a;
00915     last = a;
00916   }
00917   else
00918     first = last = a;
00919 
00920   if (incref) {
00921     if (refcnt)
00922       oqmlLock(a, oqml_True);
00923     else if (a->refcnt)
00924       oqmlLock(this, oqml_True);
00925   }
00926 
00927   cnt++;
00928 
00929   return false;
00930 }
00931 
00932 inline bool oqmlAtomList::append(oqmlAtomList *al, oqmlBool dodel, bool _detect_cycle)
00933 {
00934   if (!al)
00935     return false;
00936 
00937   if (_detect_cycle && detect_cycle(first, al->first))
00938     return true;
00939 
00940   if (refcnt)
00941     oqmlLock(al, oqml_True);
00942   else if (al->refcnt)
00943     oqmlLock(this, oqml_True);
00944 
00945   oqmlAtom *a = al->first;
00946 
00947   if (!a)
00948     return false;
00949 
00950   if (last)
00951     last->next = a;
00952   else
00953     first = a;
00954 
00955   last = al->last;
00956 
00957   cnt += al->cnt;
00958   if (dodel && !al->refcnt) {
00959     al->first = 0;
00960     al->cnt = 0;
00961     delete al;
00962   }
00963 
00964   return false;
00965 }

Generated on Mon Dec 22 18:16:05 2008 for eyedb by  doxygen 1.5.3