00001 /*
00002 File: SLContext.cc
00003
00004 Function: See header file
00005
00006 Author(s): Andrew Willmott
00007
00008 Copyright: (c) 1995-2000, Andrew Willmott
00009
00010 Notes:
00011
00012 */
00013
00014
00015 #include "gcl/SLContext.h"
00016
00029 const UInt16 slc_EOL = 0x8000;
00030 const UInt16 slc_DaemonFlag = 0x4000;
00031 const UInt16 slc_LevelMask = 0x0FFF;
00032
00033
00034 SLContext::SLContext(Int numAttrs) :
00035 attributeList(numAttrs),
00036 attributeStack()
00037 {
00038 Clear();
00039 }
00040
00041 AttrPtr SLContext::Get(AttrType attrType)
00042 {
00043 if (attributeList[attrType].level & slc_DaemonFlag)
00044 return(attributeList[attrType].daemon->Get());
00045 else
00046 return(attributeList[attrType].data);
00047 }
00048
00049 Void SLContext::Set(AttrType attrType, AttrPtr attrPtr)
00050 {
00051 Assert(attrType < attributeList.NumItems(),
00052 "(SLContext::Set) Unknown attribute type");
00053 AttrRec *pRec = &attributeList[attrType];
00054 AttrStackRec sRec;
00055 Bool isDaemon = (pRec->level & slc_DaemonFlag);
00056
00057 // if the attribute exists and wasn't set this level, push it...
00058
00059 if (pRec->data && (pRec->level & slc_LevelMask) < level)
00060 {
00061 sRec.attrRec = *pRec;
00062 sRec.attrType = attrType;
00063
00064 if (isDaemon)
00065 pRec->daemon->Save();
00066
00067 attributeStack.Push(sRec);
00068 }
00069
00070 if (isDaemon)
00071 pRec->daemon->Set(attrPtr);
00072 else
00073 pRec->data = attrPtr;
00074
00075 pRec->level = level;
00076 }
00077
00078 Void SLContext::SetDaemon(AttrType attrType, AttrDaemon *daemon)
00079 {
00080 Assert((attributeList[attrType].level & slc_DaemonFlag) == 0, "Daemon already set for this slot.");
00081
00082 Set(attrType, daemon);
00083
00084 if (daemon)
00085 attributeList[attrType].level |= slc_DaemonFlag;
00086 }
00087
00088 Void SLContext::Push()
00089 {
00090 AttrStackRec sRec;
00091
00092 level++;
00093 sRec.attrRec.level = slc_EOL; // mark pRec as a sentinel
00094 attributeStack.Push(sRec); // Add to the stack
00095 }
00096
00097 Void SLContext::Pop()
00098 {
00099 Int i;
00100
00101 // pop off all the attributes changed since the last push...
00102
00103 Assert(level > 0, "(SLContext::Pop) Too many pops");
00104
00105 while (!(attributeStack.Top().attrRec.level & slc_EOL))
00106 {
00107 if (attributeStack.Top().attrRec.level & slc_DaemonFlag)
00108 attributeStack.Top().attrRec.daemon->Restore();
00109
00110 attributeList[attributeStack.Top().attrType] =
00111 attributeStack.Top().attrRec;
00112 attributeStack.Pop();
00113 }
00114
00115 // pop off the sentinel...
00116
00117 attributeStack.Pop();
00118 level--;
00119
00120 // zero anything that wasn't previously set at this level.
00121
00122 for (i = 0; i < attributeList.NumItems(); i++)
00123 if ((attributeList[i].level & slc_LevelMask) > level)
00124 {
00125 attributeList[i].data = 0;
00126 attributeList[i].level = 0;
00127 }
00128 }
00129
00130 Bool SLContext::IsCurrent(AttrType attrType)
00131 {
00132 return(attributeList[attrType].level == level);
00133 }
00134
00135 Void SLContext::Clear()
00136 {
00137 Int i;
00138
00139 attributeStack.SetSize(0);
00140 level = 0;
00141
00142 for (i = 0; i < attributeList.NumItems(); i++)
00143 {
00144 attributeList[i].level = 0;
00145 attributeList[i].data = 0;
00146 }
00147 }
00148
00149 ostream &operator << (ostream &s, const AttrRec &ar)
00150 {
00151 s << ar.data << "@" << ar.level;
00152
00153 return(s);
00154 }
00155
00156 ostream &operator << (ostream &s, const AttrStackRec &asr)
00157 {
00158 s << asr.attrRec << ":" << asr.attrType;
00159
00160 return(s);
00161 }
00162
00163 ostream &operator << (ostream &s, const SLContext &ctx)
00164 {
00165 s << "SLContext at level " << ctx.level << ". Current attributes: " << endl;
00166 s << (AttrList &) ctx.attributeList << endl;
00167 s << "Attribute stack: " << endl << (AttrStackList &) ctx.attributeStack << endl;
00168
00169 return(s);
00170 }
00171
00172