[Groonga-commit] groonga/groonga [master] XML supported in grn_output_obj().

Back to archive index

null+****@clear***** null+****@clear*****
2010年 6月 22日 (火) 20:21:23 JST


Daijiro MORI	2010-06-22 11:21:23 +0000 (Tue, 22 Jun 2010)

  New Revision: afcbf532454a84946bc2681f4b7c43fb0cf6006a

  Log:
    XML supported in grn_output_obj().

  Modified files:
    lib/db.c
    lib/db.h
    lib/output.c
    lib/proc.c
    src/groonga.c

  Modified: lib/db.c (+28 -0)
===================================================================
--- lib/db.c    2010-06-21 05:28:02 +0000 (a6a1e57)
+++ lib/db.c    2010-06-22 11:21:23 +0000 (e34f433)
@@ -2913,6 +2913,34 @@ exit :
   GRN_API_RETURN(length);
 }
 
+unsigned int
+grn_vector_pop_element(grn_ctx *ctx, grn_obj *vector,
+                       const char **str, unsigned int *weight, grn_id *domain)
+{
+  unsigned int offset, length = 0;
+  GRN_API_ENTER;
+  if (!vector || vector->header.type != GRN_VECTOR) {
+    ERR(GRN_INVALID_ARGUMENT, "invalid vector");
+    goto exit;
+  }
+  if (!vector->u.v.n_sections) {
+    ERR(GRN_RANGE_ERROR, "offset out of range");
+    goto exit;
+  }
+  offset = --vector->u.v.n_sections;
+  {
+    grn_section *vp = &vector->u.v.sections[offset];
+    grn_obj *body = grn_vector_body(ctx, vector);
+    *str = GRN_BULK_HEAD(body) + vp->offset;
+    if (weight) { *weight = vp->weight; }
+    if (domain) { *domain = vp->domain; }
+    length = vp->length;
+    grn_bulk_truncate(ctx, body, vp->offset);
+  }
+exit :
+  GRN_API_RETURN(length);
+}
+
 #define W_SECTIONS_UNIT 8
 #define S_SECTIONS_UNIT (1 << W_SECTIONS_UNIT)
 #define M_SECTIONS_UNIT (S_SECTIONS_UNIT - 1)

  Modified: lib/db.h (+3 -0)
===================================================================
--- lib/db.h    2010-06-21 05:28:02 +0000 (115b7d5)
+++ lib/db.h    2010-06-22 11:21:23 +0000 (8ae9465)
@@ -250,6 +250,9 @@ int grn_vector_delimit(grn_ctx *ctx, grn_obj *vector);
 int grn_vector_size(grn_ctx *ctx, grn_obj *vector);
 */
 
+unsigned int grn_vector_pop_element(grn_ctx *ctx, grn_obj *vector,
+                                    const char **str, unsigned int *weight, grn_id *domain);
+
 grn_rc grn_vector_delimit(grn_ctx *ctx, grn_obj *v, unsigned int weight, grn_id domain);
 
 grn_rc grn_db_init_builtin_types(grn_ctx *ctx);

  Modified: lib/output.c (+637 -9)
===================================================================
--- lib/output.c    2010-06-21 05:28:02 +0000 (ca5dfe3)
+++ lib/output.c    2010-06-22 11:21:23 +0000 (5631c48)
@@ -36,14 +36,17 @@ static void
 put_delimiter(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type)
 {
   uint32_t level = CURR_LEVEL;
-  if (level < 2) { return; }
   switch (output_type) {
   case GRN_CONTENT_JSON:
+    if (level < 2) { return; }
     GRN_TEXT_PUTC(ctx, outbuf, ((level & 3) == 3) ? ':' : ',');
     break;
   case GRN_CONTENT_XML:
+    if (!DEPTH) { return; }
+    GRN_TEXT_PUTC(ctx, outbuf, '\n');
     break;
   case GRN_CONTENT_TSV:
+    if (level < 2) { return; }
     if (DEPTH == 1) {
       GRN_TEXT_PUTC(ctx, outbuf, ((level & 3) == 3) ? '\t' : '\n');
     } else if (DEPTH > 1) {
@@ -64,8 +67,10 @@ grn_output_array_open(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_typ
     GRN_TEXT_PUTC(ctx, outbuf, '[');
     break;
   case GRN_CONTENT_XML:
-    GRN_TEXT_PUTS(ctx, outbuf, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
-                  "<SEGMENTS>\n<SEGMENT>\n<RESULTPAGE>\n");
+    GRN_TEXT_PUTC(ctx, outbuf, '<');
+    GRN_TEXT_PUTS(ctx, outbuf, name);
+    GRN_TEXT_PUTC(ctx, outbuf, '>');
+    grn_vector_add_element(ctx, &ctx->impl->names, name, strlen(name), 0, GRN_DB_SHORT_TEXT);
     break;
   case GRN_CONTENT_TSV:
     if (DEPTH > 1) { GRN_TEXT_PUTS(ctx, outbuf, "[\t"); }
@@ -90,8 +95,13 @@ grn_output_array_close(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_ty
     }
     break;
   case GRN_CONTENT_XML:
-    GRN_TEXT_PUTS(ctx, outbuf, "</RESULTPAGE>\n</SEGMENT>\n</SEGMENTS>");
-    if (DEPTH > 1) { GRN_TEXT_PUTC(ctx, outbuf, '\n'); }
+    {
+      const char *name;
+      unsigned int name_len = grn_vector_pop_element(ctx, &ctx->impl->names, &name, NULL, NULL);
+      GRN_TEXT_PUTS(ctx, outbuf, "</");
+      GRN_TEXT_PUT(ctx, outbuf, name, name_len);
+      GRN_TEXT_PUTC(ctx, outbuf, '>');
+    }
     break;
   case GRN_CONTENT_NONE:
     break;
@@ -110,8 +120,10 @@ grn_output_map_open(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
     GRN_TEXT_PUTS(ctx, outbuf, "{");
     break;
   case GRN_CONTENT_XML:
-    GRN_TEXT_PUTS(ctx, outbuf, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
-                  "<SEGMENTS>\n<SEGMENT>\n<RESULTPAGE>\n");
+    GRN_TEXT_PUTC(ctx, outbuf, '<');
+    GRN_TEXT_PUTS(ctx, outbuf, name);
+    GRN_TEXT_PUTC(ctx, outbuf, '>');
+    grn_vector_add_element(ctx, &ctx->impl->names, name, strlen(name), 0, GRN_DB_SHORT_TEXT);
     break;
   case GRN_CONTENT_TSV:
     if (DEPTH > 1) { GRN_TEXT_PUTS(ctx, outbuf, "{\t"); }
@@ -136,8 +148,13 @@ grn_output_map_close(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type
     }
     break;
   case GRN_CONTENT_XML:
-    GRN_TEXT_PUTS(ctx, outbuf, "</RESULTPAGE>\n</SEGMENT>\n</SEGMENTS>");
-    if (DEPTH > 1) { GRN_TEXT_PUTC(ctx, outbuf, '\n'); }
+    {
+      const char *name;
+      unsigned int name_len = grn_vector_pop_element(ctx, &ctx->impl->names, &name, NULL, NULL);
+      GRN_TEXT_PUTS(ctx, outbuf, "</");
+      GRN_TEXT_PUT(ctx, outbuf, name, name_len);
+      GRN_TEXT_PUTC(ctx, outbuf, '>');
+    }
     break;
   case GRN_CONTENT_NONE:
     break;
@@ -158,7 +175,9 @@ grn_output_int32(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, in
     grn_text_itoa(ctx, outbuf, value);
     break;
   case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "<INT>");
     grn_text_itoa(ctx, outbuf, value);
+    GRN_TEXT_PUTS(ctx, outbuf, "</INT>");
     break;
   case GRN_CONTENT_NONE:
     break;
@@ -178,7 +197,53 @@ grn_output_int64(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, in
     grn_text_lltoa(ctx, outbuf, value);
     break;
   case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "<INT>");
     grn_text_lltoa(ctx, outbuf, value);
+    GRN_TEXT_PUTS(ctx, outbuf, "</INT>");
+    break;
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  INCR_LENGTH;
+}
+
+void
+grn_output_uint64(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, int64_t value)
+{
+  put_delimiter(ctx, outbuf, output_type);
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    grn_text_ulltoa(ctx, outbuf, value);
+    break;
+  case GRN_CONTENT_TSV:
+    grn_text_ulltoa(ctx, outbuf, value);
+    break;
+  case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "<INT>");
+    grn_text_ulltoa(ctx, outbuf, value);
+    GRN_TEXT_PUTS(ctx, outbuf, "</INT>");
+    break;
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  INCR_LENGTH;
+}
+
+void
+grn_output_float(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, int64_t value)
+{
+  put_delimiter(ctx, outbuf, output_type);
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    grn_text_ftoa(ctx, outbuf, value);
+    break;
+  case GRN_CONTENT_TSV:
+    grn_text_ftoa(ctx, outbuf, value);
+    break;
+  case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "<FLOAT>");
+    grn_text_ftoa(ctx, outbuf, value);
+    GRN_TEXT_PUTS(ctx, outbuf, "</FLOAT>");
     break;
   case GRN_CONTENT_NONE:
     break;
@@ -199,7 +264,9 @@ grn_output_str(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
     grn_text_esc(ctx, outbuf, value, value_len);
     break;
   case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "<TEXT>");
     grn_text_escape_xml(ctx, outbuf, value, value_len);
+    GRN_TEXT_PUTS(ctx, outbuf, "</TEXT>");
     break;
   case GRN_CONTENT_NONE:
     break;
@@ -215,6 +282,216 @@ grn_output_cstr(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
 }
 
 void
+grn_output_bool(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, char value)
+{
+  put_delimiter(ctx, outbuf, output_type);
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    GRN_TEXT_PUTS(ctx, outbuf, value ? "true" : "false");
+    break;
+  case GRN_CONTENT_TSV:
+    GRN_TEXT_PUTS(ctx, outbuf, value ? "true" : "false");
+    break;
+  case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "<BOOL>");
+    GRN_TEXT_PUTS(ctx, outbuf, value ? "true" : "false");
+    GRN_TEXT_PUTS(ctx, outbuf, "</BOOL>");
+    break;
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  INCR_LENGTH;
+}
+
+void
+grn_output_time(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, int64_t value)
+{
+  double dv = value;
+  dv /= 1000000.0;
+  put_delimiter(ctx, outbuf, output_type);
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    grn_text_ftoa(ctx, outbuf, dv);
+    break;
+  case GRN_CONTENT_TSV:
+    grn_text_ftoa(ctx, outbuf, dv);
+    break;
+  case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "<DATE>");
+    grn_text_ftoa(ctx, outbuf, dv);
+    GRN_TEXT_PUTS(ctx, outbuf, "</DATE>");
+    break;
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  INCR_LENGTH;
+}
+
+void
+grn_output_geo_point(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
+                     grn_geo_point *value)
+{
+  put_delimiter(ctx, outbuf, output_type);
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    if (value) {
+      GRN_TEXT_PUTC(ctx, outbuf, '"');
+      grn_text_itoa(ctx, outbuf, value->latitude);
+      GRN_TEXT_PUTC(ctx, outbuf, 'x');
+      grn_text_itoa(ctx, outbuf, value->longitude);
+      GRN_TEXT_PUTC(ctx, outbuf, '"');
+    } else {
+      GRN_TEXT_PUTS(ctx, outbuf, "\"\"");
+    }
+    break;
+  case GRN_CONTENT_TSV:
+    if (value) {
+      GRN_TEXT_PUTC(ctx, outbuf, '"');
+      grn_text_itoa(ctx, outbuf, value->latitude);
+      GRN_TEXT_PUTC(ctx, outbuf, 'x');
+      grn_text_itoa(ctx, outbuf, value->longitude);
+      GRN_TEXT_PUTC(ctx, outbuf, '"');
+    } else {
+      GRN_TEXT_PUTS(ctx, outbuf, "\"\"");
+    }
+    break;
+  case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "<GEO_POINT>");
+    if (value) {
+      grn_text_itoa(ctx, outbuf, value->latitude);
+      GRN_TEXT_PUTC(ctx, outbuf, 'x');
+      grn_text_itoa(ctx, outbuf, value->longitude);
+    }
+    GRN_TEXT_PUTS(ctx, outbuf, "</GEO_POINT>");
+    break;
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  INCR_LENGTH;
+}
+
+static void
+grn_text_atoj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
+              grn_obj *obj, grn_id id)
+{
+  int vs;
+  grn_obj buf;
+  GRN_TEXT_INIT(&buf, 0);
+  if (obj->header.type == GRN_ACCESSOR) {
+    grn_accessor *a = (grn_accessor *)obj;
+    for (;;) {
+      GRN_BULK_REWIND(&buf);
+      switch (a->action) {
+      case GRN_ACCESSOR_GET_ID :
+        GRN_UINT32_PUT(ctx, &buf, id);
+        buf.header.domain = GRN_DB_UINT32;
+        break;
+      case GRN_ACCESSOR_GET_KEY :
+        grn_table_get_key2(ctx, a->obj, id, &buf);
+        buf.header.domain = DB_OBJ(a->obj)->header.domain;
+        break;
+      case GRN_ACCESSOR_GET_VALUE :
+        grn_obj_get_value(ctx, a->obj, id, &buf);
+        buf.header.domain = GRN_DB_INT32; /* fix me */
+        break;
+      case GRN_ACCESSOR_GET_SCORE :
+        grn_obj_get_value(ctx, a->obj, id, &buf);
+        {
+          grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
+          GRN_INT32_PUT(ctx, &buf, ri->score);
+        }
+        buf.header.domain = GRN_DB_INT32;
+        break;
+      case GRN_ACCESSOR_GET_NSUBRECS :
+        {
+          grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
+          GRN_INT32_PUT(ctx, &buf, ri->n_subrecs);
+        }
+        buf.header.domain = GRN_DB_INT32;
+        break;
+      case GRN_ACCESSOR_GET_COLUMN_VALUE :
+        /* todo : support vector */
+        grn_obj_get_value(ctx, a->obj, id, &buf);
+        if ((a->obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR) {
+          grn_id *idp = (grn_id *)GRN_BULK_HEAD(&buf);
+          if (a->next) {
+            grn_output_array_open(ctx, outbuf, output_type, "FIELD", -1);
+            for (vs = GRN_BULK_VSIZE(&buf) / sizeof(grn_id); vs--; idp++) {
+              grn_text_atoj(ctx, outbuf, output_type, (grn_obj *)a->next, *idp);
+            }
+            grn_output_array_close(ctx, outbuf, output_type);
+          } else {
+            grn_obj b;
+            GRN_RECORD_INIT(&b, 0, DB_OBJ(a->obj)->range);
+            grn_output_array_open(ctx, outbuf, output_type, "FIELD", -1);
+            /* todo: support other fixe sized data types */
+            for (vs = GRN_BULK_VSIZE(&buf) / sizeof(grn_id); vs--; idp++) {
+              GRN_RECORD_SET(ctx, &b, *idp);
+              grn_output_obj(ctx, outbuf, output_type, &b, NULL);
+            }
+            grn_output_array_close(ctx, outbuf, output_type);
+            GRN_OBJ_FIN(ctx, &b);
+          }
+          goto exit;
+        }
+        break;
+      case GRN_ACCESSOR_GET_DB_OBJ :
+        /* todo */
+        break;
+      case GRN_ACCESSOR_LOOKUP :
+        /* todo */
+        break;
+      case GRN_ACCESSOR_FUNCALL :
+        /* todo */
+        break;
+      }
+      if (a->next) {
+        a = a->next;
+        id = *((grn_id *)GRN_BULK_HEAD(&buf));
+      } else {
+        break;
+      }
+    }
+  } else {
+    grn_obj_get_value(ctx, obj, id, &buf);
+  }
+  grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
+exit :
+  grn_obj_close(ctx, &buf);
+}
+
+static void
+grn_text_atoj_o(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
+                grn_obj *obj, grn_obj *id)
+{
+  grn_id *idp = (grn_id *)GRN_BULK_HEAD(id);
+  uint32_t ids = GRN_BULK_VSIZE(id);
+  for (;;) {
+    if (ids < sizeof(grn_id)) {
+      ERR(GRN_INVALID_ARGUMENT, "invalid id.");
+      return;
+    }
+    if (obj->header.type == GRN_ACCESSOR_VIEW) {
+      uint32_t n;
+      grn_accessor_view *v = (grn_accessor_view *)obj;
+      n = *idp;
+      if (n >= v->naccessors) {
+        ERR(GRN_INVALID_ARGUMENT, "invalid id");
+        return;
+      }
+      if (!(obj = v->accessors[n])) { return ; }
+      idp++;
+      ids -= sizeof(grn_id);
+    } else {
+      break;
+    }
+  }
+  grn_text_atoj(ctx, outbuf, output_type, obj, *idp);
+}
+
+#ifdef USE_GRN_TEXT_OTOJ
+
+void
 grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, grn_obj *obj, grn_obj_format *format)
 {
   put_delimiter(ctx, outbuf, output_type);
@@ -234,3 +511,354 @@ grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, grn_
   INCR_LENGTH;
 }
 
+#else /* USE_GRN_TEXT_OTOJ */
+
+void
+grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
+               grn_obj *obj, grn_obj_format *format)
+{
+  grn_obj buf;
+  GRN_TEXT_INIT(&buf, 0);
+  switch (obj->header.type) {
+  case GRN_BULK :
+    switch (obj->header.domain) {
+    case GRN_DB_VOID :
+    case GRN_DB_SHORT_TEXT :
+    case GRN_DB_TEXT :
+    case GRN_DB_LONG_TEXT :
+      grn_output_str(ctx, outbuf, output_type, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj));
+      break;
+    case GRN_DB_BOOL :
+      grn_output_bool(ctx, outbuf, output_type,
+                       GRN_BULK_VSIZE(obj) ? GRN_UINT8_VALUE(obj) : 0);
+      break;
+    case GRN_DB_INT8 :
+      grn_output_int32(ctx, outbuf, output_type,
+                       GRN_BULK_VSIZE(obj) ? GRN_INT8_VALUE(obj) : 0);
+      break;
+    case GRN_DB_UINT8 :
+      grn_output_int32(ctx, outbuf, output_type,
+                       GRN_BULK_VSIZE(obj) ? GRN_UINT8_VALUE(obj) : 0);
+      break;
+    case GRN_DB_INT16 :
+      grn_output_int32(ctx, outbuf, output_type,
+                       GRN_BULK_VSIZE(obj) ? GRN_INT16_VALUE(obj) : 0);
+      break;
+    case GRN_DB_UINT16 :
+      grn_output_int32(ctx, outbuf, output_type,
+                       GRN_BULK_VSIZE(obj) ? GRN_UINT16_VALUE(obj) : 0);
+      break;
+    case GRN_DB_INT32 :
+      grn_output_int32(ctx, outbuf, output_type,
+                       GRN_BULK_VSIZE(obj) ? GRN_INT32_VALUE(obj) : 0);
+      break;
+    case GRN_DB_UINT32 :
+      grn_output_int64(ctx, outbuf, output_type,
+                       GRN_BULK_VSIZE(obj) ? GRN_UINT32_VALUE(obj) : 0);
+      break;
+    case GRN_DB_INT64 :
+      grn_output_int64(ctx, outbuf, output_type,
+                       GRN_BULK_VSIZE(obj) ? GRN_INT64_VALUE(obj) : 0);
+      break;
+    case GRN_DB_UINT64 :
+      grn_output_uint64(ctx, outbuf, output_type,
+                        GRN_BULK_VSIZE(obj) ? GRN_UINT64_VALUE(obj) : 0);
+      break;
+    case GRN_DB_FLOAT :
+      grn_output_float(ctx, outbuf, output_type,
+                       GRN_BULK_VSIZE(obj) ? GRN_FLOAT_VALUE(obj) : 0);
+      break;
+    case GRN_DB_TIME :
+      grn_output_time(ctx, outbuf, output_type,
+                      GRN_BULK_VSIZE(obj) ? GRN_INT64_VALUE(obj) : 0);
+      break;
+    case GRN_DB_TOKYO_GEO_POINT :
+    case GRN_DB_WGS84_GEO_POINT :
+      grn_output_geo_point(ctx, outbuf, output_type,
+                           GRN_BULK_VSIZE(obj) ? (grn_geo_point *)GRN_BULK_HEAD(obj) : NULL);
+      break;
+    default :
+      if (format) {
+        int j;
+        int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *);
+        grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns);
+        if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) {
+          grn_output_array_open(ctx, outbuf, output_type, "FIELDS", -1);
+          for (j = 0; j < ncolumns; j++) {
+            grn_id range_id;
+            grn_output_array_open(ctx, outbuf, output_type, "FIELD", -1);
+            GRN_BULK_REWIND(&buf);
+            grn_column_name_(ctx, columns[j], &buf);
+            grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
+            /* column range */
+            range_id = grn_obj_get_range(ctx, columns[j]);
+            if (range_id == GRN_ID_NIL) {
+              GRN_TEXT_PUTS(ctx, outbuf, "null");
+            } else {
+              int name_len;
+              grn_obj *range_obj;
+              char name_buf[GRN_TABLE_MAX_KEY_SIZE];
+
+              range_obj = grn_ctx_at(ctx, range_id);
+              name_len = grn_obj_name(ctx, range_obj, name_buf,
+                                      GRN_TABLE_MAX_KEY_SIZE);
+              GRN_BULK_REWIND(&buf);
+              GRN_TEXT_PUT(ctx, &buf, name_buf, name_len);
+              grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
+            }
+            grn_output_array_close(ctx, outbuf, output_type);
+          }
+          grn_output_array_close(ctx, outbuf, output_type);
+        }
+        grn_output_array_open(ctx, outbuf, output_type, "HIT", -1);
+        for (j = 0; j < ncolumns; j++) {
+          grn_text_atoj_o(ctx, outbuf, output_type, columns[j], obj);
+        }
+        grn_output_array_close(ctx, outbuf, output_type);
+      } else {
+        grn_obj *table = grn_ctx_at(ctx, obj->header.domain);
+        grn_id id = *((grn_id *)GRN_BULK_HEAD(obj));
+        if (table && table->header.type != GRN_TABLE_NO_KEY) {
+          grn_obj *accessor = grn_obj_column(ctx, table, "_key", 4);
+          if (accessor) {
+            grn_obj_get_value(ctx, accessor, id, &buf);
+            grn_obj_unlink(ctx, accessor);
+          }
+          grn_output_obj(ctx, outbuf, output_type, &buf, format);
+        } else {
+          grn_output_int64(ctx, outbuf, output_type, id);
+        }
+      }
+      break;
+    }
+    break;
+  case GRN_UVECTOR :
+    if (format) {
+      int i, j;
+      grn_id *v = (grn_id *)GRN_BULK_HEAD(obj), *ve = (grn_id *)GRN_BULK_CURR(obj);
+      int ncolumns = GRN_BULK_VSIZE(&format->columns) / sizeof(grn_obj *);
+      grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns);
+      grn_output_array_open(ctx, outbuf, output_type, "RESULTSET", -1);
+      grn_output_array_open(ctx, outbuf, output_type, "NHITS", -1);
+      grn_text_itoa(ctx, outbuf, ve - v);
+      grn_output_array_close(ctx, outbuf, output_type);
+      if (v < ve) {
+        if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) {
+          grn_output_array_open(ctx, outbuf, output_type, "FIELDS", -1);
+          for (j = 0; j < ncolumns; j++) {
+            grn_id range_id;
+            grn_output_array_open(ctx, outbuf, output_type, "FIELD", -1);
+            GRN_BULK_REWIND(&buf);
+            grn_column_name_(ctx, columns[j], &buf);
+            grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
+            /* column range */
+            range_id = grn_obj_get_range(ctx, columns[j]);
+            if (range_id == GRN_ID_NIL) {
+              GRN_TEXT_PUTS(ctx, outbuf, "null");
+            } else {
+              int name_len;
+              grn_obj *range_obj;
+              char name_buf[GRN_TABLE_MAX_KEY_SIZE];
+
+              range_obj = grn_ctx_at(ctx, range_id);
+              name_len = grn_obj_name(ctx, range_obj, name_buf,
+                                      GRN_TABLE_MAX_KEY_SIZE);
+              GRN_BULK_REWIND(&buf);
+              GRN_TEXT_PUT(ctx, &buf, name_buf, name_len);
+              grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
+            }
+            grn_output_array_close(ctx, outbuf, output_type);
+          }
+          grn_output_array_close(ctx, outbuf, output_type);
+        }
+        for (i = 0;; i++) {
+          grn_output_array_open(ctx, outbuf, output_type, "HITS", -1);
+          for (j = 0; j < ncolumns; j++) {
+            GRN_BULK_REWIND(&buf);
+            grn_obj_get_value(ctx, columns[j], *v, &buf);
+            grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
+          }
+          grn_output_array_close(ctx, outbuf, output_type);
+        }
+      }
+      grn_output_array_close(ctx, outbuf, output_type);
+    } else {
+      grn_obj *range = grn_ctx_at(ctx, obj->header.domain);
+      if (range && range->header.type == GRN_TYPE) {
+        grn_id value_size = ((struct _grn_type *)range)->obj.range;
+        char *v = (char *)GRN_BULK_HEAD(obj),
+             *ve = (char *)GRN_BULK_CURR(obj);
+        grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1);
+        if (v < ve) {
+          for (;;) {
+            grn_obj value;
+            GRN_OBJ_INIT(&value, GRN_BULK, 0, obj->header.domain);
+            grn_bulk_write_from(ctx, &value, v, 0, value_size);
+            grn_output_obj(ctx, outbuf, output_type, &value, NULL);
+
+            v += value_size;
+            if (v < ve) {
+
+            } else {
+              break;
+            }
+          }
+        }
+        grn_output_array_close(ctx, outbuf, output_type);
+      } else {
+        grn_id *v = (grn_id *)GRN_BULK_HEAD(obj),
+               *ve = (grn_id *)GRN_BULK_CURR(obj);
+        grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1);
+        if (v < ve) {
+          for (;;) {
+            grn_obj key;
+            if (range->header.type != GRN_TABLE_NO_KEY) {
+              GRN_OBJ_INIT(&key, GRN_BULK, 0, range->header.domain);
+              grn_table_get_key2(ctx, range, *v, &key);
+              grn_output_obj(ctx, outbuf, output_type, &key, NULL);
+            } else {
+              grn_text_lltoa(ctx, outbuf, *v);
+            }
+            v++;
+            if (v < ve) {
+
+            } else {
+              break;
+            }
+          }
+        }
+        grn_output_array_close(ctx, outbuf, output_type);
+      }
+    }
+    break;
+  case GRN_VECTOR :
+    if (obj->header.domain == GRN_DB_VOID) {
+      ERR(GRN_INVALID_ARGUMENT, "invalid obj->header.domain");
+    }
+    if (format) {
+      ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
+          "cannot print GRN_VECTOR using grn_obj_format");
+    } else {
+      unsigned int i, n;
+      grn_obj value;
+      GRN_VOID_INIT(&value);
+      n = grn_vector_size(ctx, obj);
+      grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1);
+      for (i = 0; i < n; i++) {
+        const char *_value;
+        unsigned int weight, length;
+        grn_id domain;
+
+        length = grn_vector_get_element(ctx, obj, i,
+                                        &_value, &weight, &domain);
+        if (domain != GRN_DB_VOID) {
+          grn_obj_reinit(ctx, &value, domain, 0);
+        } else {
+          grn_obj_reinit(ctx, &value, obj->header.domain, 0);
+        }
+        grn_bulk_write(ctx, &value, _value, length);
+        grn_output_obj(ctx, outbuf, output_type, &value, NULL);
+      }
+      grn_output_array_close(ctx, outbuf, output_type);
+    }
+    break;
+  case GRN_PVECTOR :
+    if (format) {
+      ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
+          "cannot print GRN_PVECTOR using grn_obj_format");
+    } else {
+      unsigned int i, n;
+      grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1);
+      n = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *);
+      for (i = 0; i < n; i++) {
+        grn_obj *value;
+
+        value = GRN_PTR_VALUE_AT(obj, i);
+        grn_output_obj(ctx, outbuf, output_type, value, NULL);
+      }
+      grn_output_array_close(ctx, outbuf, output_type);
+    }
+    break;
+  case GRN_TABLE_HASH_KEY :
+  case GRN_TABLE_PAT_KEY :
+  case GRN_TABLE_NO_KEY :
+  case GRN_TABLE_VIEW :
+    if (format) {
+      int i, j;
+      int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *);
+      grn_obj id, **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns);
+      grn_table_cursor *tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0,
+                                                   format->offset, format->limit,
+                                                   GRN_CURSOR_ASCENDING);
+      if (!tc) { ERRCLR(ctx); }
+      grn_output_array_open(ctx, outbuf, output_type, "RESULTSET", -1);
+      grn_output_array_open(ctx, outbuf, output_type, "NHITS", -1);
+      grn_text_itoa(ctx, outbuf, format->nhits);
+      grn_output_array_close(ctx, outbuf, output_type);
+      if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) {
+        grn_output_array_open(ctx, outbuf, output_type, "FIELDS", -1);
+        for (j = 0; j < ncolumns; j++) {
+          grn_id range_id;
+          grn_output_array_open(ctx, outbuf, output_type, "FIELD", -1);
+          GRN_BULK_REWIND(&buf);
+          grn_column_name_(ctx, columns[j], &buf);
+          grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
+          /* column range */
+          range_id = grn_obj_get_range(ctx, columns[j]);
+          if (range_id == GRN_ID_NIL) {
+            GRN_TEXT_PUTS(ctx, outbuf, "null");
+          } else {
+            int name_len;
+            grn_obj *range_obj;
+            char name_buf[GRN_TABLE_MAX_KEY_SIZE];
+
+            range_obj = grn_ctx_at(ctx, range_id);
+            name_len = grn_obj_name(ctx, range_obj, name_buf,
+                                    GRN_TABLE_MAX_KEY_SIZE);
+            GRN_BULK_REWIND(&buf);
+            GRN_TEXT_PUT(ctx, &buf, name_buf, name_len);
+            grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
+          }
+          grn_output_array_close(ctx, outbuf, output_type);
+        }
+        grn_output_array_close(ctx, outbuf, output_type);
+      }
+      GRN_TEXT_INIT(&id, 0);
+      if (tc) {
+        for (i = 0; !grn_table_cursor_next_o(ctx, tc, &id); i++) {
+          grn_output_array_open(ctx, outbuf, output_type, "HIT", -1);
+          for (j = 0; j < ncolumns; j++) {
+            grn_text_atoj_o(ctx, outbuf, output_type, columns[j], &id);
+          }
+          grn_output_array_close(ctx, outbuf, output_type);
+        }
+        grn_table_cursor_close(ctx, tc);
+      }
+      grn_output_array_close(ctx, outbuf, output_type);
+    } else {
+      int i;
+      grn_obj id, *column = grn_obj_column(ctx, obj, "_key", 4);
+      grn_table_cursor *tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0,
+                                                   0, -1, GRN_CURSOR_ASCENDING);
+      grn_output_array_open(ctx, outbuf, output_type, "HIT", -1);
+      if (tc) {
+        GRN_TEXT_INIT(&id, 0);
+        for (i = 0; !grn_table_cursor_next_o(ctx, tc, &id); i++) {
+          /* todo:
+          grn_text_atoj_o(ctx, outbuf, output_type, column, &id);
+          */
+          GRN_BULK_REWIND(&buf);
+          grn_obj_get_value_o(ctx, column, &id, &buf);
+          grn_text_esc(ctx, outbuf, GRN_BULK_HEAD(&buf), GRN_BULK_VSIZE(&buf));
+        }
+        grn_table_cursor_close(ctx, tc);
+      }
+      grn_output_array_close(ctx, outbuf, output_type);
+      grn_obj_unlink(ctx, column);
+    }
+    break;
+  }
+  GRN_OBJ_FIN(ctx, &buf);
+}
+
+#endif /* USE_GRN_TEXT_OTOJ */

  Modified: lib/proc.c (+9 -9)
===================================================================
--- lib/proc.c    2010-06-21 05:28:02 +0000 (00c3a31)
+++ lib/proc.c    2010-06-22 11:21:23 +0000 (a294cbb)
@@ -831,7 +831,7 @@ print_tableinfo(grn_ctx *ctx, grn_obj *table)
   id = grn_obj_id(ctx, table);
   path = grn_obj_path(ctx, table);
   GRN_TEXT_INIT(&o, 0);
-  GRN_OUTPUT_ARRAY_OPEN("", -1);
+  GRN_OUTPUT_ARRAY_OPEN("TABLE", -1);
   GRN_OUTPUT_INT64(id);
   objid2name(ctx, id, &o);
   GRN_OUTPUT_OBJ(&o, NULL);
@@ -853,29 +853,29 @@ proc_table_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_dat
   grn_table_cursor *cur;
   if ((cur = grn_table_cursor_open(ctx, ctx->impl->db, NULL, 0, NULL, 0, 0, -1, 0))) {
     grn_id id;
-    GRN_OUTPUT_ARRAY_OPEN("", -1);
-    GRN_OUTPUT_ARRAY_OPEN("", -1);
-    GRN_OUTPUT_ARRAY_OPEN("", -1);
+    GRN_OUTPUT_ARRAY_OPEN("TABLE_LIST", -1);
+    GRN_OUTPUT_ARRAY_OPEN("COLUMNS", -1);
+    GRN_OUTPUT_ARRAY_OPEN("COLUMN", -1);
     GRN_OUTPUT_CSTR("id");
     GRN_OUTPUT_CSTR("UInt32");
     GRN_OUTPUT_ARRAY_CLOSE();
-    GRN_OUTPUT_ARRAY_OPEN("", -1);
+    GRN_OUTPUT_ARRAY_OPEN("COLUMN", -1);
     GRN_OUTPUT_CSTR("name");
     GRN_OUTPUT_CSTR("ShortText");
     GRN_OUTPUT_ARRAY_CLOSE();
-    GRN_OUTPUT_ARRAY_OPEN("", -1);
+    GRN_OUTPUT_ARRAY_OPEN("COLUMN", -1);
     GRN_OUTPUT_CSTR("path");
     GRN_OUTPUT_CSTR("ShortText");
     GRN_OUTPUT_ARRAY_CLOSE();
-    GRN_OUTPUT_ARRAY_OPEN("", -1);
+    GRN_OUTPUT_ARRAY_OPEN("COLUMN", -1);
     GRN_OUTPUT_CSTR("flags");
     GRN_OUTPUT_CSTR("ShortText");
     GRN_OUTPUT_ARRAY_CLOSE();
-    GRN_OUTPUT_ARRAY_OPEN("", -1);
+    GRN_OUTPUT_ARRAY_OPEN("COLUMN", -1);
     GRN_OUTPUT_CSTR("domain");
     GRN_OUTPUT_CSTR("ShortText");
     GRN_OUTPUT_ARRAY_CLOSE();
-    GRN_OUTPUT_ARRAY_OPEN("", -1);
+    GRN_OUTPUT_ARRAY_OPEN("COLUMN", -1);
     GRN_OUTPUT_CSTR("range");
     GRN_OUTPUT_CSTR("ShortText");
     GRN_OUTPUT_ARRAY_CLOSE();

  Modified: src/groonga.c (+33 -0)
===================================================================
--- src/groonga.c    2010-06-21 05:28:02 +0000 (9411988)
+++ src/groonga.c    2010-06-22 11:21:23 +0000 (d59ef84)
@@ -309,6 +309,39 @@ print_return_code(grn_ctx *ctx, grn_rc rc, grn_obj *head, grn_obj *body, grn_obj
     break;
   case GRN_CONTENT_TSV:
   case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, head, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RESULT CODE=\"");
+    grn_text_itoa(ctx, head, rc);
+    GRN_TEXT_PUTS(ctx, head, "\" UP=\"");
+    {
+      double dv;
+      grn_timeval tv;
+      grn_timeval_now(ctx, &tv);
+      dv = ctx->impl->tv.tv_sec;
+      dv += ctx->impl->tv.tv_usec / 1000000.0;
+      grn_text_ftoa(ctx, head, dv);
+      dv = (tv.tv_sec - ctx->impl->tv.tv_sec);
+      dv += (tv.tv_usec - ctx->impl->tv.tv_usec) / 1000000.0;
+      GRN_TEXT_PUTS(ctx, head, "\" ELAPSED=\"");
+      grn_text_ftoa(ctx, head, dv);
+      GRN_TEXT_PUTS(ctx, head, "\">");
+    }
+    if (rc != GRN_SUCCESS) {
+      GRN_TEXT_PUTS(ctx, head, "<ERROR>");
+      grn_text_escape_xml(ctx, head, ctx->errbuf, strlen(ctx->errbuf));
+      if (ctx->errfunc && ctx->errfile) {
+        /* TODO: output backtrace */
+        GRN_TEXT_PUTS(ctx, head, "<INFO FUNC=\"");
+        grn_text_escape_xml(ctx, head, ctx->errfunc, strlen(ctx->errfunc));
+        GRN_TEXT_PUTS(ctx, head, "\" FILE=\"");
+        grn_text_escape_xml(ctx, head, ctx->errfile, strlen(ctx->errfile));
+        GRN_TEXT_PUTS(ctx, head, "\" LINE=\"");
+        grn_text_itoa(ctx, head, ctx->errline);
+        GRN_TEXT_PUTS(ctx, head, "\">");
+      }
+      GRN_TEXT_PUTS(ctx, head, "</ERROR>");
+    }
+    GRN_TEXT_PUTS(ctx, foot, "</RESULT>");
+    break;
   case GRN_CONTENT_NONE:
     break;
   }




Groonga-commit メーリングリストの案内
Back to archive index