Moved methods to the JS library that stringify objects to JSON format.

git-svn-id: http://voip.null.ro/svn/yate@6317 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
oana 2018-06-15 13:39:48 +00:00
parent dcc1217f84
commit 1a8b055ed2
3 changed files with 168 additions and 147 deletions

View File

@ -245,6 +245,148 @@ void JsObject::printRecursive(const GenObject* obj)
Output("%s",buf.c_str());
}
String JsObject::strEscape(const char* str)
{
String s("\"");
char c;
while (str && (c = *str++)) {
switch (c) {
case '\"':
case '\\':
s += "\\";
break;
case '\b':
s += "\\b";
continue;
case '\f':
s += "\\f";
continue;
case '\n':
s += "\\n";
continue;
case '\r':
s += "\\r";
continue;
case '\t':
s += "\\t";
continue;
case '\v':
s += "\\v";
continue;
}
s += c;
}
s += "\"";
return s;
}
ExpOperation* JsObject::toJSON(const ExpOperation* oper, int spaces)
{
if (!oper || YOBJECT(JsFunction,oper) || YOBJECT(ExpFunction,oper) || JsParser::isUndefined(*oper))
return 0;
if (spaces < 0)
spaces = 0;
else if (spaces > 10)
spaces = 10;
ExpOperation* ret = new ExpOperation("","JSON");
toJSON(oper,*ret,spaces);
return ret;
}
void JsObject::toJSON(const NamedString* ns, String& buf, int spaces, int indent)
{
const ExpOperation* oper = YOBJECT(ExpOperation,ns);
if (!oper) {
if (ns)
buf << strEscape(*ns);
else
buf << "null";
return;
}
if (JsParser::isNull(*oper) || JsParser::isUndefined(*oper) || YOBJECT(JsFunction,oper)
|| YOBJECT(ExpFunction,oper)) {
buf << "null";
return;
}
const char* nl = spaces ? "\r\n" : "";
JsObject* jso = YOBJECT(JsObject,oper);
JsArray* jsa = YOBJECT(JsArray,jso);
if (jsa) {
if (jsa->length() <= 0) {
buf << "[]";
return;
}
String li(' ',indent);
String ci(' ',indent + spaces);
buf << "[" << nl;
for (int32_t i = 0; ; ) {
buf << ci;
const NamedString* p = jsa->params().getParam(String(i));
if (p)
toJSON(p,buf,spaces,indent + spaces);
else
buf << "null";
if (++i < jsa->length())
buf << "," << nl;
else {
buf << nl;
break;
}
}
buf << li << "]";
return;
}
if (jso) {
switch (jso->params().count()) {
case 1:
if (!jso->params().getParam(protoName()))
break;
// fall through
case 0:
buf << "{}";
return;
}
ObjList* l = jso->params().paramList()->skipNull();
String li(' ',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;
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)
buf << ",";
buf << nl;
}
buf << li << "}";
return;
}
if (oper->isBoolean())
buf << String::boolText(oper->valBoolean());
else if (oper->isNumber()) {
if (oper->isInteger())
buf << oper->number();
else
buf << "null";
}
else
buf << strEscape(*oper);
}
void JsObject::setPrototype(GenObject* context, const String& objName)
{
ScriptContext* ctxt = YOBJECT(ScriptContext,context);

View File

@ -2166,6 +2166,14 @@ public:
*/
static void printRecursive(const GenObject* obj);
/**
* Static method to obtain a JSON representation of the given object
* @param oper Object to represent in JSON format
* @param spaces Number of spaces used for one indentation level
* @return String represention of the object
*/
static ExpOperation* toJSON(const ExpOperation* oper, int spaces);
protected:
/**
* Try to evaluate a single native method
@ -2184,6 +2192,22 @@ protected:
inline Mutex* mutex() const
{ return m_mutex; }
/**
* Static method to obtain a JSON representation of the given object
* @param ns Object to represent in JSON format
* @param buf String used as output for the JSON represantion
* @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 helper method for escaping special characters when JSON stringifying
* @param str String to escape
* @return Escaped string
*/
static String strEscape(const char* str);
private:
static const String s_protoName;
bool m_frozen;

View File

@ -736,10 +736,7 @@ public:
static void initialize(ScriptContext* context);
protected:
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
static ExpOperation* stringify(const ExpOperation* oper, int spaces);
static void stringify(const NamedString* ns, String& buf, int spaces, int indent = 0);
void replaceParams(GenObject* obj, const NamedList& params, bool sqlEsc, char extraEsc);
static String strEscape(const char* str);
};
class JsDNS : public JsObject
@ -3965,7 +3962,7 @@ bool JsJSON::runNative(ObjList& stack, const ExpOperation& oper, GenObject* cont
if (extractArgs(stack,oper,context,args) < 1)
return false;
int spaces = args[2] ? static_cast<ExpOperation*>(args[2])->number() : 0;
ExpOperation* op = stringify(static_cast<ExpOperation*>(args[0]),spaces);
ExpOperation* op = JsObject::toJSON(static_cast<ExpOperation*>(args[0]),spaces);
if (!op)
op = new ExpWrapper(0,"JSON");
ExpEvaluator::pushOne(stack,op);
@ -4001,7 +3998,7 @@ bool JsJSON::runNative(ObjList& stack, const ExpOperation& oper, GenObject* cont
if (ok) {
ok = false;
int spaces = args[2] ? static_cast<ExpOperation*>(args[2])->number() : 0;
ExpOperation* op = stringify(static_cast<ExpOperation*>(args[1]),spaces);
ExpOperation* op = JsObject::toJSON(static_cast<ExpOperation*>(args[1]),spaces);
if (op) {
File f;
if (f.openPath(*file,true,false,true)) {
@ -4032,113 +4029,6 @@ bool JsJSON::runNative(ObjList& stack, const ExpOperation& oper, GenObject* cont
return true;
}
ExpOperation* JsJSON::stringify(const ExpOperation* oper, int spaces)
{
if (!oper || YOBJECT(JsFunction,oper) || YOBJECT(ExpFunction,oper) || JsParser::isUndefined(*oper))
return 0;
if (spaces < 0)
spaces = 0;
else if (spaces > 10)
spaces = 10;
ExpOperation* ret = new ExpOperation("","JSON");
stringify(oper,*ret,spaces);
return ret;
}
void JsJSON::stringify(const NamedString* ns, String& buf, int spaces, int indent)
{
const ExpOperation* oper = YOBJECT(ExpOperation,ns);
if (!oper) {
if (ns)
buf << strEscape(*ns);
else
buf << "null";
return;
}
if (JsParser::isNull(*oper) || JsParser::isUndefined(*oper) || YOBJECT(JsFunction,oper)
|| YOBJECT(ExpFunction,oper)) {
buf << "null";
return;
}
const char* nl = spaces ? "\r\n" : "";
JsObject* jso = YOBJECT(JsObject,oper);
JsArray* jsa = YOBJECT(JsArray,jso);
if (jsa) {
if (jsa->length() <= 0) {
buf << "[]";
return;
}
String li(' ',indent);
String ci(' ',indent + spaces);
buf << "[" << nl;
for (int32_t i = 0; ; ) {
buf << ci;
const NamedString* p = jsa->params().getParam(String(i));
if (p)
stringify(p,buf,spaces,indent + spaces);
else
buf << "null";
if (++i < jsa->length())
buf << "," << nl;
else {
buf << nl;
break;
}
}
buf << li << "]";
return;
}
if (jso) {
switch (jso->params().count()) {
case 1:
if (!jso->params().getParam(protoName()))
break;
// fall through
case 0:
buf << "{}";
return;
}
ObjList* l = jso->params().paramList()->skipNull();
String li(' ',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;
buf << ci << strEscape(p->name()) << sep;
stringify(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)
buf << ",";
buf << nl;
}
buf << li << "}";
return;
}
if (oper->isBoolean())
buf << String::boolText(oper->valBoolean());
else if (oper->isNumber()) {
if (oper->isInteger())
buf << oper->number();
else
buf << "null";
}
else
buf << strEscape(*oper);
}
void JsJSON::replaceParams(GenObject* obj, const NamedList& params, bool sqlEsc, char extraEsc)
{
ExpOperation* oper = YOBJECT(ExpOperation,obj);
@ -4168,41 +4058,6 @@ void JsJSON::replaceParams(GenObject* obj, const NamedList& params, bool sqlEsc,
params.replaceParams(*oper,sqlEsc,extraEsc);
}
String JsJSON::strEscape(const char* str)
{
String s("\"");
char c;
while (str && (c = *str++)) {
switch (c) {
case '\"':
case '\\':
s += "\\";
break;
case '\b':
s += "\\b";
continue;
case '\f':
s += "\\f";
continue;
case '\n':
s += "\\n";
continue;
case '\r':
s += "\\r";
continue;
case '\t':
s += "\\t";
continue;
case '\v':
s += "\\v";
continue;
}
s += c;
}
s += "\"";
return s;
}
void JsJSON::initialize(ScriptContext* context)
{
if (!context)