Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
util.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2 -*- */
2 /* Copyright(C) 2010-2013 Brazil
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License version 2.1 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Lesser General Public License for more details.
12 
13  You should have received a copy of the GNU Lesser General Public
14  License along with this library; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include "db.h"
19 #include "pat.h"
20 #include "ii.h"
21 #include "util.h"
22 #include "string_in.h"
23 
24 #include <string.h>
25 #include <stdio.h>
26 
27 grn_rc
28 grn_normalize_offset_and_limit(grn_ctx *ctx, int size, int *p_offset, int *p_limit)
29 {
30  int end;
31  int offset = *p_offset;
32  int limit = *p_limit;
33 
34  if (offset < 0) {
35  offset += size;
36  if (offset < 0) {
37  *p_offset = 0;
38  *p_limit = 0;
39  return GRN_TOO_SMALL_OFFSET;
40  }
41  } else if (offset != 0 && offset >= size) {
42  *p_offset = 0;
43  *p_limit = 0;
44  return GRN_TOO_LARGE_OFFSET;
45  }
46 
47  if (limit < 0) {
48  limit += size + 1;
49  if (limit < 0) {
50  *p_offset = 0;
51  *p_limit = 0;
52  return GRN_TOO_SMALL_LIMIT;
53  }
54  } else if (limit > size) {
55  limit = size;
56  }
57 
58  /* At this point, offset and limit must be zero or positive. */
59  end = offset + limit;
60  if (end > size) {
61  limit -= end - size;
62  }
63  *p_offset = offset;
64  *p_limit = limit;
65  return GRN_SUCCESS;
66 }
67 
68 grn_obj *
70 {
71  int name_size;
72 
73  name_size = grn_obj_name(ctx, obj, NULL, 0);
74  if (name_size) {
75  grn_bulk_space(ctx, buf, name_size);
76  grn_obj_name(ctx, obj, GRN_BULK_CURR(buf) - name_size, name_size);
77  } else {
78  GRN_TEXT_PUTS(ctx, buf, "(nil)");
79  }
80 
81  return buf;
82 }
83 
84 grn_obj *
86 {
87  switch (encoding) {
88  case GRN_ENC_DEFAULT :
89  GRN_TEXT_PUTS(ctx, buf, "default(");
91  GRN_TEXT_PUTS(ctx, buf, ")");
92  break;
93  case GRN_ENC_NONE :
94  GRN_TEXT_PUTS(ctx, buf, "none");
95  break;
96  case GRN_ENC_EUC_JP :
97  GRN_TEXT_PUTS(ctx, buf, "EUC-JP");
98  break;
99  case GRN_ENC_UTF8 :
100  GRN_TEXT_PUTS(ctx, buf, "UTF-8");
101  break;
102  case GRN_ENC_SJIS :
103  GRN_TEXT_PUTS(ctx, buf, "Shift_JIS");
104  break;
105  case GRN_ENC_LATIN1 :
106  GRN_TEXT_PUTS(ctx, buf, "Latin-1");
107  break;
108  case GRN_ENC_KOI8R :
109  GRN_TEXT_PUTS(ctx, buf, "KOI8-R");
110  break;
111  default :
112  GRN_TEXT_PUTS(ctx, buf, "unknown(");
113  grn_text_itoa(ctx, buf, encoding);
114  GRN_TEXT_PUTS(ctx, buf, ")");
115  break;
116  }
117 
118  return buf;
119 }
120 
121 grn_obj *
122 grn_inspect_type(grn_ctx *ctx, grn_obj *buf, unsigned char type)
123 {
124  switch (type) {
125  case GRN_VOID :
126  GRN_TEXT_PUTS(ctx, buf, "GRN_VOID");
127  break;
128  case GRN_BULK :
129  GRN_TEXT_PUTS(ctx, buf, "GRN_BULK");
130  break;
131  case GRN_PTR :
132  GRN_TEXT_PUTS(ctx, buf, "GRN_PTR");
133  break;
134  case GRN_UVECTOR :
135  GRN_TEXT_PUTS(ctx, buf, "GRN_UVECTOR");
136  break;
137  case GRN_PVECTOR :
138  GRN_TEXT_PUTS(ctx, buf, "GRN_PVECTOR");
139  break;
140  case GRN_VECTOR :
141  GRN_TEXT_PUTS(ctx, buf, "GRN_VECTOR");
142  break;
143  case GRN_MSG :
144  GRN_TEXT_PUTS(ctx, buf, "GRN_MSG");
145  break;
146  case GRN_QUERY :
147  GRN_TEXT_PUTS(ctx, buf, "GRN_QUERY");
148  break;
149  case GRN_ACCESSOR :
150  GRN_TEXT_PUTS(ctx, buf, "GRN_ACCESSOR");
151  break;
152  case GRN_SNIP :
153  GRN_TEXT_PUTS(ctx, buf, "GRN_SNIP");
154  break;
155  case GRN_PATSNIP :
156  GRN_TEXT_PUTS(ctx, buf, "GRN_PATSNIP");
157  break;
158  case GRN_STRING :
159  GRN_TEXT_PUTS(ctx, buf, "GRN_STRING");
160  break;
162  GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_HASH_KEY");
163  break;
165  GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_PAT_KEY");
166  break;
168  GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_DAT_KEY");
169  break;
171  GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_NO_KEY");
172  break;
174  GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_COLUMN_INDEX");
175  break;
177  GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_COLUMN_GEO_INDEX");
178  break;
179  case GRN_TYPE :
180  GRN_TEXT_PUTS(ctx, buf, "GRN_TYPE");
181  break;
182  case GRN_PROC :
183  GRN_TEXT_PUTS(ctx, buf, "GRN_PROC");
184  break;
185  case GRN_EXPR :
186  GRN_TEXT_PUTS(ctx, buf, "GRN_EXPR");
187  break;
188  case GRN_TABLE_HASH_KEY :
189  GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_HASH_KEY");
190  break;
191  case GRN_TABLE_PAT_KEY :
192  GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_PAT_KEY");
193  break;
194  case GRN_TABLE_DAT_KEY :
195  GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_DAT_KEY");
196  break;
197  case GRN_TABLE_NO_KEY :
198  GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_NO_KEY");
199  break;
200  case GRN_DB :
201  GRN_TEXT_PUTS(ctx, buf, "GRN_DB");
202  break;
203  case GRN_COLUMN_FIX_SIZE :
204  GRN_TEXT_PUTS(ctx, buf, "GRN_COLUMN_FIX_SIZE");
205  break;
206  case GRN_COLUMN_VAR_SIZE :
207  GRN_TEXT_PUTS(ctx, buf, "GRN_COLUMN_VAR_SIZE");
208  break;
209  case GRN_COLUMN_INDEX :
210  GRN_TEXT_PUTS(ctx, buf, "GRN_COLUMN_INDEX");
211  break;
212  default:
213  {
214  char type_in_hex[5]; /* "0xXX" */
215  sprintf(type_in_hex, "%#02x", type);
216  GRN_TEXT_PUTS(ctx, buf, "(unknown: ");
217  GRN_TEXT_PUTS(ctx, buf, type_in_hex);
218  GRN_TEXT_PUTS(ctx, buf, ")");
219  }
220  break;
221  }
222 
223  return buf;
224 }
225 
226 static grn_rc
227 grn_proc_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
228 {
229  grn_proc *proc = (grn_proc *)obj;
230  uint32_t i;
231 
232  GRN_TEXT_PUTS(ctx, buf, "#<proc:");
233  switch (proc->type) {
234  case GRN_PROC_TOKENIZER :
235  GRN_TEXT_PUTS(ctx, buf, "tokenizer");
236  break;
237  case GRN_PROC_COMMAND :
238  GRN_TEXT_PUTS(ctx, buf, "command");
239  break;
240  case GRN_PROC_FUNCTION :
241  GRN_TEXT_PUTS(ctx, buf, "function");
242  break;
243  case GRN_PROC_HOOK :
244  GRN_TEXT_PUTS(ctx, buf, "hook");
245  break;
246  case GRN_PROC_NORMALIZER :
247  GRN_TEXT_PUTS(ctx, buf, "normalizer");
248  break;
249  }
250  GRN_TEXT_PUTS(ctx, buf, " ");
251 
252  grn_inspect_name(ctx, buf, obj);
253  GRN_TEXT_PUTS(ctx, buf, " ");
254 
255  GRN_TEXT_PUTS(ctx, buf, "arguments:[");
256  for (i = 0; i < proc->nvars; i++) {
257  grn_expr_var *var = proc->vars + i;
258  if (i != 0) {
259  GRN_TEXT_PUTS(ctx, buf, ", ");
260  }
261  GRN_TEXT_PUT(ctx, buf, var->name, var->name_size);
262  }
263  GRN_TEXT_PUTS(ctx, buf, "]");
264 
265  GRN_TEXT_PUTS(ctx, buf, ">");
266 
267  return GRN_SUCCESS;
268 }
269 
270 static grn_rc
271 grn_vector_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *vector)
272 {
273  int i;
274  grn_obj *body = vector->u.v.body;
275 
276  GRN_TEXT_PUTS(ctx, buffer, "[");
277  for (i = 0; i < vector->u.v.n_sections; i++) {
278  grn_section *section = &(vector->u.v.sections[i]);
279  const char *value_raw;
280 
281  if (i > 0) {
282  GRN_TEXT_PUTS(ctx, buffer, ", ");
283  }
284 
285  value_raw = GRN_BULK_HEAD(body) + section->offset;
286  GRN_TEXT_PUTS(ctx, buffer, "{");
287  GRN_TEXT_PUTS(ctx, buffer, "\"value\":");
288  {
289  grn_obj value_object;
291  section->domain);
292  grn_bulk_write(ctx, &value_object, value_raw, section->length);
293  grn_inspect(ctx, buffer, &value_object);
294  GRN_OBJ_FIN(ctx, &value_object);
295  }
296  GRN_TEXT_PUTS(ctx, buffer, ", \"weight\":");
297  grn_text_itoa(ctx, buffer, section->weight);
298  GRN_TEXT_PUTS(ctx, buffer, "}");
299  }
300  GRN_TEXT_PUTS(ctx, buffer, "]");
301 
302  return GRN_SUCCESS;
303 }
304 
305 static grn_rc
306 grn_accessor_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
307 {
308  return grn_column_name_(ctx, obj, buf);
309 }
310 
311 static grn_rc
312 grn_type_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
313 {
314  grn_id range_id;
315 
316  GRN_TEXT_PUTS(ctx, buf, "#<type ");
317  grn_inspect_name(ctx, buf, obj);
318 
319  range_id = grn_obj_get_range(ctx, obj);
320  GRN_TEXT_PUTS(ctx, buf, " size:");
321  grn_text_lltoa(ctx, buf, range_id);
322 
323  GRN_TEXT_PUTS(ctx, buf, " type:");
324  if (obj->header.flags & GRN_OBJ_KEY_VAR_SIZE) {
325  GRN_TEXT_PUTS(ctx, buf, "var_size");
326  } else {
327  switch (obj->header.flags & GRN_OBJ_KEY_MASK) {
328  case GRN_OBJ_KEY_UINT :
329  GRN_TEXT_PUTS(ctx, buf, "uint");
330  break;
331  case GRN_OBJ_KEY_INT :
332  GRN_TEXT_PUTS(ctx, buf, "int");
333  break;
334  case GRN_OBJ_KEY_FLOAT :
335  GRN_TEXT_PUTS(ctx, buf, "float");
336  break;
337  case GRN_OBJ_KEY_GEO_POINT :
338  GRN_TEXT_PUTS(ctx, buf, "geo_point");
339  break;
340  default :
341  break;
342  }
343  }
344 
345  GRN_TEXT_PUTS(ctx, buf, ">");
346  return GRN_SUCCESS;
347 }
348 
349 static grn_rc
350 grn_column_inspect_common(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
351 {
352  grn_id range_id;
353 
354  grn_inspect_name(ctx, buf, obj);
355 
356  range_id = grn_obj_get_range(ctx, obj);
357  if (range_id) {
358  grn_obj *range = grn_ctx_at(ctx, range_id);
359  GRN_TEXT_PUTS(ctx, buf, " range:");
360  if (range) {
361  grn_inspect_name(ctx, buf, range);
362  grn_obj_unlink(ctx, range);
363  } else {
364  grn_text_lltoa(ctx, buf, range_id);
365  }
366  }
367 
368  return GRN_SUCCESS;
369 }
370 
371 static grn_rc
372 grn_store_inspect_body(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
373 {
374  grn_column_inspect_common(ctx, buf, obj);
375  GRN_TEXT_PUTS(ctx, buf, " type:");
376  switch (obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) {
377  case GRN_OBJ_COLUMN_VECTOR :
378  GRN_TEXT_PUTS(ctx, buf, "vector");
379  break;
380  case GRN_OBJ_COLUMN_SCALAR :
381  GRN_TEXT_PUTS(ctx, buf, "scalar");
382  break;
383  default:
384  break;
385  }
386 
387  GRN_TEXT_PUTS(ctx, buf, " compress:");
388  switch (obj->header.flags & GRN_OBJ_COMPRESS_MASK) {
389  case GRN_OBJ_COMPRESS_NONE :
390  GRN_TEXT_PUTS(ctx, buf, "none");
391  break;
392  case GRN_OBJ_COMPRESS_ZLIB :
393  GRN_TEXT_PUTS(ctx, buf, "zlib");
394  break;
395  case GRN_OBJ_COMPRESS_LZO :
396  GRN_TEXT_PUTS(ctx, buf, "lzo");
397  break;
398  default:
399  break;
400  }
401 
402  if (obj->header.flags & GRN_OBJ_RING_BUFFER) {
403  GRN_TEXT_PUTS(ctx, buf, " ring_buffer:true");
404  }
405 
406  return GRN_SUCCESS;
407 }
408 
409 static grn_rc
410 grn_ra_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
411 {
412  GRN_TEXT_PUTS(ctx, buf, "#<column:fix_size ");
413  grn_store_inspect_body(ctx, buf, obj);
414  GRN_TEXT_PUTS(ctx, buf, ">");
415  return GRN_SUCCESS;
416 }
417 
418 static grn_rc
419 grn_ja_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
420 {
421  GRN_TEXT_PUTS(ctx, buf, "#<column:var_size ");
422  grn_store_inspect_body(ctx, buf, obj);
423  GRN_TEXT_PUTS(ctx, buf, ">");
424  return GRN_SUCCESS;
425 }
426 
427 static grn_rc
428 grn_ii_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
429 {
430  grn_obj sources;
431  int i, n, have_flags = 0;
432  grn_id *source_ids;
433 
434  GRN_TEXT_PUTS(ctx, buf, "#<column:index ");
435  grn_column_inspect_common(ctx, buf, obj);
436 
437  GRN_TEXT_INIT(&sources, 0);
438  grn_obj_get_info(ctx, obj, GRN_INFO_SOURCE, &sources);
439  source_ids = (grn_id *)GRN_BULK_HEAD(&sources);
440  n = GRN_BULK_VSIZE(&sources) / sizeof(grn_id);
441  GRN_TEXT_PUTS(ctx, buf, " sources:[");
442  for (i = 0; i < n; i++) {
443  grn_id source_id;
444  grn_obj *source;
445  if (i) { GRN_TEXT_PUTS(ctx, buf, ", "); }
446  source_id = source_ids[i];
447  source = grn_ctx_at(ctx, source_id);
448  if (source) {
449  grn_inspect_name(ctx, buf, source);
450  } else {
451  grn_text_lltoa(ctx, buf, source_id);
452  }
453  }
454  GRN_TEXT_PUTS(ctx, buf, "]");
455  GRN_OBJ_FIN(ctx, &sources);
456 
457  GRN_TEXT_PUTS(ctx, buf, " flags:");
458  if (obj->header.flags & GRN_OBJ_WITH_SECTION) {
459  GRN_TEXT_PUTS(ctx, buf, "SECTION");
460  have_flags = 1;
461  }
462  if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) {
463  if (have_flags) { GRN_TEXT_PUTS(ctx, buf, "|"); }
464  GRN_TEXT_PUTS(ctx, buf, "WEIGHT");
465  have_flags = 1;
466  }
467  if (obj->header.flags & GRN_OBJ_WITH_POSITION) {
468  if (have_flags) { GRN_TEXT_PUTS(ctx, buf, "|"); }
469  GRN_TEXT_PUTS(ctx, buf, "POSITION");
470  have_flags = 1;
471  }
472  if (!have_flags) {
473  GRN_TEXT_PUTS(ctx, buf, "NONE");
474  }
475 
476  GRN_TEXT_PUTS(ctx, buf, " elements:");
477  grn_ii_inspect_elements(ctx, (grn_ii *)obj, buf);
478 
479  GRN_TEXT_PUTS(ctx, buf, ">");
480 
481  return GRN_SUCCESS;
482 }
483 
484 static grn_rc
485 grn_table_type_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
486 {
487  switch (obj->header.type) {
488  case GRN_TABLE_HASH_KEY:
489  GRN_TEXT_PUTS(ctx, buf, "hash");
490  break;
491  case GRN_TABLE_PAT_KEY:
492  GRN_TEXT_PUTS(ctx, buf, "pat");
493  break;
494  case GRN_TABLE_NO_KEY:
495  GRN_TEXT_PUTS(ctx, buf, "no_key");
496  break;
497  }
498 
499  return GRN_SUCCESS;
500 }
501 
502 static grn_rc
503 grn_table_key_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
504 {
505  grn_obj *domain;
506  grn_id domain_id;
507 
508  GRN_TEXT_PUTS(ctx, buf, "key:");
509  domain_id = obj->header.domain;
510  domain = grn_ctx_at(ctx, domain_id);
511  if (domain) {
512  grn_inspect_name(ctx, buf, domain);
513  grn_obj_unlink(ctx, domain);
514  } else if (domain_id) {
515  grn_text_lltoa(ctx, buf, domain_id);
516  } else {
517  GRN_TEXT_PUTS(ctx, buf, "(nil)");
518  }
519 
520  return GRN_SUCCESS;
521 }
522 
523 static grn_rc
524 grn_table_columns_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
525 {
526  grn_hash *cols;
527 
528  GRN_TEXT_PUTS(ctx, buf, "columns:[");
529  if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
531  if (grn_table_columns(ctx, obj, "", 0, (grn_obj *)cols)) {
532  int i = 0;
533  grn_id *key;
534  GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, {
535  grn_obj *col = grn_ctx_at(ctx, *key);
536  if (col) {
537  if (i++ > 0) { GRN_TEXT_PUTS(ctx, buf, ", "); }
538  grn_column_name_(ctx, col, buf);
539  grn_obj_unlink(ctx, col);
540  }
541  });
542  }
543  grn_hash_close(ctx, cols);
544  }
545  GRN_TEXT_PUTS(ctx, buf, "]");
546 
547  return GRN_SUCCESS;
548 }
549 
550 static grn_rc
551 grn_table_ids_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
552 {
553  grn_table_cursor *tc;
554 
555  GRN_TEXT_PUTS(ctx, buf, "ids:[");
556  tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0,
557  0, -1, GRN_CURSOR_ASCENDING);
558  if (tc) {
559  int i = 0;
560  grn_id id;
561  while ((id = grn_table_cursor_next(ctx, tc))) {
562  if (i++ > 0) { GRN_TEXT_PUTS(ctx, buf, ", "); }
563  grn_text_lltoa(ctx, buf, id);
564  }
565  grn_table_cursor_close(ctx, tc);
566  }
567  GRN_TEXT_PUTS(ctx, buf, "]");
568 
569  return GRN_SUCCESS;
570 }
571 
572 static grn_rc
573 grn_table_default_tokenizer_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
574 {
575  grn_obj *default_tokenizer;
576 
577  GRN_TEXT_PUTS(ctx, buf, "default_tokenizer:");
578  default_tokenizer = grn_obj_get_info(ctx, obj,
580  if (default_tokenizer) {
581  grn_inspect_name(ctx, buf, default_tokenizer);
582  grn_obj_unlink(ctx, default_tokenizer);
583  } else {
584  GRN_TEXT_PUTS(ctx, buf, "(nil)");
585  }
586 
587  return GRN_SUCCESS;
588 }
589 
590 static grn_rc
591 grn_table_normalizer_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
592 {
593  grn_obj *normalizer;
594 
595  GRN_TEXT_PUTS(ctx, buf, "normalizer:");
596  normalizer = grn_obj_get_info(ctx, obj, GRN_INFO_NORMALIZER, NULL);
597  if (normalizer) {
598  grn_inspect_name(ctx, buf, normalizer);
599  grn_obj_unlink(ctx, normalizer);
600  } else {
601  GRN_TEXT_PUTS(ctx, buf, "(nil)");
602  }
603 
604  return GRN_SUCCESS;
605 }
606 
607 static grn_rc
608 grn_table_keys_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
609 {
610  grn_table_cursor *tc;
611 
612  GRN_TEXT_PUTS(ctx, buf, "keys:[");
613  tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0,
614  0, -1, GRN_CURSOR_ASCENDING);
615  if (tc) {
616  int i = 0;
617  grn_id id;
618  grn_obj key;
619  GRN_OBJ_INIT(&key, GRN_BULK, 0, obj->header.domain);
620  while ((id = grn_table_cursor_next(ctx, tc))) {
621  if (i++ > 0) { GRN_TEXT_PUTS(ctx, buf, ", "); }
622  grn_table_get_key2(ctx, obj, id, &key);
623  grn_inspect(ctx, buf, &key);
624  GRN_BULK_REWIND(&key);
625  }
626  GRN_OBJ_FIN(ctx, &key);
627  grn_table_cursor_close(ctx, tc);
628  }
629  GRN_TEXT_PUTS(ctx, buf, "]");
630 
631  return GRN_SUCCESS;
632 }
633 
634 static grn_rc
635 grn_table_subrec_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
636 {
637  GRN_TEXT_PUTS(ctx, buf, "subrec:");
638  if (obj->header.flags & GRN_OBJ_WITH_SUBREC) {
639  switch (obj->header.flags & GRN_OBJ_UNIT_MASK) {
641  GRN_TEXT_PUTS(ctx, buf, "document:none");
642  break;
644  GRN_TEXT_PUTS(ctx, buf, "document:section");
645  break;
647  GRN_TEXT_PUTS(ctx, buf, "document:position");
648  break;
650  GRN_TEXT_PUTS(ctx, buf, "section:none");
651  break;
653  GRN_TEXT_PUTS(ctx, buf, "section:popsition");
654  break;
656  GRN_TEXT_PUTS(ctx, buf, "section:none");
657  break;
659  GRN_TEXT_PUTS(ctx, buf, "userdef:document");
660  break;
662  GRN_TEXT_PUTS(ctx, buf, "userdef:section");
663  break;
665  GRN_TEXT_PUTS(ctx, buf, "userdef:position");
666  break;
667  }
668  } else {
669  GRN_TEXT_PUTS(ctx, buf, "none");
670  }
671 
672  return GRN_SUCCESS;
673 }
674 
675 static grn_rc
676 grn_table_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
677 {
678  grn_id range_id;
679  grn_obj *range;
680 
681  GRN_TEXT_PUTS(ctx, buf, "#<table:");
682  grn_table_type_inspect(ctx, buf, obj);
683  GRN_TEXT_PUTS(ctx, buf, " ");
684 
685  grn_inspect_name(ctx, buf, obj);
686 
687  if (obj->header.type != GRN_TABLE_NO_KEY) {
688  GRN_TEXT_PUTS(ctx, buf, " ");
689  grn_table_key_inspect(ctx, buf, obj);
690  }
691 
692  GRN_TEXT_PUTS(ctx, buf, " value:");
693  range_id = grn_obj_get_range(ctx, obj);
694  range = grn_ctx_at(ctx, range_id);
695  if (range) {
696  grn_inspect_name(ctx, buf, range);
697  } else if (range_id) {
698  grn_text_lltoa(ctx, buf, range_id);
699  } else {
700  GRN_TEXT_PUTS(ctx, buf, "(nil)");
701  }
702 
703  GRN_TEXT_PUTS(ctx, buf, " size:");
704  grn_text_lltoa(ctx, buf, grn_table_size(ctx, obj));
705 
706  GRN_TEXT_PUTS(ctx, buf, " ");
707  grn_table_columns_inspect(ctx, buf, obj);
708 
709  if (obj->header.type == GRN_TABLE_NO_KEY) {
710  GRN_TEXT_PUTS(ctx, buf, " ");
711  grn_table_ids_inspect(ctx, buf, obj);
712  } else {
713  GRN_TEXT_PUTS(ctx, buf, " ");
714  grn_table_default_tokenizer_inspect(ctx, buf, obj);
715 
716  GRN_TEXT_PUTS(ctx, buf, " ");
717  grn_table_normalizer_inspect(ctx, buf, obj);
718 
719  GRN_TEXT_PUTS(ctx, buf, " ");
720  grn_table_keys_inspect(ctx, buf, obj);
721  }
722 
723  GRN_TEXT_PUTS(ctx, buf, " ");
724  grn_table_subrec_inspect(ctx, buf, obj);
725 
726  if (obj->header.type == GRN_TABLE_PAT_KEY) {
727  GRN_TEXT_PUTS(ctx, buf, " nodes:");
728  grn_pat_inspect_nodes(ctx, (grn_pat *)obj, buf);
729  }
730 
731  GRN_TEXT_PUTS(ctx, buf, ">");
732 
733  return GRN_SUCCESS;
734 }
735 
736 static grn_rc
737 grn_geo_point_inspect_point(grn_ctx *ctx, grn_obj *buf, int point)
738 {
739  GRN_TEXT_PUTS(ctx, buf, "(");
740  grn_text_itoa(ctx, buf, point / 1000 / 3600 % 3600);
741  GRN_TEXT_PUTS(ctx, buf, ", ");
742  grn_text_itoa(ctx, buf, point / 1000 / 60 % 60);
743  GRN_TEXT_PUTS(ctx, buf, ", ");
744  grn_text_itoa(ctx, buf, point / 1000 % 60);
745  GRN_TEXT_PUTS(ctx, buf, ", ");
746  grn_text_itoa(ctx, buf, point % 1000);
747  GRN_TEXT_PUTS(ctx, buf, ")");
748 
749  return GRN_SUCCESS;
750 }
751 
752 static grn_rc
753 grn_geo_point_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
754 {
755  int latitude, longitude;
756 
757  GRN_GEO_POINT_VALUE(obj, latitude, longitude);
758 
759  GRN_TEXT_PUTS(ctx, buf, "[");
760  GRN_TEXT_PUTS(ctx, buf, "(");
761  grn_text_itoa(ctx, buf, latitude);
762  GRN_TEXT_PUTS(ctx, buf, ",");
763  grn_text_itoa(ctx, buf, longitude);
764  GRN_TEXT_PUTS(ctx, buf, ")");
765 
766  GRN_TEXT_PUTS(ctx, buf, " (");
767  grn_geo_point_inspect_point(ctx, buf, latitude);
768  GRN_TEXT_PUTS(ctx, buf, ",");
769  grn_geo_point_inspect_point(ctx, buf, longitude);
770  GRN_TEXT_PUTS(ctx, buf, ")");
771 
772  {
773  int i, j;
774  grn_geo_point point;
775  uint8_t encoded[sizeof(grn_geo_point)];
776 
777  GRN_TEXT_PUTS(ctx, buf, " [");
778  point.latitude = latitude;
779  point.longitude = longitude;
780  grn_gton(encoded, &point, sizeof(grn_geo_point));
781  for (i = 0; i < sizeof(grn_geo_point); i++) {
782  if (i != 0) {
783  GRN_TEXT_PUTS(ctx, buf, " ");
784  }
785  for (j = 0; j < 8; j++) {
786  grn_text_itoa(ctx, buf, (encoded[i] >> (7 - j)) & 1);
787  }
788  }
789  GRN_TEXT_PUTS(ctx, buf, "]");
790  }
791 
792  GRN_TEXT_PUTS(ctx, buf, "]");
793 
794  return GRN_SUCCESS;
795 }
796 
797 static grn_rc
798 grn_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
799 {
800  grn_id id;
801  grn_obj *table;
802  grn_hash *cols;
803 
804  table = grn_ctx_at(ctx, obj->header.domain);
805  GRN_TEXT_PUTS(ctx, buf, "#<record:");
806  grn_table_type_inspect(ctx, buf, table);
807  GRN_TEXT_PUTS(ctx, buf, ":");
808  grn_inspect_name(ctx, buf, table);
809 
810  GRN_TEXT_PUTS(ctx, buf, " id:");
811  id = GRN_RECORD_VALUE(obj);
812  grn_text_lltoa(ctx, buf, id);
813 
814  if (grn_table_at(ctx, table, id)) {
815  if (table->header.type != GRN_TABLE_NO_KEY) {
816  grn_obj key;
817  GRN_TEXT_PUTS(ctx, buf, " key:");
818  GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);
819  grn_table_get_key2(ctx, table, id, &key);
820  grn_inspect(ctx, buf, &key);
821  GRN_OBJ_FIN(ctx, &key);
822  }
823  if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
825  if (grn_table_columns(ctx, table, "", 0, (grn_obj *)cols)) {
826  grn_id *key;
827  GRN_HASH_EACH(ctx, cols, column_id, &key, NULL, NULL, {
828  grn_obj *col = grn_ctx_at(ctx, *key);
829  if (col) {
830  grn_obj value;
831  GRN_TEXT_INIT(&value, 0);
832  GRN_TEXT_PUTS(ctx, buf, " ");
833  grn_column_name_(ctx, col, buf);
834  GRN_TEXT_PUTS(ctx, buf, ":");
835  grn_obj_get_value(ctx, col, id, &value);
836  grn_inspect(ctx, buf, &value);
837  GRN_OBJ_FIN(ctx, &value);
838  grn_obj_unlink(ctx, col);
839  }
840  });
841  }
842  grn_hash_close(ctx, cols);
843  }
844  } else {
845  GRN_TEXT_PUTS(ctx, buf, "(nonexistent)");
846  }
847  GRN_TEXT_PUTS(ctx, buf, ">");
848 
849  grn_obj_unlink(ctx, table);
850 
851  return GRN_SUCCESS;
852 }
853 
854 static grn_rc
855 grn_uvector_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
856 {
857  int i = 0;
858  grn_id *v, *ve;
859  grn_obj record;
860 
861  v = (grn_id *)GRN_BULK_HEAD(obj);
862  ve = (grn_id *)GRN_BULK_CURR(obj);
863  GRN_RECORD_INIT(&record, 0, obj->header.domain);
864  GRN_TEXT_PUTS(ctx, buf, "[");
865  while (v < ve) {
866  if (i++ > 0) { GRN_TEXT_PUTS(ctx, buf, ", "); }
867  GRN_RECORD_SET(ctx, &record, *v);
868  grn_inspect(ctx, buf, &record);
869  v++;
870  }
871  GRN_TEXT_PUTS(ctx, buf, "]");
872  GRN_OBJ_FIN(ctx, &record);
873 
874  return GRN_SUCCESS;
875 }
876 
877 grn_obj *
878 grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj)
879 {
880  grn_obj *domain;
881 
882  if (!buffer) {
883  buffer = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_TEXT);
884  }
885 
886  if (!obj) {
887  GRN_TEXT_PUTS(ctx, buffer, "(NULL)");
888  return buffer;
889  }
890 
891  switch (obj->header.type) {
892  case GRN_VOID :
893  /* TODO */
894  break;
895  case GRN_BULK :
896  switch (obj->header.domain) {
899  grn_geo_point_inspect(ctx, buffer, obj);
900  return buffer;
901  default :
902  domain = grn_ctx_at(ctx, obj->header.domain);
903  if (domain) {
904  grn_id type = domain->header.type;
905  grn_obj_unlink(ctx, domain);
906  switch (type) {
907  case GRN_TABLE_HASH_KEY :
908  case GRN_TABLE_PAT_KEY :
909  case GRN_TABLE_NO_KEY :
910  grn_record_inspect(ctx, buffer, obj);
911  return buffer;
912  default :
913  break;
914  }
915  }
916  }
917  break;
918  case GRN_PTR :
919  /* TODO */
920  break;
921  case GRN_UVECTOR :
922  domain = grn_ctx_at(ctx, obj->header.domain);
923  if (domain) {
924  grn_id type = domain->header.type;
925  grn_obj_unlink(ctx, domain);
926  switch (type) {
927  case GRN_TABLE_HASH_KEY :
928  case GRN_TABLE_PAT_KEY :
929  case GRN_TABLE_NO_KEY :
930  grn_uvector_record_inspect(ctx, buffer, obj);
931  return buffer;
932  default :
933  break;
934  }
935  }
936  break;
937  case GRN_PVECTOR :
938  /* TODO */
939  break;
940  case GRN_VECTOR :
941  grn_vector_inspect(ctx, buffer, obj);
942  return buffer;
943  case GRN_MSG :
944  /* TODO */
945  break;
946  case GRN_ACCESSOR :
947  grn_accessor_inspect(ctx, buffer, obj);
948  return buffer;
949  case GRN_SNIP :
950  case GRN_PATSNIP :
951  /* TODO */
952  break;
953  case GRN_STRING :
954  grn_string_inspect(ctx, buffer, obj);
955  break;
957  /* TODO */
958  break;
960  grn_pat_cursor_inspect(ctx, (grn_pat_cursor *)obj, buffer);
961  return buffer;
966  /* TODO */
967  break;
968  case GRN_TYPE :
969  grn_type_inspect(ctx, buffer, obj);
970  return buffer;
971  case GRN_PROC :
972  grn_proc_inspect(ctx, buffer, obj);
973  return buffer;
974  case GRN_EXPR :
975  grn_expr_inspect(ctx, buffer, obj);
976  return buffer;
977  case GRN_TABLE_HASH_KEY :
978  case GRN_TABLE_PAT_KEY :
979  case GRN_TABLE_DAT_KEY :
980  case GRN_TABLE_NO_KEY :
981  grn_table_inspect(ctx, buffer, obj);
982  return buffer;
983  case GRN_DB :
984  /* TODO */
985  break;
986  case GRN_COLUMN_FIX_SIZE :
987  grn_ra_inspect(ctx, buffer, obj);
988  return buffer;
989  case GRN_COLUMN_VAR_SIZE :
990  grn_ja_inspect(ctx, buffer, obj);
991  return buffer;
992  case GRN_COLUMN_INDEX :
993  grn_ii_inspect(ctx, buffer, obj);
994  return buffer;
995  default :
996  break;
997  }
998 
999  grn_text_otoj(ctx, buffer, obj, NULL);
1000  return buffer;
1001 }
1002 
1003 void
1004 grn_p(grn_ctx *ctx, grn_obj *obj)
1005 {
1006  grn_obj buffer;
1007 
1008  GRN_TEXT_INIT(&buffer, 0);
1009  grn_inspect(ctx, &buffer, obj);
1010  printf("%.*s\n", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
1011  grn_obj_unlink(ctx, &buffer);
1012 }
1013 
1014 void
1016 {
1017  grn_obj obj;
1018 
1019  GRN_WGS84_GEO_POINT_INIT(&obj, 0);
1020  GRN_GEO_POINT_SET(ctx, &obj, point->latitude, point->longitude);
1021  grn_p(ctx, &obj);
1022  grn_obj_unlink(ctx, &obj);
1023 }
1024 
1025 #ifdef WIN32
1026 static char *win32_base_dir = NULL;
1027 const char *
1028 grn_win32_base_dir(void)
1029 {
1030  if (!win32_base_dir) {
1031  HMODULE dll;
1032  const wchar_t *dll_filename = GRN_DLL_FILENAME;
1033  wchar_t absolute_dll_filename[MAX_PATH];
1034  DWORD absolute_dll_filename_size;
1035  dll = GetModuleHandleW(dll_filename);
1036  absolute_dll_filename_size = GetModuleFileNameW(dll,
1037  absolute_dll_filename,
1038  MAX_PATH);
1039  if (absolute_dll_filename_size == 0) {
1040  win32_base_dir = ".";
1041  } else {
1042  DWORD ansi_dll_filename_size;
1043  ansi_dll_filename_size =
1044  WideCharToMultiByte(CP_ACP, 0,
1045  absolute_dll_filename, absolute_dll_filename_size,
1046  NULL, 0, NULL, NULL);
1047  if (ansi_dll_filename_size == 0) {
1048  win32_base_dir = ".";
1049  } else {
1050  char *path;
1051  win32_base_dir = malloc(ansi_dll_filename_size + 1);
1052  WideCharToMultiByte(CP_ACP, 0,
1053  absolute_dll_filename, absolute_dll_filename_size,
1054  win32_base_dir, ansi_dll_filename_size,
1055  NULL, NULL);
1056  win32_base_dir[ansi_dll_filename_size] = '\0';
1057  if ((path = strrchr(win32_base_dir, '\\'))) {
1058  *path = '\0';
1059  }
1060  path = strrchr(win32_base_dir, '\\');
1061  if (path && (strcasecmp(path + 1, "bin") == 0 ||
1062  strcasecmp(path + 1, "lib") == 0)) {
1063  *path = '\0';
1064  } else {
1065  path = win32_base_dir + strlen(win32_base_dir);
1066  *path = '\0';
1067  }
1068  for (path = win32_base_dir; *path; path++) {
1069  if (*path == '\\') {
1070  *path = '/';
1071  }
1072  }
1073  }
1074  }
1075  }
1076  return win32_base_dir;
1077 }
1078 #endif