diff options
author | Lars Schneider <larsxschneider@gmail.com> | 2012-10-24 11:03:15 +0200 |
---|---|---|
committer | Lars Schneider <larsxschneider@gmail.com> | 2012-10-25 09:19:27 +0200 |
commit | f1e8583e475e32e47aa1fd7d42388b144604477b (patch) | |
tree | c5f8a45e425929d935eb8b6e1c9fa8bfa984980b /src/library_jansson.js | |
parent | 11a4926fc6c2bfe43fef3c66ad30e4b2df612616 (diff) |
Fix -O1 warning and use proper pointers for Jansson library.
See details: https://github.com/kripken/emscripten/pull/636#issuecomment-9456782
Diffstat (limited to 'src/library_jansson.js')
-rw-r--r-- | src/library_jansson.js | 265 |
1 files changed, 180 insertions, 85 deletions
diff --git a/src/library_jansson.js b/src/library_jansson.js index 8ecb535b..368584a7 100644 --- a/src/library_jansson.js +++ b/src/library_jansson.js @@ -10,122 +10,199 @@ var LibraryJansson = { $JANSSON: { - load: function(string, flags, error) { - var json_obj = eval('(' + string + ')'); + // Returns the node ID to which the pointer `nodePtr` points to + getNodeIDByPtr: function(nodePtr) { + if (nodePtr) + return {{{ makeGetValue('nodePtr', '0', 'i32') }}}; + else + return 0; + }, - if (json_obj != null) { - // Create the root node with the nodeID `1` - g_json_context = [null, {"name" : "root", "node" : json_obj}]; - return 1; - } else { - g_json_context = null; + // Returns the Javascript node object which is referenced by `nodeID` + getNodeByID: function(nodeID) { + if (!g_json_context) { + console.log("Jansson: No JSON context."); return null; } - }, - type: function(nodeID) { - if (!g_json_context) + var node = g_json_context[nodeID]; + if (!node) { + console.log("Jansson: Node with ID `" + nodeID + "` not found. Context has `" + g_json_context.length + "` nodes."); return null; + } - var node = g_json_context[nodeID].node; - if (typeof(node) === 'object' && (node instanceof Array)) - return 'array' - else - return typeof(node); + return node; }, - getNode: function(parentNodeID) { - if (!g_json_context) + // Returns the Javascript node object to which is referenced by `nodePtr` (via node ID). + getNodeByPtr: function(nodePtr) { + var nodeID = JANSSON.getNodeIDByPtr(nodePtr); + var node = JANSSON.getNodeByID(nodeID); + return node; + }, + + // Returns the pointer to the `nodeID` of the node that is referenced by `nodeID` + getNodePtrByID: function(nodeID) { + if (nodeID <= 0) return null; + + var node = JANSSON.getNodeByID(nodeID); - var parentNode = g_json_context[parentNodeID]; - - if (!parentNode) { - console.log("Jansson: Node with ID `" + parentNodeID + "` not found."); + if (!node) + return null; + + return node['nodeIDPtr']; + }, + + // Adds a Javascript node object to the Javascript JSON context + allocNode: function(name, node) { + var id = g_json_context.length; + g_json_context[id] = {}; + g_json_context[id]['name'] = name; + g_json_context[id]['node'] = node; + g_json_context[id]['nodeIDPtr'] = _malloc(32); + {{{ makeSetValue('g_json_context[id][\'nodeIDPtr\']', '0', 'id', 'i32') }}} + return id; + }, + + // Frees all memory that might have been allocated for a given node + freeNode: function(node) { + node['name'] = null; + node['node'] = null; + _free(node['nodeIDPtr']); + _free(node['keyPtr']); + _free(node['stringValuePtr']); + }, + + // Loads a string into the Javascript JSNON context + // Only the root node is loaded. Child nodes are loaded on demand via `loadChildNodes` method. + load: function(string, flags, error) { + // This is potentially a security problem. + // TODO: Make sure everything is properly escaped + var json_obj = eval('(' + string + ')'); + + if (json_obj != null) { + // The context is an array storing all child nodes. + // These child nodes are added to the array on demand. + // The root node is at index `1` (index `0` is intentionally `null`) + g_json_context = [null]; + var nodeID = JANSSON.allocNode('root', json_obj); + return JANSSON.getNodePtrByID(nodeID); + } else { + g_json_context = null; return null; } + }, + + // Loads the child nodes of a given node (if the node has any) into the Javascript JSON context. + loadChildNodes: function(node) { + if (!node) + return null; // Add all child nodes of the parent node to the context. // Consequently we can access these child nodes with an ID (pointer) // TODO: Here is room for performance improvements - if (!parentNode.begin) { + if (!node.begin) { var childNodeID = g_json_context.length; - for(var childNode in parentNode.node) { - var childNodeID = g_json_context.length; - g_json_context[childNodeID] = {"name" : childNode, "node" : parentNode.node[childNode]}; - if (!parentNode.begin) parentNode.begin = childNodeID; + for(var childNode in node['node']) { + var childNodeID = JANSSON.allocNode(childNode, node['node'][childNode]); + if (!node.begin) node.begin = childNodeID; }; - parentNode.end = childNodeID; + node.end = childNodeID; } - return parentNode; + return node; + }, + + // Returns the content type (object, array, string, number, null) of the node referenced by `nodePtr` + type: function(nodePtr) { + var node = JANSSON.getNodeByPtr(nodePtr); + if (!node) + return null; + + var content = node['node']; + if (typeof(content) === 'object' && (content instanceof Array)) + return 'array' + else + { + return typeof(content); + } } }, json_loads: function(string, flags, error) { - return JANSSON.load(Pointer_stringify(string), flags, error); + return JANSSON.load(Pointer_stringify(string), flags, error); }, json_loadb: function(buffer, buflen, flags, error) { return JANSSON.load(Pointer_stringify(buffer).substr(0, buflen), flags, error); }, - json_is_object: function(nodeID) { - return (JANSSON.type(nodeID) === 'object'); + json_is_object: function(nodePtr) { + return (JANSSON.type(nodePtr) === 'object'); }, - json_is_array: function(nodeID) { - return (JANSSON.type(nodeID) === 'array'); + json_is_array: function(nodePtr) { + return (JANSSON.type(nodePtr) === 'array'); }, - json_is_string: function(nodeID) { - return (JANSSON.type(nodeID) === 'string'); + json_is_string: function(nodePtr) { + return (JANSSON.type(nodePtr) === 'string'); }, - json_is_integer: function(nodeID) { - return (JANSSON.type(nodeID) === 'number'); + json_is_integer: function(nodePtr) { + return (JANSSON.type(nodePtr) === 'number'); }, - json_is_real: function(nodeID) { - return (JANSSON.type(nodeID) === 'number'); + json_is_real: function(nodePtr) { + return (JANSSON.type(nodePtr) === 'number'); }, - json_is_number: function(nodeID) { - return (JANSSON.type(nodeID) === 'number'); + json_is_number: function(nodePtr) { + return (JANSSON.type(nodePtr) === 'number'); }, - json_is_null: function(nodeID) { - var nodeType = JANSSON.type(nodeID); + json_is_null: function(nodePtr) { + var nodeType = JANSSON.type(nodePtr); return (nodeType === 'undefined' || nodeType === 'null'); }, - json_object_get: function(parentNodeID, key) { + // Returns the pointer to the child node with the key `key` of the given parent node + json_object_get: function(parentNodePtr, key) { var key = Pointer_stringify(key); - var parentNode = JANSSON.getNode(parentNodeID); + var parentNode = JANSSON.getNodeByPtr(parentNodePtr); if (!parentNode) return null; - // Find the ID (pointer) of the requested child node + JANSSON.loadChildNodes(parentNode); + + // Find the requested child node for (var i=parentNode.begin; i<=parentNode.end; i++) { - if (g_json_context[i].name == key) return i; + if (g_json_context[i]['name'] === key) + return JANSSON.getNodePtrByID(i); } return null; }, - json_object_iter: function(parentNodeID) { - var parentNode = JANSSON.getNode(parentNodeID); + // Returns the pointer to the first child node of the given parent node + json_object_iter: function(parentNodePtr) { + var parentNode = JANSSON.getNodeByPtr(parentNodePtr); if (!parentNode) return null; - return parentNode.begin; + JANSSON.loadChildNodes(parentNode); + + return JANSSON.getNodePtrByID(parentNode.begin); }, - json_object_iter_next: function(parentNodeID, childNodeID) { - var parentNode = JANSSON.getNode(parentNodeID); + // Returns a pointer to the child node after the given child node of the given parent node + json_object_iter_next: function(parentNodePtr, childNodePtr) { + var parentNode = JANSSON.getNodeByPtr(parentNodePtr); + var childNodeID = JANSSON.getNodeIDByPtr(childNodePtr); if (!parentNode) return null; @@ -133,91 +210,109 @@ var LibraryJansson = { if (childNodeID < parentNode.begin || childNodeID >= parentNode.end) return null; else - return childNodeID+1; + return JANSSON.getNodePtrByID(childNodeID+1); }, - json_array_size: function(parentNodeID, index) { - var parentNode = JANSSON.getNode(parentNodeID); + // Returns a integer containing the size of an array + json_array_size: function(parentNodePtr) { + var parentNode = JANSSON.getNodeByPtr(parentNodePtr); if (!parentNode) return 0; - var size = parentNode.end - parentNode.begin + 1; + JANSSON.loadChildNodes(parentNode); + var size = parentNode.end - parentNode.begin + 1; if (size < 0) size = 0; - return size; }, - json_array_get: function(parentNodeID, index) { - var parentNode = JANSSON.getNode(parentNodeID); - var position = parentNode.begin + index; + // Returns the pointer of the node with the index `index` in a given array parent node + json_array_get: function(parentNodePtr, index) { + var parentNode = JANSSON.getNodeByPtr(parentNodePtr); + JANSSON.loadChildNodes(parentNode); + var position = parentNode.begin + index; if (position < parentNode.begin || position > parentNode.end) return null; else - return position; + return JANSSON.getNodePtrByID(position); }, - json_object_iter_key: function(nodeID) { - var node = g_json_context[nodeID]; - + json_object_iter_key: function(nodePtr) { + var node = JANSSON.getNodeByPtr(nodePtr); if (!node) return null; - return allocate(intArrayFromString(node.name), 'i8', ALLOC_NORMAL); + if (!node['keyPtr']) { + node['keyPtr'] = allocate(intArrayFromString(node['name']), 'i8', ALLOC_NORMAL); + } + + return node['keyPtr']; }, - json_object_iter_value: function(nodeID) { - return nodeID; + json_object_iter_value: function(nodePtr) { + return nodePtr; }, - json_string_value: function(nodeID) { - var node = g_json_context[nodeID]; + json_string_value: function(nodePtr) { + var node = JANSSON.getNodeByPtr(nodePtr); if (!node) + { + console.log("Jansson: invalid node in `function json_string_value`"); return null; + } + + if (!node['stringValuePtr']) { + node['stringValuePtr'] = allocate(intArrayFromString(node['node']), 'i8', ALLOC_NORMAL); + } - return allocate(intArrayFromString(node.node), 'i8', ALLOC_NORMAL); + return node['stringValuePtr']; }, - json_integer_value: function(nodeID) { - var node = g_json_context[nodeID]; + json_integer_value: function(nodePtr) { + var node = JANSSON.getNodeByPtr(nodePtr); if (!node) return null; // Convert JSON number to an integer // c.f. http://stackoverflow.com/questions/596467/how-do-i-convert-a-float-to-an-int-in-javascript - if (node.node<0) - return Math.ceil(node.node); + if (node['node']<0) + return Math.ceil(node['node']); else - return Math.floor(node.node); + return Math.floor(node['node']); }, - json_real_value: function(nodeID) { - var node = g_json_context[nodeID]; + json_real_value: function(nodePtr) { + var node = JANSSON.getNodeByPtr(nodePtr); if (!node) return null; - return node.node; + return node['node']; }, - json_number_value: function(nodeID) { - var node = g_json_context[nodeID]; + json_number_value: function(nodePtr) { + var node = JANSSON.getNodeByPtr(nodePtr); if (!node) return null; - return node.node; + return node['node']; }, - json_delete: function(nodeID) { - // We assume, if the root node's reference count is decreased, we can forget the context. - if (nodeID == 1) + json_delete: function(nodePtr) { + // We assume, if the root node is deleted, all nodes and the context are deleted. + if (JANSSON.getNodeIDByPtr(nodePtr) == 1) { + for (var node in g_json_context) { + JANSSON.freeNode(node); + } + g_json_context = null; + } } }; |