Rizin
unix-like reverse engineering framework and cli tools
table.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2019-2021 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_util/rz_table.h>
5 #include "rz_cons.h"
6 
7 // cant do that without globals because RzList doesnt have void *user :(
8 static int Gnth = 0;
10 
11 static int sortString(const void *a, const void *b) {
12  return strcmp(a, b);
13 }
14 
15 static int sortNumber(const void *a, const void *b) {
16  return rz_num_get(NULL, a) - rz_num_get(NULL, b);
17 }
18 
19 // maybe just index by name instead of exposing those symbols as global
23 
25  if (!strcmp(name, "bool")) {
26  return &rz_table_type_bool;
27  }
28  if (!strcmp(name, "boolean")) {
29  return &rz_table_type_bool;
30  }
31  if (!strcmp(name, "string")) {
32  return &rz_table_type_string;
33  }
34  if (!strcmp(name, "number")) {
35  return &rz_table_type_number;
36  }
37  return NULL;
38 }
39 
40 static void __table_adjust(RzTable *t) {
41  RzTableColumn *col;
42  RzTableRow *row;
43  rz_vector_foreach(t->cols, col) {
44  int itemLength = rz_str_len_utf8_ansi(col->name) + 1;
45  col->width = itemLength;
46  }
47  rz_vector_foreach(t->rows, row) {
48  void **pitem;
49  char *item;
50  int ncol = 0;
51  rz_pvector_foreach (row->items, pitem) {
52  item = *pitem;
53  int itemLength = rz_str_len_utf8_ansi(item) + 1;
55  if (c) {
56  c->width = RZ_MAX(c->width, itemLength);
57  }
58  ncol++;
59  }
60  }
61 }
62 
69  rz_return_if_fail(_row);
70  RzTableRow *row = _row;
71  rz_pvector_free(row->items);
72 }
73 
74 static void rz_table_row_fini_wrapper(RZ_NONNULL void *_row, void *user) {
75  rz_table_row_fini(_row);
76 }
77 
84  rz_return_if_fail(_col);
85  RzTableColumn *col = _col;
86  free(col->name);
87 }
88 
89 static void rz_table_column_fini_wrapper(RZ_NONNULL void *_col, void *user) {
91 }
92 
95  if (!c) {
96  return NULL;
97  }
98  memcpy(c, col, sizeof(*c));
99  c->name = strdup(c->name);
100  return c;
101 }
102 
104  RzTable *t = RZ_NEW0(RzTable);
105  if (t) {
106  t->showHeader = true;
109  t->showSum = false;
110  }
111  return t;
112 }
113 
115  if (!t) {
116  return;
117  }
118  rz_vector_free(t->cols);
119  rz_vector_free(t->rows);
120  free(t);
121 }
122 
123 static bool column_exists(RzTable *t, const char *name) {
124  RzTableColumn *c;
125 
126  rz_vector_foreach(t->cols, c) {
127  if (!strcmp(c->name, name)) {
128  return true;
129  }
130  }
131  return false;
132 }
133 
134 RZ_API void rz_table_add_column(RzTable *t, RzTableColumnType *type, const char *name, int maxWidth) {
135  if (column_exists(t, name)) {
136  return;
137  }
138 
140  if (c) {
141  c->name = strdup(name);
142  c->maxWidth = maxWidth;
143  c->type = type;
144  int itemLength = rz_str_len_utf8_ansi(name) + 1;
145  c->width = itemLength;
146  c->total = -1;
147  rz_vector_push(t->cols, c);
148  }
149  RZ_FREE(c);
150 }
151 
153  RzTableRow *row = RZ_NEW(RzTableRow);
154  row->items = items;
155  return row;
156 }
157 
158 static bool __addRow(RzTable *t, RzPVector *items, const char *arg, int col) {
159  int itemLength = rz_str_len_utf8_ansi(arg) + 1;
161  if (c) {
162  char *str = strdup(arg);
163  c->width = RZ_MAX(c->width, itemLength);
164  rz_pvector_push(items, str);
165  return true;
166  }
167  return false;
168 }
169 
177  rz_return_if_fail(t && items);
178  RzTableRow *row = rz_table_row_new(items);
179  rz_vector_push(t->rows, row);
180  RZ_FREE(row);
181  // throw warning if not enough columns defined in header
182  t->totalCols = RZ_MAX(t->totalCols, rz_pvector_len(items));
183 }
184 
193 RZ_API void rz_table_set_vcolumnsf(RzTable *t, const char *fmt, va_list ap) {
195  RzTableColumnType *typeNumber = rz_table_type("number");
196  RzTableColumnType *typeBool = rz_table_type("bool");
197  const char *name;
198  const char *f = fmt;
199  for (; *f; f++) {
200  name = va_arg(ap, const char *);
201  if (!name) {
202  break;
203  }
204  switch (*f) {
205  case 'b':
206  rz_table_add_column(t, typeBool, name, 0);
207  break;
208  case 's':
209  case 'z':
211  break;
212  case 'i':
213  case 'd':
214  case 'n':
215  case 'x':
216  case 'X':
217  rz_table_add_column(t, typeNumber, name, 0);
218  break;
219  default:
220  eprintf("Invalid format string char '%c', use 's' or 'n'\n", *f);
221  break;
222  }
223  }
224 }
225 
234 RZ_API void rz_table_set_columnsf(RzTable *t, const char *fmt, ...) {
235  va_list ap;
236  va_start(ap, fmt);
237  rz_table_set_vcolumnsf(t, fmt, ap);
238  va_end(ap);
239 }
240 
241 #define add_column_to_rowf(row, fmt, ap) \
242  do { \
243  const char *arg = NULL; \
244  switch (fmt) { \
245  case 's': \
246  case 'z': \
247  arg = va_arg(ap, const char *); \
248  rz_pvector_push(row, strdup(arg ? arg : "")); \
249  break; \
250  case 'b': \
251  rz_pvector_push(row, rz_str_new(rz_str_bool(va_arg(ap, int)))); \
252  break; \
253  case 'i': \
254  case 'd': \
255  rz_pvector_push(row, rz_str_newf("%d", va_arg(ap, int))); \
256  break; \
257  case 'n': \
258  rz_pvector_push(row, rz_str_newf("%" PFMT64d, va_arg(ap, ut64))); \
259  break; \
260  case 'u': \
261  rz_pvector_push(row, rz_num_units(NULL, 32, va_arg(ap, ut64))); \
262  break; \
263  case 'x': \
264  case 'X': { \
265  ut64 n = va_arg(ap, ut64); \
266  if (n == UT64_MAX) { \
267  if (fmt == 'X') { \
268  rz_pvector_push(row, strdup("----------")); \
269  } else { \
270  rz_pvector_push(row, strdup("-1")); \
271  } \
272  } else { \
273  if (fmt == 'X') { \
274  rz_pvector_push(row, rz_str_newf("0x%08" PFMT64x, n)); \
275  } else { \
276  rz_pvector_push(row, rz_str_newf("0x%" PFMT64x, n)); \
277  } \
278  } \
279  } break; \
280  default: \
281  eprintf("Invalid format string char '%c', use 's' or 'n'\n", fmt); \
282  break; \
283  } \
284  } while (0)
285 
289 RZ_API void rz_table_add_row_columnsf(RzTable *t, const char *fmt, ...) {
290  rz_return_if_fail(t && fmt);
291 
292  va_list ap;
293  va_start(ap, fmt);
294  RzTableRow *row = rz_vector_tail(t->rows);
295  RzPVector *vec;
296  bool add_row;
297  if (row) {
298  vec = row->items;
299  add_row = false;
300  } else {
301  vec = rz_pvector_new(free);
302  add_row = true;
303  }
304  for (const char *f = fmt; *f; f++) {
305  add_column_to_rowf(vec, *f, ap);
306  }
307  va_end(ap);
308  if (add_row) {
309  rz_table_add_row_vec(t, vec);
310  }
311 }
312 
316 RZ_API void rz_table_add_rowf(RzTable *t, const char *fmt, ...) {
317  rz_return_if_fail(t && fmt);
318 
319  va_list ap;
320  va_start(ap, fmt);
321  RzPVector *vec = rz_pvector_new(free);
322  for (const char *f = fmt; *f; f++) {
323  add_column_to_rowf(vec, *f, ap);
324  }
325  va_end(ap);
326  rz_table_add_row_vec(t, vec);
327 }
328 
329 RZ_API void rz_table_add_row(RZ_NONNULL RzTable *t, const char *name, ...) {
331  va_list ap;
332  va_start(ap, name);
333  int col = 0;
334  RzPVector *items = rz_pvector_new(free);
335  __addRow(t, items, name, col++);
336  for (;;) {
337  const char *arg = va_arg(ap, const char *);
338  if (!arg) {
339  break;
340  }
341  __addRow(t, items, arg, col);
342  // TODO: assert if number of columns doesnt match t->cols
343  col++;
344  }
345  va_end(ap);
346  RzTableRow *row = rz_table_row_new(items);
347  rz_vector_push(t->rows, row);
348  RZ_FREE(row);
349  // throw warning if not enough columns defined in header
350  t->totalCols = RZ_MAX(t->totalCols, rz_pvector_len(items));
351 }
352 
353 // import / export
354 
356  RzCons *cons = (RzCons *)t->cons;
357  const char *v_line = (cons && (cons->use_utf8 || cons->use_utf8_curvy)) ? RUNE_LINE_VERT : "|";
358  int ll = rz_strbuf_length(sb);
359  switch (col->align) {
360  case RZ_TABLE_ALIGN_LEFT:
361  rz_strbuf_appendf(sb, "%s %-*s ", v_line, col->width, str);
362  break;
364  rz_strbuf_appendf(sb, "%s %*s ", v_line, col->width, str);
365  break;
366  case RZ_TABLE_ALIGN_CENTER: {
367  int len = rz_str_len_utf8(str);
368  int pad = (col->width - len) / 2;
369  int left = col->width - (pad * 2 + len);
370  rz_strbuf_appendf(sb, "%s %-*s ", v_line, pad, " ");
371  rz_strbuf_appendf(sb, "%-*s ", pad + left, str);
372  break;
373  }
374  }
375  return rz_strbuf_length(sb) - ll;
376 }
377 
378 static void __computeTotal(RzTable *t) {
379  RzTableRow *row;
380  rz_vector_foreach(t->rows, row) {
381  void **pitem;
382  char *item;
383  int c = 0;
384  rz_pvector_foreach (row->items, pitem) {
385  item = *pitem;
387  if (!rz_str_cmp(col->type->name, "number", rz_str_ansi_len("number")) && rz_str_isnumber(item)) {
388  if (col->total < 0) {
389  col->total = 0;
390  }
391  col->total += sdb_atoi(item);
392  }
393  c++;
394  }
395  }
396 }
397 
406  if (rz_vector_len(t->cols) == 0) {
407  return strdup("");
408  }
409  RzStrBuf *sb = rz_strbuf_new("");
410  RzTableRow *row;
411  RzTableColumn *col;
412  RzCons *cons = (RzCons *)t->cons;
413  bool useUtf8 = (cons && cons->use_utf8);
414  bool useUtf8Curvy = (cons && cons->use_utf8_curvy);
415  const char *v_line = useUtf8 || useUtf8Curvy ? RUNE_LINE_VERT : "|";
416  const char *h_line = useUtf8 || useUtf8Curvy ? RUNE_LINE_HORIZ : "-";
417  const char *l_intersect = useUtf8 || useUtf8Curvy ? RUNE_LINE_VERT : ")";
418  const char *rz_intersect = useUtf8 || useUtf8Curvy ? RUNE_LINE_VERT : "(";
419  const char *tl_corner = useUtf8 ? (useUtf8Curvy ? RUNE_CURVE_CORNER_TL : RUNE_CORNER_TL) : ".";
420  const char *tr_corner = useUtf8 ? (useUtf8Curvy ? RUNE_CURVE_CORNER_TR : RUNE_CORNER_TR) : ".";
421  const char *bl_corner = useUtf8 ? (useUtf8Curvy ? RUNE_CURVE_CORNER_BL : RUNE_CORNER_BL) : "`";
422  const char *br_corner = useUtf8 ? (useUtf8Curvy ? RUNE_CURVE_CORNER_BR : RUNE_CORNER_BR) : "'";
423  __table_adjust(t);
424 
425  rz_vector_foreach(t->cols, col) {
427  }
429  int maxlen = len;
430  char *h_line_str = rz_str_repeat(h_line, maxlen);
431  {
432  char *s = rz_str_newf("%s%s%s\n", tl_corner, h_line_str, tr_corner);
434  free(s);
435  }
436 
437  rz_strbuf_appendf(sb, "%s\n%s%s%s\n", v_line, l_intersect, h_line_str, rz_intersect);
438  rz_vector_foreach(t->rows, row) {
439  void **pitem;
440  char *item;
441  int c = 0;
442  rz_pvector_foreach (row->items, pitem) {
443  item = *pitem;
444  RzTableColumn *col = rz_vector_index_ptr(t->cols, c);
445  if (col) {
446  int l = __strbuf_append_col_aligned_fancy(t, sb, col, item);
447  len = RZ_MAX(len, l);
448  }
449  c++;
450  }
451  rz_strbuf_appendf(sb, "%s\n", v_line);
452  }
453 
454  if (t->showSum) {
455  char tmp[64];
456  __computeTotal(t);
457  rz_strbuf_appendf(sb, "%s%s%s\n", l_intersect, h_line_str, rz_intersect);
458  rz_vector_foreach(t->cols, col) {
459  char *num = col->total == -1 ? "" : sdb_itoa(col->total, tmp, 10);
460  int l = __strbuf_append_col_aligned_fancy(t, sb, col, num);
461  len = RZ_MAX(len, l);
462  }
463  rz_strbuf_appendf(sb, "%s\n", v_line);
464  }
465  rz_strbuf_appendf(sb, "%s%s%s\n", bl_corner, h_line_str, br_corner);
466  free(h_line_str);
467  return rz_strbuf_drain(sb);
468 }
469 
470 static int __strbuf_append_col_aligned(RzStrBuf *sb, RzTableColumn *col, const char *str, bool nopad) {
471  int ll = rz_strbuf_length(sb);
472  if (nopad) {
473  rz_strbuf_appendf(sb, "%s", str);
474  } else {
475  char *pad = "";
476  int padlen = 0;
477  int len1 = rz_str_len_utf8(str);
478  int len2 = rz_str_len_utf8_ansi(str);
479  if (len1 > len2) {
480  if (len2 < col->width) {
481  padlen = col->width - len2;
482  }
483  }
484  switch (col->align) {
485  case RZ_TABLE_ALIGN_LEFT:
486  pad = rz_str_repeat(" ", padlen);
487  rz_strbuf_appendf(sb, "%-*s%s", col->width, str, pad);
488  free(pad);
489  break;
491  pad = rz_str_repeat(" ", padlen);
492  rz_strbuf_appendf(sb, "%s%*s ", pad, col->width, str);
493  free(pad);
494  break;
495  case RZ_TABLE_ALIGN_CENTER: {
496  int pad = (col->width - len2) / 2;
497  int left = col->width - (pad * 2 + len2);
498  rz_strbuf_appendf(sb, "%-*s", pad, " ");
499  rz_strbuf_appendf(sb, "%-*s ", pad + left, str);
500  break;
501  }
502  default:
504  break;
505  }
506  }
507  return rz_strbuf_length(sb) - ll;
508 }
509 
511  if (t->showCSV) {
512  return rz_table_tocsv(t);
513  }
514  if (t->showJSON) {
515  char *s = rz_table_tojson(t);
516  char *q = rz_str_newf("%s\n", s);
517  ;
518  free(s);
519  return q;
520  }
521  if (t->showFancy) {
522  return rz_table_tofancystring(t);
523  }
524  return rz_table_tosimplestring(t);
525 }
526 
528  RzStrBuf *sb = rz_strbuf_new("");
529  RzTableRow *row;
530  RzTableColumn *col;
531  RzCons *cons = (RzCons *)t->cons;
532  const char *h_line = (cons && (cons->use_utf8 || cons->use_utf8_curvy)) ? RUNE_LONG_LINE_HORIZ : "-";
533  __table_adjust(t);
534  int maxlen = 0;
535  if (t->showHeader) {
536  rz_vector_foreach(t->cols, col) {
537  int ll = __strbuf_append_col_aligned(sb, col, col->name, false);
538  maxlen = RZ_MAX(maxlen, ll);
539  }
541  char *l = rz_str_repeat(h_line, RZ_MAX(maxlen, len));
542  if (l) {
543  rz_strbuf_appendf(sb, "\n%s\n", l);
544  free(l);
545  }
546  }
547  rz_vector_foreach(t->rows, row) {
548  void **pitem;
549  char *item;
550  int c = 0;
551  rz_pvector_foreach (row->items, pitem) {
552  item = *pitem;
553  bool nopad = (item == rz_pvector_tail(row->items));
555  if (col) {
556  (void)__strbuf_append_col_aligned(sb, col, item, nopad);
557  }
558  c++;
559  }
560  rz_strbuf_append(sb, "\n");
561  }
562  if (t->showSum) {
563  char tmp[64];
564  __computeTotal(t);
565  if (maxlen > 0) {
566  char *l = rz_str_repeat(h_line, maxlen);
567  if (l) {
568  rz_strbuf_appendf(sb, "\n%s\n", l);
569  free(l);
570  }
571  }
572  rz_vector_foreach(t->cols, col) {
573  bool nopad = (col == rz_vector_tail(t->cols));
574  (void)__strbuf_append_col_aligned(sb, col, sdb_itoa(col->total, tmp, 10), nopad);
575  }
576  }
577  return rz_strbuf_drain(sb);
578 }
579 
581  RzStrBuf *sb = rz_strbuf_new("");
582  RzTableRow *row;
583  RzTableColumn *col;
584  if (t->showHeader) {
585  const char *comma = "";
586  rz_vector_foreach(t->cols, col) {
587  if (strchr(col->name, ',')) {
588  // TODO. escaped string?
589  rz_strbuf_appendf(sb, "%s\"%s\"", comma, col->name);
590  } else {
591  rz_strbuf_appendf(sb, "%s%s", comma, col->name);
592  }
593  comma = ",";
594  }
595  rz_strbuf_append(sb, "\n");
596  }
597  rz_vector_foreach(t->rows, row) {
598  void **pitem;
599  char *item;
600  int c = 0;
601  const char *comma = "";
602  rz_pvector_foreach (row->items, pitem) {
603  item = *pitem;
605  if (col) {
606  if (strchr(col->name, ',')) {
607  rz_strbuf_appendf(sb, "%s\"%s\"", comma, col->name);
608  } else {
609  rz_strbuf_appendf(sb, "%s%s", comma, item);
610  }
611  comma = ",";
612  }
613  c++;
614  }
615  rz_strbuf_append(sb, "\n");
616  }
617  return rz_strbuf_drain(sb);
618 }
619 
628  PJ *pj = pj_new();
629  RzTableRow *row;
630  pj_a(pj);
631  rz_vector_foreach(t->rows, row) {
632  void **pitem;
633  char *item;
634  int c = 0;
635  pj_o(pj);
636  rz_pvector_foreach (row->items, pitem) {
637  item = *pitem;
639  if (col) {
640  if (col->type == &rz_table_type_number) {
641  ut64 n = rz_num_get(NULL, item);
642  if (n) {
643  pj_kn(pj, col->name, n);
644  } else if (*item && *item != '0') {
645  pj_ks(pj, col->name, item);
646  }
647  } else {
648  if (*item) {
649  pj_ks(pj, col->name, item);
650  }
651  }
652  }
653  c++;
654  }
655  pj_end(pj);
656  }
657  pj_end(pj);
658  return pj_drain(pj);
659 }
660 
661 RZ_API void rz_table_filter(RzTable *t, int nth, int op, const char *un) {
662  rz_return_if_fail(t && un);
663  RzTableRow *row;
664  ut64 uv = rz_num_math(NULL, un);
665  ut64 sum = 0;
666  size_t page = 0, page_items = 0;
667  size_t lrow = 0;
668  if (op == 't') {
669  size_t ll = rz_vector_len(t->rows);
670  if (ll > uv) {
671  uv = ll - uv;
672  }
673  }
674  if (op == 'p') {
675  sscanf(un, "%zd/%zd", &page, &page_items);
676  if (page < 1) {
677  page = 1;
678  }
679  lrow = page_items * (page - 1);
680  uv = page_items * (page);
681  }
682  size_t nrow = 0;
683  ut32 i;
684  for (i = 0; i < rz_vector_len(t->rows); i++) {
685  row = rz_vector_index_ptr(t->rows, i);
686  const char *nn = nth < 0 ? NULL : rz_pvector_at(row->items, nth);
687  ut64 nv = rz_num_math(NULL, nn);
688  bool match = true;
689  RzTableRow *del_row = RZ_NEW(RzTableRow);
690  if (!del_row) {
691  RZ_LOG_ERROR("Failed to allocate memory.\n");
692  return;
693  }
694  switch (op) {
695  case 'p':
696  nrow++;
697  if (nrow < lrow) {
698  match = false;
699  }
700  if (nrow > uv) {
701  match = false;
702  }
703  break;
704  case 't':
705  nrow++;
706  if (nrow < uv) {
707  match = false;
708  }
709  break;
710  case 'h':
711  nrow++;
712  if (nrow > uv) {
713  match = false;
714  }
715  break;
716  case '+':
717  // "sum"
718  sum += nv;
719  match = false;
720  break;
721  case '>':
722  match = (nv > uv);
723  break;
724  case ')':
725  // ">="
726  match = (nv >= uv);
727  break;
728  case '<':
729  match = (nv < uv);
730  break;
731  case '(':
732  // "<="
733  match = (nv <= uv);
734  break;
735  case '=':
736  if (nv == 0 && nn != NULL) {
737  match = !strcmp(nn, un);
738  } else {
739  match = (nv == uv);
740  }
741  break;
742  case '!':
743  if (nv == 0) {
744  match = strcmp(nn, un);
745  } else {
746  match = (nv != uv);
747  }
748  break;
749  case '~':
750  match = strstr(nn, un) != NULL;
751  break;
752  case 's':
753  match = strlen(nn) == atoi(un);
754  break;
755  case 'l':
756  match = strlen(nn) > atoi(un);
757  break;
758  case 'L':
759  match = strlen(nn) < atoi(un);
760  break;
761  case '\0':
762  break;
763  }
764  if (!match) {
765  rz_vector_remove_at(t->rows, i--, del_row);
766  rz_table_row_fini(del_row);
767  }
768  RZ_FREE(del_row);
769  }
770  if (op == '+') {
771  rz_table_add_rowf(t, "u", sum);
772  }
773 }
774 
775 static int cmp(const void *_a, const void *_b) {
776  RzTableRow *a = (RzTableRow *)_a;
777  RzTableRow *b = (RzTableRow *)_b;
778  const char *wa = rz_pvector_at(a->items, Gnth);
779  const char *wb = rz_pvector_at(b->items, Gnth);
780  int res = Gcmp(wa, wb);
781  return res;
782 }
783 
784 RZ_API void rz_table_sort(RzTable *t, int nth, bool dec) {
785  RzTableColumn *col = rz_vector_index_ptr(t->cols, nth);
786  if (col) {
787  Gnth = nth;
788  if (col->type && col->type->cmp) {
789  Gcmp = col->type->cmp;
790  rz_vector_sort(t->rows, cmp, dec);
791  }
792  Gnth = 0;
793  Gcmp = NULL;
794  }
795 }
796 
797 static int cmplen(const void *_a, const void *_b) {
798  RzTableRow *a = (RzTableRow *)_a;
799  RzTableRow *b = (RzTableRow *)_b;
800  const char *wa = rz_pvector_at(a->items, Gnth);
801  const char *wb = rz_pvector_at(b->items, Gnth);
802  int res = strlen(wa) - strlen(wb);
803  return res;
804 }
805 
806 RZ_API void rz_table_sortlen(RzTable *t, int nth, bool dec) {
807  RzTableColumn *col = rz_vector_index_ptr(t->cols, nth);
808  if (col) {
809  Gnth = nth;
810  rz_vector_sort(t->rows, cmplen, dec);
811  Gnth = 0;
812  }
813 }
814 
815 static int rz_rows_cmp(RzPVector *lhs, RzPVector *rhs, RzVector *cols, int nth) {
816  void *item_lhs, *item_rhs;
817  RzTableColumn *item_col;
818  st32 tmp, i;
819 
820  for (i = 0; i < rz_pvector_len(lhs) && i < rz_pvector_len(rhs) && i < rz_vector_len(cols); i++) {
821  item_lhs = rz_pvector_at(lhs, i);
822  item_rhs = rz_pvector_at(rhs, i);
823  item_col = rz_vector_index_ptr(cols, i);
824 
825  if (nth == -1 || i == nth) {
826  tmp = item_col->type->cmp(item_lhs, item_rhs);
827  if (tmp) {
828  return tmp;
829  }
830  }
831  }
832 
833  if (rz_pvector_len(lhs) > rz_pvector_len(rhs)) {
834  return 1;
835  } else if (rz_pvector_len(lhs) < rz_pvector_len(rhs)) {
836  return -1;
837  }
838 
839  return 0;
840 }
841 
843  rz_table_group(t, -1, NULL);
844 }
845 
847  RzTableRow *row, *uniq_row, *del_row = RZ_NEW(RzTableRow);
848  RzVector *rows = t->rows;
849  ut32 i, j;
850 
851  if (!del_row) {
852  RZ_LOG_ERROR("Failed to allocate memory.\n");
853  return;
854  }
855  for (i = 0; i < rz_vector_len(rows); i++) {
856  row = rz_vector_index_ptr(rows, i);
857  for (j = 0; j < i; j++) {
858  uniq_row = rz_vector_index_ptr(rows, j);
859  if (!rz_rows_cmp(uniq_row->items, row->items, t->cols, nth)) {
860  if (fcn) {
861  fcn(uniq_row, row, nth);
862  }
863  rz_vector_remove_at(rows, i--, del_row);
864  // free the deleted row
865  rz_table_row_fini(del_row);
866  break;
867  }
868  }
869  }
870  RZ_FREE(del_row);
871 }
872 
873 RZ_API int rz_table_column_nth(RzTable *t, const char *name) {
874  RzTableColumn *col;
875  ut32 n = 0;
876 
877  rz_vector_foreach(t->cols, col) {
878  if (!strcmp(name, col->name)) {
879  return n;
880  }
881  n++;
882  }
883  return -1;
884 }
885 
886 static int __resolveOperation(const char *op) {
887  if (!strcmp(op, "gt")) {
888  return '>';
889  }
890  if (!strcmp(op, "ge")) {
891  return ')';
892  }
893  if (!strcmp(op, "lt")) {
894  return '<';
895  }
896  if (!strcmp(op, "le")) {
897  return '(';
898  }
899  if (!strcmp(op, "eq")) {
900  return '=';
901  }
902  if (!strcmp(op, "ne")) {
903  return '!';
904  }
905  return -1;
906 }
907 
914 RZ_API void rz_table_columns(RzTable *t, RzList *col_names) {
915  // 1 bool per OLD column to indicate whether it should be freed (masked out)
916  bool *free_cols = malloc(sizeof(bool) * rz_vector_len(t->cols));
917  if (!free_cols) {
918  return;
919  }
920  size_t i;
921  for (i = 0; i < rz_vector_len(t->cols); i++) {
922  free_cols[i] = true;
923  }
924 
925  // 1 value per NEW column to indicate from which OLD column to take the info from and whether to dup it
926  struct col_source {
927  int oldcol;
928  bool dup;
929  } *col_sources = calloc(rz_list_length(col_names), sizeof(struct col_source));
930  if (!col_sources) {
931  free(free_cols);
932  return;
933  }
934 
935  // First create the plan which new columns to take from which old, which ones to dup or free.
936  RzListIter *it;
937  const char *col_name;
938  size_t new_count = 0;
939  rz_list_foreach (col_names, it, col_name) {
940  int fc = rz_table_column_nth(t, col_name);
941  if (fc < 0) {
942  continue;
943  }
944  col_sources[new_count].oldcol = fc;
945  col_sources[new_count].dup = !free_cols[fc]; // if we already used the same old column for another new column before, we must dup it for all following!
946  free_cols[fc] = false;
947  new_count++;
948  }
949 
950  RzTableRow *row;
951  rz_vector_foreach(t->rows, row) {
952  RzPVector *old_items = row->items;
953  RzPVector *new_items = rz_pvector_new(free);
954 
955  for (i = 0; i < new_count; i++) {
956  char *item = *rz_pvector_index_ptr(old_items, col_sources[i].oldcol);
957  if (!item) {
958  continue;
959  }
960  if (col_sources[i].dup) {
961  item = strdup(item);
962  }
963  rz_pvector_push(new_items, item);
964  }
965  row->items = new_items;
966 
967  // Free dropped items
968  void **item;
969  i = 0;
970  rz_pvector_foreach (old_items, item) {
971  if (free_cols[i]) {
972  free(*item);
973  }
974  i++;
975  }
976  // Set old_items->free = NULL to avoid useful items are freed
977  old_items->v.free = NULL;
978  rz_pvector_free(old_items);
979  }
980 
981  RzVector *old_cols = t->cols;
983  for (i = 0; i < new_count; i++) {
984  RzTableColumn *col = rz_vector_index_ptr(old_cols, col_sources[i].oldcol);
985  if (!col) {
986  continue;
987  }
988  if (col_sources[i].dup) {
989  col = rz_table_column_clone(col);
990  rz_vector_push(new_cols, col);
991  RZ_FREE(col);
992  } else {
993  rz_vector_push(new_cols, col);
994  }
995  }
996  t->cols = new_cols;
997 
998  // Free dropped columns
999  RzTableColumn *col;
1000  i = 0;
1001  rz_vector_foreach(old_cols, col) {
1002  if (free_cols[i]) {
1003  rz_table_column_fini(col);
1004  }
1005  i++;
1006  }
1007  // Set old_cols->free = NULL to avoid useful columns are freed
1008  old_cols->free = NULL;
1009  rz_vector_free(old_cols);
1010 
1011  free(col_sources);
1012  free(free_cols);
1013 }
1014 
1016  const char *col;
1017  RzListIter *iter;
1018  RzVector *cols = t->cols;
1020  rz_list_foreach (list, iter, col) {
1021  int ncol = rz_table_column_nth(t, col);
1022  if (ncol != -1) {
1023  RzTableColumn *c = rz_vector_index_ptr(cols, ncol);
1024  if (c) {
1025  rz_table_add_column(t, c->type, col, 0);
1026  }
1027  }
1028  }
1029  rz_vector_free(cols);
1030 }
1031 
1032 static bool set_table_format(RzTable *t, const char *q) {
1033  if (!strcmp(q, "quiet")) {
1034  t->showHeader = false;
1035  t->showFancy = false;
1036  } else if (!strcmp(q, "fancy")) {
1037  t->showFancy = true;
1038  } else if (!strcmp(q, "simple")) {
1039  t->showFancy = false;
1040  } else if (!strcmp(q, "csv")) {
1041  t->showCSV = true;
1042  } else if (!strcmp(q, "json")) {
1043  t->showJSON = true;
1044  } else {
1045  return false;
1046  }
1047  return true;
1048 }
1049 
1050 RZ_API bool rz_table_query(RzTable *t, const char *q) {
1051  rz_return_val_if_fail(t, false);
1052  q = rz_str_trim_head_ro(q);
1053  // TODO support parenthesis and (or)||
1054  // split by "&&" (or comma) -> run .filter on each
1055  // addr/gt/200,addr/lt/400,addr/sort/dec,offset/sort/inc
1056  if (!q || !*q) {
1057  __table_adjust(t);
1058  return true;
1059  }
1060  if (*q == '?') {
1061  eprintf("RzTableQuery> comma separated. 'c' stands for column name.\n");
1062  eprintf(" c/sort/inc sort rows by given colname\n");
1063  eprintf(" c/sortlen/inc sort rows by strlen()\n");
1064  eprintf(" c/cols/c1/c2 only show selected columns\n");
1065  eprintf(" c only show column c\n");
1066  eprintf(" c/gt/0x800 grep rows matching col0 > 0x800\n");
1067  eprintf(" c/ge/0x800 grep rows matching col0 >= 0x800\n");
1068  eprintf(" c/lt/0x800 grep rows matching col0 < 0x800\n");
1069  eprintf(" c/le/0x800 grep rows matching col0 <= 0x800\n");
1070  eprintf(" c/eq/0x800 grep rows matching col0 == 0x800\n");
1071  eprintf(" c/ne/0x800 grep rows matching col0 != 0x800\n");
1072  eprintf(" */uniq get the first row of each that col0 is unique\n");
1073  eprintf(" */head/10 same as | head -n 10\n");
1074  eprintf(" */tail/10 same as | tail -n 10\n");
1075  eprintf(" */page/1/10 show the first 10 rows (/page/2/10 will show the 2nd)\n");
1076  eprintf(" c/str/warn grep rows matching col(name).str(warn)\n");
1077  eprintf(" c/strlen/3 grep rows matching strlen(col) == X\n");
1078  eprintf(" c/minlen/3 grep rows matching strlen(col) > X\n");
1079  eprintf(" c/maxlen/3 grep rows matching strlen(col) < X\n");
1080  eprintf(" c/sum sum all the values of given column\n");
1081  eprintf(" :csv .tostring() == .tocsv()\n");
1082  eprintf(" :json .tostring() == .tojson()\n");
1083  eprintf(" :fancy fancy table output with lines\n");
1084  eprintf(" :simple simple table output without lines\n");
1085  eprintf(" :quiet do not print column names header, implies :simple\n");
1086  return false;
1087  }
1088 
1089  RzListIter *iter;
1090  char *qq = strdup(q);
1091  RzList *queries = rz_str_split_list(qq, ":", 0);
1092  char *query;
1093  rz_list_foreach (queries, iter, query) {
1094  bool is_formatter = set_table_format(t, query);
1095 
1096  RzList *q = rz_str_split_list(query, "/", 2);
1097  if (rz_list_length(q) < 2 && (is_formatter || !*query)) {
1098  rz_list_free(q);
1099  continue;
1100  }
1101 
1102  const char *columnName = rz_list_get_n(q, 0);
1103  if (!columnName) {
1104  eprintf("Column name is NULL for (%s)\n", query);
1105  rz_list_free(q);
1106  continue;
1107  }
1108  const char *operation = rz_list_get_n(q, 1);
1109  const char *operand = rz_list_get_n(q, 2);
1110 
1111  int col = rz_table_column_nth(t, columnName);
1112  if (col == -1) {
1113  if (*columnName == '[') {
1114  col = atoi(columnName + 1);
1115  }
1116  }
1117  if (!operation) {
1118  RzList *list = rz_list_new();
1119  if (list) {
1120  rz_list_append(list, strdup(columnName));
1121  rz_table_columns(t, list);
1122  rz_list_free(list);
1123  }
1124  } else if (!strcmp(operation, "sort")) {
1125  rz_table_sort(t, col, operand && !strcmp(operand, "dec"));
1126  } else if (!strcmp(operation, "uniq")) {
1127  rz_table_group(t, col, NULL);
1128  } else if (!strcmp(operation, "sortlen")) {
1129  rz_table_sortlen(t, col, operand && !strcmp(operand, "dec"));
1130  } else if (!strcmp(operation, "join")) {
1131  // TODO: implement join operation with other command's tables
1132  } else if (!strcmp(operation, "sum")) {
1133  char *op = strdup(operand ? operand : "");
1134  RzList *list = rz_str_split_list(op, "/", 0);
1135  rz_list_prepend(list, strdup(columnName));
1136  rz_table_columns(t, list); // select/reorder columns
1137  rz_list_free(list);
1138  rz_table_filter(t, 0, '+', op);
1139  free(op);
1140  } else if (!strcmp(operation, "strlen")) {
1141  if (operand) {
1142  rz_table_filter(t, col, 's', operand);
1143  }
1144  } else if (!strcmp(operation, "minlen")) {
1145  if (operand) {
1146  rz_table_filter(t, col, 'l', operand);
1147  }
1148  } else if (!strcmp(operation, "maxlen")) {
1149  if (operand) {
1150  rz_table_filter(t, col, 'L', operand);
1151  }
1152  } else if (!strcmp(operation, "page")) {
1153  if (operand) {
1154  rz_table_filter(t, col, 'p', operand);
1155  }
1156  } else if (!strcmp(operation, "tail")) {
1157  if (operand) {
1158  rz_table_filter(t, col, 't', operand);
1159  }
1160  } else if (!strcmp(operation, "head")) {
1161  if (operand) {
1162  rz_table_filter(t, col, 'h', operand);
1163  }
1164  } else if (!strcmp(operation, "str")) {
1165  if (operand) {
1166  rz_table_filter(t, col, '~', operand);
1167  }
1168  } else if (!strcmp(operation, "cols")) {
1169  char *op = strdup(operand ? operand : "");
1170  RzList *list = rz_str_split_list(op, "/", 0);
1171  rz_list_prepend(list, strdup(columnName));
1172  rz_table_columns(t, list); // select/reorder columns
1173  rz_list_free(list);
1174  free(op);
1175  // TODO rz_table_filter_columns (t, q);
1176  } else {
1177  int op = __resolveOperation(operation);
1178  if (op == -1) {
1179  eprintf("Invalid operation (%s)\n", operation);
1180  } else {
1181  rz_table_filter(t, col, op, operand);
1182  }
1183  }
1184  rz_list_free(q);
1185  }
1186  rz_list_free(queries);
1187  free(qq);
1188  __table_adjust(t);
1189  return true;
1190 }
1191 
1192 RZ_API bool rz_table_align(RzTable *t, int nth, int align) {
1193  RzTableColumn *col = rz_vector_index_ptr(t->cols, nth);
1194  if (col) {
1195  col->align = align;
1196  return true;
1197  }
1198  return false;
1199 }
1200 
1202  t->showHeader = false;
1203 }
1204 
1206  ut64 mul, min = -1, max = -1;
1207  RzListIter *iter;
1208  RzListInfo *info;
1209  RzCons *cons = (RzCons *)table->cons;
1210  table->showHeader = false;
1211  const char *h_line = cons->use_utf8 ? RUNE_LONG_LINE_HORIZ : "-";
1212  const char *block = cons->use_utf8 ? UTF_BLOCK : "#";
1213  int j, i;
1214  width -= 80;
1215  if (width < 1) {
1216  width = 30;
1217  }
1218 
1219  rz_table_set_columnsf(table, "sxsxsss", "No.", "start", "blocks", "end", "perms", "extra", "name");
1220  rz_list_foreach (list, iter, info) {
1221  if (min == -1 || info->pitv.addr < min) {
1222  min = info->pitv.addr;
1223  }
1224  if (max == -1 || info->pitv.addr + info->pitv.size > max) {
1225  max = info->pitv.addr + info->pitv.size;
1226  }
1227  }
1228  mul = (max - min) / width;
1229  if (min != -1 && mul > 0) {
1230  i = 0;
1231  rz_list_foreach (list, iter, info) {
1232  RzStrBuf *buf = rz_strbuf_new("");
1233  for (j = 0; j < width; j++) {
1234  ut64 pos = min + j * mul;
1235  ut64 npos = min + (j + 1) * mul;
1236  const char *arg = (info->pitv.addr < npos && (info->pitv.addr + info->pitv.size) > pos)
1237  ? block
1238  : h_line;
1240  }
1241  char *b = rz_strbuf_drain(buf);
1242  char no[64];
1243  if (va) {
1244  rz_table_add_rowf(table, "sxsxsss",
1245  rz_strf(no, "%d%c", i, rz_itv_contain(info->vitv, seek) ? '*' : ' '),
1246  info->vitv.addr,
1247  b,
1248  rz_itv_end(info->vitv),
1249  (info->perm != -1) ? rz_str_rwx_i(info->perm) : "",
1250  (info->extra) ? info->extra : "",
1251  (info->name) ? info->name : "");
1252  } else {
1253  rz_table_add_rowf(table, "sxsxsss",
1254  rz_strf(no, "%d%c", i, rz_itv_contain(info->pitv, seek) ? '*' : ' '),
1255  info->pitv.addr,
1256  b,
1257  rz_itv_end(info->pitv),
1258  (info->perm != -1) ? rz_str_rwx_i(info->perm) : "",
1259  (info->extra) ? info->extra : "",
1260  (info->name) ? info->name : "");
1261  }
1262  free(b);
1263  i++;
1264  }
1265  RzStrBuf *buf = rz_strbuf_new("");
1266  /* current seek */
1267  if (i > 0 && len != 0) {
1268  if (seek == UT64_MAX) {
1269  seek = 0;
1270  }
1271  for (j = 0; j < width; j++) {
1272  rz_strbuf_append(buf, ((j * mul) + min >= seek && (j * mul) + min <= seek + len) ? "^" : h_line);
1273  }
1274  char *s = rz_strbuf_drain(buf);
1275  rz_table_add_rowf(table, "sssssss", "=>", sdb_fmt("0x%08" PFMT64x, seek),
1276  s, sdb_fmt("0x%08" PFMT64x, seek + len), "", "", "");
1277  free(s);
1278  } else {
1280  }
1281  }
1282 }
1283 
1294  RzListIter *iter;
1295  RzList *row_name = rz_list_new();
1296  RzTable *transpose = rz_table_new();
1297  RzTableColumn *col;
1298  RzTableRow *row;
1300  void **pitem;
1301  char *item;
1302  ut32 i;
1303 
1304  // getting table column names to add to row head
1305  rz_table_add_column(transpose, typeString, "Name", 0);
1306 
1307  // adding rows to transpose table rows * (number of columns in the table)
1308  for (i = 0; i < rz_vector_len(t->rows); i++) {
1309  char name[20];
1310  if (rz_vector_len(t->rows) == 1) {
1311  rz_table_add_column(transpose, typeString, "Value", 0);
1312  } else {
1313  rz_table_add_column(transpose, typeString, rz_strf(name, "Value%d", i + 1), 0);
1314  }
1315  }
1316 
1317  // column names to row heads
1318  rz_vector_foreach(t->cols, col) {
1319  rz_list_append(row_name, col->name);
1320  }
1321 
1322  // adding rows with name alone
1323  if (row_name && t->rows) {
1324  iter = row_name->head;
1325  if (iter) {
1326  item = iter->data;
1327  for (i = 0; i < t->totalCols; i++) {
1328  rz_table_add_row(transpose, item, NULL);
1329  if (iter->n) {
1330  iter = iter->n;
1331  item = iter->data;
1332  }
1333  }
1334  }
1335  }
1336 
1337  if (transpose->rows) {
1338  rz_vector_foreach(t->rows, row) {
1339  if (!row) {
1340  RZ_LOG_WARN("Invalid row while doing transpose.\n");
1341  continue;
1342  }
1343  i = 0;
1344  rz_pvector_foreach (row->items, pitem) {
1345  item = *pitem;
1346  RzTableRow *tr_row = rz_vector_index_ptr(transpose->rows, i++);
1347  RzPVector *tr_items = tr_row->items;
1348  rz_pvector_push(tr_items, strdup(item));
1349  }
1350  }
1351  }
1352 
1353  rz_list_free(row_name);
1354  return transpose;
1355 }
1356 
1357 #if 0
1358 // TODO: to be implemented
1359 RZ_API RzTable *rz_table_clone(RzTable *t) {
1360  // TODO: implement
1361  return NULL;
1362 }
1363 
1364 RZ_API RzTable *rz_table_push(RzTable *t) {
1365  // TODO: implement
1366  return NULL;
1367 }
1368 
1369 RZ_API RzTable *rz_table_pop(RzTable *t) {
1370  // TODO: implement
1371  return NULL;
1372 }
1373 
1374 RZ_API void rz_table_fromjson(RzTable *t, const char *csv) {
1375  // TODO
1376 }
1377 
1378 RZ_API void rz_table_fromcsv(RzTable *t, const char *csv) {
1379  // TODO
1380 }
1381 
1382 RZ_API char *rz_table_tohtml(RzTable *t) {
1383  // TODO
1384  return NULL;
1385 }
1386 
1388  // When the music stops rows will be cols and cols... rows!
1389 }
1390 
1391 RZ_API void rz_table_format(RzTable *t, int nth, RzTableColumnType *type) {
1392  // change the format of a specific column
1393  // change imm base, decimal precission, ...
1394 }
1395 
1396 // to compute sum result of all the elements in a column
1397 RZ_API ut64 rz_table_reduce(RzTable *t, int nth) {
1398  // When the music stops rows will be cols and cols... rows!
1399  return 0;
1400 }
1401 #endif
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
operand
Definition: arc-opc.c:39
static RzILOpEffect * mul(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:539
static SblHeader sb
Definition: bin_mbn.c:26
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
static const char * typeString(ut32 n, int *bits)
Definition: bin_symbols.c:62
#define useUtf8Curvy
Definition: canvas_line.c:10
#define useUtf8
Definition: canvas_line.c:9
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
int max
Definition: enough.c:225
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_BORROW RzListIter * rz_list_prepend(RZ_NONNULL RzList *list, void *data)
Appends at the beginning of the list a new element.
Definition: list.c:316
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API RZ_BORROW void * rz_list_get_n(RZ_NONNULL const RzList *list, ut32 n)
Returns the N-th element of the list.
Definition: list.c:574
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode dup
Definition: sflib.h:68
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
const char * name
Definition: op.c:541
static void pad(RzStrBuf *sb, ut32 count)
Definition: protobuf.c:36
#define min(a, b)
Definition: qsort.h:83
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RUNE_CURVE_CORNER_TL
Definition: rz_cons.h:413
#define RUNE_LINE_HORIZ
Definition: rz_cons.h:403
#define RUNE_CORNER_TR
Definition: rz_cons.h:408
#define RUNE_LONG_LINE_HORIZ
Definition: rz_cons.h:417
#define RUNE_CORNER_BL
Definition: rz_cons.h:406
#define UTF_BLOCK
Definition: rz_cons.h:419
#define RUNE_CORNER_TL
Definition: rz_cons.h:407
#define RUNE_CORNER_BR
Definition: rz_cons.h:405
#define RUNE_CURVE_CORNER_BR
Definition: rz_cons.h:415
#define RUNE_CURVE_CORNER_BL
Definition: rz_cons.h:416
#define RUNE_LINE_VERT
Definition: rz_cons.h:401
#define RUNE_CURVE_CORNER_TR
Definition: rz_cons.h:414
static bool rz_itv_contain(RzInterval itv, ut64 addr)
Definition: rz_itv.h:52
static ut64 rz_itv_end(RzInterval itv)
Definition: rz_itv.h:42
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API char * pj_drain(PJ *j)
Definition: pj.c:50
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
Definition: pj.c:121
RZ_API PJ * pj_a(PJ *j)
Definition: pj.c:81
RZ_API const char * rz_str_rwx_i(int rwx)
Definition: str.c:332
RZ_API char * rz_str_repeat(const char *ch, int sz)
Definition: str.c:3249
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API size_t rz_str_ansi_len(const char *str)
Definition: str.c:1945
RZ_API bool rz_str_isnumber(const char *str)
Definition: str.c:3550
RZ_API size_t rz_str_len_utf8(const char *s)
Definition: str.c:2709
RZ_API const char * rz_str_trim_head_ro(const char *str)
Definition: str_trim.c:86
RZ_API size_t rz_str_len_utf8_ansi(const char *str)
Definition: str.c:2723
RZ_API int rz_str_cmp(const char *dst, const char *orig, int len)
Definition: str.c:974
RZ_API RzList * rz_str_split_list(char *str, const char *c, int n)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3429
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API bool rz_strbuf_prepend(RzStrBuf *sb, const char *s)
Definition: strbuf.c:201
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API int rz_strbuf_length(RzStrBuf *sb)
Definition: strbuf.c:28
@ RZ_TABLE_ALIGN_LEFT
Definition: rz_table.h:34
@ RZ_TABLE_ALIGN_RIGHT
Definition: rz_table.h:35
@ RZ_TABLE_ALIGN_CENTER
Definition: rz_table.h:36
void(* RzTableSelector)(RzTableRow *acc, RzTableRow *new_row, int nth)
Definition: rz_table.h:56
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_NEW(x)
Definition: rz_types.h:285
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define RZ_MAX(x, y)
#define UT64_MAX
Definition: rz_types_base.h:86
#define st32
Definition: rz_types_base.h:12
static void * rz_pvector_tail(RzPVector *vec)
Definition: rz_vector.h:269
static void * rz_vector_index_ptr(RzVector *vec, size_t index)
Definition: rz_vector.h:88
static void ** rz_pvector_index_ptr(RzPVector *vec, size_t index)
Definition: rz_vector.h:251
RZ_API void rz_vector_remove_at(RzVector *vec, size_t index, void *into)
Definition: vector.c:127
static void * rz_vector_tail(RzVector *vec)
Definition: rz_vector.h:100
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_vector_free(RzVector *vec)
Definition: vector.c:75
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
RZ_API RzVector * rz_vector_new(size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:42
static size_t rz_vector_len(const RzVector *vec)
Definition: rz_vector.h:82
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236
RZ_API void rz_vector_sort(RzVector *vec, RzVectorComparator cmp, bool reverse)
Sort function for RzVector.
Definition: vector.c:285
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
RZ_API char * sdb_itoa(ut64 n, char *s, int base)
Definition: util.c:38
RZ_API ut64 sdb_atoi(const char *s)
Definition: util.c:88
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
const char * name
Definition: rz_table.h:11
RzListComparator cmp
Definition: rz_table.h:12
RzTableColumnType * type
Definition: rz_table.h:17
char * name
Definition: rz_table.h:16
RzPVector * items
Definition: rz_table.h:40
bool showFancy
Definition: rz_table.h:48
RzVector * cols
Definition: rz_table.h:45
bool showSum
Definition: rz_table.h:51
bool showHeader
Definition: rz_table.h:47
bool showCSV
Definition: rz_table.h:50
bool showJSON
Definition: rz_table.h:49
void * cons
Definition: rz_table.h:53
RzVector * rows
Definition: rz_table.h:44
Definition: engine.c:71
Definition: z80asm.h:102
Definition: rz_pj.h:12
bool use_utf8
Definition: rz_cons.h:559
bool use_utf8_curvy
Definition: rz_cons.h:560
RzListIter * head
Definition: rz_list.h:19
RzVector v
Definition: rz_vector.h:56
RzVectorFree free
Definition: rz_vector.h:50
int pos
Definition: main.c:11
int width
Definition: main.c:10
ut64 maxlen
Definition: core.c:76
RZ_API bool rz_table_align(RzTable *t, int nth, int align)
Definition: table.c:1192
#define add_column_to_rowf(row, fmt, ap)
Definition: table.c:241
RZ_API RzTableRow * rz_table_row_new(RzPVector *items)
Definition: table.c:152
RZ_API void rz_table_add_column(RzTable *t, RzTableColumnType *type, const char *name, int maxWidth)
Definition: table.c:134
RZ_API void rz_table_visual_list(RzTable *table, RzList *list, ut64 seek, ut64 len, int width, bool va)
Definition: table.c:1205
RZ_API void rz_table_column_fini(RZ_NONNULL void *_col)
clear function for RzVector cols in RzTable
Definition: table.c:83
static bool set_table_format(RzTable *t, const char *q)
Definition: table.c:1032
static RzListComparator Gcmp
Definition: table.c:9
static int cmp(const void *_a, const void *_b)
Definition: table.c:775
static bool __addRow(RzTable *t, RzPVector *items, const char *arg, int col)
Definition: table.c:158
RZ_API void rz_table_uniq(RzTable *t)
Definition: table.c:842
RZ_API void rz_table_hide_header(RzTable *t)
Definition: table.c:1201
RZ_API void rz_table_filter_columns(RzTable *t, RzList *list)
Definition: table.c:1015
RZ_API void rz_table_sortlen(RzTable *t, int nth, bool dec)
Definition: table.c:806
static bool column_exists(RzTable *t, const char *name)
Definition: table.c:123
RZ_API void rz_table_add_rowf(RzTable *t, const char *fmt,...)
Definition: table.c:316
RZ_API void rz_table_add_row_vec(RZ_NONNULL RzTable *t, RZ_NONNULL RzPVector *items)
Add a new row to RzTable.
Definition: table.c:176
static int cmplen(const void *_a, const void *_b)
Definition: table.c:797
RZ_API RZ_OWN char * rz_table_tojson(RzTable *t)
Convert RzTable to json format.
Definition: table.c:626
RZ_API void rz_table_free(RzTable *t)
Definition: table.c:114
static void rz_table_row_fini_wrapper(RZ_NONNULL void *_row, void *user)
Definition: table.c:74
RZ_API void rz_table_sort(RzTable *t, int nth, bool dec)
Definition: table.c:784
RZ_API char * rz_table_tocsv(RzTable *t)
Definition: table.c:580
static RzTableColumnType rz_table_type_number
Definition: table.c:21
RZ_API bool rz_table_query(RzTable *t, const char *q)
Definition: table.c:1050
static RzTableColumnType rz_table_type_bool
Definition: table.c:22
RZ_API void rz_table_add_row_columnsf(RzTable *t, const char *fmt,...)
Definition: table.c:289
RZ_API void rz_table_add_row(RZ_NONNULL RzTable *t, const char *name,...)
Definition: table.c:329
RZ_API char * rz_table_tosimplestring(RzTable *t)
Definition: table.c:527
RZ_API void rz_table_set_vcolumnsf(RzTable *t, const char *fmt, va_list ap)
Specify the types and names of the referenced table.
Definition: table.c:193
RZ_API RzTableColumn * rz_table_column_clone(RzTableColumn *col)
Definition: table.c:93
RZ_API void rz_table_group(RzTable *t, int nth, RzTableSelector fcn)
Definition: table.c:846
static int __strbuf_append_col_aligned_fancy(RzTable *t, RzStrBuf *sb, RzTableColumn *col, char *str)
Definition: table.c:355
static int sortString(const void *a, const void *b)
Definition: table.c:11
static int rz_rows_cmp(RzPVector *lhs, RzPVector *rhs, RzVector *cols, int nth)
Definition: table.c:815
RZ_API int rz_table_column_nth(RzTable *t, const char *name)
Definition: table.c:873
static void __computeTotal(RzTable *t)
Definition: table.c:378
static int __strbuf_append_col_aligned(RzStrBuf *sb, RzTableColumn *col, const char *str, bool nopad)
Definition: table.c:470
RZ_API void rz_table_set_columnsf(RzTable *t, const char *fmt,...)
Specify the types and names of the referenced table.
Definition: table.c:234
RZ_API void rz_table_row_fini(RZ_NONNULL void *_row)
clear function for RzVector rows in RzTable
Definition: table.c:68
static int sortNumber(const void *a, const void *b)
Definition: table.c:15
RZ_API char * rz_table_tostring(RzTable *t)
Definition: table.c:510
RZ_API RZ_OWN RzTable * rz_table_transpose(RZ_NONNULL RzTable *t)
Generates the transpose of RzTable.
Definition: table.c:1292
static RzTableColumnType rz_table_type_string
Definition: table.c:20
RZ_API RzTable * rz_table_new(void)
Definition: table.c:103
RZ_API RZ_OWN char * rz_table_tofancystring(RZ_NONNULL RzTable *t)
Convert the content of RzTable to string.
Definition: table.c:404
static void __table_adjust(RzTable *t)
Definition: table.c:40
RZ_API RzTableColumnType * rz_table_type(const char *name)
Definition: table.c:24
static int __resolveOperation(const char *op)
Definition: table.c:886
RZ_API void rz_table_columns(RzTable *t, RzList *col_names)
Select specific columns in RzTable.
Definition: table.c:914
static void rz_table_column_fini_wrapper(RZ_NONNULL void *_col, void *user)
Definition: table.c:89
RZ_API void rz_table_filter(RzTable *t, int nth, int op, const char *un)
Definition: table.c:661
static int Gnth
Definition: table.c:8
Definition: dis.c:32
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int comma
Definition: z80asm.c:76
static int seek(char *argv[])