dict.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #include "dict.h"
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <assert.h>
  5. //compare dict_entries by first letter ascending, then by length descending
  6. static int compar_dict_entry(const void *ap, const void *bp) {
  7. const struct dict_entry *a=ap, *b=bp;
  8. unsigned int first_a = (unsigned int)a->str[0];
  9. unsigned int first_b = (unsigned int)b->str[0];
  10. if (first_a < first_b)
  11. return -1;
  12. else if (first_a > first_b)
  13. return 1;
  14. else {
  15. size_t len_a = strlen(a->str);
  16. size_t len_b = strlen(b->str);
  17. if (len_a > len_b)
  18. return -1;
  19. else if (len_a < len_b)
  20. return 1;
  21. else
  22. return 0;
  23. }
  24. }
  25. struct dict *dict_build(void *ctx, const struct dict_entry *entries, size_t count) {
  26. struct dict *dict = talloc_zero(ctx, struct dict);
  27. struct dict_entry *ent;
  28. int i;
  29. if (!count)
  30. return dict;
  31. ent = talloc_array(dict, struct dict_entry, count);
  32. memcpy(ent, entries, count*sizeof(struct dict_entry));
  33. qsort(ent, count, sizeof(*ent), compar_dict_entry);
  34. if (ent->str[0]==0) {
  35. dict->zero = ent;
  36. ent++, count--;
  37. if (count && ent->str[0]==0) {
  38. fprintf(stderr, "dict_entry array contains multiple empty strings\n");
  39. exit(EXIT_FAILURE);
  40. }
  41. }
  42. for (i=1; i<256; i++) {
  43. if (!count)
  44. break;
  45. if (ent->str[0] == (char)i)
  46. dict->by_first_letter[i-1] = ent;
  47. while (count && ent->str[0] == (char)i)
  48. ent++, count--;
  49. }
  50. return dict;
  51. }
  52. struct dict_entry *dict_lookup(struct dict *dict, const char **sp, const char *e) {
  53. struct dict_entry *de;
  54. unsigned int first;
  55. if (*sp >= e)
  56. return NULL;
  57. first = (unsigned int)**sp & 0xFF;
  58. if (!first) {
  59. if (dict->zero)
  60. (*sp)++;
  61. return dict->zero;
  62. }
  63. de = dict->by_first_letter[first-1];
  64. if (!de)
  65. return NULL;
  66. for (;de->str[0]==(char)first; de++) {
  67. const char *s = *sp;
  68. const char *ds = de->str;
  69. for (;;s++,ds++) {
  70. if (!*ds) {
  71. *sp = s;
  72. return de;
  73. }
  74. if (s>=e || *s!=*ds)
  75. break;
  76. }
  77. }
  78. return NULL;
  79. }