Revert "Refactor RzTable: change the internal storage to RzVector (#2421)" (#2517)

This reverts commit 1748b38ce1.
This commit is contained in:
Anton Kochkov 2022-04-08 18:06:20 +08:00 committed by GitHub
parent 6f68175068
commit d6d214572f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 276 additions and 360 deletions

View file

@ -7469,13 +7469,13 @@ static void print_stats(RzCore *core, HtPU *ht, RzAnalysisFunction *fcn, RzCmdSt
rz_list_foreach (list, iter, name) {
rz_table_add_column(t, typeNumber, name, 0);
}
RzPVector *items = rz_pvector_new(free);
rz_pvector_push(items, strdup(fcn->name));
RzList *items = rz_list_newf(free);
rz_list_append(items, strdup(fcn->name));
rz_list_foreach (list, iter, name) {
int nv = (int)ht_pu_find(ht, name, NULL);
rz_pvector_push(items, rz_str_newf("%d", nv));
rz_list_append(items, rz_str_newf("%d", nv));
}
rz_table_add_row_vec(t, items);
rz_table_add_row_list(t, items);
} else {
rz_list_foreach (list, iter, name) {
ut32 nv = (ut32)ht_pu_find(ht, name, NULL);
@ -7560,19 +7560,19 @@ RZ_IPI RzCmdStatus rz_analysis_function_all_opcode_stat_handler(RzCore *core, in
RzListIter *iter2;
rz_list_foreach (dbs, iter2, db) {
RzPVector *items = rz_pvector_new(free);
RzList *items = rz_list_newf(free);
if (!items) {
break;
}
ut64 fcnAddr = ht_pu_find(db, ".addr", NULL);
RzAnalysisFunction *fcn = rz_analysis_get_function_at(core->analysis, fcnAddr);
rz_pvector_push(items, fcn ? strdup(fcn->name) : strdup(""));
rz_pvector_push(items, fcn ? rz_str_newf("0x%08" PFMT64x, fcnAddr) : strdup("0"));
rz_list_append(items, fcn ? strdup(fcn->name) : strdup(""));
rz_list_append(items, fcn ? rz_str_newf("0x%08" PFMT64x, fcnAddr) : strdup("0"));
rz_list_foreach (keys, iter, key) {
ut32 n = (ut32)ht_pu_find(db, key, NULL);
rz_pvector_push(items, rz_str_newf("%u", n));
rz_list_append(items, rz_str_newf("%u", n));
}
rz_table_add_row_vec(t, items);
rz_table_add_row_list(t, items);
}
res = RZ_CMD_STATUS_OK;
exit:
@ -7996,17 +7996,17 @@ static void analysis_class_print(RzAnalysis *analysis, const char *class_name, b
RzAnalysisMethod *meth;
int i = 1;
rz_vector_foreach(methods, meth) {
RzPVector *row_vec = rz_pvector_new(free);
rz_pvector_push(row_vec, rz_str_newf("%d", i++));
rz_pvector_push(row_vec, rz_str_new(meth->real_name));
rz_pvector_push(row_vec, rz_str_newf("0x%" PFMT64x, meth->addr));
RzList *row_list = rz_list_newf(free);
rz_list_append(row_list, rz_str_newf("%d", i++));
rz_list_append(row_list, rz_str_new(meth->real_name));
rz_list_append(row_list, rz_str_newf("0x%" PFMT64x, meth->addr));
if (meth->vtable_offset >= 0) {
rz_pvector_push(row_vec, rz_str_newf("0x%" PFMT64x, meth->vtable_offset));
rz_list_append(row_list, rz_str_newf("0x%" PFMT64x, meth->vtable_offset));
} else {
rz_pvector_push(row_vec, rz_str_new("-1"));
rz_list_append(row_list, rz_str_new("-1"));
}
rz_pvector_push(row_vec, rz_str_new(method_type[meth->method_type]));
rz_table_add_row_vec(table, row_vec);
rz_list_append(row_list, rz_str_new(method_type[meth->method_type]));
rz_table_add_row_list(table, row_list);
}
char *s = rz_table_tostring(table);
rz_cons_printf("%s\n", s);

View file

@ -37,12 +37,13 @@ enum {
};
typedef struct {
RzPVector *items;
// TODO: use RzVector
RzList *items;
} RzTableRow;
typedef struct {
RzVector *rows;
RzVector *cols;
RzList *rows;
RzList *cols;
int totalCols;
bool showHeader;
bool showFancy;
@ -55,8 +56,8 @@ typedef struct {
typedef void (*RzTableSelector)(RzTableRow *acc, RzTableRow *new_row, int nth);
RZ_API void rz_table_row_fini(void *_row);
RZ_API void rz_table_column_fini(void *_col);
RZ_API void rz_table_row_free(void *_row);
RZ_API void rz_table_column_free(void *_col);
RZ_API RzTableColumn *rz_table_column_clone(RzTableColumn *col);
RZ_API RzTableColumnType *rz_table_type(const char *name);
RZ_API RzTable *rz_table_new(void);
@ -65,16 +66,16 @@ RZ_API int rz_table_column_nth(RzTable *t, const char *name);
RZ_API void rz_table_add_column(RzTable *t, RzTableColumnType *type, const char *name, int maxWidth);
RZ_API void rz_table_set_columnsf(RzTable *t, const char *fmt, ...);
RZ_API void rz_table_set_vcolumnsf(RzTable *t, const char *fmt, va_list ap);
RZ_API RzTableRow *rz_table_row_new(RzPVector *items);
RZ_API RzTableRow *rz_table_row_new(RzList *items);
RZ_API void rz_table_add_row(RzTable *t, const char *name, ...);
RZ_API void rz_table_add_rowf(RzTable *t, const char *fmt, ...);
RZ_API void rz_table_add_row_columnsf(RzTable *t, const char *fmt, ...);
RZ_API void rz_table_add_row_vec(RzTable *t, RzPVector *items);
RZ_API RZ_OWN char *rz_table_tofancystring(RzTable *t);
RZ_API void rz_table_add_row_list(RzTable *t, RzList *items);
RZ_API char *rz_table_tofancystring(RzTable *t);
RZ_API char *rz_table_tosimplestring(RzTable *t);
RZ_API char *rz_table_tostring(RzTable *t);
RZ_API char *rz_table_tocsv(RzTable *t);
RZ_API RZ_OWN char *rz_table_tojson(RzTable *t);
RZ_API char *rz_table_tojson(RzTable *t);
RZ_API void rz_table_filter(RzTable *t, int nth, int op, const char *un);
RZ_API void rz_table_sort(RzTable *t, int nth, bool inc);
RZ_API void rz_table_uniq(RzTable *t);

View file

@ -38,7 +38,6 @@ extern "C" {
*/
typedef int (*RzPVectorComparator)(const void *a, const void *b);
typedef int (*RzVectorComparator)(const void *a, const void *b);
typedef void (*RzVectorFree)(void *e, void *user);
typedef void (*RzPVectorFree)(void *e);
@ -154,9 +153,6 @@ RZ_API void *rz_vector_shrink(RzVector *vec);
*/
RZ_API void *rz_vector_flush(RzVector *vec);
// sort vector
RZ_API void rz_vector_sort(RzVector *vec, RzVectorComparator cmp, bool reverse);
/*
* example:
*

View file

@ -37,21 +37,21 @@ RZ_API RzTableColumnType *rz_table_type(const char *name) {
return NULL;
}
// TODO: unused for now, maybe good to call after filter :?
static void __table_adjust(RzTable *t) {
RzListIter *iter, *iter2;
RzTableColumn *col;
RzTableRow *row;
rz_vector_foreach(t->cols, col) {
rz_list_foreach (t->cols, iter, col) {
int itemLength = rz_str_len_utf8_ansi(col->name) + 1;
col->width = itemLength;
}
rz_vector_foreach(t->rows, row) {
void **pitem;
char *item;
rz_list_foreach (t->rows, iter, row) {
const char *item;
int ncol = 0;
rz_pvector_foreach (row->items, pitem) {
item = *pitem;
rz_list_foreach (row->items, iter2, item) {
int itemLength = rz_str_len_utf8_ansi(item) + 1;
RzTableColumn *c = rz_vector_index_ptr(t->cols, ncol);
RzTableColumn *c = rz_list_get_n(t->cols, ncol);
if (c) {
c->width = RZ_MAX(c->width, itemLength);
}
@ -60,34 +60,16 @@ static void __table_adjust(RzTable *t) {
}
}
/**
* \brief clear function for RzVector rows in RzTable
*
* \param _row pointer to the elements of rows in RzTable
*/
RZ_API void rz_table_row_fini(RZ_NONNULL void *_row) {
rz_return_if_fail(_row);
RZ_API void rz_table_row_free(void *_row) {
RzTableRow *row = _row;
rz_pvector_free(row->items);
rz_list_free(row->items);
free(row);
}
static void rz_table_row_fini_wrapper(RZ_NONNULL void *_row, void *user) {
rz_table_row_fini(_row);
}
/**
* \brief clear function for RzVector cols in RzTable
*
* \param _col pointer to the elements of cols in RzTable
*/
RZ_API void rz_table_column_fini(RZ_NONNULL void *_col) {
rz_return_if_fail(_col);
RZ_API void rz_table_column_free(void *_col) {
RzTableColumn *col = _col;
free(col->name);
}
static void rz_table_column_fini_wrapper(RZ_NONNULL void *_col, void *user) {
rz_table_column_fini(_col);
free(col);
}
RZ_API RzTableColumn *rz_table_column_clone(RzTableColumn *col) {
@ -104,8 +86,8 @@ RZ_API RzTable *rz_table_new(void) {
RzTable *t = RZ_NEW0(RzTable);
if (t) {
t->showHeader = true;
t->cols = rz_vector_new(sizeof(RzTableColumn), rz_table_column_fini_wrapper, NULL);
t->rows = rz_vector_new(sizeof(RzTableRow), rz_table_row_fini_wrapper, NULL);
t->cols = rz_list_newf(rz_table_column_free);
t->rows = rz_list_newf(rz_table_row_free);
t->showSum = false;
}
return t;
@ -115,15 +97,16 @@ RZ_API void rz_table_free(RzTable *t) {
if (!t) {
return;
}
rz_vector_free(t->cols);
rz_vector_free(t->rows);
rz_list_free(t->cols);
rz_list_free(t->rows);
free(t);
}
static bool column_exists(RzTable *t, const char *name) {
RzListIter *it;
RzTableColumn *c;
rz_vector_foreach(t->cols, c) {
rz_list_foreach (t->cols, it, c) {
if (!strcmp(c->name, name)) {
return true;
}
@ -143,42 +126,33 @@ RZ_API void rz_table_add_column(RzTable *t, RzTableColumnType *type, const char
c->type = type;
int itemLength = rz_str_len_utf8_ansi(name) + 1;
c->width = itemLength;
rz_list_append(t->cols, c);
c->total = -1;
rz_vector_push(t->cols, c);
}
free(c);
}
RZ_API RzTableRow *rz_table_row_new(RzPVector *items) {
RZ_API RzTableRow *rz_table_row_new(RzList *items) {
RzTableRow *row = RZ_NEW(RzTableRow);
row->items = items;
return row;
}
static bool __addRow(RzTable *t, RzPVector *items, const char *arg, int col) {
static bool __addRow(RzTable *t, RzList *items, const char *arg, int col) {
int itemLength = rz_str_len_utf8_ansi(arg) + 1;
RzTableColumn *c = rz_vector_index_ptr(t->cols, col);
RzTableColumn *c = rz_list_get_n(t->cols, col);
if (c) {
char *str = strdup(arg);
c->width = RZ_MAX(c->width, itemLength);
rz_pvector_push(items, str);
rz_list_append(items, strdup(arg));
return true;
}
return false;
}
/**
* \brief Add a new row to RzTable
*
* \param t pointer to RzTable
* \param items pointer to RzPVector which contains row elements
*/
RZ_API void rz_table_add_row_vec(RZ_NONNULL RzTable *t, RZ_NONNULL RzPVector *items) {
rz_return_if_fail(t && items);
RZ_API void rz_table_add_row_list(RzTable *t, RzList *items) {
RzTableRow *row = rz_table_row_new(items);
rz_vector_push(t->rows, row);
rz_list_append(t->rows, row);
// throw warning if not enough columns defined in header
t->totalCols = RZ_MAX(t->totalCols, rz_pvector_len(items));
t->totalCols = RZ_MAX(t->totalCols, rz_list_length(items));
}
/**
@ -244,35 +218,35 @@ RZ_API void rz_table_set_columnsf(RzTable *t, const char *fmt, ...) {
case 's': \
case 'z': \
arg = va_arg(ap, const char *); \
rz_pvector_push(row, strdup(arg ? arg : "")); \
rz_list_append(row, strdup(arg ? arg : "")); \
break; \
case 'b': \
rz_pvector_push(row, rz_str_new(rz_str_bool(va_arg(ap, int)))); \
rz_list_append(row, rz_str_new(rz_str_bool(va_arg(ap, int)))); \
break; \
case 'i': \
case 'd': \
rz_pvector_push(row, rz_str_newf("%d", va_arg(ap, int))); \
rz_list_append(row, rz_str_newf("%d", va_arg(ap, int))); \
break; \
case 'n': \
rz_pvector_push(row, rz_str_newf("%" PFMT64d, va_arg(ap, ut64))); \
rz_list_append(row, rz_str_newf("%" PFMT64d, va_arg(ap, ut64))); \
break; \
case 'u': \
rz_pvector_push(row, rz_num_units(NULL, 32, va_arg(ap, ut64))); \
rz_list_append(row, rz_num_units(NULL, 32, va_arg(ap, ut64))); \
break; \
case 'x': \
case 'X': { \
ut64 n = va_arg(ap, ut64); \
if (n == UT64_MAX) { \
if (fmt == 'X') { \
rz_pvector_push(row, strdup("----------")); \
rz_list_append(row, strdup("----------")); \
} else { \
rz_pvector_push(row, strdup("-1")); \
rz_list_append(row, strdup("-1")); \
} \
} else { \
if (fmt == 'X') { \
rz_pvector_push(row, rz_str_newf("0x%08" PFMT64x, n)); \
rz_list_append(row, rz_str_newf("0x%08" PFMT64x, n)); \
} else { \
rz_pvector_push(row, rz_str_newf("0x%" PFMT64x, n)); \
rz_list_append(row, rz_str_newf("0x%" PFMT64x, n)); \
} \
} \
} break; \
@ -290,22 +264,22 @@ RZ_API void rz_table_add_row_columnsf(RzTable *t, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
RzTableRow *row = rz_vector_tail(t->rows);
RzPVector *vec;
RzTableRow *row = rz_list_last(t->rows);
RzList *list;
bool add_row;
if (row) {
vec = row->items;
list = row->items;
add_row = false;
} else {
vec = rz_pvector_new(free);
list = rz_list_newf(free);
add_row = true;
}
for (const char *f = fmt; *f; f++) {
add_column_to_rowf(vec, *f, ap);
add_column_to_rowf(list, *f, ap);
}
va_end(ap);
if (add_row) {
rz_table_add_row_vec(t, vec);
rz_table_add_row_list(t, list);
}
}
@ -317,20 +291,19 @@ RZ_API void rz_table_add_rowf(RzTable *t, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
RzPVector *vec = rz_pvector_new(free);
RzList *list = rz_list_newf(free);
for (const char *f = fmt; *f; f++) {
add_column_to_rowf(vec, *f, ap);
add_column_to_rowf(list, *f, ap);
}
va_end(ap);
rz_table_add_row_vec(t, vec);
rz_table_add_row_list(t, list);
}
RZ_API void rz_table_add_row(RZ_NONNULL RzTable *t, const char *name, ...) {
rz_return_if_fail(t);
RZ_API void rz_table_add_row(RzTable *t, const char *name, ...) {
va_list ap;
va_start(ap, name);
int col = 0;
RzPVector *items = rz_pvector_new(free);
RzList *items = rz_list_newf(free);
__addRow(t, items, name, col++);
for (;;) {
const char *arg = va_arg(ap, const char *);
@ -343,9 +316,9 @@ RZ_API void rz_table_add_row(RZ_NONNULL RzTable *t, const char *name, ...) {
}
va_end(ap);
RzTableRow *row = rz_table_row_new(items);
rz_vector_push(t->rows, row);
rz_list_append(t->rows, row);
// throw warning if not enough columns defined in header
t->totalCols = RZ_MAX(t->totalCols, rz_pvector_len(items));
t->totalCols = RZ_MAX(t->totalCols, rz_list_length(items));
}
// import / export
@ -375,13 +348,12 @@ static int __strbuf_append_col_aligned_fancy(RzTable *t, RzStrBuf *sb, RzTableCo
static void __computeTotal(RzTable *t) {
RzTableRow *row;
rz_vector_foreach(t->rows, row) {
void **pitem;
RzListIter *iter, *iter2;
rz_list_foreach (t->rows, iter, row) {
char *item;
int c = 0;
rz_pvector_foreach (row->items, pitem) {
item = *pitem;
RzTableColumn *col = rz_vector_index_ptr(t->cols, c);
rz_list_foreach (row->items, iter2, item) {
RzTableColumn *col = rz_list_get_n(t->cols, c);
if (!rz_str_cmp(col->type->name, "number", rz_str_ansi_len("number")) && rz_str_isnumber(item)) {
if (col->total < 0) {
col->total = 0;
@ -393,21 +365,15 @@ static void __computeTotal(RzTable *t) {
}
}
/**
* \brief Convert the content of RzTable to string
*
* \param t pointer to RzTable
* \return string containing content of RzTable
*/
RZ_API RZ_OWN char *rz_table_tofancystring(RZ_NONNULL RzTable *t) {
rz_return_val_if_fail(t, NULL);
if (rz_vector_len(t->cols) == 0) {
RZ_API char *rz_table_tofancystring(RzTable *t) {
if (rz_list_length(t->cols) == 0) {
return strdup("");
}
RzStrBuf *sb = rz_strbuf_new("");
RzTableRow *row;
RzTableColumn *col;
RzCons *cons = (RzCons *)t->cons;
RzListIter *iter, *iter2;
bool useUtf8 = (cons && cons->use_utf8);
bool useUtf8Curvy = (cons && cons->use_utf8_curvy);
const char *v_line = useUtf8 || useUtf8Curvy ? RUNE_LINE_VERT : "|";
@ -420,7 +386,7 @@ RZ_API RZ_OWN char *rz_table_tofancystring(RZ_NONNULL RzTable *t) {
const char *br_corner = useUtf8 ? (useUtf8Curvy ? RUNE_CURVE_CORNER_BR : RUNE_CORNER_BR) : "'";
__table_adjust(t);
rz_vector_foreach(t->cols, col) {
rz_list_foreach (t->cols, iter, col) {
__strbuf_append_col_aligned_fancy(t, sb, col, col->name);
}
int len = rz_str_len_utf8_ansi(rz_strbuf_get(sb)) - 1;
@ -433,13 +399,11 @@ RZ_API RZ_OWN char *rz_table_tofancystring(RZ_NONNULL RzTable *t) {
}
rz_strbuf_appendf(sb, "%s\n%s%s%s\n", v_line, l_intersect, h_line_str, rz_intersect);
rz_vector_foreach(t->rows, row) {
void **pitem;
rz_list_foreach (t->rows, iter, row) {
char *item;
int c = 0;
rz_pvector_foreach (row->items, pitem) {
item = *pitem;
RzTableColumn *col = rz_vector_index_ptr(t->cols, c);
rz_list_foreach (row->items, iter2, item) {
RzTableColumn *col = rz_list_get_n(t->cols, c);
if (col) {
int l = __strbuf_append_col_aligned_fancy(t, sb, col, item);
len = RZ_MAX(len, l);
@ -453,7 +417,7 @@ RZ_API RZ_OWN char *rz_table_tofancystring(RZ_NONNULL RzTable *t) {
char tmp[64];
__computeTotal(t);
rz_strbuf_appendf(sb, "%s%s%s\n", l_intersect, h_line_str, rz_intersect);
rz_vector_foreach(t->cols, col) {
rz_list_foreach (t->cols, iter, col) {
char *num = col->total == -1 ? "" : sdb_itoa(col->total, tmp, 10);
int l = __strbuf_append_col_aligned_fancy(t, sb, col, num);
len = RZ_MAX(len, l);
@ -497,9 +461,6 @@ static int __strbuf_append_col_aligned(RzStrBuf *sb, RzTableColumn *col, const c
rz_strbuf_appendf(sb, "%-*s ", pad + left, str);
break;
}
default:
rz_warn_if_reached();
break;
}
}
return rz_strbuf_length(sb) - ll;
@ -526,12 +487,13 @@ RZ_API char *rz_table_tosimplestring(RzTable *t) {
RzStrBuf *sb = rz_strbuf_new("");
RzTableRow *row;
RzTableColumn *col;
RzListIter *iter, *iter2;
RzCons *cons = (RzCons *)t->cons;
const char *h_line = (cons && (cons->use_utf8 || cons->use_utf8_curvy)) ? RUNE_LONG_LINE_HORIZ : "-";
__table_adjust(t);
int maxlen = 0;
if (t->showHeader) {
rz_vector_foreach(t->cols, col) {
rz_list_foreach (t->cols, iter, col) {
int ll = __strbuf_append_col_aligned(sb, col, col->name, false);
maxlen = RZ_MAX(maxlen, ll);
}
@ -542,14 +504,12 @@ RZ_API char *rz_table_tosimplestring(RzTable *t) {
free(l);
}
}
rz_vector_foreach(t->rows, row) {
void **pitem;
rz_list_foreach (t->rows, iter, row) {
char *item;
int c = 0;
rz_pvector_foreach (row->items, pitem) {
item = *pitem;
bool nopad = (item == rz_pvector_tail(row->items));
RzTableColumn *col = rz_vector_index_ptr(t->cols, c);
rz_list_foreach (row->items, iter2, item) {
bool nopad = !iter2->n;
RzTableColumn *col = rz_list_get_n(t->cols, c);
if (col) {
(void)__strbuf_append_col_aligned(sb, col, item, nopad);
}
@ -567,8 +527,8 @@ RZ_API char *rz_table_tosimplestring(RzTable *t) {
free(l);
}
}
rz_vector_foreach(t->cols, col) {
bool nopad = (col == rz_vector_tail(t->cols));
rz_list_foreach (t->cols, iter, col) {
bool nopad = !iter->n;
(void)__strbuf_append_col_aligned(sb, col, sdb_itoa(col->total, tmp, 10), nopad);
}
}
@ -579,9 +539,10 @@ RZ_API char *rz_table_tocsv(RzTable *t) {
RzStrBuf *sb = rz_strbuf_new("");
RzTableRow *row;
RzTableColumn *col;
RzListIter *iter, *iter2;
if (t->showHeader) {
const char *comma = "";
rz_vector_foreach(t->cols, col) {
rz_list_foreach (t->cols, iter, col) {
if (strchr(col->name, ',')) {
// TODO. escaped string?
rz_strbuf_appendf(sb, "%s\"%s\"", comma, col->name);
@ -592,14 +553,12 @@ RZ_API char *rz_table_tocsv(RzTable *t) {
}
rz_strbuf_append(sb, "\n");
}
rz_vector_foreach(t->rows, row) {
void **pitem;
rz_list_foreach (t->rows, iter, row) {
char *item;
int c = 0;
const char *comma = "";
rz_pvector_foreach (row->items, pitem) {
item = *pitem;
RzTableColumn *col = rz_vector_index_ptr(t->cols, c);
rz_list_foreach (row->items, iter2, item) {
RzTableColumn *col = rz_list_get_n(t->cols, c);
if (col) {
if (strchr(col->name, ',')) {
rz_strbuf_appendf(sb, "%s\"%s\"", comma, col->name);
@ -615,25 +574,17 @@ RZ_API char *rz_table_tocsv(RzTable *t) {
return rz_strbuf_drain(sb);
}
/**
* \brief Convert RzTable to json format
*
* \param t pointer to RzTable
* \return json string
*/
RZ_API RZ_OWN char *rz_table_tojson(RzTable *t) {
rz_return_val_if_fail(t, NULL);
RZ_API char *rz_table_tojson(RzTable *t) {
PJ *pj = pj_new();
RzTableRow *row;
RzListIter *iter, *iter2;
pj_a(pj);
rz_vector_foreach(t->rows, row) {
void **pitem;
rz_list_foreach (t->rows, iter, row) {
char *item;
int c = 0;
pj_o(pj);
rz_pvector_foreach (row->items, pitem) {
item = *pitem;
RzTableColumn *col = rz_vector_index_ptr(t->cols, c);
rz_list_foreach (row->items, iter2, item) {
RzTableColumn *col = rz_list_get_n(t->cols, c);
if (col) {
if (col->type == &rz_table_type_number) {
ut64 n = rz_num_get(NULL, item);
@ -659,12 +610,13 @@ RZ_API RZ_OWN char *rz_table_tojson(RzTable *t) {
RZ_API void rz_table_filter(RzTable *t, int nth, int op, const char *un) {
rz_return_if_fail(t && un);
RzTableRow *row;
RzListIter *iter, *iter2;
ut64 uv = rz_num_math(NULL, un);
ut64 sum = 0;
size_t page = 0, page_items = 0;
size_t lrow = 0;
if (op == 't') {
size_t ll = rz_vector_len(t->rows);
size_t ll = rz_list_length(t->rows);
if (ll > uv) {
uv = ll - uv;
}
@ -678,10 +630,8 @@ RZ_API void rz_table_filter(RzTable *t, int nth, int op, const char *un) {
uv = page_items * (page);
}
size_t nrow = 0;
ut32 i;
for (i = 0; i < rz_vector_len(t->rows); i++) {
row = rz_vector_index_ptr(t->rows, i);
const char *nn = rz_pvector_at(row->items, nth);
rz_list_foreach_safe (t->rows, iter, iter2, row) {
const char *nn = rz_list_get_n(row->items, nth);
ut64 nv = rz_num_math(NULL, nn);
bool match = true;
switch (op) {
@ -755,7 +705,7 @@ RZ_API void rz_table_filter(RzTable *t, int nth, int op, const char *un) {
break;
}
if (!match) {
rz_vector_remove_at(t->rows, i--, NULL);
rz_list_delete(t->rows, iter);
}
}
if (op == '+') {
@ -766,19 +716,23 @@ RZ_API void rz_table_filter(RzTable *t, int nth, int op, const char *un) {
static int cmp(const void *_a, const void *_b) {
RzTableRow *a = (RzTableRow *)_a;
RzTableRow *b = (RzTableRow *)_b;
const char *wa = rz_pvector_at(a->items, Gnth);
const char *wb = rz_pvector_at(b->items, Gnth);
const char *wa = rz_list_get_n(a->items, Gnth);
const char *wb = rz_list_get_n(b->items, Gnth);
int res = Gcmp(wa, wb);
return res;
}
RZ_API void rz_table_sort(RzTable *t, int nth, bool dec) {
RzTableColumn *col = rz_vector_index_ptr(t->cols, nth);
RzTableColumn *col = rz_list_get_n(t->cols, nth);
if (col) {
Gnth = nth;
if (col->type && col->type->cmp) {
Gcmp = col->type->cmp;
rz_vector_sort(t->rows, cmp, dec);
t->rows->sorted = false; // force sorting
rz_list_sort(t->rows, cmp);
if (dec) {
rz_list_reverse(t->rows);
}
}
Gnth = 0;
Gcmp = NULL;
@ -788,42 +742,60 @@ RZ_API void rz_table_sort(RzTable *t, int nth, bool dec) {
static int cmplen(const void *_a, const void *_b) {
RzTableRow *a = (RzTableRow *)_a;
RzTableRow *b = (RzTableRow *)_b;
const char *wa = rz_pvector_at(a->items, Gnth);
const char *wb = rz_pvector_at(b->items, Gnth);
const char *wa = rz_list_get_n(a->items, Gnth);
const char *wb = rz_list_get_n(b->items, Gnth);
int res = strlen(wa) - strlen(wb);
return res;
}
RZ_API void rz_table_sortlen(RzTable *t, int nth, bool dec) {
RzTableColumn *col = rz_vector_index_ptr(t->cols, nth);
RzTableColumn *col = rz_list_get_n(t->cols, nth);
if (col) {
Gnth = nth;
rz_vector_sort(t->rows, cmplen, dec);
t->rows->sorted = false; // force sorting
rz_list_sort(t->rows, cmplen);
if (dec) {
rz_list_reverse(t->rows);
}
Gnth = 0;
}
}
static int rz_rows_cmp(RzPVector *lhs, RzPVector *rhs, RzVector *cols, int nth) {
void *item_lhs, *item_rhs;
static int rz_rows_cmp(RzList *lhs, RzList *rhs, RzList *cols, int nth) {
RzListIter *iter_lhs;
RzListIter *iter_rhs;
RzListIter *iter_col;
RzTableColumn *item_col;
st32 tmp, i;
for (i = 0; i < rz_pvector_len(lhs) && i < rz_pvector_len(rhs) && i < rz_vector_len(cols); i++) {
item_lhs = rz_pvector_at(lhs, i);
item_rhs = rz_pvector_at(rhs, i);
item_col = rz_vector_index_ptr(cols, i);
void *item_lhs;
void *item_rhs;
int tmp;
int i = 0;
for (iter_lhs = lhs->head, iter_rhs = rhs->head, iter_col = cols->head;
iter_lhs && iter_rhs && iter_col;
iter_lhs = iter_lhs->n, iter_rhs = iter_rhs->n, iter_col = iter_col->n) {
item_lhs = iter_lhs->data;
item_rhs = iter_rhs->data;
item_col = iter_col->data;
if (nth == -1 || i == nth) {
tmp = item_col->type->cmp(item_lhs, item_rhs);
if (tmp) {
return tmp;
}
}
i++;
}
if (rz_pvector_len(lhs) > rz_pvector_len(rhs)) {
if (iter_lhs) {
return 1;
} else if (rz_pvector_len(lhs) < rz_pvector_len(rhs)) {
}
if (iter_rhs) {
return -1;
}
@ -835,19 +807,27 @@ RZ_API void rz_table_uniq(RzTable *t) {
}
RZ_API void rz_table_group(RzTable *t, int nth, RzTableSelector fcn) {
RzTableRow *row, *uniq_row;
RzVector *rows = t->rows;
ut32 i, j;
RzListIter *iter;
RzListIter *tmp;
RzTableRow *row;
RzListIter *iter_inner;
RzTableRow *uniq_row;
RzList *rows = t->rows;
rz_list_foreach_safe (rows, iter, tmp, row) {
for (iter_inner = rows->head;
iter_inner && iter_inner != iter;
iter_inner = iter_inner->n) {
uniq_row = iter_inner->data;
for (i = 0; i < rz_vector_len(rows); i++) {
row = rz_vector_index_ptr(rows, i);
for (j = 0; j < i; j++) {
uniq_row = rz_vector_index_ptr(rows, j);
if (!rz_rows_cmp(uniq_row->items, row->items, t->cols, nth)) {
if (fcn) {
fcn(uniq_row, row, nth);
}
rz_vector_remove_at(rows, i--, NULL);
rz_list_delete(rows, iter);
break;
}
}
@ -855,10 +835,10 @@ RZ_API void rz_table_group(RzTable *t, int nth, RzTableSelector fcn) {
}
RZ_API int rz_table_column_nth(RzTable *t, const char *name) {
RzListIter *iter;
RzTableColumn *col;
ut32 n = 0;
rz_vector_foreach(t->cols, col) {
int n = 0;
rz_list_foreach (t->cols, iter, col) {
if (!strcmp(name, col->name)) {
return n;
}
@ -889,20 +869,14 @@ static int __resolveOperation(const char *op) {
return -1;
}
/**
* \brief Select specific columns in RzTable
*
* \param t pointer to RzTable
* \param col_names pointer to RzList containing column names
*/
RZ_API void rz_table_columns(RzTable *t, RzList *col_names) {
// 1 bool per OLD column to indicate whether it should be freed (masked out)
bool *free_cols = malloc(sizeof(bool) * rz_vector_len(t->cols));
bool *free_cols = malloc(sizeof(bool) * rz_list_length(t->cols));
if (!free_cols) {
return;
}
size_t i;
for (i = 0; i < rz_vector_len(t->cols); i++) {
for (i = 0; i < rz_list_length(t->cols); i++) {
free_cols[i] = true;
}
@ -932,62 +906,60 @@ RZ_API void rz_table_columns(RzTable *t, RzList *col_names) {
}
RzTableRow *row;
rz_vector_foreach(t->rows, row) {
RzPVector *old_items = row->items;
RzPVector *new_items = rz_pvector_new(free);
rz_list_foreach (t->rows, it, row) {
RzList *old_items = row->items;
RzList *new_items = rz_list_newf(free);
for (i = 0; i < new_count; i++) {
char *item = *rz_pvector_index_ptr(old_items, col_sources[i].oldcol);
char *item = rz_list_get_n(old_items, col_sources[i].oldcol);
if (!item) {
continue;
}
if (col_sources[i].dup) {
item = strdup(item);
}
rz_pvector_push(new_items, item);
rz_list_append(new_items, item);
}
row->items = new_items;
// Free dropped items
void **item;
char *item;
i = 0;
rz_pvector_foreach (old_items, item) {
RzListIter *fit;
rz_list_foreach (old_items, fit, item) {
if (free_cols[i]) {
free(*item);
free(item);
}
i++;
}
// Set old_items->free = NULL to avoid useful items are freed
old_items->v.free = NULL;
rz_pvector_free(old_items);
old_items->free = NULL;
rz_list_free(old_items);
}
RzVector *old_cols = t->cols;
RzVector *new_cols = rz_vector_new(sizeof(RzTableColumn), rz_table_column_fini_wrapper, NULL);
RzList *old_cols = t->cols;
RzList *new_cols = rz_list_newf(rz_table_column_free);
for (i = 0; i < new_count; i++) {
RzTableColumn *col = rz_vector_index_ptr(old_cols, col_sources[i].oldcol);
RzTableColumn *col = rz_list_get_n(old_cols, col_sources[i].oldcol);
if (!col) {
continue;
}
if (col_sources[i].dup) {
col = rz_table_column_clone(col);
}
rz_vector_push(new_cols, col);
rz_list_append(new_cols, col);
}
t->cols = new_cols;
// Free dropped columns
RzTableColumn *col;
i = 0;
rz_vector_foreach(old_cols, col) {
rz_list_foreach (old_cols, it, col) {
if (free_cols[i]) {
rz_table_column_fini(col);
rz_table_column_free(col);
}
i++;
}
// Set old_cols->free = NULL to avoid useful columns are freed
old_cols->free = NULL;
rz_vector_free(old_cols);
rz_list_free(old_cols);
free(col_sources);
free(free_cols);
@ -996,18 +968,17 @@ RZ_API void rz_table_columns(RzTable *t, RzList *col_names) {
RZ_API void rz_table_filter_columns(RzTable *t, RzList *list) {
const char *col;
RzListIter *iter;
RzVector *cols = t->cols;
t->cols = rz_vector_new(sizeof(RzTableColumn), rz_table_column_fini_wrapper, NULL);
RzList *cols = t->cols;
t->cols = rz_list_newf(rz_table_column_free);
rz_list_foreach (list, iter, col) {
int ncol = rz_table_column_nth(t, col);
if (ncol != -1) {
RzTableColumn *c = rz_vector_index_ptr(cols, ncol);
RzTableColumn *c = rz_list_get_n(cols, ncol);
if (c) {
rz_table_add_column(t, c->type, col, 0);
}
}
}
rz_vector_free(cols);
}
static bool set_table_format(RzTable *t, const char *q) {
@ -1171,7 +1142,7 @@ RZ_API bool rz_table_query(RzTable *t, const char *q) {
}
RZ_API bool rz_table_align(RzTable *t, int nth, int align) {
RzTableColumn *col = rz_vector_index_ptr(t->cols, nth);
RzTableColumn *col = rz_list_get_n(t->cols, nth);
if (col) {
col->align = align;
return true;
@ -1272,23 +1243,24 @@ RZ_API void rz_table_visual_list(RzTable *table, RzList *list, ut64 seek, ut64 l
*/
RZ_OWN RZ_API RzTable *rz_table_transpose(RZ_NONNULL RzTable *t) {
rz_return_val_if_fail(t, NULL);
RzListIter *iter1;
RzListIter *iter;
RzListIter *trrow_iter; // transpose row iter
RzList *row_name = rz_list_new();
RzList *row_list;
RzTable *transpose = rz_table_new();
RzTableColumn *col;
RzTableRow *row;
RzTableColumnType *typeString = rz_table_type("string");
void **pitem;
char *item;
ut32 i;
// getting table column names to add to row head
rz_table_add_column(transpose, typeString, "Name", 0);
// adding rows to transpose table rows * (number of columns in the table)
for (i = 0; i < rz_vector_len(t->rows); i++) {
for (int i = 0; i < t->rows->length; i++) {
char name[20];
if (rz_vector_len(t->rows) == 1) {
if (t->rows->length == 1) {
rz_table_add_column(transpose, typeString, "Value", 0);
} else {
rz_table_add_column(transpose, typeString, rz_strf(name, "Value%d", i + 1), 0);
@ -1296,7 +1268,7 @@ RZ_OWN RZ_API RzTable *rz_table_transpose(RZ_NONNULL RzTable *t) {
}
// column names to row heads
rz_vector_foreach(t->cols, col) {
rz_list_foreach (t->cols, iter1, col) {
rz_list_append(row_name, col->name);
}
@ -1305,7 +1277,7 @@ RZ_OWN RZ_API RzTable *rz_table_transpose(RZ_NONNULL RzTable *t) {
iter = row_name->head;
if (iter) {
item = iter->data;
for (i = 0; i < t->totalCols; i++) {
for (int i = 0; i < t->totalCols; i++) {
rz_table_add_row(transpose, item, NULL);
if (iter->n) {
iter = iter->n;
@ -1316,17 +1288,24 @@ RZ_OWN RZ_API RzTable *rz_table_transpose(RZ_NONNULL RzTable *t) {
}
if (transpose->rows) {
rz_vector_foreach(t->rows, row) {
i = 0;
rz_pvector_foreach (row->items, pitem) {
item = *pitem;
RzTableRow *tr_row = rz_vector_index_ptr(transpose->rows, i++);
RzPVector *tr_items = tr_row->items;
rz_pvector_push(tr_items, strdup(item));
row_list = transpose->rows;
trrow_iter = row_list->head;
RzTableRow *trans_row = trrow_iter->data;
rz_list_foreach (t->rows, iter, row) {
trrow_iter = row_list->head;
if (trrow_iter) {
trans_row = trrow_iter->data;
rz_list_foreach (row->items, iter1, item) {
if (trrow_iter && trans_row->items) {
trans_row = trrow_iter->data;
rz_list_append(trans_row->items, strdup(item));
trrow_iter = trrow_iter->n;
}
}
}
}
// free(item);
}
rz_list_free(row_name);
return transpose;
}

View file

@ -236,50 +236,6 @@ RZ_API void *rz_vector_flush(RzVector *vec) {
return r;
}
// CLRS Quicksort. It is slow, but simple.
#define VEC_INDEX(a, i) (char *)a + elem_size *(i)
static void vector_quick_sort(void *a, size_t elem_size, size_t len, RzPVectorComparator cmp, bool reverse) {
rz_return_if_fail(a);
if (len <= 1) {
return;
}
size_t i = rand() % len, j = 0;
void *t, *pivot;
t = (void *)malloc(elem_size);
pivot = (void *)malloc(elem_size);
if (!t || !pivot) {
RZ_FREE(t);
RZ_FREE(pivot);
RZ_LOG_ERROR("Failed to allocate memory\n");
return;
}
memcpy(pivot, VEC_INDEX(a, i), elem_size);
memcpy(VEC_INDEX(a, i), VEC_INDEX(a, len - 1), elem_size);
for (i = 0; i < len - 1; i++) {
if ((cmp(VEC_INDEX(a, i), pivot) < 0 && !reverse) ||
(cmp(VEC_INDEX(a, i), pivot) > 0 && reverse)) {
memcpy(t, VEC_INDEX(a, i), elem_size);
memcpy(VEC_INDEX(a, i), VEC_INDEX(a, j), elem_size);
memcpy(VEC_INDEX(a, j), t, elem_size);
j++;
}
}
memcpy(VEC_INDEX(a, len - 1), VEC_INDEX(a, j), elem_size);
memcpy(VEC_INDEX(a, j), pivot, elem_size);
RZ_FREE(t);
RZ_FREE(pivot);
vector_quick_sort(a, elem_size, j, cmp, reverse);
vector_quick_sort(VEC_INDEX(a, j + 1), elem_size, len - j - 1, cmp, reverse);
}
#undef VEC_INDEX
RZ_API void rz_vector_sort(RzVector *vec, RzVectorComparator cmp, bool reverse) {
rz_return_if_fail(vec && cmp);
vector_quick_sort(vec->a, vec->elem_size, vec->len, cmp, reverse);
}
// pvector
static void pvector_free_elem(void *e, void *user) {

View file

@ -1,45 +1,45 @@
NAME=iS query
FILE=bins/elf/analysis/main
CMDS=iS:name/sort:vaddr/cols/name
CMDS=iS:size/sort:vaddr/cols/name
EXPECT=<<EOF
vaddr name
------------------------------
0x00000000
0x00600910 .bss
0x00000000 .comment
0x006006e0 .init_array
0x006006e8 .fini_array
0x006006f0 .jcr
0x006008c8 .got
0x0040031e .gnu.version
0x004005b4 .fini
0x00600900 .data
0x004005c0 .rodata
0x00400348 .rela.dyn
0x004003a8 .init
0x00400260 .gnu.hash
0x00400200 .interp
0x0040021c .note.ABI-tag
0x00400328 .gnu.version_r
0x00000000 .comment
0x0040023c .note.gnu.build-id
0x006008d0 .got.plt
0x004005d0 .eh_frame_hdr
0x004002e0 .dynstr
0x004003d0 .plt
0x00400360 .rela.plt
0x00400280 .dynsym
0x00000000 .debug_abbrev
0x00000000 .debug_aranges
0x00000000 .debug_info
0x00000000 .debug_line
0x00000000 .debug_ranges
0x00000000 .debug_str
0x006006f8 .dynamic
0x004002e0 .dynstr
0x00400280 .dynsym
0x00000000 .debug_aranges
0x00400608 .eh_frame
0x004005d0 .eh_frame_hdr
0x004005b4 .fini
0x006006e8 .fini_array
0x00400260 .gnu.hash
0x0040031e .gnu.version
0x00400328 .gnu.version_r
0x006008c8 .got
0x006008d0 .got.plt
0x004003a8 .init
0x006006e0 .init_array
0x00400200 .interp
0x006006f0 .jcr
0x0040021c .note.ABI-tag
0x0040023c .note.gnu.build-id
0x004003d0 .plt
0x00400348 .rela.dyn
0x00400360 .rela.plt
0x004005c0 .rodata
0x00000000 .debug_line
0x00000000 .shstrtab
0x00000000 .debug_info
0x00400410 .text
0x006006f8 .dynamic
0x00000000 .strtab
0x00000000 .symtab
0x00400410 .text
EOF
RUN

View file

@ -77,7 +77,7 @@ CMDS=<<EOF
flt:size/ne/0:addr/ne/0x00000000:/head/10:csv~:..20
flt:space/eq/relocs:addr/cols/name:/head/3:json~{}
flt:/head/10:/tail/4:space/cols/name
flt:/page/2/10:sort/cols/space/size/name:name/sort/inc:fancy
flt:/page/2/10:sort/cols/space/size/name:size/sort/inc:fancy
EOF
EXPECT=<<EOF
addr,size,space,name
@ -115,17 +115,17 @@ imports loc.imp._ITM_deregisterTMCloneTable
.----------------------------------------------------------------------------------------------------.
| space | size | name |
)----------------------------------------------------------------------------------------------------(
| classes | 1 | class.A |
| classes | 1 | class.B |
| classes | 1 | class.C |
| classes | 1 | class.std::basic_ostream_char__std::char_traits_char_____std::endl_char__std |
| classes | 1 | class.std::basic_ostream_char__std::char_traits_char_____std::operator____std |
| classes | 1 | class.std::ios_base::Init |
| classes | 1 | class.std::ostream |
| imports | 16 | loc.imp._ITM_deregisterTMCloneTable |
| classes | 1 | class.std::ios_base::Init |
| classes | 1 | class.std::basic_ostream_char__std::char_traits_char_____std::operator____std |
| classes | 1 | class.std::basic_ostream_char__std::char_traits_char_____std::endl_char__std |
| classes | 1 | class.B |
| classes | 1 | class.A |
| classes | 1 | class.C |
| imports | 16 | loc.imp._ITM_registerTMCloneTable |
| segments | 4132 | segment.LOAD0 |
| imports | 16 | loc.imp._ITM_deregisterTMCloneTable |
| segments | 64 | segment.ehdr |
| segments | 4132 | segment.LOAD0 |
`----------------------------------------------------------------------------------------------------'
EOF
RUN

View file

@ -49,7 +49,7 @@ RzTable *__table_test_data1() {
bool test_rz_table_column_type(void) {
RzTable *t = __table_test_data1();
RzTableColumn *c = rz_vector_index_ptr(t->cols, 1);
RzTableColumn *c = rz_list_get_n(t->cols, 1);
c->type = rz_table_type("NUMBER");
rz_table_sort(t, 1, true);
char *s = rz_table_tostring(t);
@ -140,6 +140,7 @@ bool test_rz_table_uniq(void) {
rz_table_add_row(t, "d", "99", NULL);
rz_table_add_row(t, "c", "99", NULL);
rz_table_add_row(t, "c", "100", NULL);
rz_table_uniq(t);
char *stri = rz_table_tostring(t);
mu_assert_streq(stri,
@ -157,29 +158,38 @@ bool test_rz_table_uniq(void) {
}
static void simple_merge(RzTableRow *acc, RzTableRow *new_row, int nth) {
RzPVector *lhs = acc->items;
RzPVector *rhs = new_row->items;
RzList *lhs = acc->items;
RzList *rhs = new_row->items;
RzListIter *iter_lhs;
RzListIter *iter_rhs;
char *item_lhs;
int cnt;
for (cnt = 0; cnt < rz_pvector_len(lhs) && cnt < rz_pvector_len(rhs); cnt++) {
item_lhs = rz_pvector_at(lhs, cnt);
int i = 0;
if (cnt != nth) {
for (iter_lhs = lhs->head, iter_rhs = rhs->head;
iter_lhs && iter_rhs;
iter_lhs = iter_lhs->n, iter_rhs = iter_rhs->n) {
item_lhs = iter_lhs->data;
if (i != nth) {
if (!strcmp(item_lhs, "a")) {
free(item_lhs);
rz_pvector_set(lhs, cnt, rz_str_new("a | e"));
free(iter_lhs->data);
iter_lhs->data = rz_str_new("a | e");
} else if (!strcmp(item_lhs, "b")) {
free(item_lhs);
rz_pvector_set(lhs, cnt, rz_str_new("b | f"));
free(iter_lhs->data);
iter_lhs->data = rz_str_new("b | f");
} else if (!strcmp(item_lhs, "c")) {
free(item_lhs);
rz_pvector_set(lhs, cnt, rz_str_new("c | h"));
free(iter_lhs->data);
iter_lhs->data = rz_str_new("c | h");
} else if (!strcmp(item_lhs, "d")) {
free(item_lhs);
rz_pvector_set(lhs, cnt, rz_str_new("d | g"));
free(iter_lhs->data);
iter_lhs->data = rz_str_new("d | g");
}
}
++i;
}
}
@ -342,7 +352,7 @@ bool test_rz_table_add_row_columnsf() {
"b 98\n"
"c 99\n"
"e 10\n",
"rz_table_add_row_columnsf");
"rz_table_transpose");
free(table);
rz_table_free(t);
mu_end;

View file

@ -198,31 +198,6 @@ static bool test_vector_clone(void) {
mu_end;
}
static bool test_vector_sort(void) {
RzVector *v = rz_vector_new(sizeof("aaa"), NULL, NULL);
rz_vector_push(v, "abb");
rz_vector_push(v, "caa");
rz_vector_push(v, "abb");
rz_vector_push(v, "ccc");
// do inc sort
rz_vector_sort(v, (RzVectorComparator)strcmp, false);
mu_assert_streq(rz_vector_index_ptr(v, 0), "abb", "sorted strings");
mu_assert_streq(rz_vector_index_ptr(v, 1), "abb", "sorted strings");
mu_assert_streq(rz_vector_index_ptr(v, 2), "caa", "sorted strings");
mu_assert_streq(rz_vector_index_ptr(v, 3), "ccc", "sorted strings");
// do dec sort
rz_vector_sort(v, (RzVectorComparator)strcmp, true);
mu_assert_streq(rz_vector_index_ptr(v, 0), "ccc", "sorted strings");
mu_assert_streq(rz_vector_index_ptr(v, 1), "caa", "sorted strings");
mu_assert_streq(rz_vector_index_ptr(v, 2), "abb", "sorted strings");
mu_assert_streq(rz_vector_index_ptr(v, 3), "abb", "sorted strings");
rz_vector_free(v);
mu_end;
}
static bool test_vector_empty(void) {
RzVector v;
rz_vector_init(&v, 1, NULL, NULL);
@ -1313,7 +1288,6 @@ static int all_tests(void) {
mu_run_test(test_vector_clone);
mu_run_test(test_vector_empty);
mu_run_test(test_vector_remove_at);
mu_run_test(test_vector_sort);
mu_run_test(test_vector_remove_range);
mu_run_test(test_vector_insert);
mu_run_test(test_vector_insert_range);