summaryrefslogtreecommitdiffstats
path: root/src/structs.c
blob: 83d19b9be2a2779e508b6314996ae1193f9cbb00 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#define SC_ALLOC_CHUNK 1 /* how many x to alloc when allocing (for performance so we don't call malloc over and over again) */
#define SC_IN_STRUCT_ARRAY(type, name) _Atomic(type **) name; _Atomic(size_t) name##_sizeof; _Atomic(size_t) name##_length
#define SC_CWLE(c, name) (pthread_rwlock_wrlock(name) ? (SC_LOG(SC_LOG_ERROR,c,SC_I18N_LOCKING " " #name " " SC_I18N_FAILED)||1) :0)
#define SC_CRLE(c, name) (pthread_rwlock_rdlock(name) ? (SC_LOG(SC_LOG_ERROR,c,SC_I18N_LOCKING " " #name " " SC_I18N_FAILED)||1) :0)
#define SC_CUE(c, name) (pthread_rwlock_unlock(name) ? (SC_LOG(SC_LOG_ERROR,c,SC_I18N_UNLOCKING " " #name " " SC_I18N_FAILED)||1):0)
#define SC_REALLOC_K 1.5 /* constant to dynamically realloc large arrays (new size = current size * K) */
#define SC_ENGINE_GOOGLE (1 << 0)
/* _Atomic(size_t) sc_mem_max = 100e6; */ /* the really soft memory limit of the program: 100MB - NOT IMPLEMENTED */
#define SC_LOG(t, c, m, ...) sc_push_log(t, c, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__)
#define SC_LOG_ERROR		(1 << 0)
#define SC_LOG_WARNING	(1 << 1)
#define SC_LOG_INFO			(1 << 2)
#define SC_LOG_DEBUG		(1 << 3)
#define SC_BIGGER_ARRAY(name, type, shallinit) do { \
		name = realloc(name, sizeof(name[0])*ceil(name##_sizeof*SC_REALLOC_K)); \
		for (size_t i = name##_sizeof; shallinit && (i < ceil(name##_sizeof*SC_REALLOC_K)); i++) \
			name[i] = type##_init(); \
		name##_sizeof = ceil(name##_sizeof*SC_REALLOC_K); /* ceil je ZELO pomemben, če je chunk 1 recimo */ \
	} while (0);
#define SC_OPT_TYPE unsigned char
#define SC_OPT_IMAGE (1 << 0)
#define SC_STR(x) #x
#ifdef SC_LOGMEM
struct sc_logentry {
	unsigned char type; /* SC_LOG_ERROR, SC_LOG_WARNING, SC_LOG_INFO, SC_LOG_DEBUG */
	size_t line;
	const char * function; /* nofree */
	char * file; /* nofree */
	char * message; /* yesfree */
	time_t time;
};
int sc_logentry_free (struct sc_logentry * l); /* defined in log.c */
struct sc_logentry * sc_logentry_init (); /* defined in log.c */
#endif
struct sc_result {
	struct sc_query * query; /* nofree - free from sc_cache */
	char * url; /* yesfree - url of referer page when image searching */
	char * desc; /* yesfree - url of image when image searching */
	char * title; /* yesfree */
	time_t date; /* some search engines like to extract a date from a website, store that here - not implemented */
	unsigned short int rating; /* some search engines like to extract a rating from a website, store that here */ /* not implementd */
	unsigned short int rating_max; /* max rating when above is used /\ */ /* not implemented yet */
	char * breadcrumbs; /* yesfree - google has nice breadcrumbs, when hovering over the URL requires too much time (: */
};
struct sc_result * sc_result_init () {
	struct sc_result * r = calloc(1, sizeof(struct sc_result));
	r->url = NULL;
	r->desc = NULL;
	r->title = NULL;
	r->breadcrumbs = NULL;
	return r;
}
int sc_result_free (struct sc_result * r) {
	if (!r)
		return -1;
	free(r->url);
	free(r->desc);
	free(r->title);
	free(r->breadcrumbs);
	free(r);
	return 1;
}
struct sc_query {
	struct sc_cache * cache; /* nofree - what cache owns this query */
	SC_IN_STRUCT_ARRAY(struct sc_result, results); /* yesfree */
	char * string; /* yesfree - query string, stripped of any excess characters that should be excluded from indexing */
	time_t lookup_time; /* time of last lookup */
	unsigned char engines; /* with what engine(s) was the query done - bitmask - if there are results from multiple engines */
	SC_OPT_TYPE opt; /* some options  */
};
struct sc_query * sc_query_init () {
	struct sc_query * q = calloc(1, sizeof(struct sc_query));
	q->results_sizeof = SC_ALLOC_CHUNK;
	q->results = calloc(q->results_sizeof, sizeof(struct sc_result *));
	for (size_t i = 0; i < q->results_sizeof; i++) {
		q->results[i] = sc_result_init();
		q->results[i]->query = q;
	}
	q->string = NULL;
	return q;
}
int sc_query_free (struct sc_query * q) {
	if (!q)
		return -1;
	free(q->string); /* if they were not alloced, they are NULL, if they were free'd somewhere else, they are also set to NULL */
	for (size_t i = 0; i < q->results_sizeof; i++)
		sc_result_free(q->results[i]);
	free(q->results);
	free(q);
	return 1;
}
struct sc_cache {
	SC_IN_STRUCT_ARRAY(struct sc_query, queries); /* yesfree */
	pthread_rwlock_t * queries_lock;
#ifdef SC_LOGMEM
	SC_IN_STRUCT_ARRAY(struct sc_logentry, logentries); /* yesfree */
	pthread_rwlock_t * logentries_lock;
#endif
};
struct sc_cache * sc_cache_init() {
#define SC_CILI(name) do { name##_lock = malloc(sizeof(pthread_rwlock_t)); pthread_rwlock_init(name##_lock, NULL); } while (0)
	struct sc_cache * c = calloc(1, sizeof(struct sc_cache));
	c->queries_sizeof = SC_ALLOC_CHUNK;
	c->queries = calloc(c->queries_sizeof, sizeof(struct sc_query *));
#ifdef SC_LOGMEM
	c->logentries_sizeof = SC_ALLOC_CHUNK;
	c->logentries = calloc(c->logentries_sizeof, sizeof(struct sc_logentry *));
	for (size_t i = 0; i < c->logentries_sizeof; i++)
		c->logentries[i] = sc_logentry_init();
	SC_CILI(c->logentries);
#endif
	SC_CILI(c->queries);
	return c;
}
int sc_cache_free(struct sc_cache * c) {
	#define SC_CFLD(name) do { pthread_rwlock_destroy(name##_lock); free(name##_lock); } while(0)
	if (!c)
		return -1;
	fprintf(stderr, "c->queries_sizeof = %zu\n", c->queries_sizeof);
	for (size_t i = 0; i < c->queries_sizeof; i++)
		sc_query_free(c->queries[i]);
	free(c->queries);
#ifdef SC_LOGMEM
	for (size_t i = 0; i < c->logentries_sizeof; i++)
		sc_logentry_free(c->logentries[i]);
	SC_CFLD(c->logentries);
	free(c->logentries);
#endif
	SC_CFLD(c->queries);
	free(c);
	return 1;
}