From 579048eaf89784ec1da8592d96311fafd49aea1a Mon Sep 17 00:00:00 2001 From: sijanec Date: Thu, 1 Apr 2021 23:30:37 +0200 Subject: initial commit --- src/structs.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/structs.c (limited to 'src/structs.c') diff --git a/src/structs.c b/src/structs.c new file mode 100644 index 0000000..fa4228c --- /dev/null +++ b/src/structs.c @@ -0,0 +1,118 @@ +#define SC_ALLOC_CHUNK 128 /* 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) do { \ + name = realloc(name, sizeof(name[0])*name##_sizeof*SC_REALLOC_K); \ + for (size_t i = name##_sizeof; i < name##_sizeof*SC_REALLOC_K; i++) \ + name[i] = type##_init(); \ + name##_sizeof = name##_sizeof*SC_REALLOC_K; \ + } while (0); +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 */ + +struct sc_result { + struct sc_query * query; /* nofree - free from sc_cache */ + char * url; /* yesfree */ + char * desc; /* yesfree */ + char * title; /* yesfree */ + time_t date; /* some search engines like to extract a date from a website, store that here */ + char * html; /* yesfree - cached generated html output of said result or NULL before it's created */ + 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 */ +}; +struct sc_result * sc_result_init () { + struct sc_result * r = calloc(1, sizeof(struct sc_result)); + 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->html); + 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 */ + char * html; /* yesfree - cached generated HTML output of the result or NULL before it's created */ +}; +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; + } + 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 */ + free(q->html); /* setting to NULL here is not necessary, as we'll never use this query struct again */ + for (size_t i = 0; i < q->results_sizeof; i++) + sc_result_free(q->results[i]); + free(q); + return 1; +} +struct sc_cache { + SC_IN_STRUCT_ARRAY(struct sc_query, queries); /* yesfree */ + pthread_rwlock_t * queries_lock; + SC_IN_STRUCT_ARRAY(struct sc_logentry, logentries); /* yesfree */ + pthread_rwlock_t * logentries_lock; +}; +struct sc_cache * sc_cache_init() { + struct sc_cache * c = calloc(1, sizeof(struct sc_cache)); + c->queries_sizeof = SC_ALLOC_CHUNK; + c->logentries_sizeof = SC_ALLOC_CHUNK; + c->queries = calloc(c->queries_sizeof, sizeof(struct sc_query *)); + c->logentries = calloc(c->logentries_sizeof, sizeof(struct sc_logentry *)); + for (size_t i = 0; i < c->queries_sizeof; i++) { + c->queries[i] = sc_query_init(); + c->queries[i]->cache = c; + c->logentries[i] = sc_logentry_init(); + } +#define SC_CILI(name) do { name##_lock = malloc(sizeof(pthread_rwlock_t)); pthread_rwlock_init(name##_lock, NULL); } while (0) + SC_CILI(c->queries); + SC_CILI(c->logentries); + return c; +} +int sc_cache_free(struct sc_cache * c) { + if (!c) + return -1; + for (size_t i = 0; i < c->queries_sizeof; i++) + sc_query_free(c->queries[i]); + free(c->queries); + for (size_t i = 0; i < c->logentries_sizeof; i++) + sc_logentry_free(c->logentries[i]); + #define SC_CFLD(name) do { pthread_rwlock_destroy(name##_lock); free(name##_lock); } while(0) + SC_CFLD(c->queries); + SC_CFLD(c->logentries); + free(c); + return 1; +} -- cgit v1.2.3