00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef ir_a2b_util_INCLUDED
00022 #define ir_a2b_util_INCLUDED
00023
00024 #include "defs.h"
00025 #include "cxx_memory.h"
00026 #include "errors.h"
00027 #include "x_string.h"
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 namespace ir_a2b {
00094
00095
00096
00097
00098
00099
00100
00101 struct enum2str_tbl_entry_t {
00102 enum2str_tbl_entry_t() { }
00103 enum2str_tbl_entry_t(const enum2str_tbl_entry_t& x) { }
00104 virtual ~enum2str_tbl_entry_t() { }
00105
00106
00107 virtual INT getEnumVal() const = 0;
00108
00109
00110 virtual const char* getStr() const = 0;
00111
00112
00113 static int
00114 cmp(const void * entry1, const void * entry2) {
00115 enum2str_tbl_entry_t* e1 = (enum2str_tbl_entry_t*)entry1;
00116 enum2str_tbl_entry_t* e2 = (enum2str_tbl_entry_t*)entry2;
00117 return ux_strcasecmp(e1->getStr(), e2->getStr());
00118 }
00119
00120 };
00121
00122
00123
00124
00125 struct flag2str_tbl_entry_t {
00126 flag2str_tbl_entry_t() { }
00127 flag2str_tbl_entry_t(const flag2str_tbl_entry_t& x) { }
00128 virtual ~flag2str_tbl_entry_t() { }
00129
00130
00131 virtual UINT64 getFlagVal() const = 0;
00132
00133
00134 virtual const char* getStr() const = 0;
00135
00136
00137 static int
00138 flagcmp(const void * entry1, const void * entry2) {
00139 flag2str_tbl_entry_t* e1 = (flag2str_tbl_entry_t*)entry1;
00140 flag2str_tbl_entry_t* e2 = (flag2str_tbl_entry_t*)entry2;
00141 UINT64 v1 = e1->getFlagVal();
00142 UINT64 v2 = e2->getFlagVal();
00143
00144 if (v1 == v2) {
00145 return 0;
00146 }
00147 else if (v1 < v2) {
00148 return -1;
00149 }
00150 else {
00151 return 1;
00152 }
00153 }
00154
00155
00156 static int
00157 strcmp(const void * entry1, const void * entry2) {
00158 flag2str_tbl_entry_t* e1 = (flag2str_tbl_entry_t*)entry1;
00159 flag2str_tbl_entry_t* e2 = (flag2str_tbl_entry_t*)entry2;
00160 return ux_strcasecmp(e1->getStr(), e2->getStr());
00161 }
00162
00163 };
00164
00165
00166
00167
00168
00169
00170
00171 template <typename ENUM_TBL_ENTRY_T>
00172 void
00173 CheckEnumTable(const char* tablenm, const ENUM_TBL_ENTRY_T* table, INT tablesz)
00174 {
00175
00176
00177 for (INT val = 0; val < tablesz; ++val) {
00178 if (table[val].getEnumVal() != val) {
00179 const char* str = table[val].getStr() ? table[val].getStr() : "";
00180 Fail_FmtAssertion("ir_a2b::CheckEnumTable: Error in table '%s': invalid entry: %d -> { %d %s }", tablenm, val, table[val].getEnumVal(), str);
00181 }
00182 }
00183 }
00184
00185
00186
00187
00188
00189
00190
00191 template <typename FLG_TBL_ENTRY_T>
00192 void
00193 CheckFlagTable(const char* tablenm, const FLG_TBL_ENTRY_T* table, INT tablesz)
00194 {
00195
00196 UINT64 val, prevval = 0;
00197 for (INT i = 0; i < tablesz; ++i) {
00198 val = table[i].getFlagVal();
00199 if (i != 0 && !(prevval < val)) {
00200 Fail_FmtAssertion("ir_a2b::CheckFlagTable: Error in table '%s': %llx preceeds %llx (out of order)", tablenm, prevval, val);
00201 }
00202 prevval = table[i].getFlagVal();
00203 }
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 template <typename ENUM_TBL_ENTRY_T,
00218 const ENUM_TBL_ENTRY_T* table, INT tablesz>
00219 const char*
00220 MapEnumToStr(const char* tablenm, INT val)
00221 {
00222
00223 static bool isTableChecked = false;
00224 if (!isTableChecked) {
00225 CheckEnumTable(tablenm, table, tablesz);
00226 isTableChecked = true;
00227 }
00228
00229
00230 if (0 <= val && val < tablesz) {
00231 return table[val].getStr();
00232 }
00233 else {
00234 Fail_FmtAssertion("ir_a2b::MapEnumToStr: Error accessing table '%s': no entry for '%d'.", tablenm, val);
00235 }
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245 template <typename ENUM_TBL_ENTRY_T,
00246 const ENUM_TBL_ENTRY_T* table, INT tablesz>
00247 INT
00248 MapStrToEnum(const char* tablenm, const char* str)
00249 {
00250 struct key_t : public enum2str_tbl_entry_t {
00251 key_t(const char* s_) : s(s_) { }
00252 virtual ~key_t() { }
00253
00254 virtual INT getEnumVal() const { return 0; }
00255 virtual const char* getStr() const { return s; }
00256
00257 const char* s;
00258 };
00259
00260
00261 static bool isTableChecked = false;
00262 if (!isTableChecked) {
00263 CheckEnumTable(tablenm, table, tablesz);
00264 isTableChecked = true;
00265 }
00266
00267
00268
00269
00270 static ENUM_TBL_ENTRY_T* Str2EnumTbl = NULL;
00271 if (!Str2EnumTbl) {
00272 Str2EnumTbl = CXX_NEW_ARRAY(ENUM_TBL_ENTRY_T, tablesz, Malloc_Mem_Pool);
00273 memcpy(Str2EnumTbl, table, sizeof(ENUM_TBL_ENTRY_T) * tablesz);
00274 qsort(Str2EnumTbl, tablesz, sizeof(ENUM_TBL_ENTRY_T),
00275 enum2str_tbl_entry_t::cmp);
00276 }
00277
00278
00279 key_t key(str);
00280 ENUM_TBL_ENTRY_T* found =
00281 (ENUM_TBL_ENTRY_T*)bsearch(&key, Str2EnumTbl, tablesz,
00282 sizeof(ENUM_TBL_ENTRY_T),
00283 enum2str_tbl_entry_t::cmp);
00284 FmtAssert(found, ("ir_a2b::MapStrToEnum: Error accessing table '%s': no entry for '%s'.", tablenm, str));
00285 return found->getEnumVal();
00286 }
00287
00288
00289
00290
00291
00292
00293 struct flag_key_t : public flag2str_tbl_entry_t {
00294 flag_key_t(UINT64 flg_, const char* str_) : flg(flg_), str(str_) { }
00295 virtual ~flag_key_t() { }
00296
00297 virtual UINT64 getFlagVal() const { return flg; }
00298 virtual const char* getStr() const { return str; }
00299
00300 UINT64 flg;
00301 const char* str;
00302 };
00303
00304
00305
00306
00307
00308
00309
00310
00311 template <typename FLAG_TBL_ENTRY_T,
00312 const FLAG_TBL_ENTRY_T* table, INT tablesz>
00313 const char*
00314 MapFlagsToStr(const char* tablenm, UINT64 flags)
00315 {
00316
00317 static bool isTableChecked = false;
00318 if (!isTableChecked) {
00319 CheckFlagTable(tablenm, table, tablesz);
00320 isTableChecked = true;
00321 }
00322
00323
00324 static char* buf = NULL;
00325 static UINT bufSz = 256;
00326 if (!buf) {
00327 buf = TYPE_MEM_POOL_ALLOC_N(char, Malloc_Mem_Pool, bufSz);
00328 }
00329
00330
00331 buf[0] = '\0';
00332 UINT curBufLen = 0;
00333 bool isBufEmpty = true;
00334 for (UINT64 curflg = 0x1000000000000000LL; curflg != 0;
00335 curflg = curflg >> 1) {
00336 if ( !(flags & curflg) ) {
00337 continue;
00338 }
00339
00340
00341 flag_key_t key(curflg, NULL);
00342 FLAG_TBL_ENTRY_T* found =
00343 (FLAG_TBL_ENTRY_T*)bsearch(&key, table, tablesz,
00344 sizeof(FLAG_TBL_ENTRY_T),
00345 flag2str_tbl_entry_t::flagcmp);
00346 FmtAssert(found, ("ir_a2b::MapFlagsToStr: Error accessing table '%s': no entry for '%llx'.", tablenm, curflg));
00347
00348
00349 const char* flgstr = found->getStr();
00350 curBufLen += strlen(flgstr);
00351 if (curBufLen+2 > bufSz) {
00352 UINT oldSz = bufSz;
00353 bufSz *= 2;
00354 buf = TYPE_MEM_POOL_REALLOC_N(char, Malloc_Mem_Pool, buf,
00355 oldSz, bufSz);
00356 }
00357 if (!isBufEmpty) {
00358 strcat(buf, ",");
00359 }
00360 strcat(buf, flgstr);
00361 isBufEmpty = false;
00362 }
00363
00364 return buf;
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374 template <typename FLAG_TBL_ENTRY_T,
00375 const FLAG_TBL_ENTRY_T* table, INT tablesz>
00376 UINT64
00377 MapStrToFlags(const char* tablenm, const char* str)
00378 {
00379
00380 static bool isTableChecked = false;
00381 if (!isTableChecked) {
00382 CheckFlagTable(tablenm, table, tablesz);
00383 isTableChecked = true;
00384 }
00385
00386
00387
00388
00389 static FLAG_TBL_ENTRY_T* Str2FlagTbl = NULL;
00390 if (!Str2FlagTbl) {
00391 Str2FlagTbl = CXX_NEW_ARRAY(FLAG_TBL_ENTRY_T, tablesz, Malloc_Mem_Pool);
00392 memcpy(Str2FlagTbl, table, sizeof(FLAG_TBL_ENTRY_T) * tablesz);
00393 qsort(Str2FlagTbl, tablesz, sizeof(FLAG_TBL_ENTRY_T),
00394 flag2str_tbl_entry_t::strcmp);
00395 }
00396
00397 UINT64 flags = 0;
00398
00399
00400
00401 char* flgstr = ux_strdup(str);
00402 for (char* tok = strtok(flgstr, ","); (tok != NULL);
00403 tok = strtok((char*)NULL, ",")) {
00404
00405 flag_key_t key(0, tok);
00406 FLAG_TBL_ENTRY_T* found =
00407 (FLAG_TBL_ENTRY_T*)bsearch(&key, Str2FlagTbl, tablesz,
00408 sizeof(FLAG_TBL_ENTRY_T),
00409 flag2str_tbl_entry_t::strcmp);
00410 if (tok[0] != '\0') {
00411 FmtAssert(found, ("ir_a2b::MapStrToFlags: Error accessing table '%s': no entry for '%s'.", tablenm, tok));
00412 }
00413 flags |= found->getFlagVal();
00414 }
00415 free(flgstr);
00416
00417 return flags;
00418 }
00419
00420
00421 };
00422
00423 #endif