-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
#include <r_io.h> | ||
#include <r_reg.h> | ||
#include <r_list.h> | ||
#include <r_skiplist.h> | ||
#include <r_util.h> | ||
#include <r_syscall.h> | ||
#include <r_flags.h> | ||
|
@@ -312,7 +313,8 @@ typedef struct r_anal_type_function_t { | |
RAnalDiff *diff; | ||
RList *locs; // list of local variables | ||
//RList *locals; // list of local labels -> moved to anal->sdb_fcns | ||
RList *bbs; | ||
//RList *bbs; | ||
RSkipList *bbs_sl; | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
radare
Collaborator
|
||
RList *vars; | ||
#if FCN_OLD | ||
RList *refs; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// (c) 2016 Jeffrey Crowell | ||
// BSD 3 Clause License | ||
// radare2 | ||
|
||
// Skiplists are a probabilistic datastructure than can be used as a k-v store | ||
// with average case O(lg n) lookup time, and worst case O(n). | ||
|
||
// https://en.wikipedia.org/wiki/Skip_list | ||
|
||
#ifndef R2_SKIP_LIST_H | ||
#define R2_SKIP_LIST_H | ||
|
||
#include <r_list.h> | ||
|
||
typedef struct r_skiplist_node_t { | ||
void *data; // pointer to the value | ||
struct r_skiplist_node_t *forward[1]; // forward pointer | ||
This comment has been minimized.
Sorry, something went wrong. |
||
} r_skiplist_node; | ||
|
||
typedef struct r_skiplist_t { | ||
r_skiplist_node *head; // list header | ||
int list_level; // current level of the list. | ||
RListFree freefn; | ||
RListComparator compare; | ||
} r_skiplist; | ||
|
||
typedef r_skiplist RSkipList; | ||
|
||
R_API r_skiplist* r_skiplist_new(RListFree freefn, RListComparator comparefn); | ||
R_API r_skiplist_node* r_skiplist_insert(r_skiplist* list, void* data); | ||
R_API void r_skiplist_delete(r_skiplist* list, void* data); | ||
R_API r_skiplist_node* r_skiplist_find(r_skiplist* list, void* data); | ||
|
||
#endif // R2_SKIP_LIST_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// (c) 2016 Jeffrey Crowell | ||
This comment has been minimized.
Sorry, something went wrong.
radare
Collaborator
|
||
// BSD 3 Clause License | ||
// radare2 | ||
|
||
// Skiplists are a probabilistic datastructure than can be used as a k-v store | ||
// with average case O(lg n) lookup time, and worst case O(n). | ||
|
||
// https://en.wikipedia.org/wiki/Skip_list | ||
|
||
#include <r_skiplist.h> | ||
|
||
const int kSkipListDepth = 15; // max depth | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
// Takes in a pointer to the function to free a list element, and a pointer to | ||
// a function that retruns 0 on equality between two elements, and -1 or 1 | ||
// when unequal (for sorting). | ||
// Returns a new heap-allocated skiplist. | ||
R_API r_skiplist* r_skiplist_new(RListFree freefn, RListComparator comparefn) { | ||
int i; | ||
r_skiplist* list = calloc (1, sizeof (r_skiplist)); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
if ((list->head = | ||
calloc (1, | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
sizeof (r_skiplist_node) + | ||
kSkipListDepth * sizeof (r_skiplist_node*))) == NULL) { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
eprintf ("can't init skiplist..."); | ||
return NULL; | ||
} | ||
for (i = 0; i <= kSkipListDepth; i++) { | ||
list->head->forward[i] = list->head; | ||
} | ||
list->list_level = 0; | ||
return list; | ||
} | ||
|
||
// Inserts an element to the skiplist, and returns a pointer to the element's | ||
// node. | ||
R_API r_skiplist_node* r_skiplist_insert(r_skiplist* list, void* data) { | ||
int i, new_level; | ||
r_skiplist_node* update [kSkipListDepth + 1]; | ||
This comment has been minimized.
Sorry, something went wrong.
radare
Collaborator
|
||
r_skiplist_node* nnode; | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
// Find the spot for it. | ||
nnode = list->head; | ||
for (i = list->list_level; i >= 0; i--) { | ||
while ((nnode->forward[i] != list->head) && | ||
This comment has been minimized.
Sorry, something went wrong.
radare
Collaborator
|
||
(list->compare (nnode->forward[i]->data, data) < 1)) { | ||
nnode = nnode->forward[i]; | ||
} | ||
update[i] = nnode; | ||
} | ||
nnode = nnode->forward[0]; | ||
if (nnode != list->head && list->compare (nnode->data, data) == 0) { | ||
return nnode; | ||
} | ||
|
||
// Determine the level "randomly". | ||
// Skiplists are a probabilistic datastructure. | ||
for (new_level = 0; rand() % 2 && new_level < kSkipListDepth; new_level++); | ||
This comment has been minimized.
Sorry, something went wrong.
radare
Collaborator
|
||
|
||
if (new_level < list->list_level) { | ||
for (i = list->list_level + 1; i <= new_level; i++) { | ||
update[i] = list->head; | ||
} | ||
} | ||
|
||
// Okie, now make the node actually... | ||
if ((nnode = calloc (1, | ||
This comment has been minimized.
Sorry, something went wrong. |
||
sizeof (r_skiplist_node) + | ||
This comment has been minimized.
Sorry, something went wrong.
radare
Collaborator
|
||
new_level * sizeof (r_skiplist_node*))) == NULL) { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
eprintf ("can't calloc new node for skiplist"); | ||
return NULL; | ||
} | ||
nnode->data = data; | ||
|
||
// update fwd links. | ||
for (i = 0; i <= new_level; i++) { | ||
nnode->forward[i] = update[i]->forward[i]; | ||
} | ||
return nnode; | ||
} | ||
|
||
R_API void r_skiplist_delete(r_skiplist* list, void* data) { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
int i; | ||
r_skiplist_node *update[kSkipListDepth + 1], *node; | ||
|
||
// Delete node with data as it's payload. | ||
node = list->head; | ||
for (i = list->list_level; i >=0; i--) { | ||
while (node->forward[i] != list->head && | ||
list->compare (node->forward[i]->data, data) < 1) { | ||
node = node->forward[i]; | ||
} | ||
update[i] = node; | ||
} | ||
node = node->forward[0]; | ||
if (node == list->head || !list->compare(node->data, data)) { | ||
return; | ||
} | ||
|
||
This comment has been minimized.
Sorry, something went wrong. |
||
// Update the fwd pointers. | ||
for (i = 0; i <= list->list_level; i++) { | ||
if (update[i]->forward[i] != node) { | ||
break; | ||
} else { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
update[i]->forward[i] = node->forward[i]; | ||
} | ||
} | ||
free (node); | ||
|
||
// Update the level. | ||
while ((list->list_level > 0) && | ||
(list->head->forward[list->list_level] == list->head)) { | ||
list->list_level--; | ||
} | ||
} | ||
|
||
R_API r_skiplist_node* r_skiplist_find(r_skiplist* list, void* data) { | ||
int i; | ||
r_skiplist_node* node = list->head; | ||
for (i = list->list_level; i >= 0; i--) { | ||
while (node->forward[i] != list->head && | ||
list->compare (node->forward[i]->data, data) < 0) { | ||
node = node->forward[i]; | ||
} | ||
} | ||
node = node->forward[0]; | ||
if (node != list->head && list->compare (node->data, data)) { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
return node; | ||
} | ||
return NULL; | ||
} |
1 comment
on commit dc4edf1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@crowell Just to be consistent with the other files, we probably don't need the r_
prefix in the filename of the .c
this will break bindings once again. aka, native bindings will not be able to iterate over the basic blocks