jswrap_json.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * This file is part of Espruino, a JavaScript interpreter for Microcontrollers
  3. *
  4. * Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. *
  10. * ----------------------------------------------------------------------------
  11. * This file is designed to be parsed during the build process
  12. *
  13. * JavaScript JSON-handling Functions
  14. * ----------------------------------------------------------------------------
  15. */
  16. #include "jswrap_json.h"
  17. #include "jsparse.h"
  18. #include "jsinteractive.h"
  19. #include "jswrapper.h"
  20. /*JSON{ "type":"staticmethod",
  21. "class" : "JSON", "name" : "stringify",
  22. "description" : "Convert the given object into a JSON string which can subsequently be parsed with JSON.parse or eval",
  23. "generate" : "jswrap_json_stringify",
  24. "params" : [ [ "data", "JsVar", "The data to be converted to a JSON string"] ],
  25. "return" : ["JsVar", "A JSON string"]
  26. }*/
  27. JsVar *jswrap_json_stringify(JsVar *v) {
  28. JsVar *result = jsvNewFromEmptyString();
  29. if (result) // could be out of memory
  30. jsfGetJSON(v, result);
  31. return result;
  32. }
  33. /*JSON{ "type":"staticmethod",
  34. "class" : "JSON", "name" : "parse",
  35. "description" : "Parse the given JSON string into a JavaScript object",
  36. "generate" : "jswrap_json_parse",
  37. "params" : [ [ "string", "JsVar", "A JSON string"] ],
  38. "return" : ["JsVar", "The JavaScript object created by parsing the data string"]
  39. }*/
  40. JsVar *jswrap_json_parse(JsVar *v) {
  41. JsVar *res = 0;
  42. JsVar *bracketed = jsvNewFromString("(");
  43. if (bracketed) { // could be out of memory
  44. v = jsvAsString(v, true); // try and get this as a string
  45. jsvAppendStringVarComplete(bracketed, v);
  46. jsvAppendString(bracketed, ")");
  47. res = jspEvaluateVar(jsiGetParser(), bracketed, 0);
  48. jsvUnLock(bracketed);
  49. }
  50. return res;
  51. }
  52. /* This is like jsfGetJSONWithCallback, but handles ONLY functions (and does not print the initial 'function' text) */
  53. void jsfGetJSONForFunctionWithCallback(JsVar *var, JsfGetJSONCallbackString callbackString, JsfGetJSONCallbackVar callbackVar, void *callbackData) {
  54. assert(jsvIsFunction(var));
  55. JsVarRef coderef = 0; // TODO: this should really be in jsvAsString
  56. JsVarRef childref = var->firstChild;
  57. bool firstParm = true;
  58. callbackString(callbackData, "(");
  59. while (childref) {
  60. JsVar *child = jsvLock(childref);
  61. childref = child->nextSibling;
  62. if (jsvIsFunctionParameter(child)) {
  63. if (firstParm)
  64. firstParm=false;
  65. else
  66. callbackString(callbackData, ",");
  67. callbackVar(callbackData, child); // FIXME: escape the string
  68. } else if (jsvIsString(child) && jsvIsStringEqual(child, JSPARSE_FUNCTION_CODE_NAME)) {
  69. coderef = child->firstChild;
  70. }
  71. jsvUnLock(child);
  72. }
  73. callbackString(callbackData, ") ");
  74. if (coderef) {
  75. JsVar *codeVar = jsvLock(coderef);
  76. callbackVar(callbackData, codeVar);
  77. jsvUnLock(codeVar);
  78. } else callbackString(callbackData, "{}");
  79. }
  80. void jsfGetJSONWithCallback(JsVar *var, JsfGetJSONCallbackString callbackString, JsfGetJSONCallbackVar callbackVar, void *callbackData) {
  81. if (jsvIsUndefined(var)) {
  82. callbackString(callbackData, "undefined");
  83. } else if (jsvIsArray(var)) {
  84. int length = (int)jsvGetArrayLength(var);
  85. int i;
  86. callbackString(callbackData, "[");
  87. for (i=0;i<length;i++) {
  88. JsVar *item = jsvGetArrayItem(var, i);
  89. jsfGetJSONWithCallback(item, callbackString, callbackVar, callbackData);
  90. jsvUnLock(item);
  91. if (i<length-1) callbackString(callbackData, ",");
  92. }
  93. callbackString(callbackData, "]");
  94. } else if (jsvIsArrayBuffer(var)) {
  95. callbackString(callbackData, "new ");
  96. callbackString(callbackData, jswGetBasicObjectName(var));
  97. callbackString(callbackData, "([");
  98. callbackVar(callbackData, jsvAsString(var, false));
  99. callbackString(callbackData, "])");
  100. } else if (jsvIsObject(var)) {
  101. bool first = true;
  102. JsVarRef childref = var->firstChild;
  103. callbackString(callbackData, "{");
  104. while (childref) {
  105. JsVar *child = jsvLock(childref);
  106. bool hidden = jsvIsInternalObjectKey(child);
  107. if (!hidden) {
  108. if (first)
  109. first = false;
  110. else
  111. callbackString(callbackData, ",");
  112. callbackString(callbackData, "\"");
  113. callbackVar(callbackData, child); // FIXME: escape the string
  114. callbackString(callbackData, "\":");
  115. }
  116. JsVar *childVar = child->firstChild ? jsvLock(child->firstChild) : 0;
  117. childref = child->nextSibling;
  118. jsvUnLock(child);
  119. if (!hidden) {
  120. jsfGetJSONWithCallback(childVar, callbackString, callbackVar, callbackData);
  121. }
  122. jsvUnLock(childVar);
  123. }
  124. callbackString(callbackData, "}");
  125. } else if (jsvIsFunction(var)) {
  126. callbackString(callbackData, "function ");
  127. jsfGetJSONForFunctionWithCallback(var, callbackString, callbackVar, callbackData);
  128. } else if (jsvIsString(var) && !jsvIsName(var)) {
  129. // escape the string
  130. callbackString(callbackData, "\"");
  131. JsvStringIterator it;
  132. jsvStringIteratorNew(&it, var, 0);
  133. while (jsvStringIteratorHasChar(&it)) {
  134. char ch = jsvStringIteratorGetChar(&it);
  135. callbackString(callbackData, escapeCharacter(ch));
  136. jsvStringIteratorNext(&it);
  137. }
  138. jsvStringIteratorFree(&it);
  139. callbackString(callbackData, "\"");
  140. } else {
  141. JsVar *str = jsvAsString(var, false);
  142. if (str) {
  143. callbackVar(callbackData, str);
  144. jsvUnLock(str);
  145. }
  146. }
  147. }
  148. void jsfGetJSON(JsVar *var, JsVar *result) {
  149. assert(jsvIsString(result));
  150. jsfGetJSONWithCallback(var, (JsfGetJSONCallbackString)jsvAppendString, (JsfGetJSONCallbackVar)jsvAppendStringVarComplete, result);
  151. }
  152. void _jsfPrintJSON_str(void *data, const char *str) { NOT_USED(data); jsiConsolePrint(str); }
  153. void _jsfPrintJSON_var(void *data, JsVar *var) { NOT_USED(data); jsiConsolePrintStringVar(var); }
  154. void jsfPrintJSON(JsVar *var) {
  155. jsfGetJSONWithCallback(var, _jsfPrintJSON_str, _jsfPrintJSON_var, 0);
  156. }
  157. void jsfPrintJSONForFunction(JsVar *var) {
  158. jsfGetJSONForFunctionWithCallback(var, _jsfPrintJSON_str, _jsfPrintJSON_var, 0);
  159. }