calypso_util.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. #include "metroflip_i.h"
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "calypso_util.h"
  5. #include "../metroflip/metroflip_api.h"
  6. CalypsoElement make_calypso_final_element(
  7. const char* key,
  8. int size,
  9. const char* label,
  10. CalypsoFinalType final_type) {
  11. CalypsoElement final_element = {};
  12. final_element.type = CALYPSO_ELEMENT_TYPE_FINAL;
  13. final_element.final = malloc(sizeof(CalypsoFinalElement));
  14. final_element.final->size = size;
  15. final_element.final->final_type = final_type;
  16. strncpy(final_element.final->key, key, 36);
  17. strncpy(final_element.final->label, label, 64);
  18. return final_element;
  19. }
  20. CalypsoElement make_calypso_bitmap_element(const char* key, int size, CalypsoElement* elements) {
  21. CalypsoElement bitmap_element = {};
  22. bitmap_element.type = CALYPSO_ELEMENT_TYPE_BITMAP;
  23. bitmap_element.bitmap = malloc(sizeof(CalypsoBitmapElement));
  24. bitmap_element.bitmap->size = size;
  25. bitmap_element.bitmap->elements = malloc(size * sizeof(CalypsoElement));
  26. for(int i = 0; i < size; i++) {
  27. bitmap_element.bitmap->elements[i] = elements[i];
  28. }
  29. strncpy(bitmap_element.bitmap->key, key, 36);
  30. return bitmap_element;
  31. }
  32. CalypsoElement
  33. make_calypso_container_element(const char* key, int size, CalypsoElement* elements) {
  34. CalypsoElement container_element = {};
  35. container_element.type = CALYPSO_ELEMENT_TYPE_CONTAINER;
  36. container_element.container = malloc(sizeof(CalypsoContainerElement));
  37. container_element.container->size = size;
  38. container_element.container->elements = malloc(size * sizeof(CalypsoElement));
  39. for(int i = 0; i < size; i++) {
  40. container_element.container->elements[i] = elements[i];
  41. }
  42. strncpy(container_element.container->key, key, 36);
  43. return container_element;
  44. }
  45. CalypsoElement make_calypso_repeater_element(const char* key, int size, CalypsoElement element) {
  46. CalypsoElement repeater_element = {};
  47. repeater_element.type = CALYPSO_ELEMENT_TYPE_REPEATER;
  48. repeater_element.repeater = malloc(sizeof(CalypsoRepeaterElement));
  49. repeater_element.repeater->size = size;
  50. repeater_element.repeater->element = element;
  51. strncpy(repeater_element.repeater->key, key, 36);
  52. return repeater_element;
  53. }
  54. void free_calypso_element(CalypsoElement* element) {
  55. if(element->type == CALYPSO_ELEMENT_TYPE_FINAL) {
  56. free(element->final);
  57. } else if(element->type == CALYPSO_ELEMENT_TYPE_BITMAP) {
  58. for(int i = 0; i < element->bitmap->size; i++) {
  59. free_calypso_element(&element->bitmap->elements[i]);
  60. }
  61. free(element->bitmap->elements);
  62. free(element->bitmap);
  63. } else if(element->type == CALYPSO_ELEMENT_TYPE_CONTAINER) {
  64. for(int i = 0; i < element->container->size; i++) {
  65. free_calypso_element(&element->container->elements[i]);
  66. }
  67. free(element->container->elements);
  68. free(element->container);
  69. } else if(element->type == CALYPSO_ELEMENT_TYPE_REPEATER) {
  70. free_calypso_element(&element->repeater->element);
  71. free(element->repeater);
  72. }
  73. }
  74. void free_calypso_structure(CalypsoApp* structure) {
  75. for(int i = 0; i < structure->container->size; i++) {
  76. free_calypso_element(&structure->container->elements[i]);
  77. }
  78. free(structure->container->elements);
  79. free(structure->container);
  80. free(structure);
  81. }
  82. int* get_bitmap_positions(const char* binary_string, int* count) {
  83. int length = strlen(binary_string);
  84. int* positions = malloc(length * sizeof(int));
  85. int pos_index = 0;
  86. for(int i = 0; i < length; i++) {
  87. if(binary_string[length - 1 - i] == '1') {
  88. positions[pos_index++] = i;
  89. }
  90. }
  91. *count = pos_index;
  92. return positions;
  93. }
  94. int is_bit_present(int* positions, int count, int bit) {
  95. for(int i = 0; i < count; i++) {
  96. if(positions[i] == bit) {
  97. return 1;
  98. }
  99. }
  100. return 0;
  101. }
  102. bool is_calypso_subnode_present(
  103. const char* binary_string,
  104. const char* key,
  105. CalypsoBitmapElement* bitmap) {
  106. char bit_slice[bitmap->size + 1];
  107. strncpy(bit_slice, binary_string, bitmap->size);
  108. bit_slice[bitmap->size] = '\0';
  109. int count = 0;
  110. int* positions = get_bitmap_positions(bit_slice, &count);
  111. int offset = bitmap->size;
  112. for(int i = 0; i < count; i++) {
  113. CalypsoElement* element = &bitmap->elements[positions[i]];
  114. if(element->type == CALYPSO_ELEMENT_TYPE_FINAL) {
  115. if(strcmp(element->final->key, key) == 0) {
  116. free(positions);
  117. return true;
  118. }
  119. offset += element->final->size;
  120. } else {
  121. if(strcmp(element->bitmap->key, key) == 0) {
  122. free(positions);
  123. return true;
  124. }
  125. int sub_binary_string_size = element->bitmap->size;
  126. char bit_slice[sub_binary_string_size + 1];
  127. strncpy(bit_slice, binary_string, sub_binary_string_size);
  128. bit_slice[sub_binary_string_size] = '\0';
  129. if(is_calypso_subnode_present(binary_string + offset, key, element->bitmap)) {
  130. free(positions);
  131. return true;
  132. }
  133. offset += element->bitmap->size;
  134. }
  135. }
  136. free(positions);
  137. return false;
  138. }
  139. bool is_calypso_node_present(const char* binary_string, const char* key, CalypsoApp* structure) {
  140. int offset = 0;
  141. for(int i = 0; i < structure->container->size; i++) {
  142. if(structure->container->elements[i].type == CALYPSO_ELEMENT_TYPE_FINAL) {
  143. if(strcmp(structure->container->elements[i].final->key, key) == 0) {
  144. return true;
  145. }
  146. offset += structure->container->elements[i].final->size;
  147. } else {
  148. if(strcmp(structure->container->elements[i].bitmap->key, key) == 0) {
  149. return true;
  150. }
  151. int sub_binary_string_size = structure->container->elements[i].bitmap->size;
  152. char bit_slice[sub_binary_string_size + 1];
  153. strncpy(bit_slice, binary_string, sub_binary_string_size);
  154. bit_slice[sub_binary_string_size] = '\0';
  155. if(is_calypso_subnode_present(
  156. binary_string + offset, key, structure->container->elements[i].bitmap)) {
  157. return true;
  158. }
  159. offset += structure->container->elements[i].bitmap->size;
  160. }
  161. }
  162. return false;
  163. }
  164. int get_calypso_subnode_offset(
  165. const char* binary_string,
  166. const char* key,
  167. CalypsoElement* elem,
  168. bool* found) {
  169. // recursive function to get the offset of a subnode in a calypso binary string
  170. if(elem->type == CALYPSO_ELEMENT_TYPE_FINAL) {
  171. if(strcmp(elem->final->key, key) == 0) {
  172. *found = true;
  173. return 0;
  174. }
  175. return elem->final->size;
  176. } else if(elem->type == CALYPSO_ELEMENT_TYPE_BITMAP) {
  177. CalypsoBitmapElement* bitmap = elem->bitmap;
  178. char bit_slice[bitmap->size + 1];
  179. strncpy(bit_slice, binary_string, bitmap->size);
  180. bit_slice[bitmap->size] = '\0';
  181. int count = 0;
  182. int* positions = get_bitmap_positions(bit_slice, &count);
  183. bool f = false;
  184. int count_offset = bitmap->size;
  185. for(int i = 0; i < count; i++) {
  186. CalypsoElement element = bitmap->elements[positions[i]];
  187. count_offset +=
  188. get_calypso_subnode_offset(binary_string + count_offset, key, &element, &f);
  189. if(f) {
  190. *found = true;
  191. free(positions);
  192. return count_offset;
  193. }
  194. }
  195. free(positions);
  196. return count_offset;
  197. } else if(elem->type == CALYPSO_ELEMENT_TYPE_CONTAINER) {
  198. // same as bitmap but without bitmap at the beginning
  199. CalypsoContainerElement* container = elem->container;
  200. int count_offset = 0;
  201. bool f = false;
  202. for(int i = 0; i < container->size; i++) {
  203. CalypsoElement element = container->elements[i];
  204. count_offset +=
  205. get_calypso_subnode_offset(binary_string + count_offset, key, &element, &f);
  206. if(f) {
  207. *found = true;
  208. return count_offset;
  209. }
  210. }
  211. return count_offset;
  212. } else if(elem->type == CALYPSO_ELEMENT_TYPE_REPEATER) {
  213. // same as bitmap but instead of a bitmap, we have the count of how many times to repeat the inner element
  214. CalypsoRepeaterElement* repeater = elem->repeater;
  215. char bit_slice[repeater->size + 1];
  216. strncpy(bit_slice, binary_string, repeater->size);
  217. bit_slice[repeater->size] = '\0';
  218. int C = bit_slice_to_dec(bit_slice, 0, repeater->size - 1);
  219. int count_offset = repeater->size;
  220. bool f = false;
  221. for(int i = 0; i < C; i++) {
  222. count_offset += get_calypso_subnode_offset(
  223. binary_string + count_offset, key, &repeater->element, &f);
  224. if(f) {
  225. *found = true;
  226. return count_offset;
  227. }
  228. }
  229. }
  230. return 0;
  231. }
  232. int get_calypso_node_offset(const char* binary_string, const char* key, CalypsoApp* structure) {
  233. CalypsoElement* element = malloc(sizeof(CalypsoElement));
  234. element->type = CALYPSO_ELEMENT_TYPE_CONTAINER;
  235. element->container = structure->container;
  236. bool found;
  237. int offset = get_calypso_subnode_offset(binary_string, key, element, &found);
  238. if(!found) {
  239. FURI_LOG_E("Metroflip:Scene:Calypso", "Key %s not found in calypso structure", key);
  240. }
  241. free(element);
  242. return offset;
  243. }
  244. int get_calypso_subnode_size(const char* key, CalypsoElement* element) {
  245. if(element->type == CALYPSO_ELEMENT_TYPE_FINAL) {
  246. if(strcmp(element->final->key, key) == 0) {
  247. return element->final->size;
  248. }
  249. } else if(element->type == CALYPSO_ELEMENT_TYPE_BITMAP) {
  250. if(strcmp(element->bitmap->key, key) == 0) {
  251. return element->bitmap->size;
  252. }
  253. for(int i = 0; i < element->bitmap->size; i++) {
  254. int size = get_calypso_subnode_size(key, &element->bitmap->elements[i]);
  255. if(size != 0) {
  256. return size;
  257. }
  258. }
  259. } else if(element->type == CALYPSO_ELEMENT_TYPE_CONTAINER) {
  260. if(strcmp(element->container->key, key) == 0) {
  261. return element->container->size;
  262. }
  263. for(int i = 0; i < element->container->size; i++) {
  264. int size = get_calypso_subnode_size(key, &element->container->elements[i]);
  265. if(size != 0) {
  266. return size;
  267. }
  268. }
  269. } else if(element->type == CALYPSO_ELEMENT_TYPE_REPEATER) {
  270. if(strcmp(element->repeater->key, key) == 0) {
  271. return element->repeater->size;
  272. }
  273. int size = get_calypso_subnode_size(key, &element->repeater->element);
  274. if(size != 0) {
  275. return size;
  276. }
  277. }
  278. return 0;
  279. }
  280. int get_calypso_node_size(const char* key, CalypsoApp* structure) {
  281. CalypsoElement* element = malloc(sizeof(CalypsoElement));
  282. element->type = CALYPSO_ELEMENT_TYPE_CONTAINER;
  283. element->container = structure->container;
  284. int count = get_calypso_subnode_size(key, element);
  285. free(element);
  286. return count;
  287. }
  288. CALYPSO_CARD_TYPE guess_card_type(int country_num, int network_num) {
  289. switch(country_num) {
  290. case 56:
  291. switch(network_num) {
  292. case 1:
  293. return CALYPSO_CARD_MOBIB;
  294. default:
  295. return CALYPSO_CARD_UNKNOWN;
  296. }
  297. case 124:
  298. switch(network_num) {
  299. case 1:
  300. return CALYPSO_CARD_OPUS;
  301. default:
  302. return CALYPSO_CARD_UNKNOWN;
  303. }
  304. case 131:
  305. return CALYPSO_CARD_VIVA;
  306. case 250:
  307. switch(network_num) {
  308. case 0:
  309. return CALYPSO_CARD_PASSPASS;
  310. case 64:
  311. return CALYPSO_CARD_TAM; // Montpellier
  312. case 149:
  313. return CALYPSO_CARD_TRANSPOLE; // Lille
  314. case 502:
  315. return CALYPSO_CARD_OURA;
  316. case 901:
  317. return CALYPSO_CARD_NAVIGO;
  318. case 908:
  319. return CALYPSO_CARD_KORRIGO;
  320. case 916:
  321. return CALYPSO_CARD_TISSEO;
  322. case 920:
  323. return CALYPSO_CARD_ENVIBUS;
  324. case 921:
  325. return CALYPSO_CARD_GIRONDE;
  326. default:
  327. return CALYPSO_CARD_UNKNOWN;
  328. }
  329. case 376:
  330. return CALYPSO_CARD_RAVKAV;
  331. default:
  332. return CALYPSO_CARD_UNKNOWN;
  333. }
  334. }
  335. const char* get_country_string(int country_num) {
  336. switch(country_num) {
  337. case 56:
  338. return "Belgium";
  339. case 124:
  340. return "Canada";
  341. case 131:
  342. return "Portugal";
  343. case 250:
  344. return "France";
  345. case 376:
  346. return "Israel";
  347. default: {
  348. char* country = malloc(4 * sizeof(char));
  349. snprintf(country, 4, "%d", country_num);
  350. return country;
  351. }
  352. }
  353. }
  354. const char* get_network_string(CALYPSO_CARD_TYPE card_type) {
  355. switch(card_type) {
  356. case CALYPSO_CARD_MOBIB:
  357. return "Mobib";
  358. case CALYPSO_CARD_OPUS:
  359. return "Opus";
  360. case CALYPSO_CARD_VIVA:
  361. return "Viva";
  362. case CALYPSO_CARD_PASSPASS:
  363. return "PassPass";
  364. case CALYPSO_CARD_TAM:
  365. return "TAM";
  366. case CALYPSO_CARD_OURA:
  367. return "Oura";
  368. case CALYPSO_CARD_NAVIGO:
  369. return "IDFM";
  370. case CALYPSO_CARD_KORRIGO:
  371. return "KorriGo";
  372. case CALYPSO_CARD_TISSEO:
  373. return "Tisseo";
  374. case CALYPSO_CARD_ENVIBUS:
  375. return "Envibus";
  376. case CALYPSO_CARD_GIRONDE:
  377. return "Gironde";
  378. case CALYPSO_CARD_RAVKAV:
  379. return "Rav-Kav";
  380. default:
  381. return "Unknown";
  382. }
  383. }