diff options
Diffstat (limited to 'testing/misc_tools.h')
-rw-r--r-- | testing/misc_tools.h | 142 |
1 files changed, 141 insertions, 1 deletions
diff --git a/testing/misc_tools.h b/testing/misc_tools.h index 5079e15d..eb09693e 100644 --- a/testing/misc_tools.h +++ b/testing/misc_tools.h | |||
@@ -25,5 +25,145 @@ | |||
25 | #define MISC_TOOLS_H | 25 | #define MISC_TOOLS_H |
26 | 26 | ||
27 | unsigned char * hex_string_to_bin(char hex_string[]); | 27 | unsigned char * hex_string_to_bin(char hex_string[]); |
28 | 28 | ||
29 | /* WARNING(msg) takes a printf()-styled string and prints it | ||
30 | * with some additional details. | ||
31 | * ERROR(exit_status, msg) does the same thing as WARNING(), but | ||
32 | * also exits the program with the given exit status. | ||
33 | * Examples: | ||
34 | * WARNING("<insert warning message here>"); | ||
35 | * int exit_status = 2; | ||
36 | * ERROR(exit_status, "exiting with status %i", exit_status); | ||
37 | */ | ||
38 | #ifdef DEBUG | ||
39 | #include <assert.h> | ||
40 | #include <stdio.h> | ||
41 | #include <string.h> | ||
42 | |||
43 | #define DEBUG_PRINT(str, ...) do { \ | ||
44 | char msg[1000]; \ | ||
45 | sprintf(msg, "%s(): line %d (file %s): %s%%c\n", __FUNCTION__, __LINE__, __FILE__, str); \ | ||
46 | fprintf(stderr, msg, __VA_ARGS__); \ | ||
47 | } while (0) | ||
48 | |||
49 | #define WARNING(...) do { \ | ||
50 | fprintf(stderr, "warning in "); \ | ||
51 | DEBUG_PRINT(__VA_ARGS__, ' '); \ | ||
52 | } while (0) | ||
53 | |||
54 | #define ERROR(exit_status, ...) do { \ | ||
55 | fprintf(stderr, "error in "); \ | ||
56 | DEBUG_PRINT(__VA_ARGS__, ' '); \ | ||
57 | exit(exit_status); \ | ||
58 | } while (0) | ||
59 | #else | ||
60 | #define WARNING(...) | ||
61 | #define ERROR(...) | ||
62 | #endif // DEBUG | ||
63 | |||
64 | /************************Linked List*********************** | ||
65 | * This is a simple linked list implementation, very similar | ||
66 | * to Linux kernel's /include/linux/list.h (which we can't | ||
67 | * use because Tox is GPLv3 and Linux is GPLv2.) | ||
68 | * | ||
69 | * TODO: Make the lists easier to use with some sweat pre- | ||
70 | * processor syntactic sugar. | ||
71 | **********************************************************/ | ||
72 | |||
73 | /* Example usage | ||
74 | |||
75 | This sample program makes a new struct which contains a | ||
76 | character and a tox_list_t. It then prompts a user for | ||
77 | input until he enters q or e. It then adds each character | ||
78 | to the list, and uses a special for loop to print them. | ||
79 | It then removes all the 'z' characters, and prints the list | ||
80 | again. | ||
81 | |||
82 | //Notice that the data to be put in the list *contains* tox_list_t; | ||
83 | //usually, this is the other way around! | ||
84 | typedef struct tox_string { | ||
85 | char c; | ||
86 | tox_list_t tox_lst; //Notice that tox_lst is *NOT* a pointer. | ||
87 | } tox_string_t; | ||
88 | |||
89 | int main() | ||
90 | { | ||
91 | tox_list_t head; | ||
92 | tox_list_new(&head); //initialize head | ||
93 | |||
94 | //input a new character, until user enters q or e | ||
95 | char c = '\0'; | ||
96 | while (c != 'q' && c != 'e') { | ||
97 | scanf("%c", &c); | ||
98 | tox_string_t* tmp = malloc(sizeof(tox_string_t)); | ||
99 | tmp->c = c; | ||
100 | tox_list_add(&head, &tmp->tox_lst); //add it to the list | ||
101 | } | ||
102 | |||
103 | TOX_LIST_FOR_EACH() takes a struct tox_list and a name for a temporary pointer to use in the loop. | ||
104 | |||
105 | TOX_LIST_GET_VALUE() uses magic to return an instance of a structure that contains tox_list_t. | ||
106 | You have to give it a temporary tox_string_t, name of tox_list_t member inside our structure (tox_lst), | ||
107 | and the type of structure to return. | ||
108 | |||
109 | TOX_LIST_FOR_EACH(head, tmp) | ||
110 | printf("%c", TOX_LIST_GET_VALUE(*tmp, tox_lst, tox_string_t).c); | ||
111 | |||
112 | TOX_LIST_FOR_EACH(head, tmp) { | ||
113 | if (TOX_LIST_GET_VALUE(*tmp, tox_lst, tox_string_t).c == 'z') { | ||
114 | //If you delete tmp, you have to quit the loop, or it will go on infinitly. | ||
115 | //This will be fixed later on. | ||
116 | tox_list_remove(tmp); | ||
117 | break; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | printf("\n"); | ||
122 | TOX_LIST_FOR_EACH(head, tmp) | ||
123 | printf("%c", TOX_LIST_GET_VALUE(*tmp, tox_lst, tox_string_t).c); | ||
124 | |||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | */ | ||
129 | |||
130 | #define MEMBER_OFFSET(var_name_in_parent, parent_type) \ | ||
131 | (&(((parent_type*)0)->var_name_in_parent)) | ||
132 | |||
133 | #define GET_PARENT(var, var_name_in_parent, parent_type) \ | ||
134 | (*((parent_type*)((uint64_t)(&(var)) - (uint64_t)(MEMBER_OFFSET(var_name_in_parent, parent_type))))) | ||
135 | |||
136 | #define TOX_LIST_FOR_EACH(lst, tmp_name) \ | ||
137 | for (tox_list_t* tmp_name = lst.next; tmp_name != &lst; tmp_name = tmp_name->next) | ||
138 | |||
139 | #define TOX_LIST_GET_VALUE(tmp_name, name_in_parent, parent_type) GET_PARENT(tmp_name, name_in_parent, parent_type) | ||
140 | |||
141 | typedef struct tox_list { | ||
142 | struct tox_list *prev, *next; | ||
143 | } tox_list_t; | ||
144 | |||
145 | /* Returns a new tox_list_t. */ | ||
146 | static inline void tox_list_new(tox_list_t* lst) { | ||
147 | lst->prev = lst->next = lst; | ||
148 | } | ||
149 | |||
150 | /* Inserts a new tox_lst after lst and returns it. */ | ||
151 | static inline void tox_list_add(tox_list_t* lst, tox_list_t* new_lst) { | ||
152 | tox_list_new(new_lst); | ||
153 | |||
154 | new_lst->next = lst->next; | ||
155 | new_lst->next->prev = new_lst; | ||
156 | |||
157 | lst->next = new_lst; | ||
158 | new_lst->prev = lst; | ||
159 | } | ||
160 | |||
161 | static inline void tox_list_remove(tox_list_t* lst) { | ||
162 | #ifdef DEBUG /* TODO: check how debugging is done in Tox. */ | ||
163 | assert(lst->next != lst && lst->prev != lst); | ||
164 | #endif | ||
165 | lst->prev->next = lst->next; | ||
166 | lst->next->prev = lst->prev; | ||
167 | } | ||
168 | |||
29 | #endif // MISC_TOOLS_H | 169 | #endif // MISC_TOOLS_H |