Skip to content

Commit

Permalink
Refactor JSON to improve speed and code size (using cbprintf)
Browse files Browse the repository at this point in the history
            Now print special 'short' JSON for console.log (and the REPL) (fix #47)
            JSON.stringify now doesn't print functions (fix #207)
  • Loading branch information
gfwilliams committed Feb 27, 2014
1 parent 5443d8b commit e467765
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 94 deletions.
3 changes: 3 additions & 0 deletions ChangeLog
@@ -1,5 +1,8 @@
1v54 : Add 4x6 font (instead of 8x8)
Fix occasional instability with Waveform read/write
Refactor JSON to improve speed and code size (using cbprintf)
Now print special 'short' JSON for console.log (and the REPL) (fix #47)
JSON.stringify now doesn't print functions (fix #207)

1v53 : Attempt to deal with the case where CC3000 crashes on initialization
Fix regression with setInterval/timeout and saving
Expand Down
22 changes: 11 additions & 11 deletions src/jsinteractive.c
Expand Up @@ -475,7 +475,7 @@ void jsiAppendSerialInitialisation(JsVar *str, const char *serialName, bool addC
jsvAppendPrintf(str, "%s.setup(%d", serialName, baudrate);
if (jsvIsObject(options)) {
jsvAppendString(str, ", ");
jsfGetJSON(options, str);
jsfGetJSON(options, str, JSON_NONE);
}
jsvAppendString(str, ");\n");
}
Expand All @@ -494,7 +494,7 @@ void jsiAppendDeviceInitialisation(JsVar *str, const char *deviceName) {
jsvAppendString(str, deviceName);
jsvAppendString(str, ".setup(");
if (jsvIsObject(options)) {
jsfGetJSON(options, str);
jsfGetJSON(options, str, JSON_NONE);
}
jsvAppendString(str, ");\n");
}
Expand Down Expand Up @@ -915,7 +915,7 @@ void jsiHandleNewLine(bool execute) {
// print result (but NOT if we had an error)
if (echo && !jspHasError()) {
jsiConsolePrintChar('=');
jsfPrintJSON(v);
jsfPrintJSON(v, JSON_LIMIT | JSON_NEWLINES | JSON_PRETTY);
jsiConsolePrint("\n");
}
jsvUnLock(v);
Expand Down Expand Up @@ -1577,7 +1577,7 @@ void jsiDumpObjectState(JsVar *parentName, JsVar *parent) {
jsiConsolePrintStringVar(proto);
jsiConsolePrint(" = ");
JsVar *protoData = jsvSkipName(proto);
jsfPrintJSON(protoData);
jsfPrintJSON(protoData, JSON_NEWLINES | JSON_PRETTY);
jsvUnLock(protoData);
jsiConsolePrint(";\n");
protoRef = proto->nextSibling;
Expand All @@ -1588,7 +1588,7 @@ void jsiDumpObjectState(JsVar *parentName, JsVar *parent) {
jsiConsolePrint(".");
jsiConsolePrintStringVar(child);
jsiConsolePrint(" = ");
jsfPrintJSON(data);
jsfPrintJSON(data, JSON_NEWLINES | JSON_PRETTY);
jsiConsolePrint(";\n");

}
Expand Down Expand Up @@ -1621,7 +1621,7 @@ void jsiDumpState() {
// function-specific output
jsiConsolePrint("function ");
jsiConsolePrintStringVar(child);
jsfPrintJSONForFunction(data);
jsfPrintJSONForFunction(data, JSON_NONE);
jsiConsolePrint("\n");
// print any prototypes we had
JsVar *proto = jsvObjectGetChild(data, JSPARSE_PROTOTYPE_VAR, 0);
Expand All @@ -1635,7 +1635,7 @@ void jsiDumpState() {
jsiConsolePrint(".prototype.");
jsiConsolePrintStringVar(protoName);
jsiConsolePrint(" = ");
jsfPrintJSON(protoData);
jsfPrintJSON(protoData, JSON_NEWLINES | JSON_PRETTY);
jsiConsolePrint(";\n");
jsvUnLock(protoData);
protoRef = protoName->nextSibling;
Expand All @@ -1647,7 +1647,7 @@ void jsiDumpState() {
jsiConsolePrint("var ");
jsiConsolePrintStringVar(child);
jsiConsolePrint(" = ");
jsfPrintJSON(data);
jsfPrintJSON(data, JSON_NEWLINES | JSON_PRETTY);
jsiConsolePrint(";\n");
}
}
Expand All @@ -1665,7 +1665,7 @@ void jsiDumpState() {
bool recur = jsvGetBoolAndUnLock(jsvSkipNameAndUnLock(jsvFindChildFromStringRef(timerNamePtr->firstChild, "recur", false)));
JsVar *timerInterval = jsvSkipNameAndUnLock(jsvFindChildFromStringRef(timerNamePtr->firstChild, "interval", false));
jsiConsolePrint(recur ? "setInterval(" : "setTimeout(");
jsfPrintJSON(timerCallback);
jsfPrintJSON(timerCallback, JSON_NEWLINES | JSON_PRETTY);
jsiConsolePrintf(", %f);\n", jshGetMillisecondsFromTime(timerInterval));
jsvUnLock(timerInterval);
jsvUnLock(timerCallback);
Expand All @@ -1685,9 +1685,9 @@ void jsiDumpState() {
int watchEdge = (int)jsvGetIntegerAndUnLock(jsvSkipNameAndUnLock(jsvFindChildFromStringRef(watchNamePtr->firstChild, "edge", false)));
JsVar *watchPin = jsvSkipNameAndUnLock(jsvFindChildFromStringRef(watchNamePtr->firstChild, "pin", false));
jsiConsolePrint("setWatch(");
jsfPrintJSON(watchCallback);
jsfPrintJSON(watchCallback, JSON_NEWLINES | JSON_PRETTY);
jsiConsolePrint(", ");
jsfPrintJSON(watchPin);
jsfPrintJSON(watchPin, JSON_NEWLINES | JSON_PRETTY);
jsiConsolePrint(", { repeat:");
jsiConsolePrint(watchRecur?"true":"false");
jsiConsolePrint(", edge:");
Expand Down
20 changes: 17 additions & 3 deletions src/jsutils.c
Expand Up @@ -420,7 +420,8 @@ void vcbprintf(vcbprintf_callback user_callback, void *user_data, const char *fm
while (*fmt) {
if (*fmt == '%') {
fmt++;
switch (*fmt++) {
char fmtChar = *fmt++;
switch (fmtChar) {
case 'd': itoa(va_arg(argp, int), buf, 10); user_callback(buf,user_data); break;
case 'x': itoa(va_arg(argp, int), buf, 16); user_callback(buf,user_data); break;
case 'L': {
Expand All @@ -431,19 +432,27 @@ void vcbprintf(vcbprintf_callback user_callback, void *user_data, const char *fm
case 'f': ftoa_bounded(va_arg(argp, JsVarFloat), buf, sizeof(buf)); user_callback(buf,user_data); break;
case 's': user_callback(va_arg(argp, char *), user_data); break;
case 'c': buf[0]=(char)va_arg(argp, int/*char*/);buf[1]=0; user_callback(buf, user_data); break;
case 'q':
case 'v': {
bool quoted = fmtChar=='q';
if (quoted) user_callback("\"",user_data);
JsVar *v = jsvAsString(va_arg(argp, JsVar*), false/*no unlock*/);
buf[1] = 0;
JsvStringIterator it;
jsvStringIteratorNew(&it, v, 0);
// OPT: this could be faster than it is (sending whole blocks at once)
while (jsvStringIteratorHasChar(&it)) {
buf[0] = jsvStringIteratorGetChar(&it);
user_callback(buf,user_data);
if (quoted) {
user_callback(escapeCharacter(buf[0]), user_data);
} else {
user_callback(buf,user_data);
}
jsvStringIteratorNext(&it);
}
jsvStringIteratorFree(&it);
jsvUnLock(v);
if (quoted) user_callback("\"",user_data);
} break;
case 't': user_callback(jsvGetTypeOf(va_arg(argp, JsVar*)), user_data); break;
case 'p': jshGetPinString(buf, (Pin)va_arg(argp, int/*Pin*/)); user_callback(buf, user_data); break;
Expand All @@ -457,4 +466,9 @@ void vcbprintf(vcbprintf_callback user_callback, void *user_data, const char *fm
}
}


void cbprintf(vcbprintf_callback user_callback, void *user_data, const char *fmt, ...) {
va_list argp;
va_start(argp, fmt);
vcbprintf(user_callback,user_data, fmt, argp);
va_end(argp);
}
6 changes: 5 additions & 1 deletion src/jsutils.h
Expand Up @@ -371,12 +371,16 @@ typedef void (*vcbprintf_callback)(const char *str, void *user_data);
* %f = JsVarFloat
* %s = string (char *)
* %c = char
* %v = JsVar *
* %v = JsVar * (doesn't have to be a string - it'll be converted)
* %q = JsVar * (in quotes, and escaped)
* %p = Pin
*
* Anything else will assert
*/
void vcbprintf(vcbprintf_callback user_callback, void *user_data, const char *fmt, va_list argp);

/// This one is directly usable..
void cbprintf(vcbprintf_callback user_callback, void *user_data, const char *fmt, ...);


#endif /* JSUTILS_H_ */
8 changes: 5 additions & 3 deletions src/jsvar.c
Expand Up @@ -699,7 +699,7 @@ JsVar *jsvAsString(JsVar *v, bool unlockVar) {
jsvUnLock(filler);
} else if (jsvIsFunction(v)) {
str = jsvNewFromEmptyString();
if (str) jsfGetJSON(v, str);
if (str) jsfGetJSON(v, str, JSON_NONE);
} else {
jsErrorInternal("Variable type cannot be converted to string");
str = 0;
Expand Down Expand Up @@ -889,7 +889,8 @@ bool jsvAppendStringBuf(JsVar *var, const char *str, int length) {
return true;
}

static void _jsvAppendPrintf(const char *str, void *user_data) {
/// Special version of append designed for use with vcbprintf_callback (See jsvAppendPrintf)
void jsvStringIteratorPrintfCallback(const char *str, void *user_data) {
while (*str)
jsvStringIteratorAppend((JsvStringIterator *)user_data, *(str++));
}
Expand All @@ -901,7 +902,7 @@ void jsvAppendPrintf(JsVar *var, const char *fmt, ...) {

va_list argp;
va_start(argp, fmt);
vcbprintf((vcbprintf_callback)&_jsvAppendPrintf,&it, fmt, argp);
vcbprintf((vcbprintf_callback)&jsvStringIteratorPrintfCallback,&it, fmt, argp);
va_end(argp);

jsvStringIteratorFree(&it);
Expand Down Expand Up @@ -1574,6 +1575,7 @@ JsVarInt jsvGetArrayLength(JsVar *arr) {
if (jsvIsInt(child)) {
JsVarInt lastIdx = jsvGetInteger(child);
jsvUnLock(child);
if (lastIdx<0) lastIdx=-1;
return lastIdx+1;
}
// if not an int, keep going
Expand Down
3 changes: 3 additions & 0 deletions src/jsvar.h
Expand Up @@ -501,6 +501,9 @@ static inline void jsvStringIteratorFree(JsvStringIterator *it) {
jsvUnLock(it->var);
}

/// Special version of append designed for use with vcbprintf_callback (See jsvAppendPrintf)
void jsvStringIteratorPrintfCallback(const char *str, void *user_data);

// --------------------------------------------------------------------------------------------
typedef struct JsvArrayIterator {
JsVar *var;
Expand Down
2 changes: 1 addition & 1 deletion src/jswrap_interactive.c
Expand Up @@ -119,7 +119,7 @@ void jswrap_interface_print(JsVar *v) {
if (jsvIsString(v))
jsiConsolePrintStringVar(v);
else
jsfPrintJSON(v);
jsfPrintJSON(v, JSON_PRETTY | JSON_NEWLINES);
jsvUnLock(v);
jsvArrayIteratorNext(&it);
if (jsvArrayIteratorHasElement(&it))
Expand Down

0 comments on commit e467765

Please sign in to comment.