Rizin
unix-like reverse engineering framework and cli tools
diff.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2019 thestr4ng3r <info@florianmaerkl.de>
2 // SPDX-License-Identifier: MIT
3 
4 #include "sdb.h"
5 
6 RZ_API int sdb_diff_format(char *str, int size, const SdbDiff *diff) {
7  int r = 0;
8 #define APPENDF(...) \
9  do { \
10  int sr = snprintf(str, size, __VA_ARGS__); \
11  if (sr < 0) { \
12  return sr; \
13  } \
14  r += sr; \
15  if (sr >= size) { \
16  /* no space left, only measure from now on */ \
17  str = NULL; \
18  size = 0; \
19  } else { \
20  str += sr; \
21  size -= sr; \
22  } \
23  } while (0)
24 
25  APPENDF("%c%s ", diff->add ? '+' : '-', diff->v ? " " : "NS");
26 
27  SdbListIter *it;
28  const char *component;
29  ls_foreach (diff->path, it, component) {
30  APPENDF("%s/", component);
31  }
32 
33  if (diff->v) {
34  APPENDF("%s=%s", diff->k, diff->v);
35  } else {
36  APPENDF("%s", diff->k);
37  }
38 
39 #undef APPENDF
40  return r;
41 }
42 
43 typedef struct sdb_diff_ctx_t {
44  Sdb *a;
45  Sdb *b;
46  bool equal;
49  void *cb_user;
51 
52 #define DIFF(ctx, c, ret) \
53  do { \
54  (ctx)->equal = false; \
55  if ((ctx)->cb) { \
56  c \
57  } else { \
58  /* we already know it's not equal and don't care about the rest of the diff */ \
59  return ret; \
60  } \
61  } while (0)
62 
63 static void sdb_diff_report_ns(SdbDiffCtx *ctx, SdbNs *ns, bool add) {
64  SdbDiff diff = { ctx->path, ns->name, NULL, add };
65  ctx->cb(&diff, ctx->cb_user);
66 }
67 
68 static void sdb_diff_report_kv(SdbDiffCtx *ctx, const char *k, const char *v, bool add) {
69  SdbDiff diff = { ctx->path, k, v, add };
70  ctx->cb(&diff, ctx->cb_user);
71 }
72 
73 typedef struct sdb_diff_kv_cb_ctx {
75  bool add;
77 
78 static bool sdb_diff_report_kv_cb(void *user, const char *k, const char *v) {
79  const SdbDiffKVCbCtx *ctx = user;
80  sdb_diff_report_kv(ctx->ctx, k, v, ctx->add);
81  return true;
82 }
83 
87 static void sdb_diff_report(SdbDiffCtx *ctx, Sdb *sdb, bool add) {
88  SdbListIter *it;
89  SdbNs *ns;
90  ls_foreach (sdb->ns, it, ns) {
92  ls_push(ctx->path, ns->name);
93  sdb_diff_report(ctx, ns->sdb, add);
94  ls_pop(ctx->path);
95  }
96  SdbDiffKVCbCtx cb_ctx = { ctx, add };
97  sdb_foreach(sdb, sdb_diff_report_kv_cb, &cb_ctx);
98 }
99 
100 static bool sdb_diff_kv_cb(void *user, const char *k, const char *v) {
101  const SdbDiffKVCbCtx *ctx = user;
102  Sdb *other = ctx->add ? ctx->ctx->a : ctx->ctx->b;
103  const char *other_val = sdb_const_get(other, k, NULL);
104  if (!other_val || !*other_val) {
105  DIFF(ctx->ctx,
106  sdb_diff_report_kv(ctx->ctx, k, v, ctx->add);
107  , false);
108  } else if (!ctx->add && strcmp(v, other_val) != 0) {
109  DIFF(ctx->ctx,
110  sdb_diff_report_kv(ctx->ctx, k, v, false);
111  sdb_diff_report_kv(ctx->ctx, k, other_val, true);
112  , false);
113  }
114  return true;
115 }
116 
117 static void sdb_diff_ctx(SdbDiffCtx *ctx) {
118  SdbListIter *it;
119  SdbNs *ns;
120  ls_foreach (ctx->a->ns, it, ns) {
121  Sdb *b_ns = sdb_ns(ctx->b, ns->name, false);
122  if (!b_ns) {
123  DIFF(ctx,
124  sdb_diff_report_ns(ctx, ns, false);
125  ls_push(ctx->path, ns->name);
126  sdb_diff_report(ctx, ns->sdb, false);
127  ls_pop(ctx->path);
128  , );
129  continue;
130  }
131  Sdb *a = ctx->a;
132  Sdb *b = ctx->b;
133  ctx->a = ns->sdb;
134  ctx->b = b_ns;
135  ls_push(ctx->path, ns->name);
136  sdb_diff_ctx(ctx);
137  ls_pop(ctx->path);
138  ctx->a = a;
139  ctx->b = b;
140  }
141  ls_foreach (ctx->b->ns, it, ns) {
142  if (!sdb_ns(ctx->a, ns->name, false)) {
143  DIFF(ctx,
144  sdb_diff_report_ns(ctx, ns, true);
145  ls_push(ctx->path, ns->name);
146  sdb_diff_report(ctx, ns->sdb, true);
147  ls_pop(ctx->path);
148  , );
149  }
150  }
151  SdbDiffKVCbCtx kv_ctx = { ctx, false };
152  if (!sdb_foreach(ctx->a, sdb_diff_kv_cb, &kv_ctx)) {
153  return;
154  }
155  kv_ctx.add = true;
156  sdb_foreach(ctx->b, sdb_diff_kv_cb, &kv_ctx);
157 }
158 
159 RZ_API bool sdb_diff(Sdb *a, Sdb *b, SdbDiffCallback cb, void *cb_user) {
160  SdbDiffCtx ctx;
161  ctx.a = a;
162  ctx.b = b;
163  ctx.equal = true;
164  ctx.cb = cb;
165  ctx.cb_user = cb_user;
166  ctx.path = ls_new();
167  if (!ctx.path) {
168  return false;
169  }
170  sdb_diff_ctx(&ctx);
171  ls_free(ctx.path);
172  return ctx.equal;
173 }
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
voidpf void uLong size
Definition: ioapi.h:138
RZ_API SdbList * ls_new(void)
Definition: ls.c:16
RZ_API void * ls_pop(SdbList *list)
Definition: ls.c:244
RZ_API void ls_free(SdbList *list)
Definition: ls.c:191
#define ls_push(x, y)
Definition: ls.h:75
#define ls_foreach(list, it, pos)
Definition: ls.h:31
RZ_API Sdb * sdb_ns(Sdb *s, const char *name, int create)
Definition: ns.c:186
RZ_API const char * sdb_const_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:279
RZ_API bool sdb_foreach(Sdb *s, SdbForeachCallback cb, void *user)
Definition: sdb.c:758
void(* SdbDiffCallback)(const SdbDiff *diff, void *user)
Definition: sdb.h:145
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
Definition: ls.h:17
Definition: ls.h:22
void * cb_user
Definition: diff.c:49
SdbDiffCallback cb
Definition: diff.c:48
Sdb * a
Definition: diff.c:44
bool equal
Definition: diff.c:46
SdbList * path
Definition: diff.c:47
Sdb * b
Definition: diff.c:45
SdbDiffCtx * ctx
Definition: diff.c:74
const char * k
Definition: sdb.h:137
const char * v
Definition: sdb.h:138
const SdbList * path
Definition: sdb.h:136
bool add
Definition: sdb.h:139
Definition: sdb.h:88
char * name
Definition: sdb.h:89
Sdb * sdb
Definition: sdb.h:91
Definition: sdb.h:63
SdbList * ns
Definition: sdb.h:82
static void sdb_diff_report_ns(SdbDiffCtx *ctx, SdbNs *ns, bool add)
Definition: diff.c:63
static void sdb_diff_ctx(SdbDiffCtx *ctx)
Definition: diff.c:117
struct sdb_diff_kv_cb_ctx SdbDiffKVCbCtx
static void sdb_diff_report_kv(SdbDiffCtx *ctx, const char *k, const char *v, bool add)
Definition: diff.c:68
#define APPENDF(...)
static bool sdb_diff_report_kv_cb(void *user, const char *k, const char *v)
Definition: diff.c:78
static void sdb_diff_report(SdbDiffCtx *ctx, Sdb *sdb, bool add)
Definition: diff.c:87
struct sdb_diff_ctx_t SdbDiffCtx
#define DIFF(ctx, c, ret)
Definition: diff.c:52
RZ_API bool sdb_diff(Sdb *a, Sdb *b, SdbDiffCallback cb, void *cb_user)
Definition: diff.c:159
static bool sdb_diff_kv_cb(void *user, const char *k, const char *v)
Definition: diff.c:100
RZ_API int sdb_diff_format(char *str, int size, const SdbDiff *diff)
Definition: diff.c:6
static const char * cb[]
Definition: z80_tab.h:176
static int add(char *argv[])
Definition: ziptool.c:84