c791c339c5a9110259039a77b45b0965c17cfcbb larrym Thu Jul 28 21:28:13 2011 -0700 add JSON Element code to represent JSON in memory and print out to html (redmine #4550) diff --git src/hg/lib/jsHelper.c src/hg/lib/jsHelper.c index afa079e..a70a7de 100644 --- src/hg/lib/jsHelper.c +++ src/hg/lib/jsHelper.c @@ -475,80 +475,209 @@ "onclick=\"return setTableRowVisibility(this, '%s', '%s.section', 'section', true);\" " "id='%s_button' src='%s' alt='%s' title='%s this section' class='bigBlue'" " style='cursor:pointer;'>\n", section, track, section, buttonImage, (isOpen ? "-" : "+"), (isOpen ? "Collapse": "Expand")); printf("<B style='font-size:larger;'> %s</B></TD></TR>\n", sectionTitle); printf("<TR %sid='%s-%d'><TD colspan=2>", isOpen ? "" : "style='display: none' ", section, 1); } void jsEndCollapsibleSection() /* End the collapsible <TR id=...>. */ { puts("</TD></TR>"); } -void jsAddString(struct hash *h, char *name, char *val) +struct jsonStringElement *newJsonString(char *str) +{ +struct jsonStringElement *ele; +AllocVar(ele); +ele->str = cloneString(str); +ele->type = jsonString; +return ele; +} + +struct jsonHashElement *newJsonHash(struct hash *h) +{ +struct jsonHashElement *ele; +AllocVar(ele); +ele->type = jsonHash; +ele->hash = h; +return ele; +} + +struct jsonListElement *newJsonList(struct slRef *list) +{ +struct jsonListElement *ele; +AllocVar(ele); +ele->type = jsonList; +ele->list = list; +return ele; +} + +void jsonHashAdd(struct jsonHashElement *h, char *name, struct jsonElement *ele) +{ +hashReplace(h->hash, name, ele); +} + +void jsonHashAddString(struct jsonHashElement *h, char *name, char *val) { // Add a string to a hash which will be used to print a javascript object; // existing values are replaced. -char *str = needMem(strlen(val) + 3); val = javaScriptLiteralEncode(val); +char *str = needMem(strlen(val) + 3); sprintf(str, "'%s'", val); freez(&val); -hashReplace(h, name, str); +jsonHashAdd(h, name, (struct jsonElement *) newJsonString(str)); } -void jsAddNumber(struct hash *h, char *name, long val) +void jsonHashAddNumber(struct jsonHashElement *h, char *name, long val) { // Add a number to a hash which will be used to print a javascript object; // existing values are replaced. char buf[256]; safef(buf, sizeof(buf), "%ld", val); -hashReplace(h, name, cloneString(buf)); +jsonHashAdd(h, name, (struct jsonElement *) newJsonString(buf)); +} + +void jsonHashAddDouble(struct jsonHashElement *h, char *name, double val) +{ +// Add a number to a hash which will be used to print a javascript object; +// existing values are replaced. +char buf[256]; +safef(buf, sizeof(buf), "%.10f", val); +jsonHashAdd(h, name, (struct jsonElement *) newJsonString(buf)); } -void jsAddBoolean(struct hash *h, char *name, boolean val) +void jsonHashAddBoolean(struct jsonHashElement *h, char *name, boolean val) { // Add a boolean to a hash which will be used to print a javascript object; // existing values are replaced. -hashReplace(h, name, cloneString(val ? "true" : "false")); +jsonHashAdd(h, name, (struct jsonElement *) newJsonString(val ? "true" : "false")); } -void jsPrintHash(struct hash *hash, char *name, int indentLevel) +void jsonListAdd(struct slRef **list, struct jsonElement *ele) { -// prints a hash as a javascript variable +struct slRef *e; +AllocVar(e); +e->val = ele; +slAddHead(list, e); +} -int i; +void jsonListAddString(struct slRef **list, char *val) +{ +val = javaScriptLiteralEncode(val); +char *str = needMem(strlen(val) + 3); +sprintf(str, "'%s'", val); +freez(&val); +jsonListAdd(list, (struct jsonElement *) newJsonString(str)); +} + +void jsonListAddNumber(struct slRef **list, long val) +{ +char buf[256]; +safef(buf, sizeof(buf), "%ld", val); +jsonListAdd(list, (struct jsonElement *) newJsonString(buf)); +} + +void jsonListAddDouble(struct slRef **list, double val) +{ +char buf[256]; +safef(buf, sizeof(buf), "%.10f", val); +jsonListAdd(list, (struct jsonElement *) newJsonString(buf)); +} + +void jsonListAddBoolean(struct slRef **list, boolean val) +{ +jsonListAdd(list, (struct jsonElement *) newJsonString(val ? "true" : "false")); +} + +static char *makeIndentBuf(int indentLevel) +{ char *indentBuf; indentBuf = needMem(indentLevel + 1); -for (i = 0; i < indentLevel; i++) - indentBuf[i] = '\t'; -indentBuf[i] = 0; -if(hashNumEntries(hash)) +memset(indentBuf, '\t', indentLevel); +indentBuf[indentLevel] = 0; +return indentBuf; +} + +static void jsonPrintRecurse(struct jsonElement *json, int indentLevel) { - struct hashEl *el, *list = hashElListHash(hash); +char *indentBuf = makeIndentBuf(indentLevel); +switch (json->type) + { + case jsonHash: + { + struct jsonHashElement *ele = (struct jsonHashElement *) json; + hPrintf("{\n"); + if(hashNumEntries(ele->hash)) + { + struct hashEl *el, *list = hashElListHash(ele->hash); slSort(&list, hashElCmp); - // We add START and END comments to facilitate scraping out this variable by javascript. - hPrintf("// START %s\n%svar %s = {\n", name, indentBuf, name); for (el = list; el != NULL; el = el->next) { - hPrintf("%s\t\"%s\": %s%s\n", indentBuf, el->name, (char *) el->val, el->next == NULL ? "" : ","); + struct jsonElement *val = (struct jsonElement *) el->val; + hPrintf("%s\t\"%s\": ", indentBuf, el->name); + jsonPrintRecurse(val, indentLevel + 1); + hPrintf("%s\n", el->next == NULL ? "" : ","); } - hPrintf("%s};\n// END %s\n", indentBuf, name); hashElFreeList(&list); } + hPrintf("%s}", indentBuf); + break; + } + case jsonList: + { + struct jsonListElement *rec = (struct jsonListElement *) json; + struct slRef *el; + hPrintf("[\n"); + if(rec->list) + { + for (el = rec->list; el != NULL; el = el->next) + { + struct jsonElement *val = (struct jsonElement *) el->val; + hPrintf("%s\t", indentBuf); + jsonPrintRecurse(val, indentLevel + 1); + hPrintf("%s\n", el->next == NULL ? "" : ","); + } + } + hPrintf("%s]", indentBuf); + break; + } + case jsonString: + { + hPrintf("%s", ((struct jsonStringElement *) json)->str); + break; + } + default: + { + errAbort("jsonPrintRecurse; invalid type: %d", json->type); + break; + } + } +freez(&indentBuf); +} + +void jsonPrint(struct jsonElement *json, char *name, int indentLevel) +{ +// print out a jsonElement + +char *indentBuf = makeIndentBuf(indentLevel); +hPrintf("// START %s\n%svar %s = ", name, indentBuf, name); +jsonPrintRecurse(json, indentLevel); +hPrintf("%s;\n// END %s\n", indentBuf, name); +freez(&indentBuf); } void jsonErrPrintf(struct dyString *ds, char *format, ...) // Printf a json error to a dyString for communicating with ajax code; format is: // {"error": error message here} { va_list args; va_start(args, format); dyStringPrintf(ds, "{\"error\": \""); struct dyString *buf = newDyString(1000); dyStringVaPrintf(buf, format, args); dyStringAppend(ds, javaScriptLiteralEncode(dyStringCannibalize(&buf))); dyStringPrintf(ds, "\"}"); va_end(args); }