Add Javascript functions and test cases to help work with JSON.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1081204 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d1d9ba0e29
commit
a1581d7fde
8 changed files with 441 additions and 5 deletions
|
@ -25,5 +25,9 @@ EXTRA_DIST = htdocs/*.js htdocs/*.css
|
|||
js_test_SOURCES = js-test.cpp
|
||||
js_test_LDFLAGS = -lmozjs
|
||||
|
||||
noinst_PROGRAMS = js-test
|
||||
TESTS = js-test
|
||||
js_eval_SOURCES = js-eval.cpp
|
||||
js_eval_LDFLAGS = -lmozjs
|
||||
|
||||
noinst_PROGRAMS = js-test js-eval
|
||||
dist_noinst_SCRIPTS = util-test
|
||||
TESTS = js-test util-test
|
||||
|
|
|
@ -31,11 +31,11 @@
|
|||
* Client component wiring API, supporting JSON and ATOM bindings.
|
||||
*/
|
||||
|
||||
var JSONClient = {};
|
||||
|
||||
/**
|
||||
* Escape a character.
|
||||
*/
|
||||
var JSONClient = {};
|
||||
|
||||
JSONClient.escapeJSONChar = function(c) {
|
||||
if(c == "\"" || c == "\\") return "\\" + c;
|
||||
if (c == "\b") return "\\b";
|
||||
|
|
259
sca-cpp/trunk/modules/js/htdocs/jsonutil.js
Normal file
259
sca-cpp/trunk/modules/js/htdocs/jsonutil.js
Normal file
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JSON data conversion functions.
|
||||
*/
|
||||
var json = {};
|
||||
|
||||
/**
|
||||
* JSON exceptions.
|
||||
*/
|
||||
json.Exception = function(code, message) {
|
||||
this.name = "JSONException";
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
};
|
||||
|
||||
json.Exception.prototype = new Error();
|
||||
|
||||
json.Exception.prototype.toString = function() {
|
||||
return this.name + ": " + this.message;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return true if a list represents a JS array.
|
||||
*/
|
||||
json.isJSArray = function(l) {
|
||||
if (isNil(l))
|
||||
return true;
|
||||
var v = car(l);
|
||||
if (isSymbol(v))
|
||||
return false;
|
||||
if (isList(v))
|
||||
if (!isNil(v) && isSymbol(car(v)))
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts JSON properties to values.
|
||||
*/
|
||||
json.jsPropertiesToValues = function(propertiesSoFar, o, i) {
|
||||
if (isNil(i))
|
||||
return propertiesSoFar;
|
||||
var p = car(i);
|
||||
var jsv = o[p];
|
||||
var v = json.jsValToValue(jsv);
|
||||
|
||||
if (typeof p == 'string') {
|
||||
var n = '' + p;
|
||||
if (n.slice(0, 1) == '@')
|
||||
return json.jsPropertiesToValues(cons(mklist(attribute, "'" + n.slice(1), v), propertiesSoFar), o, cdr(i));
|
||||
if (isList(v) && !json.isJSArray(v))
|
||||
return json.jsPropertiesToValues(cons(cons(element, cons("'" + n, v)), propertiesSoFar), o, cdr(i));
|
||||
return json.jsPropertiesToValues(cons(mklist(element, "'" + n, v), propertiesSoFar), o, cdr(i));
|
||||
}
|
||||
return json.jsPropertiesToValues(cons(v, propertiesSoFar), o, cdr(i));
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a JSON val to a value.
|
||||
*/
|
||||
json.jsValToValue = function(jsv) {
|
||||
if (isList(jsv))
|
||||
return json.jsPropertiesToValues(mklist(), jsv, reverse(range(0, jsv.length)));
|
||||
if (typeof jsv == 'object')
|
||||
return json.jsPropertiesToValues(mklist(), jsv, properties(jsv));
|
||||
if (typeof jsv == 'string')
|
||||
return '' + jsv;
|
||||
return jsv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a list of strings contains a JSON document.
|
||||
*/
|
||||
json.isJSON = function(l) {
|
||||
if (isNil(l))
|
||||
return false;
|
||||
var s = car(l).slice(0, 1);
|
||||
return s == "[" || s == "{";
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a list of strings representing a JSON document to a list of values.
|
||||
*/
|
||||
json.readJSON = function(l) {
|
||||
var s = writeStrings(l);
|
||||
var obj;
|
||||
eval('obj = { \"val\": ' + s + " }");
|
||||
return json.jsValToValue(obj.val);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a list of values to JSON array elements.
|
||||
*/
|
||||
json.valuesToJSElements = function(a, l, i) {
|
||||
if (isNil(l))
|
||||
return a;
|
||||
var pv = json.valueToJSVal(car(l));
|
||||
a[i] = pv
|
||||
return json.valuesToJSElements(a, cdr(l), i + 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a value to a JSON value.
|
||||
*/
|
||||
json.valueToJSVal = function(v) {
|
||||
if (!isList(v))
|
||||
return v;
|
||||
if (json.isJSArray(v))
|
||||
return json.valuesToJSElements(range(0, v.length), v, 0);
|
||||
return json.valuesToJSProperties({}, v);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a list of values to JSON properties.
|
||||
*/
|
||||
json.valuesToJSProperties = function(o, l) {
|
||||
if (isNil(l))
|
||||
return o;
|
||||
var token = car(l);
|
||||
if (isTaggedList(token, attribute)) {
|
||||
var pv = json.valueToJSVal(attributeValue(token));
|
||||
o['@' + attributeName(token).slice(1)] = pv;
|
||||
} else if (isTaggedList(token, element)) {
|
||||
if (elementHasValue(token)) {
|
||||
var pv = json.valueToJSVal(elementValue(token));
|
||||
o[elementName(token).slice(1)] = pv;
|
||||
} else {
|
||||
var child = {};
|
||||
o[elementName(token).slice(1)] = child;
|
||||
json.valuesToJSProperties(child, elementChildren(token));
|
||||
}
|
||||
}
|
||||
return json.valuesToJSProperties(o, cdr(l));
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a list of values to a list of strings representing a JSON document.
|
||||
*/
|
||||
json.writeJSON = function(l) {
|
||||
var jsv;
|
||||
if (json.isJSArray(l))
|
||||
jsv = json.valuesToJSElements(range(0, l.length), l, 0);
|
||||
else
|
||||
jsv = json.valuesToJSProperties({}, l);
|
||||
var s = json.toJSON(jsv);
|
||||
return mklist(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a list + params to a JSON-RPC request.
|
||||
*/
|
||||
json.jsonRequest = function(id, func, params) {
|
||||
var r = mklist(mklist("'id", id), mklist("'method", func), mklist("'params", params));
|
||||
return json.writeJSON(valuesToElements(r));
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a value to a JSON-RPC result.
|
||||
*/
|
||||
json.jsonResult = function(id, val) {
|
||||
return json.writeJSON(valuesToElements(mklist(mklist("'id", id), mklist("'result", val))));
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a JSON-RPC result to a value.
|
||||
*/
|
||||
json.jsonResultValue = function(s) {
|
||||
var jsres = json.readJSON(s);
|
||||
var res = elementsToValues(jsres);
|
||||
var val = cadr(assoc("'result", res));
|
||||
if (isList(val) && !json.isJSArray(val))
|
||||
return mklist(val);
|
||||
return val;
|
||||
};
|
||||
|
||||
/**
|
||||
* Escape a character.
|
||||
*/
|
||||
json.escapeJSONChar = function(c) {
|
||||
if(c == "\"" || c == "\\") return "\\" + c;
|
||||
if (c == "\b") return "\\b";
|
||||
if (c == "\f") return "\\f";
|
||||
if (c == "\n") return "\\n";
|
||||
if (c == "\r") return "\\r";
|
||||
if (c == "\t") return "\\t";
|
||||
var hex = c.charCodeAt(0).toString(16);
|
||||
if(hex.length == 1) return "\\u000" + hex;
|
||||
if(hex.length == 2) return "\\u00" + hex;
|
||||
if(hex.length == 3) return "\\u0" + hex;
|
||||
return "\\u" + hex;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode a string into JSON format.
|
||||
*/
|
||||
json.escapeJSONString = function(s) {
|
||||
// The following should suffice but Safari's regex is broken (doesn't support callback substitutions)
|
||||
// return "\"" + s.replace(/([^\u0020-\u007f]|[\\\"])/g, json.escapeJSONChar) + "\"";
|
||||
|
||||
// Rather inefficient way to do it
|
||||
var parts = s.split("");
|
||||
for(var i = 0; i < parts.length; i++) {
|
||||
var c = parts[i];
|
||||
if(c == '"' || c == '\\' || c.charCodeAt(0) < 32 || c.charCodeAt(0) >= 128)
|
||||
parts[i] = json.escapeJSONChar(parts[i]);
|
||||
}
|
||||
return "\"" + parts.join("") + "\"";
|
||||
};
|
||||
|
||||
/**
|
||||
* Marshall objects to JSON format.
|
||||
*/
|
||||
json.toJSON = function(o) {
|
||||
if(o == null)
|
||||
return "null";
|
||||
if(o.constructor == String)
|
||||
return json.escapeJSONString(o);
|
||||
if(o.constructor == Number)
|
||||
return o.toString();
|
||||
if(o.constructor == Boolean)
|
||||
return o.toString();
|
||||
if(o.constructor == Date)
|
||||
return '{javaClass: "java.util.Date", time: ' + o.valueOf() +'}';
|
||||
if(o.constructor == Array) {
|
||||
var v = [];
|
||||
for(var i = 0; i < o.length; i++)
|
||||
v.push(json.toJSON(o[i]));
|
||||
return "[" + v.join(", ") + "]";
|
||||
}
|
||||
var v = [];
|
||||
for(attr in o) {
|
||||
if(o[attr] == null)
|
||||
v.push("\"" + attr + "\": null");
|
||||
else if(typeof o[attr] == "function")
|
||||
; // Skip
|
||||
else
|
||||
v.push(json.escapeJSONString(attr) + ": " + json.toJSON(o[attr]));
|
||||
}
|
||||
return "{" + v.join(", ") + "}";
|
||||
};
|
||||
|
|
@ -72,6 +72,13 @@ function reverse(l) {
|
|||
return l.slice(0).reverse();
|
||||
}
|
||||
|
||||
function range(a, b) {
|
||||
var l = new Array();
|
||||
for (var x = a; x < b; x++)
|
||||
l.push(x);
|
||||
return l;
|
||||
}
|
||||
|
||||
function isNil(v) {
|
||||
if (v == null || typeof v == 'undefined' || (v.constructor == Array && v.length == 0))
|
||||
return true;
|
||||
|
@ -85,7 +92,7 @@ function isSymbol(v) {
|
|||
}
|
||||
|
||||
function isString(v) {
|
||||
if (typeof v == 'string')
|
||||
if (typeof v == 'string' && v.slice(0, 1) != "'")
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -198,6 +205,21 @@ function debug(o) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple assert function.
|
||||
*/
|
||||
function AssertException() {
|
||||
}
|
||||
|
||||
AssertException.prototype.toString = function () {
|
||||
return 'AssertException';
|
||||
};
|
||||
|
||||
function assert(exp) {
|
||||
if (!exp)
|
||||
throw new AssertException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a list of strings.
|
||||
*/
|
||||
|
@ -251,6 +273,16 @@ function unmemo(obj) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the properties of an object.
|
||||
*/
|
||||
function properties(o) {
|
||||
var a = new Array();
|
||||
for (p in o)
|
||||
a.push(p);
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions with side effects. Use with moderation.
|
||||
*/
|
||||
|
|
55
sca-cpp/trunk/modules/js/js-eval.cpp
Normal file
55
sca-cpp/trunk/modules/js/js-eval.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/* $Rev$ $Date$ */
|
||||
|
||||
/**
|
||||
* Evaluate a JavaScript script.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "stream.hpp"
|
||||
#include "fstream.hpp"
|
||||
#include "string.hpp"
|
||||
#include "eval.hpp"
|
||||
|
||||
namespace tuscany {
|
||||
namespace js {
|
||||
|
||||
bool eval() {
|
||||
ostringstream os;
|
||||
for(;;) {
|
||||
int c = cin.get();
|
||||
if (c == -1)
|
||||
break;
|
||||
os << (char)c;
|
||||
}
|
||||
failable<value> v = evalScript(str(os));
|
||||
assert(hasContent(v));
|
||||
cout << v;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
tuscany::js::eval();
|
||||
return 0;
|
||||
}
|
51
sca-cpp/trunk/modules/js/json-test.js
Normal file
51
sca-cpp/trunk/modules/js/json-test.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test JSON data encoding functions.
|
||||
*/
|
||||
function testJSON() {
|
||||
var ad = mklist(mklist(attribute, "'city", "san francisco"), mklist(attribute, "'state", "ca"));
|
||||
var ac = mklist(mklist(element, "'id", "1234"), mklist(attribute, "'balance", 1000));
|
||||
var cr = mklist(mklist(attribute, "'name", "jdoe"), cons(element, cons("'address", ad)), cons(element, cons("'account", ac)));
|
||||
var c = mklist(cons(element, cons("'customer", cr)));
|
||||
var s = json.writeJSON(c);
|
||||
assert(car(s) == "{\"customer\": {\"@name\": \"jdoe\", \"address\": {\"@city\": \"san francisco\", \"@state\": \"ca\"}, \"account\": {\"id\": \"1234\", \"@balance\": 1000}}}");
|
||||
|
||||
var phones = mklist("408-1234", "650-1234");
|
||||
var l = mklist(mklist(element, "'phones", phones), mklist(element, "'lastName", "test\ttab"), mklist(attribute, "'firstName", "test1"));
|
||||
var s2 = json.writeJSON(l);
|
||||
assert(car(s2) == "{\"phones\": [\"408-1234\", \"650-1234\"], \"lastName\": \"test\\ttab\", \"@firstName\": \"test1\"}");
|
||||
|
||||
var r = json.readJSON(s2);
|
||||
var w = json.writeJSON(r);
|
||||
assert(car(w) == "{\"@firstName\": \"test1\", \"lastName\": \"test\\ttab\", \"phones\": [\"408-1234\", \"650-1234\"]}");
|
||||
|
||||
var l4 = mklist(mklist("'ns1:echoString", mklist("'@xmlns:ns1", "http://ws.apache.org/axis2/services/echo"), mklist("'text", "Hello World!")));
|
||||
var s4 = json.writeJSON(valuesToElements(l4));
|
||||
assert(car(s4) == "{\"ns1:echoString\": {\"@xmlns:ns1\": \"http://ws.apache.org/axis2/services/echo\", \"text\": \"Hello World!\"}}");
|
||||
|
||||
var r5 = elementsToValues(json.readJSON(s4));
|
||||
var s5 = json.writeJSON(valuesToElements(r5));
|
||||
assert(car(s5) == "{\"ns1:echoString\": {\"text\": \"Hello World!\", \"@xmlns:ns1\": \"http://ws.apache.org/axis2/services/echo\"}}");
|
||||
return true;
|
||||
}
|
||||
|
||||
testJSON();
|
||||
|
30
sca-cpp/trunk/modules/js/util-test
Executable file
30
sca-cpp/trunk/modules/js/util-test
Executable file
|
@ -0,0 +1,30 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# Run Javascript util test cases
|
||||
here=`readlink -f $0`; here=`dirname $here`
|
||||
|
||||
echo "Testing..."
|
||||
cat htdocs/util.js htdocs/elemutil.js htdocs/jsonutil.js json-test.js | ./js-eval 2>/dev/null 1>&2
|
||||
rc=$?
|
||||
if [ "$rc" = "0" ]; then
|
||||
echo "OK"
|
||||
fi
|
||||
|
||||
return $rc
|
|
@ -61,6 +61,7 @@ Alias /util.js $jsprefix/htdocs/util.js
|
|||
Alias /elemutil.js $jsprefix/htdocs/elemutil.js
|
||||
Alias /xmlutil.js $jsprefix/htdocs/xmlutil.js
|
||||
Alias /atomutil.js $jsprefix/htdocs/atomutil.js
|
||||
Alias /jsonutil.js $jsprefix/htdocs/jsonutil.js
|
||||
Alias /ui.js $jsprefix/htdocs/ui.js
|
||||
Alias /ui.css $jsprefix/htdocs/ui.css
|
||||
Alias /scdl.js $jsprefix/htdocs/scdl.js
|
||||
|
@ -85,6 +86,10 @@ Require all granted
|
|||
AuthType None
|
||||
Require all granted
|
||||
</Location>
|
||||
<Location /jsonutil.js>
|
||||
AuthType None
|
||||
Require all granted
|
||||
</Location>
|
||||
<Location /ui.js>
|
||||
AuthType None
|
||||
Require all granted
|
||||
|
|
Loading…
Add table
Reference in a new issue