int main(void) { struct atom_table *table; xkb_atom_t atom1, atom2, atom3; table = atom_table_new(); assert(table); assert(atom_text(table, XKB_ATOM_NONE) == NULL); assert(atom_lookup(table, NULL, 0) == XKB_ATOM_NONE); atom1 = INTERN_LITERAL(table, "hello"); assert(atom1 != XKB_ATOM_NONE); assert(atom1 == LOOKUP_LITERAL(table, "hello")); assert(streq(atom_text(table, atom1), "hello")); atom2 = atom_intern(table, "hello", 3, false); assert(atom2 != XKB_ATOM_NONE); assert(atom1 != atom2); assert(streq(atom_text(table, atom2), "hel")); assert(LOOKUP_LITERAL(table, "hel") == atom2); assert(LOOKUP_LITERAL(table, "hell") == XKB_ATOM_NONE); assert(LOOKUP_LITERAL(table, "hello") == atom1); atom3 = atom_intern(table, "", 0, false); assert(atom3 != XKB_ATOM_NONE); assert(LOOKUP_LITERAL(table, "") == atom3); atom_table_free(table); test_random_strings(); return 0; }
static void test_random_strings(void) { struct atom_string { xkb_atom_t atom; char *string; size_t len; }; struct atom_table *table; struct atom_string *arr; int N; xkb_atom_t atom; const char *string; table = atom_table_new(); assert(table); srand(clock()); N = 1 + rand() % 1500; arr = calloc(N, sizeof(*arr)); assert(arr); for (int i = 0; i < N; i++) { random_string(&arr[i].string, &arr[i].len); atom = atom_lookup(table, arr[i].string, arr[i].len); if (atom != XKB_ATOM_NONE) { string = atom_text(table, atom); assert(string); if (arr[i].len != strlen(string) || strncmp(string, arr[i].string, arr[i].len) != 0) { fprintf(stderr, "got a collision, but strings don't match!\n"); fprintf(stderr, "existing length %lu, string %s\n", strlen(string), string); fprintf(stderr, "new length %lu, string %.*s\n", arr[i].len, (int) arr[i].len, arr[i].string); assert(false); } /* OK, got a real collision. */ free(arr[i].string); i--; continue; } arr[i].atom = atom_intern(table, arr[i].string, arr[i].len, false); if (arr[i].atom == XKB_ATOM_NONE) { fprintf(stderr, "failed to intern! len: %lu, string: %.*s\n", arr[i].len, (int) arr[i].len, arr[i].string); assert(false); } } for (int i = 0; i < N; i++) { string = atom_text(table, arr[i].atom); assert(string); if (arr[i].len != strlen(string) || strncmp(string, arr[i].string, arr[i].len) != 0) { fprintf(stderr, "looked-up string doesn't match!\n"); fprintf(stderr, "found length %lu, string %s\n", strlen(string), string); fprintf(stderr, "expected length %lu, string %.*s\n", arr[i].len, (int) arr[i].len, arr[i].string); /* Since this is random, we need to dump the failing data, * so we might have some chance to reproduce. */ fprintf(stderr, "START dump of arr, N=%d\n", N); for (int j = 0; j < N; j++) { fprintf(stderr, "%u\t\t%lu\t\t%.*s\n", arr[i].atom, arr[i].len, (int) arr[i].len, arr[i].string); } fprintf(stderr, "END\n"); assert(false); } } for (int i = 0; i < N; i++) free(arr[i].string); free(arr); atom_table_free(table); }
xkb_atom_t xkb_atom_steal(struct xkb_context *ctx, char *string) { return atom_intern(ctx->atom_table, string, strlen(string), true); }
xkb_atom_t xkb_atom_intern(struct xkb_context *ctx, const char *string, size_t len) { return atom_intern(ctx->atom_table, string, len, false); }