Skip to content

Commit

Permalink
Move binary search of enum tables to Mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
Rot127 committed Jul 24, 2024
1 parent 15fb32f commit 9dc993d
Show file tree
Hide file tree
Showing 8 changed files with 350 additions and 333 deletions.
40 changes: 40 additions & 0 deletions Mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,43 @@ void map_set_alias_id(MCInst *MI, const SStream *O, const name_map *alias_mnem_i
MI->flat_insn->alias_id = name2id(alias_mnem_id_map, map_size, alias_mnem);
}

/// Does a binary search over the given map and searches for @id.
/// If @id exists in @map, it sets @found to true and returns
/// the value for the @id.
/// Otherwise, @found is set to false and it returns -1.
///
/// Of course it assumes the map is sorted.
int enum_map_bin_search(const cs_enum_id_map *map, size_t map_len, const char *id, bool *found)
{
size_t l = 0;
size_t r = map_len;
size_t id_len = strlen(id);

while (l <= r) {
size_t m = (l + r) / 2;
size_t j = 0;
size_t i = 0;
size_t entry_len = strlen(map[m].str);

while (j < entry_len && i < id_len && id[i] == map[m].str[j]) {
++j, ++i;
}
if (i == id_len && j == entry_len) {
*found = true;
return map[m].val;
}

if (id[i] < map[m].str[j]) {
r = m - 1;
} else if (id[i] > map[m].str[j]) {
l = m + 1;
}
if (m == 0 || (l + r) / 2 >= map_len) {
// Break before we go out of bounds.
break;
}
}
*found = false;
return -1;
}

22 changes: 22 additions & 0 deletions Mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,26 @@ bool map_use_alias_details(const MCInst *MI);

void map_set_alias_id(MCInst *MI, const SStream *O, const name_map *alias_mnem_id_map, int map_size);

/// Mapping from Capstone enumeration identifiers and their values.
///
/// This map MUST BE sorted to allow binary searches.
/// Please always ensure the map is sorted after you added a value.
///
/// You can sort the map with Python.
/// Copy the map into a file and run:
///
/// ```python
/// with open("/tmp/file_with_map_entries") as f:
/// text = f.readlines()
///
/// text.sort()
/// print(''.join(text))
/// ```
typedef struct {
const char *str; ///< The name of the enumeration identifier
int val; ///< The value of the identifier
} cs_enum_id_map;

int enum_map_bin_search(const cs_enum_id_map *map, size_t map_len, const char *id, bool *found);

#endif // CS_MAPPING_H
2 changes: 1 addition & 1 deletion suite/cstest/include/test_compare.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ typedef int32_t tbool;
#define compare_enum_ret(actual, expected, ret_val) \
if (expected) { \
bool found = false; \
uint32_t eval = cs_enum_get_val(expected, &found); \
uint32_t eval = enum_map_bin_search(cs_enum_map, ARR_SIZE(cs_enum_map), expected, &found); \
if (expected && (actual != eval || !found)) { \
fprintf(stderr, \
#actual " != " #expected ": %" PRId32 \
Expand Down
Loading

0 comments on commit 9dc993d

Please sign in to comment.