Added support to dump JsHashList items in print_r and toJSON.

git-svn-id: http://yate.null.ro/svn/yate/trunk@6439 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2020-10-14 14:03:56 +00:00
parent 166aa682f4
commit eedf31e959
3 changed files with 110 additions and 22 deletions

View File

@ -254,6 +254,17 @@ static void dumpRecursiveObj(const GenObject* obj, String& buf, unsigned int dep
dumpRecursiveObj(wrap->object(),buf,depth + 1,seen,flags);
else if (nptr)
dumpRecursiveObj(nptr->userData(),buf,depth + 1,seen,flags);
const JsObject* jso = YOBJECT(JsObject,obj);
if (jso) {
const HashList* hash = jso->getHashListParams();
if (hash) {
for (unsigned int i = 0; i < hash->length(); i++) {
ObjList* lst = hash->getList(i);
for (lst ? lst = lst->skipNull() : 0; lst; lst = lst->skipNext())
dumpRecursiveObj(lst->get(),buf,depth + 1,seen,flags);
}
}
}
}
@ -359,12 +370,61 @@ ExpOperation* JsObject::toJSON(const ExpOperation* oper, int spaces)
return ret;
}
void JsObject::toJSON(const NamedString* ns, String& buf, int spaces, int indent)
// Utility: retrieve a JSON candidate from given list item
// Advance the list
// Return pointer to candidate, NULL if not found
static inline GenObject* nextJSONCandidate(ObjList*& crt, bool isNs = true)
{
const ExpOperation* oper = YOBJECT(ExpOperation,ns);
if (!crt)
return 0;
if (!crt->get()) {
crt = crt->skipNull();
if (!crt)
return 0;
}
while (crt) {
GenObject* gen = crt->get();
crt = crt->skipNext();
const String& n = isNs ? static_cast<NamedString*>(gen)->name() : gen->toString();
if (!n || n == JsObject::protoName() || YOBJECT(JsFunction,gen) || YOBJECT(ExpFunction,gen))
continue;
const ExpOperation* op = YOBJECT(ExpOperation,gen);
if (!(op && JsParser::isUndefined(*op)))
return gen;
}
return 0;
}
// Utility: retrieve a JSON candidate from given hash list
// Advance the list
// Return pointer to candidate, NULL if not found
static inline GenObject* nextJSONCandidate(const HashList& hash, unsigned int& idx, ObjList*& crt)
{
GenObject* gen = nextJSONCandidate(crt,false);
if (gen)
return gen;
crt = 0;
while (++idx < hash.length()) {
crt = hash.getList(idx);
if (!crt)
continue;
gen = nextJSONCandidate(crt,false);
if (gen)
return gen;
}
return 0;
}
void JsObject::internalToJSON(const GenObject* obj, bool isStr, String& buf, int spaces, int indent)
{
if (!obj) {
buf << "null";
return;
}
const ExpOperation* oper = YOBJECT(ExpOperation,obj);
if (!oper) {
if (ns)
buf << strEscape(*ns);
if (isStr)
buf << strEscape(*static_cast<const String*>(obj));
else
buf << "null";
return;
@ -407,6 +467,30 @@ void JsObject::toJSON(const NamedString* ns, String& buf, int spaces, int indent
buf << strEscape(jso->toString());
return;
}
const HashList* hash = jso->getHashListParams();
if (hash) {
ObjList* crt = hash->getList(0);
unsigned int idx = 0;
GenObject* gen = nextJSONCandidate(*hash,idx,crt);
if (!gen) {
buf << "{}";
return;
}
String li(' ',indent);
String ci(' ',indent + spaces);
const char* sep = spaces ? ": " : ":";
buf << "{" << nl;
while (gen) {
buf << ci << strEscape(gen->toString()) << sep;
internalToJSON(gen,false,buf,spaces,indent + spaces);
gen = static_cast<NamedString*>(nextJSONCandidate(*hash,idx,crt));
if (gen)
buf << ",";
buf << nl;
}
buf << li << "}";
return;
}
switch (jso->params().count()) {
case 1:
if (!jso->params().getParam(protoName()))
@ -421,24 +505,12 @@ void JsObject::toJSON(const NamedString* ns, String& buf, int spaces, int indent
String ci(' ',indent + spaces);
const char* sep = spaces ? ": " : ":";
buf << "{" << nl;
while (l) {
const NamedString* p = static_cast<const NamedString*>(l->get());
l = l->skipNext();
if (p->name() == protoName() || YOBJECT(JsFunction,p) || YOBJECT(ExpFunction,p))
continue;
const ExpOperation* op = YOBJECT(ExpOperation,p);
if (op && JsParser::isUndefined(*op))
continue;
const NamedString* p = static_cast<NamedString*>(nextJSONCandidate(l));
while (p) {
buf << ci << strEscape(p->name()) << sep;
toJSON(p,buf,spaces,indent + spaces);
for (; l; l = l->skipNext()) {
p = static_cast<const NamedString*>(l->get());
op = YOBJECT(ExpOperation,p);
if (!(p->name() == protoName() || YOBJECT(JsFunction,p) || YOBJECT(ExpFunction,p)
|| (op && JsParser::isUndefined(*op))))
break;
}
if (l)
internalToJSON(p,true,buf,spaces,indent + spaces);
p = static_cast<NamedString*>(nextJSONCandidate(l));
if (p)
buf << ",";
buf << nl;
}
@ -494,6 +566,11 @@ void JsObject::fillFieldNames(ObjList& names)
#endif
}
const HashList* JsObject::getHashListParams() const
{
return 0;
}
bool JsObject::hasField(ObjList& stack, const String& name, GenObject* context) const
{
if (ScriptContext::hasField(stack,name,context))

View File

@ -2040,6 +2040,12 @@ public:
*/
virtual void fillFieldNames(ObjList& names);
/**
* Retrieve enclosed hashed list paramsters
* @return HashList pointer, NULL if this object don't hold one
*/
virtual const HashList* getHashListParams() const;
/**
* Check if a certain field is assigned in the object or its prototype
* @param stack Evaluation stack in use
@ -2335,7 +2341,8 @@ protected:
* @param spaces Number of spaces used for one indentation level
* @param indent Current number of spaces used for indentation
*/
static void toJSON(const NamedString* ns, String& buf, int spaces, int indent = 0);
static inline void toJSON(const NamedString* ns, String& buf, int spaces, int indent = 0)
{ internalToJSON(ns,true,buf,spaces,indent); }
/**
* Static helper method for escaping special characters when JSON stringifying
@ -2345,6 +2352,7 @@ protected:
static String strEscape(const char* str);
private:
static void internalToJSON(const GenObject* obj, bool isStr, String& buf, int spaces, int indent = 0);
static const String s_protoName;
bool m_frozen;
Mutex* m_mutex;

View File

@ -321,6 +321,9 @@ public:
virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context);
virtual void clearField(const String& name)
{ m_list.remove(name); }
virtual const HashList* getHashListParams() const
{ return &m_list; }
protected:
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
private: