/******************************************************************************/ #include "stdafx.h" namespace EE{ /****************************************************************************** '_order' is of length "elms()*2" because it stores indexes sorted by name+id (2 in total per each element) /******************************************************************************/ #define CC4_ENUM CC4('E','N','U','M') #define ENUM_CASE_SENSITIVE false /******************************************************************************/ Cache Enums("Enum"); /******************************************************************************/ Enum::Enum(C Enum &src) : Enum() {T=src;} Enum& Enum::del() { name[0]=0; Free(_order); _elms.del(); return T; } /******************************************************************************/ struct EnumElmPtr { C Enum::Elm *elm; UInt index; void set(C Enum::Elm &elm, UInt index) {T.elm=&elm; T.index=index;} static Int CompareName(C EnumElmPtr &ep0, C EnumElmPtr &ep1) {return Compare(ep0.elm->name, ep1.elm->name, ENUM_CASE_SENSITIVE);} static Int CompareID (C EnumElmPtr &ep0, C EnumElmPtr &ep1) {return Compare(ep0.elm->id , ep1.elm->id );} }; void Enum::sort() { Mems elm_ptr; elm_ptr.setNum(elms().elms()); REPAO(elm_ptr).set(T[i], i); elm_ptr.sort(EnumElmPtr::CompareName); UInt *name_order=nameOrder(); REPA(T)name_order[i]=elm_ptr[i].index; elm_ptr.sort(EnumElmPtr::CompareID ); UInt * id_order= idOrder(); REPA(T) id_order[i]=elm_ptr[i].index; } Enum& Enum::create(C Str &name, C MemPtr &elms) { del(); Set(T.name, name); T._elms=elms; Alloc(_order, T.elms().elms()*2); sort(); return T; } Enum& Enum::operator=(C Enum &src) { if(this!=&src) { Set(name, src.name); _elms=src._elms; CopyN(Alloc(Free(_order), elms().elms()*2), src._order, elms().elms()*2); } return T; } /******************************************************************************/ Int Enum::find(CChar8 *name)C { if(Is(name)) { #if 0 REPA(T)if(Equal(T[i].name, name, ENUM_CASE_SENSITIVE))return i; #else UInt *name_order=nameOrder(); for(Int l=0, r=elms().elms(); l>elm.id;} f.getN(Alloc(_order, elms().elms()*2), elms().elms()*2); if(f.ok())return true; }break; case 2: { f._getStr2(name); _elms.setNum(f.decUIntV()); FREPA(T){Elm &elm=_elms[i]; f._getStr2(elm.name)>>elm.id;} f.getN(Alloc(_order, elms().elms()*2), elms().elms()*2); if(f.ok())return true; }break; case 1: { Set(name, f._getStr()); _elms.setNum(f.decUIntV()); FREPA(T){Elm &elm=_elms[i]; Set(elm.name, f._getStr()); f>>elm.id;} f.getN(Alloc(_order, elms().elms()*2), elms().elms()*2); if(f.ok())return true; }break; case 0: { f.getByte(); // old version byte f>>name; _elms.setNum(f.getInt()); FREPA(T){Elm &elm=_elms[i]; f>>elm.name; elm.id=MD5Mem(Str8(elm.name), Length(elm.name));} f.skip(SIZE(UInt)*elms().elms()); // skip old '_order' if(f.ok()) { Alloc(_order, elms().elms()*2); sort(); return true; } }break; } del(); return false; } /******************************************************************************/ Bool Enum::save(C Str &name)C { File f; if(f.writeTry(name)){if(save(f) && f.flush())return true; f.del(); FDelFile(name);} return false; } Bool Enum::load(C Str &name) { File f; if(f.readTry(name))return load(f); del(); return false; } /******************************************************************************/ Bool Enum::saveH(C Str &name)C { FileText f; if(f.write(name, UTF_8)) // use UTF-8 Encoding because file may get used on Mac XCode GCC which doesn't handle UTF-16 properly { f.putLine("/******************************************************************************/"); f.putLine(S+"enum "+T.name); f.putLine('{').depth++; FREPA(T)f.putLine(S+T[i].name+","); f.depth--; f.putLine("};"); f.putLine("/******************************************************************************/"); return true; } return false; } /******************************************************************************/ void Enum::operator=(C Str &name) {if(!load(name))Exit(S+"Can't load enum \""+name+"\"");} /******************************************************************************/ // MAIN /******************************************************************************/ void ShutEnum() {Enums.del();} /******************************************************************************/ } /******************************************************************************/