parse.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * libuci - Library for the Unified Configuration Interface
  3. * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License version 2.1
  7. * as published by the Free Software Foundation
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. */
  14. #include <string.h>
  15. #include <stdint.h>
  16. #include "uci.h"
  17. void uci_parse_section(struct uci_section *s, const struct uci_parse_option *opts,
  18. int n_opts, struct uci_option **tb)
  19. {
  20. struct uci_element *e;
  21. memset(tb, 0, n_opts * sizeof(*tb));
  22. uci_foreach_element(&s->options, e) {
  23. struct uci_option *o = uci_to_option(e);
  24. int i;
  25. for (i = 0; i < n_opts; i++) {
  26. if (tb[i])
  27. continue;
  28. if (strcmp(opts[i].name, o->e.name) != 0)
  29. continue;
  30. if (opts[i].type != o->type)
  31. continue;
  32. /* match found */
  33. tb[i] = o;
  34. break;
  35. }
  36. }
  37. }
  38. //-----------------------------------------------------------------------------
  39. // MurmurHashNeutral2, by Austin Appleby
  40. // Same as MurmurHash2, but endian- and alignment-neutral.
  41. static uint32_t hash_murmur2(uint32_t h, const void * key, int len)
  42. {
  43. const unsigned char * data = key;
  44. const uint32_t m = 0x5bd1e995;
  45. const int r = 24;
  46. while(len >= 4)
  47. {
  48. unsigned int k;
  49. k = data[0];
  50. k |= data[1] << 8;
  51. k |= data[2] << 16;
  52. k |= data[3] << 24;
  53. k *= m;
  54. k ^= k >> r;
  55. k *= m;
  56. h *= m;
  57. h ^= k;
  58. data += 4;
  59. len -= 4;
  60. }
  61. switch(len)
  62. {
  63. case 3: h ^= data[2] << 16;
  64. /* fall through */
  65. case 2: h ^= data[1] << 8;
  66. /* fall through */
  67. case 1: h ^= data[0];
  68. h *= m;
  69. }
  70. h ^= h >> 13;
  71. h *= m;
  72. h ^= h >> 15;
  73. return h;
  74. }
  75. static uint32_t uci_hash_list(uint32_t h, const struct uci_list *list)
  76. {
  77. const struct uci_element *e;
  78. uci_foreach_element(list, e) {
  79. h = hash_murmur2(h, e->name, strlen(e->name) + 1);
  80. }
  81. return h;
  82. }
  83. uint32_t uci_hash_options(struct uci_option **tb, int n_opts)
  84. {
  85. uint32_t h = 0xdeadc0de;
  86. int i;
  87. for (i = 0; i < n_opts; i++) {
  88. const struct uci_option *o = tb[i];
  89. if (!tb[i])
  90. continue;
  91. h = hash_murmur2(h, o->e.name, strlen(o->e.name) + 1);
  92. h = hash_murmur2(h, &o->type, sizeof(o->type));
  93. switch (tb[i]->type) {
  94. case UCI_TYPE_STRING:
  95. h = hash_murmur2(h, o->v.string, strlen(o->v.string) + 1);
  96. break;
  97. case UCI_TYPE_LIST:
  98. h = uci_hash_list(h, &o->v.list);
  99. break;
  100. }
  101. }
  102. return h;
  103. }