From 31a2d9dcc2b3a519033918e180f81c4e7b9f8e7e Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Tue, 15 Mar 2005 04:56:36 +0000 Subject: new data type flext::AtomListStatic using pre-allocated space if possible fixes for OSX replaced memory-intensive STL maps by custom-made vector/map-container fix for gcc strangeness no more static assignment of symbols (problems with Metrowerks) small fix for gcc fixed bugs in SIMD code for non-power-of-2 lengths fixes for attribute editor (to deal with large dialogs) svn path=/trunk/; revision=2628 --- externals/grill/flext/changes.txt | 1 + externals/grill/flext/source/flatom.cpp | 64 ++++++------ externals/grill/flext/source/flattr.cpp | 37 +++++-- externals/grill/flext/source/flattr_ed.cpp | 59 ++++++++--- externals/grill/flext/source/flbase.cpp | 1 + externals/grill/flext/source/flbind.cpp | 40 +++++-- externals/grill/flext/source/flclass.h | 6 ++ externals/grill/flext/source/flitem.cpp | 47 ++++----- externals/grill/flext/source/fllib.cpp | 13 +-- externals/grill/flext/source/flmap.h | 154 ++++++++++++++++++++++++++- externals/grill/flext/source/flmeth.cpp | 12 +-- externals/grill/flext/source/flsupport.cpp | 162 ++++++++++++++++++++++++++++- externals/grill/flext/source/flsupport.h | 53 ++++++++-- 13 files changed, 530 insertions(+), 119 deletions(-) (limited to 'externals') diff --git a/externals/grill/flext/changes.txt b/externals/grill/flext/changes.txt index 2184cc54..afcb018c 100644 --- a/externals/grill/flext/changes.txt +++ b/externals/grill/flext/changes.txt @@ -36,6 +36,7 @@ Version history: - added lock-free Lifo and Fifo structures and used it with message queueing and thread management - eliminated default "help" (m_help) method... should be implemented in the flext-based object - changed virtual callback names m_loadbang, m_method_, m_dsp, m_signal, m_click to CbLoadbang, CbMethodResort, CbDsp, CbSignal, CbClick +- replaced memory-intensive STL maps by custom-made vector/map-monster (should be fast!) 0.4.7: - added flext::GetBool (just because flext::GetInt has been there for a while) diff --git a/externals/grill/flext/source/flatom.cpp b/externals/grill/flext/source/flatom.cpp index 3562e904..bf057c00 100644 --- a/externals/grill/flext/source/flatom.cpp +++ b/externals/grill/flext/source/flatom.cpp @@ -48,33 +48,39 @@ t_atom *flext::CopyList(int argc,const t_atom *argv) return dst; } -flext::AtomList::AtomList(int argc,const t_atom *argv): - cnt(0),lst(NULL) +void flext::AtomList::Alloc(int sz) { - operator()(argc,argv); + if(lst) { + if(cnt == sz) return; // no change + delete[] lst; + } + else + FLEXT_ASSERT(cnt == 0); + lst = new t_atom[cnt = sz]; } -flext::AtomList::AtomList(const AtomList &a): - cnt(0),lst(NULL) +flext::AtomList::~AtomList() { Free(); } + +void flext::AtomList::Free() { - operator =(a); + if(lst) { + delete[] lst; lst = NULL; + cnt = 0; + } + else + FLEXT_ASSERT(cnt == 0); } -flext::AtomList::~AtomList() { Clear(); } - - flext::AtomList &flext::AtomList::Set(int argc,const t_atom *argv,int offs,bool resize) { int ncnt = argc+offs; - if(resize && lst && cnt != ncnt) { delete[] lst; lst = NULL; cnt = 0; } + if(resize) Alloc(ncnt); - if(ncnt) { - if(!lst) lst = new t_atom[cnt = ncnt]; + // argv can be NULL indepently from argc + if(argv) + for(int i = 0; i < argc; ++i) + SetAtom(lst[offs+i],argv[i]); - if(argv) { - for(int i = 0; i < argc; ++i) SetAtom(lst[offs+i],argv[i]); - } - } return *this; } @@ -91,20 +97,16 @@ int flext::AtomList::Compare(const AtomList &a) const return Count() < a.Count()?-1:1; } +flext::AtomListStaticBase::~AtomListStaticBase() { Free(); } -#if FLEXT_SYS != FLEXT_SYS_JMAX -// not for jmax as long as t_symbol * == char * -flext::AtomAnything::AtomAnything(const t_symbol *h,int argc,const t_atom *argv): - AtomList(argc,argv),hdr(h?h:MakeSymbol("")) -{} -#endif - -flext::AtomAnything::AtomAnything(const char *h,int argc,const t_atom *argv): - AtomList(argc,argv),hdr(MakeSymbol(h)) -{} - -flext::AtomAnything::AtomAnything(const AtomAnything &a): - AtomList(a),hdr(a.hdr) -{} - +void flext::AtomListStaticBase::Alloc(int sz) +{ + if(sz < precnt) lst = predata,cnt = sz; + else AtomList::Alloc(sz); +} +void flext::AtomListStaticBase::Free() +{ + if(lst != predata) AtomList::Free(); + else lst = NULL,cnt = 0; +} diff --git a/externals/grill/flext/source/flattr.cpp b/externals/grill/flext/source/flattr.cpp index a7e35b18..f930820a 100644 --- a/externals/grill/flext/source/flattr.cpp +++ b/externals/grill/flext/source/flattr.cpp @@ -33,6 +33,7 @@ flext_base::AttrItem::AttrItem(const t_symbol *t,metharg tp,methfun f,int fl): {} +/* flext_base::AttrDataCont::AttrDataCont() {} flext_base::AttrDataCont::~AttrDataCont() @@ -40,6 +41,7 @@ flext_base::AttrDataCont::~AttrDataCont() for(iterator it = begin(); it != end(); ++it) if(it.data()) delete it.data(); } +*/ //! Add get and set attributes @@ -101,7 +103,7 @@ void flext_base::AddAttrib(t_classid c,const t_symbol *attr,metharg tp,methfun g void flext_base::ListAttrib(AtomList &la) const { - typedef DataMap AttrList; + typedef TableMap AttrList; AttrList list[2]; int i; @@ -109,10 +111,10 @@ void flext_base::ListAttrib(AtomList &la) const ItemCont *a = i?attrhead:clattrhead; if(a && a->Contained(0)) { ItemSet &ai = a->GetInlet(); - for(ItemSet::iterator as = ai.begin(); as != ai.end(); ++as) { + for(ItemSet::iterator as(ai); as; ++as) { for(Item *al = as.data(); al; al = al->nxt) { AttrItem *aa = (AttrItem *)al; - list[i][aa->index] = as.key(); + list[i].insert(aa->index,const_cast(as.key())); break; } } @@ -121,9 +123,8 @@ void flext_base::ListAttrib(AtomList &la) const la((int)(list[0].size()+list[1].size())); int ix = 0; - AttrList::iterator it; for(i = 0; i <= 1; ++i) - for(it = list[i].begin(); it != list[i].end(); ++it) + for(AttrList::iterator it(list[i]); it; ++it) SetSymbol(la[ix++],it.data()); } @@ -149,6 +150,7 @@ bool flext_base::InitAttrib(int argc,const t_atom *argv) AttrItem *attr = FindAttrib(tag,false,true); if(attr) { // make an entry (there are none beforehand...) +/* AttrDataCont::iterator it = attrdata->find(tag); if(it == attrdata->end()) { AttrDataCont::pair pair; @@ -163,6 +165,15 @@ bool flext_base::InitAttrib(int argc,const t_atom *argv) // pass value to object SetAttrib(tag,attr,a.GetInitValue()); +*/ + AttrData *a = attrdata->find(tag); + if(!a) attrdata->insert(tag,a = new AttrData); + + a->SetInit(true); + a->SetInitValue(nxt-cur-1,argv+cur+1); + + // pass value to object + SetAttrib(tag,attr,a->GetInitValue()); } } return true; @@ -174,7 +185,7 @@ bool flext_base::ListAttrib() const // defined in flsupport.cpp extern const t_symbol *sym_attributes; - AtomList la; + AtomListStatic<32> la; ListAttrib(la); ToOutAnything(GetOutAttr(),sym_attributes,la.Count(),la.Atoms()); return true; @@ -257,7 +268,7 @@ bool flext_base::SetAttrib(const t_symbol *tag,AttrItem *a,int argc,const t_atom else ok = false; break; case a_LIST: { - AtomList la(argc); + AtomListStatic<16> la(argc); for(int i = 0; i < argc; ++i) if(IsSymbol(argv[i])) GetParamSym(la[i],GetSymbol(argv[i]),thisCanvas()); @@ -344,7 +355,7 @@ bool flext_base::GetAttrib(const t_symbol *s,AtomList &a) const //! \param tag symbol "get[attribute]" bool flext_base::DumpAttrib(const t_symbol *tag,AttrItem *a) const { - AtomList la; + AtomListStatic<16> la; bool ret = GetAttrib(tag,a,la); if(ret) { ToOutAnything(GetOutAttr(),a->tag,la.Count(),la.Atoms()); @@ -360,7 +371,7 @@ bool flext_base::DumpAttrib(const t_symbol *attr) const bool flext_base::BangAttrib(const t_symbol *attr,AttrItem *item) { - AtomList val; + AtomListStatic<16> val; AttrItem *item2; if(!item->IsGet()) item = item->Counterpart(); @@ -384,12 +395,20 @@ bool flext_base::BangAttribAll() ItemCont *a = i?attrhead:clattrhead; if(a) { ItemSet &ai = a->GetInlet(); // \todo need to check for presence of inlet 0? +/* for(ItemSet::iterator as = ai.begin(); as != ai.end(); ++as) { for(Item *al = as.data(); al; al = al->nxt) { AttrItem *a = (AttrItem *)al; if(a->IsGet() && a->BothExist()) BangAttrib(as.key(),a); } } +*/ + for(ItemSet::iterator as(ai); as; ++as) { + for(Item *al = as.data(); al; al = al->nxt) { + AttrItem *a = (AttrItem *)al; + if(a->IsGet() && a->BothExist()) BangAttrib(as.key(),a); + } + } } } return true; diff --git a/externals/grill/flext/source/flattr_ed.cpp b/externals/grill/flext/source/flattr_ed.cpp index 16a418a3..d8883005 100644 --- a/externals/grill/flext/source/flattr_ed.cpp +++ b/externals/grill/flext/source/flattr_ed.cpp @@ -494,7 +494,7 @@ void flext_base::cb_GfxProperties(t_gobj *c, t_glist *) PrintList(argc,argv,buf,sizeof(buf)); sys_vgui("%s } {\n",buf); - AtomList la; + AtomListStatic<32> la; th->ListAttrib(la); int cnt = la.Count(); @@ -509,18 +509,20 @@ void flext_base::cb_GfxProperties(t_gobj *c, t_glist *) // get flags int sv; const AtomList *initdata; - AttrDataCont::iterator it = th->attrdata->find(sym); - if(it == th->attrdata->end()) + const AttrData *a = th->attrdata->find(sym); +// AttrDataCont::iterator it = th->attrdata->find(sym); +// if(it == th->attrdata->end()) + if(!a) sv = 0,initdata = NULL; else { - const AttrData &a = *it.data(); - if(a.IsSaved()) +// const AttrData &a = *it.data(); + if(a->IsSaved()) sv = 2; - else if(a.IsInit()) + else if(a->IsInit()) sv = 1; else sv = 0; - initdata = a.IsInitValue()?&a.GetInitValue():NULL; + initdata = a->IsInitValue()?&a->GetInitValue():NULL; } // get attribute type @@ -540,7 +542,7 @@ void flext_base::cb_GfxProperties(t_gobj *c, t_glist *) sys_vgui(const_cast(list?"%s {":"%s "),GetString(sym)); - AtomList lv; + AtomListStatic<32> lv; if(gattr) { // gettable attribute is present // Retrieve attribute value th->GetAttrib(sym,gattr,lv); @@ -561,7 +563,7 @@ void flext_base::cb_GfxProperties(t_gobj *c, t_glist *) if(pattr) { // if there is initialization data take this, otherwise take the current data - const AtomList &lp = initdata?*initdata:lv; + const AtomList &lp = initdata?*initdata:static_cast(lv); char *b = buf; *b = 0; for(int i = 0; i < lp.Count(); ++i) { @@ -702,10 +704,13 @@ bool flext_base::cb_AttrDialog(flext_base *th,int argc,const t_atom *argv) bool ret = th->SetAttrib(aname,attr,ccnt,argv+coffs); FLEXT_ASSERT(ret); - AttrDataCont::iterator it = th->attrdata->find(aname); +// AttrDataCont::iterator it = th->attrdata->find(aname); + AttrData *a = th->attrdata->find(aname); if(sv >= 1) { // if data not present create it + +/* if(it == th->attrdata->end()) { AttrDataCont::pair pair; pair.key() = aname; @@ -717,14 +722,30 @@ bool flext_base::cb_AttrDialog(flext_base *th,int argc,const t_atom *argv) a.SetSave(sv == 2); a.SetInit(true); a.SetInitValue(icnt,argv+ioffs); +*/ + if(!a) + th->attrdata->insert(aname,a = new AttrData); + + a->SetSave(sv == 2); + a->SetInit(true); + a->SetInitValue(icnt,argv+ioffs); } else { +/* if(it != th->attrdata->end()) { AttrData &a = *it.data(); // if data is present reset flags a.SetSave(false); a.SetInit(false); + // let init data as is + } +*/ + if(a) { + // if data is present reset flags + a->SetSave(false); + a->SetInit(false); + // let init data as is } } @@ -765,21 +786,26 @@ void flext_base::BinbufArgs(t_binbuf *b,t_binbuf *args,bool withname,bool transd void flext_base::BinbufAttr(t_binbuf *b,bool transdoll) { // process the attributes - AtomList la; + AtomListStatic<32> la,lv; ListAttrib(la); int i,cnt = la.Count(); for(i = 0; i < cnt; ++i) { const t_symbol *sym = GetSymbol(la[i]); - AtomList lv; const AtomList *lref = NULL; +/* AttrDataCont::iterator it = attrdata->find(sym); - if(it != attrdata->end()) { const AttrData &a = *it.data(); if(a.IsInit() && a.IsInitValue()) { lref = &a.GetInitValue(); -/* +*/ + AttrData *a = attrdata->find(sym); + if(a) { + if(a->IsInit() && a->IsInitValue()) { + lref = &a->GetInitValue(); + +#if 0 ///////////////////////////////////////////////////////////// // check for $-parameters lv = lref->Count(); for(int j = 0; j < lref->Count(); ++j) { @@ -795,9 +821,10 @@ void flext_base::BinbufAttr(t_binbuf *b,bool transdoll) } lref = &lv; -*/ +#endif ///////////////////////////////////////////////////////////// } - else if(a.IsSaved()) { +// else if(a.IsSaved()) { + else if(a->IsSaved()) { AttrItem *attr = FindAttrib(sym,true); // attribute must be gettable (so that the data can be retrieved) and puttable (so that the data can be inited) diff --git a/externals/grill/flext/source/flbase.cpp b/externals/grill/flext/source/flbase.cpp index 7101b484..a4ec0d1c 100644 --- a/externals/grill/flext/source/flbase.cpp +++ b/externals/grill/flext/source/flbase.cpp @@ -18,6 +18,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "flinternal.h" #include #include +#include #if FLEXT_SYS == FLEXT_SYS_PD #ifdef _MSC_VER diff --git a/externals/grill/flext/source/flbind.cpp b/externals/grill/flext/source/flbind.cpp index 5b0bfeac..ff84e4ea 100644 --- a/externals/grill/flext/source/flbind.cpp +++ b/externals/grill/flext/source/flbind.cpp @@ -144,13 +144,14 @@ bool flext_base::BindMethod(const t_symbol *sym,bool (*fun)(flext_base *,t_symbo return true; } - bool flext_base::UnbindMethod(const t_symbol *sym,bool (*fun)(flext_base *,t_symbol *s,int argc,t_atom *argv,void *data),void **data) { bool ok = false; if(bindhead && bindhead->Contained(0)) { ItemSet &set = bindhead->GetInlet(); + +/* ItemSet::iterator it1,it2; if(sym) { // specific tag @@ -173,13 +174,37 @@ bool flext_base::UnbindMethod(const t_symbol *sym,bool (*fun)(flext_base *,t_sym } } } +*/ + BindItem *item = NULL; + if(sym) { + // symbol is given + Item *it = set.find(sym); + if(fun) { + // check if function matches + for(; it && static_cast(it)->fun != fun; it = it->nxt); + } + item = static_cast(it); + } + else { + // take any entry that matches + for(ItemSet::iterator si(set); si && !item; ++si) { + for(Item *i = si.data(); i; i = i->nxt) { + BindItem *bit = (BindItem *)i; + if(!fun || bit->fun == fun) { + item = bit; + if(!sym) sym = si.key(); + break; + } + } + } + } - if(it) { - if(data) *data = it->px->data; - ok = bindhead->Remove(it,sym,0,false); + if(item) { + if(data) *data = item->px->data; + ok = bindhead->Remove(item,sym,0,false); if(ok) { - it->Unbind(sym); - delete it; + item->Unbind(sym); + delete item; } } } @@ -207,7 +232,8 @@ bool flext_base::UnbindAll() { if(bindhead && bindhead->Contained(0)) { ItemSet &set = bindhead->GetInlet(); - for(ItemSet::iterator si = set.begin(); si != set.end(); ++si) { +// for(ItemSet::iterator si = set.begin(); si != set.end(); ++si) { + for(ItemSet::iterator si(set); si; ++si) { Item *lst = si.data(); while(lst) { Item *nxt = lst->nxt; diff --git a/externals/grill/flext/source/flclass.h b/externals/grill/flext/source/flclass.h index 4fcf64a9..06c48927 100644 --- a/externals/grill/flext/source/flclass.h +++ b/externals/grill/flext/source/flclass.h @@ -650,6 +650,7 @@ protected: Item *nxt; }; +/* class ItemSet: public DataMap { @@ -657,6 +658,8 @@ protected: ItemSet(); ~ItemSet(); }; +*/ + typedef TableMap ItemSet; /*! This class holds hashed item entries \note not thread-safe! @@ -763,6 +766,7 @@ protected: int flags; }; +/* class AttrDataCont: public DataMap { @@ -770,6 +774,8 @@ protected: AttrDataCont(); ~AttrDataCont(); }; +*/ + typedef TableMap AttrDataCont; // these outlet functions don't check for thread but send directly to the real-time system #if FLEXT_SYS == FLEXT_SYS_PD || FLEXT_SYS == FLEXT_SYS_MAX diff --git a/externals/grill/flext/source/flitem.cpp b/externals/grill/flext/source/flitem.cpp index 92ce01cd..eb307d09 100755 --- a/externals/grill/flext/source/flitem.cpp +++ b/externals/grill/flext/source/flitem.cpp @@ -21,6 +21,7 @@ flext_base::Item::~Item() if(nxt) delete nxt; } +/* flext_base::ItemSet::ItemSet() {} flext_base::ItemSet::~ItemSet() @@ -28,6 +29,7 @@ flext_base::ItemSet::~ItemSet() for(iterator it = begin(); it != end(); ++it) if(it.data()) delete it.data(); } +*/ flext_base::ItemCont::ItemCont(): members(0),memsize(0),size(0),cont(NULL) @@ -64,9 +66,9 @@ void flext_base::ItemCont::Add(Item *item,const t_symbol *tag,int inlet) if(!Contained(inlet)) Resize(inlet+2); ItemSet &set = GetInlet(inlet); - Item *&lst = set[tag]; + Item *lst = set.find(tag); if(!lst) - lst = item; + set.insert(tag,lst = item); else for(;;) if(!lst->nxt) { lst->nxt = item; break; } @@ -80,17 +82,15 @@ bool flext_base::ItemCont::Remove(Item *item,const t_symbol *tag,int inlet,bool if(Contained(inlet)) { ItemSet &set = GetInlet(inlet); - ItemSet::iterator it = set.find(tag); - if(it != set.end()) { - for(Item *lit = it.data(),*prv = NULL; lit; prv = lit,lit = lit->nxt) { - if(lit == item) { - if(prv) prv->nxt = lit->nxt; - else it.data() = lit->nxt; - - lit->nxt = NULL; - if(free) delete lit; - return true; - } + Item *lit = set.find(tag); + for(Item *prv = NULL; lit; prv = lit,lit = lit->nxt) { + if(lit == item) { + if(prv) prv->nxt = lit->nxt; + else set.insert(tag,lit->nxt); + + lit->nxt = NULL; + if(free) delete lit; + return true; } } } @@ -100,30 +100,19 @@ bool flext_base::ItemCont::Remove(Item *item,const t_symbol *tag,int inlet,bool flext_base::Item *flext_base::ItemCont::FindList(const t_symbol *tag,int inlet) { FLEXT_ASSERT(tag); - - if(Contained(inlet)) { - ItemSet &ai = GetInlet(inlet); - ItemSet::iterator as = ai.find(tag); - if(as != ai.end()) return as.data(); - } - return NULL; + return Contained(inlet)?GetInlet(inlet).find(tag):NULL; } // --- class item lists (methods and attributes) ---------------- -typedef DataMap ClassMap; +typedef TableMap ClassMap; static ClassMap classarr[2]; flext_base::ItemCont *flext_base::GetClassArr(t_classid c,int ix) { ClassMap &map = classarr[ix]; - ClassMap::iterator it = map.find(c); - if(it == map.end()) { - ItemCont *cont = new ItemCont; - map[c] = cont; - return cont; - } - else - return it.data(); + ItemCont *cont = map.find(c); + if(!cont) map.insert(c,cont = new ItemCont); + return cont; } diff --git a/externals/grill/flext/source/fllib.cpp b/externals/grill/flext/source/fllib.cpp index b7f32592..85589679 100755 --- a/externals/grill/flext/source/fllib.cpp +++ b/externals/grill/flext/source/fllib.cpp @@ -126,21 +126,16 @@ libclass::libclass(t_class *&cl,flext_obj *(*newf)(int,t_atom *),void (*freef)(f {} -typedef DataMap LibMap; +typedef TableMap LibMap; static LibMap libnames; //! Store or retrieve registered classes static libclass *FindName(const t_symbol *s,libclass *o = NULL) { -// typedef std::map LibMap; - LibMap::iterator it = libnames.find(s); - if(it == libnames.end()) { - if(o) libnames[s] = o; - return o; - } - else - return it.data(); + libclass *cl = libnames.find(s); + if(!cl) libnames.insert(s,cl = o); + return cl; } diff --git a/externals/grill/flext/source/flmap.h b/externals/grill/flext/source/flmap.h index 980c2c99..8ad3a864 100644 --- a/externals/grill/flext/source/flmap.h +++ b/externals/grill/flext/source/flmap.h @@ -15,12 +15,14 @@ WARRANTIES, see the file, "license.txt," in this distribution. #ifndef __FLMAP_H #define __FLMAP_H -#include - /*! \defgroup FLEXT_SUPPORT Flext support classes @{ */ +#if 0 + +#include + //! Key/Value type for AnyMap... must have size of pointer! typedef size_t AnyMapType; @@ -74,6 +76,154 @@ public: inline void erase(K k) { AnyMap::erase(*(AnyMapType *)&k); } }; +#endif + +class TableAnyMap +{ +protected: + virtual TableAnyMap *New(TableAnyMap *parent) = 0; + virtual void Free(void *ptr) = 0; + + struct Data { + void operator()(size_t k,void *v) { key = k,value = v; } + void operator =(void *v) { value = v; } + + size_t key; + void *value; + }; + + TableAnyMap(TableAnyMap *p,int mx,Data *dt,bool o) + : owned(o),max(mx),data(dt) + , n(0),parent(p),left(NULL),right(NULL) + {} + + virtual ~TableAnyMap() { clear(); } + + int size() const; + + inline void insert(size_t k,void *t) + { + FLEXT_ASSERT(t); + if(n) _set(k,t); + else data[n++](k,t); + } + + inline void *find(size_t k) { return n?_find(k):NULL; } + + void clear(); + + inline void _toleft(size_t k,void *t) + { + if(left) + left->_set(k,t); + else { + left = New(this); + left->data[0](k,t); + left->n = 1; + } + } + + inline void _toright(size_t k,void *t) + { + if(right) + right->_set(k,t); + else { + right = New(this); + right->data[0](k,t); + right->n = 1; + } + } + + inline void _toleft(Data &v) { _toleft(v.key,v.value); } + inline void _toright(Data &v) { _toright(v.key,v.value); } + + void _set(size_t k,void *t); + void *_find(size_t k); + + Data *const data; + const int max; + const bool owned; + int n; + TableAnyMap *parent,*left,*right; + + + class iterator + { + public: + inline iterator(): map(NULL) {} + inline iterator(TableAnyMap &m): map(&m),ix(0) { leftmost(); } + inline iterator(iterator &it): map(it.map),ix(it.ix) {} + + iterator &operator =(const iterator &it) { map = it.map,ix = it.ix; return *this; } + + operator bool() const { return map && /*ix >= 0 &&*/ ix < map->n; } + + // no checking here! + void *data() const { return map->data[ix].value; } + size_t key() const { return map->data[ix].key; } + + iterator &operator ++() { forward(); return *this; } + + protected: + void leftmost() + { + // search smallest branch (go left as far as possible) + TableAnyMap *nmap; + while((nmap = map->left) != NULL) map = nmap; + } + + void forward(); + + TableAnyMap *map; + int ix; + }; +}; + + +template +class TableMap + : TableAnyMap +{ +public: + TableMap(): TableAnyMap(NULL,N,slots,O) {} + virtual ~TableMap() { clear(); } + + inline void clear() { TableAnyMap::clear(); } + + inline int size() const { return TableAnyMap::size(); } + + inline void insert(K k,T *t) { TableAnyMap::insert(*(size_t *)&k,t); } + + inline T *find(K k) { return (T *)TableAnyMap::find(*(size_t *)&k); } + + class iterator + : TableAnyMap::iterator + { + public: + inline iterator() {} + inline iterator(TableMap &m): TableAnyMap::iterator(m) {} + inline iterator(iterator &it): TableAnyMap::iterator(it) {} + + inline iterator &operator =(const iterator &it) { TableAnyMap::operator =(it); return *this; } + + inline operator bool() const {return TableAnyMap::iterator::operator bool(); } + inline T *data() const { return (T *)TableAnyMap::iterator::data(); } + inline K key() const { return (K)TableAnyMap::iterator::key(); } + + inline iterator &operator ++() { TableAnyMap::iterator::operator ++(); return *this; } + + }; + +protected: + inline TableMap(TableAnyMap *p): TableAnyMap(p,N,slots,O) {} + + virtual TableAnyMap *New(TableAnyMap *parent) { return new TableMap(parent); } + virtual void Free(void *ptr) { delete (T *)ptr; } + + Data slots[N]; +}; + + //! @} // FLEXT_SUPPORT #endif diff --git a/externals/grill/flext/source/flmeth.cpp b/externals/grill/flext/source/flmeth.cpp index 5de2083a..a9bf6749 100755 --- a/externals/grill/flext/source/flmeth.cpp +++ b/externals/grill/flext/source/flmeth.cpp @@ -92,7 +92,7 @@ void flext_base::AddMethod(ItemCont *ma,int inlet,const t_symbol *tag,methfun fu void flext_base::ListMethods(AtomList &la,int inlet) const { - typedef DataMap MethList; + typedef TableMap MethList; MethList list[2]; int i; @@ -100,13 +100,12 @@ void flext_base::ListMethods(AtomList &la,int inlet) const ItemCont *a = i?methhead:clmethhead; if(a && a->Contained(inlet)) { ItemSet &ai = a->GetInlet(inlet); - for(ItemSet::iterator as = ai.begin(); as != ai.end(); ++as) { + for(ItemSet::iterator as(ai); as; ++as) { for(Item *al = as.data(); al; al = al->nxt) { MethItem *aa = (MethItem *)al; - // check it's not related to an attribute if(!aa->IsAttr()) { - list[i][aa->index] = as.key(); + list[i].insert(aa->index,const_cast(as.key())); break; } } @@ -116,9 +115,8 @@ void flext_base::ListMethods(AtomList &la,int inlet) const la((int)list[0].size()+(int)list[1].size()); int ix = 0; - MethList::iterator it; for(i = 0; i <= 1; ++i) - for(it = list[i].begin(); it != list[i].end(); ++it) + for(MethList::iterator it(list[i]); it; ++it) SetSymbol(la[ix++],it.data()); } @@ -129,7 +127,7 @@ bool flext_base::cb_ListMethods(flext_base *c,int argc,const t_atom *argv) extern const t_symbol *sym_methods; int inlet = argc?GetAInt(argv[0]):0; - AtomList la; + AtomListStatic<32> la; c->ListMethods(la,inlet); c->ToOutAnything(c->GetOutAttr(),sym_methods,la.Count(),la.Atoms()); return true; diff --git a/externals/grill/flext/source/flsupport.cpp b/externals/grill/flext/source/flsupport.cpp index 86187025..1a55bdc5 100644 --- a/externals/grill/flext/source/flsupport.cpp +++ b/externals/grill/flext/source/flsupport.cpp @@ -16,6 +16,8 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include #include +#include +#include #include #ifdef _MSC_VER @@ -295,8 +297,166 @@ void flext_root::error(const char *fmt,...) va_end(ap); } - +#if 0 AnyMap::AnyMap() {} AnyMap::~AnyMap() {} AnyMap::iterator AnyMap::find(AnyMapType k) { return Parent::find(k); } AnyMapType &AnyMap::operator [](AnyMapType k) { return Parent::operator [](k); } +#endif + +void TableAnyMap::clear() +{ + if(left) { delete left; left = NULL; } + if(right) { delete right; right = NULL; } + if(owned) + for(int i = 0; i < n; ++i) { + FLEXT_ASSERT(data[i].value); + Free(data[i].value); + } + n = 0; +} + +int TableAnyMap::size() const +{ + int sz = n; + if(sz >= max) { + if(left) sz += left->size(); + if(right) sz += right->size(); + } + return sz; +} + +void TableAnyMap::_set(size_t k,void *t) +{ + FLEXT_ASSERT(n); + + if(n < max) { + // fall through + } + else if(k < data[0].key) { + _toleft(k,t); + return; + } + else if(k > data[max-1].key) { + _toright(k,t); + return; + } + + int ix = 0; + { + int b = n; + while(ix != b) { + const int c = (ix+b)/2; + const size_t dk = data[c].key; + if(k == dk) { + ix = c; + break; + } + else if(k < dk) + b = c; + else if(ix < c) + ix = c; + else { + ix = b; + break; + } + } + } + + size_t dk = data[ix].key; + if(k == dk) { + // update data in existing slot (same key) + if(owned) Free(data[ix].value); + data[ix] = t; + } + else if(ix >= n) { + FLEXT_ASSERT(ix == n); + // after last entry + data[n++](k,t); + } + else { + // insert new slot by shifting the higher ones + FLEXT_ASSERT(k < dk); + if(n == max) + _toright(data[max-1]); + else + ++n; + + Data *tg = data+ix; + for(Data *d = data+n-1; d > tg; d--) d[0] = d[-1]; + (*tg)(k,t); + } +} + +void *TableAnyMap::_find(size_t k) +{ + FLEXT_ASSERT(n); + if(n < max) { + // fall through + } + else if(k < data[0].key) + return left?left->_find(k):NULL; + else if(k > data[n-1].key) + return right?right->_find(k):NULL; + + //! return index of data item with key <= k + + FLEXT_ASSERT(n); + int ix = 0; + { + int b = n; + while(ix != b) { + const int c = (ix+b)/2; + const size_t dk = data[c].key; + if(k == dk) + return data[c].value; + else if(k < dk) + b = c; + else if(ix < c) + ix = c; + else { + ix = b; + break; + } + } + } + + if(data[ix].key == k) + return data[ix].value; + else + return NULL; +} + +void TableAnyMap::iterator::forward() +{ + if(map || ix >= map->n) { + if(++ix >= map->n) { + TableAnyMap *nmap; + + // we reached the end of the slots + if(map->right) { + // climb up one + map = map->right; + leftmost(); + ix = 0; + } + else { + // fall back + for(;;) { + nmap = map->parent; + if(!nmap) break; // no parent + if(nmap->left == map) { + // ok, we are in front of the slots now + ix = 0; + map = nmap; + break; + } + else { + FLEXT_ASSERT(nmap->right == map); + ix = (map = nmap)->n; + } + } + } + } + } +} diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h index b2a157c6..7aef0c85 100644 --- a/externals/grill/flext/source/flsupport.h +++ b/externals/grill/flext/source/flsupport.h @@ -545,18 +545,18 @@ public: // --- atom list stuff ------------------------------------------- //! Class representing a list of atoms - class FLEXT_SHARE AtomList: - public flext_root + class FLEXT_SHARE AtomList + : public flext_root { public: //! Construct list AtomList(): cnt(0),lst(NULL) {} //! Construct list - AtomList(int argc,const t_atom *argv = NULL); + AtomList(int argc,const t_atom *argv = NULL): cnt(0),lst(NULL) { operator()(argc,argv); } //! Construct list - AtomList(const AtomList &a); + AtomList(const AtomList &a): cnt(0),lst(NULL) { operator =(a); } //! Destroy list - ~AtomList(); + virtual ~AtomList(); //! Clear list AtomList &Clear() { return operator()(); } @@ -615,10 +615,40 @@ public: bool Print(char *buffer,int buflen) const { return flext::PrintList(Count(),Atoms(),buffer,buflen); } protected: + virtual void Alloc(int sz); + virtual void Free(); + int cnt; t_atom *lst; }; + class FLEXT_SHARE AtomListStaticBase + : public AtomList + { + protected: + AtomListStaticBase(int pc,t_atom *dt): precnt(pc),predata(dt) {} + virtual ~AtomListStaticBase(); + virtual void Alloc(int sz); + virtual void Free(); + + const int precnt; + t_atom *const predata; + }; + + template + class FLEXT_SHARE AtomListStatic + : public AtomListStaticBase + { + public: + //! Construct list + AtomListStatic(): AtomListStaticBase(PRE,pre) {} + //! Construct list + AtomListStatic(int argc,const t_atom *argv = NULL): AtomListStaticBase(PRE,pre) { operator()(argc,argv); } + //! Construct list + AtomListStatic(const AtomList &a): AtomListStaticBase(PRE,pre) { operator =(a); } + protected: + t_atom pre[PRE]; + }; //! Class representing an "anything" class FLEXT_SHARE AtomAnything: @@ -628,12 +658,19 @@ public: AtomAnything(): hdr(NULL) {} #if FLEXT_SYS != FLEXT_SYS_JMAX //! Construct anything - AtomAnything(const t_symbol *h,int argc = 0,const t_atom *argv = NULL); + AtomAnything(const t_symbol *h,int argc = 0,const t_atom *argv = NULL) + : AtomList(argc,argv),hdr(h?h:sym__) + {} #endif //! Construct anything - AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL); + AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL) + : AtomList(argc,argv),hdr(MakeSymbol(h)) + {} + //! Construct anything - AtomAnything(const AtomAnything &a); + AtomAnything(const AtomAnything &a) + : AtomList(a),hdr(a.hdr) + {} //! Clear anything AtomAnything &Clear() { return operator()(); } -- cgit v1.2.1