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