diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-16 06:57:41 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-16 06:57:41 +0000 |
commit | bd0fdbf902f8ca8e7e352582efe938e1d6743dd1 (patch) | |
tree | 4ffc871e04f7e22cad2a6ed1d921718e296dc5fe /cpp/sca/modules/json | |
parent | 2cd577564c1e4a37b25f4064b84af15d112b0654 (diff) |
Cleaning up SVN structure, moving sca trunk to sca-cpp/trunk.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@880633 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/sca/modules/json')
-rw-r--r-- | cpp/sca/modules/json/Makefile.am | 28 | ||||
-rw-r--r-- | cpp/sca/modules/json/json-test.cpp | 142 | ||||
-rw-r--r-- | cpp/sca/modules/json/json.hpp | 396 |
3 files changed, 0 insertions, 566 deletions
diff --git a/cpp/sca/modules/json/Makefile.am b/cpp/sca/modules/json/Makefile.am deleted file mode 100644 index ab85d910ad..0000000000 --- a/cpp/sca/modules/json/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -# 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. - -noinst_PROGRAMS = json-test - -nobase_include_HEADERS = *.hpp - -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -I${LIBMOZJS_INCLUDE} - -json_test_SOURCES = json-test.cpp -json_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${LIBMOZJS_LIB} -lmozjs - -TESTS = json-test - diff --git a/cpp/sca/modules/json/json-test.cpp b/cpp/sca/modules/json/json-test.cpp deleted file mode 100644 index fd506cea65..0000000000 --- a/cpp/sca/modules/json/json-test.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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$ */ - -/** - * Test JSON data conversion functions. - */ - -#include <assert.h> -#include <iostream> -#include <sstream> -#include <string> -#include "slist.hpp" -#include "json.hpp" - -namespace tuscany { -namespace json { - -bool testJSEval() { - JSONContext cx; - const std::string script("(function testJSON(n){ return JSON.parse(JSON.stringify(n)) })(5)"); - jsval rval; - assert(JS_EvaluateScript(cx, cx.getGlobal(), script.c_str(), script.length(), "testJSON.js", 1, &rval)); - const std::string r(JS_GetStringBytes(JS_ValueToString(cx, rval))); - assert(r == "5"); - return true; -} - -std::ostringstream* jsonWriter(const std::string& s, std::ostringstream* os) { - (*os) << s; - return os; -} - -bool testJSON() { - const JSONContext cx; - - { - const list<value> ad = mklist<value>(mklist<value>(attribute, "city", std::string("san francisco")), mklist<value>(attribute, "state", std::string("ca"))); - const list<value> ac = mklist<value>(mklist<value>(element, "id", std::string("1234")), mklist<value>(attribute, "balance", 1000)); - const list<value> cr = mklist<value>(mklist<value> (attribute, "name", std::string("jdoe")), cons<value>(element, cons<value>("address", ad)), cons<value>(element, cons<value>("account", ac))); - const list<value> c = mklist<value>(cons<value>(element, cons<value>("customer", cr))); - std::ostringstream os; - writeJSON<std::ostringstream*>(jsonWriter, &os, c, cx); - assert(os.str() == "{\"customer\":{\"name\":\"jdoe\",\"address\":{\"city\":\"san francisco\",\"state\":\"ca\"},\"account\":{\"id\":\"1234\",\"balance\":1000}}}"); - } - { - const list<value> phones = mklist<value> (std::string("408-1234"), std::string("650-1234")); - const list<value> l = mklist<value> (mklist<value> (element, "phones", phones), mklist<value> (element, "lastName", std::string("test\ttab")), mklist<value> (element, "firstName", std::string("test1"))); - - std::ostringstream os; - writeJSON<std::ostringstream*>(jsonWriter, &os, l, cx); - assert(os.str() == "{\"phones\":[\"408-1234\",\"650-1234\"],\"lastName\":\"test\\u0009tab\",\"firstName\":\"test1\"}"); - - std::istringstream is(os.str()); - const list<std::string> il = streamList(is); - const list<value> r = readJSON(il, cx); - assert(r == l); - - std::ostringstream wos; - write(writeJSON(r, cx), wos); - assert(wos.str() == os.str()); - } - return true; -} - -bool testJSONRPC() { - JSONContext cx; - { - const std::string lm("{\"id\": 1, \"method\": \"system.listMethods\", \"params\": []}"); - const list<value> e = readJSON(mklist(lm), cx); - const list<value> v = elementsToValues(e); - assert(assoc<value>("id", v) == mklist<value>("id", 1)); - assert(assoc<value>("method", v) == mklist<value>("method", std::string("system.listMethods"))); - assert(assoc<value>("params", v) == mklist<value>("params", list<value>())); - } - { - const std::string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}"); - const list<value> e = readJSON(mklist(i), cx); - const std::string i2("{\"id\":3,\"result\":{\"0\":{\"price\":\"$2.99\",\"name\":\"Apple\"},\"1\":{\"price\":\"$3.55\",\"name\":\"Orange\"},\"2\":{\"price\":\"$1.55\",\"name\":\"Pear\"}}}"); - const list<value> e2 = readJSON(mklist(i), cx); - assert(e == e2); - } - { - const std::string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}"); - const list<value> e = readJSON(mklist(i), cx); - std::ostringstream os; - write(writeJSON(e, cx), os); - assert(os.str() == i); - const list<value> v = elementsToValues(e); - const list<value> r = valuesToElements(v); - assert(r == e); - } - { - const list<value> r = mklist<value>(mklist<value>("id", 1), mklist<value>("result", mklist<value>(std::string("Service.get"), std::string("Service.getTotal")))); - const list<value> e = valuesToElements(r); - std::ostringstream os; - write(writeJSON(e, cx), os); - assert(os.str() == "{\"id\":1,\"result\":[\"Service.get\",\"Service.getTotal\"]}"); - } - { - const std::string f("{\"id\":1,\"result\":[\"Sample Feed\",\"123456789\",[\"Item\",\"111\",{\"javaClass\":\"services.Item\",\"name\":\"Apple\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":2.99}],[\"Item\",\"222\",{\"javaClass\":\"services.Item\",\"name\":\"Orange\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":3.55}],[\"Item\",\"333\",{\"javaClass\":\"services.Item\",\"name\":\"Pear\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":1.55}]]}"); - const list<value> r = readJSON(mklist(f), cx); - const list<value> v = elementsToValues(r); - const list<value> e = valuesToElements(v); - std::ostringstream os; - write(writeJSON(e, cx), os); - assert(os.str() == f); - } - return true; -} - -} -} - -int main() { - std::cout << "Testing..." << std::endl; - - tuscany::json::testJSEval(); - tuscany::json::testJSON(); - tuscany::json::testJSONRPC(); - - std::cout << "OK" << std::endl; - - return 0; -} diff --git a/cpp/sca/modules/json/json.hpp b/cpp/sca/modules/json/json.hpp deleted file mode 100644 index f6c8eb5fe8..0000000000 --- a/cpp/sca/modules/json/json.hpp +++ /dev/null @@ -1,396 +0,0 @@ -/* - * 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$ */ - -#ifndef tuscany_json_hpp -#define tuscany_json_hpp - -/** - * JSON data conversion functions. - */ - -#define XP_UNIX -#include <jsapi.h> -#include <string> -#include "list.hpp" -#include "value.hpp" -#include "element.hpp" -#include "monad.hpp" - -namespace tuscany { -namespace json { - -/** - * Report JSON errors. - */ -void reportError(JSContext *cx, const char *message, JSErrorReport *report) { - std::cerr << (const char*)(report->filename? report->filename : "<no filename>") << ":" - << (unsigned int)report->lineno << ":" << message << std::endl; -} - -/** - * Encapsulates a JavaScript runtime. Can be shared by multiple threads in - * a process. - */ -class JSONRuntime { -public: - JSONRuntime() { - // Create JS runtime - rt = JS_NewRuntime(8L * 1024L * 1024L); - if(rt == NULL) - cleanup(); - } - - ~JSONRuntime() { - } - - operator JSRuntime*() const { - return rt; - } -private: - bool cleanup() { - if(rt != NULL) { - JS_DestroyRuntime(rt); - rt = NULL; - } - JS_ShutDown(); - return true; - } - - JSRuntime* rt; -}; - -/** - * Global JavaScript runtime instance. - */ -JSONRuntime jsRuntime; - -JSClass jsGlobalClass = { "global", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JSCLASS_NO_OPTIONAL_MEMBERS}; - - -/** - * Represents a JavaScript context. Create one per thread. - */ -class JSONContext { -public: - JSONContext() { - // Create JS context - cx = JS_NewContext(jsRuntime, 8192); - if(cx == NULL) - return; - JS_SetOptions(cx, JSOPTION_VAROBJFIX); - JS_SetVersion(cx, JSVERSION_DEFAULT); - JS_SetErrorReporter(cx, reportError); - - // Create global JS object - global = JS_NewObject(cx, &jsGlobalClass, NULL, NULL); - if(global == NULL) { - cleanup(); - return; - } - - // Populate global object with the standard globals, like Object and Array - if(!JS_InitStandardClasses(cx, global)) { - cleanup(); - return; - } - } - - ~JSONContext() { - cleanup(); - } - - operator JSContext*() const { - return cx; - } - - JSObject* getGlobal() const { - return global; - } - -private: - bool cleanup() { - if(cx != NULL) { - JS_DestroyContext(cx); - cx = NULL; - } - return true; - } - - JSContext* cx; - JSObject* global; -}; - -/** - * Converts JS properties to values. - */ -const list<value> jsPropertiesToValues(const list<value>& propertiesSoFar, JSObject* o, JSObject* i, const JSONContext& cx) { - - const value jsValToValue(const jsval& jsv, const JSONContext& cx); - - jsid id; - if(!JS_NextProperty(cx, i, &id) || id == JSVAL_VOID) - return propertiesSoFar; - jsval jsv; - if(!JS_GetPropertyById(cx, o, id, &jsv)) - return propertiesSoFar; - const value val = jsValToValue(jsv, cx); - jsval idv; - JS_IdToValue(cx, id, &idv); - if(JSVAL_IS_STRING(idv)) { - const value type = isList(val)? element : element; - return jsPropertiesToValues(cons<value> (mklist<value> (type, JS_GetStringBytes(JSVAL_TO_STRING(idv)), val), propertiesSoFar), o, i, cx); - } - return jsPropertiesToValues(cons(val, propertiesSoFar), o, i, cx); -} - -/** - * Converts a JS val to a value. - */ -const value jsValToValue(const jsval& jsv, const JSONContext& cx) { - switch(JS_TypeOfValue(cx, jsv)) { - case JSTYPE_STRING: { - return value(std::string(JS_GetStringBytes(JSVAL_TO_STRING(jsv)))); - } - case JSTYPE_BOOLEAN: { - return value((bool)JSVAL_TO_BOOLEAN(jsv)); - } - case JSTYPE_NUMBER: { - jsdouble jsd; - JS_ValueToNumber(cx, jsv, &jsd); - return value((double)jsd); - } - case JSTYPE_OBJECT: { - JSObject* o = JSVAL_TO_OBJECT(jsv); - JSObject* i = JS_NewPropertyIterator(cx, o); - if(i == NULL) - return value(list<value> ()); - const value pv = jsPropertiesToValues(list<value> (), o, i, cx); - return pv; - } - default: { - return value(); - } - } -} - -/** - * Consumes JSON strings and populates a JS object. - */ -failable<bool, std::string> consume(JSONParser* parser, const list<std::string>& ilist, const JSONContext& cx) { - if (isNil(ilist)) - return true; - JSString* jstr = JS_NewStringCopyZ(cx, car(ilist).c_str()); - if(!JS_ConsumeJSONText(cx, parser, JS_GetStringChars(jstr), JS_GetStringLength(jstr))) - return mkfailure<bool, std::string>("JS_ConsumeJSONText failed"); - return consume(parser, cdr(ilist), cx); -} - -/** - * Convert a list of strings representing a JSON document to a list of values. - */ -const failable<list<value>, std::string> readJSON(const list<std::string>& ilist, const JSONContext& cx) { - jsval val; - JSONParser* parser = JS_BeginJSONParse(cx, &val); - if(parser == NULL) - return mkfailure<list<value>, std::string>("JS_BeginJSONParse failed"); - - const failable<bool, std::string> consumed = consume(parser, ilist, cx); - - if(!JS_FinishJSONParse(cx, parser, JSVAL_NULL)) - return mkfailure<list<value>, std::string>("JS_FinishJSONParse failed"); - if(!hasValue(consumed)) - return mkfailure<list<value>, std::string>(reason(consumed)); - - return list<value>(jsValToValue(val, cx)); -} - -/** - * Converts a list of values to JS array elements. - */ -JSObject* valuesToJSElements(JSObject* a, const list<value>& l, int i, const JSONContext& cx) { - const jsval valueToJSVal(const value& val, const JSONContext& cx); - if (isNil(l)) - return a; - jsval pv = valueToJSVal(car(l), cx); - JS_SetElement(cx, a, i, &pv); - return valuesToJSElements(a, cdr(l), ++i, cx); -} - -/** - * Returns true if a list represents a JS array. - */ -const bool isJSArray(const list<value>& l) { - if(isNil(l)) - return false; - const value v = car(l); - if(isList(v)) { - const list<value> p = v; - if(isSymbol(car(p))) - return false; - } - return true; -} - - - -/** - * Converts a list of values to JS properties. - */ -JSObject* valuesToJSProperties(JSObject* o, const list<value>& l, const JSONContext& cx) { - const jsval valueToJSVal(const value& val, const JSONContext& cx); - if(isNil(l)) - return o; - const list<value> p = car(l); - jsval pv = valueToJSVal(caddr(p), cx); - JS_SetProperty(cx, o, ((std::string)cadr(p)).c_str(), &pv); - return valuesToJSProperties(o, cdr(l), cx); -} - -/** - * Converts a value to a JS val. - */ -const jsval valueToJSVal(const value& val, const JSONContext& cx) { - switch(type(val)) { - case value::String: - case value::Symbol: { - return STRING_TO_JSVAL(JS_NewStringCopyZ(cx, ((std::string)val).c_str())); - } - case value::Bool: { - return BOOLEAN_TO_JSVAL((bool)val); - } - case value::Number: { - return DOUBLE_TO_JSVAL(JS_NewDouble(cx, (double)val)); - } - case value::List: { - if (isJSArray(val)) - return OBJECT_TO_JSVAL(valuesToJSElements(JS_NewArrayObject(cx, 0, NULL), val, 0, cx)); - return OBJECT_TO_JSVAL(valuesToJSProperties(JS_NewObject(cx, NULL, NULL, NULL), val, cx)); - } - default: { - return JSVAL_VOID; - } - } -} - -const failable<bool, std::string> writeList(const list<value>& l, JSObject* o, const JSONContext& cx) { - if (isNil(l)) - return true; - - // Write an attribute - const value token(car(l)); - - if (isTaggedList(token, attribute)) { - jsval pv = valueToJSVal(attributeValue(token), cx); - JS_SetProperty(cx, o, std::string(attributeName(token)).c_str(), &pv); - - } else if (isTaggedList(token, element)) { - - // Write the value of an element - if (elementHasValue(token)) { - jsval pv = valueToJSVal(elementValue(token), cx); - JS_SetProperty(cx, o, std::string(elementName(token)).c_str(), &pv); - - } else { - - // Write a parent element - JSObject* child = JS_NewObject(cx, NULL, NULL, NULL); - jsval pv = OBJECT_TO_JSVAL(child); - JS_SetProperty(cx, o, std::string(elementName(token)).c_str(), &pv); - - // Write its children - const failable<bool, std::string> w = writeList(elementChildren(token), child, cx); - if (!hasValue(w)) - return w; - } - } - - // Go on - return writeList(cdr(l), o, cx); -} - -/** - * Context passed to the JSON write callback function. - */ -template<typename R> class WriteContext { -public: - WriteContext(const lambda<R(std::string, R)>& reduce, const R& accum, const JSONContext& cx) : cx(cx), reduce(reduce), accum(accum) { - } - const JSONContext& cx; - const lambda<R(std::string, R)> reduce; - R accum; -}; - -/** - * Called by JS_Stringify to write JSON out. - */ -template<typename R> JSBool writeCallback(const jschar *buf, uint32 len, void *data) { - WriteContext<R>& wcx = *(static_cast<WriteContext<R>*> (data)); - JSString* jstr = JS_NewUCStringCopyN(wcx.cx, buf, len); - wcx.accum = wcx.reduce(std::string(JS_GetStringBytes(jstr), JS_GetStringLength(jstr)), wcx.accum); - return JS_TRUE; -} - -/** - * Convert a list of values to a JSON document. - */ -template<typename R> const failable<R, std::string> writeJSON(const lambda<R(std::string, R)>& reduce, const R& initial, const list<value>& l, const JSONContext& cx) { - JSObject* o = JS_NewObject(cx, NULL, NULL, NULL); - jsval val = OBJECT_TO_JSVAL(o); - const failable<bool, std::string> w = writeList(l, o, cx); - if (!hasValue(w)) - return mkfailure<R, std::string>(reason(w)); - - WriteContext<R> wcx(reduce, initial, cx); - if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback<R>, &wcx)) - return mkfailure<R, std::string>("JS_Stringify failed"); - return wcx.accum; -} - -/** - * Convert a list of values to a list of strings representing a JSON document. - */ -const failable<list<std::string>, std::string> writeJSON(const list<value>& l, const JSONContext& cx) { - const failable<list<std::string>, std::string> ls = writeJSON<list<std::string> >(rcons<std::string>, list<std::string>(), l, cx); - if (!hasValue(ls)) - return ls; - return reverse(list<std::string>(ls)); -} - -/** - * Convert a function + params to a JSON request. - */ -const failable<list<std::string>, std::string> jsonRequest(const value& id, const value& func, const value& params, json::JSONContext& cx) { - const list<value> r = mklist<value>(mklist<value>("id", id), mklist<value>("method", func), mklist<value>("params", params)); - return writeJSON(valuesToElements(r), cx); -} - -/** - * Convert a value to a JSON result. - */ -const failable<list<std::string>, std::string> jsonResult(const value& id, const value& val, JSONContext& cx) { - return writeJSON(valuesToElements(mklist<value>(mklist<value>("id", id), mklist<value>("result", val))), cx); -} - -} -} - -#endif /* tuscany_json_hpp */ |