Last active
September 14, 2023 14:16
-
-
Save sigzegv/58bbfb21092b84ef1974bf3c2c1aefe0 to your computer and use it in GitHub Desktop.
C snippets
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
char* | |
file_get_contents(const char* fname) { | |
FILE* f = fopen(fname, "r"); | |
if (!f) { | |
printf("failed reading %s", fname); | |
return NULL; | |
} | |
fseek(f, 0, SEEK_END); | |
long sz = ftell(f); | |
fseek(f, 0, SEEK_SET); | |
char* content = malloc(sizeof(char) * sz + 1); | |
fread(content, sz, 1, f); | |
fclose(f); | |
content[sz] = '\0'; | |
return content; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://stackoverflow.com/questions/7666509/hash-function-for-string | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdint.h> | |
#define SEED 0x12345678 | |
uint32_t DJB2_hash(const uint8_t *str) | |
{ | |
uint32_t hash = 5381; | |
uint8_t c; | |
while ((c = *str++)) | |
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ | |
return hash; | |
} | |
uint32_t FNV(const void* key, int len, uint32_t h) | |
{ | |
// Source: https://github.com/aappleby/smhasher/blob/master/src/Hashes.cpp | |
h ^= 2166136261UL; | |
const uint8_t* data = (const uint8_t*)key; | |
for(int i = 0; i < len; i++) | |
{ | |
h ^= data[i]; | |
h *= 16777619; | |
} | |
return h; | |
} | |
uint32_t MurmurOAAT(const void * key, uint32_t h) | |
{ | |
const uint8_t* str = (const uint8_t*)key; | |
// One-byte-at-a-time hash based on Murmur's mix | |
// Source: https://github.com/aappleby/smhasher/blob/master/src/Hashes.cpp | |
for (; *str; ++str) { | |
h ^= *str; | |
h *= 0x5bd1e995; | |
h ^= h >> 15; | |
} | |
return h; | |
} | |
uint32_t KR_v2_hash(const char *s) | |
{ | |
// Source: https://stackoverflow.com/a/45641002/5407270 | |
uint32_t hashval = 0; | |
for (hashval = 0; *s != '\0'; s++) | |
hashval = *s + 31*hashval; | |
return hashval; | |
} | |
uint32_t Jenkins_one_at_a_time_hash(const char *str, size_t len) | |
{ | |
uint32_t hash, i; | |
for(hash = i = 0; i < len; ++i) | |
{ | |
hash += str[i]; | |
hash += (hash << 10); | |
hash ^= (hash >> 6); | |
} | |
hash += (hash << 3); | |
hash ^= (hash >> 11); | |
hash += (hash << 15); | |
return hash; | |
} | |
uint32_t crc32b(const uint8_t *str) { | |
// Source: https://stackoverflow.com/a/21001712 | |
unsigned int byte, crc, mask; | |
int i = 0, j; | |
crc = 0xFFFFFFFF; | |
while (str[i] != 0) { | |
byte = str[i]; | |
crc = crc ^ byte; | |
for (j = 7; j >= 0; j--) { | |
mask = -(crc & 1); | |
crc = (crc >> 1) ^ (0xEDB88320 & mask); | |
} | |
i = i + 1; | |
} | |
return ~crc; | |
} | |
uint32_t _rotl32(uint32_t x, int32_t bits) | |
{ | |
return x<<bits | x>>(32-bits); // C idiom: will be optimized to a single operation | |
} | |
uint32_t Coffin_hash(char const *input) { | |
// Source: https://stackoverflow.com/a/7666668/5407270 | |
uint32_t result = 0x55555555; | |
while (*input) { | |
result ^= *input++; | |
result = _rotl32(result, 5); | |
} | |
return result; | |
} | |
uint32_t x17(const void * key, int len, uint32_t h) | |
{ | |
// Source: https://github.com/aappleby/smhasher/blob/master/src/Hashes.cpp | |
const uint8_t * data = (const uint8_t*)key; | |
for (int i = 0; i < len; ++i) | |
{ | |
h = 17 * h + (data[i] - ' '); | |
} | |
return h ^ (h >> 16); | |
} | |
int main() { | |
char *key = "samplekey"; | |
uint32_t h = MurmurOAAT(key, SEED); | |
printf("%u\n", h); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
typedef struct hsearch_data htree_t; | |
htree_t* | |
htree_create(size_t sz) { | |
htree_t *h = malloc(sizeof(htree_t)); | |
if (NULL == h) { | |
return NULL; | |
} | |
if (!hcreate_r(sz, h)) { | |
free(h); | |
return NULL; | |
} | |
return h; | |
} | |
int | |
htree_set(htree_t* h, char *key, void* data) { | |
ENTRY* i; | |
if (!hsearch_r((ENTRY){.key = key, .data = data}, ENTER, &i, h)) { | |
return 0; | |
} | |
return 1; | |
} | |
void* | |
htree_find(htree_t* h, char *key) { | |
ENTRY* res; | |
if (!hsearch_r((ENTRY){.key = key}, FIND, &res, h)) { | |
return NULL; | |
} | |
return res->data; | |
} | |
void | |
htree_delete(htree_t *h) { | |
hdestroy_r(h); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ctype.h> | |
#include <string.h> | |
#define eprintf(...) fprintf(stderr, __VA_ARGS__) | |
/** | |
* gets last char in string | |
*/ | |
char *str_last(char *str) { | |
return str + strlen(str); | |
} | |
/** | |
* replace all occurences of 'o' by 'n' in str | |
*/ | |
int str_replace_chr(char *str, char o, char n) { | |
char *p; | |
int count = 0; | |
while((p = strchr(str, o)) != NULL) { | |
*p = n; | |
count++; | |
} | |
return count; | |
} | |
/** | |
* Trim spaces in string str. | |
* The returned string has to be freed | |
*/ | |
char *strtrim(const char *s) { | |
char* str = s; | |
// trim front | |
while(isspace((unsigned char)*str)) str++; | |
if(*str == 0) return str; | |
// trim trail | |
char *end = str + strlen(str) - 1; | |
while(end > str && isspace((unsigned char)*end)) end--; | |
end[1] = '\0'; // write new null terminator character | |
return str; | |
} | |
/** | |
* Extracts the string between st and end positions. | |
* st and end must be part of same string. | |
* Returned buffer must be freed | |
*/ | |
char *str_extract(const char *st, const char *end) { | |
int len = end - st; | |
char *s = malloc(len + 1); | |
strncpy(s, st, len); | |
*(s + len) = '\0'; | |
return s; | |
} | |
/** | |
* Searches for a substring in str, enclosed by st_tok and end_tok strings. | |
* Returned buffer must be freed | |
*/ | |
char* | |
substr(const char *str, const char *st_tok, const char *end_tok) { | |
if (st_tok == end_tok) { | |
return NULL; | |
} | |
// reverse st_tok and end_tok if end_tok is before st_tok | |
if (end_tok < st_tok) { | |
char* tmp = st_tok; | |
st_tok = end_tok; | |
end_tok = tmp; | |
} | |
char *stpos = strstr(str, st_tok); // searches for first st_tok's occurence. | |
if (NULL == stpos) { | |
fprintf(stderr, "token %s not found", st_tok); | |
return NULL; | |
} | |
stpos += strlen(st_tok); // start searching after the end of 'st_tok''s matched occurence | |
char *endpos = strstr(stpos, end_tok); // searches for first end_tok's occurence | |
if (NULL == endpos) { | |
fprintf(stderr, "end token %s not found", end_tok); | |
return NULL; | |
} | |
return str_extract(stpos, endpos); | |
} | |
/** | |
* Splits a string against a separator. | |
* It keeps empty strings between twin separators. | |
*/ | |
char **str_split(const char *str, const char sep) { | |
char *st = (char *)str; | |
char *last = NULL; | |
char **splits = NULL; | |
int count = 0; | |
while((last = strchr(st, sep)) != NULL) { | |
splits = realloc(splits, sizeof(char *) * (count+1)); | |
char *m = str_extract(st, last); | |
*(splits + count) = m; | |
count++; | |
st = last + 1; | |
} | |
char *m = str_extract(st, str_last(st)); | |
*(splits + count) = m; | |
return splits; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment