| 181 | } |
| 182 | |
| 183 | void writeNestedHashToClient(client *c, robj_roptr o) { |
| 184 | if (o == nullptr) { |
| 185 | addReply(c, shared.null[c->resp]); |
| 186 | } else if (o->type == OBJ_STRING) { |
| 187 | addReplyBulk(c, o); |
| 188 | } else if (o->type == OBJ_LIST) { |
| 189 | unsigned char *zl = (unsigned char*)ptrFromObj(o); |
| 190 | addReplyArrayLen(c, ziplistLen(zl)); |
| 191 | unsigned char *p = ziplistIndex(zl, ZIPLIST_HEAD); |
| 192 | while (p != nullptr) { |
| 193 | unsigned char *str; |
| 194 | unsigned int len; |
| 195 | long long lval; |
| 196 | if (ziplistGet(p, &str, &len, &lval)) { |
| 197 | char rgT[128]; |
| 198 | if (str == nullptr) { |
| 199 | len = ll2string(rgT, 128, lval); |
| 200 | str = (unsigned char*)rgT; |
| 201 | } |
| 202 | addReplyBulkCBuffer(c, (const char*)str, len); |
| 203 | } |
| 204 | p = ziplistNext(zl, p); |
| 205 | } |
| 206 | } else { |
| 207 | serverAssert(o->type == OBJ_NESTEDHASH ); |
| 208 | dict *d = (dict*)ptrFromObj(o); |
| 209 | |
| 210 | if (dictSize(d) > 1) |
| 211 | addReplyArrayLen(c, dictSize(d)); |
| 212 | |
| 213 | dictIterator *di = dictGetIterator(d); |
| 214 | dictEntry *de; |
| 215 | while ((de = dictNext(di))) { |
| 216 | robj_roptr oT = (robj*)dictGetVal(de); |
| 217 | addReplyArrayLen(c, 2); |
| 218 | addReplyBulkCBuffer(c, (sds)dictGetKey(de), sdslen((sds)dictGetKey(de))); |
| 219 | if (oT->type == OBJ_STRING) { |
| 220 | addReplyBulk(c, oT); |
| 221 | } else { |
| 222 | writeNestedHashToClient(c, oT); |
| 223 | } |
| 224 | } |
| 225 | dictReleaseIterator(di); |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | inline bool FSimpleJsonEscapeCh(char ch) { |
| 230 | return (ch == '"' || ch == '\\'); |
no test coverage detected