2
0

uci.uc 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. let mocklib = global.mocklib;
  2. let byte = (str, off) => {
  3. let v = ord(str, off);
  4. return length(v) ? v[0] : v;
  5. };
  6. let hash = (s) => {
  7. let h = 7;
  8. for (let i = 0; i < length(s); i++)
  9. h = h * 31 + byte(s, i);
  10. return h;
  11. };
  12. let id = (config, t, n) => {
  13. while (true) {
  14. let id = sprintf('cfg%08x', hash(t + n));
  15. if (!exists(config, id))
  16. return id;
  17. n++;
  18. }
  19. };
  20. let fixup_config = (config) => {
  21. let rv = {};
  22. let n_section = 0;
  23. for (let stype in config) {
  24. switch (type(config[stype])) {
  25. case 'object':
  26. config[stype] = [ config[stype] ];
  27. /* fall through */
  28. case 'array':
  29. for (let idx, sobj in config[stype]) {
  30. let sid, anon;
  31. if (exists(sobj, '.name') && !exists(rv, sobj['.name'])) {
  32. sid = sobj['.name'];
  33. anon = false;
  34. }
  35. else {
  36. sid = id(rv, stype, idx);
  37. anon = true;
  38. }
  39. rv[sid] = {
  40. '.index': n_section++,
  41. ...sobj,
  42. '.name': sid,
  43. '.type': stype,
  44. '.anonymous': anon
  45. };
  46. }
  47. break;
  48. }
  49. }
  50. for (let n, sid in sort(keys(rv), (a, b) => rv[a]['.index'] - rv[b]['.index']))
  51. rv[sid]['.index'] = n;
  52. return rv;
  53. };
  54. return {
  55. cursor: () => ({
  56. _configs: {},
  57. load: function(file) {
  58. let basename = replace(file, /^.+\//, ''),
  59. path = sprintf("uci/%s.json", basename),
  60. mock = mocklib.read_json_file(path);
  61. if (!mock || mock != mock) {
  62. mocklib.I("No configuration fixture defined for uci package %s.", file);
  63. mocklib.I("Provide a mock configuration through the following JSON file:\n%s\n", path);
  64. return null;
  65. }
  66. this._configs[basename] = fixup_config(mock);
  67. },
  68. _get_section: function(config, section) {
  69. if (!exists(this._configs, config)) {
  70. this.load(config);
  71. if (!exists(this._configs, config))
  72. return null;
  73. }
  74. let cfg = this._configs[config],
  75. extended = match(section, "^@([A-Za-z0-9_-]+)\[(-?[0-9]+)\]$");
  76. if (extended) {
  77. let stype = extended[1],
  78. sindex = +extended[2];
  79. let sids = sort(
  80. filter(keys(cfg), sid => cfg[sid]['.type'] == stype),
  81. (a, b) => cfg[a]['.index'] - cfg[b]['.index']
  82. );
  83. if (sindex < 0)
  84. sindex = sids.length + sindex;
  85. return cfg[sids[sindex]];
  86. }
  87. return cfg[section];
  88. },
  89. get: function(config, section, option) {
  90. let sobj = this._get_section(config, section);
  91. if (option && index(option, ".") == 0)
  92. return null;
  93. else if (sobj && option)
  94. return sobj[option];
  95. else if (sobj)
  96. return sobj[".type"];
  97. },
  98. get_all: function(config, section) {
  99. return section ? this._get_section(config, section) : this._configs[config];
  100. },
  101. foreach: function(config, stype, cb) {
  102. let rv = false;
  103. if (exists(this._configs, config)) {
  104. let cfg = this._configs[config],
  105. sids = sort(keys(cfg), (a, b) => cfg[a]['.index'] - cfg[b]['.index']);
  106. for (let i, sid in sids) {
  107. if (stype == null || cfg[sid]['.type'] == stype) {
  108. if (cb({ ...(cfg[sid]) }) === false)
  109. break;
  110. rv = true;
  111. }
  112. }
  113. }
  114. return rv;
  115. }
  116. })
  117. };