6 #define _R_MAP(r, max) ArrayList r; STATIC_INIT(r) { AL_NEW(r, max, NULL, e); } 7 #define _R_GET(r, i) AL_gete(r, i) 8 #define _R_SET(r, i, e) AL_sete(r, i, e) 9 #define _R_DEL(r) AL_DELETE(r) 11 #define _R_MAP(r, max) entity r[max] 12 #define _R_GET(r, i) r[i] 13 #define _R_SET(r, i, e) r[i] = e 17 #define REGISTRY_MAX(id) id##_MAX 18 #define REGISTRY_COUNT(id) id##_COUNT 26 #define REGISTRY(id, max) \ 27 void Register##id(); \ 28 ACCUMULATE void REGISTRY_DEPENDS_(id) {} \ 29 REGISTRY_BEGIN(id) {} \ 31 void _Register##id() {} \ 33 void Register##id() { if (id##_state) return; id##_state = 1; REGISTRY_DEPENDS_(id); REGISTRY_BEGIN_(id); _Register##id(); id##_state = 2; REGISTRY_END_(id); } \ 34 const int id##_MAX = max; \ 36 noref entity id##_first, id##_last; \ 37 _R_MAP(_##id, id##_MAX); \ 38 SHUTDOWN(id) { _R_DEL(_##id); } \ 40 #define REGISTRY_DEFINE_GET(id, null) \ 41 entity id##_from(int i) { if (i >= 0 && i < id##_COUNT) { entity e = _R_GET(_##id, i); if (e) return e; } return null; } 43 #define REGISTRY_GET(id, i) id##_from(i) 46 #define REGISTRY_DEPENDS(id, dep) void Register##dep(); void REGISTRY_DEPENDS_(id) { Register##dep(); } 47 #define REGISTRY_DEPENDS_(id) Register##id##_Depends() 50 #define REGISTRY_BEGIN(id) ACCUMULATE void REGISTRY_BEGIN_(id) { noref void() f = Register##id; } void REGISTRY_BEGIN_(id) 51 #define REGISTRY_BEGIN_(id) Register##id##_First() 54 #define REGISTRY_END(id) ACCUMULATE void REGISTRY_END_(id) { noref void() f = Register##id; } void REGISTRY_END_(id) 55 #define REGISTRY_END_(id) Register##id##_Done() 67 LOG_FATALF(
"Registry capacity exceeded (%d)", _max);
87 #define REGISTER(...) EVAL_REGISTER(OVERLOAD_(REGISTER, __VA_ARGS__)) 88 #define EVAL_REGISTER(...) __VA_ARGS__ 89 #define REGISTER_5(registry, ns, id, fld, inst) REGISTER_4(registry, ns##_##id, fld, inst) 90 #define REGISTER_4(registry, id, fld, inst) \ 92 REGISTER_INIT(id) {} \ 93 void Register_##id() \ 97 _regCheck(registry##_COUNT, registry##_MAX); \ 99 this.registered_id = #id; \ 100 REGISTRY_PUSH(registry, fld, this); \ 102 Register_##id##_init(this); \ 104 ACCUMULATE_FUNCTION(_Register##registry, Register_##id) \ 107 #define REGISTRY_PUSH(registry, fld, it) MACRO_BEGIN \ 108 it.fld = registry##_COUNT; \ 109 _R_SET(_##registry, registry##_COUNT, it); \ 110 ++registry##_COUNT; \ 111 if (!registry##_first) registry##_first = it; \ 112 if (registry##_last) registry##_last.REGISTRY_NEXT = it; \ 113 registry##_last = it; \ 116 #define REGISTRY_RESERVE(registry, fld, id, suffix) MACRO_BEGIN \ 117 entity e = new_pure(registry_reserved); \ 118 e.registered_id = #id "/" #suffix; \ 119 REGISTRY_PUSH(registry, fld, e); \ 122 #define REGISTER_INIT(id) ACCUMULATE void Register_##id##_init(entity this) 125 #define REGISTRY_NEXT enemy 128 #define REGISTRY_SORT(...) EVAL_REGISTRY_SORT(OVERLOAD(REGISTRY_SORT, __VA_ARGS__)) 129 #define EVAL_REGISTRY_SORT(...) __VA_ARGS__ 130 #define REGISTRY_SORT_1(id) REGISTRY_SORT_2(id, 0) 131 #define REGISTRY_SORT_2(id, skip) \ 132 void _REGISTRY_SWAP_##id(int i, int j, entity pass) \ 134 i += skip; j += skip; \ 136 entity a = _R_GET(_##id, i), b = _R_GET(_##id, j); \ 137 _R_SET(_##id, i, b); \ 138 _R_SET(_##id, j, a); \ 140 entity a_next = a.REGISTRY_NEXT, b_next = b.REGISTRY_NEXT; \ 141 a.REGISTRY_NEXT = b_next; \ 142 b.REGISTRY_NEXT = a_next; \ 144 if (i == 0) id##_first = b; \ 145 else _R_GET(_##id, i - 1).REGISTRY_NEXT = b; \ 147 if (j == 0) id##_first = a; \ 148 else _R_GET(_##id, j - 1).REGISTRY_NEXT = a; \ 150 int _REGISTRY_CMP_##id(int i, int j, entity pass) \ 152 i += skip; j += skip; \ 153 string a = _R_GET(_##id, i).registered_id; \ 154 string b = _R_GET(_##id, j).registered_id; \ 155 return strcmp(a, b); \ 157 STATIC_INIT(Registry_sort_##id) \ 159 heapsort(id##_COUNT - (skip), _REGISTRY_SWAP_##id, _REGISTRY_CMP_##id, NULL); \ 162 #define REGISTRY_HASH(id) Registry_hash_##id 172 #define Registry_send(id, hash) 175 #define REGISTRY_CHECK(id) \ 176 string REGISTRY_HASH(id); \ 177 STATIC_INIT(Registry_check_##id) \ 181 FOREACH(id, true, s = strcat(s, ":", it.registered_id)); \ 182 s = substring(s, 1, -1); \ 183 string h = REGISTRY_HASH(id) = strzone(digest_hex("MD4", s)); \ 184 LOG_DEBUGF(#id ": %s\n[%s]", h, s); \ 186 void Registry_check(string r, string sv) \ 190 string cl = REGISTRY_HASH(id); \ 193 LOG_FATALF("client/server mismatch (%s).\nCL: %s\nSV: %s", r, cl, sv); \ 197 void Registry_send_all() { Registry_send(#id, REGISTRY_HASH(id)); } \ 199 #define _REGISTER_REGISTRY(id, str) \ 200 ACCUMULATE_FUNCTION(__static_init_1, Register##id) \ 201 CLASS(id##Registry, Object) \ 202 ATTRIB(id##Registry, m_name, string, str); \ 203 ATTRIB(id##Registry, REGISTRY_NEXT, entity, id##_first); \ 204 METHOD(id##Registry, m_reload, void()); \ 205 ENDCLASS(id##Registry) \ 206 REGISTER(Registries, REGISTRY, id, m_id, NEW(id##Registry)); \ 207 METHOD(id##Registry, m_reload, void()) { \ 212 #define REGISTER_REGISTRY(id) _REGISTER_REGISTRY(id, #id) #define Registry_send(id, hash)
string registered_id
registered item identifier
ERASEABLE ACCUMULATE void Registry_check(string r, string sv)
void _regCheck(int i, int _max)
#define REGISTRY_NEXT
internal next pointer
#define REGISTRY(id, max)
Declare a new registry.
ERASEABLE ACCUMULATE void Registry_send_all()