1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2010-2017 Brazil
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License version 2.1 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#include "grn_db.h"
20#include "grn_pat.h"
21#include "grn_ii.h"
22#include "grn_util.h"
23#include "grn_string.h"
24#include "grn_expr.h"
25#include "grn_load.h"
26
27#include <string.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <fcntl.h>
31#include <sys/stat.h>
32
33#ifdef WIN32
34# include <io.h>
35# include <share.h>
36#endif /* WIN32 */
37
38grn_rc
39grn_normalize_offset_and_limit(grn_ctx *ctx, int size, int *p_offset, int *p_limit)
40{
41 int end;
42 int offset = *p_offset;
43 int limit = *p_limit;
44
45 if (offset < 0) {
46 offset += size;
47 if (offset < 0) {
48 *p_offset = 0;
49 *p_limit = 0;
50 return GRN_TOO_SMALL_OFFSET;
51 }
52 } else if (offset != 0 && offset >= size) {
53 *p_offset = 0;
54 *p_limit = 0;
55 return GRN_TOO_LARGE_OFFSET;
56 }
57
58 if (limit < 0) {
59 limit += size + 1;
60 if (limit < 0) {
61 *p_offset = 0;
62 *p_limit = 0;
63 return GRN_TOO_SMALL_LIMIT;
64 }
65 } else if (limit > size) {
66 limit = size;
67 }
68
69 /* At this point, offset and limit must be zero or positive. */
70 end = offset + limit;
71 if (end > size) {
72 limit -= end - size;
73 }
74 *p_offset = offset;
75 *p_limit = limit;
76 return GRN_SUCCESS;
77}
78
79grn_obj *
80grn_inspect_name(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
81{
82 int name_size;
83
84 name_size = grn_obj_name(ctx, obj, NULL, 0);
85 if (name_size > 0) {
86 grn_bulk_space(ctx, buf, name_size);
87 grn_obj_name(ctx, obj, GRN_BULK_CURR(buf) - name_size, name_size);
88 } else {
89 grn_id id;
90
91 id = grn_obj_id(ctx, obj);
92 if (id == GRN_ID_NIL) {
93 GRN_TEXT_PUTS(ctx, buf, "(nil)");
94 } else {
95 GRN_TEXT_PUTS(ctx, buf, "(anonymous:");
96 grn_text_lltoa(ctx, buf, id);
97 GRN_TEXT_PUTS(ctx, buf, ")");
98 }
99 }
100
101 return buf;
102}
103
104grn_obj *
105grn_inspect_encoding(grn_ctx *ctx, grn_obj *buf, grn_encoding encoding)
106{
107 switch (encoding) {
108 case GRN_ENC_DEFAULT :
109 GRN_TEXT_PUTS(ctx, buf, "default(");
110 grn_inspect_encoding(ctx, buf, grn_get_default_encoding());
111 GRN_TEXT_PUTS(ctx, buf, ")");
112 break;
113 case GRN_ENC_NONE :
114 GRN_TEXT_PUTS(ctx, buf, "none");
115 break;
116 case GRN_ENC_EUC_JP :
117 GRN_TEXT_PUTS(ctx, buf, "EUC-JP");
118 break;
119 case GRN_ENC_UTF8 :
120 GRN_TEXT_PUTS(ctx, buf, "UTF-8");
121 break;
122 case GRN_ENC_SJIS :
123 GRN_TEXT_PUTS(ctx, buf, "Shift_JIS");
124 break;
125 case GRN_ENC_LATIN1 :
126 GRN_TEXT_PUTS(ctx, buf, "Latin-1");
127 break;
128 case GRN_ENC_KOI8R :
129 GRN_TEXT_PUTS(ctx, buf, "KOI8-R");
130 break;
131 default :
132 GRN_TEXT_PUTS(ctx, buf, "unknown(");
133 grn_text_itoa(ctx, buf, encoding);
134 GRN_TEXT_PUTS(ctx, buf, ")");
135 break;
136 }
137
138 return buf;
139}
140
141grn_obj *
142grn_inspect_type(grn_ctx *ctx, grn_obj *buf, unsigned char type)
143{
144 switch (type) {
145 case GRN_VOID :
146 GRN_TEXT_PUTS(ctx, buf, "GRN_VOID");
147 break;
148 case GRN_BULK :
149 GRN_TEXT_PUTS(ctx, buf, "GRN_BULK");
150 break;
151 case GRN_PTR :
152 GRN_TEXT_PUTS(ctx, buf, "GRN_PTR");
153 break;
154 case GRN_UVECTOR :
155 GRN_TEXT_PUTS(ctx, buf, "GRN_UVECTOR");
156 break;
157 case GRN_PVECTOR :
158 GRN_TEXT_PUTS(ctx, buf, "GRN_PVECTOR");
159 break;
160 case GRN_VECTOR :
161 GRN_TEXT_PUTS(ctx, buf, "GRN_VECTOR");
162 break;
163 case GRN_MSG :
164 GRN_TEXT_PUTS(ctx, buf, "GRN_MSG");
165 break;
166 case GRN_QUERY :
167 GRN_TEXT_PUTS(ctx, buf, "GRN_QUERY");
168 break;
169 case GRN_ACCESSOR :
170 GRN_TEXT_PUTS(ctx, buf, "GRN_ACCESSOR");
171 break;
172 case GRN_SNIP :
173 GRN_TEXT_PUTS(ctx, buf, "GRN_SNIP");
174 break;
175 case GRN_PATSNIP :
176 GRN_TEXT_PUTS(ctx, buf, "GRN_PATSNIP");
177 break;
178 case GRN_STRING :
179 GRN_TEXT_PUTS(ctx, buf, "GRN_STRING");
180 break;
181 case GRN_CURSOR_TABLE_HASH_KEY :
182 GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_HASH_KEY");
183 break;
184 case GRN_CURSOR_TABLE_PAT_KEY :
185 GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_PAT_KEY");
186 break;
187 case GRN_CURSOR_TABLE_DAT_KEY :
188 GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_DAT_KEY");
189 break;
190 case GRN_CURSOR_TABLE_NO_KEY :
191 GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_NO_KEY");
192 break;
193 case GRN_CURSOR_COLUMN_INDEX :
194 GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_COLUMN_INDEX");
195 break;
196 case GRN_CURSOR_COLUMN_GEO_INDEX :
197 GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_COLUMN_GEO_INDEX");
198 break;
199 case GRN_TYPE :
200 GRN_TEXT_PUTS(ctx, buf, "GRN_TYPE");
201 break;
202 case GRN_PROC :
203 GRN_TEXT_PUTS(ctx, buf, "GRN_PROC");
204 break;
205 case GRN_EXPR :
206 GRN_TEXT_PUTS(ctx, buf, "GRN_EXPR");
207 break;
208 case GRN_TABLE_HASH_KEY :
209 GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_HASH_KEY");
210 break;
211 case GRN_TABLE_PAT_KEY :
212 GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_PAT_KEY");
213 break;
214 case GRN_TABLE_DAT_KEY :
215 GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_DAT_KEY");
216 break;
217 case GRN_TABLE_NO_KEY :
218 GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_NO_KEY");
219 break;
220 case GRN_DB :
221 GRN_TEXT_PUTS(ctx, buf, "GRN_DB");
222 break;
223 case GRN_COLUMN_FIX_SIZE :
224 GRN_TEXT_PUTS(ctx, buf, "GRN_COLUMN_FIX_SIZE");
225 break;
226 case GRN_COLUMN_VAR_SIZE :
227 GRN_TEXT_PUTS(ctx, buf, "GRN_COLUMN_VAR_SIZE");
228 break;
229 case GRN_COLUMN_INDEX :
230 GRN_TEXT_PUTS(ctx, buf, "GRN_COLUMN_INDEX");
231 break;
232 default:
233 {
234#define TYPE_IN_HEX_SIZE 5 /* "0xXX" */
235 char type_in_hex[TYPE_IN_HEX_SIZE];
236 grn_snprintf(type_in_hex,
237 TYPE_IN_HEX_SIZE,
238 TYPE_IN_HEX_SIZE,
239 "%#02x", type);
240#undef TYPE_IN_HEX_SIZE
241 GRN_TEXT_PUTS(ctx, buf, "(unknown: ");
242 GRN_TEXT_PUTS(ctx, buf, type_in_hex);
243 GRN_TEXT_PUTS(ctx, buf, ")");
244 }
245 break;
246 }
247
248 return buf;
249}
250
251
252grn_obj *
253grn_inspect_query_log_flags(grn_ctx *ctx, grn_obj *buffer, unsigned int flags)
254{
255 grn_bool have_content = GRN_FALSE;
256
257 if (flags == GRN_QUERY_LOG_NONE) {
258 GRN_TEXT_PUTS(ctx, buffer, "NONE");
259 return buffer;
260 }
261
262#define CHECK_FLAG(NAME) do { \
263 if (flags & GRN_QUERY_LOG_ ## NAME) { \
264 if (have_content) { \
265 GRN_TEXT_PUTS(ctx, buffer, "|"); \
266 } \
267 GRN_TEXT_PUTS(ctx, buffer, #NAME); \
268 have_content = GRN_TRUE; \
269 } \
270 } while (GRN_FALSE)
271
272 CHECK_FLAG(COMMAND);
273 CHECK_FLAG(RESULT_CODE);
274 CHECK_FLAG(DESTINATION);
275 CHECK_FLAG(CACHE);
276 CHECK_FLAG(SIZE);
277 CHECK_FLAG(SCORE);
278
279#undef CHECK_FALG
280
281 return buffer;
282}
283
284static grn_rc
285grn_proc_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
286{
287 grn_proc *proc = (grn_proc *)obj;
288 uint32_t i;
289
290 GRN_TEXT_PUTS(ctx, buf, "#<proc:");
291 switch (proc->type) {
292 case GRN_PROC_INVALID :
293 GRN_TEXT_PUTS(ctx, buf, "invalid");
294 GRN_TEXT_PUTS(ctx, buf, ">");
295 return GRN_SUCCESS;
296 break;
297 case GRN_PROC_TOKENIZER :
298 GRN_TEXT_PUTS(ctx, buf, "tokenizer");
299 break;
300 case GRN_PROC_COMMAND :
301 GRN_TEXT_PUTS(ctx, buf, "command");
302 break;
303 case GRN_PROC_FUNCTION :
304 GRN_TEXT_PUTS(ctx, buf, "function");
305 break;
306 case GRN_PROC_HOOK :
307 GRN_TEXT_PUTS(ctx, buf, "hook");
308 break;
309 case GRN_PROC_NORMALIZER :
310 GRN_TEXT_PUTS(ctx, buf, "normalizer");
311 break;
312 case GRN_PROC_TOKEN_FILTER :
313 GRN_TEXT_PUTS(ctx, buf, "token-filter");
314 break;
315 case GRN_PROC_SCORER :
316 GRN_TEXT_PUTS(ctx, buf, "scorer");
317 break;
318 case GRN_PROC_WINDOW_FUNCTION :
319 GRN_TEXT_PUTS(ctx, buf, "window-function");
320 break;
321 }
322 GRN_TEXT_PUTS(ctx, buf, " ");
323
324 grn_inspect_name(ctx, buf, obj);
325 GRN_TEXT_PUTS(ctx, buf, " ");
326
327 GRN_TEXT_PUTS(ctx, buf, "arguments:[");
328 for (i = 0; i < proc->nvars; i++) {
329 grn_expr_var *var = proc->vars + i;
330 if (i != 0) {
331 GRN_TEXT_PUTS(ctx, buf, ", ");
332 }
333 GRN_TEXT_PUT(ctx, buf, var->name, var->name_size);
334 }
335 GRN_TEXT_PUTS(ctx, buf, "]");
336
337 GRN_TEXT_PUTS(ctx, buf, ">");
338
339 return GRN_SUCCESS;
340}
341
342grn_rc
343grn_expr_code_inspect_indented(grn_ctx *ctx,
344 grn_obj *buffer,
345 grn_expr_code *code,
346 const char *indent)
347{
348 if (!code) {
349 GRN_TEXT_PUTS(ctx, buffer, "(NULL)");
350 return GRN_SUCCESS;
351 }
352
353 GRN_TEXT_PUTS(ctx, buffer, "<");
354 GRN_TEXT_PUTS(ctx, buffer, grn_operator_to_string(code->op));
355 GRN_TEXT_PUTS(ctx, buffer, " ");
356 GRN_TEXT_PUTS(ctx, buffer, "n_args:");
357 grn_text_itoa(ctx, buffer, code->nargs);
358 GRN_TEXT_PUTS(ctx, buffer, ", ");
359 GRN_TEXT_PUTS(ctx, buffer, "flags:");
360 grn_text_itoh(ctx, buffer, code->flags, 1);
361 GRN_TEXT_PUTS(ctx, buffer, ", ");
362 GRN_TEXT_PUTS(ctx, buffer, "modify:");
363 grn_text_itoa(ctx, buffer, code->modify);
364 GRN_TEXT_PUTS(ctx, buffer, ", ");
365 GRN_TEXT_PUTS(ctx, buffer, "value:");
366 grn_inspect_indented(ctx, buffer, code->value, " ");
367 GRN_TEXT_PUTS(ctx, buffer, ">");
368
369 return GRN_SUCCESS;
370}
371
372grn_rc
373grn_expr_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *expr)
374{
375 grn_expr *e = (grn_expr *)expr;
376
377 GRN_TEXT_PUTS(ctx, buffer, "#<expr\n");
378 {
379 int i = 0;
380 grn_obj *value;
381 const char *name;
382 uint32_t name_len;
383 unsigned int n_vars;
384 grn_hash *vars = grn_expr_get_vars(ctx, expr, &n_vars);
385 GRN_TEXT_PUTS(ctx, buffer, " vars:{");
386 GRN_HASH_EACH(ctx, vars, id, &name, &name_len, &value, {
387 if (i++) {
388 GRN_TEXT_PUTC(ctx, buffer, ',');
389 }
390 GRN_TEXT_PUTS(ctx, buffer, "\n ");
391 GRN_TEXT_PUT(ctx, buffer, name, name_len);
392 GRN_TEXT_PUTC(ctx, buffer, ':');
393 grn_inspect_indented(ctx, buffer, value, " ");
394 });
395 GRN_TEXT_PUTS(ctx, buffer, "\n },");
396 }
397
398 {
399 uint32_t i;
400 grn_expr_code *code;
401 GRN_TEXT_PUTS(ctx, buffer, "\n codes:{");
402 for (i = 0, code = e->codes; i < e->codes_curr; i++, code++) {
403 if (i) { GRN_TEXT_PUTC(ctx, buffer, ','); }
404 GRN_TEXT_PUTS(ctx, buffer, "\n ");
405 grn_text_itoa(ctx, buffer, i);
406 GRN_TEXT_PUTS(ctx, buffer, ":");
407 grn_expr_code_inspect_indented(ctx, buffer, code, " ");
408 }
409 GRN_TEXT_PUTS(ctx, buffer, "\n }");
410 }
411
412 GRN_TEXT_PUTS(ctx, buffer, "\n>");
413
414 return GRN_SUCCESS;
415}
416
417static grn_rc
418grn_ptr_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *ptr)
419{
420 size_t size;
421
422 GRN_TEXT_PUTS(ctx, buffer, "#<ptr:");
423
424 size = GRN_BULK_VSIZE(ptr);
425 if (size == 0) {
426 GRN_TEXT_PUTS(ctx, buffer, "(empty)");
427 } else if (size >= sizeof(grn_obj *)) {
428 grn_obj *content = GRN_PTR_VALUE(ptr);
429 grn_inspect(ctx, buffer, content);
430 if (size > sizeof(grn_obj *)) {
431 grn_text_printf(ctx, buffer,
432 " (and more data: %" GRN_FMT_SIZE ")",
433 size - sizeof(grn_obj *));
434 }
435 }
436 GRN_TEXT_PUTS(ctx, buffer, ">");
437
438 return GRN_SUCCESS;
439}
440
441static grn_rc
442grn_pvector_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *pvector)
443{
444 int i, n;
445
446 GRN_TEXT_PUTS(ctx, buffer, "[");
447 n = GRN_BULK_VSIZE(pvector) / sizeof(grn_obj *);
448 for (i = 0; i < n; i++) {
449 grn_obj *element = GRN_PTR_VALUE_AT(pvector, i);
450
451 if (i > 0) {
452 GRN_TEXT_PUTS(ctx, buffer, ", ");
453 }
454
455 grn_inspect(ctx, buffer, element);
456 }
457 GRN_TEXT_PUTS(ctx, buffer, "]");
458
459 return GRN_SUCCESS;
460}
461
462static grn_rc
463grn_vector_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *vector)
464{
465 int i;
466 grn_obj *body = vector->u.v.body;
467
468 GRN_TEXT_PUTS(ctx, buffer, "[");
469 for (i = 0; i < vector->u.v.n_sections; i++) {
470 grn_section *section = &(vector->u.v.sections[i]);
471 const char *value_raw;
472
473 if (i > 0) {
474 GRN_TEXT_PUTS(ctx, buffer, ", ");
475 }
476
477 value_raw = GRN_BULK_HEAD(body) + section->offset;
478 GRN_TEXT_PUTS(ctx, buffer, "{");
479 GRN_TEXT_PUTS(ctx, buffer, "\"value\":");
480 {
481 grn_obj value_object;
482 GRN_OBJ_INIT(&value_object, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY,
483 section->domain);
484 GRN_TEXT_SET(ctx, &value_object, value_raw, section->length);
485 grn_inspect(ctx, buffer, &value_object);
486 GRN_OBJ_FIN(ctx, &value_object);
487 }
488 GRN_TEXT_PUTS(ctx, buffer, ", \"weight\":");
489 grn_text_itoa(ctx, buffer, section->weight);
490 GRN_TEXT_PUTS(ctx, buffer, "}");
491 }
492 GRN_TEXT_PUTS(ctx, buffer, "]");
493
494 return GRN_SUCCESS;
495}
496
497static grn_rc
498grn_accessor_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
499{
500 grn_accessor *accessor = (grn_accessor *)obj;
501
502 GRN_TEXT_PUTS(ctx, buf, "#<accessor ");
503 for (; accessor; accessor = accessor->next) {
504 grn_bool show_obj_name = GRN_FALSE;
505 grn_bool show_obj_domain_name = GRN_FALSE;
506
507 if (accessor != (grn_accessor *)obj) {
508 GRN_TEXT_PUTS(ctx, buf, ".");
509 }
510 switch (accessor->action) {
511 case GRN_ACCESSOR_GET_ID :
512 GRN_TEXT_PUT(ctx,
513 buf,
514 GRN_COLUMN_NAME_ID,
515 GRN_COLUMN_NAME_ID_LEN);
516 show_obj_name = GRN_TRUE;
517 break;
518 case GRN_ACCESSOR_GET_KEY :
519 GRN_TEXT_PUT(ctx,
520 buf,
521 GRN_COLUMN_NAME_KEY,
522 GRN_COLUMN_NAME_KEY_LEN);
523 show_obj_name = GRN_TRUE;
524 break;
525 case GRN_ACCESSOR_GET_VALUE :
526 GRN_TEXT_PUT(ctx,
527 buf,
528 GRN_COLUMN_NAME_VALUE,
529 GRN_COLUMN_NAME_VALUE_LEN);
530 show_obj_name = GRN_TRUE;
531 break;
532 case GRN_ACCESSOR_GET_SCORE :
533 GRN_TEXT_PUT(ctx,
534 buf,
535 GRN_COLUMN_NAME_SCORE,
536 GRN_COLUMN_NAME_SCORE_LEN);
537 break;
538 case GRN_ACCESSOR_GET_NSUBRECS :
539 GRN_TEXT_PUT(ctx,
540 buf,
541 GRN_COLUMN_NAME_NSUBRECS,
542 GRN_COLUMN_NAME_NSUBRECS_LEN);
543 break;
544 case GRN_ACCESSOR_GET_MAX :
545 GRN_TEXT_PUT(ctx,
546 buf,
547 GRN_COLUMN_NAME_MAX,
548 GRN_COLUMN_NAME_MAX_LEN);
549 break;
550 case GRN_ACCESSOR_GET_MIN :
551 GRN_TEXT_PUT(ctx,
552 buf,
553 GRN_COLUMN_NAME_MIN,
554 GRN_COLUMN_NAME_MIN_LEN);
555 break;
556 case GRN_ACCESSOR_GET_SUM :
557 GRN_TEXT_PUT(ctx,
558 buf,
559 GRN_COLUMN_NAME_SUM,
560 GRN_COLUMN_NAME_SUM_LEN);
561 break;
562 case GRN_ACCESSOR_GET_AVG :
563 GRN_TEXT_PUT(ctx,
564 buf,
565 GRN_COLUMN_NAME_AVG,
566 GRN_COLUMN_NAME_AVG_LEN);
567 break;
568 case GRN_ACCESSOR_GET_COLUMN_VALUE :
569 grn_column_name_(ctx, accessor->obj, buf);
570 show_obj_domain_name = GRN_TRUE;
571 break;
572 case GRN_ACCESSOR_GET_DB_OBJ :
573 grn_text_printf(ctx, buf, "(_db)");
574 break;
575 case GRN_ACCESSOR_LOOKUP :
576 grn_text_printf(ctx, buf, "(_lookup)");
577 break;
578 case GRN_ACCESSOR_FUNCALL :
579 grn_text_printf(ctx, buf, "(_funcall)");
580 break;
581 default :
582 grn_text_printf(ctx, buf, "(unknown:%u)", accessor->action);
583 break;
584 }
585
586 if (show_obj_name || show_obj_domain_name) {
587 grn_obj *target = accessor->obj;
588 char name[GRN_TABLE_MAX_KEY_SIZE];
589 int name_size;
590
591 if (show_obj_domain_name) {
592 target = grn_ctx_at(ctx, target->header.domain);
593 }
594
595 name_size = grn_obj_name(ctx,
596 target,
597 name,
598 GRN_TABLE_MAX_KEY_SIZE);
599 GRN_TEXT_PUTS(ctx, buf, "(");
600 if (name_size == 0) {
601 GRN_TEXT_PUTS(ctx, buf, "anonymous");
602 } else {
603 GRN_TEXT_PUT(ctx, buf, name, name_size);
604 }
605 GRN_TEXT_PUTS(ctx, buf, ")");
606 }
607 }
608 GRN_TEXT_PUTS(ctx, buf, ">");
609
610 return GRN_SUCCESS;
611}
612
613static grn_rc
614grn_type_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
615{
616 grn_id range_id;
617
618 GRN_TEXT_PUTS(ctx, buf, "#<type ");
619 grn_inspect_name(ctx, buf, obj);
620
621 range_id = grn_obj_get_range(ctx, obj);
622 GRN_TEXT_PUTS(ctx, buf, " size:");
623 grn_text_lltoa(ctx, buf, range_id);
624
625 GRN_TEXT_PUTS(ctx, buf, " type:");
626 if (obj->header.flags & GRN_OBJ_KEY_VAR_SIZE) {
627 GRN_TEXT_PUTS(ctx, buf, "var_size");
628 } else {
629 switch (obj->header.flags & GRN_OBJ_KEY_MASK) {
630 case GRN_OBJ_KEY_UINT :
631 GRN_TEXT_PUTS(ctx, buf, "uint");
632 break;
633 case GRN_OBJ_KEY_INT :
634 GRN_TEXT_PUTS(ctx, buf, "int");
635 break;
636 case GRN_OBJ_KEY_FLOAT :
637 GRN_TEXT_PUTS(ctx, buf, "float");
638 break;
639 case GRN_OBJ_KEY_GEO_POINT :
640 GRN_TEXT_PUTS(ctx, buf, "geo_point");
641 break;
642 default :
643 break;
644 }
645 }
646
647 GRN_TEXT_PUTS(ctx, buf, ">");
648 return GRN_SUCCESS;
649}
650
651static grn_rc
652grn_column_inspect_common(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
653{
654 grn_id range_id;
655
656 grn_inspect_name(ctx, buf, obj);
657
658 range_id = grn_obj_get_range(ctx, obj);
659 if (range_id) {
660 grn_obj *range = grn_ctx_at(ctx, range_id);
661 GRN_TEXT_PUTS(ctx, buf, " range:");
662 if (range) {
663 grn_inspect_name(ctx, buf, range);
664 } else {
665 grn_text_lltoa(ctx, buf, range_id);
666 }
667 }
668
669 return GRN_SUCCESS;
670}
671
672static grn_rc
673grn_store_inspect_body(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
674{
675 grn_column_inspect_common(ctx, buf, obj);
676 GRN_TEXT_PUTS(ctx, buf, " type:");
677 switch (obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) {
678 case GRN_OBJ_COLUMN_VECTOR :
679 GRN_TEXT_PUTS(ctx, buf, "vector");
680 break;
681 case GRN_OBJ_COLUMN_SCALAR :
682 GRN_TEXT_PUTS(ctx, buf, "scalar");
683 break;
684 default:
685 break;
686 }
687
688 GRN_TEXT_PUTS(ctx, buf, " compress:");
689 switch (obj->header.flags & GRN_OBJ_COMPRESS_MASK) {
690 case GRN_OBJ_COMPRESS_NONE :
691 GRN_TEXT_PUTS(ctx, buf, "none");
692 break;
693 case GRN_OBJ_COMPRESS_ZLIB :
694 GRN_TEXT_PUTS(ctx, buf, "zlib");
695 break;
696 case GRN_OBJ_COMPRESS_LZ4 :
697 GRN_TEXT_PUTS(ctx, buf, "lz4");
698 break;
699 case GRN_OBJ_COMPRESS_ZSTD :
700 GRN_TEXT_PUTS(ctx, buf, "zstd");
701 break;
702 default:
703 break;
704 }
705
706 if (obj->header.flags & GRN_OBJ_RING_BUFFER) {
707 GRN_TEXT_PUTS(ctx, buf, " ring_buffer:true");
708 }
709
710 return GRN_SUCCESS;
711}
712
713static grn_rc
714grn_ra_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
715{
716 GRN_TEXT_PUTS(ctx, buf, "#<column:fix_size ");
717 grn_store_inspect_body(ctx, buf, obj);
718 GRN_TEXT_PUTS(ctx, buf, ">");
719 return GRN_SUCCESS;
720}
721
722static grn_rc
723grn_ja_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
724{
725 GRN_TEXT_PUTS(ctx, buf, "#<column:var_size ");
726 grn_store_inspect_body(ctx, buf, obj);
727 GRN_TEXT_PUTS(ctx, buf, ">");
728 return GRN_SUCCESS;
729}
730
731static grn_rc
732grn_ii_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
733{
734 grn_obj sources;
735 int i, n, have_flags = 0;
736 grn_id *source_ids;
737
738 GRN_TEXT_PUTS(ctx, buf, "#<column:index ");
739 grn_column_inspect_common(ctx, buf, obj);
740
741 GRN_TEXT_INIT(&sources, 0);
742 grn_obj_get_info(ctx, obj, GRN_INFO_SOURCE, &sources);
743 source_ids = (grn_id *)GRN_BULK_HEAD(&sources);
744 n = GRN_BULK_VSIZE(&sources) / sizeof(grn_id);
745 GRN_TEXT_PUTS(ctx, buf, " sources:[");
746 for (i = 0; i < n; i++) {
747 grn_id source_id;
748 grn_obj *source;
749 if (i) { GRN_TEXT_PUTS(ctx, buf, ", "); }
750 source_id = source_ids[i];
751 source = grn_ctx_at(ctx, source_id);
752 if (source) {
753 grn_inspect_name(ctx, buf, source);
754 } else {
755 grn_text_lltoa(ctx, buf, source_id);
756 }
757 }
758 GRN_TEXT_PUTS(ctx, buf, "]");
759 GRN_OBJ_FIN(ctx, &sources);
760
761 GRN_TEXT_PUTS(ctx, buf, " flags:");
762 if (obj->header.flags & GRN_OBJ_WITH_SECTION) {
763 GRN_TEXT_PUTS(ctx, buf, "SECTION");
764 have_flags = 1;
765 }
766 if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) {
767 if (have_flags) { GRN_TEXT_PUTS(ctx, buf, "|"); }
768 GRN_TEXT_PUTS(ctx, buf, "WEIGHT");
769 have_flags = 1;
770 }
771 if (obj->header.flags & GRN_OBJ_WITH_POSITION) {
772 if (have_flags) { GRN_TEXT_PUTS(ctx, buf, "|"); }
773 GRN_TEXT_PUTS(ctx, buf, "POSITION");
774 have_flags = 1;
775 }
776 if (!have_flags) {
777 GRN_TEXT_PUTS(ctx, buf, "NONE");
778 }
779
780 GRN_TEXT_PUTS(ctx, buf, ">");
781
782 return GRN_SUCCESS;
783}
784
785static grn_rc
786grn_table_type_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
787{
788 switch (obj->header.type) {
789 case GRN_TABLE_HASH_KEY:
790 GRN_TEXT_PUTS(ctx, buf, "hash");
791 break;
792 case GRN_TABLE_PAT_KEY:
793 GRN_TEXT_PUTS(ctx, buf, "pat");
794 break;
795 case GRN_TABLE_DAT_KEY:
796 GRN_TEXT_PUTS(ctx, buf, "dat");
797 break;
798 case GRN_TABLE_NO_KEY:
799 GRN_TEXT_PUTS(ctx, buf, "no_key");
800 break;
801 }
802
803 return GRN_SUCCESS;
804}
805
806static grn_rc
807grn_table_key_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
808{
809 grn_obj *domain;
810 grn_id domain_id;
811
812 GRN_TEXT_PUTS(ctx, buf, "key:");
813 domain_id = obj->header.domain;
814 domain = grn_ctx_at(ctx, domain_id);
815 if (domain) {
816 grn_inspect_name(ctx, buf, domain);
817 } else if (domain_id) {
818 grn_text_lltoa(ctx, buf, domain_id);
819 } else {
820 GRN_TEXT_PUTS(ctx, buf, "(nil)");
821 }
822
823 return GRN_SUCCESS;
824}
825
826static grn_rc
827grn_table_columns_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
828{
829 grn_hash *cols;
830
831 GRN_TEXT_PUTS(ctx, buf, "columns:[");
832 if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
833 GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) {
834 if (grn_table_columns(ctx, obj, "", 0, (grn_obj *)cols)) {
835 int i = 0;
836 grn_id *key;
837 GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, {
838 grn_obj *col = grn_ctx_at(ctx, *key);
839 if (col) {
840 if (i++ > 0) { GRN_TEXT_PUTS(ctx, buf, ", "); }
841 grn_column_name_(ctx, col, buf);
842 }
843 });
844 }
845 grn_hash_close(ctx, cols);
846 }
847 GRN_TEXT_PUTS(ctx, buf, "]");
848
849 return GRN_SUCCESS;
850}
851
852static grn_rc
853grn_table_ids_and_values_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
854{
855 int i = 0;
856 grn_obj value;
857
858 GRN_VALUE_FIX_SIZE_INIT(&value, 0, grn_obj_get_range(ctx, obj));
859
860 GRN_TEXT_PUTS(ctx, buf, "ids&values:[");
861 GRN_TABLE_EACH_BEGIN(ctx, obj, cursor, id) {
862 void *value_buffer;
863 int value_size;
864
865 if (i++ > 0) {
866 GRN_TEXT_PUTS(ctx, buf, ", ");
867 }
868
869 GRN_TEXT_PUTS(ctx, buf, "\n ");
870 grn_text_lltoa(ctx, buf, id);
871 GRN_TEXT_PUTS(ctx, buf, ":");
872 value_size = grn_table_cursor_get_value(ctx, cursor, &value_buffer);
873 grn_bulk_write_from(ctx, &value, value_buffer, 0, value_size);
874 grn_inspect(ctx, buf, &value);
875 } GRN_TABLE_EACH_END(ctx, cursor);
876 GRN_TEXT_PUTS(ctx, buf, "\n]");
877
878 GRN_OBJ_FIN(ctx, &value);
879
880 return GRN_SUCCESS;
881}
882
883static grn_rc
884grn_table_ids_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
885{
886 grn_table_cursor *tc;
887
888 GRN_TEXT_PUTS(ctx, buf, "ids:[");
889 tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0,
890 0, -1, GRN_CURSOR_ASCENDING);
891 if (tc) {
892 int i = 0;
893 grn_id id;
894 while ((id = grn_table_cursor_next(ctx, tc))) {
895 if (i++ > 0) { GRN_TEXT_PUTS(ctx, buf, ", "); }
896 grn_text_lltoa(ctx, buf, id);
897 }
898 grn_table_cursor_close(ctx, tc);
899 }
900 GRN_TEXT_PUTS(ctx, buf, "]");
901
902 return GRN_SUCCESS;
903}
904
905static grn_rc
906grn_table_default_tokenizer_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
907{
908 grn_obj *default_tokenizer;
909
910 GRN_TEXT_PUTS(ctx, buf, "default_tokenizer:");
911 default_tokenizer = grn_obj_get_info(ctx, obj,
912 GRN_INFO_DEFAULT_TOKENIZER, NULL);
913 if (default_tokenizer) {
914 grn_inspect_name(ctx, buf, default_tokenizer);
915 } else {
916 GRN_TEXT_PUTS(ctx, buf, "(nil)");
917 }
918
919 return GRN_SUCCESS;
920}
921
922static grn_rc
923grn_table_normalizer_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
924{
925 grn_obj *normalizer;
926
927 GRN_TEXT_PUTS(ctx, buf, "normalizer:");
928 normalizer = grn_obj_get_info(ctx, obj, GRN_INFO_NORMALIZER, NULL);
929 if (normalizer) {
930 grn_inspect_name(ctx, buf, normalizer);
931 } else {
932 GRN_TEXT_PUTS(ctx, buf, "(nil)");
933 }
934
935 return GRN_SUCCESS;
936}
937
938static grn_rc
939grn_table_keys_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
940{
941 grn_table_cursor *tc;
942 int max_n_keys = 10;
943
944 /* TODO */
945 /* max_n_keys = grn_atoi(grn_getenv("GRN_INSPECT_TABLE_MAX_N_KEYS")); */
946
947 GRN_TEXT_PUTS(ctx, buf, "keys:[");
948 tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0,
949 0, -1, GRN_CURSOR_ASCENDING);
950 if (tc) {
951 int i = 0;
952 grn_id id;
953 grn_obj key;
954 GRN_OBJ_INIT(&key, GRN_BULK, 0, obj->header.domain);
955 while ((id = grn_table_cursor_next(ctx, tc))) {
956 if (max_n_keys > 0 && i >= max_n_keys) {
957 GRN_TEXT_PUTS(ctx, buf, ", ...");
958 break;
959 }
960 if (i++ > 0) { GRN_TEXT_PUTS(ctx, buf, ", "); }
961 grn_table_get_key2(ctx, obj, id, &key);
962 grn_inspect(ctx, buf, &key);
963 GRN_BULK_REWIND(&key);
964 }
965 GRN_OBJ_FIN(ctx, &key);
966 grn_table_cursor_close(ctx, tc);
967 }
968 GRN_TEXT_PUTS(ctx, buf, "]");
969
970 return GRN_SUCCESS;
971}
972
973static grn_rc
974grn_table_subrec_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
975{
976 GRN_TEXT_PUTS(ctx, buf, "subrec:");
977 if (obj->header.flags & GRN_OBJ_WITH_SUBREC) {
978 switch (obj->header.flags & GRN_OBJ_UNIT_MASK) {
979 case GRN_OBJ_UNIT_DOCUMENT_NONE :
980 GRN_TEXT_PUTS(ctx, buf, "document:none");
981 break;
982 case GRN_OBJ_UNIT_DOCUMENT_SECTION :
983 GRN_TEXT_PUTS(ctx, buf, "document:section");
984 break;
985 case GRN_OBJ_UNIT_DOCUMENT_POSITION :
986 GRN_TEXT_PUTS(ctx, buf, "document:position");
987 break;
988 case GRN_OBJ_UNIT_SECTION_NONE :
989 GRN_TEXT_PUTS(ctx, buf, "section:none");
990 break;
991 case GRN_OBJ_UNIT_SECTION_POSITION :
992 GRN_TEXT_PUTS(ctx, buf, "section:popsition");
993 break;
994 case GRN_OBJ_UNIT_POSITION_NONE :
995 GRN_TEXT_PUTS(ctx, buf, "section:none");
996 break;
997 case GRN_OBJ_UNIT_USERDEF_DOCUMENT :
998 GRN_TEXT_PUTS(ctx, buf, "userdef:document");
999 break;
1000 case GRN_OBJ_UNIT_USERDEF_SECTION :
1001 GRN_TEXT_PUTS(ctx, buf, "userdef:section");
1002 break;
1003 case GRN_OBJ_UNIT_USERDEF_POSITION :
1004 GRN_TEXT_PUTS(ctx, buf, "userdef:position");
1005 break;
1006 }
1007 } else {
1008 GRN_TEXT_PUTS(ctx, buf, "none");
1009 }
1010
1011 return GRN_SUCCESS;
1012}
1013
1014static grn_rc
1015grn_table_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
1016{
1017 grn_id range_id;
1018 grn_obj *range;
1019
1020 GRN_TEXT_PUTS(ctx, buf, "#<table:");
1021 grn_table_type_inspect(ctx, buf, obj);
1022 GRN_TEXT_PUTS(ctx, buf, " ");
1023
1024 grn_inspect_name(ctx, buf, obj);
1025
1026 if (obj->header.type != GRN_TABLE_NO_KEY) {
1027 GRN_TEXT_PUTS(ctx, buf, " ");
1028 grn_table_key_inspect(ctx, buf, obj);
1029 }
1030
1031 GRN_TEXT_PUTS(ctx, buf, " value:");
1032 range_id = grn_obj_get_range(ctx, obj);
1033 range = grn_ctx_at(ctx, range_id);
1034 if (range) {
1035 grn_inspect_name(ctx, buf, range);
1036 } else if (range_id) {
1037 grn_text_lltoa(ctx, buf, range_id);
1038 } else {
1039 GRN_TEXT_PUTS(ctx, buf, "(nil)");
1040 }
1041
1042 GRN_TEXT_PUTS(ctx, buf, " size:");
1043 grn_text_lltoa(ctx, buf, grn_table_size(ctx, obj));
1044
1045 GRN_TEXT_PUTS(ctx, buf, " ");
1046 grn_table_columns_inspect(ctx, buf, obj);
1047
1048 if (obj->header.type == GRN_TABLE_NO_KEY) {
1049 GRN_TEXT_PUTS(ctx, buf, " ");
1050 if (range) {
1051 grn_table_ids_and_values_inspect(ctx, buf, obj);
1052 } else {
1053 grn_table_ids_inspect(ctx, buf, obj);
1054 }
1055 } else {
1056 GRN_TEXT_PUTS(ctx, buf, " ");
1057 grn_table_default_tokenizer_inspect(ctx, buf, obj);
1058
1059 GRN_TEXT_PUTS(ctx, buf, " ");
1060 grn_table_normalizer_inspect(ctx, buf, obj);
1061
1062 GRN_TEXT_PUTS(ctx, buf, " ");
1063 grn_table_keys_inspect(ctx, buf, obj);
1064 }
1065
1066 GRN_TEXT_PUTS(ctx, buf, " ");
1067 grn_table_subrec_inspect(ctx, buf, obj);
1068
1069 if (obj->header.type == GRN_TABLE_PAT_KEY) {
1070 GRN_TEXT_PUTS(ctx, buf, " nodes:");
1071 grn_pat_inspect_nodes(ctx, (grn_pat *)obj, buf);
1072 }
1073
1074 GRN_TEXT_PUTS(ctx, buf, ">");
1075
1076 return GRN_SUCCESS;
1077}
1078
1079static grn_rc
1080grn_db_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
1081{
1082 grn_db *db = (grn_db *)obj;
1083
1084 GRN_TEXT_PUTS(ctx, buf, "#<db");
1085
1086 GRN_TEXT_PUTS(ctx, buf, " key_type:");
1087 grn_table_type_inspect(ctx, buf, db->keys);
1088
1089 GRN_TEXT_PUTS(ctx, buf, " size:");
1090 grn_text_lltoa(ctx, buf, grn_table_size(ctx, obj));
1091
1092 GRN_TEXT_PUTS(ctx, buf, ">");
1093
1094 return GRN_SUCCESS;
1095}
1096
1097static grn_rc
1098grn_time_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj)
1099{
1100 int64_t time_raw;
1101 int64_t sec;
1102 int32_t usec;
1103
1104 time_raw = GRN_TIME_VALUE(obj);
1105 GRN_TIME_UNPACK(time_raw, sec, usec);
1106 grn_text_printf(ctx, buffer,
1107 "%" GRN_FMT_INT64D ".%d",
1108 sec, usec);
1109
1110 return GRN_SUCCESS;
1111}
1112
1113static grn_rc
1114grn_geo_point_inspect_point(grn_ctx *ctx, grn_obj *buf, int point)
1115{
1116 GRN_TEXT_PUTS(ctx, buf, "(");
1117 grn_text_itoa(ctx, buf, point / 1000 / 3600 % 3600);
1118 GRN_TEXT_PUTS(ctx, buf, ", ");
1119 grn_text_itoa(ctx, buf, point / 1000 / 60 % 60);
1120 GRN_TEXT_PUTS(ctx, buf, ", ");
1121 grn_text_itoa(ctx, buf, point / 1000 % 60);
1122 GRN_TEXT_PUTS(ctx, buf, ", ");
1123 grn_text_itoa(ctx, buf, point % 1000);
1124 GRN_TEXT_PUTS(ctx, buf, ")");
1125
1126 return GRN_SUCCESS;
1127}
1128
1129static grn_rc
1130grn_geo_point_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
1131{
1132 int latitude, longitude;
1133
1134 GRN_GEO_POINT_VALUE(obj, latitude, longitude);
1135
1136 GRN_TEXT_PUTS(ctx, buf, "[");
1137 GRN_TEXT_PUTS(ctx, buf, "(");
1138 grn_text_itoa(ctx, buf, latitude);
1139 GRN_TEXT_PUTS(ctx, buf, ",");
1140 grn_text_itoa(ctx, buf, longitude);
1141 GRN_TEXT_PUTS(ctx, buf, ")");
1142
1143 GRN_TEXT_PUTS(ctx, buf, " (");
1144 grn_geo_point_inspect_point(ctx, buf, latitude);
1145 GRN_TEXT_PUTS(ctx, buf, ",");
1146 grn_geo_point_inspect_point(ctx, buf, longitude);
1147 GRN_TEXT_PUTS(ctx, buf, ")");
1148
1149 {
1150 int i, j;
1151 grn_geo_point point;
1152 uint8_t encoded[sizeof(grn_geo_point)];
1153
1154 GRN_TEXT_PUTS(ctx, buf, " [");
1155 point.latitude = latitude;
1156 point.longitude = longitude;
1157 grn_gton(encoded, &point, sizeof(grn_geo_point));
1158 for (i = 0; i < sizeof(grn_geo_point); i++) {
1159 if (i != 0) {
1160 GRN_TEXT_PUTS(ctx, buf, " ");
1161 }
1162 for (j = 0; j < 8; j++) {
1163 grn_text_itoa(ctx, buf, (encoded[i] >> (7 - j)) & 1);
1164 }
1165 }
1166 GRN_TEXT_PUTS(ctx, buf, "]");
1167 }
1168
1169 GRN_TEXT_PUTS(ctx, buf, "]");
1170
1171 return GRN_SUCCESS;
1172}
1173
1174static grn_rc
1175grn_json_load_open_bracket_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
1176{
1177 uint32_t i, n;
1178
1179 n = GRN_UINT32_VALUE(obj);
1180
1181 GRN_TEXT_PUTS(ctx, buf, "[");
1182 for (i = 0; i < n; i++) {
1183 grn_obj *value;
1184 value = obj + 1 + i;
1185 if (i > 0) {
1186 GRN_TEXT_PUTS(ctx, buf, ", ");
1187 }
1188 grn_inspect(ctx, buf, value);
1189 }
1190 GRN_TEXT_PUTS(ctx, buf, "]");
1191
1192 return GRN_SUCCESS;
1193}
1194
1195static grn_rc
1196grn_json_load_open_brace_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
1197{
1198 uint32_t i, n;
1199
1200 n = GRN_UINT32_VALUE(obj);
1201
1202 GRN_TEXT_PUTS(ctx, buf, "{");
1203 for (i = 0; i < n; i += 2) {
1204 grn_obj *key, *value;
1205 key = obj + 1 + i;
1206 value = key + 1;
1207 if (i > 0) {
1208 GRN_TEXT_PUTS(ctx, buf, ", ");
1209 }
1210 grn_inspect(ctx, buf, key);
1211 GRN_TEXT_PUTS(ctx, buf, ": ");
1212 grn_inspect(ctx, buf, value);
1213 }
1214 GRN_TEXT_PUTS(ctx, buf, "}");
1215
1216 return GRN_SUCCESS;
1217}
1218
1219static grn_rc
1220grn_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
1221{
1222 grn_obj *table;
1223 grn_hash *cols;
1224
1225 table = grn_ctx_at(ctx, obj->header.domain);
1226 GRN_TEXT_PUTS(ctx, buf, "#<record:");
1227 if (table) {
1228 grn_table_type_inspect(ctx, buf, table);
1229 GRN_TEXT_PUTS(ctx, buf, ":");
1230 grn_inspect_name(ctx, buf, table);
1231 } else {
1232 GRN_TEXT_PUTS(ctx, buf, "(anonymous table:");
1233 grn_text_lltoa(ctx, buf, obj->header.domain);
1234 GRN_TEXT_PUTS(ctx, buf, ")");
1235 }
1236
1237 GRN_TEXT_PUTS(ctx, buf, " id:");
1238 if (GRN_BULK_VSIZE(obj) == 0) {
1239 GRN_TEXT_PUTS(ctx, buf, "(no value)");
1240 } else {
1241 grn_id id;
1242
1243 id = GRN_RECORD_VALUE(obj);
1244 grn_text_lltoa(ctx, buf, id);
1245
1246 if (table && grn_table_at(ctx, table, id)) {
1247 if (table->header.type != GRN_TABLE_NO_KEY) {
1248 grn_obj key;
1249 GRN_TEXT_PUTS(ctx, buf, " key:");
1250 GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);
1251 grn_table_get_key2(ctx, table, id, &key);
1252 grn_inspect(ctx, buf, &key);
1253 GRN_OBJ_FIN(ctx, &key);
1254 }
1255 if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
1256 GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) {
1257 if (grn_table_columns(ctx, table, "", 0, (grn_obj *)cols)) {
1258 grn_id *key;
1259 GRN_HASH_EACH(ctx, cols, column_id, &key, NULL, NULL, {
1260 grn_obj *col = grn_ctx_at(ctx, *key);
1261 if (col) {
1262 grn_obj value;
1263 GRN_TEXT_INIT(&value, 0);
1264 GRN_TEXT_PUTS(ctx, buf, " ");
1265 grn_column_name_(ctx, col, buf);
1266 GRN_TEXT_PUTS(ctx, buf, ":");
1267 grn_obj_get_value(ctx, col, id, &value);
1268 grn_inspect(ctx, buf, &value);
1269 GRN_OBJ_FIN(ctx, &value);
1270 }
1271 });
1272 }
1273 grn_hash_close(ctx, cols);
1274 }
1275 } else {
1276 GRN_TEXT_PUTS(ctx, buf, "(nonexistent)");
1277 }
1278 }
1279
1280 GRN_TEXT_PUTS(ctx, buf, ">");
1281
1282 return GRN_SUCCESS;
1283}
1284
1285static grn_rc
1286grn_uvector_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
1287{
1288 unsigned int i, n = 0;
1289 grn_obj record;
1290
1291 GRN_RECORD_INIT(&record, 0, obj->header.domain);
1292 GRN_TEXT_PUTS(ctx, buf, "[");
1293 n = grn_vector_size(ctx, obj);
1294 for (i = 0; i < n; i++) {
1295 grn_id id;
1296 unsigned int weight;
1297
1298 if (i > 0) {
1299 GRN_TEXT_PUTS(ctx, buf, ", ");
1300 }
1301
1302 id = grn_uvector_get_element(ctx, obj, i, &weight);
1303 GRN_TEXT_PUTS(ctx, buf, "#<element record:");
1304 GRN_RECORD_SET(ctx, &record, id);
1305 grn_inspect(ctx, buf, &record);
1306 grn_text_printf(ctx, buf, ", weight:%u>", weight);
1307 }
1308 GRN_TEXT_PUTS(ctx, buf, "]");
1309 GRN_OBJ_FIN(ctx, &record);
1310
1311 return GRN_SUCCESS;
1312}
1313
1314grn_obj *
1315grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj)
1316{
1317 grn_obj *domain;
1318
1319 if (!buffer) {
1320 buffer = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_TEXT);
1321 }
1322
1323 if (!obj) {
1324 GRN_TEXT_PUTS(ctx, buffer, "(NULL)");
1325 return buffer;
1326 }
1327
1328 switch (obj->header.type) {
1329 case GRN_VOID :
1330 /* TODO */
1331 break;
1332 case GRN_BULK :
1333 switch (obj->header.domain) {
1334 case GRN_DB_TIME :
1335 grn_time_inspect(ctx, buffer, obj);
1336 return buffer;
1337 case GRN_DB_TOKYO_GEO_POINT :
1338 case GRN_DB_WGS84_GEO_POINT :
1339 grn_geo_point_inspect(ctx, buffer, obj);
1340 return buffer;
1341 case GRN_JSON_LOAD_OPEN_BRACKET :
1342 grn_json_load_open_bracket_inspect(ctx, buffer, obj);
1343 return buffer;
1344 case GRN_JSON_LOAD_OPEN_BRACE :
1345 grn_json_load_open_brace_inspect(ctx, buffer, obj);
1346 return buffer;
1347 default :
1348 domain = grn_ctx_at(ctx, obj->header.domain);
1349 if (domain) {
1350 grn_id type = domain->header.type;
1351 switch (type) {
1352 case GRN_TABLE_HASH_KEY :
1353 case GRN_TABLE_PAT_KEY :
1354 case GRN_TABLE_NO_KEY :
1355 grn_record_inspect(ctx, buffer, obj);
1356 return buffer;
1357 default :
1358 break;
1359 }
1360 }
1361 }
1362 break;
1363 case GRN_PTR :
1364 grn_ptr_inspect(ctx, buffer, obj);
1365 break;
1366 case GRN_UVECTOR :
1367 domain = grn_ctx_at(ctx, obj->header.domain);
1368 if (domain) {
1369 grn_id type = domain->header.type;
1370 switch (type) {
1371 case GRN_TABLE_HASH_KEY :
1372 case GRN_TABLE_PAT_KEY :
1373 case GRN_TABLE_NO_KEY :
1374 grn_uvector_record_inspect(ctx, buffer, obj);
1375 return buffer;
1376 default :
1377 break;
1378 }
1379 }
1380 break;
1381 case GRN_PVECTOR :
1382 grn_pvector_inspect(ctx, buffer, obj);
1383 return buffer;
1384 case GRN_VECTOR :
1385 grn_vector_inspect(ctx, buffer, obj);
1386 return buffer;
1387 case GRN_MSG :
1388 /* TODO */
1389 break;
1390 case GRN_ACCESSOR :
1391 grn_accessor_inspect(ctx, buffer, obj);
1392 return buffer;
1393 case GRN_SNIP :
1394 case GRN_PATSNIP :
1395 /* TODO */
1396 break;
1397 case GRN_STRING :
1398 grn_string_inspect(ctx, buffer, obj);
1399 break;
1400 case GRN_CURSOR_TABLE_HASH_KEY :
1401 /* TODO */
1402 break;
1403 case GRN_CURSOR_TABLE_PAT_KEY :
1404 grn_pat_cursor_inspect(ctx, (grn_pat_cursor *)obj, buffer);
1405 return buffer;
1406 case GRN_CURSOR_TABLE_DAT_KEY :
1407 case GRN_CURSOR_TABLE_NO_KEY :
1408 case GRN_CURSOR_COLUMN_INDEX :
1409 case GRN_CURSOR_COLUMN_GEO_INDEX :
1410 /* TODO */
1411 break;
1412 case GRN_TYPE :
1413 grn_type_inspect(ctx, buffer, obj);
1414 return buffer;
1415 case GRN_PROC :
1416 grn_proc_inspect(ctx, buffer, obj);
1417 return buffer;
1418 case GRN_EXPR :
1419 grn_expr_inspect(ctx, buffer, obj);
1420 return buffer;
1421 case GRN_TABLE_HASH_KEY :
1422 case GRN_TABLE_PAT_KEY :
1423 case GRN_TABLE_DAT_KEY :
1424 case GRN_TABLE_NO_KEY :
1425 grn_table_inspect(ctx, buffer, obj);
1426 return buffer;
1427 case GRN_DB :
1428 grn_db_inspect(ctx, buffer, obj);
1429 break;
1430 case GRN_COLUMN_FIX_SIZE :
1431 grn_ra_inspect(ctx, buffer, obj);
1432 return buffer;
1433 case GRN_COLUMN_VAR_SIZE :
1434 grn_ja_inspect(ctx, buffer, obj);
1435 return buffer;
1436 case GRN_COLUMN_INDEX :
1437 grn_ii_inspect(ctx, buffer, obj);
1438 return buffer;
1439 default :
1440 break;
1441 }
1442
1443 grn_text_otoj(ctx, buffer, obj, NULL);
1444 return buffer;
1445}
1446
1447grn_obj *
1448grn_inspect_indented(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj,
1449 const char *indent)
1450{
1451 grn_obj sub_buffer;
1452
1453 GRN_TEXT_INIT(&sub_buffer, 0);
1454 grn_inspect(ctx, &sub_buffer, obj);
1455 {
1456 const char *inspected = GRN_TEXT_VALUE(&sub_buffer);
1457 size_t inspected_size = GRN_TEXT_LEN(&sub_buffer);
1458 size_t i, line_start;
1459
1460 if (!buffer) {
1461 buffer = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_TEXT);
1462 }
1463
1464 line_start = 0;
1465 for (i = 0; i < inspected_size; i++) {
1466 if (inspected[i] == '\n') {
1467 if (line_start != 0) {
1468 GRN_TEXT_PUTS(ctx, buffer, indent);
1469 }
1470 GRN_TEXT_PUT(ctx, buffer, inspected + line_start, i + 1 - line_start);
1471 line_start = i + 1;
1472 }
1473 }
1474 if (line_start != 0) {
1475 GRN_TEXT_PUTS(ctx, buffer, indent);
1476 }
1477 GRN_TEXT_PUT(ctx, buffer,
1478 inspected + line_start,
1479 inspected_size - line_start);
1480 }
1481 GRN_OBJ_FIN(ctx, &sub_buffer);
1482
1483 return buffer;
1484}
1485
1486grn_obj *
1487grn_inspect_limited(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj)
1488{
1489 grn_obj sub_buffer;
1490 unsigned int max_size = GRN_CTX_MSGSIZE / 2;
1491
1492 GRN_TEXT_INIT(&sub_buffer, 0);
1493 grn_inspect(ctx, &sub_buffer, obj);
1494 if (GRN_TEXT_LEN(&sub_buffer) > max_size) {
1495 GRN_TEXT_PUT(ctx, buffer, GRN_TEXT_VALUE(&sub_buffer), max_size);
1496 GRN_TEXT_PUTS(ctx, buffer, "...(");
1497 grn_text_lltoa(ctx, buffer, GRN_TEXT_LEN(&sub_buffer));
1498 GRN_TEXT_PUTS(ctx, buffer, ")");
1499 } else {
1500 GRN_TEXT_PUT(ctx,
1501 buffer,
1502 GRN_TEXT_VALUE(&sub_buffer),
1503 GRN_TEXT_LEN(&sub_buffer));
1504 }
1505 GRN_OBJ_FIN(ctx, &sub_buffer);
1506
1507 return buffer;
1508}
1509
1510void
1511grn_p(grn_ctx *ctx, grn_obj *obj)
1512{
1513 grn_obj buffer;
1514
1515 GRN_TEXT_INIT(&buffer, 0);
1516 grn_inspect(ctx, &buffer, obj);
1517 printf("%.*s\n", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
1518 GRN_OBJ_FIN(ctx, &buffer);
1519}
1520
1521void
1522grn_p_geo_point(grn_ctx *ctx, grn_geo_point *point)
1523{
1524 grn_obj obj;
1525
1526 GRN_WGS84_GEO_POINT_INIT(&obj, 0);
1527 GRN_GEO_POINT_SET(ctx, &obj, point->latitude, point->longitude);
1528 grn_p(ctx, &obj);
1529 GRN_OBJ_FIN(ctx, &obj);
1530}
1531
1532void
1533grn_p_ii_values(grn_ctx *ctx, grn_obj *ii)
1534{
1535 grn_obj buffer;
1536
1537 GRN_TEXT_INIT(&buffer, 0);
1538 grn_ii_inspect_values(ctx, (grn_ii *)ii, &buffer);
1539 printf("%.*s\n", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
1540 GRN_OBJ_FIN(ctx, &buffer);
1541}
1542
1543void
1544grn_p_expr_code(grn_ctx *ctx, grn_expr_code *code)
1545{
1546 grn_obj buffer;
1547
1548 GRN_TEXT_INIT(&buffer, 0);
1549 grn_expr_code_inspect_indented(ctx, &buffer, code, "");
1550 printf("%.*s\n", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
1551 GRN_OBJ_FIN(ctx, &buffer);
1552}
1553
1554void
1555grn_p_record(grn_ctx *ctx, grn_obj *table, grn_id id)
1556{
1557 grn_obj record;
1558
1559 GRN_RECORD_INIT(&record, 0, grn_obj_id(ctx, table));
1560 GRN_RECORD_SET(ctx, &record, id);
1561 grn_p(ctx, &record);
1562 GRN_OBJ_FIN(ctx, &record);
1563}
1564
1565#ifdef WIN32
1566int
1567grn_mkstemp(char *path_template)
1568{
1569 errno_t error;
1570 size_t path_template_size;
1571 int fd;
1572
1573 path_template_size = strlen(path_template) + 1;
1574 error = _mktemp_s(path_template, path_template_size);
1575 if (error != 0) {
1576 return -1;
1577 }
1578
1579 error = _sopen_s(&fd,
1580 path_template,
1581 _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
1582 _SH_DENYNO,
1583 _S_IREAD | _S_IWRITE);
1584 if (error != 0) {
1585 return -1;
1586 }
1587
1588 return fd;
1589}
1590#else /* WIN32 */
1591int
1592grn_mkstemp(char *path_template)
1593{
1594# ifdef HAVE_MKSTEMP
1595 return mkstemp(path_template);
1596# else /* HAVE_MKSTEMP */
1597 mktemp(path_template);
1598 return open(path_template, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
1599# endif /* HAVE_MKSTEMP */
1600}
1601#endif /* WIN32 */
1602
1603grn_bool
1604grn_path_exist(const char *path)
1605{
1606 struct stat status;
1607 return stat(path, &status) == 0;
1608}
1609
1610/* todo : refine */
1611/*
1612 * grn_tokenize splits a string into at most buf_size tokens and
1613 * returns the number of tokens. The ending address of each token is
1614 * written into tokbuf. Delimiters are ' ' and ','.
1615 * Then, the address to the remaining is set to rest.
1616 */
1617int
1618grn_tokenize(const char *str, size_t str_len,
1619 const char **tokbuf, int buf_size,
1620 const char **rest)
1621{
1622 const char **tok = tokbuf, **tok_end = tokbuf + buf_size;
1623 if (buf_size > 0) {
1624 const char *str_end = str + str_len;
1625 while (str < str_end && (' ' == *str || ',' == *str)) { str++; }
1626 for (;;) {
1627 if (str == str_end) {
1628 *tok++ = str;
1629 break;
1630 }
1631 if (' ' == *str || ',' == *str) {
1632 /* *str = '\0'; */
1633 *tok++ = str;
1634 if (tok == tok_end) { break; }
1635 do { str++; } while (str < str_end && (' ' == *str || ',' == *str));
1636 } else {
1637 str++;
1638 }
1639 }
1640 }
1641 if (rest) { *rest = str; }
1642 return tok - tokbuf;
1643}
1644