/*
* 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
frt_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;
}