| 1 | #include <stddef.h> |
| 2 | #include <stdint.h> |
| 3 | #include <stdbool.h> |
| 4 | #include <lib/guid.h> |
| 5 | #include <lib/misc.h> |
| 6 | |
| 7 | bool is_valid_guid(const char *s) { |
| 8 | for (size_t i = 0; ; i++) { |
| 9 | switch (i) { |
| 10 | case 8: |
| 11 | case 13: |
| 12 | case 18: |
| 13 | case 23: |
| 14 | if (s[i] != '-') |
| 15 | return false; |
| 16 | break; |
| 17 | case 36: |
| 18 | return s[i] == 0; |
| 19 | default: |
| 20 | if (digit_to_int(s[i]) == -1) |
| 21 | return false; |
| 22 | break; |
| 23 | } |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | static void guid_convert_le_cluster(uint8_t *dest, const char *s, int len) { |
| 28 | size_t p = 0; |
| 29 | for (int i = len - 1; i >= 0; i--) { |
| 30 | int val = digit_to_int(s[i]); |
| 31 | |
| 32 | i % 2 ? (dest[p] = val) : (dest[p++] |= val << 4); |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | static void guid_convert_be_cluster(uint8_t *dest, const char *s, int len) { |
| 37 | size_t p = 0; |
| 38 | for (int i = 0; i < len; i++) { |
| 39 | int val = digit_to_int(s[i]); |
| 40 | |
| 41 | i % 2 ? (dest[p++] |= val) : (dest[p] = val << 4); |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | bool string_to_guid_be(struct guid *guid, const char *s) { |
| 46 | if (!is_valid_guid(s)) |
| 47 | return false; |
| 48 | |
| 49 | guid_convert_be_cluster((uint8_t *)guid + 0, s + 0, 8); |
| 50 | guid_convert_be_cluster((uint8_t *)guid + 4, s + 9, 4); |
| 51 | guid_convert_be_cluster((uint8_t *)guid + 6, s + 14, 4); |
| 52 | guid_convert_be_cluster((uint8_t *)guid + 8, s + 19, 4); |
| 53 | guid_convert_be_cluster((uint8_t *)guid + 10, s + 24, 12); |
| 54 | |
| 55 | return true; |
| 56 | } |
| 57 | |
| 58 | bool string_to_guid_mixed(struct guid *guid, const char *s) { |
| 59 | if (!is_valid_guid(s)) |
| 60 | return false; |
| 61 | |
| 62 | guid_convert_le_cluster((uint8_t *)guid + 0, s + 0, 8); |
| 63 | guid_convert_le_cluster((uint8_t *)guid + 4, s + 9, 4); |
| 64 | guid_convert_le_cluster((uint8_t *)guid + 6, s + 14, 4); |
| 65 | guid_convert_be_cluster((uint8_t *)guid + 8, s + 19, 4); |
| 66 | guid_convert_be_cluster((uint8_t *)guid + 10, s + 24, 12); |
| 67 | |
| 68 | return true; |
| 69 | } |
| 70 | |
| 71 | static void uint_to_hex(uint32_t num, char *dest, int len) { |
| 72 | const char digits[] = "0123456789abcdef"; |
| 73 | for (int i = 0; i < len; i++) { |
| 74 | dest[i] = digits[(num >> ((len - 1 - i) * 4)) & 0xf]; |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | void guid_to_string(const struct guid *guid, char *s) { |
| 79 | uint_to_hex(guid->a, s, 8); |
| 80 | s[8] = '-'; |
| 81 | uint_to_hex(guid->b, s + 9, 4); |
| 82 | s[13] = '-'; |
| 83 | uint_to_hex(guid->c, s + 14, 4); |
| 84 | s[18] = '-'; |
| 85 | uint_to_hex(guid->d[0], s + 19, 2); |
| 86 | uint_to_hex(guid->d[1], s + 21, 2); |
| 87 | s[23] = '-'; |
| 88 | uint_to_hex(guid->d[2], s + 24, 2); |
| 89 | uint_to_hex(guid->d[3], s + 26, 2); |
| 90 | uint_to_hex(guid->d[4], s + 28, 2); |
| 91 | uint_to_hex(guid->d[5], s + 30, 2); |
| 92 | uint_to_hex(guid->d[6], s + 32, 2); |
| 93 | uint_to_hex(guid->d[7], s + 34, 2); |
| 94 | s[36] = 0; |
| 95 | } |