+static const char *
+jsonstring(Pool *pool, const char *s)
+{
+ int needed = 0;
+ const unsigned char *s1;
+ char *r, *rp;
+
+ for (s1 = (const unsigned char *)s; *s1; s1++)
+ {
+ if (*s1 < 32)
+ needed += *s1 == '\n' ? 2 : 6;
+ else if (*s1 == '\\' || *s1 == '\"')
+ needed += 2;
+ else
+ needed++;
+ }
+ r = rp = pool_alloctmpspace(pool, needed + 3);
+ *rp++ = '\"';
+ for (s1 = (const unsigned char *)s; *s1; s1++)
+ {
+ if (*s1 < 32)
+ {
+ int x;
+ if (*s1 == '\n')
+ {
+ *rp++ = '\\';
+ *rp++ = 'n';
+ continue;
+ }
+ *rp++ = '\\';
+ *rp++ = 'u';
+ *rp++ = '0';
+ *rp++ = '0';
+ x = *s1 / 16;
+ *rp++ = (x < 10 ? '0' : 'a' - 10) + x;
+ x = *s1 & 15;
+ *rp++ = (x < 10 ? '0' : 'a' - 10) + x;
+ }
+ else if (*s1 == '\\' || *s1 == '\"')
+ {
+ *rp++ = '\\';
+ *rp++ = *s1;
+ }
+ else
+ *rp++ = *s1;
+ }
+ *rp++ = '\"';
+ *rp = 0;
+ return r;
+}
+
+struct cbdata {
+ unsigned char *first;
+ int nfirst;
+ int baseindent;
+};
+
+static int
+dump_attr_json(Repo *repo, Repodata *data, Repokey *key, KeyValue *kv, struct cbdata *cbdata)
+{
+ Pool *pool = repo->pool;
+ const char *keyname;
+ KeyValue *kvp;
+ int indent = cbdata->baseindent;
+ int isarray = 0;
+ const char *str;
+ int depth = 0;
+
+ keyname = pool_id2str(repo->pool, key->name);
+ for (kvp = kv; (kvp = kvp->parent) != 0; indent += 4)
+ depth++;
+ if (cbdata->nfirst < depth + 1)
+ {
+ cbdata->first = solv_realloc(cbdata->first, depth + 16);
+ memset(cbdata->first + cbdata->nfirst, 0, depth + 16 - cbdata->nfirst);
+ cbdata->nfirst = depth + 16;
+ }
+ switch(key->type)
+ {
+ case REPOKEY_TYPE_IDARRAY:
+ case REPOKEY_TYPE_DIRNUMNUMARRAY:
+ case REPOKEY_TYPE_DIRSTRARRAY:
+ isarray = 1;
+ break;
+ case REPOKEY_TYPE_FIXARRAY:
+ case REPOKEY_TYPE_FLEXARRAY:
+ isarray = 2;
+ break;
+ default:
+ break;
+ }
+ if (!isarray || !kv->entry)
+ {
+ if (cbdata->first[depth])
+ printf(",\n");
+ printf("%*s%s: ", indent, "", jsonstring(pool, keyname));
+ cbdata->first[depth] = 1;
+ }
+ if (isarray == 1 && !kv->entry)
+ printf("[\n%*s", indent + 2, "");
+ else if (isarray == 1 && kv->entry)
+ printf("%*s", indent + 2, "");
+ switch(key->type)
+ {
+ case REPOKEY_TYPE_ID:
+ if (data && data->localpool)
+ str = stringpool_id2str(&data->spool, kv->id);
+ else
+ str = pool_dep2str(repo->pool, kv->id);
+ printf("%s", jsonstring(pool, str));
+ break;
+ case REPOKEY_TYPE_CONSTANTID:
+ str = pool_dep2str(repo->pool, kv->id);
+ printf("%s", jsonstring(pool, str));
+ break;
+ case REPOKEY_TYPE_IDARRAY:
+ if (data && data->localpool)
+ str = stringpool_id2str(&data->spool, kv->id);
+ else
+ str = pool_dep2str(repo->pool, kv->id);
+ printf("%s", jsonstring(pool, str));
+ break;
+ case REPOKEY_TYPE_STR:
+ str = kv->str;
+ printf("%s", jsonstring(pool, str));
+ break;
+ case REPOKEY_TYPE_VOID:
+ printf("null");
+ break;
+ case REPOKEY_TYPE_U32:
+ case REPOKEY_TYPE_CONSTANT:
+ printf("%u", kv->num);
+ break;
+ case REPOKEY_TYPE_NUM:
+ printf("%llu", SOLV_KV_NUM64(kv));
+ break;
+ case REPOKEY_TYPE_BINARY:
+ printf("\"<binary>\"");
+ break;
+ case REPOKEY_TYPE_DIRNUMNUMARRAY:
+ printf("{\n");
+ printf("%*s \"dir\": %s,\n", indent, "", jsonstring(pool, repodata_dir2str(data, kv->id, 0)));
+ printf("%*s \"num1\": %u,\n", indent, "", kv->num);
+ printf("%*s \"num2\": %u\n", indent, "", kv->num2);
+ printf("%*s }", indent, "");
+ break;
+ case REPOKEY_TYPE_DIRSTRARRAY:
+ printf("%s", jsonstring(pool, repodata_dir2str(data, kv->id, kv->str)));
+ break;
+ case REPOKEY_TYPE_FIXARRAY:
+ case REPOKEY_TYPE_FLEXARRAY:
+ cbdata->first[depth + 1] = 0;
+ if (!kv->entry)
+ printf("[\n");
+ else
+ {
+ if (kv->eof != 2)
+ printf("\n%*s },\n", indent, "");
+ else
+ printf("\n%*s }\n", indent, "");
+ }
+ if (kv->eof != 2)
+ printf("%*s {\n", indent, "");
+ else
+ printf("%*s]", indent, "");
+ break;
+ default:
+ if (solv_chksum_len(key->type))
+ {
+ printf("{\n");
+ printf("%*s \"value\": %s,\n", indent, "", jsonstring(pool, repodata_chk2str(data, key->type, (unsigned char *)kv->str)));
+ printf("%*s \"type\": %s\n", indent, "", jsonstring(pool, solv_chksum_type2str(key->type)));
+ printf("%*s}", indent, "");
+ break;
+ }
+ printf("\"?\"");
+ break;
+ }
+ if (isarray == 1)
+ {
+ if (!kv->eof)
+ printf(",\n");
+ else
+ printf("\n%*s]", indent, "");
+ }
+ return 0;
+}
+