Added support for a native implementation of a Javascript HashList.
When generating iterator for JsObjects avoid checking that were not setting duplicates in the iterator. JsObject does not allow setting duplicates. git-svn-id: http://yate.null.ro/svn/yate/trunk@6264 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
e2060c65fe
commit
6f58478394
|
@ -2570,7 +2570,7 @@ bool JsCode::runOperation(ObjList& stack, const ExpOperation& oper, GenObject* c
|
|||
bool ret = false;
|
||||
if (obj && (!obj->frozen() || !obj->hasField(stack,name,context))
|
||||
&& obj->toString() != YSTRING("()")) {
|
||||
obj->params().clearParam(name);
|
||||
obj->clearField(name);
|
||||
ret = true;
|
||||
}
|
||||
DDebug(DebugAll,"Deleted '%s' : %s",name.c_str(),String::boolText(ret));
|
||||
|
|
|
@ -271,7 +271,7 @@ JsObject* JsObject::buildCallContext(Mutex* mtx, JsObject* thisObj)
|
|||
|
||||
void JsObject::fillFieldNames(ObjList& names)
|
||||
{
|
||||
ScriptContext::fillFieldNames(names,params(),"__");
|
||||
ScriptContext::fillFieldNames(names,params(),false,"__");
|
||||
const NamedList* native = nativeParams();
|
||||
if (native)
|
||||
ScriptContext::fillFieldNames(names,*native);
|
||||
|
|
|
@ -184,7 +184,8 @@ bool ScriptContext::copyFields(ObjList& stack, const ScriptContext& original, Ge
|
|||
|
||||
void ScriptContext::fillFieldNames(ObjList& names)
|
||||
{
|
||||
fillFieldNames(names,params());
|
||||
bool checkDupl = !(YOBJECT(JsObject,this));
|
||||
fillFieldNames(names,params(),checkDupl);
|
||||
const NamedList* native = nativeParams();
|
||||
if (native)
|
||||
fillFieldNames(names,*native);
|
||||
|
@ -195,7 +196,7 @@ void ScriptContext::fillFieldNames(ObjList& names)
|
|||
#endif
|
||||
}
|
||||
|
||||
void ScriptContext::fillFieldNames(ObjList& names, const NamedList& list, const char* skip)
|
||||
void ScriptContext::fillFieldNames(ObjList& names, const NamedList& list, bool checkDupl, const char* skip)
|
||||
{
|
||||
ObjList* tail = &names;
|
||||
for (const ObjList* l = list.paramList()->skipNull(); l; l = l->skipNext()) {
|
||||
|
@ -204,12 +205,25 @@ void ScriptContext::fillFieldNames(ObjList& names, const NamedList& list, const
|
|||
continue;
|
||||
if (skip && s->name().startsWith(skip))
|
||||
continue;
|
||||
if (names.find(s->name()))
|
||||
if (checkDupl && names.find(s->name()))
|
||||
continue;
|
||||
tail = tail->append(new String(s->name()));
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptContext::fillFieldNames(ObjList& names, const HashList& list)
|
||||
{
|
||||
ObjList* tail = &names;
|
||||
for (unsigned int i = 0; i < list.length(); i++) {
|
||||
ObjList* o = list.getList(i);
|
||||
for (o = o ? o->skipNull() : 0;o;o = o->skipNext()) {
|
||||
GenObject* obj = o->get();
|
||||
if (obj->toString().null())
|
||||
continue;
|
||||
tail = tail->append(new String(obj->toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define MAKE_NAME(x) { #x, ScriptRun::x }
|
||||
static const TokenDict s_states[] = {
|
||||
|
|
|
@ -1469,9 +1469,17 @@ public:
|
|||
* Fill a list with the unique names of all fields
|
||||
* @param names List to which key names must be added
|
||||
* @param list List of parameters whose names to be added
|
||||
* @param checkDupl True to ignore duplicates from the given list
|
||||
* @param skip Parameters starting with this prefix will not be added
|
||||
*/
|
||||
static void fillFieldNames(ObjList& names, const NamedList& list, const char* skip = 0);
|
||||
static void fillFieldNames(ObjList& names, const NamedList& list, bool checkDupl = true, const char* skip = 0);
|
||||
|
||||
/**
|
||||
* Fill a list with the unique names from a Hash list
|
||||
* @param names List to which key names must be added
|
||||
* @param list Hash list whose names are to be added
|
||||
*/
|
||||
static void fillFieldNames(ObjList& names, const HashList& list);
|
||||
|
||||
/**
|
||||
* Try to evaluate a single function in the context
|
||||
|
@ -2050,6 +2058,13 @@ public:
|
|||
*/
|
||||
virtual ExpOperation* popValue(ObjList& stack, GenObject* context = 0);
|
||||
|
||||
/**
|
||||
* Delete a field of the object
|
||||
* @param name Name of field to remove
|
||||
*/
|
||||
virtual void clearField(const String& name)
|
||||
{ params().clearParam(name); }
|
||||
|
||||
/**
|
||||
* Retrieve the object frozen status (cannot modify attributes or methods)
|
||||
* @return True if the object is frozen
|
||||
|
|
|
@ -255,6 +255,37 @@ private:
|
|||
bool m_exit;
|
||||
};
|
||||
|
||||
class JsHashList : public JsObject
|
||||
{
|
||||
public:
|
||||
inline JsHashList(Mutex* mtx)
|
||||
: JsObject("HashList",mtx,true),
|
||||
m_list()
|
||||
{
|
||||
XDebug(DebugAll,"JsHashList::JsHashList() [%p]",this);
|
||||
}
|
||||
inline JsHashList(unsigned int size, Mutex* mtx)
|
||||
: JsObject(mtx,"[object HashList]",false),
|
||||
m_list(size)
|
||||
{
|
||||
XDebug(DebugAll,"JsHashList::JsHashList(%u) [%p]",size,this);
|
||||
}
|
||||
virtual ~JsHashList()
|
||||
{
|
||||
XDebug(DebugAll,"~JsHashList() [%p]",this);
|
||||
m_list.clear();
|
||||
}
|
||||
virtual void* getObject(const String& name) const;
|
||||
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
virtual void fillFieldNames(ObjList& names);
|
||||
virtual bool runField(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
virtual void clearField(const String& name)
|
||||
{ m_list.remove(name); }
|
||||
private:
|
||||
HashList m_list;
|
||||
};
|
||||
|
||||
#define MKDEBUG(lvl) params().addParam(new ExpOperation((int64_t)Debug ## lvl,"Debug" # lvl))
|
||||
#define MKTIME(typ) params().addParam(new ExpOperation((int64_t)SysUsage:: typ ## Time,# typ "Time"))
|
||||
class JsEngine : public JsObject, public DebugEnabler
|
||||
|
@ -322,6 +353,7 @@ public:
|
|||
params().addParam(new ExpFunction("btoh"));
|
||||
params().addParam(new ExpFunction("htob"));
|
||||
addConstructor(params(), "Semaphore", new JsSemaphore(mtx));
|
||||
addConstructor(params(),"HashList",new JsHashList(mtx));
|
||||
}
|
||||
static void initialize(ScriptContext* context, const char* name = 0);
|
||||
inline void resetWorker()
|
||||
|
@ -3663,6 +3695,100 @@ void JsXML::initialize(ScriptContext* context)
|
|||
addConstructor(params,"XML",new JsXML(mtx));
|
||||
}
|
||||
|
||||
void* JsHashList::getObject(const String& name) const
|
||||
{
|
||||
void* obj = (name == YATOM("JsHashList")) ? const_cast<JsHashList*>(this) : JsObject::getObject(name);
|
||||
if (!obj)
|
||||
obj = m_list.getObject(name);
|
||||
return obj;
|
||||
}
|
||||
|
||||
JsObject* JsHashList::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
XDebug(&__plugin,DebugAll,"JsHashList::runConstructor '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
||||
ObjList args;
|
||||
unsigned int cnt = 17; // default value for HashList
|
||||
switch (extractArgs(stack,oper,context,args)) {
|
||||
case 1:
|
||||
{
|
||||
ExpOperation* op = static_cast<ExpOperation*>(args[0]);
|
||||
if (!op || !op->isInteger() || op->toNumber() <= 0)
|
||||
return 0;
|
||||
cnt = op->toNumber();
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
JsHashList* obj = new JsHashList(cnt,mutex());
|
||||
if (!ref()) {
|
||||
TelEngine::destruct(obj);
|
||||
return 0;
|
||||
}
|
||||
obj->params().addParam(new ExpWrapper(this,protoName()));
|
||||
return obj;
|
||||
}
|
||||
|
||||
void JsHashList::fillFieldNames(ObjList& names)
|
||||
{
|
||||
JsObject::fillFieldNames(names);
|
||||
ScriptContext::fillFieldNames(names,m_list);
|
||||
#ifdef XDEBUG
|
||||
String tmp;
|
||||
tmp.append(names,",");
|
||||
Debug(DebugInfo,"JsHashList::fillFieldNames: %s",tmp.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool JsHashList::runField(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
XDebug(DebugAll,"JsHashList::runField() '%s' in '%s' [%p]",
|
||||
oper.name().c_str(),toString().c_str(),this);
|
||||
ExpOperation* obj = static_cast<ExpOperation*>(m_list[oper.name()]);
|
||||
if (obj) {
|
||||
ExpWrapper* wrp = YOBJECT(ExpWrapper,obj);
|
||||
if (wrp)
|
||||
ExpEvaluator::pushOne(stack,wrp->clone(oper.name()));
|
||||
else
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation(*obj,oper.name()));
|
||||
return true;
|
||||
}
|
||||
return JsObject::runField(stack,oper,context);
|
||||
}
|
||||
|
||||
bool JsHashList::runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
XDebug(DebugAll,"JsHashList::runAssign() '%s'='%s' (%s) in '%s' [%p]",
|
||||
oper.name().c_str(),oper.c_str(),oper.typeOf(),toString().c_str(),this);
|
||||
if (frozen()) {
|
||||
Debug(DebugWarn,"Object '%s' is frozen",toString().c_str());
|
||||
return false;
|
||||
}
|
||||
ObjList* obj = m_list.find(oper.name());
|
||||
ExpOperation* cln = 0;
|
||||
ExpFunction* ef = YOBJECT(ExpFunction,&oper);
|
||||
if (ef)
|
||||
cln = ef->ExpOperation::clone();
|
||||
else {
|
||||
ExpWrapper* w = YOBJECT(ExpWrapper,&oper);
|
||||
if (w) {
|
||||
JsFunction* jsf = YOBJECT(JsFunction,w->object());
|
||||
if (jsf)
|
||||
jsf->firstName(oper.name());
|
||||
cln = w->clone(oper.name());
|
||||
}
|
||||
else
|
||||
cln = oper.clone();
|
||||
}
|
||||
if (!obj)
|
||||
m_list.append(cln);
|
||||
else
|
||||
obj->set(cln);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsJSON::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue