/* * call-seq: * term_doc_enum.to_json() -> string * * Returns a json representation of the term doc enum. It will also add the * term positions if they are available. You can speed this up by having the * method return arrays instead of objects, simply by passing an argument to * the to_json method. For example; * * term_doc_enum.to_json() #=> * # [ * # {"document":1,"frequency":12}, * # {"document":11,"frequency":1}, * # {"document":29,"frequency":120}, * # {"document":30,"frequency":3} * # ] * * term_doc_enum.to_json(:fast) #=> * # [ * # [1,12], * # [11,1], * # [29,120], * # [30,3] * # ] */ static VALUE frb_tde_to_json(int argc, VALUE *argv, VALUE self) { TermDocEnum *tde = (TermDocEnum *)DATA_PTR(self); VALUE rjson; char *json, *jp; int capa = 65536; char *format; char close = (argc > 0) ? ']' : '}'; bool do_positions = tde->next_position != NULL; jp = json = ALLOC_N(char, capa); *(jp++) = '['; if (do_positions) { if (argc == 0) { format = "{\"document\":%d,\"frequency\":%d,\"positions\":["; } else { format = "[%d,%d,["; } } else { if (argc == 0) { format = "{\"document\":%d,\"frequency\":%d},"; } else { format = "[%d,%d],"; } } while (tde->next(tde)) { /* 100 chars should be enough room for an extra entry */ if ((jp - json) + 100 + tde->freq(tde) * 20 > capa) { capa <<= 1; REALLOC_N(json, char, capa); } sprintf(jp, format, tde->doc_num(tde), tde->freq(tde)); jp += strlen(jp); if (do_positions) { int pos; while (0 <= (pos = tde->next_position(tde))) { sprintf(jp, "%d,", pos); jp += strlen(jp); } if (*(jp - 1) == ',') jp--; *(jp++) = ']'; *(jp++) = close; *(jp++) = ','; } } if (*(jp - 1) == ',') jp--; *(jp++) = ']'; *jp = '\0'; rjson = rb_str_new2(json); free(json); return rjson; }