summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--testing/misc_tools.c12
-rw-r--r--testing/misc_tools.h142
2 files changed, 152 insertions, 2 deletions
diff --git a/testing/misc_tools.c b/testing/misc_tools.c
index aa546a88..fa7f42c9 100644
--- a/testing/misc_tools.c
+++ b/testing/misc_tools.c
@@ -25,7 +25,11 @@
25 25
26#include <string.h> 26#include <string.h>
27#include <stdlib.h> 27#include <stdlib.h>
28#include <stdio.h> /* for sscanf */ 28#include <stdio.h>
29
30#ifdef DEBUG
31#include <assert.h>
32#endif // DEBUG
29 33
30/* TODO: rewrite */ 34/* TODO: rewrite */
31unsigned char * hex_string_to_bin(char hex_string[]) 35unsigned char * hex_string_to_bin(char hex_string[])
@@ -39,3 +43,9 @@ unsigned char * hex_string_to_bin(char hex_string[])
39 43
40 return val; 44 return val;
41} 45}
46
47
48
49
50
51
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
27unsigned char * hex_string_to_bin(char hex_string[]); 27unsigned 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
75This sample program makes a new struct which contains a
76character and a tox_list_t. It then prompts a user for
77input until he enters q or e. It then adds each character
78to the list, and uses a special for loop to print them.
79It then removes all the 'z' characters, and prints the list
80again.
81
82//Notice that the data to be put in the list *contains* tox_list_t;
83//usually, this is the other way around!
84typedef 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
89int 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
103TOX_LIST_FOR_EACH() takes a struct tox_list and a name for a temporary pointer to use in the loop.
104
105TOX_LIST_GET_VALUE() uses magic to return an instance of a structure that contains tox_list_t.
106You have to give it a temporary tox_string_t, name of tox_list_t member inside our structure (tox_lst),
107and 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
141typedef struct tox_list {
142 struct tox_list *prev, *next;
143} tox_list_t;
144
145/* Returns a new tox_list_t. */
146static 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. */
151static 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
161static 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