summaryrefslogblamecommitdiffstats
path: root/src/structs.c
blob: f23e52f96a4a51c29114ff0b76f4d2de0e034afb (plain) (tree)
1
2
3
4
5
6
7
8
                                                                                                                              




                                                                                                                                    

                                                                                                                           


                                                                                                          
                                                  
                                                                                                                      
                    
                    












                                                                                                 
                









                                                                                         
      











                                                                         
                                                                                                                                 

                                                                  

                                                                            
                                   
                                                                                                                       

                                                                                                                                          
                                                                                                                             


                                                                   



                              







                                           
                             







                                                                                                                            

                                                                                                             
                                                             








                                                                           
                         
                            
                             

                 
















                                   
               





                          
                                                                                                                                                     
                                                                                                                                     
                           

                                                      
                         
                


                     
      









                                                                                             
                                   
                                                                                                                              
                                                                 
                     
                                           
                                                                          
      

                                              
                                                                                   
                                                         
                                                      
                               

                            


                                        
                                                                                                     

                          
                     
                                                                        


                                                      


                                        
                

                                                         
                               
                            
      
                            


                 
#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) */
/* _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_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_STR(x) #x
enum sc_opt {
	SC_ENGINE_GOOGLE =	1 << 0,
	SC_LOG_ERROR	 =	1 << 1,
	SC_LOG_WARNING	 =	1 << 2,
	SC_LOG_INFO	 =	1 << 3,
	SC_LOG_DEBUG	 =	1 << 4,
	SC_OPT_IMAGE 	 =	1 << 5
};
#define SC_LOG_MASK (SC_LOG_ERROR | SC_LOG_WARNING | SC_LOG_INFO | SC_LOG_DEBUG)
#define SC_OPT_TYPE enum sc_opt
#define SC_OPT_INIT 0
#define SC_OPT_COMPAR /* mask */ (/* SC_ENGINE_GOOGLE | */ /* any engine is okay */ SC_OPT_IMAGE)
#define SC_COMPAR_CAST (int (*)(const void *, const void *))
#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_cache {
#ifdef SC_OLD_STORAGE
	SC_IN_STRUCT_ARRAY(struct sc_query, queries); /* yesfree */
#else
	void * qrp; /* queries root pointer-tsearch(3) */
#endif
	pthread_rwlock_t * queries_lock;
#ifdef SC_LOGMEM
	SC_IN_STRUCT_ARRAY(struct sc_logentry, logentries); /* yesfree */
	pthread_rwlock_t * logentries_lock;
#endif
};
int sc_push_log (SC_OPT_TYPE t, struct sc_cache * c, const char * ca, char * f, size_t l, unsigned short int isf, char * m, ...);
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 */
	char * suggested; /* yesfree - suggested search query (did you mean) */
	bool redirect; /* true if client is encouraged to be redirected to suggested (showing results for) */
	SC_OPT_TYPE opt; /* some options including engines */
};
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;
	q->suggested = NULL;
	q->opt = SC_OPT_INIT;
	return q;
}
#ifdef SC_OLD_STORAGE
int
#else
void 
#endif
sc_query_free (
#ifdef SC_OLD_STORAGE
		struct sc_query
#else
		void
#endif
		* i) {
	struct sc_query * q =
#ifndef SC_OLD_STORAGE
		(struct sc_query *)
#endif
		i;
	if (!q)
		return
#ifdef SC_OLD_STORAGE
			-1
#endif
			;
	if (q->cache)
		SC_LOG(SC_LOG_DEBUG, q->cache, "sc_query_free: %s (sugg: %s)", q->string ? q->string : "NULL", q->suggested ? q->suggested : "NULL");
	free(q->string); /* if they were not alloced, they are NULL, if they were free'd somewhere else, they are also set to NULL */
	free(q->suggested);
	for (size_t i = 0; i < q->results_sizeof; i++)
		sc_result_free(q->results[i]);
	free(q->results);
	free(q);
	return
#ifdef SC_OLD_STORAGE
		1
#endif
		;
}
int sc_query_compar (const struct sc_query * a, const struct sc_query * b) {
#define SC_QUERY_COMPAR_OPT ->opt & SC_OPT_COMPAR
	int r = (a SC_QUERY_COMPAR_OPT) < (b SC_QUERY_COMPAR_OPT) ? -1
		: (a SC_QUERY_COMPAR_OPT) > (b SC_QUERY_COMPAR_OPT) ? 1 : 0;
	if (r) /* first we compare options, because it should be faster than query strings */
		return r; /* yeah, I know, useless optimizations */
	return strcmp(a->string, b->string);
}
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));
#ifdef SC_OLD_STORAGE
	c->queries_sizeof = SC_ALLOC_CHUNK;
	c->queries = calloc(c->queries_sizeof, sizeof(struct sc_query *));
#endif
#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;
#ifdef SC_OLD_STORAGE
	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);
#else
	tdestroy(c->qrp, sc_query_free);
#endif
#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;
}